tweakit 0.6.0 → 0.7.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/AGENTS.md +5 -5
- package/README.md +3 -3
- package/dist/tweaks/auto.js +1 -1
- package/dist/tweaks/auto.js.map +1 -1
- package/dist/tweaks/bezier-S2BOXQBM.js +2 -0
- package/dist/tweaks/bezier-S2BOXQBM.js.map +6 -0
- package/dist/tweaks/chunk-3MZAAMC2.js +2 -0
- package/dist/tweaks/chunk-3MZAAMC2.js.map +6 -0
- package/dist/tweaks/chunk-ETB35KFV.js +2 -0
- package/dist/tweaks/chunk-ETB35KFV.js.map +6 -0
- package/dist/tweaks/chunk-YB5GKWZI.js +2 -0
- package/dist/tweaks/chunk-YB5GKWZI.js.map +6 -0
- package/dist/tweaks/clip-A3VI53BK.js +2 -0
- package/dist/tweaks/clip-A3VI53BK.js.map +6 -0
- package/dist/tweaks/color-UGYMAF3W.js +2 -0
- package/dist/tweaks/core.js +1 -1
- package/dist/tweaks/core.js.map +3 -3
- package/dist/tweaks/fold-GY47HIQA.js +2 -0
- package/dist/tweaks/fold-GY47HIQA.js.map +6 -0
- package/dist/tweaks/gradient-BTX25WSH.js +2 -0
- package/dist/tweaks/gradient-BTX25WSH.js.map +6 -0
- package/dist/tweaks/{heavy-CLD7UAVI.js → heavy-NPFIGHRM.js} +2 -2
- package/dist/tweaks/image-HTQQ4WX6.js +4 -0
- package/dist/tweaks/image-HTQQ4WX6.js.map +6 -0
- package/dist/tweaks/{image-store-WRKY2NPU.js → image-store-QD5SMZXG.js} +1 -1
- package/dist/tweaks/image-store-QD5SMZXG.js.map +6 -0
- package/dist/tweaks/interval-BHPI4LRN.js +2 -0
- package/dist/tweaks/interval-BHPI4LRN.js.map +6 -0
- package/dist/tweaks/markup-QM53TQJZ.js +2 -0
- package/dist/tweaks/markup-QM53TQJZ.js.map +6 -0
- package/dist/tweaks/monitor-722WIYGW.js +3 -0
- package/dist/tweaks/monitor-722WIYGW.js.map +6 -0
- package/dist/tweaks/motion-HMCZK6HJ.js +2 -0
- package/dist/tweaks/motion-HMCZK6HJ.js.map +6 -0
- package/dist/tweaks/plot-D3NQ6XNN.js +3 -0
- package/dist/tweaks/plot-D3NQ6XNN.js.map +6 -0
- package/dist/tweaks/point-XDXKMDXH.js +2 -0
- package/dist/tweaks/point-XDXKMDXH.js.map +6 -0
- package/dist/tweaks/presets-EUWNSCUW.js +2 -0
- package/dist/tweaks/presets-EUWNSCUW.js.map +6 -0
- package/dist/tweaks/shadow-AM7VSRNS.js +2 -0
- package/dist/tweaks/shadow-AM7VSRNS.js.map +6 -0
- package/dist/tweaks/shadow-root-RYUV3AGS.js +3 -0
- package/dist/tweaks/shadow-root-RYUV3AGS.js.map +6 -0
- package/dist/tweaks/sides-JWIURDA4.js +2 -0
- package/dist/tweaks/sides-JWIURDA4.js.map +6 -0
- package/dist/tweaks/spring-BF5GBTPM.js +2 -0
- package/dist/tweaks/spring-BF5GBTPM.js.map +6 -0
- package/dist/tweaks/tabs-PRVUUZXZ.js +2 -0
- package/dist/tweaks/tabs-PRVUUZXZ.js.map +6 -0
- package/dist/tweaks.css +1 -1
- package/dist/tweaks.js +5 -4
- package/dist/tweaks.js.map +3 -3
- package/dist/types/tweaks/enhance.d.ts +3 -2
- package/dist/types/tweaks/types.d.ts +278 -72
- package/package.json +5 -2
- package/src/tweaks/auto.ts +9 -5
- package/src/tweaks/clip.ts +84 -22
- package/src/tweaks/controls/basic.ts +463 -139
- package/src/tweaks/controls/bezier.ts +152 -47
- package/src/tweaks/controls/color.ts +610 -161
- package/src/tweaks/controls/gradient.ts +256 -77
- package/src/tweaks/controls/image.ts +388 -132
- package/src/tweaks/controls/interval.ts +126 -41
- package/src/tweaks/controls/monitor.ts +142 -36
- package/src/tweaks/controls/motion.ts +231 -56
- package/src/tweaks/controls/plot.ts +321 -101
- package/src/tweaks/controls/point.ts +134 -45
- package/src/tweaks/controls/shadow.ts +103 -30
- package/src/tweaks/controls/sides.ts +150 -40
- package/src/tweaks/controls/spring.ts +220 -60
- package/src/tweaks/controls/tabs.ts +39 -18
- package/src/tweaks/core.ts +1 -1
- package/src/tweaks/easing.ts +45 -20
- package/src/tweaks/enhance.ts +21 -6
- package/src/tweaks/feedback.ts +133 -34
- package/src/tweaks/fold.ts +22 -10
- package/src/tweaks/heavy.ts +461 -137
- package/src/tweaks/icons.ts +12 -5
- package/src/tweaks/image-store.ts +131 -43
- package/src/tweaks/lazy.ts +36 -19
- package/src/tweaks/markup.ts +255 -92
- package/src/tweaks/panel.ts +1262 -438
- package/src/tweaks/presets.ts +85 -0
- package/src/tweaks/schema.ts +213 -51
- package/src/tweaks/shadow-root.ts +178 -0
- package/src/tweaks/shared.ts +802 -190
- package/src/tweaks/standalone.ts +120 -30
- package/src/tweaks/types.ts +644 -143
- package/src/tweaks/undo.ts +104 -0
- package/src/tweaks.css +556 -550
- package/src/wide-gamut.ts +473 -125
- package/dist/tweaks/bezier-JFEZMCLP.js +0 -2
- package/dist/tweaks/bezier-JFEZMCLP.js.map +0 -6
- package/dist/tweaks/chunk-6UO4DHBN.js +0 -2
- package/dist/tweaks/chunk-6UO4DHBN.js.map +0 -6
- package/dist/tweaks/chunk-DIQMLBAS.js +0 -2
- package/dist/tweaks/chunk-DIQMLBAS.js.map +0 -6
- package/dist/tweaks/chunk-XE6OUJBG.js +0 -2
- package/dist/tweaks/chunk-XE6OUJBG.js.map +0 -6
- package/dist/tweaks/clip-WW7JYO4X.js +0 -2
- package/dist/tweaks/clip-WW7JYO4X.js.map +0 -6
- package/dist/tweaks/color-YMMFURP6.js +0 -2
- package/dist/tweaks/fold-U6YRZLCJ.js +0 -2
- package/dist/tweaks/fold-U6YRZLCJ.js.map +0 -6
- package/dist/tweaks/gradient-JER7PW4D.js +0 -2
- package/dist/tweaks/gradient-JER7PW4D.js.map +0 -6
- package/dist/tweaks/image-H6QSLGO3.js +0 -4
- package/dist/tweaks/image-H6QSLGO3.js.map +0 -6
- package/dist/tweaks/image-store-WRKY2NPU.js.map +0 -6
- package/dist/tweaks/interval-TEUHQGZN.js +0 -2
- package/dist/tweaks/interval-TEUHQGZN.js.map +0 -6
- package/dist/tweaks/markup-NIBJD6E2.js +0 -2
- package/dist/tweaks/markup-NIBJD6E2.js.map +0 -6
- package/dist/tweaks/monitor-3BY7YCGX.js +0 -3
- package/dist/tweaks/monitor-3BY7YCGX.js.map +0 -6
- package/dist/tweaks/motion-FQPUBKKM.js +0 -2
- package/dist/tweaks/motion-FQPUBKKM.js.map +0 -6
- package/dist/tweaks/plot-2HBNBZSG.js +0 -3
- package/dist/tweaks/plot-2HBNBZSG.js.map +0 -6
- package/dist/tweaks/point-VV6XV3I6.js +0 -2
- package/dist/tweaks/point-VV6XV3I6.js.map +0 -6
- package/dist/tweaks/shadow-5E4E55I2.js +0 -2
- package/dist/tweaks/shadow-5E4E55I2.js.map +0 -6
- package/dist/tweaks/sides-P3STEVYY.js +0 -2
- package/dist/tweaks/sides-P3STEVYY.js.map +0 -6
- package/dist/tweaks/spring-HUVSXNVN.js +0 -2
- package/dist/tweaks/spring-HUVSXNVN.js.map +0 -6
- package/dist/tweaks/tabs-76FW7LQ7.js +0 -2
- package/dist/tweaks/tabs-76FW7LQ7.js.map +0 -6
- /package/dist/tweaks/{color-YMMFURP6.js.map → color-UGYMAF3W.js.map} +0 -0
- /package/dist/tweaks/{heavy-CLD7UAVI.js.map → heavy-NPFIGHRM.js.map} +0 -0
package/src/tweaks/standalone.ts
CHANGED
|
@@ -1,89 +1,179 @@
|
|
|
1
1
|
/* Standalone controls — the kit's controls without the panel: mountControl() builds one control
|
|
2
2
|
* into a host of your own, createColorPicker() hands out the color editor surface alone. */
|
|
3
|
-
import { el, getControl, onReady, setDisabled, valueChanged } from "./shared.js";
|
|
3
|
+
import { el, getControl, onReady, setDisabled, valueChanged, isolate, using } from "./shared.js";
|
|
4
4
|
import { metaFor, VALUELESS } from "./schema.js";
|
|
5
5
|
import { ensureForMetas } from "./lazy.js";
|
|
6
6
|
import { createControl } from "./controls/basic.js";
|
|
7
7
|
import { addHintMarker } from "./feedback.js";
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
SchemaValue,
|
|
10
|
+
HeldValue,
|
|
11
|
+
KnownType,
|
|
12
|
+
MountOptions,
|
|
13
|
+
MountedControl,
|
|
14
|
+
ColorPickerOptions,
|
|
15
|
+
ColorPicker,
|
|
16
|
+
ColorMode,
|
|
17
|
+
Control,
|
|
18
|
+
Get,
|
|
19
|
+
} from "./types.js";
|
|
9
20
|
import type { Meta } from "./schema.js";
|
|
10
21
|
import type { PickerBody, PickerOptions } from "./controls/color.js";
|
|
11
22
|
|
|
12
|
-
// Outside a .
|
|
13
|
-
const scope = (cls: string) => el("div", `${cls}
|
|
14
|
-
// Run `build` once the lazy module has landed (synchronously when none is missing); the handled fork keeps a failed
|
|
23
|
+
// Outside a .twk-panel the cascade delivers none of the kit's tokens, so the wrapper carries .twk-portal.
|
|
24
|
+
const scope = (cls: string) => el("div", `${cls} twk-standalone twk-portal`);
|
|
25
|
+
// Run `build` once the lazy module has landed (synchronously when none is missing); the handled fork keeps a failed
|
|
26
|
+
// chunk out of the unhandled-rejection channel.
|
|
15
27
|
const whenLoaded = <H>(metas: Array<Pick<Meta, "type">>, build: () => void, handle: H): Promise<H> => {
|
|
16
28
|
const pend = ensureForMetas(metas);
|
|
17
|
-
if (!pend) {
|
|
29
|
+
if (!pend) {
|
|
30
|
+
build();
|
|
31
|
+
return Promise.resolve(handle);
|
|
32
|
+
}
|
|
18
33
|
const ready = pend.then(build).then(() => handle);
|
|
19
34
|
ready.catch(() => {});
|
|
20
35
|
return ready;
|
|
21
36
|
};
|
|
22
37
|
|
|
23
38
|
/** One control from a schema value, into `host`; a folder or tabs set is tweaks()'s to build. */
|
|
24
|
-
export function mountControl<const V extends HeldValue>(
|
|
39
|
+
export function mountControl<const V extends HeldValue>(
|
|
40
|
+
host: Element,
|
|
41
|
+
value: V & KnownType<V>,
|
|
42
|
+
opts?: MountOptions,
|
|
43
|
+
): MountedControl;
|
|
25
44
|
export function mountControl(host: Element, value: SchemaValue, opts: MountOptions = {}): MountedControl {
|
|
26
45
|
const key = opts.key ?? "value";
|
|
27
46
|
const meta = metaFor(key, value);
|
|
28
|
-
if (!meta || meta.type === "folder" || meta.type === "tabs")
|
|
47
|
+
if (!meta || meta.type === "folder" || meta.type === "tabs")
|
|
48
|
+
throw new TypeError(`[tweaks] mountControl: "${key}" is not a single-control schema value`);
|
|
29
49
|
if (opts.label != null) meta.label = String(opts.label); // the option wins over the derived label; "" = no label
|
|
30
50
|
const valued = !VALUELESS.has(meta.type); // display/action controls carry no value: set/get are inert
|
|
31
|
-
const root = scope("
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
const root = scope("twk-control"); // the control fills it in on ready
|
|
52
|
+
const iso = isolate(root, opts.shadow);
|
|
53
|
+
host.append(iso.box);
|
|
54
|
+
let ctrl: Control | null = null,
|
|
55
|
+
destroyed = false,
|
|
56
|
+
last: unknown = meta.value,
|
|
57
|
+
parked: unknown,
|
|
58
|
+
queued = false;
|
|
34
59
|
// Gated the way the panel gates notify(): a same-value set() stays silent instead of echoing.
|
|
35
|
-
const emit = (v: unknown) => {
|
|
60
|
+
const emit = (v: unknown) => {
|
|
61
|
+
if (!valueChanged(last, v)) return;
|
|
62
|
+
last = v;
|
|
63
|
+
opts.onChange && opts.onChange(v, key);
|
|
64
|
+
};
|
|
36
65
|
const build = () => {
|
|
37
66
|
if (destroyed) return; // destroy() before the chunk landed — nothing to mount
|
|
38
|
-
ctrl = createControl(meta, valued ? emit : () => {});
|
|
67
|
+
ctrl = using(opts.strings, () => createControl(meta, valued ? emit : () => {}));
|
|
39
68
|
if (!ctrl) return; // a failed chunk degrades to an empty wrapper
|
|
40
69
|
if (meta.hint) addHintMarker(ctrl.el, meta.hint);
|
|
41
70
|
// Resolved once at mount: with no siblings for a predicate to read, `get` answers undefined.
|
|
42
71
|
const none: Get = () => undefined;
|
|
43
|
-
try {
|
|
44
|
-
|
|
72
|
+
try {
|
|
73
|
+
if (meta.render && !meta.render(none)) ctrl.el.classList.add("twk-cond-hidden");
|
|
74
|
+
} catch {}
|
|
75
|
+
// each predicate fails on its own
|
|
76
|
+
try {
|
|
77
|
+
const d = typeof meta.disabled === "function" ? meta.disabled(none) : meta.disabled;
|
|
78
|
+
if (d) setDisabled(ctrl.el, true);
|
|
79
|
+
} catch {}
|
|
45
80
|
root.append(ctrl.el);
|
|
46
81
|
if (!valued) return;
|
|
47
82
|
last = ctrl.get(); // the form the control opened on
|
|
48
|
-
|
|
83
|
+
// a set() from the lazy window applies and announces now
|
|
84
|
+
if (queued) {
|
|
85
|
+
ctrl.set(parked);
|
|
86
|
+
emit(ctrl.get());
|
|
87
|
+
}
|
|
49
88
|
};
|
|
50
89
|
const handle: MountedControl = {
|
|
51
|
-
el:
|
|
52
|
-
set: (v) => {
|
|
90
|
+
el: iso.box,
|
|
91
|
+
set: (v) => {
|
|
92
|
+
if (destroyed || !valued) return;
|
|
93
|
+
if (ctrl) {
|
|
94
|
+
ctrl.set(v);
|
|
95
|
+
emit(ctrl.get());
|
|
96
|
+
} else {
|
|
97
|
+
parked = v;
|
|
98
|
+
queued = true;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
53
101
|
get: () => (!valued ? undefined : ctrl ? ctrl.get() : queued ? parked : meta.value),
|
|
54
|
-
|
|
102
|
+
// onLive listeners release on their next event by this mark
|
|
103
|
+
destroy: () => {
|
|
104
|
+
destroyed = true;
|
|
105
|
+
if (ctrl && typeof ctrl.destroy === "function") ctrl.destroy();
|
|
106
|
+
root.dataset.twkDestroyed = "";
|
|
107
|
+
root.remove();
|
|
108
|
+
iso.end();
|
|
109
|
+
},
|
|
55
110
|
ready: null,
|
|
56
111
|
};
|
|
57
112
|
handle.ready = whenLoaded([meta], build, handle);
|
|
113
|
+
// the handled fork whenLoaded keeps
|
|
114
|
+
if (iso.dressed) (handle.ready = Promise.all([handle.ready, iso.dressed]).then(() => handle)).catch(() => {});
|
|
58
115
|
return handle;
|
|
59
116
|
}
|
|
60
117
|
|
|
61
118
|
/** The color editor surface alone, for a host page that brings its own swatch. */
|
|
62
119
|
export function createColorPicker(opts: ColorPickerOptions = {}): ColorPicker {
|
|
63
|
-
const root = scope("
|
|
64
|
-
|
|
65
|
-
|
|
120
|
+
const root = scope("twk-color-picker"),
|
|
121
|
+
iso = isolate(root, opts.shadow);
|
|
122
|
+
let body: PickerBody | null = null,
|
|
123
|
+
destroyed = false,
|
|
124
|
+
last = opts.value,
|
|
125
|
+
parked: string,
|
|
126
|
+
queued = false,
|
|
127
|
+
parkedMode: ColorMode = null;
|
|
128
|
+
const emit = (v: string) => {
|
|
129
|
+
if (!valueChanged(last, v)) return;
|
|
130
|
+
last = v;
|
|
131
|
+
opts.onChange && opts.onChange(v);
|
|
132
|
+
};
|
|
66
133
|
const build = () => {
|
|
67
134
|
if (destroyed) return;
|
|
68
|
-
|
|
135
|
+
// registered by the color module beside its control
|
|
136
|
+
const make = getControl<PickerBody, PickerOptions>("colorpicker");
|
|
69
137
|
if (!make) return;
|
|
70
|
-
body = make({ value: opts.value, mode: opts.mode }, emit);
|
|
138
|
+
body = using(opts.strings, () => make({ value: opts.value, mode: opts.mode }, emit));
|
|
71
139
|
last = body.get();
|
|
72
140
|
root.append(body.el);
|
|
73
141
|
if (parkedMode) body.setMode(parkedMode);
|
|
74
|
-
if (queued) {
|
|
142
|
+
if (queued) {
|
|
143
|
+
body.set(parked);
|
|
144
|
+
emit(body.get());
|
|
145
|
+
}
|
|
75
146
|
onReady(body.reflow); // next frame: the thumbs need a real box
|
|
76
147
|
};
|
|
77
148
|
const picker: ColorPicker = {
|
|
78
|
-
el:
|
|
79
|
-
set: (v) => {
|
|
149
|
+
el: iso.box,
|
|
150
|
+
set: (v) => {
|
|
151
|
+
if (destroyed) return;
|
|
152
|
+
if (body) {
|
|
153
|
+
body.set(v);
|
|
154
|
+
emit(body.get());
|
|
155
|
+
} else {
|
|
156
|
+
parked = v;
|
|
157
|
+
queued = true;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
80
160
|
get: () => (body ? body.get() : queued ? parked : opts.value),
|
|
81
161
|
mode: () => (body ? body.mode() : parkedMode || opts.mode || "oklch"),
|
|
82
|
-
setMode: (m) => {
|
|
83
|
-
|
|
84
|
-
|
|
162
|
+
setMode: (m) => {
|
|
163
|
+
if (body) body.setMode(m);
|
|
164
|
+
else parkedMode = m;
|
|
165
|
+
},
|
|
166
|
+
reflow: () => {
|
|
167
|
+
if (body) body.reflow();
|
|
168
|
+
},
|
|
169
|
+
destroy: () => {
|
|
170
|
+
destroyed = true;
|
|
171
|
+
root.remove();
|
|
172
|
+
iso.end();
|
|
173
|
+
},
|
|
85
174
|
ready: null,
|
|
86
175
|
};
|
|
87
176
|
picker.ready = whenLoaded([{ type: "color" }], build, picker);
|
|
177
|
+
if (iso.dressed) (picker.ready = Promise.all([picker.ready, iso.dressed]).then(() => picker)).catch(() => {});
|
|
88
178
|
return picker;
|
|
89
179
|
}
|