@kitlangton/knobs 0.1.0 → 0.3.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 +303 -41
- package/dist/dev/{chunk-qtt698hp.js → chunk-7xgkerd2.js} +34 -11
- package/dist/dev/{chunk-ktsn42p7.js → chunk-jx1ktap3.js} +13762 -11794
- package/dist/dev/{chunk-kdewv0mt.js → chunk-pmkvb9ep.js} +1692 -207
- package/dist/dev/{chunk-e13znr7c.js → chunk-v8ssbcbk.js} +18 -7
- package/dist/dev/index.js +557 -130
- package/dist/index.js +589 -141
- package/dist/panel.js +21615 -17048
- package/dist/types/core/keys.d.ts +2 -0
- package/dist/types/core/random.d.ts +61 -1
- package/dist/types/core/remote.d.ts +5 -1
- package/dist/types/core/schema.d.ts +35 -6
- package/dist/types/core/store.d.ts +97 -8
- package/dist/types/core/unlock.d.ts +77 -0
- package/dist/types/core/variants.d.ts +10 -2
- package/dist/types/index.d.ts +4 -2
- package/dist/types/panel/attach.d.ts +2 -0
- package/dist/types/panel/crumbs.d.ts +19 -0
- package/dist/types/panel/editors.d.ts +20 -0
- package/dist/types/panel/feel.d.ts +103 -0
- package/dist/types/panel/flash.d.ts +13 -0
- package/dist/types/panel/give.d.ts +34 -1
- package/dist/types/panel/gpu/color.d.ts +4 -4
- package/dist/types/panel/gpu/renderer.d.ts +110 -6
- package/dist/types/panel/gpu/shader.wgsl.d.ts +1 -1
- package/dist/types/panel/haptics.d.ts +6 -2
- package/dist/types/panel/has.d.ts +0 -1
- package/dist/types/panel/index.d.ts +3 -1
- package/dist/types/panel/inspector.d.ts +33 -3
- package/dist/types/panel/lens.d.ts +113 -0
- package/dist/types/panel/motion.d.ts +2 -0
- package/dist/types/panel/optkeys.d.ts +7 -0
- package/dist/types/panel/page-hints.d.ts +2 -1
- package/dist/types/panel/prefs.d.ts +2 -2
- package/dist/types/panel/presence.d.ts +20 -0
- package/dist/types/panel/presets.d.ts +17 -5
- package/dist/types/panel/ramp-morph.d.ts +117 -0
- package/dist/types/panel/ramps.d.ts +1 -1
- package/dist/types/panel/reel.d.ts +43 -0
- package/dist/types/panel/scope.d.ts +48 -0
- package/dist/types/panel/slider.d.ts +22 -5
- package/dist/types/panel/sound.d.ts +137 -0
- package/dist/types/panel/styles.d.ts +1 -1
- package/dist/types/panel/tab-transition.d.ts +15 -0
- package/dist/types/panel/tabs.d.ts +1 -1
- package/dist/types/panel/toggle.d.ts +27 -0
- package/dist/types/panel/toolbar-grid.d.ts +6 -0
- package/dist/types/ui/activity-css.d.ts +1 -0
- package/dist/types/ui/activity-model.d.ts +122 -0
- package/dist/types/ui/activity.d.ts +67 -0
- package/dist/types/ui/follow.d.ts +17 -0
- package/dist/types/ui/index.d.ts +5 -1
- package/dist/types/ui/look.d.ts +9 -0
- package/dist/types/ui/picker-css.d.ts +1 -0
- package/dist/types/ui/picker-model.d.ts +53 -0
- package/dist/types/ui/picker.d.ts +67 -0
- package/dist/types/ui/react.d.ts +27 -0
- package/dist/types/ui/scrollbar.d.ts +12 -0
- package/dist/types/ui/solid.d.ts +23 -0
- package/dist/types/ui/split-model.d.ts +55 -0
- package/dist/types/ui/split.d.ts +22 -3
- package/dist/ui-react.js +3462 -690
- package/dist/ui-solid.js +3440 -689
- package/dist/ui.js +2963 -264
- package/package.json +1 -1
package/dist/dev/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
matchesCombo2,
|
|
16
16
|
comboParts2,
|
|
17
17
|
comboLabel2,
|
|
18
|
+
isTypingTarget,
|
|
18
19
|
sampleGradient2,
|
|
19
20
|
gradientCss2,
|
|
20
21
|
sampleCurve2,
|
|
@@ -46,6 +47,7 @@ import {
|
|
|
46
47
|
gradient2,
|
|
47
48
|
curve2,
|
|
48
49
|
toolbarShortcut2,
|
|
50
|
+
actionShortcut2,
|
|
49
51
|
toolbar2,
|
|
50
52
|
watch2,
|
|
51
53
|
sparkline2,
|
|
@@ -71,8 +73,141 @@ import {
|
|
|
71
73
|
browserStorage,
|
|
72
74
|
urlFlag2,
|
|
73
75
|
storageKey
|
|
74
|
-
} from "./chunk-
|
|
75
|
-
__chunks(import.meta.url,["
|
|
76
|
+
} from "./chunk-7xgkerd2.js";
|
|
77
|
+
__chunks(import.meta.url,["8qt6yygv","jx1ktap3","v8ssbcbk","7xgkerd2","pmkvb9ep"],[["./index.js",3],["./chunk-jx1ktap3.js",3,4],["./chunk-v8ssbcbk.js",3,4],["./chunk-7xgkerd2.js"],["./chunk-pmkvb9ep.js",3]],0);
|
|
78
|
+
// src/core/random.ts
|
|
79
|
+
var lattice = (min, max, step, r) => min + Math.floor(r * (Math.floor((max - min) / step + 0.000000001) + 1)) * step, between = (min, max, r) => min + (max - min) * r;
|
|
80
|
+
function pick(field, random) {
|
|
81
|
+
let r = () => Math.max(0, Math.min(1 - Number.EPSILON, random()));
|
|
82
|
+
switch (field.kind) {
|
|
83
|
+
case "knob":
|
|
84
|
+
return lattice(field.min, field.max, field.step, r());
|
|
85
|
+
case "choice":
|
|
86
|
+
return field.options[Math.floor(r() * field.options.length)];
|
|
87
|
+
case "toggle":
|
|
88
|
+
return r() >= 0.5;
|
|
89
|
+
case "spring":
|
|
90
|
+
return { duration: between(0.2, 0.9, r()), bounce: between(0, 0.45, r()) };
|
|
91
|
+
case "color": {
|
|
92
|
+
let l = between(0.5, 0.85, r()), h = between(0, 360, r());
|
|
93
|
+
return { l, c: between(0.25, 0.85, r()) * maxChroma(l, h), h };
|
|
94
|
+
}
|
|
95
|
+
case "point":
|
|
96
|
+
return {
|
|
97
|
+
x: lattice(field.min.x, field.max.x, field.step.x, r()),
|
|
98
|
+
y: lattice(field.min.y, field.max.y, field.step.y, r())
|
|
99
|
+
};
|
|
100
|
+
case "easing": {
|
|
101
|
+
let curves = Object.values(EASINGS2);
|
|
102
|
+
return curves[Math.floor(r() * curves.length)];
|
|
103
|
+
}
|
|
104
|
+
case "vec": {
|
|
105
|
+
let axis = () => lattice(field.min, field.max, field.step, r());
|
|
106
|
+
return field.axes === 3 ? { x: axis(), y: axis(), z: axis() } : { x: axis(), y: axis() };
|
|
107
|
+
}
|
|
108
|
+
case "range":
|
|
109
|
+
return [
|
|
110
|
+
lattice(field.min, field.max, field.step, r()),
|
|
111
|
+
lattice(field.min, field.max, field.step, r())
|
|
112
|
+
];
|
|
113
|
+
case "angle": {
|
|
114
|
+
let top = field.wrap ? field.max - field.step : field.max;
|
|
115
|
+
return lattice(field.min, Math.max(field.min, top), field.step, r());
|
|
116
|
+
}
|
|
117
|
+
case "seed":
|
|
118
|
+
return lattice(field.min, field.max, 1, r());
|
|
119
|
+
case "keybind":
|
|
120
|
+
return field.value;
|
|
121
|
+
case "gradient":
|
|
122
|
+
return randomStops(field.value.length, r);
|
|
123
|
+
case "curve":
|
|
124
|
+
return randomPoints(field.range, r);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var AROUND = {
|
|
128
|
+
spread: 0.35,
|
|
129
|
+
switch: 0.3,
|
|
130
|
+
hue: 20,
|
|
131
|
+
lightness: 0.06,
|
|
132
|
+
chroma: 0.15
|
|
133
|
+
};
|
|
134
|
+
function near(v, min, max, step, r, reach = max - min) {
|
|
135
|
+
let span = max - min;
|
|
136
|
+
if (!(span > 0))
|
|
137
|
+
return v;
|
|
138
|
+
let width = Math.min(span, reach * AROUND.spread), lo = Math.max(min, Math.min(max - width, v - width / 2)), top = Math.floor(span / step + 0.000000001), a = Math.max(0, Math.ceil((lo - min) / step - 0.000000001)), b = Math.min(top, Math.floor((lo + width - min) / step + 0.000000001)), n = b < a ? Math.round((v - min) / step) : a + Math.floor(r * (b - a + 1));
|
|
139
|
+
return Number((min + Math.max(0, Math.min(top, n)) * step).toPrecision(14));
|
|
140
|
+
}
|
|
141
|
+
var unit = (r) => r * 2 - 1;
|
|
142
|
+
function around(field, base, random) {
|
|
143
|
+
let r = () => Math.max(0, Math.min(1 - Number.EPSILON, random()));
|
|
144
|
+
switch (field.kind) {
|
|
145
|
+
case "knob":
|
|
146
|
+
return near(base, field.min, field.max, field.step, r());
|
|
147
|
+
case "choice": {
|
|
148
|
+
if (field.options.length < 2 || r() >= AROUND.switch)
|
|
149
|
+
return base;
|
|
150
|
+
let rest = field.options.filter((o) => o !== base);
|
|
151
|
+
return rest[Math.floor(r() * rest.length)];
|
|
152
|
+
}
|
|
153
|
+
case "toggle":
|
|
154
|
+
return r() < AROUND.switch ? !base : base;
|
|
155
|
+
case "spring": {
|
|
156
|
+
let s = base, d = SPRING2.duration, b = SPRING2.bounce;
|
|
157
|
+
return {
|
|
158
|
+
duration: near(s.duration, d.min, d.max, d.step, r(), 0.7),
|
|
159
|
+
bounce: near(s.bounce, b.min, b.max, b.step, r(), 0.45)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
case "color": {
|
|
163
|
+
let c = parseColor2(base) ?? { l: 0.7, c: 0.1, h: 0 }, max0 = maxChroma(c.l, c.h), rel = max0 > 0.0001 ? Math.min(1, Math.max(0, c.c / max0)) : 0.5, h = (c.h + unit(r()) * AROUND.hue + 360) % 360, l = Math.min(1, Math.max(0, c.l + unit(r()) * AROUND.lightness)), k = Math.min(1, Math.max(0, rel + unit(r()) * AROUND.chroma));
|
|
164
|
+
return { l, c: k * maxChroma(l, h), h };
|
|
165
|
+
}
|
|
166
|
+
case "point": {
|
|
167
|
+
let p = base;
|
|
168
|
+
return {
|
|
169
|
+
x: near(p.x, field.min.x, field.max.x, field.step.x, r()),
|
|
170
|
+
y: near(p.y, field.min.y, field.max.y, field.step.y, r())
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
case "easing":
|
|
174
|
+
return base.map((v, i) => {
|
|
175
|
+
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y;
|
|
176
|
+
return near(v, lo, hi, 0.001, r());
|
|
177
|
+
});
|
|
178
|
+
case "vec": {
|
|
179
|
+
let v = base, axis = (n) => near(n, field.min, field.max, field.step, r());
|
|
180
|
+
return field.axes === 3 ? { x: axis(v.x), y: axis(v.y), z: axis(v.z ?? 0) } : { x: axis(v.x), y: axis(v.y) };
|
|
181
|
+
}
|
|
182
|
+
case "range": {
|
|
183
|
+
let [a, b] = base;
|
|
184
|
+
return [
|
|
185
|
+
near(a, field.min, field.max, field.step, r()),
|
|
186
|
+
near(b, field.min, field.max, field.step, r())
|
|
187
|
+
];
|
|
188
|
+
}
|
|
189
|
+
case "angle": {
|
|
190
|
+
let v = base;
|
|
191
|
+
if (!field.wrap)
|
|
192
|
+
return near(v, field.min, field.max, field.step, r());
|
|
193
|
+
let span = field.max - field.min;
|
|
194
|
+
return v + unit(r()) * span * (AROUND.spread / 2);
|
|
195
|
+
}
|
|
196
|
+
case "gradient":
|
|
197
|
+
return mutateStops(base, r, [AROUND.hue / 2, AROUND.hue], [AROUND.lightness / 2, AROUND.lightness]);
|
|
198
|
+
case "curve":
|
|
199
|
+
return mutatePoints(base, field.range, r, [
|
|
200
|
+
AROUND.spread / 2,
|
|
201
|
+
AROUND.spread
|
|
202
|
+
]);
|
|
203
|
+
case "seed":
|
|
204
|
+
case "keybind":
|
|
205
|
+
return pick(field, random);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function randomValues(schema, random = Math.random) {
|
|
209
|
+
return normalize(schema, Object.fromEntries(Object.entries(schema).flatMap(([key, field]) => hasValue2(field) ? [[key, pick(field, random)]] : [])));
|
|
210
|
+
}
|
|
76
211
|
// src/core/code.ts
|
|
77
212
|
var literal = (value) => Array.isArray(value) ? `[${value.map(literal).join(", ")}]` : typeof value === "object" && value !== null ? `{ ${Object.entries(value).map(([k, v]) => `${k}: ${literal(v)}`).join(", ")} }` : JSON.stringify(value);
|
|
78
213
|
function formatCode(values, format = "ts") {
|
|
@@ -96,12 +231,12 @@ var MUTATE = {
|
|
|
96
231
|
chroma: 0.02,
|
|
97
232
|
lightness: [0.015, 0.045],
|
|
98
233
|
bezier: [0.03, 0.06]
|
|
99
|
-
},
|
|
234
|
+
}, between2 = (min, max, r) => min + (max - min) * r, signed = (random) => random() < 0.5 ? -1 : 1;
|
|
100
235
|
function nudge(v, min, max, step, random, reach = max - min) {
|
|
101
236
|
let span = max - min;
|
|
102
237
|
if (!(span > 0))
|
|
103
238
|
return v;
|
|
104
|
-
let sign = signed(random), by = reach *
|
|
239
|
+
let sign = signed(random), by = reach * between2(MUTATE.min, MUTATE.max, random()), next = v + sign * by;
|
|
105
240
|
if (next > max || next < min)
|
|
106
241
|
next = v - sign * by;
|
|
107
242
|
let top = Math.floor(span / step + 0.000000001), at = (n) => Number((min + n * step).toPrecision(14)), steps = Math.max(0, Math.min(top, Math.round((next - min) / step)));
|
|
@@ -130,12 +265,12 @@ function shift(field, value, random) {
|
|
|
130
265
|
};
|
|
131
266
|
}
|
|
132
267
|
case "color": {
|
|
133
|
-
let c = parseColor2(value) ?? { l: 0.7, c: 0.1, h: 0 }, max0 = maxChroma(c.l, c.h), rel0 = max0 > 0.0001 ? Math.min(1, Math.max(0, c.c / max0)) : 0.5, h = (c.h + signed(random) *
|
|
268
|
+
let c = parseColor2(value) ?? { l: 0.7, c: 0.1, h: 0 }, max0 = maxChroma(c.l, c.h), rel0 = max0 > 0.0001 ? Math.min(1, Math.max(0, c.c / max0)) : 0.5, h = (c.h + signed(random) * between2(MUTATE.hue[0], MUTATE.hue[1], random()) + 360) % 360, l = Math.min(1, Math.max(0, c.l + signed(random) * between2(MUTATE.lightness[0], MUTATE.lightness[1], random())));
|
|
134
269
|
return { l, c: nudge(rel0, 0, 1, 0.01, random) * maxChroma(l, h), h };
|
|
135
270
|
}
|
|
136
271
|
case "easing":
|
|
137
272
|
return value.map((v, i) => {
|
|
138
|
-
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y, next = v + signed(random) *
|
|
273
|
+
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y, next = v + signed(random) * between2(MUTATE.bezier[0], MUTATE.bezier[1], random());
|
|
139
274
|
return Math.min(hi, Math.max(lo, next));
|
|
140
275
|
});
|
|
141
276
|
case "choice": {
|
|
@@ -161,7 +296,7 @@ function shift(field, value, random) {
|
|
|
161
296
|
if (!field.wrap)
|
|
162
297
|
return nudge(v, field.min, field.max, field.step, random);
|
|
163
298
|
let span = field.max - field.min;
|
|
164
|
-
return v + signed(random) * span *
|
|
299
|
+
return v + signed(random) * span * between2(MUTATE.min, MUTATE.max, random());
|
|
165
300
|
}
|
|
166
301
|
case "seed":
|
|
167
302
|
return nudge(value, field.min, field.max, 1, random);
|
|
@@ -203,57 +338,141 @@ function mutateValues(schema, current, keys = valueKeys(schema), random = Math.r
|
|
|
203
338
|
return out;
|
|
204
339
|
}
|
|
205
340
|
|
|
206
|
-
// src/core/
|
|
207
|
-
var
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
x: lattice(field.min.x, field.max.x, field.step.x, r()),
|
|
226
|
-
y: lattice(field.min.y, field.max.y, field.step.y, r())
|
|
227
|
-
};
|
|
228
|
-
case "easing": {
|
|
229
|
-
let curves = Object.values(EASINGS2);
|
|
230
|
-
return curves[Math.floor(r() * curves.length)];
|
|
231
|
-
}
|
|
232
|
-
case "vec": {
|
|
233
|
-
let axis = () => lattice(field.min, field.max, field.step, r());
|
|
234
|
-
return field.axes === 3 ? { x: axis(), y: axis(), z: axis() } : { x: axis(), y: axis() };
|
|
235
|
-
}
|
|
236
|
-
case "range":
|
|
237
|
-
return [
|
|
238
|
-
lattice(field.min, field.max, field.step, r()),
|
|
239
|
-
lattice(field.min, field.max, field.step, r())
|
|
240
|
-
];
|
|
241
|
-
case "angle": {
|
|
242
|
-
let top = field.wrap ? field.max - field.step : field.max;
|
|
243
|
-
return lattice(field.min, Math.max(field.min, top), field.step, r());
|
|
244
|
-
}
|
|
245
|
-
case "seed":
|
|
246
|
-
return lattice(field.min, field.max, 1, r());
|
|
247
|
-
case "keybind":
|
|
248
|
-
return field.value;
|
|
249
|
-
case "gradient":
|
|
250
|
-
return randomStops(field.value.length, r);
|
|
251
|
-
case "curve":
|
|
252
|
-
return randomPoints(field.range, r);
|
|
253
|
-
}
|
|
341
|
+
// src/core/unlock.ts
|
|
342
|
+
var KONAMI = Object.freeze([
|
|
343
|
+
"ArrowUp",
|
|
344
|
+
"ArrowUp",
|
|
345
|
+
"ArrowDown",
|
|
346
|
+
"ArrowDown",
|
|
347
|
+
"ArrowLeft",
|
|
348
|
+
"ArrowRight",
|
|
349
|
+
"ArrowLeft",
|
|
350
|
+
"ArrowRight",
|
|
351
|
+
"b",
|
|
352
|
+
"a"
|
|
353
|
+
]), GATE = Symbol.for("knobs.unlock.v1"), gate = () => {
|
|
354
|
+
let holder = globalThis;
|
|
355
|
+
return holder[GATE] ??= { unlocked: !1, listeners: /* @__PURE__ */ new Set };
|
|
356
|
+
}, isUnlocked = () => globalThis[GATE]?.unlocked ?? !1;
|
|
357
|
+
function onUnlock(listener) {
|
|
358
|
+
let listeners = gate().listeners;
|
|
359
|
+
return listeners.add(listener), () => void listeners.delete(listener);
|
|
254
360
|
}
|
|
255
|
-
|
|
256
|
-
|
|
361
|
+
var UNLOCK_KEY = "knobs:unlocked";
|
|
362
|
+
function sequenceKeys(sequence) {
|
|
363
|
+
return typeof sequence === "string" ? [...sequence] : [...sequence];
|
|
364
|
+
}
|
|
365
|
+
var fold = (key) => key.length === 1 ? key.toLowerCase() : key;
|
|
366
|
+
function sequenceMatcher(sequence, gap = 1500) {
|
|
367
|
+
let want = sequenceKeys(sequence).map(fold), typed = [], last = -1 / 0;
|
|
368
|
+
return (key, at) => {
|
|
369
|
+
if (!want.length)
|
|
370
|
+
return !1;
|
|
371
|
+
if (at - last > gap)
|
|
372
|
+
typed = [];
|
|
373
|
+
if (last = at, typed.push(fold(key)), typed.length > want.length)
|
|
374
|
+
typed.shift();
|
|
375
|
+
if (typed.length === want.length && typed.every((k, i) => k === want[i]))
|
|
376
|
+
return typed = [], !0;
|
|
377
|
+
return !1;
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function queryUnlock(search, name) {
|
|
381
|
+
let params = new URLSearchParams(search);
|
|
382
|
+
if (!params.has(name))
|
|
383
|
+
return;
|
|
384
|
+
return !["off", "0", "false", "lock", "no"].includes((params.get(name) ?? "").toLowerCase());
|
|
385
|
+
}
|
|
386
|
+
function resolveUnlock(input) {
|
|
387
|
+
let unlocked = input.query ?? (input.persist && input.stored);
|
|
388
|
+
return { unlocked, remember: input.persist && input.query !== void 0 ? unlocked : void 0 };
|
|
389
|
+
}
|
|
390
|
+
function inCorner(x, y, width, height, corner, size = 48) {
|
|
391
|
+
let left = corner.endsWith("left") ? x <= size : x >= width - size, top = corner.startsWith("top") ? y <= size : y >= height - size;
|
|
392
|
+
return left && top;
|
|
393
|
+
}
|
|
394
|
+
function tapCounter(count = 3, within = 500) {
|
|
395
|
+
let taps = 0, last = -1 / 0;
|
|
396
|
+
return (at) => {
|
|
397
|
+
if (taps = at - last <= within ? taps + 1 : 1, last = at, taps < count)
|
|
398
|
+
return !1;
|
|
399
|
+
return taps = 0, !0;
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
var readStored = () => {
|
|
403
|
+
try {
|
|
404
|
+
return globalThis.localStorage?.getItem(UNLOCK_KEY) === "1";
|
|
405
|
+
} catch {
|
|
406
|
+
return !1;
|
|
407
|
+
}
|
|
408
|
+
}, writeStored = (on) => {
|
|
409
|
+
try {
|
|
410
|
+
if (on)
|
|
411
|
+
globalThis.localStorage?.setItem(UNLOCK_KEY, "1");
|
|
412
|
+
else
|
|
413
|
+
globalThis.localStorage?.removeItem(UNLOCK_KEY);
|
|
414
|
+
} catch {}
|
|
415
|
+
};
|
|
416
|
+
function unlock(options) {
|
|
417
|
+
let g = gate();
|
|
418
|
+
g.panel = options.panel;
|
|
419
|
+
let persist = options.persist !== !1, query = options.query === void 0 ? "knobs" : options.query, sequence = options.sequence === void 0 ? "knobs" : options.sequence, corner = options.corner === void 0 ? "top-right" : options.corner, win = typeof window > "u" ? void 0 : window, announce = (text) => {
|
|
420
|
+
(g.module ? Promise.resolve(g.module) : g.panel?.())?.then((m) => {
|
|
421
|
+
if (g.module = m, g.unlocked === (text === "knobs unlocked"))
|
|
422
|
+
m.status?.(text);
|
|
423
|
+
}).catch(() => {});
|
|
424
|
+
}, set = (on, say) => {
|
|
425
|
+
if (persist)
|
|
426
|
+
writeStored(on);
|
|
427
|
+
if (g.unlocked === on)
|
|
428
|
+
return;
|
|
429
|
+
g.unlocked = on;
|
|
430
|
+
for (let listener of [...g.listeners])
|
|
431
|
+
listener();
|
|
432
|
+
if (say)
|
|
433
|
+
announce(on ? "knobs unlocked" : "knobs locked");
|
|
434
|
+
}, start = resolveUnlock({
|
|
435
|
+
query: query && win ? queryUnlock(win.location.search, query) : void 0,
|
|
436
|
+
stored: persist && readStored(),
|
|
437
|
+
persist
|
|
438
|
+
});
|
|
439
|
+
if (start.remember !== void 0)
|
|
440
|
+
writeStored(start.remember);
|
|
441
|
+
set(start.unlocked || g.unlocked, !1);
|
|
442
|
+
let offs = [];
|
|
443
|
+
if (win && sequence !== !1 && sequenceKeys(sequence).length) {
|
|
444
|
+
let typed = sequenceMatcher(sequence), onKey = (event) => {
|
|
445
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.isComposing || event.repeat)
|
|
446
|
+
return;
|
|
447
|
+
if (event.key === "Shift" || event.key === "CapsLock" || isTypingTarget(event.target))
|
|
448
|
+
return;
|
|
449
|
+
if (typed(event.key, event.timeStamp || performance.now()))
|
|
450
|
+
set(!g.unlocked, !0);
|
|
451
|
+
};
|
|
452
|
+
win.addEventListener("keydown", onKey, !0), offs.push(() => win.removeEventListener("keydown", onKey, !0));
|
|
453
|
+
}
|
|
454
|
+
if (win && corner) {
|
|
455
|
+
let tapped = tapCounter(), onTap = (event) => {
|
|
456
|
+
if (!event.isPrimary)
|
|
457
|
+
return;
|
|
458
|
+
if (!inCorner(event.clientX, event.clientY, win.innerWidth, win.innerHeight, corner))
|
|
459
|
+
return void (tapped = tapCounter());
|
|
460
|
+
if (tapped(event.timeStamp || performance.now()))
|
|
461
|
+
set(!g.unlocked, !0);
|
|
462
|
+
};
|
|
463
|
+
win.addEventListener("pointerdown", onTap, { capture: !0, passive: !0 }), offs.push(() => win.removeEventListener("pointerdown", onTap, !0));
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
get unlocked() {
|
|
467
|
+
return g.unlocked;
|
|
468
|
+
},
|
|
469
|
+
unlock: () => set(!0, !0),
|
|
470
|
+
lock: () => set(!1, !0),
|
|
471
|
+
dispose() {
|
|
472
|
+
for (let off of offs.splice(0))
|
|
473
|
+
off();
|
|
474
|
+
}
|
|
475
|
+
};
|
|
257
476
|
}
|
|
258
477
|
|
|
259
478
|
// src/core/variants.ts
|
|
@@ -312,12 +531,28 @@ function createVariants(schema, id, key, storage, get, set, notify, enabled) {
|
|
|
312
531
|
});
|
|
313
532
|
return persist([...list, variant]), variant;
|
|
314
533
|
},
|
|
315
|
-
load(id) {
|
|
534
|
+
load(id, options) {
|
|
316
535
|
read();
|
|
317
536
|
let variant = list.find((v) => v.id === id);
|
|
318
537
|
if (!variant)
|
|
319
538
|
throw Error(`Unknown variant: ${id}`);
|
|
320
|
-
set(variant.values);
|
|
539
|
+
set(variant.values, id, Boolean(options?.coalesce));
|
|
540
|
+
},
|
|
541
|
+
rename(id, name) {
|
|
542
|
+
if (read(), name.length > 100)
|
|
543
|
+
throw Error("Variant names must be at most 100 characters.");
|
|
544
|
+
let at = list.findIndex((v) => v.id === id);
|
|
545
|
+
if (at < 0)
|
|
546
|
+
throw Error(`Unknown variant: ${id}`);
|
|
547
|
+
let was = list[at], trimmed = name.trim();
|
|
548
|
+
if ((was.name ?? "") === trimmed)
|
|
549
|
+
return;
|
|
550
|
+
let next = [...list];
|
|
551
|
+
next[at] = Object.freeze({
|
|
552
|
+
id: was.id,
|
|
553
|
+
...trimmed ? { name: trimmed } : {},
|
|
554
|
+
values: was.values
|
|
555
|
+
}), persist(next);
|
|
321
556
|
},
|
|
322
557
|
remove(id) {
|
|
323
558
|
read(), persist(list.filter((v) => v.id !== id));
|
|
@@ -354,10 +589,10 @@ function sameField(a, b) {
|
|
|
354
589
|
function defineControls(id, input, options = {}) {
|
|
355
590
|
if (!id.trim())
|
|
356
591
|
throw Error("Controls need a stable, nonempty id.");
|
|
357
|
-
let schema = Object.freeze({ ...input }), locked = normalize(schema, {}), actions = Object.freeze([...options.actions ?? []]), theme = options.theme ?? "dark", density = options.density ?? "default", renderer = options.renderer ?? "auto", enabled = () => typeof options.enabled === "function" ? options.enabled() : options.enabled ?? (Boolean(options.ship) || typeof location < "u" && ["localhost", "127.0.0.1", "[::1]"].includes(location.hostname)), storage = () => options.storage === void 0 ? browserStorage() : options.storage, persistMode = options.persist ?? "all", valueStorage = () => persistMode === "all" ? storage() : null, variantStorage = () => persistMode === "none" ? null : storage(), draw = options.random ?? Math.random, hostHistory = options.history, unsubscribeHistory, listeners = /* @__PURE__ */ new Set, refreshes = 0, notify = () => {
|
|
592
|
+
let schema = Object.freeze({ ...input }), locked = normalize(schema, {}), actions = Object.freeze([...options.actions ?? []]), theme = options.theme ?? "dark", density = options.density ?? "default", renderer = options.renderer ?? "auto", enabled = () => typeof options.enabled === "function" ? options.enabled() : options.enabled ?? (Boolean(options.ship) || isUnlocked() || typeof location < "u" && ["localhost", "127.0.0.1", "[::1]"].includes(location.hostname)), storage = () => options.storage === void 0 ? browserStorage() : options.storage, persistMode = options.persist ?? "all", valueStorage = () => persistMode === "all" ? storage() : null, variantStorage = () => persistMode === "none" ? null : storage(), draw = options.random ?? Math.random, hostHistory = options.history, unsubscribeHistory, unsubscribeUnlock, listeners = /* @__PURE__ */ new Set, refreshes = 0, notify = () => {
|
|
358
593
|
for (let cb of [...listeners])
|
|
359
594
|
cb();
|
|
360
|
-
}, mixed = /* @__PURE__ */ new Set, current = locked, read = !1, error = null, locks = /* @__PURE__ */ new Set, comparing = null, landing = !1, echo = Math.max(0, options.echo ?? 0), grabbed = /* @__PURE__ */ new Set, changedAt = /* @__PURE__ */ new Map, sent = /* @__PURE__ */ new Map, pending = /* @__PURE__ */ new Map, echoTimer, now = () => typeof performance < "u" ? performance.now() : Date.now(), isHeld = (key) => grabbed.has(key) || echo > 0 && now() - (changedAt.get(key) ?? -1 / 0) < echo, past = [], future = [], HISTORY = 100, stateKey = storageKey(id, "state"), buildPresets = () => Object.freeze(Object.fromEntries([
|
|
595
|
+
}, mixed = /* @__PURE__ */ new Set, current = locked, read = !1, error = null, locks = /* @__PURE__ */ new Set, bindings = /* @__PURE__ */ new Map, comparing = null, landing = !1, echo = Math.max(0, options.echo ?? 0), grabbed = /* @__PURE__ */ new Set, changedAt = /* @__PURE__ */ new Map, sent = /* @__PURE__ */ new Map, pending = /* @__PURE__ */ new Map, echoTimer, now = () => typeof performance < "u" ? performance.now() : Date.now(), isHeld = (key) => grabbed.has(key) || echo > 0 && now() - (changedAt.get(key) ?? -1 / 0) < echo, NO_BASE = Object.freeze({ preset: null, groups: Object.freeze({}) }), base = NO_BASE, past = [], future = [], HISTORY = 100, stateKey = storageKey(id, "state"), buildPresets = () => Object.freeze(Object.fromEntries([
|
|
361
596
|
["default", locked],
|
|
362
597
|
...Object.entries(options.presets ?? {}).map(([id, patch]) => {
|
|
363
598
|
if (id === "default" || id === "custom")
|
|
@@ -397,6 +632,9 @@ function defineControls(id, input, options = {}) {
|
|
|
397
632
|
if (data?.version === 1) {
|
|
398
633
|
if (current = normalize(schema, data.values), Array.isArray(data.locks))
|
|
399
634
|
locks = new Set(data.locks.filter((k) => typeof k === "string" && Object.hasOwn(schema, k)));
|
|
635
|
+
if (data.bindings && typeof data.bindings === "object")
|
|
636
|
+
bindings = new Map(Object.entries(data.bindings).flatMap(([id, combo]) => typeof combo === "string" && bindable(id) ? [[id, normalizeCombo2(combo)]] : []));
|
|
637
|
+
base = readBase(data.base);
|
|
400
638
|
}
|
|
401
639
|
}
|
|
402
640
|
} catch (cause) {
|
|
@@ -415,7 +653,9 @@ function defineControls(id, input, options = {}) {
|
|
|
415
653
|
valueStorage()?.setItem(stateKey, JSON.stringify({
|
|
416
654
|
version: 1,
|
|
417
655
|
values: current,
|
|
418
|
-
...locks.size ? { locks: [...locks] } : {}
|
|
656
|
+
...locks.size ? { locks: [...locks] } : {},
|
|
657
|
+
...bindings.size ? { bindings: Object.fromEntries(bindings) } : {},
|
|
658
|
+
...base !== NO_BASE ? { base } : {}
|
|
419
659
|
})), error = null;
|
|
420
660
|
} catch (cause) {
|
|
421
661
|
error = String(cause);
|
|
@@ -424,6 +664,74 @@ function defineControls(id, input, options = {}) {
|
|
|
424
664
|
function commit(next) {
|
|
425
665
|
current = next, persist(), notify();
|
|
426
666
|
}
|
|
667
|
+
let makeBase = (preset, groups) => preset === null && Object.keys(groups).length === 0 ? NO_BASE : Object.freeze({ preset, groups: Object.freeze({ ...groups }) }), sameBase = (a, b) => a === b || a.preset?.kind === b.preset?.kind && a.preset?.id === b.preset?.id && Object.keys(a.groups).length === Object.keys(b.groups).length && Object.entries(a.groups).every(([g, i]) => b.groups[g] === i);
|
|
668
|
+
function validBase(b) {
|
|
669
|
+
let preset = b.preset?.kind === "preset" && !(b.preset.id !== "default" && Object.hasOwn(presets, b.preset.id)) ? null : b.preset, groups = Object.fromEntries(Object.entries(b.groups).filter(([g, i]) => groupPresets[g]?.[i] !== void 0)), next = makeBase(preset, groups);
|
|
670
|
+
return sameBase(next, b) ? b : next;
|
|
671
|
+
}
|
|
672
|
+
function readBase(raw) {
|
|
673
|
+
if (!raw || typeof raw !== "object")
|
|
674
|
+
return NO_BASE;
|
|
675
|
+
let { preset, groups } = raw, ref = preset && typeof preset === "object" && (preset.kind === "preset" || preset.kind === "variant") && typeof preset.id === "string" ? Object.freeze({ kind: preset.kind, id: preset.id }) : null, byGroup = groups && typeof groups === "object" ? Object.fromEntries(Object.entries(groups).filter((e) => Number.isInteger(e[1]))) : {};
|
|
676
|
+
return validBase(makeBase(ref, byGroup));
|
|
677
|
+
}
|
|
678
|
+
function activeBase() {
|
|
679
|
+
load();
|
|
680
|
+
let ref = base.preset;
|
|
681
|
+
if (ref?.kind === "variant" && !variants.list().some((v) => v.id === ref.id))
|
|
682
|
+
base = makeBase(null, base.groups);
|
|
683
|
+
return base;
|
|
684
|
+
}
|
|
685
|
+
let hasBase = () => activeBase() !== NO_BASE, baseCache;
|
|
686
|
+
function baseValues() {
|
|
687
|
+
if (!enabled())
|
|
688
|
+
return locked;
|
|
689
|
+
let b = activeBase();
|
|
690
|
+
if (b === NO_BASE)
|
|
691
|
+
return locked;
|
|
692
|
+
let list = b.preset?.kind === "variant" ? variants.list() : null, c = baseCache;
|
|
693
|
+
if (c && c.base === b && c.schema === schema && c.presets === presets && c.groupPresets === groupPresets && c.variants === list)
|
|
694
|
+
return c.values;
|
|
695
|
+
let out = locked, ref = b.preset;
|
|
696
|
+
if (ref?.kind === "preset" && Object.hasOwn(presets, ref.id))
|
|
697
|
+
out = presets[ref.id];
|
|
698
|
+
else if (ref?.kind === "variant") {
|
|
699
|
+
let found = list?.find((v) => v.id === ref.id);
|
|
700
|
+
if (found)
|
|
701
|
+
out = normalize(schema, found.values);
|
|
702
|
+
}
|
|
703
|
+
let groups = Object.entries(b.groups);
|
|
704
|
+
if (groups.length) {
|
|
705
|
+
out = { ...out };
|
|
706
|
+
for (let [g, i] of groups)
|
|
707
|
+
Object.assign(out, groupPresets[g]?.[i]?.values);
|
|
708
|
+
}
|
|
709
|
+
let values = Object.freeze(out);
|
|
710
|
+
return baseCache = { base: b, schema, presets, groupPresets, variants: list, values }, values;
|
|
711
|
+
}
|
|
712
|
+
let covered = (key) => {
|
|
713
|
+
let b = activeBase();
|
|
714
|
+
if (b.preset)
|
|
715
|
+
return !0;
|
|
716
|
+
let group = schema[key]?.group;
|
|
717
|
+
return group !== void 0 && Object.hasOwn(b.groups, group);
|
|
718
|
+
};
|
|
719
|
+
function declaredShortcut(id) {
|
|
720
|
+
let slash = id.indexOf("/"), key = slash < 0 ? id : id.slice(0, slash), field = Object.hasOwn(schema, key) ? schema[key] : void 0;
|
|
721
|
+
if (field?.kind === "action" && slash < 0)
|
|
722
|
+
return { found: !0, ...field.shortcut ? { combo: field.shortcut } : {} };
|
|
723
|
+
if (field?.kind === "toolbar" && slash >= 0) {
|
|
724
|
+
let item = field.items.find((i) => (i.id ?? i.label) === id.slice(slash + 1));
|
|
725
|
+
if (!item)
|
|
726
|
+
return { found: !1 };
|
|
727
|
+
let key = toolbarShortcut2(item)?.key;
|
|
728
|
+
return { found: !0, ...key ? { combo: normalizeCombo2(key) } : {} };
|
|
729
|
+
}
|
|
730
|
+
return { found: !1 };
|
|
731
|
+
}
|
|
732
|
+
function bindable(id) {
|
|
733
|
+
return declaredShortcut(id).found;
|
|
734
|
+
}
|
|
427
735
|
let fieldKeys = () => valueKeys(schema), valueField = (k) => {
|
|
428
736
|
let field = Object.hasOwn(schema, k) ? schema[k] : void 0;
|
|
429
737
|
return field && hasValue2(field) ? field : void 0;
|
|
@@ -486,10 +794,13 @@ function defineControls(id, input, options = {}) {
|
|
|
486
794
|
pending.delete(k);
|
|
487
795
|
};
|
|
488
796
|
function set(patch, setOpts) {
|
|
797
|
+
write(patch, setOpts);
|
|
798
|
+
}
|
|
799
|
+
function write(patch, setOpts, nextBase) {
|
|
489
800
|
if (!enabled())
|
|
490
801
|
return;
|
|
491
802
|
release();
|
|
492
|
-
let previous = load(), forced = mixed.size ? Object.keys(patch).filter((k) => mixed.has(k) && valueField(k)) : [];
|
|
803
|
+
let previous = load(), was = activeBase(), moves = nextBase !== void 0 && !sameBase(nextBase, was), forced = mixed.size ? Object.keys(patch).filter((k) => mixed.has(k) && valueField(k)) : [];
|
|
493
804
|
for (let k of forced)
|
|
494
805
|
mixed.delete(k);
|
|
495
806
|
let applied = applyPatch(previous, previous, patch) ?? {
|
|
@@ -499,9 +810,10 @@ function defineControls(id, input, options = {}) {
|
|
|
499
810
|
for (let k of forced)
|
|
500
811
|
if (!(k in diff))
|
|
501
812
|
diff[k] = next[k];
|
|
502
|
-
|
|
813
|
+
let changed = Object.keys(diff).length > 0;
|
|
814
|
+
if (!changed && !moves)
|
|
503
815
|
return;
|
|
504
|
-
if (next === previous) {
|
|
816
|
+
if (next === previous && !moves) {
|
|
505
817
|
notify(), options.onChange?.(diff, next, {
|
|
506
818
|
source: setOpts?.source ?? "local",
|
|
507
819
|
...setOpts?.key ? { key: setOpts.key } : {}
|
|
@@ -509,16 +821,27 @@ function defineControls(id, input, options = {}) {
|
|
|
509
821
|
return;
|
|
510
822
|
}
|
|
511
823
|
if (!setOpts?.coalesce || past.length === 0) {
|
|
512
|
-
if (past.push(previous), past.length > HISTORY)
|
|
824
|
+
if (past.push({ values: previous, base: was }), past.length > HISTORY)
|
|
513
825
|
past.shift();
|
|
514
826
|
}
|
|
515
|
-
future.length = 0,
|
|
827
|
+
if (future.length = 0, moves)
|
|
828
|
+
base = nextBase;
|
|
829
|
+
if (markChanged(diff), commit(next), !changed)
|
|
830
|
+
return;
|
|
831
|
+
options.onChange?.(diff, next, {
|
|
516
832
|
source: setOpts?.source ?? "local",
|
|
517
833
|
...setOpts?.coalesce ? { coalesce: !0 } : {},
|
|
518
834
|
...setOpts?.key ? { key: setOpts.key } : {},
|
|
519
|
-
...setOpts?.group ? { group: setOpts.group } : {}
|
|
835
|
+
...setOpts?.group ? { group: setOpts.group } : {},
|
|
836
|
+
...setOpts?.base ? { base: !0 } : {}
|
|
520
837
|
});
|
|
521
838
|
}
|
|
839
|
+
function step(to, source) {
|
|
840
|
+
let before = load(), left = { values: before, base: activeBase() }, diff = changes(before, to.values);
|
|
841
|
+
if (base = validBase(to.base), markChanged(diff), commit(to.values), Object.keys(diff).length)
|
|
842
|
+
options.onChange?.(diff, to.values, { source });
|
|
843
|
+
return left;
|
|
844
|
+
}
|
|
522
845
|
function place(values, replace, land) {
|
|
523
846
|
let previous = load(), applied = applyPatch(replace ? locked : previous, previous, values);
|
|
524
847
|
if (!applied)
|
|
@@ -626,7 +949,7 @@ function defineControls(id, input, options = {}) {
|
|
|
626
949
|
schema = Object.freeze({ ...next });
|
|
627
950
|
if (changed) {
|
|
628
951
|
let previous = load();
|
|
629
|
-
schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets();
|
|
952
|
+
schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets(), base = validBase(base);
|
|
630
953
|
for (let k of [...locks])
|
|
631
954
|
if (!valueField(k))
|
|
632
955
|
locks.delete(k);
|
|
@@ -661,7 +984,60 @@ function defineControls(id, input, options = {}) {
|
|
|
661
984
|
listen(cb) {
|
|
662
985
|
return readoutListeners.add(cb), () => readoutListeners.delete(cb);
|
|
663
986
|
}
|
|
664
|
-
},
|
|
987
|
+
}, variants = createVariants(() => schema, id, storageKey(id, "variants"), variantStorage, get, (v, variant, coalesce) => write(v, { source: "variant", coalesce }, makeBase(Object.freeze({ kind: "variant", id: variant }), {})), notify, enabled), resettable = (keys) => (keys ?? fieldKeys()).filter((k) => valueField(k) && !blocked(k));
|
|
988
|
+
function offBase(keys) {
|
|
989
|
+
if (!hasBase())
|
|
990
|
+
return !1;
|
|
991
|
+
let cur = load(), b = baseValues();
|
|
992
|
+
return keys.some((k) => !same(cur[k], b[k]));
|
|
993
|
+
}
|
|
994
|
+
function toBase(keys, meta) {
|
|
995
|
+
let b = baseValues(), patch = Object.fromEntries(keys.map((k) => [k, b[k]]));
|
|
996
|
+
write(patch, { source: "reset", base: !0, ...meta });
|
|
997
|
+
}
|
|
998
|
+
function toDefaults(keys, nextBase) {
|
|
999
|
+
let patch = {};
|
|
1000
|
+
for (let k of keys)
|
|
1001
|
+
patch[k] = locked[k];
|
|
1002
|
+
write(patch, { source: "reset" }, nextBase);
|
|
1003
|
+
let resetKeys = options[RESET_KEYS];
|
|
1004
|
+
if (resetKeys)
|
|
1005
|
+
resetKeys(Object.keys(patch));
|
|
1006
|
+
else
|
|
1007
|
+
for (let key of Object.keys(patch))
|
|
1008
|
+
options.onReset?.({ key });
|
|
1009
|
+
}
|
|
1010
|
+
function live(load, make, unmake) {
|
|
1011
|
+
let disposed = !1, loading = !1, handle, sync = () => {
|
|
1012
|
+
if (disposed)
|
|
1013
|
+
return;
|
|
1014
|
+
if (!enabled()) {
|
|
1015
|
+
if (handle !== void 0)
|
|
1016
|
+
unmake(handle);
|
|
1017
|
+
handle = void 0;
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
if (handle !== void 0 || loading)
|
|
1021
|
+
return;
|
|
1022
|
+
let pending = load();
|
|
1023
|
+
if (!pending)
|
|
1024
|
+
return;
|
|
1025
|
+
loading = !0, pending.then((module) => {
|
|
1026
|
+
if (loading = !1, !disposed && enabled() && handle === void 0)
|
|
1027
|
+
handle = make(module);
|
|
1028
|
+
}).catch((cause) => {
|
|
1029
|
+
loading = !1, error = String(cause), notify();
|
|
1030
|
+
});
|
|
1031
|
+
};
|
|
1032
|
+
sync();
|
|
1033
|
+
let off = onUnlock(sync);
|
|
1034
|
+
return () => {
|
|
1035
|
+
if (disposed = !0, off(), handle !== void 0)
|
|
1036
|
+
unmake(handle);
|
|
1037
|
+
handle = void 0;
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
let controls = {
|
|
665
1041
|
id,
|
|
666
1042
|
get schema() {
|
|
667
1043
|
return schema;
|
|
@@ -680,9 +1056,10 @@ function defineControls(id, input, options = {}) {
|
|
|
680
1056
|
marks: options.marks !== !1,
|
|
681
1057
|
chip: Object.freeze({
|
|
682
1058
|
...options.chip,
|
|
683
|
-
reveal: options.chip?.reveal ?? (devBuild() ? "hover" : "shortcut"),
|
|
1059
|
+
reveal: options.chip?.reveal ?? (devBuild() || !options.ship ? "hover" : "shortcut"),
|
|
684
1060
|
shortcut: options.chip?.shortcut ?? "Alt+Shift+D"
|
|
685
1061
|
}),
|
|
1062
|
+
toggleKey: options.toggleKey ?? (options.ship ? !1 : "`"),
|
|
686
1063
|
groupPresetDisplay: options.groupPresetDisplay ?? "auto",
|
|
687
1064
|
groupLabel: (group) => options.groupLabels?.[group] ?? fieldLabels().group.get(group),
|
|
688
1065
|
sectionLabel: (section) => options.sectionLabels?.[section] ?? fieldLabels().section.get(section),
|
|
@@ -763,8 +1140,7 @@ function defineControls(id, input, options = {}) {
|
|
|
763
1140
|
let previous = past.pop();
|
|
764
1141
|
if (!previous)
|
|
765
1142
|
return;
|
|
766
|
-
|
|
767
|
-
future.push(before), markChanged(diff), commit(previous), options.onChange?.(diff, previous, { source: "undo" });
|
|
1143
|
+
future.push(step(previous, "undo"));
|
|
768
1144
|
},
|
|
769
1145
|
redo() {
|
|
770
1146
|
if (release(), hostHistory)
|
|
@@ -772,37 +1148,30 @@ function defineControls(id, input, options = {}) {
|
|
|
772
1148
|
let next = future.pop();
|
|
773
1149
|
if (!next)
|
|
774
1150
|
return;
|
|
775
|
-
|
|
776
|
-
past.push(before), markChanged(diff), commit(next), options.onChange?.(diff, next, { source: "redo" });
|
|
1151
|
+
past.push(step(next, "redo"));
|
|
777
1152
|
},
|
|
778
1153
|
getServerSnapshot: () => locked,
|
|
779
1154
|
subscribe(cb) {
|
|
780
1155
|
if (listeners.add(cb), hostHistory?.subscribe && !unsubscribeHistory)
|
|
781
1156
|
unsubscribeHistory = hostHistory.subscribe(notify);
|
|
782
|
-
return () => {
|
|
783
|
-
if (listeners.delete(cb),
|
|
784
|
-
|
|
1157
|
+
return unsubscribeUnlock ??= onUnlock(notify), () => {
|
|
1158
|
+
if (listeners.delete(cb), listeners.size)
|
|
1159
|
+
return;
|
|
1160
|
+
unsubscribeHistory?.(), unsubscribeHistory = void 0, unsubscribeUnlock?.(), unsubscribeUnlock = void 0;
|
|
785
1161
|
};
|
|
786
1162
|
},
|
|
787
1163
|
reset(keys) {
|
|
788
1164
|
if (!enabled())
|
|
789
1165
|
return;
|
|
1166
|
+
let open = resettable(keys);
|
|
1167
|
+
if (offBase(open))
|
|
1168
|
+
return toBase(open, {});
|
|
790
1169
|
let skipped = fieldKeys().some(blocked);
|
|
791
1170
|
if (!keys && !skipped) {
|
|
792
|
-
|
|
1171
|
+
write(locked, { source: "reset" }, NO_BASE), options.onReset?.({});
|
|
793
1172
|
return;
|
|
794
1173
|
}
|
|
795
|
-
|
|
796
|
-
for (let k of keys ?? fieldKeys())
|
|
797
|
-
if (valueField(k) && !blocked(k))
|
|
798
|
-
patch[k] = locked[k];
|
|
799
|
-
set(patch, { source: "reset" });
|
|
800
|
-
let resetKeys = options[RESET_KEYS];
|
|
801
|
-
if (resetKeys)
|
|
802
|
-
resetKeys(Object.keys(patch));
|
|
803
|
-
else
|
|
804
|
-
for (let key of Object.keys(patch))
|
|
805
|
-
options.onReset?.({ key });
|
|
1174
|
+
toDefaults(open, keys ? void 0 : NO_BASE);
|
|
806
1175
|
},
|
|
807
1176
|
resetKey(key) {
|
|
808
1177
|
if (!enabled())
|
|
@@ -811,24 +1180,40 @@ function defineControls(id, input, options = {}) {
|
|
|
811
1180
|
throw Error(`Unknown control key: ${key}`);
|
|
812
1181
|
if (blocked(key))
|
|
813
1182
|
return;
|
|
1183
|
+
if (offBase([key]))
|
|
1184
|
+
return toBase([key], { key });
|
|
814
1185
|
set({ [key]: locked[key] }, { source: "reset", key }), options.onReset?.({ key });
|
|
815
1186
|
},
|
|
816
1187
|
resetGroup(group) {
|
|
817
1188
|
if (!enabled())
|
|
818
1189
|
return;
|
|
819
|
-
let keys = Object.keys(schema).filter((k) => schema[k].group === group && hasValue2(schema[k])), open = keys.filter((k) => !blocked(k));
|
|
1190
|
+
let keys = Object.keys(schema).filter((k) => schema[k].group === group && hasValue2(schema[k])), open = keys.filter((k) => !blocked(k)), b = activeBase(), index = b.groups[group];
|
|
1191
|
+
if (offBase(open)) {
|
|
1192
|
+
toBase(open, { group });
|
|
1193
|
+
let preset = index === void 0 ? void 0 : groupPresets[group]?.[index];
|
|
1194
|
+
if (preset && index !== void 0)
|
|
1195
|
+
options.onPreset?.({ group, index, name: preset.name });
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others);
|
|
820
1199
|
if (open.length < keys.length)
|
|
821
|
-
return
|
|
1200
|
+
return toDefaults(open, forget);
|
|
822
1201
|
let patch = {};
|
|
823
1202
|
for (let k of keys)
|
|
824
1203
|
patch[k] = locked[k];
|
|
825
|
-
|
|
1204
|
+
write(patch, { source: "reset", group }, forget), options.onReset?.({ group });
|
|
826
1205
|
},
|
|
827
1206
|
isModified(key) {
|
|
828
|
-
let cur = get();
|
|
1207
|
+
let cur = get(), b = baseValues();
|
|
829
1208
|
if (key !== void 0)
|
|
830
|
-
return !same(cur[key],
|
|
831
|
-
return !equal(cur,
|
|
1209
|
+
return !same(cur[key], b[key]);
|
|
1210
|
+
return !equal(cur, b);
|
|
1211
|
+
},
|
|
1212
|
+
canReset(keys) {
|
|
1213
|
+
if (!enabled())
|
|
1214
|
+
return !1;
|
|
1215
|
+
let cur = get(), b = baseValues();
|
|
1216
|
+
return resettable(keys).some((k) => !same(cur[k], b[k]) || !same(cur[k], locked[k])) || !keys && hasBase();
|
|
832
1217
|
},
|
|
833
1218
|
modified() {
|
|
834
1219
|
let cur = get(), out = {};
|
|
@@ -843,8 +1228,17 @@ function defineControls(id, input, options = {}) {
|
|
|
843
1228
|
let chosen = pool(keys);
|
|
844
1229
|
if (chosen.length === 0)
|
|
845
1230
|
return;
|
|
846
|
-
|
|
847
|
-
|
|
1231
|
+
if (!hasBase()) {
|
|
1232
|
+
let sub = Object.fromEntries(chosen.map((k) => [k, schema[k]]));
|
|
1233
|
+
set(randomValues(sub, draw), { source: "randomize" });
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
let b = baseValues(), patch = {};
|
|
1237
|
+
for (let k of chosen) {
|
|
1238
|
+
let field = valueField(k);
|
|
1239
|
+
patch[k] = covered(k) ? around(field, b[k], draw) : pick(field, draw);
|
|
1240
|
+
}
|
|
1241
|
+
set(patch, { source: "randomize" });
|
|
848
1242
|
},
|
|
849
1243
|
mutate(keys) {
|
|
850
1244
|
if (!enabled())
|
|
@@ -880,6 +1274,33 @@ function defineControls(id, input, options = {}) {
|
|
|
880
1274
|
return !1;
|
|
881
1275
|
return load(), locks.has(key);
|
|
882
1276
|
},
|
|
1277
|
+
shortcut(key, item) {
|
|
1278
|
+
let id = item === void 0 ? key : `${key}/${item}`, declared = declaredShortcut(id);
|
|
1279
|
+
if (!declared.found)
|
|
1280
|
+
return;
|
|
1281
|
+
if (enabled())
|
|
1282
|
+
load();
|
|
1283
|
+
return (enabled() ? bindings.get(id) : void 0) ?? declared.combo;
|
|
1284
|
+
},
|
|
1285
|
+
rebind(key, combo, item) {
|
|
1286
|
+
let id = item === void 0 ? key : `${key}/${item}`, declared = declaredShortcut(id);
|
|
1287
|
+
if (!declared.found)
|
|
1288
|
+
throw Error(`Not an action or toolbar button: ${id}`);
|
|
1289
|
+
if (!enabled())
|
|
1290
|
+
return;
|
|
1291
|
+
load();
|
|
1292
|
+
let next = combo === void 0 ? void 0 : normalizeCombo2(combo);
|
|
1293
|
+
if (combo !== void 0 && combo.trim() && !next)
|
|
1294
|
+
throw Error(`Not a key combination: ${combo}`);
|
|
1295
|
+
let was = bindings.get(id);
|
|
1296
|
+
if (next === void 0 || next === (declared.combo ?? ""))
|
|
1297
|
+
bindings.delete(id);
|
|
1298
|
+
else
|
|
1299
|
+
bindings.set(id, next);
|
|
1300
|
+
if (bindings.get(id) === was)
|
|
1301
|
+
return;
|
|
1302
|
+
persist(), notify();
|
|
1303
|
+
},
|
|
883
1304
|
canRoll(key) {
|
|
884
1305
|
if (!enabled())
|
|
885
1306
|
return !1;
|
|
@@ -913,15 +1334,15 @@ function defineControls(id, input, options = {}) {
|
|
|
913
1334
|
return;
|
|
914
1335
|
if (!hold)
|
|
915
1336
|
return release();
|
|
916
|
-
let before = past.at(-1), now = load();
|
|
1337
|
+
let before = past.at(-1)?.values, now = load();
|
|
917
1338
|
if (comparing || !before || equal(before, now))
|
|
918
1339
|
return;
|
|
919
1340
|
comparing = before, options.onChange?.(changes(now, before), before, { source: "compare" }), notify();
|
|
920
1341
|
},
|
|
921
|
-
preset(id) {
|
|
1342
|
+
preset(id, presetOptions) {
|
|
922
1343
|
if (!Object.hasOwn(presets, id))
|
|
923
1344
|
throw Error(`Unknown preset: ${id}`);
|
|
924
|
-
|
|
1345
|
+
write(presets[id], { source: "preset", coalesce: presetOptions?.coalesce }, id === "default" ? NO_BASE : makeBase(Object.freeze({ kind: "preset", id }), {}));
|
|
925
1346
|
},
|
|
926
1347
|
matchingPreset: () => Object.keys(presets).find((id) => equal(get(), presets[id])) ?? "custom",
|
|
927
1348
|
get groupPresets() {
|
|
@@ -933,41 +1354,36 @@ function defineControls(id, input, options = {}) {
|
|
|
933
1354
|
throw Error(`Unknown preset ${index + 1} for group ${group}`);
|
|
934
1355
|
if (!enabled())
|
|
935
1356
|
return;
|
|
936
|
-
|
|
1357
|
+
let b = activeBase();
|
|
1358
|
+
write(preset.values, { source: "preset", group, coalesce: presetOptions?.coalesce }, makeBase(b.preset, { ...b.groups, [group]: index })), options.onPreset?.({ group, index, name: preset.name });
|
|
1359
|
+
},
|
|
1360
|
+
activePreset() {
|
|
1361
|
+
if (!enabled())
|
|
1362
|
+
return null;
|
|
1363
|
+
return activeBase().preset;
|
|
1364
|
+
},
|
|
1365
|
+
activeGroupPreset(group) {
|
|
1366
|
+
if (!enabled())
|
|
1367
|
+
return -1;
|
|
1368
|
+
return activeBase().groups[group] ?? -1;
|
|
937
1369
|
},
|
|
1370
|
+
baseValues,
|
|
938
1371
|
matchingGroupPreset(group) {
|
|
939
1372
|
let cur = get();
|
|
940
1373
|
return (groupPresets[group] ?? []).findIndex((p) => Object.entries(p.values).every(([k, v]) => same(cur[k], v)));
|
|
941
1374
|
},
|
|
942
1375
|
code: (format, values) => formatCode(values ?? get(), format),
|
|
943
|
-
variants
|
|
1376
|
+
variants,
|
|
944
1377
|
attach(element, chip) {
|
|
945
|
-
let load = options.ship ? () => options.ship().then((m) => m.attach) : () => (__preload("
|
|
946
|
-
|
|
947
|
-
return () => {};
|
|
948
|
-
let disposed = !1, detach;
|
|
949
|
-
return load().then((attach) => {
|
|
950
|
-
if (!disposed && enabled())
|
|
951
|
-
detach = attach(controls, element, chip);
|
|
952
|
-
}).catch((cause) => {
|
|
953
|
-
error = String(cause), notify();
|
|
954
|
-
}), () => {
|
|
955
|
-
disposed = !0, detach?.();
|
|
956
|
-
};
|
|
1378
|
+
let load = options.ship ? () => options.ship().then((m) => m.attach) : () => (__preload("v8ssbcbk"), import("./chunk-v8ssbcbk.js")).then((m) => m.attach);
|
|
1379
|
+
return live(load, (attach) => attach(controls, element, chip), (detach) => detach());
|
|
957
1380
|
},
|
|
958
1381
|
mount(container, mountOptions) {
|
|
959
|
-
let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => (__preload("
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
if (!disposed && enabled())
|
|
965
|
-
panel = mountPanel(controls, container, mountOptions), mountOptions?.onReady?.(panel);
|
|
966
|
-
}).catch((cause) => {
|
|
967
|
-
error = String(cause), notify();
|
|
968
|
-
}), () => {
|
|
969
|
-
disposed = !0, panel?.dispose();
|
|
970
|
-
};
|
|
1382
|
+
let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => (__preload("jx1ktap3"), import("./chunk-jx1ktap3.js")).then((m) => m.mountPanel);
|
|
1383
|
+
return live(load, (mountPanel) => {
|
|
1384
|
+
let panel = mountPanel(controls, container, mountOptions);
|
|
1385
|
+
return mountOptions?.onReady?.(panel), panel;
|
|
1386
|
+
}, (panel) => panel.dispose());
|
|
971
1387
|
}
|
|
972
1388
|
};
|
|
973
1389
|
return Object.freeze(controls);
|
|
@@ -992,7 +1408,11 @@ var optionId = (o) => typeof o === "string" ? o : String(o.id ?? o.value ?? o.la
|
|
|
992
1408
|
function descriptorToField(d) {
|
|
993
1409
|
let meta = pickMeta(d);
|
|
994
1410
|
if (d.kind === "action")
|
|
995
|
-
return action2(d.label,
|
|
1411
|
+
return action2(d.label, {
|
|
1412
|
+
...meta,
|
|
1413
|
+
...d.global ? { global: !0 } : {},
|
|
1414
|
+
...d.rebind ? { rebind: !0 } : {}
|
|
1415
|
+
});
|
|
996
1416
|
if (readoutDescriptor(d))
|
|
997
1417
|
return readoutField(d);
|
|
998
1418
|
if (d.kind === "toolbar")
|
|
@@ -1243,6 +1663,7 @@ function createRemoteControls(id, descriptors, options = {}) {
|
|
|
1243
1663
|
}, controls = defineControls(id, fromDescriptors(frozenDescriptors), {
|
|
1244
1664
|
enabled: options.enabled ?? !0,
|
|
1245
1665
|
ship: options.ship,
|
|
1666
|
+
toggleKey: options.toggleKey,
|
|
1246
1667
|
echo: options.echo ?? ECHO_MS,
|
|
1247
1668
|
storage: options.storage ?? null,
|
|
1248
1669
|
persist: options.persist,
|
|
@@ -1268,9 +1689,11 @@ function createRemoteControls(id, descriptors, options = {}) {
|
|
|
1268
1689
|
groupFolded: options.groupFolded,
|
|
1269
1690
|
sectionFolded: options.sectionFolded,
|
|
1270
1691
|
onChange(patch, _values, meta) {
|
|
1271
|
-
if (meta.source === "remote"
|
|
1692
|
+
if (meta.source === "remote")
|
|
1693
|
+
return;
|
|
1694
|
+
if (meta.source === "reset" && !meta.base)
|
|
1272
1695
|
return;
|
|
1273
|
-
if (meta.source === "preset" && meta.group !== void 0 && options.onPreset)
|
|
1696
|
+
if ((meta.source === "preset" || meta.base && meta.group !== void 0 && controls.activeGroupPreset(meta.group) >= 0) && meta.group !== void 0 && options.onPreset)
|
|
1274
1697
|
return;
|
|
1275
1698
|
let changes = [];
|
|
1276
1699
|
for (let [key, val] of Object.entries(patch)) {
|
|
@@ -1331,10 +1754,13 @@ function fromSettings(groups, home = {}) {
|
|
|
1331
1754
|
return { descriptors, values };
|
|
1332
1755
|
}
|
|
1333
1756
|
export {
|
|
1757
|
+
AROUND,
|
|
1334
1758
|
CURVE_SHAPES2 as CURVE_SHAPES,
|
|
1335
1759
|
EASINGS2 as EASINGS,
|
|
1760
|
+
KONAMI,
|
|
1336
1761
|
SPRING2 as SPRING,
|
|
1337
1762
|
action2 as action,
|
|
1763
|
+
actionShortcut2 as actionShortcut,
|
|
1338
1764
|
angle2 as angle,
|
|
1339
1765
|
bezierCss2 as bezierCss,
|
|
1340
1766
|
bezierPoint2 as bezierPoint,
|
|
@@ -1381,6 +1807,7 @@ export {
|
|
|
1381
1807
|
toggle2 as toggle,
|
|
1382
1808
|
toolbar2 as toolbar,
|
|
1383
1809
|
toolbarShortcut2 as toolbarShortcut,
|
|
1810
|
+
unlock,
|
|
1384
1811
|
urlFlag2 as urlFlag,
|
|
1385
1812
|
vec22 as vec2,
|
|
1386
1813
|
vec32 as vec3,
|