tweakit 0.5.2 → 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.
Files changed (120) hide show
  1. package/AGENTS.md +32 -30
  2. package/README.md +55 -29
  3. package/THIRD-PARTY-NOTICES.md +0 -1
  4. package/dist/tweaks/auto.js +2 -0
  5. package/dist/tweaks/auto.js.map +6 -0
  6. package/dist/tweaks/bezier-S2BOXQBM.js +2 -0
  7. package/dist/tweaks/bezier-S2BOXQBM.js.map +6 -0
  8. package/dist/tweaks/chunk-3MZAAMC2.js +2 -0
  9. package/dist/tweaks/chunk-3MZAAMC2.js.map +6 -0
  10. package/dist/tweaks/chunk-ETB35KFV.js +2 -0
  11. package/dist/tweaks/chunk-ETB35KFV.js.map +6 -0
  12. package/dist/tweaks/chunk-YB5GKWZI.js +2 -0
  13. package/dist/tweaks/chunk-YB5GKWZI.js.map +6 -0
  14. package/dist/tweaks/clip-A3VI53BK.js +2 -0
  15. package/dist/tweaks/clip-A3VI53BK.js.map +6 -0
  16. package/dist/tweaks/color-UGYMAF3W.js +2 -0
  17. package/dist/tweaks/color-UGYMAF3W.js.map +6 -0
  18. package/dist/tweaks/core.js +2 -1
  19. package/dist/tweaks/core.js.map +6 -0
  20. package/dist/tweaks/fold-GY47HIQA.js +2 -0
  21. package/dist/tweaks/fold-GY47HIQA.js.map +6 -0
  22. package/dist/tweaks/gradient-BTX25WSH.js +2 -0
  23. package/dist/tweaks/gradient-BTX25WSH.js.map +6 -0
  24. package/dist/tweaks/heavy-NPFIGHRM.js +2 -0
  25. package/dist/tweaks/heavy-NPFIGHRM.js.map +6 -0
  26. package/dist/tweaks/image-HTQQ4WX6.js +4 -0
  27. package/dist/tweaks/image-HTQQ4WX6.js.map +6 -0
  28. package/dist/tweaks/image-store-QD5SMZXG.js +2 -0
  29. package/dist/tweaks/image-store-QD5SMZXG.js.map +6 -0
  30. package/dist/tweaks/interval-BHPI4LRN.js +2 -0
  31. package/dist/tweaks/interval-BHPI4LRN.js.map +6 -0
  32. package/dist/tweaks/markup-QM53TQJZ.js +2 -0
  33. package/dist/tweaks/markup-QM53TQJZ.js.map +6 -0
  34. package/dist/tweaks/monitor-722WIYGW.js +3 -0
  35. package/dist/tweaks/monitor-722WIYGW.js.map +6 -0
  36. package/dist/tweaks/motion-HMCZK6HJ.js +2 -0
  37. package/dist/tweaks/motion-HMCZK6HJ.js.map +6 -0
  38. package/dist/tweaks/plot-D3NQ6XNN.js +3 -0
  39. package/dist/tweaks/plot-D3NQ6XNN.js.map +6 -0
  40. package/dist/tweaks/point-XDXKMDXH.js +2 -0
  41. package/dist/tweaks/point-XDXKMDXH.js.map +6 -0
  42. package/dist/tweaks/presets-EUWNSCUW.js +2 -0
  43. package/dist/tweaks/presets-EUWNSCUW.js.map +6 -0
  44. package/dist/tweaks/shadow-AM7VSRNS.js +2 -0
  45. package/dist/tweaks/shadow-AM7VSRNS.js.map +6 -0
  46. package/dist/tweaks/shadow-root-RYUV3AGS.js +3 -0
  47. package/dist/tweaks/shadow-root-RYUV3AGS.js.map +6 -0
  48. package/dist/tweaks/sides-JWIURDA4.js +2 -0
  49. package/dist/tweaks/sides-JWIURDA4.js.map +6 -0
  50. package/dist/tweaks/spring-BF5GBTPM.js +2 -0
  51. package/dist/tweaks/spring-BF5GBTPM.js.map +6 -0
  52. package/dist/tweaks/tabs-PRVUUZXZ.js +2 -0
  53. package/dist/tweaks/tabs-PRVUUZXZ.js.map +6 -0
  54. package/dist/tweaks.css +1 -1
  55. package/dist/tweaks.js +7 -3
  56. package/dist/tweaks.js.map +6 -0
  57. package/dist/types/tweaks/easing.d.ts +8 -11
  58. package/dist/types/tweaks/enhance.d.ts +3 -2
  59. package/dist/types/tweaks/panel.d.ts +6 -4
  60. package/dist/types/tweaks/schema.d.ts +4 -8
  61. package/dist/types/tweaks/standalone.d.ts +3 -3
  62. package/dist/types/tweaks/types.d.ts +499 -116
  63. package/package.json +30 -5
  64. package/src/tweaks/auto.ts +16 -0
  65. package/src/tweaks/clip.ts +156 -0
  66. package/src/tweaks/controls/basic.ts +727 -0
  67. package/src/tweaks/controls/bezier.ts +204 -0
  68. package/src/tweaks/controls/color.ts +861 -0
  69. package/src/tweaks/controls/gradient.ts +419 -0
  70. package/src/tweaks/controls/image.ts +555 -0
  71. package/src/tweaks/controls/interval.ts +189 -0
  72. package/src/tweaks/controls/monitor.ts +211 -0
  73. package/src/tweaks/controls/motion.ts +316 -0
  74. package/src/tweaks/controls/plot.ts +440 -0
  75. package/src/tweaks/controls/point.ts +208 -0
  76. package/src/tweaks/controls/shadow.ts +156 -0
  77. package/src/tweaks/controls/sides.ts +196 -0
  78. package/src/tweaks/controls/spring.ts +308 -0
  79. package/src/tweaks/controls/tabs.ts +68 -0
  80. package/src/tweaks/core.ts +9 -0
  81. package/src/tweaks/easing.ts +118 -0
  82. package/src/tweaks/enhance.ts +35 -0
  83. package/src/tweaks/feedback.ts +218 -0
  84. package/src/tweaks/fold.ts +33 -0
  85. package/src/tweaks/heavy.ts +626 -0
  86. package/src/tweaks/icons.ts +26 -0
  87. package/src/tweaks/image-store.ts +189 -0
  88. package/src/tweaks/lazy.ts +63 -0
  89. package/src/tweaks/markup.ts +317 -0
  90. package/src/tweaks/panel.ts +1693 -0
  91. package/src/tweaks/presets.ts +85 -0
  92. package/src/tweaks/schema.ts +351 -0
  93. package/src/tweaks/shadow-root.ts +178 -0
  94. package/src/tweaks/shared.ts +1137 -0
  95. package/src/tweaks/single.ts +22 -0
  96. package/src/tweaks/standalone.ts +179 -0
  97. package/src/tweaks/types.ts +1027 -0
  98. package/src/tweaks/undo.ts +104 -0
  99. package/src/tweaks.css +965 -0
  100. package/src/wide-gamut.ts +658 -0
  101. package/dist/tweaks/bezier-2RABC6LD.js +0 -1
  102. package/dist/tweaks/chunk-4ATI34PB.js +0 -1
  103. package/dist/tweaks/chunk-7OSCMZ2J.js +0 -1
  104. package/dist/tweaks/chunk-W3JNIJ2F.js +0 -1
  105. package/dist/tweaks/clip-ECGCECEC.js +0 -1
  106. package/dist/tweaks/colour-2RE3FQ5E.js +0 -1
  107. package/dist/tweaks/fold-UGN7TXGX.js +0 -1
  108. package/dist/tweaks/gradient-DB6XTDHO.js +0 -1
  109. package/dist/tweaks/heavy-PKOMHB3C.js +0 -1
  110. package/dist/tweaks/image-7MCLBOZ3.js +0 -1
  111. package/dist/tweaks/interval-L2E4L3AZ.js +0 -1
  112. package/dist/tweaks/markup-ZJJ6CCWM.js +0 -1
  113. package/dist/tweaks/monitor-IEK742PG.js +0 -2
  114. package/dist/tweaks/motion-N5UNVR55.js +0 -1
  115. package/dist/tweaks/plot-VVTOY3RA.js +0 -2
  116. package/dist/tweaks/point-YMMHSLO7.js +0 -1
  117. package/dist/tweaks/shadow-IKYOV3VN.js +0 -1
  118. package/dist/tweaks/sides-FH227Z54.js +0 -1
  119. package/dist/tweaks/spring-3PKAFIH7.js +0 -1
  120. package/dist/tweaks/tabs-BKK5NIIY.js +0 -1
@@ -0,0 +1,22 @@
1
+ /* Single-file build entry. Statically imports every control so each self-registers
2
+ * into the shared registry on load; with the esbuild define TW_SPLIT=false, core's
3
+ * dynamic-import map is empty, so esbuild inlines the whole kit into one self-contained,
4
+ * synchronous file — a drop-in that needs no bundler. The code-split build uses core.ts
5
+ * directly (TW_SPLIT=true) and loads these controls on demand instead. */
6
+ import "./markup.js"; // registers enhance()'s work, so enhance() stays synchronous here
7
+ import "./heavy.js"; // registers the Number control
8
+ import "./controls/color.js";
9
+ import "./controls/gradient.js";
10
+ import "./controls/shadow.js";
11
+ import "./controls/sides.js";
12
+ import "./controls/interval.js";
13
+ import "./controls/tabs.js";
14
+ import "./controls/image.js";
15
+ import "./controls/monitor.js";
16
+ import "./controls/spring.js";
17
+ import "./controls/bezier.js";
18
+ import "./controls/motion.js";
19
+ import "./controls/point.js";
20
+ import "./controls/plot.js";
21
+
22
+ export * from "./core.js";
@@ -0,0 +1,179 @@
1
+ /* Standalone controls — the kit's controls without the panel: mountControl() builds one control
2
+ * into a host of your own, createColorPicker() hands out the color editor surface alone. */
3
+ import { el, getControl, onReady, setDisabled, valueChanged, isolate, using } from "./shared.js";
4
+ import { metaFor, VALUELESS } from "./schema.js";
5
+ import { ensureForMetas } from "./lazy.js";
6
+ import { createControl } from "./controls/basic.js";
7
+ import { addHintMarker } from "./feedback.js";
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";
20
+ import type { Meta } from "./schema.js";
21
+ import type { PickerBody, PickerOptions } from "./controls/color.js";
22
+
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.
27
+ const whenLoaded = <H>(metas: Array<Pick<Meta, "type">>, build: () => void, handle: H): Promise<H> => {
28
+ const pend = ensureForMetas(metas);
29
+ if (!pend) {
30
+ build();
31
+ return Promise.resolve(handle);
32
+ }
33
+ const ready = pend.then(build).then(() => handle);
34
+ ready.catch(() => {});
35
+ return ready;
36
+ };
37
+
38
+ /** One control from a schema value, into `host`; a folder or tabs set is tweaks()'s to build. */
39
+ export function mountControl<const V extends HeldValue>(
40
+ host: Element,
41
+ value: V & KnownType<V>,
42
+ opts?: MountOptions,
43
+ ): MountedControl;
44
+ export function mountControl(host: Element, value: SchemaValue, opts: MountOptions = {}): MountedControl {
45
+ const key = opts.key ?? "value";
46
+ const meta = metaFor(key, value);
47
+ if (!meta || meta.type === "folder" || meta.type === "tabs")
48
+ throw new TypeError(`[tweaks] mountControl: "${key}" is not a single-control schema value`);
49
+ if (opts.label != null) meta.label = String(opts.label); // the option wins over the derived label; "" = no label
50
+ const valued = !VALUELESS.has(meta.type); // display/action controls carry no value: set/get are inert
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;
59
+ // Gated the way the panel gates notify(): a same-value set() stays silent instead of echoing.
60
+ const emit = (v: unknown) => {
61
+ if (!valueChanged(last, v)) return;
62
+ last = v;
63
+ opts.onChange && opts.onChange(v, key);
64
+ };
65
+ const build = () => {
66
+ if (destroyed) return; // destroy() before the chunk landed — nothing to mount
67
+ ctrl = using(opts.strings, () => createControl(meta, valued ? emit : () => {}));
68
+ if (!ctrl) return; // a failed chunk degrades to an empty wrapper
69
+ if (meta.hint) addHintMarker(ctrl.el, meta.hint);
70
+ // Resolved once at mount: with no siblings for a predicate to read, `get` answers undefined.
71
+ const none: Get = () => undefined;
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 {}
80
+ root.append(ctrl.el);
81
+ if (!valued) return;
82
+ last = ctrl.get(); // the form the control opened on
83
+ // a set() from the lazy window applies and announces now
84
+ if (queued) {
85
+ ctrl.set(parked);
86
+ emit(ctrl.get());
87
+ }
88
+ };
89
+ const handle: MountedControl = {
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
+ },
101
+ get: () => (!valued ? undefined : ctrl ? ctrl.get() : queued ? parked : meta.value),
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
+ },
110
+ ready: null,
111
+ };
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(() => {});
115
+ return handle;
116
+ }
117
+
118
+ /** The color editor surface alone, for a host page that brings its own swatch. */
119
+ export function createColorPicker(opts: ColorPickerOptions = {}): ColorPicker {
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
+ };
133
+ const build = () => {
134
+ if (destroyed) return;
135
+ // registered by the color module beside its control
136
+ const make = getControl<PickerBody, PickerOptions>("colorpicker");
137
+ if (!make) return;
138
+ body = using(opts.strings, () => make({ value: opts.value, mode: opts.mode }, emit));
139
+ last = body.get();
140
+ root.append(body.el);
141
+ if (parkedMode) body.setMode(parkedMode);
142
+ if (queued) {
143
+ body.set(parked);
144
+ emit(body.get());
145
+ }
146
+ onReady(body.reflow); // next frame: the thumbs need a real box
147
+ };
148
+ const picker: ColorPicker = {
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
+ },
160
+ get: () => (body ? body.get() : queued ? parked : opts.value),
161
+ mode: () => (body ? body.mode() : parkedMode || opts.mode || "oklch"),
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
+ },
174
+ ready: null,
175
+ };
176
+ picker.ready = whenLoaded([{ type: "color" }], build, picker);
177
+ if (iso.dressed) (picker.ready = Promise.all([picker.ready, iso.dressed]).then(() => picker)).catch(() => {});
178
+ return picker;
179
+ }