@stanko/ctrls 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,288 @@
1
+ import random from "../utils/random";
2
+ import BezierEasing from "bezier-easing";
3
+ const easings = {
4
+ EASE: [0.25, 0.1, 0.25, 1],
5
+ LINEAR: [0, 0, 1, 1],
6
+ EASE_IN: [0.42, 0, 1, 1],
7
+ EASE_OUT: [0, 0, 0.58, 1],
8
+ EASE_IN_OUT: [0.42, 0, 0.58, 1],
9
+ };
10
+ const w = 100;
11
+ const h = 40;
12
+ const getPath = (x1, y1, x2, y2) => {
13
+ return `M 0 ${h} C ${x1} ${y1} ${x2} ${y2} ${w} 0`;
14
+ };
15
+ export class EasingCtrl {
16
+ constructor(config, onChange, onInput) {
17
+ this.type = "easing";
18
+ this.parse = (string) => {
19
+ return string.split(",").map(Number);
20
+ };
21
+ this.getRandomValue = () => {
22
+ const min = 0;
23
+ const max = 1;
24
+ const value = [
25
+ random(min, max, null, 2),
26
+ random(min, max, null, 2),
27
+ random(min, max, null, 2),
28
+ random(min, max, null, 2),
29
+ ];
30
+ return value;
31
+ };
32
+ this.getDefaultValue = () => {
33
+ return easings.LINEAR;
34
+ };
35
+ this.valueToString = (value = this.value) => {
36
+ return value.join(",");
37
+ };
38
+ this.getRelativeValues = (value = this.value) => {
39
+ let [x1, y1, x2, y2] = value;
40
+ // Cap x values
41
+ x1 = Math.max(Math.min(x1, 1), 0);
42
+ x2 = Math.max(Math.min(x2, 1), 0);
43
+ const px = [x1 * w, h - y1 * h, x2 * w, h - y2 * h];
44
+ const percentage = [
45
+ x1 * 100,
46
+ 100 - y1 * 100,
47
+ x2 * 100,
48
+ 100 - y2 * 100,
49
+ ];
50
+ return { px, percentage };
51
+ };
52
+ this.buildUI = () => {
53
+ const { value } = this;
54
+ const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
55
+ line1.setAttribute("class", "ctrls__easing-line ctrls__easing-line--1");
56
+ line1.setAttribute("x1", "0");
57
+ line1.setAttribute("y1", `${h}`);
58
+ const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
59
+ line2.setAttribute("class", "ctrls__easing-line ctrls__easing-line--2");
60
+ line2.setAttribute("x1", `${w}`);
61
+ line2.setAttribute("y1", "0");
62
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
63
+ path.setAttribute("class", "ctrls__easing-path");
64
+ const borders = document.createElementNS("http://www.w3.org/2000/svg", "path");
65
+ borders.classList.add("easing-borders");
66
+ borders.setAttribute("d", `M 0 0 h ${w} M 0 ${h} h ${w}`);
67
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
68
+ svg.setAttribute("viewBox", `0 0 ${w} ${h}`);
69
+ svg.appendChild(borders);
70
+ svg.appendChild(path);
71
+ svg.appendChild(line1);
72
+ svg.appendChild(line2);
73
+ const handle1 = document.createElement("button");
74
+ handle1.className = "ctrls__easing-handle ctrls__easing-handle--1";
75
+ handle1.innerHTML = "";
76
+ const handle2 = document.createElement("button");
77
+ handle2.className = "ctrls__easing-handle ctrls__easing-handle--2";
78
+ handle2.innerHTML = "";
79
+ const control = document.createElement("div");
80
+ control.className = "ctrls__easing";
81
+ control.appendChild(svg);
82
+ control.appendChild(handle1);
83
+ control.appendChild(handle2);
84
+ const addListeners = (handle, index) => {
85
+ let dragging = false;
86
+ let dragStart = { x: 0, y: 0 };
87
+ let positionStart = { x: 0, y: 0 };
88
+ const getNewValue = (clientX, clientY) => {
89
+ const ratio = w / this.control.clientWidth;
90
+ const leftOffset = clientX - dragStart.x;
91
+ const topOffset = clientY - dragStart.y;
92
+ const x = positionStart.x + leftOffset * ratio;
93
+ const y = positionStart.y + topOffset * ratio;
94
+ const attr = element.getAttribute("data-value").split(",");
95
+ const newValue = attr.map(Number);
96
+ newValue[index] = parseFloat((x / w).toFixed(2));
97
+ newValue[index + 1] = parseFloat((1 - y / h).toFixed(2));
98
+ // Cap x values
99
+ newValue[index] = Math.max(Math.min(newValue[index], 1), 0);
100
+ return newValue;
101
+ };
102
+ // Mouse dragging
103
+ handle.addEventListener("mousedown", (e) => {
104
+ dragStart = { x: e.clientX, y: e.clientY };
105
+ positionStart = {
106
+ x: (parseFloat(handle.style.left) * w) / 100,
107
+ y: (parseFloat(handle.style.top) * h) / 100,
108
+ };
109
+ dragging = true;
110
+ document.body.style.userSelect = "none";
111
+ });
112
+ document.addEventListener("mouseup", (e) => {
113
+ if (dragging) {
114
+ document.body.style.userSelect = "";
115
+ dragging = false;
116
+ const newValue = getNewValue(e.clientX, e.clientY);
117
+ this.value = newValue;
118
+ this.onChange(this.name, this.value);
119
+ this.update();
120
+ }
121
+ });
122
+ document.addEventListener("mousemove", (e) => {
123
+ if (dragging) {
124
+ const newValue = getNewValue(e.clientX, e.clientY);
125
+ this.onInput(this.name, this.value);
126
+ this.updateUI(newValue);
127
+ }
128
+ });
129
+ // Touch dragging
130
+ handle.addEventListener("touchstart", (e) => {
131
+ if (e.touches.length > 1) {
132
+ return;
133
+ }
134
+ dragStart = { x: e.touches[0].clientX, y: e.touches[0].clientY };
135
+ positionStart = {
136
+ x: (parseFloat(handle.style.left) * w) / 100,
137
+ y: (parseFloat(handle.style.top) * h) / 100,
138
+ };
139
+ dragging = true;
140
+ document.body.style.userSelect = "none";
141
+ });
142
+ document.addEventListener("touchmove", (e) => {
143
+ if (dragging) {
144
+ e.preventDefault();
145
+ const newValue = getNewValue(e.touches[0].clientX, e.touches[0].clientY);
146
+ this.onInput(this.name, this.value);
147
+ this.updateUI(newValue);
148
+ }
149
+ });
150
+ document.addEventListener("touchend", (e) => {
151
+ if (dragging) {
152
+ document.body.style.userSelect = "";
153
+ dragging = false;
154
+ const newValue = getNewValue(e.changedTouches[0].clientX, e.changedTouches[0].clientY);
155
+ this.value = newValue;
156
+ this.onChange(this.name, this.value);
157
+ this.update();
158
+ }
159
+ });
160
+ // Arrow keys
161
+ handle.addEventListener("keydown", (e) => {
162
+ const offsets = {
163
+ ArrowLeft: [-0.03, 0],
164
+ ArrowRight: [0.03, 0],
165
+ ArrowUp: [0, 0.03],
166
+ ArrowDown: [0, -0.03],
167
+ };
168
+ if (offsets[e.key]) {
169
+ e.preventDefault();
170
+ const newValue = [...this.value];
171
+ newValue[index] = parseFloat((newValue[index] + offsets[e.key][0]).toFixed(2));
172
+ newValue[index + 1] = parseFloat((newValue[index + 1] + offsets[e.key][1]).toFixed(2));
173
+ // Cap x values
174
+ newValue[index] = Math.max(Math.min(newValue[index], 1), 0);
175
+ this.value = newValue;
176
+ this.onChange(this.name, this.value);
177
+ this.update();
178
+ }
179
+ });
180
+ };
181
+ addListeners(handle1, 0);
182
+ addListeners(handle2, 2);
183
+ // Presets
184
+ let presetButtons = null;
185
+ if (Object.keys(this.presets).length > 0) {
186
+ presetButtons = document.createElement("div");
187
+ presetButtons.classList.add("ctrls__easing-buttons");
188
+ for (const key of Object.keys(this.presets)) {
189
+ const button = document.createElement("button");
190
+ button.textContent = key.toLowerCase().replace("ease_", "");
191
+ button.addEventListener("click", () => {
192
+ this.value = this.presets[key];
193
+ this.onChange(this.name, this.value);
194
+ this.update();
195
+ });
196
+ presetButtons.appendChild(button);
197
+ }
198
+ }
199
+ const ticks = document.createElementNS("http://www.w3.org/2000/svg", "svg");
200
+ ticks.classList.add("ctrls__easing-ticks");
201
+ ticks.setAttribute("viewBox", `0 0 ${w} 5`);
202
+ ticks.setAttribute("preserveAspectRatio", "none");
203
+ const tickCount = 30;
204
+ const ticksElements = [];
205
+ for (let i = 0; i < tickCount; i++) {
206
+ const tick = document.createElementNS("http://www.w3.org/2000/svg", "line");
207
+ tick.setAttribute("y1", "0");
208
+ tick.setAttribute("y2", "5");
209
+ ticksElements.push(tick);
210
+ ticks.appendChild(tick);
211
+ }
212
+ const controlWrapper = document.createElement("div");
213
+ controlWrapper.classList.add("ctrls__easing-wrapper");
214
+ controlWrapper.appendChild(ticks);
215
+ controlWrapper.appendChild(control);
216
+ const right = document.createElement("div");
217
+ right.classList.add("ctrls__control-right");
218
+ right.appendChild(controlWrapper);
219
+ if (presetButtons) {
220
+ right.appendChild(presetButtons);
221
+ }
222
+ const label = document.createElement("span");
223
+ label.textContent = this.label;
224
+ label.classList.add("ctrls__control-label");
225
+ const element = document.createElement("div");
226
+ element.classList.add("ctrls__control", "ctrls__control--easing");
227
+ element.setAttribute("data-value", value.join(","));
228
+ element.appendChild(label);
229
+ element.appendChild(right);
230
+ return {
231
+ element,
232
+ ticks: ticksElements,
233
+ control,
234
+ handles: [handle1, handle2],
235
+ lines: [line1, line2],
236
+ path,
237
+ };
238
+ };
239
+ this.updateUI = (value = this.value) => {
240
+ const { handles, lines, path, ticks } = this;
241
+ const { px, percentage } = this.getRelativeValues(value);
242
+ // Helper lines
243
+ lines[0].setAttribute("x2", px[0].toString());
244
+ lines[0].setAttribute("y2", px[1].toString());
245
+ lines[1].setAttribute("x2", px[2].toString());
246
+ lines[1].setAttribute("y2", px[3].toString());
247
+ // Handles
248
+ handles[0].style.left = `${percentage[0]}%`;
249
+ handles[0].style.top = `${percentage[1]}%`;
250
+ handles[1].style.left = `${percentage[2]}%`;
251
+ handles[1].style.top = `${percentage[3]}%`;
252
+ // Path
253
+ path.setAttribute("d", getPath(...px));
254
+ // Ticks
255
+ const e = BezierEasing(...value);
256
+ ticks.forEach((tick, i) => {
257
+ // Subtracting 1 to get 0-1 range (including 1)
258
+ const x = i / (ticks.length - 1);
259
+ const t = (e(x) * w).toString();
260
+ tick.setAttribute("x1", t);
261
+ tick.setAttribute("x2", t);
262
+ });
263
+ };
264
+ this.update = (value = this.value) => {
265
+ this.value = value;
266
+ this.updateUI();
267
+ this.element.setAttribute("data-value", value.join(","));
268
+ };
269
+ this.name = config.name;
270
+ this.label = config.label || config.name;
271
+ this.value =
272
+ config.defaultValue === undefined
273
+ ? this.getDefaultValue()
274
+ : config.defaultValue;
275
+ this.isRandomizationDisabled = config.isRandomizationDisabled || false;
276
+ this.onChange = onChange;
277
+ this.onInput = onInput;
278
+ this.presets = config.presets || easings;
279
+ const { element, ticks, control, handles, lines, path } = this.buildUI();
280
+ this.element = element;
281
+ this.ticks = ticks;
282
+ this.control = control;
283
+ this.handles = handles;
284
+ this.lines = lines;
285
+ this.path = path;
286
+ this.updateUI();
287
+ }
288
+ }
@@ -0,0 +1,28 @@
1
+ import type { Ctrl, CtrlChangeHandler, CtrlType, CtrlTypeRegistry } from ".";
2
+ type Option = {
3
+ label: string;
4
+ value: string;
5
+ };
6
+ export type RadioControlOptions = {
7
+ items: Option[];
8
+ };
9
+ export declare class RadioCtrl implements Ctrl<string> {
10
+ type: CtrlType;
11
+ name: string;
12
+ label: string;
13
+ value: string;
14
+ isRandomizationDisabled: boolean;
15
+ onChange: CtrlChangeHandler<string>;
16
+ onInput: CtrlChangeHandler<string>;
17
+ items: Option[];
18
+ element: HTMLElement;
19
+ columns: 1 | 2 | 3 | 4 | 5;
20
+ constructor(config: CtrlTypeRegistry["radio"]["config"], onChange: CtrlChangeHandler<string>, onInput: CtrlChangeHandler<string>);
21
+ parse: (string: string) => string;
22
+ getRandomValue: () => string;
23
+ getDefaultValue: () => string;
24
+ valueToString: (value?: string) => string;
25
+ buildUI: () => HTMLDivElement;
26
+ update: (value: string) => void;
27
+ }
28
+ export {};
@@ -0,0 +1,83 @@
1
+ import random from "../utils/random";
2
+ export class RadioCtrl {
3
+ constructor(config, onChange, onInput) {
4
+ this.type = "radio";
5
+ this.parse = (string) => {
6
+ const item = this.items.find((item) => item.value === string);
7
+ return item?.value || this.getDefaultValue();
8
+ };
9
+ this.getRandomValue = () => {
10
+ const index = random(0, this.items.length - 1, null, 0);
11
+ return this.items[index].value;
12
+ };
13
+ this.getDefaultValue = () => {
14
+ return this.items[0].value;
15
+ };
16
+ this.valueToString = (value = this.value) => {
17
+ return value;
18
+ };
19
+ this.buildUI = () => {
20
+ const { items, value } = this;
21
+ const inputs = items.map((item) => {
22
+ const input = document.createElement("input");
23
+ input.setAttribute("type", "radio");
24
+ input.setAttribute("name", this.name);
25
+ input.setAttribute("value", item.value);
26
+ input.checked = item.value === value;
27
+ input.addEventListener("change", () => {
28
+ this.value = this.parse(input.value);
29
+ this.onChange(this.name, this.value);
30
+ });
31
+ input.addEventListener("input", () => {
32
+ this.value = this.parse(input.value);
33
+ this.onInput(this.name, this.value);
34
+ });
35
+ const label = document.createElement("span");
36
+ label.textContent = item.label;
37
+ const option = document.createElement("label");
38
+ option.classList.add("ctrls__radio-label");
39
+ option.appendChild(input);
40
+ option.appendChild(label);
41
+ return option;
42
+ });
43
+ const right = document.createElement("div");
44
+ right.classList.add("ctrls__control-right");
45
+ right.style.gridTemplateColumns = `repeat(${this.columns}, 1fr)`;
46
+ right.append(...inputs);
47
+ const label = document.createElement("span");
48
+ label.textContent = this.label;
49
+ label.classList.add("ctrls__control-label");
50
+ const element = document.createElement("div");
51
+ element.classList.add("ctrls__control", "ctrls__control--radio");
52
+ element.appendChild(label);
53
+ element.appendChild(right);
54
+ return element;
55
+ };
56
+ this.update = (value) => {
57
+ const item = this.items.find((item) => item.value === value);
58
+ this.value = item?.value || this.getDefaultValue();
59
+ // Unselect previous option
60
+ const prev = this.element.querySelector(`input:checked`);
61
+ prev.checked = false;
62
+ // Select new option
63
+ const next = this.element.querySelector(`[value="${this.value}"]`);
64
+ next.checked = true;
65
+ };
66
+ this.items = [];
67
+ Object.keys(config.items).forEach((key) => {
68
+ this.items.push({
69
+ label: key,
70
+ value: config.items[key],
71
+ });
72
+ });
73
+ this.columns = config.columns || 3;
74
+ this.name = config.name;
75
+ this.label = config.label || config.name;
76
+ const defaultValue = this.items.find((item) => item.value === config.defaultValue);
77
+ this.value = defaultValue?.value || this.getDefaultValue();
78
+ this.isRandomizationDisabled = config.isRandomizationDisabled || false;
79
+ this.onChange = onChange;
80
+ this.onInput = onInput;
81
+ this.element = this.buildUI();
82
+ }
83
+ }
@@ -0,0 +1,25 @@
1
+ import type { Ctrl, CtrlChangeHandler, CtrlType, CtrlTypeRegistry } from ".";
2
+ export declare class RangeCtrl implements Ctrl<number> {
3
+ type: CtrlType;
4
+ name: string;
5
+ label: string;
6
+ value: number;
7
+ isRandomizationDisabled: boolean;
8
+ onChange: CtrlChangeHandler<number>;
9
+ onInput: CtrlChangeHandler<number>;
10
+ min: number;
11
+ max: number;
12
+ step: number;
13
+ element: HTMLElement;
14
+ input: HTMLInputElement;
15
+ constructor(config: CtrlTypeRegistry["range"]["config"], onChange: CtrlChangeHandler<number>, onInput: CtrlChangeHandler<number>);
16
+ parse: (string: string) => number;
17
+ getRandomValue: () => number;
18
+ getDefaultValue: () => number;
19
+ valueToString: (value?: number) => string;
20
+ buildUI: () => {
21
+ element: HTMLLabelElement;
22
+ input: HTMLInputElement;
23
+ };
24
+ update: (value: number) => void;
25
+ }
@@ -0,0 +1,83 @@
1
+ import random from "../utils/random";
2
+ import { roundToStep } from "../utils/round-to-step";
3
+ // TODO
4
+ // Add a span with the current value
5
+ export class RangeCtrl {
6
+ constructor(config, onChange, onInput) {
7
+ this.type = "range";
8
+ this.parse = (string) => {
9
+ return parseFloat(string);
10
+ };
11
+ this.getRandomValue = () => {
12
+ const { min, max, step } = this;
13
+ const value = random(min, max);
14
+ return roundToStep(value, step);
15
+ };
16
+ this.getDefaultValue = () => {
17
+ return this.min;
18
+ };
19
+ this.valueToString = (value = this.value) => {
20
+ return value.toString();
21
+ };
22
+ this.buildUI = () => {
23
+ const { min, max, step, value } = this;
24
+ const input = document.createElement("input");
25
+ input.classList.add("ctrls__range-input");
26
+ input.setAttribute("type", "range");
27
+ input.setAttribute("min", min.toString());
28
+ input.setAttribute("max", max.toString());
29
+ input.setAttribute("step", step.toString());
30
+ input.setAttribute("value", value.toString());
31
+ input.addEventListener("input", () => {
32
+ this.value = this.parse(input.value);
33
+ this.onInput(this.name, this.value);
34
+ });
35
+ input.addEventListener("change", () => {
36
+ this.value = this.parse(input.value);
37
+ this.onChange(this.name, this.value);
38
+ });
39
+ input.addEventListener("input", () => {
40
+ const value = this.parse(input.value);
41
+ const percentage = ((value - min) / (max - min)) * 100;
42
+ this.element.style.setProperty("--gradient-position", `${percentage.toFixed(2)}%`);
43
+ });
44
+ const right = document.createElement("div");
45
+ right.classList.add("ctrls__control-right");
46
+ right.append(input);
47
+ const label = document.createElement("span");
48
+ label.textContent = this.label;
49
+ label.classList.add("ctrls__control-label");
50
+ const element = document.createElement("label");
51
+ element.classList.add("ctrls__control", "ctrls__control--range");
52
+ element.appendChild(label);
53
+ element.appendChild(right);
54
+ return {
55
+ element,
56
+ input,
57
+ };
58
+ };
59
+ this.update = (value) => {
60
+ const { min, max } = this;
61
+ this.value = value;
62
+ this.input.value = value.toString();
63
+ const percentage = ((this.value - min) / (max - min)) * 100;
64
+ this.element.style.setProperty("--gradient-position", `${percentage.toFixed(2)}%`);
65
+ };
66
+ this.name = config.name;
67
+ this.label = config.label || config.name;
68
+ this.isRandomizationDisabled = config.isRandomizationDisabled || false;
69
+ this.onChange = onChange;
70
+ this.onInput = onInput;
71
+ this.min = config.min;
72
+ this.max = config.max;
73
+ this.step = config.step || 1;
74
+ this.value =
75
+ config.defaultValue === undefined
76
+ ? this.getDefaultValue()
77
+ : config.defaultValue;
78
+ const { input, element } = this.buildUI();
79
+ this.input = input;
80
+ this.element = element;
81
+ this.update(this.value);
82
+ }
83
+ }
@@ -0,0 +1,22 @@
1
+ import type { Ctrl, CtrlChangeHandler, CtrlConfig, CtrlType } from ".";
2
+ export declare class SeedCtrl implements Ctrl<string> {
3
+ type: CtrlType;
4
+ name: string;
5
+ label: string;
6
+ value: string;
7
+ isRandomizationDisabled: boolean;
8
+ onChange: CtrlChangeHandler<string>;
9
+ onInput: CtrlChangeHandler<string>;
10
+ element: HTMLElement;
11
+ input: HTMLInputElement;
12
+ constructor(config: CtrlConfig<string>, onChange: CtrlChangeHandler<string>, onInput: CtrlChangeHandler<string>);
13
+ parse: (string: string) => string;
14
+ getRandomValue: () => string;
15
+ getDefaultValue: () => string;
16
+ valueToString: (value?: string) => string;
17
+ buildUI: () => {
18
+ element: HTMLDivElement;
19
+ input: HTMLInputElement;
20
+ };
21
+ update: (value?: string) => void;
22
+ }
@@ -0,0 +1,79 @@
1
+ import generateSeed from "../utils/generate-seed";
2
+ import { refreshIcon } from "../utils/icons";
3
+ export class SeedCtrl {
4
+ constructor(config, onChange, onInput) {
5
+ this.type = "seed";
6
+ this.parse = (string) => {
7
+ return string;
8
+ };
9
+ this.getRandomValue = () => {
10
+ return generateSeed();
11
+ };
12
+ this.getDefaultValue = () => {
13
+ return generateSeed();
14
+ };
15
+ this.valueToString = (value = this.value) => {
16
+ if (value.trim() === "") {
17
+ return this.getRandomValue();
18
+ }
19
+ return value;
20
+ };
21
+ this.buildUI = () => {
22
+ const { value } = this;
23
+ const id = `control-${this.name}`;
24
+ const input = document.createElement("input");
25
+ input.classList.add("ctrls__seed-input");
26
+ input.setAttribute("type", "text");
27
+ input.setAttribute("value", value.toString());
28
+ input.setAttribute("id", id);
29
+ input.addEventListener("change", () => {
30
+ this.value = this.parse(input.value);
31
+ this.onChange(this.name, this.value);
32
+ });
33
+ input.addEventListener("input", () => {
34
+ this.value = this.parse(input.value);
35
+ this.onInput(this.name, this.value);
36
+ });
37
+ const reload = document.createElement("button");
38
+ reload.innerHTML = refreshIcon;
39
+ reload.classList.add("ctrls__seed-new-button", "ctrls__btn");
40
+ reload.addEventListener("click", () => {
41
+ this.value = this.getRandomValue();
42
+ this.update();
43
+ this.onChange(this.name, this.getRandomValue());
44
+ });
45
+ const right = document.createElement("div");
46
+ right.classList.add("ctrls__control-right");
47
+ right.append(input);
48
+ right.append(reload);
49
+ const label = document.createElement("label");
50
+ label.textContent = this.label;
51
+ label.setAttribute("for", id);
52
+ label.classList.add("ctrls__control-label");
53
+ const element = document.createElement("div");
54
+ element.classList.add("ctrls__control", "ctrls__control--seed");
55
+ element.appendChild(label);
56
+ element.appendChild(right);
57
+ return {
58
+ element,
59
+ input,
60
+ };
61
+ };
62
+ this.update = (value = this.value) => {
63
+ this.value = value;
64
+ this.input.value = value;
65
+ };
66
+ this.name = config.name;
67
+ this.label = config.label || config.name;
68
+ this.value =
69
+ config.defaultValue === undefined
70
+ ? this.getDefaultValue()
71
+ : config.defaultValue;
72
+ this.isRandomizationDisabled = config.isRandomizationDisabled || false;
73
+ this.onChange = onChange;
74
+ this.onInput = onInput;
75
+ const { input, element } = this.buildUI();
76
+ this.input = input;
77
+ this.element = element;
78
+ }
79
+ }