GeneratorControls.vue (7305B)
1 <script> 2 import VSwatches from 'vue-swatches'; 3 import 'vue-swatches/dist/vue-swatches.css'; 4 import GeneratorExportOptions from './GeneratorExportOptions.vue'; 5 6 export default { 7 name: 'GeneratorControls', 8 components: { 9 VSwatches, 10 GeneratorExportOptions, 11 }, 12 props: { 13 initialFill: { 14 type: String, 15 required: true, 16 }, 17 rotation: { 18 type: Number, 19 required: true, 20 }, 21 scale: { 22 type: Number, 23 required: true, 24 }, 25 curvature: { 26 type: Number, 27 required: true, 28 }, 29 }, 30 data() { 31 return { 32 fill: this.initialFill, 33 }; 34 }, 35 watch: { 36 fill(newVal) { 37 this.$emit('controls-changed', { 38 id: 'fill', 39 value: newVal, 40 }); 41 }, 42 }, 43 methods: { 44 handleControlChange(e) { 45 this.$emit('controls-changed', { 46 id: e.target.id, 47 value: e.target.value, 48 }); 49 }, 50 handleDetailChange(e) { 51 const { id } = e.target; 52 53 for (const propertyIndex in this.detailToggleState) { 54 const state = this.detailToggleState[~~propertyIndex]; 55 56 if (state.id === id) { 57 state.checked = true; 58 59 this.$emit('controls-changed', { 60 id: 'detail', 61 value: state.value, 62 }); 63 } else { 64 state.checked = false; 65 } 66 } 67 }, 68 }, 69 }; 70 </script> 71 72 <template> 73 <div class="generator-controls"> 74 <div class="generator-controls__inputs"> 75 <label for="rotation" class="generator-controls__label"> 76 Rotation 77 </label> 78 <BaseRangeInput 79 name="rotation" 80 class="generator-controls__slider" 81 :min="-45" 82 :max="45" 83 :value="rotation" 84 :step="1" 85 @change="handleControlChange" 86 /> 87 <label for="scale" class="generator-controls__label"> 88 Scale 89 </label> 90 <BaseRangeInput 91 name="scale" 92 class="generator-controls__slider" 93 :min="0" 94 :max="200" 95 :value="scale" 96 :step="1" 97 @change="handleControlChange" 98 /> 99 <label for="curvature" class="generator-controls__label"> 100 Curvature 101 </label> 102 <BaseRangeInput 103 name="curvature" 104 class="generator-controls__slider" 105 :min="0" 106 :max="1" 107 :value="curvature" 108 :step="0.01" 109 @change="handleControlChange" 110 /> 111 <label for="colorHex" class="generator-controls__label"> 112 Fill 113 </label> 114 <div class="generator-controls__swatch"> 115 <input 116 id="colorHex" 117 v-model="fill" 118 class="generator-conrols__swatch-text" 119 type="text" 120 name="colorHex" 121 /> 122 <VSwatches 123 v-model="fill" 124 :swatches="[ 125 '#EF4E4E', 126 '#F9703E', 127 '#FADB5F', 128 '#6CD410', 129 '#31B237', 130 '#2DCCA7', 131 '#1CD4D4', 132 '#40C3F7', 133 '#2186EB', 134 '#3A66DB', 135 '#9446ED', 136 '#ED47ED', 137 '#E8368F', 138 '#829AB1', 139 '#7B8794', 140 '#F5F7FA', 141 ]" 142 :trigger-style="{ 143 width: '64px', 144 height: '48px', 145 borderRadius: '0 12px 12px 0', 146 }" 147 /> 148 </div> 149 <hr /> 150 <p 151 class="generator-controls__label generator-controls__label--export" 152 > 153 Export 154 </p> 155 <GeneratorExportOptions /> 156 </div> 157 </div> 158 </template> 159 160 <style scoped> 161 .generator-controls { 162 justify-self: center; 163 display: flex; 164 justify-content: center; 165 align-items: center; 166 flex-direction: column; 167 max-width: var(--spacing-13); 168 width: 100%; 169 padding-right: var(--spacing-1); 170 } 171 172 .generator-controls__inputs { 173 display: grid; 174 grid-template-columns: max-content 1fr; 175 grid-template-rows: var(--spacing-6) var(--spacing-6) var(--spacing-6) max-content max-content; 176 grid-row-gap: var(--spacing-5); 177 justify-content: center; 178 width: 100%; 179 } 180 181 .generator-controls__label { 182 grid-column: 1; 183 align-self: center; 184 margin-right: var(--spacing-6); 185 font-size: var(--font-size-4); 186 font-weight: 700; 187 } 188 189 .generator-controls__slider { 190 grid-column: 2; 191 } 192 193 .generator-controls__color-picker { 194 grid-column: -1 / 1; 195 } 196 197 .generator-controls__swatch { 198 grid-column: 2; 199 display: flex; 200 align-items: center; 201 justify-content: space-between; 202 height: var(--spacing-6); 203 background: var(--grey-000); 204 border-radius: 12px; 205 } 206 207 .generator-conrols__swatch-text { 208 -webkit-appearance: none; 209 position: relative; 210 width: 100%; 211 min-width: 0; 212 text-transform: uppercase; 213 height: 100%; 214 padding-left: var(--spacing-3); 215 background: transparent; 216 border: 2px solid var(--grey-000); 217 border-radius: 12px 0 0 12px; 218 box-shadow: none; 219 transition: border 125ms ease-in-out; 220 } 221 222 .generator-controls__swatch:hover .generator-conrols__swatch-text { 223 border: 2px solid var(--grey-100); 224 border-right: 0; 225 } 226 227 .generator-controls__detail { 228 align-self: center; 229 } 230 231 .generator-export-controls { 232 grid-column: 2; 233 } 234 235 hr { 236 grid-column: -1 / 1; 237 border: 0; 238 height: 2px; 239 background: var(--grey-000); 240 margin: var(--spacing-1) 0; 241 } 242 243 @media only screen and (max-width: 62rem) { 244 .generator-controls { 245 padding: 0 var(--spacing-4); 246 padding-bottom: var(--spacing-3); 247 } 248 249 .generator-controls__inputs { 250 grid-row-gap: var(--spacing-5); 251 grid-auto-rows: minmax(var(--spacing-5), max-content); 252 } 253 254 .generator-controls__label { 255 font-size: var(--font-size-3); 256 margin-right: var(--spacing-5); 257 } 258 259 .generator-export-controls { 260 grid-column: -1 / 1; 261 } 262 263 .generator-controls__label--export { 264 display: none; 265 } 266 } 267 </style> 268 269 <style> 270 .vue-swatches__trigger__wrapper { 271 display: block; 272 transform-origin: 100% 100%; 273 transition: transform 125ms ease-in-out; 274 } 275 276 .generator-controls__swatch:hover .vue-swatches__trigger__wrapper { 277 transform: scaleX(1.125); 278 } 279 280 .vue-swatches__container { 281 box-shadow: 0 24px 32px rgba(16, 42, 67, 0.075) !important; 282 border: 2px solid var(--grey-100); 283 border-radius: 24px !important; 284 } 285 </style>