@kitlangton/knobs 0.4.0-next.11 → 0.4.0-next.13

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/dist/dev/index.js CHANGED
@@ -1,6 +1,4 @@
1
1
  import {
2
- __preload,
3
- __chunks,
4
2
  maxChroma,
5
3
  oklchToRgb,
6
4
  parseColor2,
@@ -27,6 +25,7 @@ import {
27
25
  pickMeta,
28
26
  isReadout2,
29
27
  hasValue2,
28
+ variantsOf,
30
29
  pinnedKeys,
31
30
  SPRING2,
32
31
  valueKeys,
@@ -45,6 +44,7 @@ import {
45
44
  angle2,
46
45
  seed2,
47
46
  keybind2,
47
+ text2,
48
48
  gradient2,
49
49
  curve2,
50
50
  toolbarShortcut2,
@@ -76,8 +76,7 @@ import {
76
76
  browserStorage,
77
77
  urlFlag2,
78
78
  storageKey
79
- } from "./chunk-mjdgzad5.js";
80
- __chunks(import.meta.url,["js6xfzn6","bnhzf1tj","75gbzbyd","mjdgzad5","j57rhjtm"],[["./index.js",3],["./chunk-bnhzf1tj.js",3,4],["./chunk-75gbzbyd.js",3,4],["./chunk-mjdgzad5.js"],["./chunk-j57rhjtm.js",3]],0);
79
+ } from "./chunk-7kns3qe6.js";
81
80
  // src/core/random.ts
82
81
  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;
83
82
  function pick(field, random) {
@@ -120,6 +119,7 @@ function pick(field, random) {
120
119
  case "seed":
121
120
  return lattice(field.min, field.max, 1, r());
122
121
  case "keybind":
122
+ case "text":
123
123
  return field.value;
124
124
  case "gradient":
125
125
  return randomStops(field.value.length, r);
@@ -205,6 +205,7 @@ function around(field, base, random) {
205
205
  ]);
206
206
  case "seed":
207
207
  case "keybind":
208
+ case "text":
208
209
  return pick(field, random);
209
210
  }
210
211
  }
@@ -304,6 +305,7 @@ function shift(field, value, random) {
304
305
  case "seed":
305
306
  return nudge(value, field.min, field.max, 1, random);
306
307
  case "keybind":
308
+ case "text":
307
309
  return value;
308
310
  case "gradient":
309
311
  return mutateStops(value, random, MUTATE.hue, MUTATE.lightness);
@@ -479,7 +481,7 @@ function unlock(options) {
479
481
  }
480
482
 
481
483
  // src/core/variants.ts
482
- function createVariants(schema, id, key, storage, get, set, notify, enabled) {
484
+ function createVariants(schema, id, key, storage, get, set, notify, enabled, seed) {
483
485
  let ready = !1, list = Object.freeze([]);
484
486
  function parse(json) {
485
487
  let data = JSON.parse(json);
@@ -508,7 +510,7 @@ function createVariants(schema, id, key, storage, get, set, notify, enabled) {
508
510
  if (ready || !enabled())
509
511
  return;
510
512
  let json = storage()?.getItem(key);
511
- list = json ? parse(json) : Object.freeze([]), ready = !0;
513
+ list = json ? parse(json) : Object.freeze([...seed?.() ?? []]), ready = !0;
512
514
  }
513
515
  function persist(next) {
514
516
  if (!enabled())
@@ -595,32 +597,69 @@ function defineControls(id, input, options = {}) {
595
597
  let schema = Object.freeze({ ...input }), locked = normalize(schema, {}), actions = Object.freeze([...options.actions ?? []]), { theme, appearance } = options, 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 = () => {
596
598
  for (let cb of [...listeners])
597
599
  cb();
598
- }, 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"), pinnedOf, pinned = () => {
600
+ }, 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({
601
+ preset: null,
602
+ groups: Object.freeze({}),
603
+ scopes: Object.freeze({})
604
+ }), base = NO_BASE, past = [], future = [], HISTORY = 100, stateKey = storageKey(id, "state"), pinnedOf, pinned = () => {
599
605
  if (pinnedOf?.schema !== schema)
600
606
  pinnedOf = { schema, keys: pinnedKeys(schema, options.pinned) };
601
607
  return pinnedOf.keys;
602
- }, unpinned = (values) => {
603
- let keys = pinned();
604
- if (keys.size === 0)
605
- return values;
606
- let out = { ...values };
607
- for (let k of keys)
608
- if (Object.hasOwn(locked, k))
609
- out[k] = locked[k];
610
- return Object.freeze(out);
611
- }, presetPatch = (values) => {
612
- let keys = pinned();
613
- if (keys.size === 0)
614
- return values;
615
- return Object.fromEntries(Object.entries(values).filter(([k]) => !keys.has(k)));
616
- }, buildPresets = () => Object.freeze(Object.fromEntries([
617
- ["default", locked],
618
- ...Object.entries(options.presets ?? {}).map(([id, patch]) => {
619
- if (id === "default" || id === "custom")
620
- throw Error(`Reserved preset id: ${id}`);
621
- return [id, unpinned(normalize(schema, { ...locked, ...patch }))];
622
- })
623
- ])), presets = buildPresets(), buildGroupPresets = () => Object.freeze(Object.fromEntries(Object.entries(options.groupPresets ?? {}).map(([group, list]) => {
608
+ }, variantsChoice = () => variantsOf(schema, (key) => pinned().has(key)), scopingOf, scoping = () => {
609
+ if (scopingOf?.schema === schema)
610
+ return scopingOf;
611
+ let fields = schema, groupTab = /* @__PURE__ */ new Map;
612
+ for (let f of Object.values(fields))
613
+ if (f.group !== void 0 && f.tab !== void 0 && !groupTab.has(f.group))
614
+ groupTab.set(f.group, f.tab);
615
+ let tabOf = (f) => f.tab ?? (f.group !== void 0 ? groupTab.get(f.group) : void 0), named = new Set(Object.keys(options.scopedPresets ?? {}));
616
+ if (named.has(""))
617
+ throw Error("A scope needs a nonempty tab or group id.");
618
+ let v = variantsChoice(), group = v?.field.group, variants = v ? tabOf(v.field) ?? (group !== void 0 && named.has(group) ? group : "") : void 0;
619
+ if (variants)
620
+ named.add(variants);
621
+ let of = /* @__PURE__ */ new Map;
622
+ for (let k of valueKeys(schema)) {
623
+ if (pinned().has(k))
624
+ continue;
625
+ let f = fields[k], tab = tabOf(f);
626
+ of.set(k, tab !== void 0 && named.has(tab) ? tab : f.group !== void 0 && named.has(f.group) ? f.group : "");
627
+ }
628
+ return scopingOf = { schema, of, named: [...named], variants }, scopingOf;
629
+ }, within = (values, scope) => {
630
+ let of = scoping().of, out;
631
+ for (let k of Object.keys(locked))
632
+ if (of.get(k) !== scope && !same(values[k], locked[k]))
633
+ out ??= { ...values }, out[k] = locked[k];
634
+ return out ? Object.freeze(out) : values;
635
+ }, unpinned = (values) => within(values, ""), patchIn = (values, scope) => {
636
+ let of = scoping().of;
637
+ return Object.fromEntries(Object.entries(values).filter(([k]) => of.get(k) === scope));
638
+ }, buildPresets = (scope) => {
639
+ let own = (scope === "" ? options.presets : options.scopedPresets?.[scope]) ?? {}, v = scoping().variants === scope ? variantsChoice() : void 0;
640
+ if (v && Object.hasOwn(own, v.field.value))
641
+ throw Error(`The default variant (${v.field.value}) is the schema's defaults; set its values there.`);
642
+ let ids = [
643
+ ...v ? v.field.options.filter((o) => o !== v.field.value) : [],
644
+ ...Object.keys(own).filter((id) => !v?.field.options.includes(id))
645
+ ];
646
+ return Object.freeze(Object.fromEntries([
647
+ ["default", locked],
648
+ ...ids.map((id) => {
649
+ if (id === "default" || id === "custom")
650
+ throw Error(`Reserved preset id: ${id}`);
651
+ let variant = v?.field.options.includes(id) ? { [v.key]: id } : {};
652
+ return [id, within(normalize(schema, { ...locked, ...variant, ...own[id] }), scope)];
653
+ })
654
+ ]));
655
+ }, buildScopePresets = () => new Map(scoping().named.map((scope) => [scope, buildPresets(scope)])), presets = buildPresets(""), scopePresets = buildScopePresets(), presetsIn = (scope) => {
656
+ if (scope === "")
657
+ return presets;
658
+ let found = scopePresets.get(scope);
659
+ if (!found)
660
+ throw Error(`Unknown preset scope: ${scope}`);
661
+ return found;
662
+ }, buildGroupPresets = () => Object.freeze(Object.fromEntries(Object.entries(options.groupPresets ?? {}).map(([group, list]) => {
624
663
  let named = list.flatMap((p) => Object.keys(p.values).filter((k) => Object.hasOwn(schema, k))), covered = new Set((named.length ? named : Object.keys(schema).filter((k) => schema[k].group === group)).filter((k) => hasValue2(schema[k])));
625
664
  return [
626
665
  group,
@@ -685,22 +724,54 @@ function defineControls(id, input, options = {}) {
685
724
  function commit(next) {
686
725
  current = next, persist(), notify();
687
726
  }
688
- 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);
727
+ let makeBase = (preset, groups, scopes = {}) => preset === null && Object.keys(groups).length === 0 && Object.keys(scopes).length === 0 ? NO_BASE : Object.freeze({
728
+ preset,
729
+ groups: Object.freeze({ ...groups }),
730
+ scopes: Object.freeze({ ...scopes })
731
+ }), withScope = (scopes, scope, ref) => {
732
+ let { [scope]: _, ...others } = scopes;
733
+ return ref ? { ...others, [scope]: ref } : others;
734
+ }, sameRef = (a, b) => a?.kind === b?.kind && a?.id === b?.id, sameBase = (a, b) => a === b || sameRef(a.preset, b.preset) && Object.keys(a.groups).length === Object.keys(b.groups).length && Object.entries(a.groups).every(([g, i]) => b.groups[g] === i) && Object.keys(a.scopes).length === Object.keys(b.scopes).length && Object.entries(a.scopes).every(([s, ref]) => sameRef(ref, b.scopes[s])), seedsScopes = () => scopePresets.size > 0 && Object.keys(options.presets ?? {}).length === 0, groupsOutside = (groups, scope) => {
735
+ let of = scoping().of;
736
+ return Object.fromEntries(Object.entries(groups).filter(([g]) => !(groupPresets[g] ?? []).some((p) => Object.keys(p.values).some((k) => of.get(k) === scope))));
737
+ }, known = (ref, scope) => ref.kind === "variant" || ref.id !== "default" && Object.hasOwn(scopePresets.get(scope) ?? {}, ref.id);
689
738
  function validBase(b) {
690
- 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);
739
+ 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)), scopes = Object.fromEntries(Object.entries(b.scopes).filter(([s, ref]) => scopePresets.has(s) && known(ref, s))), next = makeBase(preset, groups, scopes);
691
740
  return sameBase(next, b) ? b : next;
692
741
  }
742
+ let readRef = (raw) => raw && typeof raw === "object" && (raw.kind === "preset" || raw.kind === "variant") && typeof raw.id === "string" ? Object.freeze({ kind: raw.kind, id: raw.id }) : null;
693
743
  function readBase(raw) {
694
744
  if (!raw || typeof raw !== "object")
695
745
  return NO_BASE;
696
- 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]))) : {};
697
- return validBase(makeBase(ref, byGroup));
746
+ let { preset, groups, scopes } = raw, ref = readRef(preset), byGroup = groups && typeof groups === "object" ? Object.fromEntries(Object.entries(groups).filter((e) => Number.isInteger(e[1]))) : {}, byScope = {};
747
+ if (scopes && typeof scopes === "object")
748
+ for (let [s, r] of Object.entries(scopes)) {
749
+ let found = readRef(r);
750
+ if (found)
751
+ byScope[s] = found;
752
+ }
753
+ if (ref?.kind === "preset" && !Object.hasOwn(presets, ref.id)) {
754
+ for (let [s, list] of scopePresets)
755
+ if (!byScope[s] && ref.id !== "default" && Object.hasOwn(list, ref.id))
756
+ byScope[s] = ref;
757
+ ref = null;
758
+ } else if (ref?.kind === "variant" && seedsScopes()) {
759
+ let id = ref.id;
760
+ for (let s of scopePresets.keys())
761
+ if (!byScope[s] && scopeVariants(s).list().some((v) => v.id === id))
762
+ byScope[s] = ref;
763
+ ref = null;
764
+ }
765
+ return validBase(makeBase(ref, byGroup, byScope));
698
766
  }
699
767
  function activeBase() {
700
768
  load();
701
- let ref = base.preset;
702
- if (ref?.kind === "variant" && !variants.list().some((v) => v.id === ref.id))
703
- base = makeBase(null, base.groups);
769
+ let gone = (ref, list) => ref?.kind === "variant" && !list().some((v) => v.id === ref.id), preset = gone(base.preset, () => variants.list()) ? null : base.preset, scopes = base.scopes;
770
+ for (let [s, ref] of Object.entries(base.scopes))
771
+ if (gone(ref, () => scopeVariants(s).list()))
772
+ scopes = withScope(scopes, s, void 0);
773
+ if (preset !== base.preset || scopes !== base.scopes)
774
+ base = makeBase(preset, base.groups, scopes);
704
775
  return base;
705
776
  }
706
777
  let hasBase = () => activeBase() !== NO_BASE, baseCache;
@@ -710,17 +781,23 @@ function defineControls(id, input, options = {}) {
710
781
  let b = activeBase();
711
782
  if (b === NO_BASE)
712
783
  return locked;
713
- let list = b.preset?.kind === "variant" ? variants.list() : null, c = baseCache;
714
- if (c && c.base === b && c.schema === schema && c.presets === presets && c.groupPresets === groupPresets && c.variants === list)
784
+ let lists = [
785
+ b.preset?.kind === "variant" ? variants.list() : null,
786
+ ...Object.entries(b.scopes).map(([s, ref]) => ref.kind === "variant" ? scopeVariants(s).list() : null)
787
+ ], c = baseCache;
788
+ if (c && c.base === b && c.schema === schema && c.presets === presets && c.scopePresets === scopePresets && c.groupPresets === groupPresets && c.variants.length === lists.length && c.variants.every((l, i) => l === lists[i]))
715
789
  return c.values;
716
- let out = locked, ref = b.preset;
717
- if (ref?.kind === "preset" && Object.hasOwn(presets, ref.id))
718
- out = presets[ref.id];
719
- else if (ref?.kind === "variant") {
790
+ let valuesOf = (ref, scope, list) => {
791
+ if (ref.kind === "preset")
792
+ return presetsIn(scope)[ref.id];
720
793
  let found = list?.find((v) => v.id === ref.id);
721
- if (found)
722
- out = unpinned(normalize(schema, found.values));
723
- }
794
+ return found ? within(normalize(schema, found.values), scope) : void 0;
795
+ }, out = locked;
796
+ if (b.preset)
797
+ out = valuesOf(b.preset, "", lists[0]) ?? locked;
798
+ let scoped = Object.entries(b.scopes);
799
+ if (scoped.length)
800
+ out = { ...out }, scoped.forEach(([s, ref], i) => Object.assign(out, patchIn(valuesOf(ref, s, lists[i + 1]) ?? locked, s)));
724
801
  let groups = Object.entries(b.groups);
725
802
  if (groups.length) {
726
803
  out = { ...out };
@@ -728,13 +805,16 @@ function defineControls(id, input, options = {}) {
728
805
  Object.assign(out, groupPresets[g]?.[i]?.values);
729
806
  }
730
807
  let values = Object.freeze(out);
731
- return baseCache = { base: b, schema, presets, groupPresets, variants: list, values }, values;
808
+ return baseCache = { base: b, schema, presets, scopePresets, groupPresets, variants: lists, values }, values;
732
809
  }
733
810
  let covered = (key) => {
734
811
  let b = activeBase(), group = schema[key]?.group;
735
812
  if (group !== void 0 && Object.hasOwn(b.groups, group))
736
813
  return !0;
737
- return b.preset !== null && !pinned().has(key);
814
+ let scope = scoping().of.get(key);
815
+ if (scope === void 0)
816
+ return !1;
817
+ return scope === "" ? b.preset !== null : Object.hasOwn(b.scopes, scope);
738
818
  };
739
819
  function declaredShortcut(id) {
740
820
  let slash = id.indexOf("/"), key = slash < 0 ? id : id.slice(0, slash), field = Object.hasOwn(schema, key) ? schema[key] : void 0;
@@ -969,7 +1049,7 @@ function defineControls(id, input, options = {}) {
969
1049
  schema = Object.freeze({ ...next });
970
1050
  if (changed) {
971
1051
  let previous = load();
972
- schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets(), base = validBase(base);
1052
+ schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(""), scopePresets = buildScopePresets(), groupPresets = buildGroupPresets(), base = validBase(base);
973
1053
  for (let k of [...locks])
974
1054
  if (!valueField(k))
975
1055
  locks.delete(k);
@@ -1004,7 +1084,33 @@ function defineControls(id, input, options = {}) {
1004
1084
  listen(cb) {
1005
1085
  return readoutListeners.add(cb), () => readoutListeners.delete(cb);
1006
1086
  }
1007
- }, variants = createVariants(() => schema, id, storageKey(id, "variants"), variantStorage, () => unpinned(get()), (v, variant, coalesce) => write(presetPatch(v), { source: "variant", coalesce }, makeBase(Object.freeze({ kind: "variant", id: variant }), {})), notify, enabled), resettable = (keys) => (keys ?? fieldKeys()).filter((k) => valueField(k) && !blocked(k));
1087
+ }, variants = createVariants(() => schema, id, storageKey(id, "variants"), variantStorage, () => unpinned(get()), (v, variant, coalesce) => write(patchIn(v, ""), { source: "variant", coalesce }, makeBase(Object.freeze({ kind: "variant", id: variant }), {}, activeBase().scopes)), notify, enabled), scopeVariantsMade = /* @__PURE__ */ new Map;
1088
+ function scopeVariants(scope) {
1089
+ let made = scopeVariantsMade.get(scope);
1090
+ if (made)
1091
+ return made;
1092
+ return made = createVariants(() => schema, id, storageKey(id, `variants:${scope}`), variantStorage, () => within(get(), scope), (v, variant, coalesce) => {
1093
+ let b = activeBase();
1094
+ write(patchIn(v, scope), { source: "variant", coalesce }, makeBase(b.preset, groupsOutside(b.groups, scope), withScope(b.scopes, scope, Object.freeze({ kind: "variant", id: variant }))));
1095
+ }, notify, enabled, () => !seedsScopes() ? [] : variants.list().flatMap((v) => {
1096
+ let values = within(normalize(schema, v.values), scope);
1097
+ return equal(values, locked) ? [] : [{ ...v, values }];
1098
+ })), scopeVariantsMade.set(scope, made), made;
1099
+ }
1100
+ let scopesOf, scopes = () => {
1101
+ if (scopesOf?.presets === scopePresets)
1102
+ return scopesOf.value;
1103
+ let of = scoping().of, value = Object.freeze(Object.fromEntries([...scopePresets].map(([scope, list]) => [
1104
+ scope,
1105
+ Object.freeze({
1106
+ id: scope,
1107
+ keys: Object.freeze([...of].flatMap(([k, s]) => s === scope ? [k] : [])),
1108
+ presets: list,
1109
+ variants: scopeVariants(scope)
1110
+ })
1111
+ ])));
1112
+ return scopesOf = { presets: scopePresets, value }, value;
1113
+ }, resettable = (keys) => (keys ?? fieldKeys()).filter((k) => valueField(k) && !blocked(k));
1008
1114
  function offBase(keys) {
1009
1115
  if (!hasBase())
1010
1116
  return !1;
@@ -1068,6 +1174,10 @@ function defineControls(id, input, options = {}) {
1068
1174
  get presets() {
1069
1175
  return presets;
1070
1176
  },
1177
+ get scopes() {
1178
+ return scopes();
1179
+ },
1180
+ scopeOf: (key) => scoping().of.get(key),
1071
1181
  actions,
1072
1182
  theme,
1073
1183
  appearance,
@@ -1088,7 +1198,10 @@ function defineControls(id, input, options = {}) {
1088
1198
  sectionDescription: (section) => options.sectionDescriptions?.[section] ?? fieldLabels().sectionText.get(section),
1089
1199
  groupFolded: options.groupFolded,
1090
1200
  sectionFolded: options.sectionFolded,
1091
- presetLabel: (presetId) => options.presetLabels?.[presetId] ?? (presetId === "default" ? options.defaultLabel : void 0) ?? presetId,
1201
+ presetLabel: (presetId, scope = "") => {
1202
+ let v = scoping().variants === scope ? variantsChoice() : void 0, option = presetId === "default" ? v?.field.value : presetId;
1203
+ return options.presetLabels?.[presetId] ?? (presetId === "default" ? options.defaultLabel : void 0) ?? (v && option !== void 0 && v.field.options.includes(option) ? v.field.labels?.[option] ?? option : presetId);
1204
+ },
1092
1205
  isPinned: (key) => pinned().has(key),
1093
1206
  get,
1094
1207
  set,
@@ -1217,7 +1330,7 @@ function defineControls(id, input, options = {}) {
1217
1330
  options.onPreset?.({ group, index, name: preset.name });
1218
1331
  return;
1219
1332
  }
1220
- let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others);
1333
+ let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others, b.scopes);
1221
1334
  if (open.length < keys.length)
1222
1335
  return toDefaults(open, forget);
1223
1336
  let patch = {};
@@ -1362,13 +1475,15 @@ function defineControls(id, input, options = {}) {
1362
1475
  comparing = before, options.onChange?.(changes(now, before), before, { source: "compare" }), notify();
1363
1476
  },
1364
1477
  preset(id, presetOptions) {
1365
- if (!Object.hasOwn(presets, id))
1478
+ let scope = presetOptions?.scope ?? "", list = presetsIn(scope);
1479
+ if (!Object.hasOwn(list, id))
1366
1480
  throw Error(`Unknown preset: ${id}`);
1367
- write(presetPatch(presets[id]), { source: "preset", coalesce: presetOptions?.coalesce }, id === "default" ? NO_BASE : makeBase(Object.freeze({ kind: "preset", id }), {}));
1481
+ let b = activeBase(), ref = id === "default" ? void 0 : Object.freeze({ kind: "preset", id });
1482
+ write(patchIn(list[id], scope), { source: "preset", coalesce: presetOptions?.coalesce }, scope === "" ? makeBase(ref ?? null, {}, b.scopes) : makeBase(b.preset, groupsOutside(b.groups, scope), withScope(b.scopes, scope, ref)));
1368
1483
  },
1369
- matchingPreset: () => {
1370
- let cur = unpinned(get());
1371
- return Object.keys(presets).find((id) => equal(cur, presets[id])) ?? "custom";
1484
+ matchingPreset: (scope = "") => {
1485
+ let list = presetsIn(scope), cur = within(get(), scope);
1486
+ return Object.keys(list).find((id) => equal(cur, list[id])) ?? "custom";
1372
1487
  },
1373
1488
  get groupPresets() {
1374
1489
  return groupPresets;
@@ -1380,12 +1495,13 @@ function defineControls(id, input, options = {}) {
1380
1495
  if (!enabled())
1381
1496
  return;
1382
1497
  let b = activeBase();
1383
- write(preset.values, { source: "preset", group, coalesce: presetOptions?.coalesce }, makeBase(b.preset, { ...b.groups, [group]: index })), options.onPreset?.({ group, index, name: preset.name });
1498
+ write(preset.values, { source: "preset", group, coalesce: presetOptions?.coalesce }, makeBase(b.preset, { ...b.groups, [group]: index }, b.scopes)), options.onPreset?.({ group, index, name: preset.name });
1384
1499
  },
1385
- activePreset() {
1500
+ activePreset(scope) {
1386
1501
  if (!enabled())
1387
1502
  return null;
1388
- return activeBase().preset;
1503
+ let b = activeBase();
1504
+ return scope ? b.scopes[scope] ?? null : b.preset;
1389
1505
  },
1390
1506
  activeGroupPreset(group) {
1391
1507
  if (!enabled())
@@ -1400,11 +1516,11 @@ function defineControls(id, input, options = {}) {
1400
1516
  code: (format, values) => formatCode(values ?? get(), format),
1401
1517
  variants,
1402
1518
  attach(element, chip) {
1403
- let load = options.ship ? () => options.ship().then((m) => m.attach) : () => (__preload("75gbzbyd"), import("./chunk-75gbzbyd.js")).then((m) => m.attach);
1519
+ let load = options.ship ? () => options.ship().then((m) => m.attach) : () => import("./chunk-44r02asc.js").then((m) => m.attach);
1404
1520
  return live(load, (attach) => attach(controls, element, chip), (detach) => detach());
1405
1521
  },
1406
1522
  mount(container, mountOptions) {
1407
- let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => (__preload("bnhzf1tj"), import("./chunk-bnhzf1tj.js")).then((m) => m.mountPanel);
1523
+ let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => import("./chunk-mbhy4jg5.js").then((m) => m.mountPanel);
1408
1524
  return live(load, (mountPanel) => {
1409
1525
  let panel = mountPanel(controls, container, mountOptions);
1410
1526
  return mountOptions?.onReady?.(panel), panel;
@@ -1441,7 +1557,7 @@ function descriptorToField(d) {
1441
1557
  if (readoutDescriptor(d))
1442
1558
  return readoutField(d);
1443
1559
  if (d.kind === "toolbar")
1444
- return toolbar2(d.items.map(({ key, ...item }) => ({ ...item, id: key })), meta);
1560
+ return toolbar2(d.items.map(({ key, ...item }) => ({ ...item, id: key })), d.labels !== void 0 ? { ...meta, labels: d.labels } : meta);
1445
1561
  if (d.bind)
1446
1562
  return flatSpring2({}, { ...meta, id: d.key }).duration;
1447
1563
  if (d.kind === "knob" || d.kind === "number") {
@@ -1516,6 +1632,12 @@ function descriptorToField(d) {
1516
1632
  });
1517
1633
  if (d.kind === "keybind")
1518
1634
  return keybind2(typeof d.default === "string" ? d.default : "", meta);
1635
+ if (d.kind === "text")
1636
+ return text2(typeof d.default === "string" ? d.default : "", {
1637
+ ...d.multiline ? { multiline: !0 } : {},
1638
+ ...d.placeholder ? { placeholder: d.placeholder } : {},
1639
+ ...meta
1640
+ });
1519
1641
  if (d.kind === "gradient") {
1520
1642
  let fallback = [
1521
1643
  { at: 0, color: "#000000" },
@@ -1594,7 +1716,7 @@ var decimal = (n) => String(Math.round(n * 1e4) / 1e4), swiftLiteral = (d, v) =>
1594
1716
  let [a, b] = v;
1595
1717
  return `${decimal(a)}...${decimal(b)}`;
1596
1718
  }
1597
- if (d.kind === "keybind")
1719
+ if (d.kind === "keybind" || d.kind === "text")
1598
1720
  return JSON.stringify(v);
1599
1721
  if (d.kind === "gradient")
1600
1722
  return `Gradient(stops: [${(Array.isArray(v) ? v : []).map((s) => {
@@ -1623,6 +1745,7 @@ var decimal = (n) => String(Math.round(n * 1e4) / 1e4), swiftLiteral = (d, v) =>
1623
1745
  range: "ClosedRange<Double>",
1624
1746
  seed: "Int",
1625
1747
  keybind: "String",
1748
+ text: "String",
1626
1749
  gradient: "Gradient",
1627
1750
  curve: "[CGPoint]"
1628
1751
  };
@@ -1696,6 +1819,7 @@ function createRemoteControls(id, descriptors, options = {}) {
1696
1819
  tunable: options.tunable,
1697
1820
  history: options.history,
1698
1821
  presets: options.presets,
1822
+ scopedPresets: options.scopedPresets,
1699
1823
  pinned: options.pinned,
1700
1824
  groupPresets: options.groupPresets,
1701
1825
  onPreset: options.onPreset,
@@ -1832,6 +1956,7 @@ export {
1832
1956
  springCss2 as springCss,
1833
1957
  springMotion2 as springMotion,
1834
1958
  table2 as table,
1959
+ text2 as text,
1835
1960
  toggle2 as toggle,
1836
1961
  toolbar2 as toolbar,
1837
1962
  toolbarShortcut2 as toolbarShortcut,