@povio/ui 5.0.0-rc.10 → 5.0.0-rc.11

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.
@@ -48,8 +48,8 @@ import { i as alertDefinition, n as statusIconDefinition, r as statusSeparatorDe
48
48
  import { a as toastDefinition, i as toastContainerDefinition } from "./toast.cva-C_L_RffH.js";
49
49
  import { t as linkDefinition } from "./link.cva-DMTHZiJG.js";
50
50
  import { t as tooltipWrapperTriggerDefinition } from "./tooltipWrapper.cva-BBQ4ic3D.js";
51
- import { C as validToken, S as toRgb, a as generateShades, b as spacingLevels, c as isFontSizeToken, d as layoutKindFor, f as layoutKinds, g as listedLayoutToken, h as linkedLayoutTokens, i as exportCss, l as isRgb, m as layoutScales, n as controlHeightCounterpart, o as groupFor, p as layoutLevelFor, r as emptyTheme, s as groups, t as baseColorNames, u as labelFor, v as previewTokens, x as toHex, y as runtimeCss } from "./theme-model-DtYPxNvH.js";
52
- import $ahdqC$react, { Suspense, createContext, lazy, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
51
+ import { C as toRgb, S as toHex, _ as listedLayoutToken, a as generateShades, b as runtimeCss, c as isEditableToken, d as labelFor, f as layoutKindFor, g as linkedLayoutTokens, h as layoutScales, i as exportCss, l as isFontSizeToken, m as layoutLevelFor, n as controlHeightCounterpart, o as groupFor, p as layoutKinds, r as emptyTheme, s as groups, t as baseColorNames, u as isRgb, w as validToken, x as spacingLevels, y as previewTokens } from "./theme-model-DtTsIxou.js";
52
+ import $ahdqC$react, { Fragment, Suspense, createContext, lazy, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
53
53
  import { c } from "react/compiler-runtime";
54
54
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
55
55
  import { mergeProps } from "react-aria/mergeProps";
@@ -609,7 +609,7 @@ const emptyConfiguration = () => ({
609
609
  });
610
610
  const ConfigurationContext = createContext(null);
611
611
  function UIConfigurationProvider(t0) {
612
- const $ = c(40);
612
+ const $ = c(48);
613
613
  const { defaults, initialValue, onApply, children } = t0;
614
614
  const inheritedOverrides = UIOverrides.useConfig();
615
615
  const [applied, setApplied] = useState(initialValue ?? emptyConfiguration);
@@ -618,64 +618,96 @@ function UIConfigurationProvider(t0) {
618
618
  const [floating, setFloating] = useState(false);
619
619
  const [revision, setRevision] = useState(0);
620
620
  const [previewConfiguration, setPreviewConfiguration] = useState(null);
621
- const active = previewConfiguration ?? (isOpen ? draft : applied);
621
+ const [tokenRequest, setTokenRequest] = useState(null);
622
+ const [componentHosts, setComponentHosts] = useState(0);
622
623
  let t1;
623
- if ($[0] !== applied) {
624
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
624
625
  t1 = () => {
626
+ setComponentHosts(_temp$7);
627
+ return () => setComponentHosts(_temp2$5);
628
+ };
629
+ $[0] = t1;
630
+ } else t1 = $[0];
631
+ const hostComponents = t1;
632
+ const active = previewConfiguration ?? (isOpen ? draft : applied);
633
+ let t2;
634
+ if ($[1] !== applied) {
635
+ t2 = () => {
625
636
  setFloating(false);
626
637
  setDraft(structuredClone(applied));
627
- setRevision(_temp$7);
638
+ setRevision(_temp3$4);
628
639
  setOpen(true);
629
640
  };
630
- $[0] = applied;
631
- $[1] = t1;
632
- } else t1 = $[1];
633
- const open = t1;
634
- let t2;
635
- if ($[2] !== isOpen || $[3] !== open) {
636
- t2 = () => {
637
- if (isOpen) setRevision(_temp2$5);
641
+ $[1] = applied;
642
+ $[2] = t2;
643
+ } else t2 = $[2];
644
+ const open = t2;
645
+ let t3;
646
+ if ($[3] !== isOpen || $[4] !== open) {
647
+ t3 = () => {
648
+ if (isOpen) setRevision(_temp4$4);
638
649
  else open();
639
650
  setFloating(true);
640
651
  };
641
- $[2] = isOpen;
642
- $[3] = open;
643
- $[4] = t2;
644
- } else t2 = $[4];
645
- const openFloating = t2;
646
- let t3;
647
- if ($[5] !== applied) {
648
- t3 = () => {
652
+ $[3] = isOpen;
653
+ $[4] = open;
654
+ $[5] = t3;
655
+ } else t3 = $[5];
656
+ const openFloating = t3;
657
+ let t4;
658
+ if ($[6] !== isOpen || $[7] !== openFloating) {
659
+ t4 = (name) => {
660
+ setTokenRequest((current) => ({
661
+ name,
662
+ id: (current?.id ?? 0) + 1
663
+ }));
664
+ if (!isOpen) openFloating();
665
+ };
666
+ $[6] = isOpen;
667
+ $[7] = openFloating;
668
+ $[8] = t4;
669
+ } else t4 = $[8];
670
+ const revealToken = t4;
671
+ let t5;
672
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
673
+ t5 = () => setTokenRequest(null);
674
+ $[9] = t5;
675
+ } else t5 = $[9];
676
+ const clearTokenRequest = t5;
677
+ let t6;
678
+ if ($[10] !== applied) {
679
+ t6 = () => {
649
680
  setDraft(structuredClone(applied));
650
681
  setOpen(false);
651
682
  };
652
- $[5] = applied;
653
- $[6] = t3;
654
- } else t3 = $[6];
655
- const cancel = t3;
656
- let t4;
657
- if ($[7] !== draft || $[8] !== onApply) {
658
- t4 = () => {
683
+ $[10] = applied;
684
+ $[11] = t6;
685
+ } else t6 = $[11];
686
+ const cancel = t6;
687
+ let t7;
688
+ if ($[12] !== draft || $[13] !== onApply) {
689
+ t7 = () => {
659
690
  onApply?.(structuredClone(draft));
660
691
  setApplied(structuredClone(draft));
661
692
  setOpen(false);
662
693
  };
663
- $[7] = draft;
664
- $[8] = onApply;
665
- $[9] = t4;
666
- } else t4 = $[9];
667
- const apply = t4;
668
- let t5;
669
- if ($[10] !== active.overrides || $[11] !== inheritedOverrides) {
670
- t5 = applyCvaEdits(inheritedOverrides, active.overrides);
671
- $[10] = active.overrides;
672
- $[11] = inheritedOverrides;
673
- $[12] = t5;
674
- } else t5 = $[12];
675
- const overrides = t5;
676
- let t6;
677
- if ($[13] !== active || $[14] !== apply || $[15] !== cancel || $[16] !== defaults || $[17] !== draft || $[18] !== floating || $[19] !== inheritedOverrides || $[20] !== isOpen || $[21] !== open || $[22] !== openFloating || $[23] !== revision) {
678
- t6 = {
694
+ $[12] = draft;
695
+ $[13] = onApply;
696
+ $[14] = t7;
697
+ } else t7 = $[14];
698
+ const apply = t7;
699
+ let t8;
700
+ if ($[15] !== active.overrides || $[16] !== inheritedOverrides) {
701
+ t8 = applyCvaEdits(inheritedOverrides, active.overrides);
702
+ $[15] = active.overrides;
703
+ $[16] = inheritedOverrides;
704
+ $[17] = t8;
705
+ } else t8 = $[17];
706
+ const overrides = t8;
707
+ const t9 = componentHosts > 0;
708
+ let t10;
709
+ if ($[18] !== active || $[19] !== apply || $[20] !== cancel || $[21] !== defaults || $[22] !== draft || $[23] !== floating || $[24] !== inheritedOverrides || $[25] !== isOpen || $[26] !== open || $[27] !== openFloating || $[28] !== revealToken || $[29] !== revision || $[30] !== t9 || $[31] !== tokenRequest) {
710
+ t10 = {
679
711
  defaults,
680
712
  inheritedOverrides,
681
713
  draft,
@@ -688,77 +720,91 @@ function UIConfigurationProvider(t0) {
688
720
  floating,
689
721
  cancel,
690
722
  apply,
691
- revision
723
+ revision,
724
+ revealToken,
725
+ tokenRequest,
726
+ clearTokenRequest,
727
+ componentsHosted: t9,
728
+ hostComponents
692
729
  };
693
- $[13] = active;
694
- $[14] = apply;
695
- $[15] = cancel;
696
- $[16] = defaults;
697
- $[17] = draft;
698
- $[18] = floating;
699
- $[19] = inheritedOverrides;
700
- $[20] = isOpen;
701
- $[21] = open;
702
- $[22] = openFloating;
703
- $[23] = revision;
704
- $[24] = t6;
705
- } else t6 = $[24];
706
- const contextValue = t6;
707
- let t7;
708
- if ($[25] !== active.theme || $[26] !== defaults) {
709
- t7 = runtimeCss(defaults, active.theme);
710
- $[25] = active.theme;
711
- $[26] = defaults;
712
- $[27] = t7;
713
- } else t7 = $[27];
714
- let t8;
715
- if ($[28] !== t7) {
716
- t8 = /* @__PURE__ */ jsx("style", {
730
+ $[18] = active;
731
+ $[19] = apply;
732
+ $[20] = cancel;
733
+ $[21] = defaults;
734
+ $[22] = draft;
735
+ $[23] = floating;
736
+ $[24] = inheritedOverrides;
737
+ $[25] = isOpen;
738
+ $[26] = open;
739
+ $[27] = openFloating;
740
+ $[28] = revealToken;
741
+ $[29] = revision;
742
+ $[30] = t9;
743
+ $[31] = tokenRequest;
744
+ $[32] = t10;
745
+ } else t10 = $[32];
746
+ const contextValue = t10;
747
+ let t11;
748
+ if ($[33] !== active.theme || $[34] !== defaults) {
749
+ t11 = runtimeCss(defaults, active.theme);
750
+ $[33] = active.theme;
751
+ $[34] = defaults;
752
+ $[35] = t11;
753
+ } else t11 = $[35];
754
+ let t12;
755
+ if ($[36] !== t11) {
756
+ t12 = /* @__PURE__ */ jsx("style", {
717
757
  "data-povio-ui-configuration": true,
718
- children: t7
758
+ children: t11
719
759
  });
720
- $[28] = t7;
721
- $[29] = t8;
722
- } else t8 = $[29];
723
- let t9;
724
- if ($[30] !== active.config || $[31] !== children) {
725
- t9 = /* @__PURE__ */ jsx(UIConfig.Provider, {
760
+ $[36] = t11;
761
+ $[37] = t12;
762
+ } else t12 = $[37];
763
+ let t13;
764
+ if ($[38] !== active.config || $[39] !== children) {
765
+ t13 = /* @__PURE__ */ jsx(UIConfig.Provider, {
726
766
  config: active.config,
727
767
  children
728
768
  });
729
- $[30] = active.config;
730
- $[31] = children;
731
- $[32] = t9;
732
- } else t9 = $[32];
733
- let t10;
734
- if ($[33] !== overrides || $[34] !== t9) {
735
- t10 = /* @__PURE__ */ jsx(UIOverrides.Provider, {
769
+ $[38] = active.config;
770
+ $[39] = children;
771
+ $[40] = t13;
772
+ } else t13 = $[40];
773
+ let t14;
774
+ if ($[41] !== overrides || $[42] !== t13) {
775
+ t14 = /* @__PURE__ */ jsx(UIOverrides.Provider, {
736
776
  config: overrides,
737
- children: t9
777
+ children: t13
738
778
  });
739
- $[33] = overrides;
740
- $[34] = t9;
741
- $[35] = t10;
742
- } else t10 = $[35];
743
- let t11;
744
- if ($[36] !== contextValue || $[37] !== t10 || $[38] !== t8) {
745
- t11 = /* @__PURE__ */ jsxs(ConfigurationContext.Provider, {
779
+ $[41] = overrides;
780
+ $[42] = t13;
781
+ $[43] = t14;
782
+ } else t14 = $[43];
783
+ let t15;
784
+ if ($[44] !== contextValue || $[45] !== t12 || $[46] !== t14) {
785
+ t15 = /* @__PURE__ */ jsxs(ConfigurationContext.Provider, {
746
786
  value: contextValue,
747
- children: [t8, t10]
787
+ children: [t12, t14]
748
788
  });
749
- $[36] = contextValue;
750
- $[37] = t10;
751
- $[38] = t8;
752
- $[39] = t11;
753
- } else t11 = $[39];
754
- return t11;
789
+ $[44] = contextValue;
790
+ $[45] = t12;
791
+ $[46] = t14;
792
+ $[47] = t15;
793
+ } else t15 = $[47];
794
+ return t15;
755
795
  }
756
- function _temp2$5(value_0) {
796
+ function _temp4$4(value_0) {
757
797
  return value_0 + 1;
758
798
  }
759
- function _temp$7(value) {
799
+ function _temp3$4(value) {
760
800
  return value + 1;
761
801
  }
802
+ function _temp2$5(count_0) {
803
+ return count_0 - 1;
804
+ }
805
+ function _temp$7(count) {
806
+ return count + 1;
807
+ }
762
808
  function useUIConfiguration() {
763
809
  const context = use(ConfigurationContext);
764
810
  if (!context) throw new Error("useUIConfiguration requires UIConfigurationProvider");
@@ -766,6 +812,10 @@ function useUIConfiguration() {
766
812
  }
767
813
  //#endregion
768
814
  //#region src/configurator/inspector/InspectorDetails.tsx
815
+ /** A token as a design tool names a variable: `--text-large--line-height` → `text-large/line-height`. */
816
+ const variableName = (token) => token.replace(/^--/, "").replace(/-base$/, "").replaceAll("--", "/");
817
+ /** Pixel values read like the box model's numbers and fonts by their family, as a design tool shows them. */
818
+ const displayValue = (value, label) => label === "Font" ? value.split(",")[0]?.replace(/["']/g, "").trim() ?? value : value.replace(/(-?\d*\.\d+)px/g, (_, amount) => `${Math.round(Number(amount) * 10) / 10}px`);
769
819
  /** Shared inspector measurements and property groups for preview and app canvas. */
770
820
  function InspectorDetails(t0) {
771
821
  const $ = c(18);
@@ -813,16 +863,30 @@ function InspectorDetails(t0) {
813
863
  if ($[10] !== onSelect || $[11] !== snapshot.groups) {
814
864
  let t6;
815
865
  if ($[13] !== onSelect) {
816
- t6 = (group_1) => /* @__PURE__ */ jsxs("section", { children: [group_1.name !== "Layout" && /* @__PURE__ */ jsx("h3", { children: group_1.name }), /* @__PURE__ */ jsx("dl", { children: group_1.properties.map((property_0) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: property_0.label }), /* @__PURE__ */ jsxs("dd", { children: [
817
- property_0.color && /* @__PURE__ */ jsx("i", { style: { background: property_0.color } }),
818
- /* @__PURE__ */ jsx("span", { children: property_0.value }),
819
- property_0.token && /* @__PURE__ */ jsx("button", {
820
- type: "button",
821
- title: `Edit ${property_0.token}`,
822
- onClick: () => onSelect(property_0.token),
823
- children: property_0.token.replace(/^--/, "")
824
- })
825
- ] })] }, property_0.label)) })] }, group_1.name);
866
+ t6 = (group_1) => /* @__PURE__ */ jsxs("section", { children: [group_1.name !== "Layout" && /* @__PURE__ */ jsx("h3", { children: group_1.name }), /* @__PURE__ */ jsx("dl", { children: group_1.properties.map((property_0) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: property_0.label }), /* @__PURE__ */ jsx("dd", { children: property_0.token ? /* @__PURE__ */ jsxs("button", {
867
+ type: "button",
868
+ className: "studio-inspector-chip",
869
+ title: `Edit ${property_0.token} · ${property_0.value}`,
870
+ onClick: () => onSelect(property_0.token),
871
+ children: [
872
+ property_0.color && /* @__PURE__ */ jsx("i", { style: { background: property_0.color } }),
873
+ /* @__PURE__ */ jsx("span", {
874
+ className: "studio-inspector-chip-name",
875
+ children: variableName(property_0.token)
876
+ }),
877
+ /* @__PURE__ */ jsx("span", {
878
+ className: "studio-inspector-chip-value",
879
+ children: displayValue(property_0.value, property_0.label)
880
+ })
881
+ ]
882
+ }) : /* @__PURE__ */ jsxs("span", {
883
+ className: "studio-inspector-chip",
884
+ title: property_0.value,
885
+ children: [property_0.color && /* @__PURE__ */ jsx("i", { style: { background: property_0.color } }), /* @__PURE__ */ jsx("span", {
886
+ className: "studio-inspector-chip-value",
887
+ children: displayValue(property_0.value, property_0.label)
888
+ })]
889
+ }) })] }, property_0.label)) })] }, group_1.name);
826
890
  $[13] = onSelect;
827
891
  $[14] = t6;
828
892
  } else t6 = $[14];
@@ -1435,6 +1499,74 @@ function splitVariants(className) {
1435
1499
  utility: current
1436
1500
  };
1437
1501
  }
1502
+ /** Variants that style a pseudo-element or other elements, never the element's own value. */
1503
+ const otherTargets = /* @__PURE__ */ new Set([
1504
+ "placeholder",
1505
+ "before",
1506
+ "after",
1507
+ "selection",
1508
+ "marker",
1509
+ "file",
1510
+ "first-letter",
1511
+ "first-line",
1512
+ "backdrop",
1513
+ "*",
1514
+ "**"
1515
+ ]);
1516
+ const stateSelectors = {
1517
+ hover: ":hover",
1518
+ focus: ":focus",
1519
+ "focus-within": ":focus-within",
1520
+ "focus-visible": ":focus-visible",
1521
+ active: ":active",
1522
+ disabled: ":disabled",
1523
+ enabled: ":enabled",
1524
+ checked: ":checked",
1525
+ indeterminate: ":indeterminate",
1526
+ invalid: ":invalid",
1527
+ valid: ":valid",
1528
+ required: ":required",
1529
+ optional: ":optional",
1530
+ "read-only": ":read-only",
1531
+ "placeholder-shown": ":placeholder-shown",
1532
+ empty: ":empty",
1533
+ open: ":is([open], :popover-open, :open)",
1534
+ first: ":first-child",
1535
+ last: ":last-child",
1536
+ only: ":only-child",
1537
+ odd: ":nth-child(odd)",
1538
+ even: ":nth-child(even)"
1539
+ };
1540
+ /** A CSS selector for one state variant, or `undefined` when its condition cannot be read from the element. */
1541
+ function variantSelector(variant) {
1542
+ if (variant.startsWith("not-")) {
1543
+ const inner = variantSelector(variant.slice(4));
1544
+ return inner && `:not(${inner})`;
1545
+ }
1546
+ if (variant.startsWith("has-")) {
1547
+ const inner = variantSelector(variant.slice(4));
1548
+ return inner && `:has(${inner})`;
1549
+ }
1550
+ if (stateSelectors[variant]) return stateSelectors[variant];
1551
+ if (variant.startsWith("aria-") && !variant.includes("[")) return `[aria-${variant.slice(5)}="true"]`;
1552
+ const arbitrary = variant.match(/^\[(&?)(:[^\s&>+~,]+)\]$/);
1553
+ return arbitrary ? arbitrary[2].replaceAll("_", " ") : void 0;
1554
+ }
1555
+ /**
1556
+ * How a variant class relates to an element's current value: `other` styles a pseudo-element or descendants,
1557
+ * `inactive` / `active` are state conditions read from the element, and `unknown` covers breakpoints, container
1558
+ * queries, group/peer state and anything else that cannot be checked from the element alone.
1559
+ */
1560
+ function variantState(variants, element) {
1561
+ if (variants.some((variant) => otherTargets.has(variant))) return "other";
1562
+ const selectors = variants.map(variantSelector);
1563
+ if (selectors.some((selector) => selector === void 0) || typeof element.matches !== "function") return "unknown";
1564
+ try {
1565
+ return element.matches(`*${selectors.join("")}`) ? "active" : "inactive";
1566
+ } catch {
1567
+ return "unknown";
1568
+ }
1569
+ }
1438
1570
  /** Breakpoint weight when every variant is an active breakpoint; `undefined` for state variants or inactive breakpoints. */
1439
1571
  function variantWeight(variants, viewportWidth, rootFontSize) {
1440
1572
  let weight = 0;
@@ -1545,17 +1677,21 @@ function inspectElement(element, isKnown) {
1545
1677
  const position = style.getPropertyValue("position");
1546
1678
  if (position && position !== "static") box.position = readSides("");
1547
1679
  const classes = Array.from(element.classList);
1548
- const plainClasses = classes.filter((name) => !splitVariants(name).variants.length && !name.includes("["));
1680
+ const plainOf = (list) => list.filter((name) => !splitVariants(name).variants.length && !name.includes("["));
1681
+ const plainClasses = plainOf(classes);
1549
1682
  const spacing = inspectTokens(plainClasses.join(" "), isKnown);
1550
- const candidates = (prefix, namespaces) => plainClasses.flatMap((raw) => {
1683
+ const candidates = (prefix, namespaces, suffix = "") => (plain) => plain.flatMap((raw) => {
1551
1684
  const utility = raw.replace(/^!|!$/g, "");
1552
1685
  if (!utility.startsWith(`${prefix}-`)) return [];
1553
- const suffix = utility.slice(prefix.length + 1);
1554
- return namespaces.map((namespace) => `--${namespace}${suffix}`);
1686
+ const name = utility.slice(prefix.length + 1);
1687
+ return namespaces.map((namespace) => `--${namespace}${name}${suffix}`);
1555
1688
  });
1556
- const variantsAffect = (prefixes) => classes.some((raw) => {
1689
+ const touches = (utility, prefixes) => prefixes.some((prefix) => utility.replace(/^!/, "").startsWith(`${prefix}-`));
1690
+ const variantsAffect = (node, list, plain, prefixes) => list.some((raw) => {
1557
1691
  const { variants, utility } = splitVariants(raw);
1558
- return variants.length > 0 && prefixes.some((prefix) => utility.replace(/^!/, "").startsWith(`${prefix}-`));
1692
+ if (!variants.length || plain.includes(utility) || !touches(utility, prefixes)) return false;
1693
+ const state = variantState(variants, node);
1694
+ return state === "active" || state === "unknown";
1559
1695
  });
1560
1696
  const equivalent = (value, computed, property) => {
1561
1697
  if (!value) return false;
@@ -1570,12 +1706,35 @@ function inspectElement(element, isKnown) {
1570
1706
  if (length[2] === "em") factor = Number.parseFloat(style.fontSize);
1571
1707
  return Math.abs(Number(length[1]) * factor - Number.parseFloat(computed)) < .02;
1572
1708
  }
1709
+ if (property === "line-height" && /^\d+(?:\.\d+)?$/.test(value) && computed.endsWith("px")) return Math.abs(Number(value) * Number.parseFloat(style.fontSize) - Number.parseFloat(computed)) < .05;
1573
1710
  return value.replace(/["']/g, "").replace(/\s+/g, " ") === computed.replace(/["']/g, "").replace(/\s+/g, " ");
1574
1711
  };
1575
- const property = (label, css, tokens = [], prefixes = []) => {
1712
+ const matchingToken = (nodeStyle, tokens, computed, css) => tokens.find((token) => !!token && isKnown(token) && equivalent(resolveToken(nodeStyle, token), computed, css));
1713
+ /**
1714
+ * Inherited properties (type and text color) usually come from an ancestor's utility, like the text style on a
1715
+ * field wrapper. Walk up to the first element whose plain class renders this value; stop where the value changes or
1716
+ * where a variant or arbitrary class sets it, since its active condition is unknown.
1717
+ */
1718
+ const inheritedToken = (css, computed, tokens, prefixes) => {
1719
+ for (let node = element.parentElement; node; node = node.parentElement) {
1720
+ const nodeStyle = view.getComputedStyle(node);
1721
+ if (css !== "line-height" && nodeStyle.getPropertyValue(css) !== computed) return void 0;
1722
+ const list = Array.from(node.classList);
1723
+ const plain = plainOf(list);
1724
+ if (variantsAffect(node, list, plain, prefixes)) return void 0;
1725
+ const token = matchingToken(nodeStyle, tokens(plain), computed, css);
1726
+ if (token) return token;
1727
+ if (list.some((name) => name.includes("[") && touches(splitVariants(name).utility, prefixes))) return void 0;
1728
+ }
1729
+ };
1730
+ const setsOwn = (css, prefixes) => classes.some((name) => {
1731
+ const { utility } = splitVariants(name);
1732
+ return name.includes("[") && touches(utility, prefixes) || css === "line-height" && touches(utility, ["leading"]) || css === "letter-spacing" && touches(utility, ["tracking"]);
1733
+ });
1734
+ const property = (label, css, tokens = [], prefixes = [], inherited = false) => {
1576
1735
  const computed = style.getPropertyValue(css);
1577
- const matching = variantsAffect(prefixes) ? [] : tokens.filter((token) => !!token && isKnown(token) && equivalent(resolveToken(style, token), computed, css));
1578
- const token = [...new Set(matching)][0];
1736
+ const own = typeof tokens === "function" ? tokens(plainClasses) : tokens;
1737
+ const token = variantsAffect(element, classes, plainClasses, prefixes) ? void 0 : matchingToken(style, own, computed, css) ?? (inherited && typeof tokens === "function" && !setsOwn(css, prefixes) ? inheritedToken(css, computed, tokens, prefixes) : void 0);
1579
1738
  const isColor = css.includes("color");
1580
1739
  return {
1581
1740
  label,
@@ -1618,18 +1777,19 @@ function inspectElement(element, isKnown) {
1618
1777
  property("Radius", "border-radius", [spacing.radius], ["rounded"]),
1619
1778
  ...sides.map((side) => property(`Border ${side} width`, `border-${side}-width`))
1620
1779
  ];
1780
+ const withBase = (tokens) => (plain) => tokens(plain).flatMap((token) => [token, `${token}-base`]);
1621
1781
  const typography = [
1622
- property("Font", "font-family", candidates("font", ["font-"]), ["font"]),
1623
- property("Size", "font-size", candidates("text", ["text-"]), ["text"]),
1624
- property("Weight", "font-weight", candidates("font", ["font-weight-"]), ["font"]),
1625
- property("Line height", "line-height"),
1626
- property("Letter spacing", "letter-spacing"),
1782
+ property("Font", "font-family", candidates("font", ["font-"]), ["font"], true),
1783
+ property("Size", "font-size", candidates("text", ["text-"]), ["text"], true),
1784
+ property("Weight", "font-weight", candidates("font", ["font-weight-"]), ["font"], true),
1785
+ property("Line height", "line-height", candidates("text", ["text-"], "--line-height"), ["text", "leading"], true),
1786
+ property("Letter spacing", "letter-spacing", candidates("text", ["text-"], "--letter-spacing"), ["text", "tracking"], true),
1627
1787
  property("Alignment", "text-align")
1628
1788
  ];
1629
1789
  const appearance = [
1630
- property("Text", "color", candidates("text", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["text"]),
1631
- property("Fill", "background-color", candidates("bg", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["bg"]),
1632
- property("Border", "border-top-color", candidates("border", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["border"]),
1790
+ property("Text", "color", withBase(candidates("text", ["color-", ""])), ["text"], true),
1791
+ property("Fill", "background-color", withBase(candidates("bg", ["color-", ""])), ["bg"]),
1792
+ property("Border", "border-top-color", withBase(candidates("border", ["color-", ""])), ["border"]),
1633
1793
  property("Opacity", "opacity"),
1634
1794
  property("Shadow", "box-shadow")
1635
1795
  ];
@@ -2446,9 +2606,20 @@ function useStudioWindow(bounds, enabled = true) {
2446
2606
  }
2447
2607
  };
2448
2608
  }
2609
+ const move = controls("move");
2449
2610
  return {
2450
2611
  ref,
2451
- move: controls("move"),
2612
+ move,
2613
+ dragArea: {
2614
+ onPointerMove: (event_3) => move.onPointerMove(event_3),
2615
+ onPointerUp: (event_4) => move.onPointerUp(event_4),
2616
+ onLostPointerCapture: move.onLostPointerCapture,
2617
+ onPointerCancel: move.onPointerCancel,
2618
+ onPointerDown(event_5) {
2619
+ if (event_5.target.closest("button, input, select, textarea, a, label, [role='tab']")) return;
2620
+ move.onPointerDown(event_5);
2621
+ }
2622
+ },
2452
2623
  resize: (edge) => controls(edge)
2453
2624
  };
2454
2625
  }
@@ -4535,8 +4706,8 @@ function familyName(value) {
4535
4706
  * theme's font families, like a design tool's font picker.
4536
4707
  */
4537
4708
  function FontRoleCard(t0) {
4538
- const $ = c(44);
4539
- const { label, value, options, changed, onChange, onReset } = t0;
4709
+ const $ = c(46);
4710
+ const { label, value, options, changed, onChange, onReset, token, highlighted } = t0;
4540
4711
  let t1;
4541
4712
  if ($[0] !== options || $[1] !== value) {
4542
4713
  let t2;
@@ -4551,112 +4722,113 @@ function FontRoleCard(t0) {
4551
4722
  $[2] = t1;
4552
4723
  } else t1 = $[2];
4553
4724
  const selected = t1;
4554
- let t2;
4725
+ const t2 = `studio-font-role ${highlighted ? "is-highlighted" : ""}`;
4726
+ let t3;
4555
4727
  if ($[5] !== label) {
4556
- t2 = /* @__PURE__ */ jsx("span", { children: label });
4728
+ t3 = /* @__PURE__ */ jsx("span", { children: label });
4557
4729
  $[5] = label;
4558
- $[6] = t2;
4559
- } else t2 = $[6];
4560
- let t3;
4730
+ $[6] = t3;
4731
+ } else t3 = $[6];
4732
+ let t4;
4561
4733
  if ($[7] !== selected?.label || $[8] !== value) {
4562
- t3 = selected?.label ?? familyName(value);
4734
+ t4 = selected?.label ?? familyName(value);
4563
4735
  $[7] = selected?.label;
4564
4736
  $[8] = value;
4565
- $[9] = t3;
4566
- } else t3 = $[9];
4567
- let t4;
4568
- if ($[10] !== t3) {
4569
- t4 = /* @__PURE__ */ jsx("strong", { children: t3 });
4570
- $[10] = t3;
4571
- $[11] = t4;
4572
- } else t4 = $[11];
4737
+ $[9] = t4;
4738
+ } else t4 = $[9];
4573
4739
  let t5;
4574
- if ($[12] !== t2 || $[13] !== t4) {
4575
- t5 = /* @__PURE__ */ jsxs("span", {
4740
+ if ($[10] !== t4) {
4741
+ t5 = /* @__PURE__ */ jsx("strong", { children: t4 });
4742
+ $[10] = t4;
4743
+ $[11] = t5;
4744
+ } else t5 = $[11];
4745
+ let t6;
4746
+ if ($[12] !== t3 || $[13] !== t5) {
4747
+ t6 = /* @__PURE__ */ jsxs("span", {
4576
4748
  className: "studio-font-role-text",
4577
- children: [t2, t4]
4749
+ children: [t3, t5]
4578
4750
  });
4579
- $[12] = t2;
4580
- $[13] = t4;
4581
- $[14] = t5;
4582
- } else t5 = $[14];
4583
- let t6;
4751
+ $[12] = t3;
4752
+ $[13] = t5;
4753
+ $[14] = t6;
4754
+ } else t6 = $[14];
4755
+ let t7;
4584
4756
  if ($[15] !== value) {
4585
- t6 = /* @__PURE__ */ jsx("span", {
4757
+ t7 = /* @__PURE__ */ jsx("span", {
4586
4758
  className: "studio-font-role-sample",
4587
4759
  style: { fontFamily: value },
4588
4760
  "aria-hidden": "true",
4589
4761
  children: "Aa"
4590
4762
  });
4591
4763
  $[15] = value;
4592
- $[16] = t6;
4593
- } else t6 = $[16];
4594
- const t7 = `${label} font`;
4595
- const t8 = selected?.name ?? "";
4596
- let t9;
4764
+ $[16] = t7;
4765
+ } else t7 = $[16];
4766
+ const t8 = `${label} font`;
4767
+ const t9 = selected?.name ?? "";
4768
+ let t10;
4597
4769
  if ($[17] !== onChange || $[18] !== options) {
4598
- t9 = (event) => {
4599
- const option_0 = options.find((t10) => {
4600
- const { name } = t10;
4770
+ t10 = (event) => {
4771
+ const option_0 = options.find((t11) => {
4772
+ const { name } = t11;
4601
4773
  return name === event.target.value;
4602
4774
  });
4603
4775
  if (option_0) onChange(option_0.value);
4604
4776
  };
4605
4777
  $[17] = onChange;
4606
4778
  $[18] = options;
4607
- $[19] = t9;
4608
- } else t9 = $[19];
4609
- let t10;
4779
+ $[19] = t10;
4780
+ } else t10 = $[19];
4781
+ let t11;
4610
4782
  if ($[20] !== selected) {
4611
- t10 = !selected && /* @__PURE__ */ jsx("option", {
4783
+ t11 = !selected && /* @__PURE__ */ jsx("option", {
4612
4784
  value: "",
4613
4785
  disabled: true,
4614
4786
  children: "Custom"
4615
4787
  });
4616
4788
  $[20] = selected;
4617
- $[21] = t10;
4618
- } else t10 = $[21];
4619
- let t11;
4789
+ $[21] = t11;
4790
+ } else t11 = $[21];
4791
+ let t12;
4620
4792
  if ($[22] !== options) {
4621
- t11 = new Set(options.map(_temp3));
4793
+ t12 = new Set(options.map(_temp3));
4622
4794
  $[22] = options;
4623
- $[23] = t11;
4624
- } else t11 = $[23];
4625
- let t12;
4626
- if ($[24] !== t11) {
4627
- t12 = [...t11];
4628
- $[24] = t11;
4629
- $[25] = t12;
4630
- } else t12 = $[25];
4795
+ $[23] = t12;
4796
+ } else t12 = $[23];
4631
4797
  let t13;
4632
- if ($[26] !== options || $[27] !== t12) {
4633
- t13 = t12.map((group_0) => /* @__PURE__ */ jsx("optgroup", {
4798
+ if ($[24] !== t12) {
4799
+ t13 = [...t12];
4800
+ $[24] = t12;
4801
+ $[25] = t13;
4802
+ } else t13 = $[25];
4803
+ let t14;
4804
+ if ($[26] !== options || $[27] !== t13) {
4805
+ t14 = t13.map((group_0) => /* @__PURE__ */ jsx("optgroup", {
4634
4806
  label: group_0,
4635
4807
  children: options.filter((option_1) => option_1.group === group_0).map(_temp4)
4636
4808
  }, group_0));
4637
4809
  $[26] = options;
4638
- $[27] = t12;
4639
- $[28] = t13;
4640
- } else t13 = $[28];
4641
- let t14;
4642
- if ($[29] !== t10 || $[30] !== t13 || $[31] !== t7 || $[32] !== t8 || $[33] !== t9) {
4643
- t14 = /* @__PURE__ */ jsxs("select", {
4810
+ $[27] = t13;
4811
+ $[28] = t14;
4812
+ } else t14 = $[28];
4813
+ let t15;
4814
+ if ($[29] !== t10 || $[30] !== t11 || $[31] !== t14 || $[32] !== t8 || $[33] !== t9) {
4815
+ t15 = /* @__PURE__ */ jsxs("select", {
4644
4816
  className: "studio-font-role-select",
4645
- "aria-label": t7,
4646
- value: t8,
4647
- onChange: t9,
4648
- children: [t10, t13]
4817
+ "aria-label": t8,
4818
+ value: t9,
4819
+ onChange: t10,
4820
+ children: [t11, t14]
4649
4821
  });
4650
4822
  $[29] = t10;
4651
- $[30] = t13;
4652
- $[31] = t7;
4823
+ $[30] = t11;
4824
+ $[31] = t14;
4653
4825
  $[32] = t8;
4654
4826
  $[33] = t9;
4655
- $[34] = t14;
4656
- } else t14 = $[34];
4657
- let t15;
4827
+ $[34] = t15;
4828
+ } else t15 = $[34];
4829
+ let t16;
4658
4830
  if ($[35] !== changed || $[36] !== label || $[37] !== onReset) {
4659
- t15 = changed && /* @__PURE__ */ jsx("button", {
4831
+ t16 = changed && /* @__PURE__ */ jsx("button", {
4660
4832
  type: "button",
4661
4833
  className: "studio-font-role-reset",
4662
4834
  "aria-label": `Reset ${label} font`,
@@ -4670,26 +4842,29 @@ function FontRoleCard(t0) {
4670
4842
  $[35] = changed;
4671
4843
  $[36] = label;
4672
4844
  $[37] = onReset;
4673
- $[38] = t15;
4674
- } else t15 = $[38];
4675
- let t16;
4676
- if ($[39] !== t14 || $[40] !== t15 || $[41] !== t5 || $[42] !== t6) {
4677
- t16 = /* @__PURE__ */ jsxs("div", {
4678
- className: "studio-font-role",
4845
+ $[38] = t16;
4846
+ } else t16 = $[38];
4847
+ let t17;
4848
+ if ($[39] !== t15 || $[40] !== t16 || $[41] !== t2 || $[42] !== t6 || $[43] !== t7 || $[44] !== token) {
4849
+ t17 = /* @__PURE__ */ jsxs("div", {
4850
+ className: t2,
4851
+ "data-token": token,
4679
4852
  children: [
4680
- t5,
4681
4853
  t6,
4682
- t14,
4683
- t15
4854
+ t7,
4855
+ t15,
4856
+ t16
4684
4857
  ]
4685
4858
  });
4686
- $[39] = t14;
4687
- $[40] = t15;
4688
- $[41] = t5;
4859
+ $[39] = t15;
4860
+ $[40] = t16;
4861
+ $[41] = t2;
4689
4862
  $[42] = t6;
4690
- $[43] = t16;
4691
- } else t16 = $[43];
4692
- return t16;
4863
+ $[43] = t7;
4864
+ $[44] = token;
4865
+ $[45] = t17;
4866
+ } else t17 = $[45];
4867
+ return t17;
4693
4868
  }
4694
4869
  function _temp4(option_2) {
4695
4870
  return /* @__PURE__ */ jsx("option", {
@@ -5248,6 +5423,67 @@ function _temp(t0) {
5248
5423
  return step;
5249
5424
  }
5250
5425
  //#endregion
5426
+ //#region src/configurator/ComponentPreview.tsx
5427
+ const ComponentGallery = lazy(() => import("./ComponentGallery-DDSqnm9f.js"));
5428
+ /** Every component, styled by a configuration; the configurator's preview and the App Canvas Components view. */
5429
+ function ComponentPreview(t0) {
5430
+ const $ = c(14);
5431
+ const { value, mode, inspector } = t0;
5432
+ const { defaults } = useUIConfiguration();
5433
+ const t1 = value.config;
5434
+ const t2 = `studio-sample ${mode}`;
5435
+ let t3;
5436
+ if ($[0] !== defaults || $[1] !== mode || $[2] !== value.theme) {
5437
+ t3 = previewTokens(defaults, value.theme, mode);
5438
+ $[0] = defaults;
5439
+ $[1] = mode;
5440
+ $[2] = value.theme;
5441
+ $[3] = t3;
5442
+ } else t3 = $[3];
5443
+ const t4 = t3;
5444
+ let t5;
5445
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
5446
+ t5 = /* @__PURE__ */ jsx("p", {
5447
+ className: "studio-gallery-loading",
5448
+ children: "Loading components…"
5449
+ });
5450
+ $[4] = t5;
5451
+ } else t5 = $[4];
5452
+ let t6;
5453
+ if ($[5] !== inspector) {
5454
+ t6 = /* @__PURE__ */ jsx(Suspense, {
5455
+ fallback: t5,
5456
+ children: /* @__PURE__ */ jsx(ComponentGallery, { inspector })
5457
+ });
5458
+ $[5] = inspector;
5459
+ $[6] = t6;
5460
+ } else t6 = $[6];
5461
+ let t7;
5462
+ if ($[7] !== t2 || $[8] !== t4 || $[9] !== t6) {
5463
+ t7 = /* @__PURE__ */ jsx("div", {
5464
+ className: t2,
5465
+ style: t4,
5466
+ "data-testid": "component-preview",
5467
+ children: t6
5468
+ });
5469
+ $[7] = t2;
5470
+ $[8] = t4;
5471
+ $[9] = t6;
5472
+ $[10] = t7;
5473
+ } else t7 = $[10];
5474
+ let t8;
5475
+ if ($[11] !== t7 || $[12] !== value.config) {
5476
+ t8 = /* @__PURE__ */ jsx(UIConfig.Provider, {
5477
+ config: t1,
5478
+ children: t7
5479
+ });
5480
+ $[11] = t7;
5481
+ $[12] = value.config;
5482
+ $[13] = t8;
5483
+ } else t8 = $[13];
5484
+ return t8;
5485
+ }
5486
+ //#endregion
5251
5487
  //#region src/configurator/UIConfigurator.tsx
5252
5488
  const colorNamespaces = {
5253
5489
  surface: "Surfaces",
@@ -5346,64 +5582,6 @@ function groupKeyFor(section, name, defaults) {
5346
5582
  const textStyle = section === "Typography" ? name.match(/^--text-(.+?)(?:--.+)?$/)?.[1] : void 0;
5347
5583
  return textStyle ? `--text-${textStyle}` : section === "Typography" ? name.startsWith("--font-weight-") ? "Font weights" : name.startsWith("--font-") ? "Font families" : "Letter spacing" : section === "Colors" ? baseColorNames(defaults).has(name) ? `Base system · ${name.slice(2).split("-")[0]}` : colorNamespaces[name.slice(2).split("-")[0]] ?? "Other" : section === "Spacing" || section === "Radius" || section === "Sizing" ? componentToken(name).title : section === "Effects" ? effectToken(name).title : "tokens";
5348
5584
  }
5349
- const ComponentGallery = lazy(() => import("./ComponentGallery-CMFrbwEN.js"));
5350
- function ComponentPreview(t0) {
5351
- const $ = c(14);
5352
- const { value, mode, inspector } = t0;
5353
- const { defaults } = useUIConfiguration();
5354
- const t1 = value.config;
5355
- const t2 = `studio-sample ${mode}`;
5356
- let t3;
5357
- if ($[0] !== defaults || $[1] !== mode || $[2] !== value.theme) {
5358
- t3 = previewTokens(defaults, value.theme, mode);
5359
- $[0] = defaults;
5360
- $[1] = mode;
5361
- $[2] = value.theme;
5362
- $[3] = t3;
5363
- } else t3 = $[3];
5364
- const t4 = t3;
5365
- let t5;
5366
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
5367
- t5 = /* @__PURE__ */ jsx("p", {
5368
- className: "studio-gallery-loading",
5369
- children: "Loading components…"
5370
- });
5371
- $[4] = t5;
5372
- } else t5 = $[4];
5373
- let t6;
5374
- if ($[5] !== inspector) {
5375
- t6 = /* @__PURE__ */ jsx(Suspense, {
5376
- fallback: t5,
5377
- children: /* @__PURE__ */ jsx(ComponentGallery, { inspector })
5378
- });
5379
- $[5] = inspector;
5380
- $[6] = t6;
5381
- } else t6 = $[6];
5382
- let t7;
5383
- if ($[7] !== t2 || $[8] !== t4 || $[9] !== t6) {
5384
- t7 = /* @__PURE__ */ jsx("div", {
5385
- className: t2,
5386
- style: t4,
5387
- "data-testid": "component-preview",
5388
- children: t6
5389
- });
5390
- $[7] = t2;
5391
- $[8] = t4;
5392
- $[9] = t6;
5393
- $[10] = t7;
5394
- } else t7 = $[10];
5395
- let t8;
5396
- if ($[11] !== t7 || $[12] !== value.config) {
5397
- t8 = /* @__PURE__ */ jsx(UIConfig.Provider, {
5398
- config: t1,
5399
- children: t7
5400
- });
5401
- $[11] = t7;
5402
- $[12] = value.config;
5403
- $[13] = t8;
5404
- } else t8 = $[13];
5405
- return t8;
5406
- }
5407
5585
  /** Changing a text style's font size sets its line height to this multiple of it; the line height stays editable. */
5408
5586
  const fontSizeLineHeight = "1.5";
5409
5587
  const remPresets = [
@@ -5621,7 +5799,7 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5621
5799
  return () => observer.disconnect();
5622
5800
  }, [studioWindow.ref]);
5623
5801
  const inherited = UIConfig.useConfig();
5624
- const { defaults, draft, setDraft, isOpen, cancel, apply, revision } = useUIConfiguration();
5802
+ const { defaults, draft, setDraft, isOpen, cancel, apply, revision, tokenRequest, clearTokenRequest, componentsHosted } = useUIConfiguration();
5625
5803
  const remembered = memory.current;
5626
5804
  const [mode, setMode] = useState(remembered.mode ?? "light");
5627
5805
  const [sizeUnit, setSizeUnit] = useState(remembered.sizeUnit ?? "px");
@@ -5708,7 +5886,7 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5708
5886
  setHighlightedToken(null);
5709
5887
  };
5710
5888
  const [highlightedToken, setHighlightedToken] = useState(null);
5711
- const isInspectable = useCallback((name) => (name in defaults.theme || name in defaults.light || name in defaults.dark) && groups.includes(groupFor(name)) && !name.startsWith("--color-"), [defaults]);
5889
+ const isInspectable = useCallback((name) => isEditableToken(name, defaults), [defaults]);
5712
5890
  const describeToken = useCallback((name_0) => {
5713
5891
  const section_0 = sectionFor(name_0);
5714
5892
  const bucket = mode === "dark" && name_0 in defaults.dark ? "dark" : name_0 in defaults.light ? "light" : "theme";
@@ -5746,10 +5924,20 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5746
5924
  }));
5747
5925
  setHighlightedToken(name_1);
5748
5926
  }, [defaults]);
5927
+ useEffect(() => {
5928
+ if (!tokenRequest) return;
5929
+ focusToken(tokenRequest.name);
5930
+ clearTokenRequest();
5931
+ }, [
5932
+ tokenRequest,
5933
+ focusToken,
5934
+ clearTokenRequest
5935
+ ]);
5749
5936
  useEffect(() => {
5750
5937
  if (!highlightedToken) return;
5751
5938
  const frame_0 = requestAnimationFrame(() => {
5752
- (editorRef.current?.ownerDocument.getElementById(`token-${highlightedToken}`)?.closest(".studio-token"))?.scrollIntoView({
5939
+ const doc = editorRef.current?.ownerDocument;
5940
+ (doc?.getElementById(`token-${highlightedToken}`)?.closest(".studio-token") ?? doc?.querySelector(`.studio-font-role[data-token="${CSS.escape(highlightedToken)}"]`))?.scrollIntoView({
5753
5941
  block: "center",
5754
5942
  behavior: "smooth"
5755
5943
  });
@@ -5886,17 +6074,17 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5886
6074
  const inActiveTab = (key_6) => !tabbed || tabFor(key_6) === activeSectionTab;
5887
6075
  const flatTab = tabbed && section === "Typography" && activeSectionTab !== textStylesTab;
5888
6076
  const orderedGroups = [...visibleGroups].filter(([key_7]) => inActiveTab(key_7)).sort(([a_0], [b_0]) => groupRank(a_0) - groupRank(b_0));
5889
- const collapsibleKeys = sectionKeys.filter(inActiveTab);
6077
+ const collapsibleKeys = sectionKeys.filter((key_8) => inActiveTab(key_8) && !groupedEntries.get(key_8)?.compact);
5890
6078
  const primaryGroup = collapsibleKeys[0];
5891
- const isExpanded = (key_8) => searching || (expandedGroups[`${section}:${key_8}`] ?? key_8 === primaryGroup);
5892
- const toggleGroup = (key_9) => setExpandedGroups((current_10) => ({
6079
+ const isExpanded = (key_9) => searching || (expandedGroups[`${section}:${key_9}`] ?? key_9 === primaryGroup);
6080
+ const toggleGroup = (key_10) => setExpandedGroups((current_10) => ({
5893
6081
  ...current_10,
5894
- [`${section}:${key_9}`]: !isExpanded(key_9)
6082
+ [`${section}:${key_10}`]: !isExpanded(key_10)
5895
6083
  }));
5896
6084
  const allExpanded = collapsibleKeys.every(isExpanded);
5897
6085
  const setAllGroups = (expanded) => setExpandedGroups((current_11) => ({
5898
6086
  ...current_11,
5899
- ...Object.fromEntries(collapsibleKeys.map((key_10) => [`${section}:${key_10}`, expanded]))
6087
+ ...Object.fromEntries(collapsibleKeys.map((key_11) => [`${section}:${key_11}`, expanded]))
5900
6088
  }));
5901
6089
  const groupChanged = (entries_1) => entries_1.some(([name_19]) => {
5902
6090
  const bucket_1 = mode === "dark" && name_19 in defaults.dark ? "dark" : name_19 in defaults.light ? "light" : "theme";
@@ -5970,7 +6158,9 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5970
6158
  options,
5971
6159
  changed: name_24 in draft.theme.theme,
5972
6160
  onChange: (value_12) => setToken(name_24, value_12),
5973
- onReset: () => setToken(name_24)
6161
+ onReset: () => setToken(name_24),
6162
+ token: name_24,
6163
+ highlighted: highlightedToken === name_24
5974
6164
  }, `${revision}-${resetRevision}-${name_24}`))
5975
6165
  }),
5976
6166
  /* @__PURE__ */ jsx(FontUpload, { onUpload: refreshLoadedFonts }),
@@ -5978,7 +6168,39 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5978
6168
  ]
5979
6169
  }, "font-families");
5980
6170
  };
6171
+ const textStyleColumns = [
6172
+ "Font size",
6173
+ "Line height",
6174
+ "Letter spacing"
6175
+ ];
6176
+ const textStyleColumn = (name_25) => name_25.endsWith("--line-height") ? 1 : name_25.endsWith("--letter-spacing") ? 2 : 0;
6177
+ const firstTextStyle = orderedGroups.find(([, group_3]) => group_3.compact)?.[0];
6178
+ /** One table row per text style, under a single column header; a style without a token leaves its cell empty. */
6179
+ const renderTextStyleRow = (key_12, group_4) => /* @__PURE__ */ jsxs(Fragment, { children: [key_12 === firstTextStyle && /* @__PURE__ */ jsxs("div", {
6180
+ className: "studio-type-row studio-type-head",
6181
+ "aria-hidden": "true",
6182
+ children: [/* @__PURE__ */ jsx("span", { children: "Style" }), textStyleColumns.map((column) => /* @__PURE__ */ jsx("span", { children: column }, column))]
6183
+ }), /* @__PURE__ */ jsxs("div", {
6184
+ className: "studio-type-row",
6185
+ role: "group",
6186
+ "aria-label": group_4.title,
6187
+ children: [/* @__PURE__ */ jsxs("span", {
6188
+ className: "studio-type-name",
6189
+ children: [group_4.title, groupChanged(group_4.entries) && /* @__PURE__ */ jsx("span", {
6190
+ className: "studio-group-changed",
6191
+ "aria-label": "has changes"
6192
+ })]
6193
+ }), textStyleColumns.map((column_0, index) => {
6194
+ const entry_3 = group_4.entries.find(([name_26]) => textStyleColumn(name_26) === index);
6195
+ return /* @__PURE__ */ jsx("div", {
6196
+ className: "studio-type-cell",
6197
+ children: entry_3 && renderToken(entry_3, true)
6198
+ }, column_0);
6199
+ })]
6200
+ })] }, key_12);
5981
6201
  const showTabs = sectionTabList.length > 1 && isTokenSection(section);
6202
+ const overrideCount = `${changedCount} ${changedCount === 1 ? "override" : "overrides"}`;
6203
+ const footerStatus = Object.keys(invalidFields).length ? "Fix invalid values or reset before applying or exporting." : nothingToReset && !changedCount ? "No active changes to reset." : (popupBlocked ? "Allow pop-ups for this site, then try again." : message) || overrideCount;
5982
6204
  const toggleAllButton = isTokenSection(section) && !flatTab && collapsibleKeys.length > 1 && /* @__PURE__ */ jsxs("button", {
5983
6205
  type: "button",
5984
6206
  className: "studio-toggle-all",
@@ -5989,15 +6211,15 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
5989
6211
  "aria-hidden": "true"
5990
6212
  }), allExpanded ? "Collapse all" : "Expand all"]
5991
6213
  });
5992
- const selectControl = (label, key_11, field_1, options_0) => /* @__PURE__ */ jsxs("label", {
6214
+ const selectControl = (label, key_13, field_1, options_0) => /* @__PURE__ */ jsxs("label", {
5993
6215
  className: "studio-setting",
5994
6216
  children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("select", {
5995
6217
  "aria-label": label,
5996
- value: String(config[key_11][field_1]),
5997
- onChange: (event) => setComponent(key_11, field_1, event.target.value),
6218
+ value: String(config[key_13][field_1]),
6219
+ onChange: (event) => setComponent(key_13, field_1, event.target.value),
5998
6220
  children: options_0.map((option) => /* @__PURE__ */ jsx("option", { children: option }, option))
5999
6221
  })]
6000
- }, `${key_11}-${field_1}`);
6222
+ }, `${key_13}-${field_1}`);
6001
6223
  return /* @__PURE__ */ jsx(Overlay, {
6002
6224
  className: `studio-overlay${floating && !poppedOut ? " studio-overlay-floating" : ""}`,
6003
6225
  isOpen,
@@ -6008,13 +6230,15 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6008
6230
  children: /* @__PURE__ */ jsx(Surface, {
6009
6231
  className: `studio-modal${poppedOut ? " studio-modal-popout" : ""}`,
6010
6232
  ref: studioWindow.ref,
6233
+ "data-components-hosted": componentsHosted || void 0,
6011
6234
  children: /* @__PURE__ */ jsxs($f2ff30fde7b014be$export$3ddf2d174ce01153, {
6012
6235
  className: "studio-dialog",
6013
- "data-compact-preview": compactPreview || void 0,
6236
+ "data-compact-preview": compactPreview && !componentsHosted || void 0,
6014
6237
  style: { "--studio-editor-track": editorWidth ? `minmax(260px, ${editorWidth}px)` : void 0 },
6015
6238
  children: [
6016
6239
  /* @__PURE__ */ jsxs("header", {
6017
6240
  className: "studio-topbar",
6241
+ ...poppedOut ? {} : studioWindow.dragArea,
6018
6242
  children: [
6019
6243
  /* @__PURE__ */ jsx("div", {
6020
6244
  className: "studio-title",
@@ -6029,11 +6253,11 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6029
6253
  children: [/* @__PURE__ */ jsxs("div", {
6030
6254
  className: "studio-section-tabs",
6031
6255
  children: [
6032
- navSections.map((group_3) => /* @__PURE__ */ jsx("button", {
6033
- "aria-current": !compactPreview && (group_3 === "Layout" ? isLayoutKind(section) : section === group_3) ? "page" : void 0,
6034
- onClick: () => changeSection(group_3 === "Layout" ? lastLayoutSection : group_3),
6035
- children: group_3
6036
- }, group_3)),
6256
+ navSections.map((group_5) => /* @__PURE__ */ jsx("button", {
6257
+ "aria-current": !compactPreview && (group_5 === "Layout" ? isLayoutKind(section) : section === group_5) ? "page" : void 0,
6258
+ onClick: () => changeSection(group_5 === "Layout" ? lastLayoutSection : group_5),
6259
+ children: group_5
6260
+ }, group_5)),
6037
6261
  /* @__PURE__ */ jsx("span", {
6038
6262
  className: "studio-nav-divider",
6039
6263
  "aria-hidden": "true"
@@ -6044,7 +6268,7 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6044
6268
  children: "Advanced"
6045
6269
  })
6046
6270
  ]
6047
- }), /* @__PURE__ */ jsx("button", {
6271
+ }), !componentsHosted && /* @__PURE__ */ jsx("button", {
6048
6272
  type: "button",
6049
6273
  className: "studio-preview-tab",
6050
6274
  "aria-current": compactPreview ? "page" : void 0,
@@ -6053,20 +6277,37 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6053
6277
  const dialog = bodyRef.current?.parentElement;
6054
6278
  if (dialog) dialog.scrollTop = 0;
6055
6279
  },
6056
- children: "Live preview"
6280
+ children: "Components"
6057
6281
  })]
6058
6282
  }),
6059
6283
  /* @__PURE__ */ jsx("div", {
6060
6284
  className: "studio-topbar-controls",
6061
6285
  children: /* @__PURE__ */ jsxs("label", {
6062
6286
  className: "studio-search",
6063
- children: [/* @__PURE__ */ jsx(Search, { size: 14 }), /* @__PURE__ */ jsx("input", {
6064
- "aria-label": "Search tokens",
6065
- placeholder: "Search tokens",
6066
- value: search,
6067
- disabled: !isTokenSection(section),
6068
- onChange: (event_0) => setSearch(event_0.target.value)
6069
- })]
6287
+ title: "Search tokens",
6288
+ children: [
6289
+ /* @__PURE__ */ jsx(Search, { size: 14 }),
6290
+ /* @__PURE__ */ jsx("input", {
6291
+ "aria-label": "Search tokens",
6292
+ placeholder: "Search tokens",
6293
+ value: search,
6294
+ disabled: !isTokenSection(section),
6295
+ onChange: (event_0) => setSearch(event_0.target.value),
6296
+ onKeyDown: (event_1) => {
6297
+ if (event_1.key !== "Escape") return;
6298
+ event_1.stopPropagation();
6299
+ if (search) setSearch("");
6300
+ else event_1.currentTarget.blur();
6301
+ }
6302
+ }),
6303
+ search && /* @__PURE__ */ jsx("button", {
6304
+ type: "button",
6305
+ className: "studio-search-clear",
6306
+ "aria-label": "Clear search",
6307
+ onClick: () => setSearch(""),
6308
+ children: /* @__PURE__ */ jsx(X, { size: 12 })
6309
+ })
6310
+ ]
6070
6311
  })
6071
6312
  })
6072
6313
  ]
@@ -6074,413 +6315,413 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6074
6315
  /* @__PURE__ */ jsxs("div", {
6075
6316
  ref: bodyRef,
6076
6317
  className: "studio-body",
6077
- children: [
6078
- /* @__PURE__ */ jsxs("main", {
6079
- ref: editorRef,
6080
- className: "studio-editor",
6081
- onScroll: (event_1) => memory.current.editorScroll = event_1.currentTarget.scrollTop,
6082
- children: [
6083
- layoutSection ? /* @__PURE__ */ jsxs("div", {
6084
- className: "studio-subtabs-bar",
6085
- children: [/* @__PURE__ */ jsx("div", {
6086
- className: "studio-subtabs",
6087
- role: "tablist",
6088
- "aria-label": "Layout tokens",
6089
- children: layoutKinds.map((kind_0) => /* @__PURE__ */ jsxs("button", {
6090
- type: "button",
6091
- role: "tab",
6092
- "aria-selected": kind_0 === section,
6093
- onClick: () => changeSection(kind_0),
6094
- children: [kind_0, Object.keys(draft.theme.theme).some((name_25) => layoutKindFor(name_25) === kind_0) && /* @__PURE__ */ jsx("span", {
6095
- className: "studio-group-changed",
6096
- "aria-label": "has changes"
6097
- })]
6098
- }, kind_0))
6099
- }), toggleAllButton]
6100
- }) : showTabs ? /* @__PURE__ */ jsxs("div", {
6101
- className: "studio-subtabs-bar",
6102
- children: [/* @__PURE__ */ jsx("div", {
6103
- className: "studio-subtabs",
6104
- role: "tablist",
6105
- "aria-label": `${section} tokens`,
6106
- children: sectionTabList.map((tab_0) => /* @__PURE__ */ jsxs("button", {
6107
- type: "button",
6108
- role: "tab",
6109
- "aria-selected": !searching && tab_0 === activeSectionTab,
6110
- disabled: searching,
6111
- onClick: () => setSectionTabs((current_12) => ({
6112
- ...current_12,
6113
- [section]: tab_0
6114
- })),
6115
- children: [tab_0, groupChanged([...groupedEntries].filter(([key_12]) => tabFor(key_12) === tab_0).flatMap(([, group_4]) => group_4.entries)) && /* @__PURE__ */ jsx("span", {
6318
+ children: [/* @__PURE__ */ jsxs("main", {
6319
+ ref: editorRef,
6320
+ className: "studio-editor",
6321
+ onScroll: (event_2) => memory.current.editorScroll = event_2.currentTarget.scrollTop,
6322
+ children: [
6323
+ layoutSection ? /* @__PURE__ */ jsxs("div", {
6324
+ className: "studio-subtabs-bar",
6325
+ children: [/* @__PURE__ */ jsx("div", {
6326
+ className: "studio-subtabs",
6327
+ role: "tablist",
6328
+ "aria-label": "Layout tokens",
6329
+ children: layoutKinds.map((kind_0) => /* @__PURE__ */ jsxs("button", {
6330
+ type: "button",
6331
+ role: "tab",
6332
+ "aria-selected": kind_0 === section,
6333
+ onClick: () => changeSection(kind_0),
6334
+ children: [kind_0, Object.keys(draft.theme.theme).some((name_27) => layoutKindFor(name_27) === kind_0) && /* @__PURE__ */ jsx("span", {
6335
+ className: "studio-group-changed",
6336
+ "aria-label": "has changes"
6337
+ })]
6338
+ }, kind_0))
6339
+ }), toggleAllButton]
6340
+ }) : showTabs ? /* @__PURE__ */ jsxs("div", {
6341
+ className: "studio-subtabs-bar",
6342
+ children: [/* @__PURE__ */ jsx("div", {
6343
+ className: "studio-subtabs",
6344
+ role: "tablist",
6345
+ "aria-label": `${section} tokens`,
6346
+ children: sectionTabList.map((tab_0) => /* @__PURE__ */ jsxs("button", {
6347
+ type: "button",
6348
+ role: "tab",
6349
+ "aria-selected": !searching && tab_0 === activeSectionTab,
6350
+ disabled: searching,
6351
+ onClick: () => setSectionTabs((current_12) => ({
6352
+ ...current_12,
6353
+ [section]: tab_0
6354
+ })),
6355
+ children: [tab_0, groupChanged([...groupedEntries].filter(([key_14]) => tabFor(key_14) === tab_0).flatMap(([, group_6]) => group_6.entries)) && /* @__PURE__ */ jsx("span", {
6356
+ className: "studio-group-changed",
6357
+ "aria-label": "has changes"
6358
+ })]
6359
+ }, tab_0))
6360
+ }), toggleAllButton]
6361
+ }) : advancedSection ? /* @__PURE__ */ jsx("div", {
6362
+ className: "studio-subtabs-bar",
6363
+ children: /* @__PURE__ */ jsx("div", {
6364
+ className: "studio-subtabs",
6365
+ role: "tablist",
6366
+ "aria-label": "Advanced settings",
6367
+ children: advancedSections.map(([key_15, label_0]) => /* @__PURE__ */ jsxs("button", {
6368
+ type: "button",
6369
+ role: "tab",
6370
+ "aria-selected": key_15 === section,
6371
+ onClick: () => changeSection(key_15),
6372
+ children: [label_0, (key_15 === "Components" ? Object.keys(draft.config).length > 0 : key_15 === "Variants & overrides" && Object.keys(draft.overrides ?? {}).length > 0) && /* @__PURE__ */ jsx("span", {
6373
+ className: "studio-group-changed",
6374
+ "aria-label": "has changes"
6375
+ })]
6376
+ }, key_15))
6377
+ })
6378
+ }) : /* @__PURE__ */ jsxs("div", {
6379
+ className: "studio-editor-heading",
6380
+ children: [/* @__PURE__ */ jsx("h2", { children: section }), toggleAllButton]
6381
+ }),
6382
+ isTokenSection(section) && /* @__PURE__ */ jsxs(Fragment$1, { children: [layoutSection && !searching && /* @__PURE__ */ jsx(LayoutScaleControl, {
6383
+ kind: layoutSection,
6384
+ level: layoutLevelFor(defaults, draft.theme.theme, layoutSection),
6385
+ onChange: (level_0) => setLayoutLevel(layoutSection, level_0)
6386
+ }, layoutSection), /* @__PURE__ */ jsxs("div", {
6387
+ className: `studio-token-list ${section !== "Typography" ? "studio-token-list-inline" : "studio-token-list-rows"}`,
6388
+ children: [orderedGroups.map(([key_16, group_7]) => group_7.compact && !flatTab ? renderTextStyleRow(key_16, group_7) : group_7.title && !flatTab ? /* @__PURE__ */ jsxs("fieldset", {
6389
+ className: `studio-token-group ${group_7.compact ? "studio-type-style" : ""} ${!isExpanded(key_16) ? "is-collapsed" : ""}`,
6390
+ children: [/* @__PURE__ */ jsxs("legend", { children: [/* @__PURE__ */ jsxs("button", {
6391
+ type: "button",
6392
+ className: "studio-group-toggle",
6393
+ "aria-expanded": isExpanded(key_16),
6394
+ "aria-controls": `group-${section}-${key_16.replaceAll(" ", "-")}`,
6395
+ onClick: () => toggleGroup(key_16),
6396
+ children: [
6397
+ /* @__PURE__ */ jsx(ChevronRight, {
6398
+ size: 14,
6399
+ "aria-hidden": "true"
6400
+ }),
6401
+ group_7.title,
6402
+ groupChanged(group_7.entries) && /* @__PURE__ */ jsx("span", {
6116
6403
  className: "studio-group-changed",
6117
6404
  "aria-label": "has changes"
6118
- })]
6119
- }, tab_0))
6120
- }), toggleAllButton]
6121
- }) : advancedSection ? /* @__PURE__ */ jsx("div", {
6122
- className: "studio-subtabs-bar",
6123
- children: /* @__PURE__ */ jsx("div", {
6124
- className: "studio-subtabs",
6125
- role: "tablist",
6126
- "aria-label": "Advanced settings",
6127
- children: advancedSections.map(([key_13, label_0]) => /* @__PURE__ */ jsxs("button", {
6405
+ })
6406
+ ]
6407
+ }), section === "Colors" && isPaletteGroup(group_7.entries) && /* @__PURE__ */ jsx("span", {
6408
+ className: "studio-palette-actions",
6409
+ children: /* @__PURE__ */ jsx("button", {
6128
6410
  type: "button",
6129
- role: "tab",
6130
- "aria-selected": key_13 === section,
6131
- onClick: () => changeSection(key_13),
6132
- children: [label_0, (key_13 === "Components" ? Object.keys(draft.config).length > 0 : key_13 === "Variants & overrides" && Object.keys(draft.overrides ?? {}).length > 0) && /* @__PURE__ */ jsx("span", {
6133
- className: "studio-group-changed",
6134
- "aria-label": "has changes"
6411
+ className: "studio-palette-reset",
6412
+ "aria-label": `Reset ${group_7.title} palette`,
6413
+ title: "Reset every shade in this palette to its default",
6414
+ disabled: !groupChanged(group_7.entries),
6415
+ onClick: () => {
6416
+ for (const [name_28] of group_7.entries) setToken(name_28);
6417
+ },
6418
+ children: /* @__PURE__ */ jsx(RotateCcw, {
6419
+ size: 13,
6420
+ "aria-hidden": "true"
6421
+ })
6422
+ })
6423
+ })] }), /* @__PURE__ */ jsxs("div", {
6424
+ id: `group-${section}-${key_16.replaceAll(" ", "-")}`,
6425
+ hidden: !isExpanded(key_16),
6426
+ className: group_7.compact ? "studio-type-fields" : void 0,
6427
+ children: [section === "Colors" && isPaletteGroup(group_7.entries) && renderPaletteShades(group_7.title, group_7.entries), group_7.entries.map((entry_4) => renderToken(entry_4, group_7.compact))]
6428
+ })]
6429
+ }, key_16) : section === "Typography" && key_16 === "Font families" ? renderFontFamilies(group_7.entries) : group_7.entries.map((entry_5) => renderToken(entry_5))), !orderedGroups.length && /* @__PURE__ */ jsx("p", { children: "No matching tokens. Try a component name such as “button”." })]
6430
+ })] }),
6431
+ section === "Variants & overrides" && /* @__PURE__ */ jsx(CvaEditor, {
6432
+ slot: cvaSlot,
6433
+ setSlot: (slot) => {
6434
+ setCvaSlot(slot);
6435
+ setCvaVariants({});
6436
+ },
6437
+ onPreview: setCvaVariants
6438
+ }),
6439
+ section === "Presets" && /* @__PURE__ */ jsxs("div", {
6440
+ className: "studio-presets",
6441
+ children: [/* @__PURE__ */ jsx("p", {
6442
+ className: "studio-presets-intro",
6443
+ children: "A preset replaces your theme edits with its own. Component defaults and overrides stay as they are; Apply or Save theme keeps it, Cancel discards it."
6444
+ }), [appThemePreset, ...themePresets].map((preset_0) => {
6445
+ const active = isPresetActive(preset_0, defaults, draft.theme);
6446
+ const colors = presetEdits(preset_0, defaults).light;
6447
+ const swatch = (name_29) => `rgb(${colors[name_29] ?? defaults.light[name_29]})`;
6448
+ return /* @__PURE__ */ jsxs("div", {
6449
+ className: `studio-preset ${active ? "is-active" : ""}`,
6450
+ children: [
6451
+ /* @__PURE__ */ jsx("span", {
6452
+ className: "studio-preset-swatches",
6453
+ "aria-hidden": "true",
6454
+ children: [
6455
+ 50,
6456
+ 200,
6457
+ 500,
6458
+ 900,
6459
+ 950
6460
+ ].map((step) => /* @__PURE__ */ jsx("i", { style: { background: swatch(`--neutral-${step}-base`) } }, step))
6461
+ }),
6462
+ /* @__PURE__ */ jsxs("span", {
6463
+ className: "studio-preset-text",
6464
+ children: [/* @__PURE__ */ jsx("strong", { children: preset_0.label }), /* @__PURE__ */ jsx("span", { children: preset_0.description })]
6465
+ }),
6466
+ /* @__PURE__ */ jsx("button", {
6467
+ type: "button",
6468
+ className: active ? void 0 : "studio-primary",
6469
+ disabled: active,
6470
+ onClick: () => applyPreset(preset_0),
6471
+ children: active ? "Active" : "Apply preset"
6472
+ })
6473
+ ]
6474
+ }, preset_0.id);
6475
+ })]
6476
+ }),
6477
+ section === "Components" && /* @__PURE__ */ jsxs("div", {
6478
+ className: "studio-settings",
6479
+ children: [
6480
+ /* @__PURE__ */ jsx("h3", { children: "Editor" }),
6481
+ /* @__PURE__ */ jsxs("label", {
6482
+ className: "studio-setting",
6483
+ children: [/* @__PURE__ */ jsx("span", { children: "Size units" }), /* @__PURE__ */ jsxs("select", {
6484
+ "aria-label": "Size units",
6485
+ value: sizeUnit,
6486
+ onChange: (event_3) => setSizeUnit(event_3.target.value),
6487
+ children: [/* @__PURE__ */ jsx("option", {
6488
+ value: "px",
6489
+ children: "px"
6490
+ }), /* @__PURE__ */ jsx("option", {
6491
+ value: "rem",
6492
+ children: "rem"
6135
6493
  })]
6136
- }, key_13))
6494
+ })]
6495
+ }),
6496
+ /* @__PURE__ */ jsx("h3", { children: "Buttons" }),
6497
+ selectControl("Appearance", "button", "variant", [
6498
+ "contained",
6499
+ "outlined",
6500
+ "subtle",
6501
+ "ghost",
6502
+ "text"
6503
+ ]),
6504
+ selectControl("Button size", "button", "size", [
6505
+ "default",
6506
+ "sm",
6507
+ "s"
6508
+ ]),
6509
+ /* @__PURE__ */ jsx("h3", { children: "Inputs" }),
6510
+ selectControl("Input appearance", "input", "variant", ["outlined", "filled"]),
6511
+ selectControl("Label layout", "input", "as", [
6512
+ "default",
6513
+ "floating",
6514
+ "inline",
6515
+ "filter"
6516
+ ]),
6517
+ selectControl("Input size", "input", "size", ["default", "small"]),
6518
+ [
6519
+ "isClearable",
6520
+ "hideLabel",
6521
+ "alwaysShowClear"
6522
+ ].map((field_2) => /* @__PURE__ */ jsxs("label", {
6523
+ className: "studio-setting",
6524
+ children: [/* @__PURE__ */ jsx("span", { children: {
6525
+ isClearable: "Allow clearing",
6526
+ hideLabel: "Hide labels",
6527
+ alwaysShowClear: "Always show clear button"
6528
+ }[field_2] }), /* @__PURE__ */ jsx("input", {
6529
+ type: "checkbox",
6530
+ checked: config.input[field_2],
6531
+ onChange: (event_4) => setComponent("input", field_2, event_4.target.checked)
6532
+ })]
6533
+ }, field_2)),
6534
+ /* @__PURE__ */ jsx("h3", { children: "Rendering" }),
6535
+ /* @__PURE__ */ jsxs("label", {
6536
+ className: "studio-setting",
6537
+ children: [/* @__PURE__ */ jsxs("span", { children: ["Use static inputs until interaction", /* @__PURE__ */ jsx("small", { children: "Reduce work when rendering large forms." })] }), /* @__PURE__ */ jsx("input", {
6538
+ type: "checkbox",
6539
+ checked: config.renderStaticInput,
6540
+ onChange: (event_5) => setDraft((current_13) => ({
6541
+ ...current_13,
6542
+ config: {
6543
+ ...current_13.config,
6544
+ renderStaticInput: event_5.target.checked
6545
+ }
6546
+ }))
6547
+ })]
6548
+ }),
6549
+ /* @__PURE__ */ jsx("p", {
6550
+ className: "studio-help",
6551
+ children: "Component props override these defaults. The preview uses inherited defaults unless an example needs a specific state."
6137
6552
  })
6138
- }) : /* @__PURE__ */ jsxs("div", {
6139
- className: "studio-editor-heading",
6140
- children: [/* @__PURE__ */ jsx("h2", { children: section }), toggleAllButton]
6141
- }),
6142
- isTokenSection(section) && /* @__PURE__ */ jsxs(Fragment$1, { children: [layoutSection && !searching && /* @__PURE__ */ jsx(LayoutScaleControl, {
6143
- kind: layoutSection,
6144
- level: layoutLevelFor(defaults, draft.theme.theme, layoutSection),
6145
- onChange: (level_0) => setLayoutLevel(layoutSection, level_0)
6146
- }, layoutSection), /* @__PURE__ */ jsxs("div", {
6147
- className: `studio-token-list ${section !== "Typography" ? "studio-token-list-inline" : "studio-token-list-rows"}`,
6148
- children: [orderedGroups.map(([key_14, group_5]) => group_5.title && !flatTab ? /* @__PURE__ */ jsxs("fieldset", {
6149
- className: `studio-token-group ${group_5.compact ? "studio-type-style" : ""} ${!isExpanded(key_14) ? "is-collapsed" : ""}`,
6150
- children: [/* @__PURE__ */ jsxs("legend", { children: [/* @__PURE__ */ jsxs("button", {
6151
- type: "button",
6152
- className: "studio-group-toggle",
6153
- "aria-expanded": isExpanded(key_14),
6154
- "aria-controls": `group-${section}-${key_14.replaceAll(" ", "-")}`,
6155
- onClick: () => toggleGroup(key_14),
6156
- children: [
6157
- /* @__PURE__ */ jsx(ChevronRight, {
6158
- size: 14,
6159
- "aria-hidden": "true"
6160
- }),
6161
- group_5.title,
6162
- groupChanged(group_5.entries) && /* @__PURE__ */ jsx("span", {
6163
- className: "studio-group-changed",
6164
- "aria-label": "has changes"
6165
- })
6166
- ]
6167
- }), section === "Colors" && isPaletteGroup(group_5.entries) && /* @__PURE__ */ jsx("span", {
6168
- className: "studio-palette-actions",
6169
- children: /* @__PURE__ */ jsx("button", {
6170
- type: "button",
6171
- className: "studio-palette-reset",
6172
- "aria-label": `Reset ${group_5.title} palette`,
6173
- title: "Reset every shade in this palette to its default",
6174
- disabled: !groupChanged(group_5.entries),
6553
+ ]
6554
+ }),
6555
+ section === "Export" && /* @__PURE__ */ jsxs("div", {
6556
+ className: "studio-export",
6557
+ children: [
6558
+ /* @__PURE__ */ jsxs("div", {
6559
+ className: "studio-mode",
6560
+ children: [
6561
+ /* @__PURE__ */ jsx("button", {
6562
+ "aria-pressed": exportTab === "css",
6563
+ onClick: () => setExportTab("css"),
6564
+ children: "Tailwind CSS"
6565
+ }),
6566
+ /* @__PURE__ */ jsx("button", {
6567
+ "aria-pressed": exportTab === "config",
6568
+ onClick: () => setExportTab("config"),
6569
+ children: "UIConfig"
6570
+ }),
6571
+ /* @__PURE__ */ jsx("button", {
6572
+ "aria-pressed": exportTab === "overrides",
6573
+ onClick: () => setExportTab("overrides"),
6574
+ children: "UIOverrides"
6575
+ })
6576
+ ]
6577
+ }),
6578
+ /* @__PURE__ */ jsx("p", { children: exportTab === "css" ? "Import after your existing theme. Only changed tokens are included; light and dark colors remain separate." : exportTab === "overrides" ? "Merge these edited slots with your existing app overrides. New Tailwind classes require a rebuild." : "Wrap your application with this provider. Only changed component settings are included." }),
6579
+ /* @__PURE__ */ jsx("textarea", {
6580
+ ref: exportRef,
6581
+ "aria-label": "Exported configuration",
6582
+ readOnly: true,
6583
+ value: exportText,
6584
+ spellCheck: false
6585
+ }),
6586
+ /* @__PURE__ */ jsxs("div", {
6587
+ className: "studio-export-actions",
6588
+ children: [
6589
+ exportTab === "css" && themeWriter && /* @__PURE__ */ jsx("button", {
6590
+ disabled: savingTheme || !!Object.keys(invalidFields).length,
6591
+ title: `Save to ${themeWriter.file}`,
6592
+ onClick: async () => {
6593
+ setSavingTheme(true);
6594
+ setMessage("");
6595
+ try {
6596
+ await saveThemeCss(themeWriter, exportText);
6597
+ setMessage(`Saved theme to ${themeWriter.file}.`);
6598
+ } catch (error) {
6599
+ setMessage(error instanceof Error ? error.message : "Could not save theme.");
6600
+ } finally {
6601
+ setSavingTheme(false);
6602
+ }
6603
+ },
6604
+ children: savingTheme ? "Saving theme…" : "Save theme"
6605
+ }),
6606
+ /* @__PURE__ */ jsx("button", {
6607
+ disabled: !!Object.keys(invalidFields).length,
6608
+ onClick: async () => {
6609
+ try {
6610
+ await navigator.clipboard.writeText(exportText);
6611
+ setMessage("Copied to clipboard.");
6612
+ } catch {
6613
+ exportRef.current?.select();
6614
+ setMessage("Clipboard unavailable. The export is selected for manual copying.");
6615
+ }
6616
+ },
6617
+ children: "Copy code"
6618
+ }),
6619
+ /* @__PURE__ */ jsxs("button", {
6620
+ disabled: !!Object.keys(invalidFields).length,
6175
6621
  onClick: () => {
6176
- for (const [name_26] of group_5.entries) setToken(name_26);
6622
+ const url = URL.createObjectURL(new Blob([exportText], { type: "text/plain" }));
6623
+ const link = document.createElement("a");
6624
+ link.href = url;
6625
+ link.download = exportTab === "css" ? "povio-theme.css" : exportTab === "overrides" ? "povio-ui-overrides.ts" : "povio-ui-config.ts";
6626
+ link.click();
6627
+ setTimeout(() => URL.revokeObjectURL(url), 1e3);
6628
+ setMessage("Export downloaded.");
6177
6629
  },
6178
- children: /* @__PURE__ */ jsx(RotateCcw, {
6179
- size: 13,
6180
- "aria-hidden": "true"
6181
- })
6630
+ children: [/* @__PURE__ */ jsx(ArrowDownToLine, { size: 14 }), " Download"]
6182
6631
  })
6183
- })] }), /* @__PURE__ */ jsxs("div", {
6184
- id: `group-${section}-${key_14.replaceAll(" ", "-")}`,
6185
- hidden: !isExpanded(key_14),
6186
- className: group_5.compact ? "studio-type-fields" : void 0,
6187
- children: [section === "Colors" && isPaletteGroup(group_5.entries) && renderPaletteShades(group_5.title, group_5.entries), group_5.entries.map((entry_3) => renderToken(entry_3, group_5.compact))]
6188
- })]
6189
- }, key_14) : section === "Typography" && key_14 === "Font families" ? renderFontFamilies(group_5.entries) : group_5.entries.map((entry_4) => renderToken(entry_4))), !orderedGroups.length && /* @__PURE__ */ jsx("p", { children: "No matching tokens. Try a component name such as “button”." })]
6190
- })] }),
6191
- section === "Variants & overrides" && /* @__PURE__ */ jsx(CvaEditor, {
6192
- slot: cvaSlot,
6193
- setSlot: (slot) => {
6194
- setCvaSlot(slot);
6195
- setCvaVariants({});
6196
- },
6197
- onPreview: setCvaVariants
6198
- }),
6199
- section === "Presets" && /* @__PURE__ */ jsxs("div", {
6200
- className: "studio-presets",
6201
- children: [/* @__PURE__ */ jsx("p", {
6202
- className: "studio-presets-intro",
6203
- children: "A preset replaces your theme edits with its own. Component defaults and overrides stay as they are; Apply or Save theme keeps it, Cancel discards it."
6204
- }), [appThemePreset, ...themePresets].map((preset_0) => {
6205
- const active = isPresetActive(preset_0, defaults, draft.theme);
6206
- const colors = presetEdits(preset_0, defaults).light;
6207
- const swatch = (name_27) => `rgb(${colors[name_27] ?? defaults.light[name_27]})`;
6208
- return /* @__PURE__ */ jsxs("div", {
6209
- className: `studio-preset ${active ? "is-active" : ""}`,
6210
- children: [
6211
- /* @__PURE__ */ jsx("span", {
6212
- className: "studio-preset-swatches",
6213
- "aria-hidden": "true",
6214
- children: [
6215
- 50,
6216
- 200,
6217
- 500,
6218
- 900,
6219
- 950
6220
- ].map((step) => /* @__PURE__ */ jsx("i", { style: { background: swatch(`--neutral-${step}-base`) } }, step))
6221
- }),
6222
- /* @__PURE__ */ jsxs("span", {
6223
- className: "studio-preset-text",
6224
- children: [/* @__PURE__ */ jsx("strong", { children: preset_0.label }), /* @__PURE__ */ jsx("span", { children: preset_0.description })]
6225
- }),
6226
- /* @__PURE__ */ jsx("button", {
6227
- type: "button",
6228
- className: active ? void 0 : "studio-primary",
6229
- disabled: active,
6230
- onClick: () => applyPreset(preset_0),
6231
- children: active ? "Active" : "Apply preset"
6232
- })
6233
- ]
6234
- }, preset_0.id);
6235
- })]
6236
- }),
6237
- section === "Components" && /* @__PURE__ */ jsxs("div", {
6238
- className: "studio-settings",
6239
- children: [
6240
- /* @__PURE__ */ jsx("h3", { children: "Editor" }),
6241
- /* @__PURE__ */ jsxs("label", {
6242
- className: "studio-setting",
6243
- children: [/* @__PURE__ */ jsx("span", { children: "Size units" }), /* @__PURE__ */ jsxs("select", {
6244
- "aria-label": "Size units",
6245
- value: sizeUnit,
6246
- onChange: (event_2) => setSizeUnit(event_2.target.value),
6247
- children: [/* @__PURE__ */ jsx("option", {
6248
- value: "px",
6249
- children: "px"
6250
- }), /* @__PURE__ */ jsx("option", {
6251
- value: "rem",
6252
- children: "rem"
6253
- })]
6254
- })]
6255
- }),
6256
- /* @__PURE__ */ jsx("h3", { children: "Buttons" }),
6257
- selectControl("Appearance", "button", "variant", [
6258
- "contained",
6259
- "outlined",
6260
- "subtle",
6261
- "ghost",
6262
- "text"
6263
- ]),
6264
- selectControl("Button size", "button", "size", [
6265
- "default",
6266
- "sm",
6267
- "s"
6268
- ]),
6269
- /* @__PURE__ */ jsx("h3", { children: "Inputs" }),
6270
- selectControl("Input appearance", "input", "variant", ["outlined", "filled"]),
6271
- selectControl("Label layout", "input", "as", [
6272
- "default",
6273
- "floating",
6274
- "inline",
6275
- "filter"
6276
- ]),
6277
- selectControl("Input size", "input", "size", ["default", "small"]),
6278
- [
6279
- "isClearable",
6280
- "hideLabel",
6281
- "alwaysShowClear"
6282
- ].map((field_2) => /* @__PURE__ */ jsxs("label", {
6283
- className: "studio-setting",
6284
- children: [/* @__PURE__ */ jsx("span", { children: {
6285
- isClearable: "Allow clearing",
6286
- hideLabel: "Hide labels",
6287
- alwaysShowClear: "Always show clear button"
6288
- }[field_2] }), /* @__PURE__ */ jsx("input", {
6289
- type: "checkbox",
6290
- checked: config.input[field_2],
6291
- onChange: (event_3) => setComponent("input", field_2, event_3.target.checked)
6292
- })]
6293
- }, field_2)),
6294
- /* @__PURE__ */ jsx("h3", { children: "Rendering" }),
6295
- /* @__PURE__ */ jsxs("label", {
6296
- className: "studio-setting",
6297
- children: [/* @__PURE__ */ jsxs("span", { children: ["Use static inputs until interaction", /* @__PURE__ */ jsx("small", { children: "Reduce work when rendering large forms." })] }), /* @__PURE__ */ jsx("input", {
6298
- type: "checkbox",
6299
- checked: config.renderStaticInput,
6300
- onChange: (event_4) => setDraft((current_13) => ({
6301
- ...current_13,
6302
- config: {
6303
- ...current_13.config,
6304
- renderStaticInput: event_4.target.checked
6305
- }
6306
- }))
6307
- })]
6308
- }),
6309
- /* @__PURE__ */ jsx("p", {
6310
- className: "studio-help",
6311
- children: "Component props override these defaults. The preview uses inherited defaults unless an example needs a specific state."
6312
- })
6313
- ]
6314
- }),
6315
- section === "Export" && /* @__PURE__ */ jsxs("div", {
6316
- className: "studio-export",
6317
- children: [
6318
- /* @__PURE__ */ jsxs("div", {
6319
- className: "studio-mode",
6320
- children: [
6321
- /* @__PURE__ */ jsx("button", {
6322
- "aria-pressed": exportTab === "css",
6323
- onClick: () => setExportTab("css"),
6324
- children: "Tailwind CSS"
6325
- }),
6326
- /* @__PURE__ */ jsx("button", {
6327
- "aria-pressed": exportTab === "config",
6328
- onClick: () => setExportTab("config"),
6329
- children: "UIConfig"
6330
- }),
6331
- /* @__PURE__ */ jsx("button", {
6332
- "aria-pressed": exportTab === "overrides",
6333
- onClick: () => setExportTab("overrides"),
6334
- children: "UIOverrides"
6335
- })
6336
- ]
6337
- }),
6338
- /* @__PURE__ */ jsx("p", { children: exportTab === "css" ? "Import after your existing theme. Only changed tokens are included; light and dark colors remain separate." : exportTab === "overrides" ? "Merge these edited slots with your existing app overrides. New Tailwind classes require a rebuild." : "Wrap your application with this provider. Only changed component settings are included." }),
6339
- /* @__PURE__ */ jsx("textarea", {
6340
- ref: exportRef,
6341
- "aria-label": "Exported configuration",
6342
- readOnly: true,
6343
- value: exportText,
6344
- spellCheck: false
6345
- }),
6346
- /* @__PURE__ */ jsxs("div", {
6347
- className: "studio-export-actions",
6348
- children: [
6349
- exportTab === "css" && themeWriter && /* @__PURE__ */ jsx("button", {
6350
- disabled: savingTheme || !!Object.keys(invalidFields).length,
6351
- title: `Save to ${themeWriter.file}`,
6352
- onClick: async () => {
6353
- setSavingTheme(true);
6354
- setMessage("");
6355
- try {
6356
- await saveThemeCss(themeWriter, exportText);
6357
- setMessage(`Saved theme to ${themeWriter.file}.`);
6358
- } catch (error) {
6359
- setMessage(error instanceof Error ? error.message : "Could not save theme.");
6360
- } finally {
6361
- setSavingTheme(false);
6362
- }
6363
- },
6364
- children: savingTheme ? "Saving theme…" : "Save theme"
6365
- }),
6366
- /* @__PURE__ */ jsx("button", {
6367
- disabled: !!Object.keys(invalidFields).length,
6368
- onClick: async () => {
6369
- try {
6370
- await navigator.clipboard.writeText(exportText);
6371
- setMessage("Copied to clipboard.");
6372
- } catch {
6373
- exportRef.current?.select();
6374
- setMessage("Clipboard unavailable. The export is selected for manual copying.");
6375
- }
6376
- },
6377
- children: "Copy code"
6378
- }),
6379
- /* @__PURE__ */ jsxs("button", {
6380
- disabled: !!Object.keys(invalidFields).length,
6381
- onClick: () => {
6382
- const url = URL.createObjectURL(new Blob([exportText], { type: "text/plain" }));
6383
- const link = document.createElement("a");
6384
- link.href = url;
6385
- link.download = exportTab === "css" ? "povio-theme.css" : exportTab === "overrides" ? "povio-ui-overrides.ts" : "povio-ui-config.ts";
6386
- link.click();
6387
- setTimeout(() => URL.revokeObjectURL(url), 1e3);
6388
- setMessage("Export downloaded.");
6389
- },
6390
- children: [/* @__PURE__ */ jsx(ArrowDownToLine, { size: 14 }), " Download"]
6391
- })
6392
- ]
6393
- })
6394
- ]
6395
- })
6396
- ]
6397
- }),
6398
- /* @__PURE__ */ jsxs("aside", {
6399
- ref: previewRef,
6400
- className: "studio-preview",
6401
- onScroll: (event_5) => memory.current.previewScroll = event_5.currentTarget.scrollTop,
6402
- children: [
6403
- /* @__PURE__ */ jsxs("div", {
6404
- className: "studio-preview-heading",
6405
- children: [/* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("i", {}), " LIVE PREVIEW"] }), /* @__PURE__ */ jsxs("div", {
6406
- className: "studio-preview-actions",
6407
- children: [/* @__PURE__ */ jsx(ColorModeSwitch, {
6408
- value: mode,
6409
- onChange: setMode
6410
- }), isTokenSection(section) && /* @__PURE__ */ jsxs("div", {
6411
- className: "studio-mode studio-preview-modes",
6412
- role: "group",
6413
- "aria-label": "Preview mode",
6414
- children: [/* @__PURE__ */ jsx("button", {
6415
- type: "button",
6416
- "aria-pressed": previewMode === "gallery",
6417
- onClick: () => setPreviewMode("gallery"),
6418
- children: "Gallery"
6419
- }), /* @__PURE__ */ jsx("button", {
6420
- type: "button",
6421
- "aria-pressed": previewMode === "focused",
6422
- onClick: () => setPreviewMode("focused"),
6423
- children: "Token preview"
6424
- })]
6632
+ ]
6633
+ })
6634
+ ]
6635
+ })
6636
+ ]
6637
+ }), !componentsHosted && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("aside", {
6638
+ ref: previewRef,
6639
+ className: "studio-preview",
6640
+ onScroll: (event_6) => memory.current.previewScroll = event_6.currentTarget.scrollTop,
6641
+ children: [
6642
+ /* @__PURE__ */ jsxs("div", {
6643
+ className: "studio-preview-heading",
6644
+ children: [/* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("i", {}), " COMPONENTS"] }), /* @__PURE__ */ jsxs("div", {
6645
+ className: "studio-preview-actions",
6646
+ children: [/* @__PURE__ */ jsx(ColorModeSwitch, {
6647
+ value: mode,
6648
+ onChange: setMode
6649
+ }), isTokenSection(section) && /* @__PURE__ */ jsxs("div", {
6650
+ className: "studio-mode studio-preview-modes",
6651
+ role: "group",
6652
+ "aria-label": "Preview mode",
6653
+ children: [/* @__PURE__ */ jsx("button", {
6654
+ type: "button",
6655
+ "aria-pressed": previewMode === "gallery",
6656
+ onClick: () => setPreviewMode("gallery"),
6657
+ children: "Gallery"
6658
+ }), /* @__PURE__ */ jsx("button", {
6659
+ type: "button",
6660
+ "aria-pressed": previewMode === "focused",
6661
+ onClick: () => setPreviewMode("focused"),
6662
+ children: "Token preview"
6425
6663
  })]
6426
6664
  })]
6427
- }),
6428
- /* @__PURE__ */ jsx(PreviewInspector, {
6429
- revision: draft,
6430
- isKnown: isInspectable,
6431
- onSelect: focusToken,
6432
- onScroll: (scrollTop) => {
6433
- memory.current.previewScroll = scrollTop;
6434
- },
6435
- children: section === "Variants & overrides" || isTokenSection(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
6436
- variants: cvaVariants,
6437
- setVariants: setCvaVariants,
6438
- section,
6439
- slot: cvaSlot,
6440
- mode,
6441
- entries: visibleGroups.flatMap(([, group_6]) => group_6.entries)
6442
- }) : /* @__PURE__ */ jsx(ComponentPreview, {
6443
- value: draft,
6444
- mode,
6445
- inspector: {
6446
- isKnown: isInspectable,
6447
- describe: describeToken,
6448
- onSelect: focusToken,
6449
- revision: draft
6450
- }
6451
- })
6452
- }),
6453
- /* @__PURE__ */ jsx("p", {
6454
- className: "studio-preview-note",
6455
- children: section === "Variants & overrides" || previewMode === "focused" ? "Preview follows the current section. Variant controls affect only the preview." : "Click to pin or unpin an element. Use Interact to try components."
6665
+ })]
6666
+ }),
6667
+ /* @__PURE__ */ jsx(PreviewInspector, {
6668
+ revision: draft,
6669
+ isKnown: isInspectable,
6670
+ onSelect: focusToken,
6671
+ onScroll: (scrollTop) => {
6672
+ memory.current.previewScroll = scrollTop;
6673
+ },
6674
+ children: section === "Variants & overrides" || isTokenSection(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
6675
+ variants: cvaVariants,
6676
+ setVariants: setCvaVariants,
6677
+ section,
6678
+ slot: cvaSlot,
6679
+ mode,
6680
+ entries: visibleGroups.flatMap(([, group_8]) => group_8.entries)
6681
+ }) : /* @__PURE__ */ jsx(ComponentPreview, {
6682
+ value: draft,
6683
+ mode,
6684
+ inspector: {
6685
+ isKnown: isInspectable,
6686
+ describe: describeToken,
6687
+ onSelect: focusToken,
6688
+ revision: draft
6689
+ }
6456
6690
  })
6457
- ]
6458
- }),
6459
- /* @__PURE__ */ jsx(PanelResizeHandle, {
6460
- label: "Resize editor and preview",
6461
- column: 2,
6462
- width: editorWidth,
6463
- min: 260,
6464
- max: () => (bodyRef.current?.parentElement?.clientWidth ?? 0) - 320,
6465
- onResize: setEditorWidth,
6466
- onReset: () => setEditorWidth(void 0)
6467
- })
6468
- ]
6691
+ }),
6692
+ /* @__PURE__ */ jsx("p", {
6693
+ className: "studio-preview-note",
6694
+ children: section === "Variants & overrides" || previewMode === "focused" ? "Preview follows the current section. Variant controls affect only the preview." : "Click to pin or unpin an element. Use Interact to try components."
6695
+ })
6696
+ ]
6697
+ }), /* @__PURE__ */ jsx(PanelResizeHandle, {
6698
+ label: "Resize editor and preview",
6699
+ column: 2,
6700
+ width: editorWidth,
6701
+ min: 260,
6702
+ max: () => (bodyRef.current?.parentElement?.clientWidth ?? 0) - 320,
6703
+ onResize: setEditorWidth,
6704
+ onReset: () => setEditorWidth(void 0)
6705
+ })] })]
6469
6706
  }),
6470
6707
  /* @__PURE__ */ jsxs("footer", {
6471
6708
  className: "studio-footer",
6472
6709
  children: [
6473
- /* @__PURE__ */ jsxs("button", {
6710
+ /* @__PURE__ */ jsx("button", {
6711
+ className: "studio-footer-reset",
6712
+ "aria-label": "Reset all",
6713
+ title: "Reset all",
6474
6714
  onClick: () => {
6475
6715
  const hasChanges = !!changedCount || !!Object.keys(invalidFields).length;
6476
6716
  setNothingToReset(!hasChanges);
6477
6717
  setConfirmingReset(hasChanges);
6478
6718
  },
6479
- children: [/* @__PURE__ */ jsx(RotateCcw, { size: 14 }), " Reset all"]
6719
+ children: /* @__PURE__ */ jsx(RotateCcw, { size: 14 })
6480
6720
  }),
6481
6721
  /* @__PURE__ */ jsx("span", {
6482
6722
  role: "status",
6483
- children: Object.keys(invalidFields).length ? "Fix invalid values or reset before applying or exporting." : nothingToReset && !changedCount ? "No active changes to reset." : (popupBlocked ? "Allow pop-ups for this site, then try again." : message) || `${changedCount} overrides · Changes stay in this session`
6723
+ title: footerStatus === overrideCount ? `${overrideCount} · Changes stay in this session` : footerStatus,
6724
+ children: footerStatus
6484
6725
  }),
6485
6726
  /* @__PURE__ */ jsx("button", {
6486
6727
  onClick: () => cancel(),
@@ -6488,11 +6729,12 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6488
6729
  }),
6489
6730
  /* @__PURE__ */ jsxs("button", {
6490
6731
  className: "studio-primary",
6732
+ "aria-label": "Apply settings",
6491
6733
  disabled: !!Object.keys(invalidFields).length,
6492
6734
  onClick: () => {
6493
6735
  apply();
6494
6736
  },
6495
- children: [/* @__PURE__ */ jsx(Check, { size: 15 }), " Apply settings"]
6737
+ children: [/* @__PURE__ */ jsx(Check, { size: 14 }), " Apply"]
6496
6738
  })
6497
6739
  ]
6498
6740
  }),
@@ -6570,135 +6812,69 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, floating,
6570
6812
  })
6571
6813
  });
6572
6814
  }
6815
+ /** Where a floating configurator first opens; an editor-only window (components shown by the host) is narrower. */
6816
+ const floatingDefault = {
6817
+ left: 32,
6818
+ top: 80,
6819
+ width: 640,
6820
+ height: 720
6821
+ };
6822
+ const hostedFloatingWidth = 360;
6573
6823
  function UIConfigurationModal() {
6574
- const $ = c(28);
6575
- const { isOpen, revision, open, openFloating, floating } = useUIConfiguration();
6824
+ const { isOpen, revision, open, openFloating, floating, componentsHosted } = useUIConfiguration();
6576
6825
  const [minimized, setMinimized] = useState(false);
6577
6826
  const [hasLauncher, setHasLauncher] = useState(false);
6578
6827
  const restorePopout = useRef(false);
6579
6828
  const launcherPosition = useRef(null);
6580
- let t0;
6581
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6582
- t0 = () => setMinimized(false);
6583
- $[0] = t0;
6584
- } else t0 = $[0];
6585
- let t1;
6586
- if ($[1] !== revision) {
6587
- t1 = [revision];
6588
- $[1] = revision;
6589
- $[2] = t1;
6590
- } else t1 = $[2];
6591
- useEffect(t0, t1);
6592
- let t2;
6593
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
6594
- t2 = {};
6595
- $[3] = t2;
6596
- } else t2 = $[3];
6597
- const memory = useRef(t2);
6829
+ useEffect(() => setMinimized(false), [revision]);
6830
+ const memory = useRef({});
6598
6831
  const windowBounds = useRef(null);
6599
- let t3;
6600
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
6601
- t3 = {
6602
- left: 32,
6603
- top: 80,
6604
- width: 640,
6605
- height: 720
6606
- };
6607
- $[4] = t3;
6608
- } else t3 = $[4];
6609
- const floatingBounds = useRef(t3);
6832
+ const floatingBounds = useRef(floatingDefault);
6833
+ if (componentsHosted && floatingBounds.current === floatingDefault) floatingBounds.current = {
6834
+ ...floatingDefault,
6835
+ width: hostedFloatingWidth
6836
+ };
6610
6837
  const popout = useStudioPopout(isOpen && !minimized);
6611
- if ((!isOpen || minimized) && hasLauncher) {
6612
- let t4;
6613
- if ($[5] !== floating || $[6] !== isOpen || $[7] !== open || $[8] !== openFloating || $[9] !== popout) {
6614
- t4 = createPortal(/* @__PURE__ */ jsx(ConfigurationLauncher, {
6615
- position: launcherPosition,
6616
- onOpen: () => {
6617
- setMinimized(false);
6618
- if (!isOpen) {
6619
- if (floating) openFloating();
6620
- else open();
6621
- }
6622
- if (restorePopout.current) popout.open();
6623
- }
6624
- }), document.body);
6625
- $[5] = floating;
6626
- $[6] = isOpen;
6627
- $[7] = open;
6628
- $[8] = openFloating;
6629
- $[9] = popout;
6630
- $[10] = t4;
6631
- } else t4 = $[10];
6632
- return t4;
6633
- }
6838
+ if ((!isOpen || minimized) && hasLauncher) return createPortal(/* @__PURE__ */ jsx(ConfigurationLauncher, {
6839
+ position: launcherPosition,
6840
+ onOpen: () => {
6841
+ setMinimized(false);
6842
+ if (!isOpen) {
6843
+ if (floating) openFloating();
6844
+ else open();
6845
+ }
6846
+ if (restorePopout.current) popout.open();
6847
+ }
6848
+ }), document.body);
6634
6849
  if (!isOpen) return null;
6635
- const t4 = floating ? floatingBounds : windowBounds;
6636
- const t5 = !!popout.popup;
6637
- let t6;
6638
- let t7;
6639
- let t8;
6640
- if ($[11] !== popout) {
6641
- t6 = () => {
6850
+ const content = /* @__PURE__ */ jsx(ConfigurationModalContent, {
6851
+ memory,
6852
+ windowBounds: floating ? floatingBounds : windowBounds,
6853
+ floating,
6854
+ poppedOut: !!popout.popup,
6855
+ onPopout: () => {
6642
6856
  restorePopout.current = true;
6643
6857
  popout.open();
6644
- };
6645
- t7 = () => {
6858
+ },
6859
+ onDock: () => {
6646
6860
  restorePopout.current = false;
6647
6861
  popout.dock();
6648
- };
6649
- t8 = () => {
6862
+ },
6863
+ onMinimize: () => {
6650
6864
  restorePopout.current = !!popout.popup;
6651
6865
  setHasLauncher(true);
6652
6866
  setMinimized(true);
6653
6867
  popout.dock();
6654
- };
6655
- $[11] = popout;
6656
- $[12] = t6;
6657
- $[13] = t7;
6658
- $[14] = t8;
6659
- } else {
6660
- t6 = $[12];
6661
- t7 = $[13];
6662
- t8 = $[14];
6663
- }
6664
- let t9;
6665
- if ($[15] !== floating || $[16] !== popout.blocked || $[17] !== revision || $[18] !== t4 || $[19] !== t5 || $[20] !== t6 || $[21] !== t7 || $[22] !== t8) {
6666
- t9 = /* @__PURE__ */ jsx(ConfigurationModalContent, {
6667
- memory,
6668
- windowBounds: t4,
6669
- floating,
6670
- poppedOut: t5,
6671
- onPopout: t6,
6672
- onDock: t7,
6673
- onMinimize: t8,
6674
- popupBlocked: popout.blocked
6675
- }, revision);
6676
- $[15] = floating;
6677
- $[16] = popout.blocked;
6678
- $[17] = revision;
6679
- $[18] = t4;
6680
- $[19] = t5;
6681
- $[20] = t6;
6682
- $[21] = t7;
6683
- $[22] = t8;
6684
- $[23] = t9;
6685
- } else t9 = $[23];
6686
- const content = t9;
6687
- let t10;
6688
- if ($[24] !== content || $[25] !== floating || $[26] !== popout.popup) {
6689
- t10 = popout.popup ? createPortal(/* @__PURE__ */ jsx(StudioPopoutContext, {
6690
- value: true,
6691
- children: /* @__PURE__ */ jsx(UNSAFE_PortalProvider, {
6692
- getContainer: () => popout.popup.document.body,
6693
- children: content
6694
- })
6695
- }), popout.popup.document.body) : floating ? createPortal(content, document.body) : content;
6696
- $[24] = content;
6697
- $[25] = floating;
6698
- $[26] = popout.popup;
6699
- $[27] = t10;
6700
- } else t10 = $[27];
6701
- return t10;
6868
+ },
6869
+ popupBlocked: popout.blocked
6870
+ }, revision);
6871
+ return popout.popup ? createPortal(/* @__PURE__ */ jsx(StudioPopoutContext, {
6872
+ value: true,
6873
+ children: /* @__PURE__ */ jsx(UNSAFE_PortalProvider, {
6874
+ getContainer: () => popout.popup.document.body,
6875
+ children: content
6876
+ })
6877
+ }), popout.popup.document.body) : floating ? createPortal(content, document.body) : content;
6702
6878
  }
6703
6879
  //#endregion
6704
6880
  export { getBoxHighlights as a, UIConfigurationProvider as c, Pin as d, Moon as f, inspectTokens as i, useUIConfiguration as l, ColorModeSwitch as n, HighlightOverlay as o, inspectElement as r, InspectorDetails as s, UIConfigurationModal as t, Sun as u };