@stanko/ctrls 0.3.4 → 0.4.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.
- package/README.md +81 -5
- package/dist/ctrls/ctrl-boolean.d.ts +2 -2
- package/dist/ctrls/ctrl-boolean.js +1 -1
- package/dist/ctrls/ctrl-dual-range.d.ts +2 -2
- package/dist/ctrls/ctrl-dual-range.js +1 -1
- package/dist/ctrls/ctrl-easing.d.ts +2 -2
- package/dist/ctrls/ctrl-easing.js +1 -1
- package/dist/ctrls/ctrl-file.d.ts +27 -0
- package/dist/ctrls/ctrl-file.js +99 -0
- package/dist/ctrls/ctrl-html.d.ts +2 -0
- package/dist/ctrls/ctrl-html.js +13 -0
- package/dist/ctrls/ctrl-radio.d.ts +2 -2
- package/dist/ctrls/ctrl-range.d.ts +2 -2
- package/dist/ctrls/ctrl-range.js +1 -1
- package/dist/ctrls/ctrl-seed.d.ts +2 -2
- package/dist/ctrls/ctrl-seed.js +1 -1
- package/dist/ctrls/dom.d.ts +12 -0
- package/dist/ctrls/dom.js +16 -0
- package/dist/ctrls/index.d.ts +3 -127
- package/dist/ctrls/index.js +93 -85
- package/dist/ctrls/types.d.ts +146 -0
- package/dist/ctrls/types.js +1 -0
- package/dist/ctrls.css +198 -89
- package/dist/ctrls.css.map +1 -1
- package/dist/utils/icons.d.ts +2 -0
- package/dist/utils/icons.js +2 -0
- package/dist/utils/random.d.ts +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Define controls as an array, then instantiate the `Ctrls` class:
|
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
31
|
import { Ctrls } from "@stanko/ctrls";
|
|
32
|
-
import type {
|
|
32
|
+
import type { ConfigItem } from "@stanko/ctrls";
|
|
33
33
|
|
|
34
34
|
// Import CSS
|
|
35
35
|
import "@stanko/ctrls/dist/ctrls.css";
|
|
@@ -58,7 +58,7 @@ const config = [
|
|
|
58
58
|
// - speed, shape and size
|
|
59
59
|
|
|
60
60
|
// Casting the config to enable editor's code completion
|
|
61
|
-
] as const satisfies readonly
|
|
61
|
+
] as const satisfies readonly ConfigItem[];
|
|
62
62
|
|
|
63
63
|
// Create the instance of Ctrls
|
|
64
64
|
export const options = new Ctrls(config, {
|
|
@@ -138,11 +138,20 @@ All controls share the following properties:
|
|
|
138
138
|
```ts
|
|
139
139
|
{
|
|
140
140
|
// --- Mandatory --- //
|
|
141
|
-
type: CtrlType; // "seed" | "easing" | "boolean" | "range" | "dual-range" | "radio"
|
|
141
|
+
type: CtrlType; // "seed" | "easing" | "boolean" | "range" | "dual-range" | "radio" | "group"
|
|
142
|
+
// Name of the component.
|
|
143
|
+
//
|
|
144
|
+
// It will be converted to camel case and used in the values object
|
|
145
|
+
// This might counter-intuitive for some people,
|
|
146
|
+
// but it is my personal preference to have properties named in camel case when using them in code
|
|
147
|
+
//
|
|
148
|
+
// However, names are going to be converted to kebab case when used in the hash,
|
|
149
|
+
// because it is nicer that URL be all lowercase
|
|
142
150
|
name: string;
|
|
143
151
|
|
|
144
152
|
// --- Optional --- //
|
|
145
|
-
// If passed, it will be used instead of the name
|
|
153
|
+
// If passed, it will be used instead of the name,
|
|
154
|
+
// if not, name will be be converted to space case and used as a label.
|
|
146
155
|
label?: string;
|
|
147
156
|
// Depends on the control type, the default value for the control
|
|
148
157
|
defaultValue?: T;
|
|
@@ -332,6 +341,31 @@ Example:
|
|
|
332
341
|
|
|
333
342
|
</div>
|
|
334
343
|
|
|
344
|
+
### File
|
|
345
|
+
|
|
346
|
+
File input.
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
{
|
|
350
|
+
// Optional
|
|
351
|
+
accept?: string; // a comma separated list of allowed file types
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Example:
|
|
356
|
+
|
|
357
|
+
<div class="example">
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"type": "file",
|
|
362
|
+
"name": "background",
|
|
363
|
+
"accept": "image/*"
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
</div>
|
|
368
|
+
|
|
335
369
|
### Group
|
|
336
370
|
|
|
337
371
|
Collapsible group of controls. All values are going to be nested in an object using the group's name.
|
|
@@ -339,7 +373,10 @@ Collapsible group of controls. All values are going to be nested in an object us
|
|
|
339
373
|
```ts
|
|
340
374
|
{
|
|
341
375
|
// Mandatory
|
|
342
|
-
controls: ConfigItem[]
|
|
376
|
+
controls: ConfigItem[];
|
|
377
|
+
|
|
378
|
+
// Optional
|
|
379
|
+
isCollapsed?: boolean;
|
|
343
380
|
}
|
|
344
381
|
```
|
|
345
382
|
|
|
@@ -366,6 +403,42 @@ Example:
|
|
|
366
403
|
|
|
367
404
|
</div>
|
|
368
405
|
|
|
406
|
+
### HTML
|
|
407
|
+
|
|
408
|
+
Custom HTML to be rendered. You'll need to create your element and add it to the config.
|
|
409
|
+
|
|
410
|
+
Doesn't influence the values object as it doesn't have a value.
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
{
|
|
414
|
+
// Mandatory
|
|
415
|
+
html: HTMLElement;
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Example:
|
|
420
|
+
|
|
421
|
+
```ts
|
|
422
|
+
const downloadButton = document.createElement('button');
|
|
423
|
+
downloadButton.innerHTML = "PNG";
|
|
424
|
+
// Add your styles
|
|
425
|
+
downloadButton.addEventListener('click', () => {
|
|
426
|
+
alert("Download button clicked");
|
|
427
|
+
})
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
<div class="example">
|
|
431
|
+
|
|
432
|
+
```json
|
|
433
|
+
{
|
|
434
|
+
"type": "html",
|
|
435
|
+
"name": "download",
|
|
436
|
+
"html": downloadButton
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
</div>
|
|
441
|
+
|
|
369
442
|
## Theming
|
|
370
443
|
|
|
371
444
|
Ctrls uses CSS variables for theming. There are many you can adjust, but I recommend starting with these four:
|
|
@@ -411,6 +484,9 @@ Thank you for stopping by! If you end up using Ctrls, please let me know, I woul
|
|
|
411
484
|
* [ ] Allow users to pass a custom PRNG lib
|
|
412
485
|
* [ ] Hash storage - check if there is an instance using hash storage already
|
|
413
486
|
* [ ] Storage - local storage
|
|
487
|
+
* [ ] Check if `onInput` si triggered when it should
|
|
488
|
+
* [ ] Use dom helpers everywhere
|
|
489
|
+
* [x] `toHtmlId(this.name)` => `toHtmlId(this.id)`
|
|
414
490
|
* [x] Add `name` and `id` to inputs
|
|
415
491
|
* [x] TypeDef bug - easing presets should be optional
|
|
416
492
|
* [x] Add title which collapses the controls
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ctrl,
|
|
1
|
+
import type { Ctrl, CtrlItemType, CtrlChangeHandler, CtrlConfig } from "./types";
|
|
2
2
|
export declare class BooleanCtrl implements Ctrl<boolean> {
|
|
3
|
-
type:
|
|
3
|
+
type: CtrlItemType;
|
|
4
4
|
id: string;
|
|
5
5
|
group?: string;
|
|
6
6
|
name: string;
|
|
@@ -16,7 +16,7 @@ export class BooleanCtrl {
|
|
|
16
16
|
return value.toString();
|
|
17
17
|
};
|
|
18
18
|
this.buildUI = () => {
|
|
19
|
-
const id = toHtmlId(this.
|
|
19
|
+
const id = toHtmlId(this.id);
|
|
20
20
|
const input = document.createElement("input");
|
|
21
21
|
input.classList.add("ctrls__boolean-input");
|
|
22
22
|
input.setAttribute("type", "checkbox");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import DualRangeInput from "@stanko/dual-range-input";
|
|
2
|
-
import type { Ctrl, CtrlChangeHandler,
|
|
2
|
+
import type { Ctrl, CtrlChangeHandler, CtrlItemType, ConfigFor } from "./types";
|
|
3
3
|
export type DualRangeControlOptions = {
|
|
4
4
|
min: number;
|
|
5
5
|
max: number;
|
|
@@ -10,7 +10,7 @@ export type DualRangeValue = {
|
|
|
10
10
|
max: number;
|
|
11
11
|
};
|
|
12
12
|
export declare class DualRangeCtrl implements Ctrl<DualRangeValue> {
|
|
13
|
-
type:
|
|
13
|
+
type: CtrlItemType;
|
|
14
14
|
id: string;
|
|
15
15
|
group?: string;
|
|
16
16
|
name: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Ctrl, CtrlChangeHandler,
|
|
1
|
+
import type { Ctrl, CtrlChangeHandler, CtrlItemType, ConfigFor } from "./types";
|
|
2
2
|
export type Easing = [number, number, number, number];
|
|
3
3
|
export declare class EasingCtrl implements Ctrl<Easing> {
|
|
4
|
-
type:
|
|
4
|
+
type: CtrlItemType;
|
|
5
5
|
id: string;
|
|
6
6
|
group?: string;
|
|
7
7
|
name: string;
|
|
@@ -52,7 +52,7 @@ export class EasingCtrl {
|
|
|
52
52
|
};
|
|
53
53
|
this.buildUI = () => {
|
|
54
54
|
const { value } = this;
|
|
55
|
-
const id = toHtmlId(this.
|
|
55
|
+
const id = toHtmlId(this.id);
|
|
56
56
|
const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
57
57
|
line1.setAttribute("class", "ctrls__easing-line ctrls__easing-line--1");
|
|
58
58
|
line1.setAttribute("x1", "0");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Ctrl, CtrlChangeHandler, CtrlConfig, CtrlItemType } from "./types";
|
|
2
|
+
export declare class FileCtrl implements Ctrl<File | null> {
|
|
3
|
+
id: string;
|
|
4
|
+
type: CtrlItemType;
|
|
5
|
+
name: string;
|
|
6
|
+
label: string;
|
|
7
|
+
group: string;
|
|
8
|
+
value: File | null;
|
|
9
|
+
isRandomizationDisabled: boolean;
|
|
10
|
+
onChange: CtrlChangeHandler;
|
|
11
|
+
onInput: CtrlChangeHandler;
|
|
12
|
+
element: HTMLElement;
|
|
13
|
+
input: HTMLInputElement;
|
|
14
|
+
preview: HTMLDivElement;
|
|
15
|
+
accept: string;
|
|
16
|
+
constructor(config: CtrlConfig<File | null>, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
|
|
17
|
+
buildUI: () => {
|
|
18
|
+
element: HTMLDivElement;
|
|
19
|
+
input: HTMLInputElement;
|
|
20
|
+
preview: HTMLDivElement;
|
|
21
|
+
};
|
|
22
|
+
update: (file: File | null) => void;
|
|
23
|
+
parse: () => null;
|
|
24
|
+
getRandomValue: () => null;
|
|
25
|
+
getDefaultValue: () => null;
|
|
26
|
+
valueToString: () => string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { toHtmlId } from "../utils/string-utils";
|
|
2
|
+
import { dom } from "./dom";
|
|
3
|
+
import { closeIcon } from "../utils/icons";
|
|
4
|
+
const IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "webp", "svg+xml"];
|
|
5
|
+
export class FileCtrl {
|
|
6
|
+
constructor(config, onChange, onInput) {
|
|
7
|
+
this.type = "file";
|
|
8
|
+
this.buildUI = () => {
|
|
9
|
+
const id = toHtmlId(this.id);
|
|
10
|
+
const input = dom.input("ctrls__file-input", {
|
|
11
|
+
type: "file",
|
|
12
|
+
id: id,
|
|
13
|
+
name: id,
|
|
14
|
+
});
|
|
15
|
+
input.addEventListener("change", () => {
|
|
16
|
+
this.update(input.files ? input.files[0] : null);
|
|
17
|
+
this.onChange(this);
|
|
18
|
+
this.onInput(this);
|
|
19
|
+
});
|
|
20
|
+
const fakeInput = dom.label("ctrls__file-fake-input ctrls__btn ctrls__btn--sm", { for: id });
|
|
21
|
+
fakeInput.innerHTML = "select file";
|
|
22
|
+
if (this.accept) {
|
|
23
|
+
fakeInput.innerHTML += `<span>${this.accept}</span>`;
|
|
24
|
+
}
|
|
25
|
+
const clearButton = dom.button("ctrls__file-clear ctrls__btn");
|
|
26
|
+
clearButton.innerHTML = closeIcon;
|
|
27
|
+
clearButton.addEventListener("click", () => {
|
|
28
|
+
if (input.files) {
|
|
29
|
+
this.update(null);
|
|
30
|
+
this.onChange(this);
|
|
31
|
+
this.onInput(this);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const top = dom.div("ctrls__file-top");
|
|
35
|
+
top.append(input);
|
|
36
|
+
top.append(fakeInput);
|
|
37
|
+
top.append(clearButton);
|
|
38
|
+
const preview = dom.div("ctrls__file-preview");
|
|
39
|
+
const right = dom.div("ctrls__control-right");
|
|
40
|
+
right.append(top);
|
|
41
|
+
right.append(preview);
|
|
42
|
+
const label = dom.label("ctrls__control-label", {
|
|
43
|
+
for: id,
|
|
44
|
+
});
|
|
45
|
+
label.textContent = this.label;
|
|
46
|
+
const element = dom.div("ctrls__control ctrls__control--file");
|
|
47
|
+
element.appendChild(label);
|
|
48
|
+
element.appendChild(right);
|
|
49
|
+
return {
|
|
50
|
+
element,
|
|
51
|
+
input,
|
|
52
|
+
preview,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
this.update = (file) => {
|
|
56
|
+
this.value = file;
|
|
57
|
+
if (file) {
|
|
58
|
+
const item = document.createElement("figure");
|
|
59
|
+
item.classList.add("ctrls__file-preview-item");
|
|
60
|
+
if (IMAGE_EXTENSIONS.includes(file.type.split("/")[1])) {
|
|
61
|
+
console.log(URL.createObjectURL(file), file);
|
|
62
|
+
const img = document.createElement("img");
|
|
63
|
+
img.src = URL.createObjectURL(file);
|
|
64
|
+
img.alt = file.name;
|
|
65
|
+
img.classList.add("ctrls__file-image");
|
|
66
|
+
item.appendChild(img);
|
|
67
|
+
}
|
|
68
|
+
const label = document.createElement("figcaption");
|
|
69
|
+
label.classList.add("ctrls__file-label");
|
|
70
|
+
label.textContent = file.name;
|
|
71
|
+
item.appendChild(label);
|
|
72
|
+
this.preview.replaceChildren(item);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.preview.innerHTML = "";
|
|
76
|
+
this.input.value = "";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
// Files can't be preserved in the URL hash,
|
|
80
|
+
// so these are only placeholders to satisfy the interface
|
|
81
|
+
this.parse = () => null;
|
|
82
|
+
this.getRandomValue = () => null;
|
|
83
|
+
this.getDefaultValue = () => null;
|
|
84
|
+
this.valueToString = () => "";
|
|
85
|
+
this.name = config.name;
|
|
86
|
+
this.id = config.id || config.name;
|
|
87
|
+
this.label = config.label || config.name;
|
|
88
|
+
this.group = config.group || "";
|
|
89
|
+
this.value = null;
|
|
90
|
+
this.accept = config.accept || "";
|
|
91
|
+
this.isRandomizationDisabled = config.isRandomizationDisabled || false;
|
|
92
|
+
this.onChange = onChange;
|
|
93
|
+
this.onInput = onInput;
|
|
94
|
+
const { input, element, preview } = this.buildUI();
|
|
95
|
+
this.input = input;
|
|
96
|
+
this.element = element;
|
|
97
|
+
this.preview = preview;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const getHTMLControlElement = (config) => {
|
|
2
|
+
const right = document.createElement("div");
|
|
3
|
+
right.classList.add("ctrls__control-right");
|
|
4
|
+
right.append(config.html);
|
|
5
|
+
const label = document.createElement("label");
|
|
6
|
+
label.textContent = config.label || config.name;
|
|
7
|
+
label.classList.add("ctrls__control-label");
|
|
8
|
+
const element = document.createElement("div");
|
|
9
|
+
element.classList.add("ctrls__control", "ctrls__control--seed");
|
|
10
|
+
element.appendChild(label);
|
|
11
|
+
element.appendChild(right);
|
|
12
|
+
return element;
|
|
13
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Ctrl, CtrlChangeHandler,
|
|
1
|
+
import type { Ctrl, CtrlChangeHandler, CtrlItemType, ConfigFor } from "./types";
|
|
2
2
|
type Option = {
|
|
3
3
|
label: string;
|
|
4
4
|
value: string;
|
|
@@ -7,7 +7,7 @@ export type RadioControlOptions = {
|
|
|
7
7
|
items: Option[];
|
|
8
8
|
};
|
|
9
9
|
export declare class RadioCtrl implements Ctrl<string> {
|
|
10
|
-
type:
|
|
10
|
+
type: CtrlItemType;
|
|
11
11
|
htmlId: string;
|
|
12
12
|
id: string;
|
|
13
13
|
group?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ctrl, CtrlChangeHandler,
|
|
1
|
+
import type { Ctrl, CtrlChangeHandler, CtrlItemType, ConfigFor } from "./types";
|
|
2
2
|
export declare class RangeCtrl implements Ctrl<number> {
|
|
3
|
-
type:
|
|
3
|
+
type: CtrlItemType;
|
|
4
4
|
id: string;
|
|
5
5
|
group?: string;
|
|
6
6
|
name: string;
|
package/dist/ctrls/ctrl-range.js
CHANGED
|
@@ -20,7 +20,7 @@ export class RangeCtrl {
|
|
|
20
20
|
};
|
|
21
21
|
this.buildUI = () => {
|
|
22
22
|
const { min, max, step, value } = this;
|
|
23
|
-
const id = toHtmlId(this.
|
|
23
|
+
const id = toHtmlId(this.id);
|
|
24
24
|
const input = document.createElement("input");
|
|
25
25
|
input.classList.add("ctrls__range-input");
|
|
26
26
|
input.setAttribute("type", "range");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ctrl, CtrlChangeHandler, CtrlConfig,
|
|
1
|
+
import type { Ctrl, CtrlChangeHandler, CtrlConfig, CtrlItemType } from "./types";
|
|
2
2
|
export declare class SeedCtrl implements Ctrl<string> {
|
|
3
|
-
type:
|
|
3
|
+
type: CtrlItemType;
|
|
4
4
|
id: string;
|
|
5
5
|
group?: string;
|
|
6
6
|
name: string;
|
package/dist/ctrls/ctrl-seed.js
CHANGED
|
@@ -21,7 +21,7 @@ export class SeedCtrl {
|
|
|
21
21
|
};
|
|
22
22
|
this.buildUI = () => {
|
|
23
23
|
const { value } = this;
|
|
24
|
-
const id = toHtmlId(this.
|
|
24
|
+
const id = toHtmlId(this.id);
|
|
25
25
|
const input = document.createElement("input");
|
|
26
26
|
input.classList.add("ctrls__seed-input");
|
|
27
27
|
input.setAttribute("type", "text");
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Attrs = Record<string, string | number> & {
|
|
2
|
+
for?: string;
|
|
3
|
+
};
|
|
4
|
+
export declare const dom: {
|
|
5
|
+
el: <T extends keyof HTMLElementTagNameMap>(tag: T, className?: string, attrs?: Attrs) => HTMLElementTagNameMap[T];
|
|
6
|
+
div: (className?: string, attrs?: Attrs) => HTMLDivElement;
|
|
7
|
+
span: (className?: string, attrs?: Attrs) => HTMLSpanElement;
|
|
8
|
+
input: (className?: string, attrs?: Attrs) => HTMLInputElement;
|
|
9
|
+
label: (className?: string, attrs?: Attrs) => HTMLLabelElement;
|
|
10
|
+
button: (className?: string, attrs?: Attrs) => HTMLButtonElement;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const el = (tag, className = "", attrs = {}) => {
|
|
2
|
+
const element = document.createElement(tag);
|
|
3
|
+
element.className = className;
|
|
4
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
5
|
+
element.setAttribute(key, value.toString());
|
|
6
|
+
}
|
|
7
|
+
return element;
|
|
8
|
+
};
|
|
9
|
+
export const dom = {
|
|
10
|
+
el,
|
|
11
|
+
div: (className = "", attrs = {}) => el("div", className, attrs),
|
|
12
|
+
span: (className = "", attrs = {}) => el("span", className, attrs),
|
|
13
|
+
input: (className = "", attrs = {}) => el("input", className, attrs),
|
|
14
|
+
label: (className = "", attrs = {}) => el("label", className, attrs),
|
|
15
|
+
button: (className = "", attrs = {}) => el("button", className, attrs),
|
|
16
|
+
};
|
package/dist/ctrls/index.d.ts
CHANGED
|
@@ -1,127 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BooleanCtrl } from "./ctrl-boolean";
|
|
3
|
-
import { DualRangeCtrl, type DualRangeValue } from "./ctrl-dual-range";
|
|
4
|
-
import { EasingCtrl, type Easing } from "./ctrl-easing";
|
|
5
|
-
import { RadioCtrl } from "./ctrl-radio";
|
|
6
|
-
import { RangeCtrl } from "./ctrl-range";
|
|
7
|
-
import { SeedCtrl } from "./ctrl-seed";
|
|
8
|
-
export interface PRNG {
|
|
9
|
-
(): number;
|
|
10
|
-
}
|
|
11
|
-
export type CtrlType = "boolean" | "range" | "radio" | "seed" | "easing" | "dual-range" | "group";
|
|
12
|
-
export type CtrlChangeHandler = (control: CtrlComponent) => void;
|
|
13
|
-
export type CtrlConfig<T = unknown> = {
|
|
14
|
-
type: CtrlType;
|
|
15
|
-
id?: string;
|
|
16
|
-
name: string;
|
|
17
|
-
group?: string;
|
|
18
|
-
label?: string;
|
|
19
|
-
defaultValue?: T;
|
|
20
|
-
isRandomizationDisabled?: boolean;
|
|
21
|
-
};
|
|
22
|
-
export interface Ctrl<T> {
|
|
23
|
-
id: string;
|
|
24
|
-
group?: string;
|
|
25
|
-
name: string;
|
|
26
|
-
label: string;
|
|
27
|
-
type: CtrlType;
|
|
28
|
-
isRandomizationDisabled: boolean;
|
|
29
|
-
onChange: CtrlChangeHandler;
|
|
30
|
-
parse: (value: string) => T;
|
|
31
|
-
getRandomValue: () => T;
|
|
32
|
-
getDefaultValue: () => T;
|
|
33
|
-
buildUI: () => unknown;
|
|
34
|
-
valueToString: (value?: T) => string;
|
|
35
|
-
update: (value: T) => void;
|
|
36
|
-
element: HTMLElement;
|
|
37
|
-
}
|
|
38
|
-
export interface CtrlTypeMap {
|
|
39
|
-
boolean: {
|
|
40
|
-
value: boolean;
|
|
41
|
-
};
|
|
42
|
-
range: {
|
|
43
|
-
value: number;
|
|
44
|
-
min: number;
|
|
45
|
-
max: number;
|
|
46
|
-
step?: number;
|
|
47
|
-
};
|
|
48
|
-
radio: {
|
|
49
|
-
value: string;
|
|
50
|
-
items: Record<string, string>;
|
|
51
|
-
columns?: 1 | 2 | 3 | 4 | 5;
|
|
52
|
-
};
|
|
53
|
-
seed: {
|
|
54
|
-
value: string;
|
|
55
|
-
};
|
|
56
|
-
easing: {
|
|
57
|
-
value: Easing;
|
|
58
|
-
presets?: Record<string, Easing>;
|
|
59
|
-
};
|
|
60
|
-
"dual-range": {
|
|
61
|
-
value: DualRangeValue;
|
|
62
|
-
min: number;
|
|
63
|
-
max: number;
|
|
64
|
-
step?: number;
|
|
65
|
-
};
|
|
66
|
-
group: {
|
|
67
|
-
value: Record<string, unknown>;
|
|
68
|
-
controls: readonly ConfigItem[];
|
|
69
|
-
isRandomizationDisabled?: boolean;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
export type TypedControlConfig = {
|
|
73
|
-
[K in CtrlType]: {
|
|
74
|
-
type: K;
|
|
75
|
-
id?: string;
|
|
76
|
-
name: string;
|
|
77
|
-
group?: string;
|
|
78
|
-
label?: string;
|
|
79
|
-
defaultValue?: CtrlTypeMap[K]["value"];
|
|
80
|
-
isRandomizationDisabled?: boolean;
|
|
81
|
-
} & Omit<CtrlTypeMap[K], "value">;
|
|
82
|
-
}[CtrlType];
|
|
83
|
-
export type GroupConfig = {
|
|
84
|
-
type: "group";
|
|
85
|
-
name: string;
|
|
86
|
-
label?: string;
|
|
87
|
-
controls: readonly TypedControlConfig[];
|
|
88
|
-
isRandomizationDisabled?: boolean;
|
|
89
|
-
};
|
|
90
|
-
export type ConfigItem = TypedControlConfig | GroupConfig;
|
|
91
|
-
export type ConfigFor<T extends CtrlType> = Extract<TypedControlConfig, {
|
|
92
|
-
type: T;
|
|
93
|
-
}>;
|
|
94
|
-
type ExtractValues<Configs extends readonly ConfigItem[]> = {
|
|
95
|
-
[C in Extract<Configs[number], {
|
|
96
|
-
type: Exclude<CtrlType, "group">;
|
|
97
|
-
}> as C["name"]]: CtrlTypeMap[C["type"]]["value"];
|
|
98
|
-
} & {
|
|
99
|
-
[C in Extract<Configs[number], {
|
|
100
|
-
type: "group";
|
|
101
|
-
}> as C["name"]]: OptionsMap<C["controls"]>;
|
|
102
|
-
};
|
|
103
|
-
type DerivedProps<Configs extends readonly ConfigItem[]> = {
|
|
104
|
-
[C in Extract<Configs[number], {
|
|
105
|
-
type: "easing";
|
|
106
|
-
}> as `${C["name"]}Easing`]: ReturnType<typeof BezierEasing>;
|
|
107
|
-
} & {
|
|
108
|
-
[C in Extract<Configs[number], {
|
|
109
|
-
type: "seed";
|
|
110
|
-
}> as `${C["name"]}Rng`]: PRNG;
|
|
111
|
-
} & {
|
|
112
|
-
[C in Extract<Configs[number], {
|
|
113
|
-
type: "group";
|
|
114
|
-
}> as C["name"]]: DerivedProps<C["controls"]>;
|
|
115
|
-
};
|
|
116
|
-
type OptionsMap<Configs extends readonly ConfigItem[]> = ExtractValues<Configs> & DerivedProps<Configs>;
|
|
117
|
-
type ControlsOptions = {
|
|
118
|
-
showRandomizeButton?: boolean;
|
|
119
|
-
storage?: "hash" | "none";
|
|
120
|
-
theme?: "system" | "light" | "dark";
|
|
121
|
-
parent?: Element;
|
|
122
|
-
title?: string;
|
|
123
|
-
};
|
|
124
|
-
type CtrlComponent = BooleanCtrl | RangeCtrl | RadioCtrl | SeedCtrl | EasingCtrl | DualRangeCtrl;
|
|
1
|
+
import type { CtrlComponent, ConfigItem, ControlsOptions, TypedControlConfig, OptionsMap } from "./types";
|
|
125
2
|
export declare class Ctrls<Configs extends readonly ConfigItem[]> {
|
|
126
3
|
options: ControlsOptions;
|
|
127
4
|
controls: CtrlComponent[];
|
|
@@ -130,8 +7,8 @@ export declare class Ctrls<Configs extends readonly ConfigItem[]> {
|
|
|
130
7
|
onChange?: (updatedValues: Partial<ReturnType<typeof this.getValues>>) => void;
|
|
131
8
|
onInput?: (updatedValues: Partial<ReturnType<typeof this.getValues>>) => void;
|
|
132
9
|
constructor(configs: Configs, options?: ControlsOptions);
|
|
133
|
-
|
|
134
|
-
|
|
10
|
+
processControls: (configs: Configs) => HTMLElement[];
|
|
11
|
+
registerControl: (config: TypedControlConfig, onChangeControlHandler: (control: CtrlComponent) => void, onInputControlHandler: (control: CtrlComponent) => void, group?: string) => CtrlComponent;
|
|
135
12
|
toggleVisibility: () => void;
|
|
136
13
|
addHashListeners: () => void;
|
|
137
14
|
getHash: () => string;
|
|
@@ -141,4 +18,3 @@ export declare class Ctrls<Configs extends readonly ConfigItem[]> {
|
|
|
141
18
|
getValues(): OptionsMap<Configs>;
|
|
142
19
|
randomize: () => void;
|
|
143
20
|
}
|
|
144
|
-
export {};
|