@kitlangton/knobs 0.1.0 → 0.2.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 +174 -30
- package/dist/dev/{chunk-e13znr7c.js → chunk-4km87zfx.js} +3 -3
- package/dist/dev/{chunk-ktsn42p7.js → chunk-5cr85vv6.js} +7448 -5390
- package/dist/dev/{chunk-kdewv0mt.js → chunk-693jd1gj.js} +171 -70
- package/dist/dev/{chunk-qtt698hp.js → chunk-gezhc24g.js} +21 -7
- package/dist/dev/index.js +377 -106
- package/dist/index.js +392 -108
- package/dist/panel.js +9518 -6749
- package/dist/types/core/random.d.ts +61 -1
- package/dist/types/core/remote.d.ts +3 -1
- package/dist/types/core/schema.d.ts +30 -6
- package/dist/types/core/store.d.ts +68 -6
- package/dist/types/core/variants.d.ts +10 -2
- package/dist/types/index.d.ts +3 -2
- package/dist/types/panel/editors.d.ts +11 -0
- package/dist/types/panel/flash.d.ts +13 -0
- package/dist/types/panel/gpu/renderer.d.ts +78 -6
- 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 +1 -0
- package/dist/types/panel/inspector.d.ts +32 -2
- package/dist/types/panel/optkeys.d.ts +7 -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 +19 -0
- package/dist/types/panel/slider.d.ts +1 -1
- package/dist/types/panel/sound.d.ts +137 -0
- package/dist/types/panel/styles.d.ts +1 -1
- 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/solid.d.ts +23 -0
- package/dist/types/ui/split-model.d.ts +54 -0
- package/dist/types/ui/split.d.ts +17 -0
- package/dist/ui-react.js +3239 -567
- package/dist/ui-solid.js +3123 -472
- package/dist/ui.js +2688 -100
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -497,7 +497,15 @@ function choice(value, options, meta) {
|
|
|
497
497
|
}, meta);
|
|
498
498
|
}
|
|
499
499
|
function action(label, meta) {
|
|
500
|
-
|
|
500
|
+
let { shortcut, global, rebind, run, ...rest } = meta ?? {}, key = shortcutOf({ ...shortcut ? { shortcut } : {}, ...global ? { global } : {} }), combo = key ? normalizeCombo(key.key) : "";
|
|
501
|
+
if (key && !combo)
|
|
502
|
+
throw Error("An action's shortcut must name a key.");
|
|
503
|
+
return withMeta({
|
|
504
|
+
kind: "action",
|
|
505
|
+
...run ? { run } : {},
|
|
506
|
+
...key ? { shortcut: combo, scope: key.scope } : {},
|
|
507
|
+
...rebind ? { rebind: !0 } : {}
|
|
508
|
+
}, { ...rest, ...label !== void 0 ? { label } : {} });
|
|
501
509
|
}
|
|
502
510
|
function flatSpring(parts = {}, meta = {}) {
|
|
503
511
|
let id = meta.id ?? meta.label ?? `spring-${++springIds}`, half = (part, input, fallback) => {
|
|
@@ -523,7 +531,7 @@ function flatSpring(parts = {}, meta = {}) {
|
|
|
523
531
|
}
|
|
524
532
|
var springIds = 0;
|
|
525
533
|
function toggle(value, meta) {
|
|
526
|
-
return withMeta({ kind: "toggle", value }, meta);
|
|
534
|
+
return withMeta({ kind: "toggle", value }, { ...meta, random: meta?.random ?? !1 });
|
|
527
535
|
}
|
|
528
536
|
function spring(value = {}, meta) {
|
|
529
537
|
let field = { kind: "spring", value: { duration: 0.5, bounce: 0 } };
|
|
@@ -666,13 +674,19 @@ function curve(points, options = {}) {
|
|
|
666
674
|
...presets && Object.keys(presets).length ? { presets } : {}
|
|
667
675
|
}, options);
|
|
668
676
|
}
|
|
669
|
-
function
|
|
670
|
-
let s =
|
|
677
|
+
function shortcutOf(o) {
|
|
678
|
+
let s = o.shortcut;
|
|
671
679
|
if (!s)
|
|
672
680
|
return;
|
|
673
681
|
if (typeof s === "string")
|
|
674
|
-
return { key: s, scope:
|
|
675
|
-
return s.key ? { key: s.key, scope: s.scope ?? (
|
|
682
|
+
return { key: s, scope: o.global ? "page" : "panel" };
|
|
683
|
+
return s.key ? { key: s.key, scope: s.scope ?? (o.global ? "page" : "panel") } : void 0;
|
|
684
|
+
}
|
|
685
|
+
function toolbarShortcut(item) {
|
|
686
|
+
return shortcutOf(item);
|
|
687
|
+
}
|
|
688
|
+
function actionShortcut(field) {
|
|
689
|
+
return field.shortcut ? { key: field.shortcut, scope: field.scope ?? "panel" } : void 0;
|
|
676
690
|
}
|
|
677
691
|
function toolbar(items, meta) {
|
|
678
692
|
if (!items.length)
|
|
@@ -910,6 +924,139 @@ function springCss(value) {
|
|
|
910
924
|
let { omega, zeta } = springMotion(value), { easing, ms } = springEasing(omega, zeta);
|
|
911
925
|
return { easing, duration: ms };
|
|
912
926
|
}
|
|
927
|
+
// src/core/random.ts
|
|
928
|
+
var lattice = (min, max, step, r) => min + Math.floor(r * (Math.floor((max - min) / step + 0.000000001) + 1)) * step, between2 = (min, max, r) => min + (max - min) * r;
|
|
929
|
+
function pick(field, random) {
|
|
930
|
+
let r = () => Math.max(0, Math.min(1 - Number.EPSILON, random()));
|
|
931
|
+
switch (field.kind) {
|
|
932
|
+
case "knob":
|
|
933
|
+
return lattice(field.min, field.max, field.step, r());
|
|
934
|
+
case "choice":
|
|
935
|
+
return field.options[Math.floor(r() * field.options.length)];
|
|
936
|
+
case "toggle":
|
|
937
|
+
return r() >= 0.5;
|
|
938
|
+
case "spring":
|
|
939
|
+
return { duration: between2(0.2, 0.9, r()), bounce: between2(0, 0.45, r()) };
|
|
940
|
+
case "color": {
|
|
941
|
+
let l = between2(0.5, 0.85, r()), h = between2(0, 360, r());
|
|
942
|
+
return { l, c: between2(0.25, 0.85, r()) * maxChroma(l, h), h };
|
|
943
|
+
}
|
|
944
|
+
case "point":
|
|
945
|
+
return {
|
|
946
|
+
x: lattice(field.min.x, field.max.x, field.step.x, r()),
|
|
947
|
+
y: lattice(field.min.y, field.max.y, field.step.y, r())
|
|
948
|
+
};
|
|
949
|
+
case "easing": {
|
|
950
|
+
let curves = Object.values(EASINGS);
|
|
951
|
+
return curves[Math.floor(r() * curves.length)];
|
|
952
|
+
}
|
|
953
|
+
case "vec": {
|
|
954
|
+
let axis = () => lattice(field.min, field.max, field.step, r());
|
|
955
|
+
return field.axes === 3 ? { x: axis(), y: axis(), z: axis() } : { x: axis(), y: axis() };
|
|
956
|
+
}
|
|
957
|
+
case "range":
|
|
958
|
+
return [
|
|
959
|
+
lattice(field.min, field.max, field.step, r()),
|
|
960
|
+
lattice(field.min, field.max, field.step, r())
|
|
961
|
+
];
|
|
962
|
+
case "angle": {
|
|
963
|
+
let top = field.wrap ? field.max - field.step : field.max;
|
|
964
|
+
return lattice(field.min, Math.max(field.min, top), field.step, r());
|
|
965
|
+
}
|
|
966
|
+
case "seed":
|
|
967
|
+
return lattice(field.min, field.max, 1, r());
|
|
968
|
+
case "keybind":
|
|
969
|
+
return field.value;
|
|
970
|
+
case "gradient":
|
|
971
|
+
return randomStops(field.value.length, r);
|
|
972
|
+
case "curve":
|
|
973
|
+
return randomPoints(field.range, r);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
var AROUND = {
|
|
977
|
+
spread: 0.35,
|
|
978
|
+
switch: 0.3,
|
|
979
|
+
hue: 20,
|
|
980
|
+
lightness: 0.06,
|
|
981
|
+
chroma: 0.15
|
|
982
|
+
};
|
|
983
|
+
function near(v, min, max, step, r, reach = max - min) {
|
|
984
|
+
let span = max - min;
|
|
985
|
+
if (!(span > 0))
|
|
986
|
+
return v;
|
|
987
|
+
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));
|
|
988
|
+
return Number((min + Math.max(0, Math.min(top, n)) * step).toPrecision(14));
|
|
989
|
+
}
|
|
990
|
+
var unit = (r) => r * 2 - 1;
|
|
991
|
+
function around(field, base, random) {
|
|
992
|
+
let r = () => Math.max(0, Math.min(1 - Number.EPSILON, random()));
|
|
993
|
+
switch (field.kind) {
|
|
994
|
+
case "knob":
|
|
995
|
+
return near(base, field.min, field.max, field.step, r());
|
|
996
|
+
case "choice": {
|
|
997
|
+
if (field.options.length < 2 || r() >= AROUND.switch)
|
|
998
|
+
return base;
|
|
999
|
+
let rest = field.options.filter((o) => o !== base);
|
|
1000
|
+
return rest[Math.floor(r() * rest.length)];
|
|
1001
|
+
}
|
|
1002
|
+
case "toggle":
|
|
1003
|
+
return r() < AROUND.switch ? !base : base;
|
|
1004
|
+
case "spring": {
|
|
1005
|
+
let s = base, d = SPRING.duration, b = SPRING.bounce;
|
|
1006
|
+
return {
|
|
1007
|
+
duration: near(s.duration, d.min, d.max, d.step, r(), 0.7),
|
|
1008
|
+
bounce: near(s.bounce, b.min, b.max, b.step, r(), 0.45)
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
case "color": {
|
|
1012
|
+
let c = parseColor(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));
|
|
1013
|
+
return { l, c: k * maxChroma(l, h), h };
|
|
1014
|
+
}
|
|
1015
|
+
case "point": {
|
|
1016
|
+
let p = base;
|
|
1017
|
+
return {
|
|
1018
|
+
x: near(p.x, field.min.x, field.max.x, field.step.x, r()),
|
|
1019
|
+
y: near(p.y, field.min.y, field.max.y, field.step.y, r())
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
case "easing":
|
|
1023
|
+
return base.map((v, i) => {
|
|
1024
|
+
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y;
|
|
1025
|
+
return near(v, lo, hi, 0.001, r());
|
|
1026
|
+
});
|
|
1027
|
+
case "vec": {
|
|
1028
|
+
let v = base, axis = (n) => near(n, field.min, field.max, field.step, r());
|
|
1029
|
+
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) };
|
|
1030
|
+
}
|
|
1031
|
+
case "range": {
|
|
1032
|
+
let [a, b] = base;
|
|
1033
|
+
return [
|
|
1034
|
+
near(a, field.min, field.max, field.step, r()),
|
|
1035
|
+
near(b, field.min, field.max, field.step, r())
|
|
1036
|
+
];
|
|
1037
|
+
}
|
|
1038
|
+
case "angle": {
|
|
1039
|
+
let v = base;
|
|
1040
|
+
if (!field.wrap)
|
|
1041
|
+
return near(v, field.min, field.max, field.step, r());
|
|
1042
|
+
let span = field.max - field.min;
|
|
1043
|
+
return v + unit(r()) * span * (AROUND.spread / 2);
|
|
1044
|
+
}
|
|
1045
|
+
case "gradient":
|
|
1046
|
+
return mutateStops(base, r, [AROUND.hue / 2, AROUND.hue], [AROUND.lightness / 2, AROUND.lightness]);
|
|
1047
|
+
case "curve":
|
|
1048
|
+
return mutatePoints(base, field.range, r, [
|
|
1049
|
+
AROUND.spread / 2,
|
|
1050
|
+
AROUND.spread
|
|
1051
|
+
]);
|
|
1052
|
+
case "seed":
|
|
1053
|
+
case "keybind":
|
|
1054
|
+
return pick(field, random);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
function randomValues(schema, random = Math.random) {
|
|
1058
|
+
return normalize(schema, Object.fromEntries(Object.entries(schema).flatMap(([key, field]) => hasValue(field) ? [[key, pick(field, random)]] : [])));
|
|
1059
|
+
}
|
|
913
1060
|
// src/core/code.ts
|
|
914
1061
|
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);
|
|
915
1062
|
function formatCode(values, format = "ts") {
|
|
@@ -933,12 +1080,12 @@ var MUTATE = {
|
|
|
933
1080
|
chroma: 0.02,
|
|
934
1081
|
lightness: [0.015, 0.045],
|
|
935
1082
|
bezier: [0.03, 0.06]
|
|
936
|
-
},
|
|
1083
|
+
}, between3 = (min, max, r) => min + (max - min) * r, signed2 = (random) => random() < 0.5 ? -1 : 1;
|
|
937
1084
|
function nudge(v, min, max, step, random, reach = max - min) {
|
|
938
1085
|
let span = max - min;
|
|
939
1086
|
if (!(span > 0))
|
|
940
1087
|
return v;
|
|
941
|
-
let sign = signed2(random), by = reach *
|
|
1088
|
+
let sign = signed2(random), by = reach * between3(MUTATE.min, MUTATE.max, random()), next = v + sign * by;
|
|
942
1089
|
if (next > max || next < min)
|
|
943
1090
|
next = v - sign * by;
|
|
944
1091
|
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)));
|
|
@@ -967,12 +1114,12 @@ function shift(field, value, random) {
|
|
|
967
1114
|
};
|
|
968
1115
|
}
|
|
969
1116
|
case "color": {
|
|
970
|
-
let c = parseColor(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 + signed2(random) *
|
|
1117
|
+
let c = parseColor(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 + signed2(random) * between3(MUTATE.hue[0], MUTATE.hue[1], random()) + 360) % 360, l = Math.min(1, Math.max(0, c.l + signed2(random) * between3(MUTATE.lightness[0], MUTATE.lightness[1], random())));
|
|
971
1118
|
return { l, c: nudge(rel0, 0, 1, 0.01, random) * maxChroma(l, h), h };
|
|
972
1119
|
}
|
|
973
1120
|
case "easing":
|
|
974
1121
|
return value.map((v, i) => {
|
|
975
|
-
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y, next = v + signed2(random) *
|
|
1122
|
+
let [lo, hi] = i % 2 === 0 ? [0, 1] : EASING_Y, next = v + signed2(random) * between3(MUTATE.bezier[0], MUTATE.bezier[1], random());
|
|
976
1123
|
return Math.min(hi, Math.max(lo, next));
|
|
977
1124
|
});
|
|
978
1125
|
case "choice": {
|
|
@@ -998,7 +1145,7 @@ function shift(field, value, random) {
|
|
|
998
1145
|
if (!field.wrap)
|
|
999
1146
|
return nudge(v, field.min, field.max, field.step, random);
|
|
1000
1147
|
let span = field.max - field.min;
|
|
1001
|
-
return v + signed2(random) * span *
|
|
1148
|
+
return v + signed2(random) * span * between3(MUTATE.min, MUTATE.max, random());
|
|
1002
1149
|
}
|
|
1003
1150
|
case "seed":
|
|
1004
1151
|
return nudge(value, field.min, field.max, 1, random);
|
|
@@ -1040,59 +1187,6 @@ function mutateValues(schema, current, keys = valueKeys(schema), random = Math.r
|
|
|
1040
1187
|
return out;
|
|
1041
1188
|
}
|
|
1042
1189
|
|
|
1043
|
-
// src/core/random.ts
|
|
1044
|
-
var lattice = (min, max, step, r) => min + Math.floor(r * (Math.floor((max - min) / step + 0.000000001) + 1)) * step, between3 = (min, max, r) => min + (max - min) * r;
|
|
1045
|
-
function pick(field, random) {
|
|
1046
|
-
let r = () => Math.max(0, Math.min(1 - Number.EPSILON, random()));
|
|
1047
|
-
switch (field.kind) {
|
|
1048
|
-
case "knob":
|
|
1049
|
-
return lattice(field.min, field.max, field.step, r());
|
|
1050
|
-
case "choice":
|
|
1051
|
-
return field.options[Math.floor(r() * field.options.length)];
|
|
1052
|
-
case "toggle":
|
|
1053
|
-
return r() >= 0.5;
|
|
1054
|
-
case "spring":
|
|
1055
|
-
return { duration: between3(0.2, 0.9, r()), bounce: between3(0, 0.45, r()) };
|
|
1056
|
-
case "color": {
|
|
1057
|
-
let l = between3(0.5, 0.85, r()), h = between3(0, 360, r());
|
|
1058
|
-
return { l, c: between3(0.25, 0.85, r()) * maxChroma(l, h), h };
|
|
1059
|
-
}
|
|
1060
|
-
case "point":
|
|
1061
|
-
return {
|
|
1062
|
-
x: lattice(field.min.x, field.max.x, field.step.x, r()),
|
|
1063
|
-
y: lattice(field.min.y, field.max.y, field.step.y, r())
|
|
1064
|
-
};
|
|
1065
|
-
case "easing": {
|
|
1066
|
-
let curves = Object.values(EASINGS);
|
|
1067
|
-
return curves[Math.floor(r() * curves.length)];
|
|
1068
|
-
}
|
|
1069
|
-
case "vec": {
|
|
1070
|
-
let axis = () => lattice(field.min, field.max, field.step, r());
|
|
1071
|
-
return field.axes === 3 ? { x: axis(), y: axis(), z: axis() } : { x: axis(), y: axis() };
|
|
1072
|
-
}
|
|
1073
|
-
case "range":
|
|
1074
|
-
return [
|
|
1075
|
-
lattice(field.min, field.max, field.step, r()),
|
|
1076
|
-
lattice(field.min, field.max, field.step, r())
|
|
1077
|
-
];
|
|
1078
|
-
case "angle": {
|
|
1079
|
-
let top = field.wrap ? field.max - field.step : field.max;
|
|
1080
|
-
return lattice(field.min, Math.max(field.min, top), field.step, r());
|
|
1081
|
-
}
|
|
1082
|
-
case "seed":
|
|
1083
|
-
return lattice(field.min, field.max, 1, r());
|
|
1084
|
-
case "keybind":
|
|
1085
|
-
return field.value;
|
|
1086
|
-
case "gradient":
|
|
1087
|
-
return randomStops(field.value.length, r);
|
|
1088
|
-
case "curve":
|
|
1089
|
-
return randomPoints(field.range, r);
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
function randomValues(schema, random = Math.random) {
|
|
1093
|
-
return normalize(schema, Object.fromEntries(Object.entries(schema).flatMap(([key, field]) => hasValue(field) ? [[key, pick(field, random)]] : [])));
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
1190
|
// src/core/internal.ts
|
|
1097
1191
|
var RESHAPE = Symbol.for("knobs.reshape"), RESET_KEYS = Symbol.for("knobs.resetKeys"), REFRESHES = Symbol.for("knobs.refreshes");
|
|
1098
1192
|
|
|
@@ -1290,12 +1384,28 @@ function createVariants(schema, id, key, storage, get, set, notify, enabled) {
|
|
|
1290
1384
|
});
|
|
1291
1385
|
return persist([...list, variant]), variant;
|
|
1292
1386
|
},
|
|
1293
|
-
load(id) {
|
|
1387
|
+
load(id, options) {
|
|
1294
1388
|
read();
|
|
1295
1389
|
let variant = list.find((v) => v.id === id);
|
|
1296
1390
|
if (!variant)
|
|
1297
1391
|
throw Error(`Unknown variant: ${id}`);
|
|
1298
|
-
set(variant.values);
|
|
1392
|
+
set(variant.values, id, Boolean(options?.coalesce));
|
|
1393
|
+
},
|
|
1394
|
+
rename(id, name) {
|
|
1395
|
+
if (read(), name.length > 100)
|
|
1396
|
+
throw Error("Variant names must be at most 100 characters.");
|
|
1397
|
+
let at = list.findIndex((v) => v.id === id);
|
|
1398
|
+
if (at < 0)
|
|
1399
|
+
throw Error(`Unknown variant: ${id}`);
|
|
1400
|
+
let was = list[at], trimmed = name.trim();
|
|
1401
|
+
if ((was.name ?? "") === trimmed)
|
|
1402
|
+
return;
|
|
1403
|
+
let next = [...list];
|
|
1404
|
+
next[at] = Object.freeze({
|
|
1405
|
+
id: was.id,
|
|
1406
|
+
...trimmed ? { name: trimmed } : {},
|
|
1407
|
+
values: was.values
|
|
1408
|
+
}), persist(next);
|
|
1299
1409
|
},
|
|
1300
1410
|
remove(id) {
|
|
1301
1411
|
read(), persist(list.filter((v) => v.id !== id));
|
|
@@ -1335,7 +1445,7 @@ function defineControls(id, input, options = {}) {
|
|
|
1335
1445
|
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 = () => Boolean(options.ship) && (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 = () => {
|
|
1336
1446
|
for (let cb of [...listeners])
|
|
1337
1447
|
cb();
|
|
1338
|
-
}, 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([
|
|
1448
|
+
}, 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([
|
|
1339
1449
|
["default", locked],
|
|
1340
1450
|
...Object.entries(options.presets ?? {}).map(([id, patch]) => {
|
|
1341
1451
|
if (id === "default" || id === "custom")
|
|
@@ -1375,6 +1485,9 @@ function defineControls(id, input, options = {}) {
|
|
|
1375
1485
|
if (data?.version === 1) {
|
|
1376
1486
|
if (current = normalize(schema, data.values), Array.isArray(data.locks))
|
|
1377
1487
|
locks = new Set(data.locks.filter((k) => typeof k === "string" && Object.hasOwn(schema, k)));
|
|
1488
|
+
if (data.bindings && typeof data.bindings === "object")
|
|
1489
|
+
bindings = new Map(Object.entries(data.bindings).flatMap(([id, combo]) => typeof combo === "string" && bindable(id) ? [[id, normalizeCombo(combo)]] : []));
|
|
1490
|
+
base = readBase(data.base);
|
|
1378
1491
|
}
|
|
1379
1492
|
}
|
|
1380
1493
|
} catch (cause) {
|
|
@@ -1393,7 +1506,9 @@ function defineControls(id, input, options = {}) {
|
|
|
1393
1506
|
valueStorage()?.setItem(stateKey, JSON.stringify({
|
|
1394
1507
|
version: 1,
|
|
1395
1508
|
values: current,
|
|
1396
|
-
...locks.size ? { locks: [...locks] } : {}
|
|
1509
|
+
...locks.size ? { locks: [...locks] } : {},
|
|
1510
|
+
...bindings.size ? { bindings: Object.fromEntries(bindings) } : {},
|
|
1511
|
+
...base !== NO_BASE ? { base } : {}
|
|
1397
1512
|
})), error = null;
|
|
1398
1513
|
} catch (cause) {
|
|
1399
1514
|
error = String(cause);
|
|
@@ -1402,6 +1517,74 @@ function defineControls(id, input, options = {}) {
|
|
|
1402
1517
|
function commit(next) {
|
|
1403
1518
|
current = next, persist(), notify();
|
|
1404
1519
|
}
|
|
1520
|
+
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);
|
|
1521
|
+
function validBase(b) {
|
|
1522
|
+
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);
|
|
1523
|
+
return sameBase(next, b) ? b : next;
|
|
1524
|
+
}
|
|
1525
|
+
function readBase(raw) {
|
|
1526
|
+
if (!raw || typeof raw !== "object")
|
|
1527
|
+
return NO_BASE;
|
|
1528
|
+
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]))) : {};
|
|
1529
|
+
return validBase(makeBase(ref, byGroup));
|
|
1530
|
+
}
|
|
1531
|
+
function activeBase() {
|
|
1532
|
+
load();
|
|
1533
|
+
let ref = base.preset;
|
|
1534
|
+
if (ref?.kind === "variant" && !variants.list().some((v) => v.id === ref.id))
|
|
1535
|
+
base = makeBase(null, base.groups);
|
|
1536
|
+
return base;
|
|
1537
|
+
}
|
|
1538
|
+
let hasBase = () => activeBase() !== NO_BASE, baseCache;
|
|
1539
|
+
function baseValues() {
|
|
1540
|
+
if (!enabled())
|
|
1541
|
+
return locked;
|
|
1542
|
+
let b = activeBase();
|
|
1543
|
+
if (b === NO_BASE)
|
|
1544
|
+
return locked;
|
|
1545
|
+
let list = b.preset?.kind === "variant" ? variants.list() : null, c = baseCache;
|
|
1546
|
+
if (c && c.base === b && c.schema === schema && c.presets === presets && c.groupPresets === groupPresets && c.variants === list)
|
|
1547
|
+
return c.values;
|
|
1548
|
+
let out = locked, ref = b.preset;
|
|
1549
|
+
if (ref?.kind === "preset" && Object.hasOwn(presets, ref.id))
|
|
1550
|
+
out = presets[ref.id];
|
|
1551
|
+
else if (ref?.kind === "variant") {
|
|
1552
|
+
let found = list?.find((v) => v.id === ref.id);
|
|
1553
|
+
if (found)
|
|
1554
|
+
out = normalize(schema, found.values);
|
|
1555
|
+
}
|
|
1556
|
+
let groups = Object.entries(b.groups);
|
|
1557
|
+
if (groups.length) {
|
|
1558
|
+
out = { ...out };
|
|
1559
|
+
for (let [g, i] of groups)
|
|
1560
|
+
Object.assign(out, groupPresets[g]?.[i]?.values);
|
|
1561
|
+
}
|
|
1562
|
+
let values = Object.freeze(out);
|
|
1563
|
+
return baseCache = { base: b, schema, presets, groupPresets, variants: list, values }, values;
|
|
1564
|
+
}
|
|
1565
|
+
let covered = (key) => {
|
|
1566
|
+
let b = activeBase();
|
|
1567
|
+
if (b.preset)
|
|
1568
|
+
return !0;
|
|
1569
|
+
let group = schema[key]?.group;
|
|
1570
|
+
return group !== void 0 && Object.hasOwn(b.groups, group);
|
|
1571
|
+
};
|
|
1572
|
+
function declaredShortcut(id) {
|
|
1573
|
+
let slash = id.indexOf("/"), key = slash < 0 ? id : id.slice(0, slash), field = Object.hasOwn(schema, key) ? schema[key] : void 0;
|
|
1574
|
+
if (field?.kind === "action" && slash < 0)
|
|
1575
|
+
return { found: !0, ...field.shortcut ? { combo: field.shortcut } : {} };
|
|
1576
|
+
if (field?.kind === "toolbar" && slash >= 0) {
|
|
1577
|
+
let item = field.items.find((i) => (i.id ?? i.label) === id.slice(slash + 1));
|
|
1578
|
+
if (!item)
|
|
1579
|
+
return { found: !1 };
|
|
1580
|
+
let key = toolbarShortcut(item)?.key;
|
|
1581
|
+
return { found: !0, ...key ? { combo: normalizeCombo(key) } : {} };
|
|
1582
|
+
}
|
|
1583
|
+
return { found: !1 };
|
|
1584
|
+
}
|
|
1585
|
+
function bindable(id) {
|
|
1586
|
+
return declaredShortcut(id).found;
|
|
1587
|
+
}
|
|
1405
1588
|
let fieldKeys = () => valueKeys(schema), valueField = (k) => {
|
|
1406
1589
|
let field = Object.hasOwn(schema, k) ? schema[k] : void 0;
|
|
1407
1590
|
return field && hasValue(field) ? field : void 0;
|
|
@@ -1464,10 +1647,13 @@ function defineControls(id, input, options = {}) {
|
|
|
1464
1647
|
pending.delete(k);
|
|
1465
1648
|
};
|
|
1466
1649
|
function set(patch, setOpts) {
|
|
1650
|
+
write(patch, setOpts);
|
|
1651
|
+
}
|
|
1652
|
+
function write(patch, setOpts, nextBase) {
|
|
1467
1653
|
if (!enabled())
|
|
1468
1654
|
return;
|
|
1469
1655
|
release();
|
|
1470
|
-
let previous = load(), forced = mixed.size ? Object.keys(patch).filter((k) => mixed.has(k) && valueField(k)) : [];
|
|
1656
|
+
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)) : [];
|
|
1471
1657
|
for (let k of forced)
|
|
1472
1658
|
mixed.delete(k);
|
|
1473
1659
|
let applied = applyPatch(previous, previous, patch) ?? {
|
|
@@ -1477,9 +1663,10 @@ function defineControls(id, input, options = {}) {
|
|
|
1477
1663
|
for (let k of forced)
|
|
1478
1664
|
if (!(k in diff))
|
|
1479
1665
|
diff[k] = next[k];
|
|
1480
|
-
|
|
1666
|
+
let changed = Object.keys(diff).length > 0;
|
|
1667
|
+
if (!changed && !moves)
|
|
1481
1668
|
return;
|
|
1482
|
-
if (next === previous) {
|
|
1669
|
+
if (next === previous && !moves) {
|
|
1483
1670
|
notify(), options.onChange?.(diff, next, {
|
|
1484
1671
|
source: setOpts?.source ?? "local",
|
|
1485
1672
|
...setOpts?.key ? { key: setOpts.key } : {}
|
|
@@ -1487,16 +1674,27 @@ function defineControls(id, input, options = {}) {
|
|
|
1487
1674
|
return;
|
|
1488
1675
|
}
|
|
1489
1676
|
if (!setOpts?.coalesce || past.length === 0) {
|
|
1490
|
-
if (past.push(previous), past.length > HISTORY)
|
|
1677
|
+
if (past.push({ values: previous, base: was }), past.length > HISTORY)
|
|
1491
1678
|
past.shift();
|
|
1492
1679
|
}
|
|
1493
|
-
future.length = 0,
|
|
1680
|
+
if (future.length = 0, moves)
|
|
1681
|
+
base = nextBase;
|
|
1682
|
+
if (markChanged(diff), commit(next), !changed)
|
|
1683
|
+
return;
|
|
1684
|
+
options.onChange?.(diff, next, {
|
|
1494
1685
|
source: setOpts?.source ?? "local",
|
|
1495
1686
|
...setOpts?.coalesce ? { coalesce: !0 } : {},
|
|
1496
1687
|
...setOpts?.key ? { key: setOpts.key } : {},
|
|
1497
|
-
...setOpts?.group ? { group: setOpts.group } : {}
|
|
1688
|
+
...setOpts?.group ? { group: setOpts.group } : {},
|
|
1689
|
+
...setOpts?.base ? { base: !0 } : {}
|
|
1498
1690
|
});
|
|
1499
1691
|
}
|
|
1692
|
+
function step(to, source) {
|
|
1693
|
+
let before = load(), left = { values: before, base: activeBase() }, diff = changes(before, to.values);
|
|
1694
|
+
if (base = validBase(to.base), markChanged(diff), commit(to.values), Object.keys(diff).length)
|
|
1695
|
+
options.onChange?.(diff, to.values, { source });
|
|
1696
|
+
return left;
|
|
1697
|
+
}
|
|
1500
1698
|
function place(values, replace, land) {
|
|
1501
1699
|
let previous = load(), applied = applyPatch(replace ? locked : previous, previous, values);
|
|
1502
1700
|
if (!applied)
|
|
@@ -1604,7 +1802,7 @@ function defineControls(id, input, options = {}) {
|
|
|
1604
1802
|
schema = Object.freeze({ ...next });
|
|
1605
1803
|
if (changed) {
|
|
1606
1804
|
let previous = load();
|
|
1607
|
-
schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets();
|
|
1805
|
+
schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets(), base = validBase(base);
|
|
1608
1806
|
for (let k of [...locks])
|
|
1609
1807
|
if (!valueField(k))
|
|
1610
1808
|
locks.delete(k);
|
|
@@ -1639,7 +1837,30 @@ function defineControls(id, input, options = {}) {
|
|
|
1639
1837
|
listen(cb) {
|
|
1640
1838
|
return readoutListeners.add(cb), () => readoutListeners.delete(cb);
|
|
1641
1839
|
}
|
|
1642
|
-
},
|
|
1840
|
+
}, 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));
|
|
1841
|
+
function offBase(keys) {
|
|
1842
|
+
if (!hasBase())
|
|
1843
|
+
return !1;
|
|
1844
|
+
let cur = load(), b = baseValues();
|
|
1845
|
+
return keys.some((k) => !same(cur[k], b[k]));
|
|
1846
|
+
}
|
|
1847
|
+
function toBase(keys, meta) {
|
|
1848
|
+
let b = baseValues(), patch = Object.fromEntries(keys.map((k) => [k, b[k]]));
|
|
1849
|
+
write(patch, { source: "reset", base: !0, ...meta });
|
|
1850
|
+
}
|
|
1851
|
+
function toDefaults(keys, nextBase) {
|
|
1852
|
+
let patch = {};
|
|
1853
|
+
for (let k of keys)
|
|
1854
|
+
patch[k] = locked[k];
|
|
1855
|
+
write(patch, { source: "reset" }, nextBase);
|
|
1856
|
+
let resetKeys = options[RESET_KEYS];
|
|
1857
|
+
if (resetKeys)
|
|
1858
|
+
resetKeys(Object.keys(patch));
|
|
1859
|
+
else
|
|
1860
|
+
for (let key of Object.keys(patch))
|
|
1861
|
+
options.onReset?.({ key });
|
|
1862
|
+
}
|
|
1863
|
+
let controls = {
|
|
1643
1864
|
id,
|
|
1644
1865
|
get schema() {
|
|
1645
1866
|
return schema;
|
|
@@ -1741,8 +1962,7 @@ function defineControls(id, input, options = {}) {
|
|
|
1741
1962
|
let previous = past.pop();
|
|
1742
1963
|
if (!previous)
|
|
1743
1964
|
return;
|
|
1744
|
-
|
|
1745
|
-
future.push(before), markChanged(diff), commit(previous), options.onChange?.(diff, previous, { source: "undo" });
|
|
1965
|
+
future.push(step(previous, "undo"));
|
|
1746
1966
|
},
|
|
1747
1967
|
redo() {
|
|
1748
1968
|
if (release(), hostHistory)
|
|
@@ -1750,8 +1970,7 @@ function defineControls(id, input, options = {}) {
|
|
|
1750
1970
|
let next = future.pop();
|
|
1751
1971
|
if (!next)
|
|
1752
1972
|
return;
|
|
1753
|
-
|
|
1754
|
-
past.push(before), markChanged(diff), commit(next), options.onChange?.(diff, next, { source: "redo" });
|
|
1973
|
+
past.push(step(next, "redo"));
|
|
1755
1974
|
},
|
|
1756
1975
|
getServerSnapshot: () => locked,
|
|
1757
1976
|
subscribe(cb) {
|
|
@@ -1765,22 +1984,15 @@ function defineControls(id, input, options = {}) {
|
|
|
1765
1984
|
reset(keys) {
|
|
1766
1985
|
if (!enabled())
|
|
1767
1986
|
return;
|
|
1987
|
+
let open = resettable(keys);
|
|
1988
|
+
if (offBase(open))
|
|
1989
|
+
return toBase(open, {});
|
|
1768
1990
|
let skipped = fieldKeys().some(blocked);
|
|
1769
1991
|
if (!keys && !skipped) {
|
|
1770
|
-
|
|
1992
|
+
write(locked, { source: "reset" }, NO_BASE), options.onReset?.({});
|
|
1771
1993
|
return;
|
|
1772
1994
|
}
|
|
1773
|
-
|
|
1774
|
-
for (let k of keys ?? fieldKeys())
|
|
1775
|
-
if (valueField(k) && !blocked(k))
|
|
1776
|
-
patch[k] = locked[k];
|
|
1777
|
-
set(patch, { source: "reset" });
|
|
1778
|
-
let resetKeys = options[RESET_KEYS];
|
|
1779
|
-
if (resetKeys)
|
|
1780
|
-
resetKeys(Object.keys(patch));
|
|
1781
|
-
else
|
|
1782
|
-
for (let key of Object.keys(patch))
|
|
1783
|
-
options.onReset?.({ key });
|
|
1995
|
+
toDefaults(open, keys ? void 0 : NO_BASE);
|
|
1784
1996
|
},
|
|
1785
1997
|
resetKey(key) {
|
|
1786
1998
|
if (!enabled())
|
|
@@ -1789,24 +2001,40 @@ function defineControls(id, input, options = {}) {
|
|
|
1789
2001
|
throw Error(`Unknown control key: ${key}`);
|
|
1790
2002
|
if (blocked(key))
|
|
1791
2003
|
return;
|
|
2004
|
+
if (offBase([key]))
|
|
2005
|
+
return toBase([key], { key });
|
|
1792
2006
|
set({ [key]: locked[key] }, { source: "reset", key }), options.onReset?.({ key });
|
|
1793
2007
|
},
|
|
1794
2008
|
resetGroup(group) {
|
|
1795
2009
|
if (!enabled())
|
|
1796
2010
|
return;
|
|
1797
|
-
let keys = Object.keys(schema).filter((k) => schema[k].group === group && hasValue(schema[k])), open = keys.filter((k) => !blocked(k));
|
|
2011
|
+
let keys = Object.keys(schema).filter((k) => schema[k].group === group && hasValue(schema[k])), open = keys.filter((k) => !blocked(k)), b = activeBase(), index = b.groups[group];
|
|
2012
|
+
if (offBase(open)) {
|
|
2013
|
+
toBase(open, { group });
|
|
2014
|
+
let preset = index === void 0 ? void 0 : groupPresets[group]?.[index];
|
|
2015
|
+
if (preset && index !== void 0)
|
|
2016
|
+
options.onPreset?.({ group, index, name: preset.name });
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others);
|
|
1798
2020
|
if (open.length < keys.length)
|
|
1799
|
-
return
|
|
2021
|
+
return toDefaults(open, forget);
|
|
1800
2022
|
let patch = {};
|
|
1801
2023
|
for (let k of keys)
|
|
1802
2024
|
patch[k] = locked[k];
|
|
1803
|
-
|
|
2025
|
+
write(patch, { source: "reset", group }, forget), options.onReset?.({ group });
|
|
1804
2026
|
},
|
|
1805
2027
|
isModified(key) {
|
|
1806
|
-
let cur = get();
|
|
2028
|
+
let cur = get(), b = baseValues();
|
|
1807
2029
|
if (key !== void 0)
|
|
1808
|
-
return !same(cur[key],
|
|
1809
|
-
return !equal(cur,
|
|
2030
|
+
return !same(cur[key], b[key]);
|
|
2031
|
+
return !equal(cur, b);
|
|
2032
|
+
},
|
|
2033
|
+
canReset(keys) {
|
|
2034
|
+
if (!enabled())
|
|
2035
|
+
return !1;
|
|
2036
|
+
let cur = get(), b = baseValues();
|
|
2037
|
+
return resettable(keys).some((k) => !same(cur[k], b[k]) || !same(cur[k], locked[k])) || !keys && hasBase();
|
|
1810
2038
|
},
|
|
1811
2039
|
modified() {
|
|
1812
2040
|
let cur = get(), out = {};
|
|
@@ -1821,8 +2049,17 @@ function defineControls(id, input, options = {}) {
|
|
|
1821
2049
|
let chosen = pool(keys);
|
|
1822
2050
|
if (chosen.length === 0)
|
|
1823
2051
|
return;
|
|
1824
|
-
|
|
1825
|
-
|
|
2052
|
+
if (!hasBase()) {
|
|
2053
|
+
let sub = Object.fromEntries(chosen.map((k) => [k, schema[k]]));
|
|
2054
|
+
set(randomValues(sub, draw), { source: "randomize" });
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
let b = baseValues(), patch = {};
|
|
2058
|
+
for (let k of chosen) {
|
|
2059
|
+
let field = valueField(k);
|
|
2060
|
+
patch[k] = covered(k) ? around(field, b[k], draw) : pick(field, draw);
|
|
2061
|
+
}
|
|
2062
|
+
set(patch, { source: "randomize" });
|
|
1826
2063
|
},
|
|
1827
2064
|
mutate(keys) {
|
|
1828
2065
|
if (!enabled())
|
|
@@ -1858,6 +2095,33 @@ function defineControls(id, input, options = {}) {
|
|
|
1858
2095
|
return !1;
|
|
1859
2096
|
return load(), locks.has(key);
|
|
1860
2097
|
},
|
|
2098
|
+
shortcut(key, item) {
|
|
2099
|
+
let id = item === void 0 ? key : `${key}/${item}`, declared = declaredShortcut(id);
|
|
2100
|
+
if (!declared.found)
|
|
2101
|
+
return;
|
|
2102
|
+
if (enabled())
|
|
2103
|
+
load();
|
|
2104
|
+
return (enabled() ? bindings.get(id) : void 0) ?? declared.combo;
|
|
2105
|
+
},
|
|
2106
|
+
rebind(key, combo, item) {
|
|
2107
|
+
let id = item === void 0 ? key : `${key}/${item}`, declared = declaredShortcut(id);
|
|
2108
|
+
if (!declared.found)
|
|
2109
|
+
throw Error(`Not an action or toolbar button: ${id}`);
|
|
2110
|
+
if (!enabled())
|
|
2111
|
+
return;
|
|
2112
|
+
load();
|
|
2113
|
+
let next = combo === void 0 ? void 0 : normalizeCombo(combo);
|
|
2114
|
+
if (combo !== void 0 && combo.trim() && !next)
|
|
2115
|
+
throw Error(`Not a key combination: ${combo}`);
|
|
2116
|
+
let was = bindings.get(id);
|
|
2117
|
+
if (next === void 0 || next === (declared.combo ?? ""))
|
|
2118
|
+
bindings.delete(id);
|
|
2119
|
+
else
|
|
2120
|
+
bindings.set(id, next);
|
|
2121
|
+
if (bindings.get(id) === was)
|
|
2122
|
+
return;
|
|
2123
|
+
persist(), notify();
|
|
2124
|
+
},
|
|
1861
2125
|
canRoll(key) {
|
|
1862
2126
|
if (!enabled())
|
|
1863
2127
|
return !1;
|
|
@@ -1891,15 +2155,15 @@ function defineControls(id, input, options = {}) {
|
|
|
1891
2155
|
return;
|
|
1892
2156
|
if (!hold)
|
|
1893
2157
|
return release();
|
|
1894
|
-
let before = past.at(-1), now = load();
|
|
2158
|
+
let before = past.at(-1)?.values, now = load();
|
|
1895
2159
|
if (comparing || !before || equal(before, now))
|
|
1896
2160
|
return;
|
|
1897
2161
|
comparing = before, options.onChange?.(changes(now, before), before, { source: "compare" }), notify();
|
|
1898
2162
|
},
|
|
1899
|
-
preset(id) {
|
|
2163
|
+
preset(id, presetOptions) {
|
|
1900
2164
|
if (!Object.hasOwn(presets, id))
|
|
1901
2165
|
throw Error(`Unknown preset: ${id}`);
|
|
1902
|
-
|
|
2166
|
+
write(presets[id], { source: "preset", coalesce: presetOptions?.coalesce }, id === "default" ? NO_BASE : makeBase(Object.freeze({ kind: "preset", id }), {}));
|
|
1903
2167
|
},
|
|
1904
2168
|
matchingPreset: () => Object.keys(presets).find((id) => equal(get(), presets[id])) ?? "custom",
|
|
1905
2169
|
get groupPresets() {
|
|
@@ -1911,14 +2175,26 @@ function defineControls(id, input, options = {}) {
|
|
|
1911
2175
|
throw Error(`Unknown preset ${index + 1} for group ${group}`);
|
|
1912
2176
|
if (!enabled())
|
|
1913
2177
|
return;
|
|
1914
|
-
|
|
2178
|
+
let b = activeBase();
|
|
2179
|
+
write(preset.values, { source: "preset", group, coalesce: presetOptions?.coalesce }, makeBase(b.preset, { ...b.groups, [group]: index })), options.onPreset?.({ group, index, name: preset.name });
|
|
2180
|
+
},
|
|
2181
|
+
activePreset() {
|
|
2182
|
+
if (!enabled())
|
|
2183
|
+
return null;
|
|
2184
|
+
return activeBase().preset;
|
|
2185
|
+
},
|
|
2186
|
+
activeGroupPreset(group) {
|
|
2187
|
+
if (!enabled())
|
|
2188
|
+
return -1;
|
|
2189
|
+
return activeBase().groups[group] ?? -1;
|
|
1915
2190
|
},
|
|
2191
|
+
baseValues,
|
|
1916
2192
|
matchingGroupPreset(group) {
|
|
1917
2193
|
let cur = get();
|
|
1918
2194
|
return (groupPresets[group] ?? []).findIndex((p) => Object.entries(p.values).every(([k, v]) => same(cur[k], v)));
|
|
1919
2195
|
},
|
|
1920
2196
|
code: (format, values) => formatCode(values ?? get(), format),
|
|
1921
|
-
variants
|
|
2197
|
+
variants,
|
|
1922
2198
|
attach(element, chip) {
|
|
1923
2199
|
let load = options.ship ? () => options.ship().then((m) => m.attach) : void 0;
|
|
1924
2200
|
if (!load || !enabled())
|
|
@@ -1970,7 +2246,11 @@ var optionId = (o) => typeof o === "string" ? o : String(o.id ?? o.value ?? o.la
|
|
|
1970
2246
|
function descriptorToField(d) {
|
|
1971
2247
|
let meta = pickMeta(d);
|
|
1972
2248
|
if (d.kind === "action")
|
|
1973
|
-
return action(d.label,
|
|
2249
|
+
return action(d.label, {
|
|
2250
|
+
...meta,
|
|
2251
|
+
...d.global ? { global: !0 } : {},
|
|
2252
|
+
...d.rebind ? { rebind: !0 } : {}
|
|
2253
|
+
});
|
|
1974
2254
|
if (readoutDescriptor(d))
|
|
1975
2255
|
return readoutField(d);
|
|
1976
2256
|
if (d.kind === "toolbar")
|
|
@@ -2246,9 +2526,11 @@ function createRemoteControls(id, descriptors, options = {}) {
|
|
|
2246
2526
|
groupFolded: options.groupFolded,
|
|
2247
2527
|
sectionFolded: options.sectionFolded,
|
|
2248
2528
|
onChange(patch, _values, meta) {
|
|
2249
|
-
if (meta.source === "remote"
|
|
2529
|
+
if (meta.source === "remote")
|
|
2530
|
+
return;
|
|
2531
|
+
if (meta.source === "reset" && !meta.base)
|
|
2250
2532
|
return;
|
|
2251
|
-
if (meta.source === "preset" && meta.group !== void 0 && options.onPreset)
|
|
2533
|
+
if ((meta.source === "preset" || meta.base && meta.group !== void 0 && controls.activeGroupPreset(meta.group) >= 0) && meta.group !== void 0 && options.onPreset)
|
|
2252
2534
|
return;
|
|
2253
2535
|
let changes = [];
|
|
2254
2536
|
for (let [key, val] of Object.entries(patch)) {
|
|
@@ -2309,10 +2591,12 @@ function fromSettings(groups, home = {}) {
|
|
|
2309
2591
|
return { descriptors, values };
|
|
2310
2592
|
}
|
|
2311
2593
|
export {
|
|
2594
|
+
AROUND,
|
|
2312
2595
|
CURVE_SHAPES,
|
|
2313
2596
|
EASINGS,
|
|
2314
2597
|
SPRING,
|
|
2315
2598
|
action,
|
|
2599
|
+
actionShortcut,
|
|
2316
2600
|
angle,
|
|
2317
2601
|
bezierCss,
|
|
2318
2602
|
bezierPoint,
|