@kitlangton/knobs 0.4.0-next.12 → 0.4.0-next.14

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.
@@ -496,6 +496,7 @@ var META_KEYS = [
496
496
  "sectionFolded",
497
497
  "tab",
498
498
  "pinned",
499
+ "inPresets",
499
500
  "subsection"
500
501
  ];
501
502
  function pickMeta(source, skip = []) {
@@ -529,6 +530,13 @@ function pinnedKeys(schema, groups = []) {
529
530
  out.add(key);
530
531
  return out;
531
532
  }
533
+ function presetFreeKeys(schema, pinned, groups = {}) {
534
+ let out = new Set(pinned);
535
+ for (let [key, f] of Object.entries(schema))
536
+ if (f.inPresets === !1 || f.group !== void 0 && groups[f.group] === !1)
537
+ out.add(key);
538
+ return out;
539
+ }
532
540
  var SPRING2 = {
533
541
  duration: { min: 0.05, max: 2, step: 0.01 },
534
542
  bounce: { min: -0.5, max: 1, step: 0.01 }
@@ -1177,4 +1185,4 @@ function urlFlag2(name) {
1177
1185
  }
1178
1186
  var storageKey = (id, part) => `knobs:${encodeURIComponent(id)}:${part}:v1`;
1179
1187
 
1180
- export { maxChroma, oklchToRgb, parseColor2, fitColor, formatColor, colorHex2, EASINGS2, EASING_Y, easingName, bezierPoint2, bezierCss2, normalizeCombo2, letterOf2, comboFromEvent2, heldMods, matchesCombo2, comboParts2, comboLabel2, isTypingTarget, GRADIENT_SAMPLES, sampleGradient2, gradientSamples, gradientCss2, stopColorAt, sampleCurve2, curveSamples, CURVE_SHAPES2, inRange, sameRamp, randomStops, mutateStops, randomPoints, mutatePoints, pickMeta, isReadout2, hasValue2, variantsOf, pinnedKeys, SPRING2, valueKeys, knob2, choice2, action2, flatSpring2, toggle2, spring2, color2, point2, easing2, vec22, vec32, range2, angle2, seed2, keybind2, text2, gradient2, curve2, toolbarShortcut2, actionShortcut2, toolbar2, watch2, sparkline2, graph2, meter2, table2, log2, wrapAngle2, normalizeField, normalize, isRecord, same, equal, Spring, springMotion2, springResponse, springEasing, springCss2, SPRINGS2, FADE, MOTION, reducedMotion, reducedSpring2, springLinear, DEFAULT_LINEAR, motionCss, RESHAPE, RESET_KEYS, REFRESHES, readoutState, pushReadout, READOUT, memoryStorage2, browserStorage, urlFlag2, storageKey };
1188
+ export { maxChroma, oklchToRgb, parseColor2, fitColor, formatColor, colorHex2, EASINGS2, EASING_Y, easingName, bezierPoint2, bezierCss2, normalizeCombo2, letterOf2, comboFromEvent2, heldMods, matchesCombo2, comboParts2, comboLabel2, isTypingTarget, GRADIENT_SAMPLES, sampleGradient2, gradientSamples, gradientCss2, stopColorAt, sampleCurve2, curveSamples, CURVE_SHAPES2, inRange, sameRamp, randomStops, mutateStops, randomPoints, mutatePoints, pickMeta, isReadout2, hasValue2, variantsOf, pinnedKeys, presetFreeKeys, SPRING2, valueKeys, knob2, choice2, action2, flatSpring2, toggle2, spring2, color2, point2, easing2, vec22, vec32, range2, angle2, seed2, keybind2, text2, gradient2, curve2, toolbarShortcut2, actionShortcut2, toolbar2, watch2, sparkline2, graph2, meter2, table2, log2, wrapAngle2, normalizeField, normalize, isRecord, same, equal, Spring, springMotion2, springResponse, springEasing, springCss2, SPRINGS2, FADE, MOTION, reducedMotion, reducedSpring2, springLinear, DEFAULT_LINEAR, motionCss, RESHAPE, RESET_KEYS, REFRESHES, readoutState, pushReadout, READOUT, memoryStorage2, browserStorage, urlFlag2, storageKey };
package/dist/dev/index.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  hasValue2,
28
28
  variantsOf,
29
29
  pinnedKeys,
30
+ presetFreeKeys,
30
31
  SPRING2,
31
32
  valueKeys,
32
33
  knob2,
@@ -76,7 +77,7 @@ import {
76
77
  browserStorage,
77
78
  urlFlag2,
78
79
  storageKey
79
- } from "./chunk-7kns3qe6.js";
80
+ } from "./chunk-v2g91mrm.js";
80
81
  // src/core/random.ts
81
82
  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;
82
83
  function pick(field, random) {
@@ -481,7 +482,7 @@ function unlock(options) {
481
482
  }
482
483
 
483
484
  // src/core/variants.ts
484
- function createVariants(schema, id, key, storage, get, set, notify, enabled) {
485
+ function createVariants(schema, id, key, storage, get, set, notify, enabled, seed) {
485
486
  let ready = !1, list = Object.freeze([]);
486
487
  function parse(json) {
487
488
  let data = JSON.parse(json);
@@ -510,7 +511,7 @@ function createVariants(schema, id, key, storage, get, set, notify, enabled) {
510
511
  if (ready || !enabled())
511
512
  return;
512
513
  let json = storage()?.getItem(key);
513
- list = json ? parse(json) : Object.freeze([]), ready = !0;
514
+ list = json ? parse(json) : Object.freeze([...seed?.() ?? []]), ready = !0;
514
515
  }
515
516
  function persist(next) {
516
517
  if (!enabled())
@@ -575,7 +576,7 @@ function createVariants(schema, id, key, storage, get, set, notify, enabled) {
575
576
  }
576
577
 
577
578
  // src/core/store.ts
578
- var devBuild = () => !0;
579
+ var devBuild = () => !0, defaultLabelOf = (label, scope) => typeof label === "object" ? label[scope] : label;
579
580
  function sameField(a, b) {
580
581
  if (a === b)
581
582
  return !0;
@@ -597,26 +598,50 @@ function defineControls(id, input, options = {}) {
597
598
  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 = () => {
598
599
  for (let cb of [...listeners])
599
600
  cb();
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({ preset: null, groups: Object.freeze({}) }), base = NO_BASE, past = [], future = [], HISTORY = 100, stateKey = storageKey(id, "state"), pinnedOf, pinned = () => {
601
+ }, 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({
602
+ preset: null,
603
+ groups: Object.freeze({}),
604
+ scopes: Object.freeze({})
605
+ }), base = NO_BASE, past = [], future = [], HISTORY = 100, stateKey = storageKey(id, "state"), pinnedOf, pinned = () => {
601
606
  if (pinnedOf?.schema !== schema)
602
607
  pinnedOf = { schema, keys: pinnedKeys(schema, options.pinned) };
603
608
  return pinnedOf.keys;
604
- }, variantsChoice = () => variantsOf(schema, (key) => pinned().has(key)), unpinned = (values) => {
605
- let keys = pinned();
606
- if (keys.size === 0)
607
- return values;
608
- let out = { ...values };
609
- for (let k of keys)
610
- if (Object.hasOwn(locked, k))
611
- out[k] = locked[k];
612
- return Object.freeze(out);
613
- }, presetPatch = (values) => {
614
- let keys = pinned();
615
- if (keys.size === 0)
616
- return values;
617
- return Object.fromEntries(Object.entries(values).filter(([k]) => !keys.has(k)));
618
- }, buildPresets = () => {
619
- let own = options.presets ?? {}, v = variantsChoice();
609
+ }, freeOf, presetFree = () => {
610
+ if (freeOf?.schema !== schema)
611
+ freeOf = { schema, keys: presetFreeKeys(schema, pinned(), options.inPresets) };
612
+ return freeOf.keys;
613
+ }, variantsChoice = () => variantsOf(schema, (key) => presetFree().has(key)), scopingOf, scoping = () => {
614
+ if (scopingOf?.schema === schema)
615
+ return scopingOf;
616
+ let fields = schema, groupTab = /* @__PURE__ */ new Map;
617
+ for (let f of Object.values(fields))
618
+ if (f.group !== void 0 && f.tab !== void 0 && !groupTab.has(f.group))
619
+ groupTab.set(f.group, f.tab);
620
+ let tabOf = (f) => f.tab ?? (f.group !== void 0 ? groupTab.get(f.group) : void 0), named = new Set(Object.keys(options.scopedPresets ?? {}));
621
+ if (named.has(""))
622
+ throw Error("A scope needs a nonempty tab or group id.");
623
+ let v = variantsChoice(), group = v?.field.group, variants = v ? tabOf(v.field) ?? (group !== void 0 && named.has(group) ? group : "") : void 0;
624
+ if (variants)
625
+ named.add(variants);
626
+ let of = /* @__PURE__ */ new Map;
627
+ for (let k of valueKeys(schema)) {
628
+ if (presetFree().has(k))
629
+ continue;
630
+ let f = fields[k], tab = tabOf(f);
631
+ of.set(k, tab !== void 0 && named.has(tab) ? tab : f.group !== void 0 && named.has(f.group) ? f.group : "");
632
+ }
633
+ return scopingOf = { schema, of, named: [...named], variants }, scopingOf;
634
+ }, within = (values, scope) => {
635
+ let of = scoping().of, out;
636
+ for (let k of Object.keys(locked))
637
+ if (of.get(k) !== scope && !same(values[k], locked[k]))
638
+ out ??= { ...values }, out[k] = locked[k];
639
+ return out ? Object.freeze(out) : values;
640
+ }, unpinned = (values) => within(values, ""), patchIn = (values, scope) => {
641
+ let of = scoping().of;
642
+ return Object.fromEntries(Object.entries(values).filter(([k]) => of.get(k) === scope));
643
+ }, buildPresets = (scope) => {
644
+ let own = (scope === "" ? options.presets : options.scopedPresets?.[scope]) ?? {}, v = scoping().variants === scope ? variantsChoice() : void 0;
620
645
  if (v && Object.hasOwn(own, v.field.value))
621
646
  throw Error(`The default variant (${v.field.value}) is the schema's defaults; set its values there.`);
622
647
  let ids = [
@@ -629,10 +654,17 @@ function defineControls(id, input, options = {}) {
629
654
  if (id === "default" || id === "custom")
630
655
  throw Error(`Reserved preset id: ${id}`);
631
656
  let variant = v?.field.options.includes(id) ? { [v.key]: id } : {};
632
- return [id, unpinned(normalize(schema, { ...locked, ...variant, ...own[id] }))];
657
+ return [id, within(normalize(schema, { ...locked, ...variant, ...own[id] }), scope)];
633
658
  })
634
659
  ]));
635
- }, presets = buildPresets(), buildGroupPresets = () => Object.freeze(Object.fromEntries(Object.entries(options.groupPresets ?? {}).map(([group, list]) => {
660
+ }, buildScopePresets = () => new Map(scoping().named.map((scope) => [scope, buildPresets(scope)])), presets = buildPresets(""), scopePresets = buildScopePresets(), presetsIn = (scope) => {
661
+ if (scope === "")
662
+ return presets;
663
+ let found = scopePresets.get(scope);
664
+ if (!found)
665
+ throw Error(`Unknown preset scope: ${scope}`);
666
+ return found;
667
+ }, buildGroupPresets = () => Object.freeze(Object.fromEntries(Object.entries(options.groupPresets ?? {}).map(([group, list]) => {
636
668
  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])));
637
669
  return [
638
670
  group,
@@ -697,22 +729,54 @@ function defineControls(id, input, options = {}) {
697
729
  function commit(next) {
698
730
  current = next, persist(), notify();
699
731
  }
700
- 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);
732
+ let makeBase = (preset, groups, scopes = {}) => preset === null && Object.keys(groups).length === 0 && Object.keys(scopes).length === 0 ? NO_BASE : Object.freeze({
733
+ preset,
734
+ groups: Object.freeze({ ...groups }),
735
+ scopes: Object.freeze({ ...scopes })
736
+ }), withScope = (scopes, scope, ref) => {
737
+ let { [scope]: _, ...others } = scopes;
738
+ return ref ? { ...others, [scope]: ref } : others;
739
+ }, 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) => {
740
+ let of = scoping().of;
741
+ return Object.fromEntries(Object.entries(groups).filter(([g]) => !(groupPresets[g] ?? []).some((p) => Object.keys(p.values).some((k) => of.get(k) === scope))));
742
+ }, known = (ref, scope) => ref.kind === "variant" || ref.id !== "default" && Object.hasOwn(scopePresets.get(scope) ?? {}, ref.id);
701
743
  function validBase(b) {
702
- 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);
744
+ 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);
703
745
  return sameBase(next, b) ? b : next;
704
746
  }
747
+ 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;
705
748
  function readBase(raw) {
706
749
  if (!raw || typeof raw !== "object")
707
750
  return NO_BASE;
708
- 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]))) : {};
709
- return validBase(makeBase(ref, byGroup));
751
+ 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 = {};
752
+ if (scopes && typeof scopes === "object")
753
+ for (let [s, r] of Object.entries(scopes)) {
754
+ let found = readRef(r);
755
+ if (found)
756
+ byScope[s] = found;
757
+ }
758
+ if (ref?.kind === "preset" && !Object.hasOwn(presets, ref.id)) {
759
+ for (let [s, list] of scopePresets)
760
+ if (!byScope[s] && ref.id !== "default" && Object.hasOwn(list, ref.id))
761
+ byScope[s] = ref;
762
+ ref = null;
763
+ } else if (ref?.kind === "variant" && seedsScopes()) {
764
+ let id = ref.id;
765
+ for (let s of scopePresets.keys())
766
+ if (!byScope[s] && scopeVariants(s).list().some((v) => v.id === id))
767
+ byScope[s] = ref;
768
+ ref = null;
769
+ }
770
+ return validBase(makeBase(ref, byGroup, byScope));
710
771
  }
711
772
  function activeBase() {
712
773
  load();
713
- let ref = base.preset;
714
- if (ref?.kind === "variant" && !variants.list().some((v) => v.id === ref.id))
715
- base = makeBase(null, base.groups);
774
+ 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;
775
+ for (let [s, ref] of Object.entries(base.scopes))
776
+ if (gone(ref, () => scopeVariants(s).list()))
777
+ scopes = withScope(scopes, s, void 0);
778
+ if (preset !== base.preset || scopes !== base.scopes)
779
+ base = makeBase(preset, base.groups, scopes);
716
780
  return base;
717
781
  }
718
782
  let hasBase = () => activeBase() !== NO_BASE, baseCache;
@@ -722,17 +786,23 @@ function defineControls(id, input, options = {}) {
722
786
  let b = activeBase();
723
787
  if (b === NO_BASE)
724
788
  return locked;
725
- let list = b.preset?.kind === "variant" ? variants.list() : null, c = baseCache;
726
- if (c && c.base === b && c.schema === schema && c.presets === presets && c.groupPresets === groupPresets && c.variants === list)
789
+ let lists = [
790
+ b.preset?.kind === "variant" ? variants.list() : null,
791
+ ...Object.entries(b.scopes).map(([s, ref]) => ref.kind === "variant" ? scopeVariants(s).list() : null)
792
+ ], c = baseCache;
793
+ 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]))
727
794
  return c.values;
728
- let out = locked, ref = b.preset;
729
- if (ref?.kind === "preset" && Object.hasOwn(presets, ref.id))
730
- out = presets[ref.id];
731
- else if (ref?.kind === "variant") {
795
+ let valuesOf = (ref, scope, list) => {
796
+ if (ref.kind === "preset")
797
+ return presetsIn(scope)[ref.id];
732
798
  let found = list?.find((v) => v.id === ref.id);
733
- if (found)
734
- out = unpinned(normalize(schema, found.values));
735
- }
799
+ return found ? within(normalize(schema, found.values), scope) : void 0;
800
+ }, out = locked;
801
+ if (b.preset)
802
+ out = valuesOf(b.preset, "", lists[0]) ?? locked;
803
+ let scoped = Object.entries(b.scopes);
804
+ if (scoped.length)
805
+ out = { ...out }, scoped.forEach(([s, ref], i) => Object.assign(out, patchIn(valuesOf(ref, s, lists[i + 1]) ?? locked, s)));
736
806
  let groups = Object.entries(b.groups);
737
807
  if (groups.length) {
738
808
  out = { ...out };
@@ -740,13 +810,16 @@ function defineControls(id, input, options = {}) {
740
810
  Object.assign(out, groupPresets[g]?.[i]?.values);
741
811
  }
742
812
  let values = Object.freeze(out);
743
- return baseCache = { base: b, schema, presets, groupPresets, variants: list, values }, values;
813
+ return baseCache = { base: b, schema, presets, scopePresets, groupPresets, variants: lists, values }, values;
744
814
  }
745
815
  let covered = (key) => {
746
816
  let b = activeBase(), group = schema[key]?.group;
747
817
  if (group !== void 0 && Object.hasOwn(b.groups, group))
748
818
  return !0;
749
- return b.preset !== null && !pinned().has(key);
819
+ let scope = scoping().of.get(key);
820
+ if (scope === void 0)
821
+ return !1;
822
+ return scope === "" ? b.preset !== null : Object.hasOwn(b.scopes, scope);
750
823
  };
751
824
  function declaredShortcut(id) {
752
825
  let slash = id.indexOf("/"), key = slash < 0 ? id : id.slice(0, slash), field = Object.hasOwn(schema, key) ? schema[key] : void 0;
@@ -981,7 +1054,7 @@ function defineControls(id, input, options = {}) {
981
1054
  schema = Object.freeze({ ...next });
982
1055
  if (changed) {
983
1056
  let previous = load();
984
- schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(), groupPresets = buildGroupPresets(), base = validBase(base);
1057
+ schema = Object.freeze({ ...next }), locked = normalize(schema, {}), presets = buildPresets(""), scopePresets = buildScopePresets(), groupPresets = buildGroupPresets(), base = validBase(base);
985
1058
  for (let k of [...locks])
986
1059
  if (!valueField(k))
987
1060
  locks.delete(k);
@@ -1016,7 +1089,33 @@ function defineControls(id, input, options = {}) {
1016
1089
  listen(cb) {
1017
1090
  return readoutListeners.add(cb), () => readoutListeners.delete(cb);
1018
1091
  }
1019
- }, 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));
1092
+ }, 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;
1093
+ function scopeVariants(scope) {
1094
+ let made = scopeVariantsMade.get(scope);
1095
+ if (made)
1096
+ return made;
1097
+ return made = createVariants(() => schema, id, storageKey(id, `variants:${scope}`), variantStorage, () => within(get(), scope), (v, variant, coalesce) => {
1098
+ let b = activeBase();
1099
+ write(patchIn(v, scope), { source: "variant", coalesce }, makeBase(b.preset, groupsOutside(b.groups, scope), withScope(b.scopes, scope, Object.freeze({ kind: "variant", id: variant }))));
1100
+ }, notify, enabled, () => !seedsScopes() ? [] : variants.list().flatMap((v) => {
1101
+ let values = within(normalize(schema, v.values), scope);
1102
+ return equal(values, locked) ? [] : [{ ...v, values }];
1103
+ })), scopeVariantsMade.set(scope, made), made;
1104
+ }
1105
+ let scopesOf, scopes = () => {
1106
+ if (scopesOf?.presets === scopePresets)
1107
+ return scopesOf.value;
1108
+ let of = scoping().of, value = Object.freeze(Object.fromEntries([...scopePresets].map(([scope, list]) => [
1109
+ scope,
1110
+ Object.freeze({
1111
+ id: scope,
1112
+ keys: Object.freeze([...of].flatMap(([k, s]) => s === scope ? [k] : [])),
1113
+ presets: list,
1114
+ variants: scopeVariants(scope)
1115
+ })
1116
+ ])));
1117
+ return scopesOf = { presets: scopePresets, value }, value;
1118
+ }, resettable = (keys) => (keys ?? fieldKeys()).filter((k) => valueField(k) && !blocked(k));
1020
1119
  function offBase(keys) {
1021
1120
  if (!hasBase())
1022
1121
  return !1;
@@ -1080,6 +1179,10 @@ function defineControls(id, input, options = {}) {
1080
1179
  get presets() {
1081
1180
  return presets;
1082
1181
  },
1182
+ get scopes() {
1183
+ return scopes();
1184
+ },
1185
+ scopeOf: (key) => scoping().of.get(key),
1083
1186
  actions,
1084
1187
  theme,
1085
1188
  appearance,
@@ -1100,11 +1203,12 @@ function defineControls(id, input, options = {}) {
1100
1203
  sectionDescription: (section) => options.sectionDescriptions?.[section] ?? fieldLabels().sectionText.get(section),
1101
1204
  groupFolded: options.groupFolded,
1102
1205
  sectionFolded: options.sectionFolded,
1103
- presetLabel: (presetId) => {
1104
- let v = variantsChoice(), option = presetId === "default" ? v?.field.value : presetId;
1105
- 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);
1206
+ presetLabel: (presetId, scope = "") => {
1207
+ let v = scoping().variants === scope ? variantsChoice() : void 0, option = presetId === "default" ? v?.field.value : presetId;
1208
+ return options.presetLabels?.[presetId] ?? (presetId === "default" ? defaultLabelOf(options.defaultLabel, scope) : void 0) ?? (v && option !== void 0 && v.field.options.includes(option) ? v.field.labels?.[option] ?? option : presetId);
1106
1209
  },
1107
1210
  isPinned: (key) => pinned().has(key),
1211
+ inPresets: (key) => !presetFree().has(key),
1108
1212
  get,
1109
1213
  set,
1110
1214
  sync,
@@ -1232,7 +1336,7 @@ function defineControls(id, input, options = {}) {
1232
1336
  options.onPreset?.({ group, index, name: preset.name });
1233
1337
  return;
1234
1338
  }
1235
- let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others);
1339
+ let { [group]: _, ...others } = b.groups, forget = index === void 0 ? void 0 : makeBase(b.preset, others, b.scopes);
1236
1340
  if (open.length < keys.length)
1237
1341
  return toDefaults(open, forget);
1238
1342
  let patch = {};
@@ -1377,13 +1481,15 @@ function defineControls(id, input, options = {}) {
1377
1481
  comparing = before, options.onChange?.(changes(now, before), before, { source: "compare" }), notify();
1378
1482
  },
1379
1483
  preset(id, presetOptions) {
1380
- if (!Object.hasOwn(presets, id))
1484
+ let scope = presetOptions?.scope ?? "", list = presetsIn(scope);
1485
+ if (!Object.hasOwn(list, id))
1381
1486
  throw Error(`Unknown preset: ${id}`);
1382
- write(presetPatch(presets[id]), { source: "preset", coalesce: presetOptions?.coalesce }, id === "default" ? NO_BASE : makeBase(Object.freeze({ kind: "preset", id }), {}));
1487
+ let b = activeBase(), ref = id === "default" ? void 0 : Object.freeze({ kind: "preset", id });
1488
+ 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)));
1383
1489
  },
1384
- matchingPreset: () => {
1385
- let cur = unpinned(get());
1386
- return Object.keys(presets).find((id) => equal(cur, presets[id])) ?? "custom";
1490
+ matchingPreset: (scope = "") => {
1491
+ let list = presetsIn(scope), cur = within(get(), scope);
1492
+ return Object.keys(list).find((id) => equal(cur, list[id])) ?? "custom";
1387
1493
  },
1388
1494
  get groupPresets() {
1389
1495
  return groupPresets;
@@ -1395,12 +1501,13 @@ function defineControls(id, input, options = {}) {
1395
1501
  if (!enabled())
1396
1502
  return;
1397
1503
  let b = activeBase();
1398
- write(preset.values, { source: "preset", group, coalesce: presetOptions?.coalesce }, makeBase(b.preset, { ...b.groups, [group]: index })), options.onPreset?.({ group, index, name: preset.name });
1504
+ 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 });
1399
1505
  },
1400
- activePreset() {
1506
+ activePreset(scope) {
1401
1507
  if (!enabled())
1402
1508
  return null;
1403
- return activeBase().preset;
1509
+ let b = activeBase();
1510
+ return scope ? b.scopes[scope] ?? null : b.preset;
1404
1511
  },
1405
1512
  activeGroupPreset(group) {
1406
1513
  if (!enabled())
@@ -1415,11 +1522,11 @@ function defineControls(id, input, options = {}) {
1415
1522
  code: (format, values) => formatCode(values ?? get(), format),
1416
1523
  variants,
1417
1524
  attach(element, chip) {
1418
- let load = options.ship ? () => options.ship().then((m) => m.attach) : () => import("./chunk-ab7vfghg.js").then((m) => m.attach);
1525
+ let load = options.ship ? () => options.ship().then((m) => m.attach) : () => import("./chunk-f0e5tkqg.js").then((m) => m.attach);
1419
1526
  return live(load, (attach) => attach(controls, element, chip), (detach) => detach());
1420
1527
  },
1421
1528
  mount(container, mountOptions) {
1422
- let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => import("./chunk-9qtvxa6k.js").then((m) => m.mountPanel);
1529
+ let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => import("./chunk-s7d5a8vb.js").then((m) => m.mountPanel);
1423
1530
  return live(load, (mountPanel) => {
1424
1531
  let panel = mountPanel(controls, container, mountOptions);
1425
1532
  return mountOptions?.onReady?.(panel), panel;
@@ -1718,7 +1825,9 @@ function createRemoteControls(id, descriptors, options = {}) {
1718
1825
  tunable: options.tunable,
1719
1826
  history: options.history,
1720
1827
  presets: options.presets,
1828
+ scopedPresets: options.scopedPresets,
1721
1829
  pinned: options.pinned,
1830
+ inPresets: options.inPresets,
1722
1831
  groupPresets: options.groupPresets,
1723
1832
  onPreset: options.onPreset,
1724
1833
  actions: options.actions,