@povio/ui 5.0.0-rc.6 → 5.0.0-rc.7

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.
@@ -8,6 +8,7 @@ import { t as Info } from "../info-iUmX3uDk.js";
8
8
  import { a as checkboxDefinition, i as checkboxContentWrapperDefinition, o as checkboxGroupLabelDefinition, r as checkboxContentRowDefinition, s as checkboxIconDefinition, u as Minus } from "../CheckboxCheckmark-CpC3wlMs.js";
9
9
  import { i as Search, n as selectListBoxItemDefinition, r as selectInputTagsContentWrapperDefinition, t as selectPopoverDefinition } from "../selectDesktop.cva-CHAMxhfO.js";
10
10
  import { t as Upload } from "../upload-CXU83BJ4.js";
11
+ import { t as X } from "../x-B6vfz8Ps.js";
11
12
  import { t as clsx } from "../clsx-CnD0nOiA.js";
12
13
  import { n as StyleMergeUtils, r as cva, t as UIOverrides } from "../uiOverrides.context-BTCH9y5a.js";
13
14
  import { c as $7230ffa83bc0c2cf$export$ef03459518577ad4, i as $7230ffa83bc0c2cf$export$9d4c57ee4c6ffdd8, l as $7230ffa83bc0c2cf$export$fabf2dc03a41866e, n as $7230ffa83bc0c2cf$export$29f1550f4b0d4415, r as $7230ffa83bc0c2cf$export$4d86445c2cf5e3, s as $7230ffa83bc0c2cf$export$df3a06d6289f983e, t as $7230ffa83bc0c2cf$export$2881499e37b75b9a } from "../utils-Czcqspm7.js";
@@ -48,7 +49,8 @@ import { a as toastDefinition, i as toastContainerDefinition } from "../toast.cv
48
49
  import { t as linkDefinition } from "../link.cva-DMTHZiJG.js";
49
50
  import { t as tooltipWrapperTriggerDefinition } from "../tooltipWrapper.cva-BBQ4ic3D.js";
50
51
  import { C as validToken, S as toRgb, _ as parseThemeCss, 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";
51
- import $ahdqC$react, { Suspense, createContext, lazy, use, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
52
+ import { n as splitVariants, t as inspectTokens } from "../token-classes-Bfcx0get.js";
53
+ import $ahdqC$react, { Suspense, createContext, lazy, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
52
54
  import { c } from "react/compiler-runtime";
53
55
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
54
56
  import { mergeProps } from "react-aria/mergeProps";
@@ -69,7 +71,7 @@ import { UNSAFE_PortalProvider } from "react-aria";
69
71
  * This source code is licensed under the ISC license.
70
72
  * See the LICENSE file in the root directory of this source tree.
71
73
  */
72
- const __iconData$8 = {
74
+ const __iconData$9 = {
73
75
  name: "arrow-down-to-line",
74
76
  size: 24,
75
77
  node: [
@@ -87,8 +89,8 @@ const __iconData$8 = {
87
89
  }]
88
90
  ]
89
91
  };
90
- __iconData$8.node;
91
- const ArrowDownToLine = createLucideIcon(__iconData$8);
92
+ __iconData$9.node;
93
+ const ArrowDownToLine = createLucideIcon(__iconData$9);
92
94
  //#endregion
93
95
  //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/chevrons-up-down.mjs
94
96
  /**
@@ -97,7 +99,7 @@ const ArrowDownToLine = createLucideIcon(__iconData$8);
97
99
  * This source code is licensed under the ISC license.
98
100
  * See the LICENSE file in the root directory of this source tree.
99
101
  */
100
- const __iconData$7 = {
102
+ const __iconData$8 = {
101
103
  name: "chevrons-up-down",
102
104
  size: 24,
103
105
  node: [["path", {
@@ -108,8 +110,8 @@ const __iconData$7 = {
108
110
  key: "sgt6xg"
109
111
  }]]
110
112
  };
111
- __iconData$7.node;
112
- const ChevronsUpDown = createLucideIcon(__iconData$7);
113
+ __iconData$8.node;
114
+ const ChevronsUpDown = createLucideIcon(__iconData$8);
113
115
  //#endregion
114
116
  //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/external-link.mjs
115
117
  /**
@@ -118,7 +120,7 @@ const ChevronsUpDown = createLucideIcon(__iconData$7);
118
120
  * This source code is licensed under the ISC license.
119
121
  * See the LICENSE file in the root directory of this source tree.
120
122
  */
121
- const __iconData$6 = {
123
+ const __iconData$7 = {
122
124
  name: "external-link",
123
125
  size: 24,
124
126
  node: [
@@ -136,8 +138,8 @@ const __iconData$6 = {
136
138
  }]
137
139
  ]
138
140
  };
139
- __iconData$6.node;
140
- const ExternalLink = createLucideIcon(__iconData$6);
141
+ __iconData$7.node;
142
+ const ExternalLink = createLucideIcon(__iconData$7);
141
143
  //#endregion
142
144
  //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/moon.mjs
143
145
  /**
@@ -146,7 +148,7 @@ const ExternalLink = createLucideIcon(__iconData$6);
146
148
  * This source code is licensed under the ISC license.
147
149
  * See the LICENSE file in the root directory of this source tree.
148
150
  */
149
- const __iconData$5 = {
151
+ const __iconData$6 = {
150
152
  name: "moon",
151
153
  size: 24,
152
154
  node: [["path", {
@@ -154,8 +156,8 @@ const __iconData$5 = {
154
156
  key: "kfwtm"
155
157
  }]]
156
158
  };
157
- __iconData$5.node;
158
- const Moon = createLucideIcon(__iconData$5);
159
+ __iconData$6.node;
160
+ const Moon = createLucideIcon(__iconData$6);
159
161
  //#endregion
160
162
  //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/panel-top.mjs
161
163
  /**
@@ -164,7 +166,7 @@ const Moon = createLucideIcon(__iconData$5);
164
166
  * This source code is licensed under the ISC license.
165
167
  * See the LICENSE file in the root directory of this source tree.
166
168
  */
167
- const __iconData$4 = {
169
+ const __iconData$5 = {
168
170
  name: "panel-top",
169
171
  size: 24,
170
172
  node: [["rect", {
@@ -179,8 +181,29 @@ const __iconData$4 = {
179
181
  key: "1pudct"
180
182
  }]]
181
183
  };
184
+ __iconData$5.node;
185
+ const PanelTop = createLucideIcon(__iconData$5);
186
+ //#endregion
187
+ //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/pin.mjs
188
+ /**
189
+ * @license lucide-react v1.43.0 - ISC
190
+ *
191
+ * This source code is licensed under the ISC license.
192
+ * See the LICENSE file in the root directory of this source tree.
193
+ */
194
+ const __iconData$4 = {
195
+ name: "pin",
196
+ size: 24,
197
+ node: [["path", {
198
+ d: "M12 17v5",
199
+ key: "bb1du9"
200
+ }], ["path", {
201
+ d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z",
202
+ key: "1nkz8b"
203
+ }]]
204
+ };
182
205
  __iconData$4.node;
183
- const PanelTop = createLucideIcon(__iconData$4);
206
+ const Pin = createLucideIcon(__iconData$4);
184
207
  //#endregion
185
208
  //#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/plus.mjs
186
209
  /**
@@ -599,7 +622,7 @@ function UIConfigurationProvider(t0) {
599
622
  if ($[0] !== applied) {
600
623
  t1 = () => {
601
624
  setDraft(structuredClone(applied));
602
- setRevision(_temp$6);
625
+ setRevision(_temp$7);
603
626
  setOpen(true);
604
627
  };
605
628
  $[0] = applied;
@@ -709,7 +732,7 @@ function UIConfigurationProvider(t0) {
709
732
  } else t10 = $[33];
710
733
  return t10;
711
734
  }
712
- function _temp$6(value) {
735
+ function _temp$7(value) {
713
736
  return value + 1;
714
737
  }
715
738
  function useUIConfiguration() {
@@ -718,6 +741,1013 @@ function useUIConfiguration() {
718
741
  return context;
719
742
  }
720
743
  //#endregion
744
+ //#region src/configurator/inspector/HighlightOverlay.tsx
745
+ const arcs = {
746
+ topLeft: "M0 100 A100 100 0 0 1 100 0",
747
+ topRight: "M0 0 A100 100 0 0 1 100 100",
748
+ bottomRight: "M100 0 A100 100 0 0 1 0 100",
749
+ bottomLeft: "M100 100 A100 100 0 0 1 0 0"
750
+ };
751
+ function HighlightOverlay(t0) {
752
+ const $ = c(17);
753
+ const { highlight, width } = t0;
754
+ const first = highlight.regions[0];
755
+ let t1;
756
+ if ($[0] !== highlight.key) {
757
+ t1 = highlight.key.split(".");
758
+ $[0] = highlight.key;
759
+ $[1] = t1;
760
+ } else t1 = $[1];
761
+ const kind = t1[0];
762
+ const t2 = highlight.key;
763
+ let t3;
764
+ if ($[2] !== highlight.regions || $[3] !== kind) {
765
+ let t4;
766
+ if ($[5] !== kind) {
767
+ t4 = (region) => /* @__PURE__ */ jsx("div", {
768
+ className: `studio-measure-region is-${kind}${region.line ? ` is-${region.line}` : ""}${region.corner ? " is-corner" : ""}`,
769
+ style: {
770
+ left: region.left,
771
+ top: region.top,
772
+ width: region.width,
773
+ height: region.height
774
+ },
775
+ children: region.corner && /* @__PURE__ */ jsx("svg", {
776
+ viewBox: "0 0 100 100",
777
+ preserveAspectRatio: "none",
778
+ "aria-hidden": "true",
779
+ children: /* @__PURE__ */ jsx("path", {
780
+ d: arcs[region.corner],
781
+ fill: "none",
782
+ stroke: "currentColor",
783
+ strokeWidth: "2",
784
+ vectorEffect: "non-scaling-stroke"
785
+ })
786
+ })
787
+ }, `${region.left}:${region.top}:${region.width}:${region.height}`);
788
+ $[5] = kind;
789
+ $[6] = t4;
790
+ } else t4 = $[6];
791
+ t3 = highlight.regions.map(t4);
792
+ $[2] = highlight.regions;
793
+ $[3] = kind;
794
+ $[4] = t3;
795
+ } else t3 = $[4];
796
+ const t4 = Math.max(4, Math.min(first?.left ?? 4, width - 220));
797
+ const t5 = Math.max(4, (first?.top ?? 26) - 22);
798
+ let t6;
799
+ if ($[7] !== t4 || $[8] !== t5) {
800
+ t6 = {
801
+ left: t4,
802
+ top: t5
803
+ };
804
+ $[7] = t4;
805
+ $[8] = t5;
806
+ $[9] = t6;
807
+ } else t6 = $[9];
808
+ let t7;
809
+ if ($[10] !== highlight.label || $[11] !== t6) {
810
+ t7 = /* @__PURE__ */ jsx("span", {
811
+ className: "studio-measure-label",
812
+ style: t6,
813
+ children: highlight.label
814
+ });
815
+ $[10] = highlight.label;
816
+ $[11] = t6;
817
+ $[12] = t7;
818
+ } else t7 = $[12];
819
+ let t8;
820
+ if ($[13] !== highlight.key || $[14] !== t3 || $[15] !== t7) {
821
+ t8 = /* @__PURE__ */ jsxs("div", {
822
+ className: "studio-measure-regions",
823
+ "data-property": t2,
824
+ children: [t3, t7]
825
+ });
826
+ $[13] = highlight.key;
827
+ $[14] = t3;
828
+ $[15] = t7;
829
+ $[16] = t8;
830
+ } else t8 = $[16];
831
+ return t8;
832
+ }
833
+ //#endregion
834
+ //#region src/configurator/inspector/box-highlights.ts
835
+ const sides = [
836
+ "top",
837
+ "right",
838
+ "bottom",
839
+ "left"
840
+ ];
841
+ const corners = [
842
+ "topLeft",
843
+ "topRight",
844
+ "bottomRight",
845
+ "bottomLeft"
846
+ ];
847
+ const numeric = (value) => Number.parseFloat(value) || 0;
848
+ const formatted = (value) => String(Math.round(value * 100) / 100);
849
+ /** Read-only geometry in the inspected element's viewport (including pop-out documents). */
850
+ function getBoxHighlights(element, key) {
851
+ const view = element.ownerDocument.defaultView;
852
+ if (!view) return {
853
+ regions: [],
854
+ label: ""
855
+ };
856
+ const style = view.getComputedStyle(element);
857
+ const rect = element.getBoundingClientRect();
858
+ const sx = element.offsetWidth ? rect.width / element.offsetWidth : 1;
859
+ const sy = element.offsetHeight ? rect.height / element.offsetHeight : 1;
860
+ const read = (name) => style.getPropertyValue(name);
861
+ const scale = (side) => side === "left" || side === "right" ? sx : sy;
862
+ const values = (prefix, suffix = "") => Object.fromEntries(sides.map((side) => [side, numeric(read(`${prefix}-${side}${suffix}`)) * scale(side)]));
863
+ const border = values("border", "-width");
864
+ const padding = values("padding");
865
+ const inner = {
866
+ left: rect.left + border.left,
867
+ top: rect.top + border.top,
868
+ width: Math.max(0, rect.width - border.left - border.right),
869
+ height: Math.max(0, rect.height - border.top - border.bottom)
870
+ };
871
+ const content = {
872
+ left: inner.left + padding.left,
873
+ top: inner.top + padding.top,
874
+ width: Math.max(0, inner.width - padding.left - padding.right),
875
+ height: Math.max(0, inner.height - padding.top - padding.bottom)
876
+ };
877
+ const [kind, part] = key.split(".");
878
+ let regions = [];
879
+ let value = "";
880
+ if (kind === "width" || kind === "height") {
881
+ value = formatted(content[kind] / (kind === "width" ? sx : sy));
882
+ regions = [{
883
+ left: content.left,
884
+ top: content.top,
885
+ width: kind === "width" ? content.width : 1,
886
+ height: kind === "height" ? content.height : 1,
887
+ line: kind === "width" ? "horizontal" : "vertical"
888
+ }];
889
+ } else if (kind === "radius") {
890
+ const radii = corners.map((corner) => {
891
+ const cssCorner = corner.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
892
+ const components = read(`border-${cssCorner}-radius`).trim().split(/\s+/);
893
+ const resolve = (raw, dimension, factor) => raw.endsWith("%") ? numeric(raw) / 100 * dimension : numeric(raw) * factor;
894
+ return [resolve(components[0] || "0", rect.width, sx), resolve(components[1] || components[0] || "0", rect.height, sy)];
895
+ });
896
+ const factor = Math.min(1, rect.width / (radii[0][0] + radii[1][0] || 1), rect.width / (radii[3][0] + radii[2][0] || 1), rect.height / (radii[0][1] + radii[3][1] || 1), rect.height / (radii[1][1] + radii[2][1] || 1));
897
+ const corner = part;
898
+ const radius = radii[corners.indexOf(corner)];
899
+ const width = Math.max(1, radius[0] * factor);
900
+ const height = Math.max(1, radius[1] * factor);
901
+ value = `${formatted(radius[0] * factor / sx)} × ${formatted(radius[1] * factor / sy)}`;
902
+ regions = [{
903
+ left: rect.left + (corner.endsWith("Right") ? rect.width - width : 0),
904
+ top: rect.top + (corner.startsWith("bottom") ? rect.height - height : 0),
905
+ width,
906
+ height,
907
+ corner
908
+ }];
909
+ } else if (kind === "gap") {
910
+ const row = part === "row";
911
+ const rawGap = read(`${part}-gap`);
912
+ const gap = rawGap.endsWith("%") ? numeric(rawGap) / 100 * (row ? content.height / sy : content.width / sx) : numeric(rawGap);
913
+ const size = gap * (row ? sy : sx);
914
+ value = formatted(gap);
915
+ if (size > 0 && /^(inline-)?(flex|grid)$/.test(read("display"))) {
916
+ const children = Array.from(element.children).slice(0, 80).flatMap((child) => {
917
+ const childStyle = view.getComputedStyle(child);
918
+ const box = child.getBoundingClientRect();
919
+ return childStyle.display === "none" || childStyle.visibility === "hidden" || /^(absolute|fixed)$/.test(childStyle.position) || !box.width || !box.height ? [] : [box];
920
+ }).sort((a, b) => row ? a.top - b.top : a.left - b.left);
921
+ const seen = /* @__PURE__ */ new Set();
922
+ for (let i = 0; i < children.length; i++) {
923
+ const a = children[i];
924
+ for (let j = i + 1; j < children.length; j++) {
925
+ const b = children[j];
926
+ const start = row ? a.bottom : a.right;
927
+ const end = row ? b.top : b.left;
928
+ const crossStart = Math.max(row ? a.left : a.top, row ? b.left : b.top, row ? content.left : content.top);
929
+ const crossEnd = Math.min(row ? a.right : a.bottom, row ? b.right : b.bottom, row ? content.left + content.width : content.top + content.height);
930
+ if (end - start < size - .5 || crossEnd <= crossStart) continue;
931
+ if (children.some((c, index) => index !== i && index !== j && (row ? c.top >= start && c.bottom <= end && c.right > crossStart && c.left < crossEnd : c.left >= start && c.right <= end && c.bottom > crossStart && c.top < crossEnd))) continue;
932
+ const axisStart = Math.max((start + end - size) / 2, row ? content.top : content.left);
933
+ const axisEnd = Math.min((start + end + size) / 2, row ? content.top + content.height : content.left + content.width);
934
+ if (axisEnd <= axisStart) continue;
935
+ const region = row ? {
936
+ left: crossStart,
937
+ top: axisStart,
938
+ width: crossEnd - crossStart,
939
+ height: axisEnd - axisStart
940
+ } : {
941
+ left: axisStart,
942
+ top: crossStart,
943
+ width: axisEnd - axisStart,
944
+ height: crossEnd - crossStart
945
+ };
946
+ const id = Object.values(region).map(formatted).join(",");
947
+ if (!seen.has(id)) {
948
+ seen.add(id);
949
+ regions.push(region);
950
+ }
951
+ }
952
+ }
953
+ }
954
+ } else {
955
+ const side = part;
956
+ const horizontal = side === "top" || side === "bottom";
957
+ const raw = read(kind === "position" ? side : `${kind}-${side}${kind === "border" ? "-width" : ""}`);
958
+ const amount = numeric(raw) * scale(side);
959
+ value = formatted(numeric(raw));
960
+ const base = kind === "padding" ? inner : rect;
961
+ const outward = kind === "margin" || kind === "position";
962
+ const thickness = Math.max(1, Math.abs(amount));
963
+ const positiveEdge = side === "bottom" || side === "right";
964
+ const edge = horizontal ? base.top + (positiveEdge ? base.height : 0) : base.left + (positiveEdge ? base.width : 0);
965
+ const offset = outward ? positiveEdge ? amount < 0 ? -thickness : 0 : amount < 0 ? 0 : -thickness : positiveEdge ? -thickness : 0;
966
+ regions = [{
967
+ left: horizontal ? base.left : edge + offset,
968
+ top: horizontal ? edge + offset : base.top,
969
+ width: horizontal ? base.width : thickness,
970
+ height: horizontal ? thickness : base.height
971
+ }];
972
+ if (kind === "position") {
973
+ if (raw === "auto" || read("position") === "static") regions = [];
974
+ else if (read("position") === "absolute" || read("position") === "fixed") {
975
+ const parent = element.offsetParent;
976
+ const parentRect = parent?.getBoundingClientRect();
977
+ const parentStyle = parent ? view.getComputedStyle(parent) : null;
978
+ const parentScale = parent && "offsetWidth" in parent && parent.offsetWidth ? parentRect.width / Number(parent.offsetWidth) : 1;
979
+ const parentScaleY = parent && "offsetHeight" in parent && parent.offsetHeight ? parentRect.height / Number(parent.offsetHeight) : 1;
980
+ const referenceEdge = (parentRect ? {
981
+ left: parentRect.left + numeric(parentStyle.getPropertyValue("border-left-width")) * parentScale,
982
+ right: parentRect.right - numeric(parentStyle.getPropertyValue("border-right-width")) * parentScale,
983
+ top: parentRect.top + numeric(parentStyle.getPropertyValue("border-top-width")) * parentScaleY,
984
+ bottom: parentRect.bottom - numeric(parentStyle.getPropertyValue("border-bottom-width")) * parentScaleY
985
+ } : {
986
+ left: 0,
987
+ top: 0,
988
+ right: view.innerWidth,
989
+ bottom: view.innerHeight
990
+ })[side];
991
+ const targetEdge = edge + (positiveEdge ? 1 : -1) * numeric(read(`margin-${side}`)) * scale(side);
992
+ const start = Math.min(referenceEdge, targetEdge);
993
+ const length = Math.max(1, Math.abs(referenceEdge - targetEdge));
994
+ regions = [{
995
+ left: horizontal ? rect.left : start,
996
+ top: horizontal ? start : rect.top,
997
+ width: horizontal ? rect.width : length,
998
+ height: horizontal ? length : rect.height
999
+ }];
1000
+ }
1001
+ }
1002
+ }
1003
+ const name = key.replace(".", " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
1004
+ return {
1005
+ regions,
1006
+ label: `${name}: ${value} px`
1007
+ };
1008
+ }
1009
+ //#endregion
1010
+ //#region src/configurator/inspector/inspection-model.ts
1011
+ function readableColor(value) {
1012
+ const rgb = value.trim().match(/^rgb\(\s*(\d+)\s*[, ]\s*(\d+)\s*[, ]\s*(\d+)\s*\)$/);
1013
+ if (!rgb) return value;
1014
+ return `#${rgb.slice(1).map((channel) => Number(channel).toString(16).padStart(2, "0")).join("")}`;
1015
+ }
1016
+ function resolveToken(style, name, seen = /* @__PURE__ */ new Set()) {
1017
+ if (seen.has(name)) return "";
1018
+ seen.add(name);
1019
+ const value = style.getPropertyValue(name).trim();
1020
+ const reference = value.match(/^var\((--[\w-]+)\)$/);
1021
+ return reference ? resolveToken(style, reference[1], seen) : value;
1022
+ }
1023
+ /** Read-only inspection; always use the element's window, including detached previews. */
1024
+ function inspectElement(element, isKnown) {
1025
+ const view = element.ownerDocument.defaultView;
1026
+ if (!view) throw new Error("The inspected element has no document window.");
1027
+ const style = view.getComputedStyle(element);
1028
+ const rootFontSize = Number.parseFloat(view.getComputedStyle(element.ownerDocument.documentElement).fontSize) || 16;
1029
+ const bounds = element.getBoundingClientRect();
1030
+ const sides = [
1031
+ "top",
1032
+ "right",
1033
+ "bottom",
1034
+ "left"
1035
+ ];
1036
+ const readSides = (prefix, suffix = "") => Object.fromEntries(sides.map((side) => [side, style.getPropertyValue(`${prefix}${side}${suffix}`) || "0px"]));
1037
+ const padding = readSides("padding-");
1038
+ const border = readSides("border-", "-width");
1039
+ const margin = readSides("margin-");
1040
+ const contentDimension = (axis) => {
1041
+ const value = style.getPropertyValue(axis);
1042
+ const dimension = Number.parseFloat(value);
1043
+ const hasPixelDimension = /^\d+(?:\.\d+)?px$/.test(value);
1044
+ if (hasPixelDimension && style.getPropertyValue("box-sizing") !== "border-box") return dimension;
1045
+ const inset = (axis === "width" ? ["left", "right"] : ["top", "bottom"]).reduce((total, side) => total + (Number.parseFloat(padding[side]) || 0) + (Number.parseFloat(border[side]) || 0), 0);
1046
+ return Math.max(0, (hasPixelDimension ? dimension : bounds[axis]) - inset);
1047
+ };
1048
+ const box = {
1049
+ content: {
1050
+ width: contentDimension("width"),
1051
+ height: contentDimension("height")
1052
+ },
1053
+ padding,
1054
+ border,
1055
+ margin,
1056
+ radius: {
1057
+ topLeft: style.getPropertyValue("border-top-left-radius") || "0px",
1058
+ topRight: style.getPropertyValue("border-top-right-radius") || "0px",
1059
+ bottomRight: style.getPropertyValue("border-bottom-right-radius") || "0px",
1060
+ bottomLeft: style.getPropertyValue("border-bottom-left-radius") || "0px"
1061
+ },
1062
+ gap: {
1063
+ row: style.getPropertyValue("row-gap") || "normal",
1064
+ column: style.getPropertyValue("column-gap") || "normal"
1065
+ }
1066
+ };
1067
+ const position = style.getPropertyValue("position");
1068
+ if (position && position !== "static") box.position = readSides("");
1069
+ const classes = Array.from(element.classList);
1070
+ const plainClasses = classes.filter((name) => !splitVariants(name).variants.length && !name.includes("["));
1071
+ const spacing = inspectTokens(plainClasses.join(" "), isKnown);
1072
+ const candidates = (prefix, namespaces) => plainClasses.flatMap((raw) => {
1073
+ const utility = raw.replace(/^!|!$/g, "");
1074
+ if (!utility.startsWith(`${prefix}-`)) return [];
1075
+ const suffix = utility.slice(prefix.length + 1);
1076
+ return namespaces.map((namespace) => `--${namespace}${suffix}`);
1077
+ });
1078
+ const variantsAffect = (prefixes) => classes.some((raw) => {
1079
+ const { variants, utility } = splitVariants(raw);
1080
+ return variants.length > 0 && prefixes.some((prefix) => utility.replace(/^!/, "").startsWith(`${prefix}-`));
1081
+ });
1082
+ const equivalent = (value, computed, property) => {
1083
+ if (!value) return false;
1084
+ if (property.includes("color")) {
1085
+ if (value.match(/^\d+(?:\.\d+)?\s+\d+(?:\.\d+)?\s+\d+(?:\.\d+)?$/)) value = `rgb(${value})`;
1086
+ return readableColor(value).toLowerCase() === readableColor(computed).toLowerCase();
1087
+ }
1088
+ const length = value.match(/^(-?\d+(?:\.\d+)?)(rem|px|em)$/);
1089
+ if (length && computed.endsWith("px")) {
1090
+ let factor = 1;
1091
+ if (length[2] === "rem") factor = rootFontSize;
1092
+ if (length[2] === "em") factor = Number.parseFloat(style.fontSize);
1093
+ return Math.abs(Number(length[1]) * factor - Number.parseFloat(computed)) < .02;
1094
+ }
1095
+ return value.replace(/["']/g, "").replace(/\s+/g, " ") === computed.replace(/["']/g, "").replace(/\s+/g, " ");
1096
+ };
1097
+ const property = (label, css, tokens = [], prefixes = []) => {
1098
+ const computed = style.getPropertyValue(css);
1099
+ const matching = variantsAffect(prefixes) ? [] : tokens.filter((token) => !!token && isKnown(token) && equivalent(resolveToken(style, token), computed, css));
1100
+ const token = [...new Set(matching)][0];
1101
+ const isColor = css.includes("color");
1102
+ return {
1103
+ label,
1104
+ value: isColor ? readableColor(computed) : computed,
1105
+ ...token ? { token } : {},
1106
+ ...isColor ? { color: computed } : {}
1107
+ };
1108
+ };
1109
+ const tag = element.tagName.toLowerCase();
1110
+ const role = element.getAttribute("role");
1111
+ const context = element.closest("[data-inspector-name]")?.getAttribute("data-inspector-name") || element.closest(".studio-gallery-card")?.querySelector(".studio-gallery-card-title")?.textContent?.trim();
1112
+ const description = (element.getAttribute("aria-label") || element.innerText || element.textContent || "").trim().replace(/\s+/g, " ").slice(0, 100);
1113
+ const name = context || role || tag;
1114
+ const paddingPrefixes = [
1115
+ "p",
1116
+ "px",
1117
+ "py",
1118
+ "pt",
1119
+ "pr",
1120
+ "pb",
1121
+ "pl",
1122
+ "ps",
1123
+ "pe"
1124
+ ];
1125
+ const layout = [
1126
+ {
1127
+ label: "Width",
1128
+ value: style.getPropertyValue("width") || `${bounds.width}px`
1129
+ },
1130
+ {
1131
+ label: "Height",
1132
+ value: style.getPropertyValue("height") || `${bounds.height}px`
1133
+ },
1134
+ property("Display", "display"),
1135
+ property("Position", "position"),
1136
+ ...sides.map((side) => property(`Padding ${side}`, `padding-${side}`, [spacing.padding[side]], paddingPrefixes)),
1137
+ ...sides.map((side) => property(`Margin ${side}`, `margin-${side}`)),
1138
+ property("Row gap", "row-gap", [spacing.gap.row], ["gap"]),
1139
+ property("Column gap", "column-gap", [spacing.gap.column], ["gap"]),
1140
+ property("Radius", "border-radius", [spacing.radius], ["rounded"]),
1141
+ ...sides.map((side) => property(`Border ${side} width`, `border-${side}-width`))
1142
+ ];
1143
+ const typography = [
1144
+ property("Font", "font-family", candidates("font", ["font-"]), ["font"]),
1145
+ property("Size", "font-size", candidates("text", ["text-"]), ["text"]),
1146
+ property("Weight", "font-weight", candidates("font", ["font-weight-"]), ["font"]),
1147
+ property("Line height", "line-height"),
1148
+ property("Letter spacing", "letter-spacing"),
1149
+ property("Alignment", "text-align")
1150
+ ];
1151
+ const appearance = [
1152
+ property("Text", "color", candidates("text", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["text"]),
1153
+ property("Fill", "background-color", candidates("bg", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["bg"]),
1154
+ property("Border", "border-top-color", candidates("border", ["color-", ""]).flatMap((token) => [token, `${token}-base`]), ["border"]),
1155
+ property("Opacity", "opacity"),
1156
+ property("Shadow", "box-shadow")
1157
+ ];
1158
+ const isZero = (value) => value.split(/\s+/).every((part) => /^-?0(?:\.0+)?(?:px|rem|em|%)?$/.test(part));
1159
+ const visibleProperty = (row) => {
1160
+ if (row.label === "Width" || row.label === "Height" || row.token) return true;
1161
+ const value = row.value.trim();
1162
+ if (!value) return false;
1163
+ if (/^(Padding|Margin|Border .* width|Row gap|Column gap|Radius)/.test(row.label) && (isZero(value) || value === "normal")) return false;
1164
+ if (row.label === "Position" && value === "static") return false;
1165
+ if (row.label === "Display" && ["inline", "block"].includes(value)) return false;
1166
+ if (row.label === "Shadow" && value === "none") return false;
1167
+ if (row.label === "Opacity" && Number(value) === 1) return false;
1168
+ if (row.label === "Fill" && (value === "transparent" || /^rgba?\([^)]*[,/]\s*0(?:\.0+)?%?\s*\)$/.test(value))) return false;
1169
+ if (row.label === "Border" && !(Number.parseFloat(border.top) > 0)) return false;
1170
+ if (row.label === "Line height" && value === "normal") return false;
1171
+ if (row.label === "Letter spacing" && (value === "normal" || isZero(value))) return false;
1172
+ if (row.label === "Alignment" && [
1173
+ "normal",
1174
+ "start",
1175
+ "left"
1176
+ ].includes(value)) return false;
1177
+ if (row.label === "Weight" && ["400", "normal"].includes(value)) return false;
1178
+ return true;
1179
+ };
1180
+ return {
1181
+ name,
1182
+ display: style.display,
1183
+ tag,
1184
+ description,
1185
+ width: bounds.width,
1186
+ height: bounds.height,
1187
+ box,
1188
+ groups: [
1189
+ {
1190
+ name: "Layout",
1191
+ properties: layout
1192
+ },
1193
+ {
1194
+ name: "Typography",
1195
+ properties: typography
1196
+ },
1197
+ {
1198
+ name: "Appearance",
1199
+ properties: appearance
1200
+ }
1201
+ ].map((group) => ({
1202
+ name: group.name,
1203
+ properties: group.properties.filter(visibleProperty)
1204
+ })).filter((group) => group.properties.length > 0)
1205
+ };
1206
+ }
1207
+ //#endregion
1208
+ //#region src/configurator/inspector/PreviewInspector.tsx
1209
+ /** Read the real element underneath the inert gallery's stretched zoom button. */
1210
+ function elementAtPoint(root, x, y) {
1211
+ const direct = root.ownerDocument.elementsFromPoint(x, y).find((element) => root.contains(element));
1212
+ if (!direct || direct.closest(".studio-inspect-layer")) return null;
1213
+ const demo = direct.closest(".studio-gallery-card")?.querySelector(".studio-gallery-demo");
1214
+ let hit = direct;
1215
+ if (demo) {
1216
+ const found = [demo, ...demo.querySelectorAll("*")].reverse().find((element) => {
1217
+ if (element.namespaceURI !== "http://www.w3.org/1999/xhtml" || element.closest(".sr-only")) return false;
1218
+ const rect = element.getBoundingClientRect();
1219
+ return rect.width > 1 && rect.height > 1 && x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
1220
+ });
1221
+ if (!found) return null;
1222
+ hit = found;
1223
+ }
1224
+ const semantic = hit.closest("button,input,textarea,select,a,label,[role],h1,h2,h3,h4,h5,h6,p");
1225
+ if (semantic && root.contains(semantic) && (!demo || demo.contains(semantic))) hit = semantic;
1226
+ if (hit.namespaceURI !== "http://www.w3.org/1999/xhtml" || hit === root || hit.classList.contains("studio-gallery-card-hit")) return null;
1227
+ return hit;
1228
+ }
1229
+ function PreviewInspector({ children, revision, isKnown, onSelect, onScroll }) {
1230
+ const selectionDescriptionId = useId();
1231
+ const rootRef = useRef(null);
1232
+ const targetRef = useRef(null);
1233
+ const frameRef = useRef(null);
1234
+ const pendingPoint = useRef(null);
1235
+ const pinnedRef = useRef(false);
1236
+ const [pinned, setPinned] = useState(false);
1237
+ const [inspectMode, setInspectMode] = useState(true);
1238
+ const [snapshot, setSnapshot] = useState(null);
1239
+ const [outline, setOutline] = useState(null);
1240
+ const highlightKey = useRef(null);
1241
+ const [highlight, setHighlight] = useState(null);
1242
+ const measure = useCallback(() => {
1243
+ const root = rootRef.current;
1244
+ const target = targetRef.current;
1245
+ if (!root || !target?.isConnected || !root.contains(target)) {
1246
+ targetRef.current = null;
1247
+ pinnedRef.current = false;
1248
+ setPinned(false);
1249
+ setSnapshot(null);
1250
+ setOutline(null);
1251
+ highlightKey.current = null;
1252
+ setHighlight(null);
1253
+ return;
1254
+ }
1255
+ const rect = target.getBoundingClientRect();
1256
+ if (!rect.width || !rect.height) {
1257
+ setSnapshot(null);
1258
+ setOutline(null);
1259
+ highlightKey.current = null;
1260
+ setHighlight(null);
1261
+ return;
1262
+ }
1263
+ const origin = root.getBoundingClientRect();
1264
+ const next = inspectElement(target, isKnown);
1265
+ setSnapshot((current) => JSON.stringify(current) === JSON.stringify(next) ? current : next);
1266
+ setOutline({
1267
+ left: rect.left - origin.left,
1268
+ top: rect.top - origin.top,
1269
+ width: rect.width,
1270
+ height: rect.height
1271
+ });
1272
+ if (highlightKey.current) {
1273
+ const details = getBoxHighlights(target, highlightKey.current);
1274
+ setHighlight({
1275
+ key: highlightKey.current,
1276
+ label: details.label,
1277
+ regions: details.regions.map((region) => ({
1278
+ width: region.width,
1279
+ height: region.height,
1280
+ corner: region.corner,
1281
+ line: region.line,
1282
+ left: region.left - origin.left,
1283
+ top: region.top - origin.top
1284
+ }))
1285
+ });
1286
+ }
1287
+ }, [isKnown]);
1288
+ const schedule = useCallback(() => {
1289
+ const owner = rootRef.current?.ownerDocument.defaultView;
1290
+ if (!owner || frameRef.current !== null) return;
1291
+ frameRef.current = owner.requestAnimationFrame(() => {
1292
+ frameRef.current = null;
1293
+ const root_0 = rootRef.current;
1294
+ const point = pendingPoint.current;
1295
+ pendingPoint.current = null;
1296
+ if (root_0 && point && !pinnedRef.current) {
1297
+ const hit = elementAtPoint(root_0, point.x, point.y);
1298
+ if (hit) targetRef.current = hit;
1299
+ }
1300
+ measure();
1301
+ });
1302
+ }, [measure]);
1303
+ useLayoutEffect(schedule, [schedule, revision]);
1304
+ useEffect(() => {
1305
+ const root_1 = rootRef.current;
1306
+ const owner_0 = root_1?.ownerDocument.defaultView;
1307
+ if (!root_1 || !owner_0) return;
1308
+ const observer = new ResizeObserver(schedule);
1309
+ observer.observe(root_1);
1310
+ const modal = root_1.closest(".studio-modal");
1311
+ if (modal) observer.observe(modal);
1312
+ const mutations = new MutationObserver((records) => {
1313
+ if (records.some((record) => {
1314
+ return !(record.target.nodeType === 1 ? record.target : record.target.parentElement)?.closest(".studio-hover-outline-layer");
1315
+ })) schedule();
1316
+ });
1317
+ mutations.observe(root_1, {
1318
+ subtree: true,
1319
+ childList: true,
1320
+ attributes: true,
1321
+ characterData: true
1322
+ });
1323
+ owner_0.addEventListener("scroll", schedule, true);
1324
+ owner_0.addEventListener("resize", schedule);
1325
+ return () => {
1326
+ observer.disconnect();
1327
+ mutations.disconnect();
1328
+ owner_0.removeEventListener("scroll", schedule, true);
1329
+ owner_0.removeEventListener("resize", schedule);
1330
+ if (frameRef.current !== null) owner_0.cancelAnimationFrame(frameRef.current);
1331
+ frameRef.current = null;
1332
+ };
1333
+ }, [schedule]);
1334
+ const showHighlight = useCallback((key) => {
1335
+ highlightKey.current = key;
1336
+ if (!key) {
1337
+ setHighlight(null);
1338
+ return;
1339
+ }
1340
+ const target_0 = targetRef.current;
1341
+ const canvas = rootRef.current;
1342
+ if (target_0 && canvas) {
1343
+ const rect_0 = target_0.getBoundingClientRect();
1344
+ const view = canvas.getBoundingClientRect();
1345
+ if (rect_0.bottom < view.top || rect_0.top > view.bottom || rect_0.right < view.left || rect_0.left > view.right) target_0.scrollIntoView({
1346
+ block: "nearest",
1347
+ inline: "nearest"
1348
+ });
1349
+ }
1350
+ schedule();
1351
+ }, [schedule]);
1352
+ const dismiss = () => {
1353
+ targetRef.current = null;
1354
+ pendingPoint.current = null;
1355
+ pinnedRef.current = false;
1356
+ setPinned(false);
1357
+ setSnapshot(null);
1358
+ setOutline(null);
1359
+ highlightKey.current = null;
1360
+ setHighlight(null);
1361
+ };
1362
+ return /* @__PURE__ */ jsxs("div", {
1363
+ className: `studio-hover-inspector${inspectMode || snapshot ? " has-inspector" : ""}`,
1364
+ onPointerMoveCapture: (event) => {
1365
+ if (event.target.closest(".studio-inspector-panel, .studio-inspector-toolbar")) return;
1366
+ if (!inspectMode) return;
1367
+ if (!pinnedRef.current) pendingPoint.current = {
1368
+ x: event.clientX,
1369
+ y: event.clientY
1370
+ };
1371
+ schedule();
1372
+ },
1373
+ onFocusCapture: (event_0) => {
1374
+ if (event_0.target.closest(".studio-inspector-panel, .studio-inspector-toolbar") || !inspectMode) return;
1375
+ if (pinnedRef.current || !rootRef.current) return;
1376
+ const element_0 = event_0.target;
1377
+ const rect_1 = element_0.getBoundingClientRect();
1378
+ targetRef.current = elementAtPoint(rootRef.current, rect_1.left + rect_1.width / 2, rect_1.top + rect_1.height / 2) ?? element_0;
1379
+ schedule();
1380
+ },
1381
+ onPointerDownCapture: (event_1) => {
1382
+ if (!inspectMode || event_1.target.closest(".studio-inspector-panel, .studio-inspector-toolbar, .studio-inspect-region")) return;
1383
+ event_1.preventDefault();
1384
+ event_1.stopPropagation();
1385
+ },
1386
+ onClickCapture: (event_2) => {
1387
+ const element_1 = event_2.target;
1388
+ if (!inspectMode || element_1.closest(".studio-inspector-panel, .studio-inspector-toolbar, .studio-inspect-region")) return;
1389
+ const root_2 = rootRef.current;
1390
+ if (!root_2) return;
1391
+ const rect_2 = element_1.getBoundingClientRect();
1392
+ const hit_0 = elementAtPoint(root_2, event_2.detail ? event_2.clientX : rect_2.left + rect_2.width / 2, event_2.detail ? event_2.clientY : rect_2.top + rect_2.height / 2);
1393
+ if (!hit_0) return;
1394
+ event_2.preventDefault();
1395
+ event_2.stopPropagation();
1396
+ if (pinnedRef.current && targetRef.current === hit_0) {
1397
+ pinnedRef.current = false;
1398
+ setPinned(false);
1399
+ schedule();
1400
+ return;
1401
+ }
1402
+ targetRef.current = hit_0;
1403
+ pendingPoint.current = null;
1404
+ pinnedRef.current = true;
1405
+ setPinned(true);
1406
+ schedule();
1407
+ },
1408
+ onKeyDownCapture: (event_3) => {
1409
+ if (inspectMode && rootRef.current?.contains(event_3.target) && [
1410
+ "ArrowLeft",
1411
+ "ArrowRight",
1412
+ "ArrowUp",
1413
+ "ArrowDown",
1414
+ "Home",
1415
+ "End",
1416
+ "PageUp",
1417
+ "PageDown"
1418
+ ].includes(event_3.key)) {
1419
+ event_3.preventDefault();
1420
+ event_3.stopPropagation();
1421
+ return;
1422
+ }
1423
+ if (event_3.key === "Escape" && snapshot && inspectMode) {
1424
+ event_3.preventDefault();
1425
+ event_3.stopPropagation();
1426
+ dismiss();
1427
+ }
1428
+ },
1429
+ children: [
1430
+ /* @__PURE__ */ jsxs("div", {
1431
+ className: "studio-inspector-toolbar",
1432
+ children: [/* @__PURE__ */ jsx("span", { children: pinned ? "Selection pinned" : "Hover to inspect · click to select" }), /* @__PURE__ */ jsxs("div", {
1433
+ className: "studio-mode",
1434
+ role: "group",
1435
+ "aria-label": "Preview interaction",
1436
+ children: [/* @__PURE__ */ jsx("button", {
1437
+ type: "button",
1438
+ "aria-pressed": inspectMode,
1439
+ onClick: () => setInspectMode(true),
1440
+ children: "Inspect"
1441
+ }), /* @__PURE__ */ jsx("button", {
1442
+ type: "button",
1443
+ "aria-pressed": !inspectMode,
1444
+ onClick: () => setInspectMode(false),
1445
+ children: "Interact"
1446
+ })]
1447
+ })]
1448
+ }),
1449
+ /* @__PURE__ */ jsxs("div", {
1450
+ className: "studio-inspector-canvas-shell",
1451
+ children: [/* @__PURE__ */ jsx("div", {
1452
+ ref: rootRef,
1453
+ className: "studio-inspector-canvas",
1454
+ onScroll: (event_4) => onScroll?.(event_4.currentTarget.scrollTop),
1455
+ children
1456
+ }), /* @__PURE__ */ jsxs("div", {
1457
+ className: "studio-hover-outline-layer",
1458
+ "aria-hidden": "true",
1459
+ children: [outline && snapshot && /* @__PURE__ */ jsx("div", {
1460
+ className: "studio-hover-outline",
1461
+ style: outline,
1462
+ children: !highlight && /* @__PURE__ */ jsxs("span", { children: [
1463
+ snapshot.name,
1464
+ " · ",
1465
+ Math.round(snapshot.width),
1466
+ " × ",
1467
+ Math.round(snapshot.height)
1468
+ ] })
1469
+ }), highlight && /* @__PURE__ */ jsx(HighlightOverlay, {
1470
+ highlight,
1471
+ width: rootRef.current?.clientWidth ?? 0
1472
+ })]
1473
+ })]
1474
+ }),
1475
+ (inspectMode || snapshot) && /* @__PURE__ */ jsxs("aside", {
1476
+ className: "studio-inspector-panel",
1477
+ "aria-label": "Inspector view",
1478
+ "aria-describedby": selectionDescriptionId,
1479
+ children: [
1480
+ /* @__PURE__ */ jsx("span", {
1481
+ id: selectionDescriptionId,
1482
+ hidden: true,
1483
+ children: snapshot ? `Inspecting ${snapshot.name}` : "No selected element"
1484
+ }),
1485
+ /* @__PURE__ */ jsxs("header", { children: [
1486
+ /* @__PURE__ */ jsx("strong", { children: "Inspector view" }),
1487
+ /* @__PURE__ */ jsx("button", {
1488
+ type: "button",
1489
+ "aria-label": "Pin inspected element",
1490
+ "aria-pressed": pinned,
1491
+ disabled: !snapshot,
1492
+ title: "Pin inspected element",
1493
+ onClick: () => {
1494
+ pinnedRef.current = !pinned;
1495
+ setPinned(!pinned);
1496
+ },
1497
+ children: /* @__PURE__ */ jsx(Pin, { size: 14 })
1498
+ }),
1499
+ /* @__PURE__ */ jsx("button", {
1500
+ type: "button",
1501
+ "aria-label": "Close inspector view",
1502
+ onClick: () => {
1503
+ dismiss();
1504
+ setInspectMode(false);
1505
+ },
1506
+ children: /* @__PURE__ */ jsx(X, { size: 15 })
1507
+ })
1508
+ ] }),
1509
+ snapshot ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("section", {
1510
+ className: "studio-inspector-layout",
1511
+ children: [/* @__PURE__ */ jsxs("div", {
1512
+ className: "studio-inspector-section-heading",
1513
+ children: [/* @__PURE__ */ jsx("h3", { children: "Layout" }), /* @__PURE__ */ jsx("span", {
1514
+ title: "CSS display",
1515
+ children: snapshot.display
1516
+ })]
1517
+ }), /* @__PURE__ */ jsx(BoxModel, {
1518
+ snapshot,
1519
+ onSelect,
1520
+ onHighlight: showHighlight
1521
+ })]
1522
+ }), snapshot.groups.map((group) => ({
1523
+ name: group.name,
1524
+ properties: group.properties.filter((property) => group.name !== "Layout" || ![
1525
+ "Width",
1526
+ "Height",
1527
+ "Margin",
1528
+ "Border width",
1529
+ "Radius",
1530
+ "Row gap",
1531
+ "Column gap",
1532
+ "Display"
1533
+ ].includes(property.label) && !/^(Padding |Margin |Border .* width$)/.test(property.label))
1534
+ })).filter((group_0) => group_0.properties.length).map((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: [
1535
+ property_0.color && /* @__PURE__ */ jsx("i", { style: { background: property_0.color } }),
1536
+ /* @__PURE__ */ jsx("span", { children: property_0.value }),
1537
+ property_0.token && /* @__PURE__ */ jsx("button", {
1538
+ type: "button",
1539
+ title: `Edit ${property_0.token}`,
1540
+ onClick: () => onSelect(property_0.token),
1541
+ children: property_0.token.replace(/^--/, "")
1542
+ })
1543
+ ] })] }, property_0.label)) })] }, group_1.name))] }) : /* @__PURE__ */ jsx("p", {
1544
+ className: "studio-inspector-empty",
1545
+ children: "Hover an element in the preview to inspect it. Click to pin your selection."
1546
+ })
1547
+ ]
1548
+ })
1549
+ ]
1550
+ });
1551
+ }
1552
+ function BoxModel(t0) {
1553
+ const $ = c(39);
1554
+ const { snapshot, onSelect, onHighlight } = t0;
1555
+ const box = snapshot.box;
1556
+ const number = _temp2$4;
1557
+ let t1;
1558
+ let t2;
1559
+ let t3;
1560
+ let t4;
1561
+ if ($[0] !== box.border || $[1] !== box.content.height || $[2] !== box.content.width || $[3] !== box.gap.column || $[4] !== box.gap.row || $[5] !== box.margin || $[6] !== box.padding || $[7] !== box.position || $[8] !== box.radius || $[9] !== onHighlight || $[10] !== onSelect || $[11] !== snapshot.groups) {
1562
+ const properties = snapshot.groups.flatMap(_temp3$3);
1563
+ const tokenFor = (label) => properties.find((property) => property.label === label)?.token;
1564
+ const nonzero = _temp5$1;
1565
+ let t5;
1566
+ if ($[16] !== onHighlight || $[17] !== onSelect) {
1567
+ t5 = (text, label_0, className, token, key) => /* @__PURE__ */ jsx("button", {
1568
+ type: "button",
1569
+ className,
1570
+ title: token ? `Edit ${token}` : `${label_0}: ${text}`,
1571
+ "aria-label": `${label_0}: ${text}`,
1572
+ "data-token": token,
1573
+ "data-box-highlight": key,
1574
+ onPointerEnter: () => onHighlight(key ?? null),
1575
+ onPointerLeave: () => onHighlight(null),
1576
+ onFocus: () => onHighlight(key ?? null),
1577
+ onBlur: () => onHighlight(null),
1578
+ onClick: () => token ? onSelect(token) : onHighlight(key ?? null),
1579
+ children: number(text)
1580
+ });
1581
+ $[16] = onHighlight;
1582
+ $[17] = onSelect;
1583
+ $[18] = t5;
1584
+ } else t5 = $[18];
1585
+ const value_1 = t5;
1586
+ const layer = (name, values, children) => /* @__PURE__ */ jsxs("div", {
1587
+ className: `studio-box-layer is-${name}`,
1588
+ style: name === "border" ? { borderRadius: [
1589
+ box.radius.topLeft,
1590
+ box.radius.topRight,
1591
+ box.radius.bottomRight,
1592
+ box.radius.bottomLeft
1593
+ ].map((radius) => nonzero(radius) ? "12px" : "0px").join(" ") } : void 0,
1594
+ children: [
1595
+ /* @__PURE__ */ jsx("span", {
1596
+ className: "studio-box-name",
1597
+ children: name
1598
+ }),
1599
+ [
1600
+ "top",
1601
+ "right",
1602
+ "bottom",
1603
+ "left"
1604
+ ].map((side) => /* @__PURE__ */ jsx("span", { children: value_1(values[side], `${name} ${side}`, `studio-box-value is-${side}`, tokenFor(`${name[0].toUpperCase()}${name.slice(1)} ${side}`), `${name}.${side}`) }, side)),
1605
+ name === "border" && Object.values(box.radius).some(nonzero) && Object.entries(box.radius).map((t6) => {
1606
+ const [corner, radius_0] = t6;
1607
+ return /* @__PURE__ */ jsx("span", { children: value_1(radius_0, `Radius ${corner}`, `studio-box-radius is-${corner}`, tokenFor("Radius"), `radius.${corner}`) }, corner);
1608
+ }),
1609
+ children
1610
+ ]
1611
+ });
1612
+ let t7;
1613
+ if ($[19] !== box.gap.row) {
1614
+ t7 = nonzero(box.gap.row);
1615
+ $[19] = box.gap.row;
1616
+ $[20] = t7;
1617
+ } else t7 = $[20];
1618
+ const hasRowGap = t7;
1619
+ let t8;
1620
+ if ($[21] !== box.gap.column) {
1621
+ t8 = nonzero(box.gap.column);
1622
+ $[21] = box.gap.column;
1623
+ $[22] = t8;
1624
+ } else t8 = $[22];
1625
+ const hasColumnGap = t8;
1626
+ const t9 = `${Math.round(box.content.width * 10) / 10}px`;
1627
+ let t10;
1628
+ if ($[23] !== t9 || $[24] !== value_1) {
1629
+ t10 = value_1(t9, "Content width", "studio-box-dimension-value", void 0, "width");
1630
+ $[23] = t9;
1631
+ $[24] = value_1;
1632
+ $[25] = t10;
1633
+ } else t10 = $[25];
1634
+ let t11;
1635
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
1636
+ t11 = /* @__PURE__ */ jsx("span", { children: "×" });
1637
+ $[26] = t11;
1638
+ } else t11 = $[26];
1639
+ const t12 = `${Math.round(box.content.height * 10) / 10}px`;
1640
+ let t13;
1641
+ if ($[27] !== t12 || $[28] !== value_1) {
1642
+ t13 = value_1(t12, "Content height", "studio-box-dimension-value", void 0, "height");
1643
+ $[27] = t12;
1644
+ $[28] = value_1;
1645
+ $[29] = t13;
1646
+ } else t13 = $[29];
1647
+ let t14;
1648
+ if ($[30] !== t10 || $[31] !== t13) {
1649
+ t14 = /* @__PURE__ */ jsx("div", {
1650
+ className: "studio-box-content",
1651
+ title: "Content width × height",
1652
+ children: /* @__PURE__ */ jsxs("div", {
1653
+ className: "studio-box-dimensions",
1654
+ children: [
1655
+ t10,
1656
+ t11,
1657
+ t13
1658
+ ]
1659
+ })
1660
+ });
1661
+ $[30] = t10;
1662
+ $[31] = t13;
1663
+ $[32] = t14;
1664
+ } else t14 = $[32];
1665
+ const content = t14;
1666
+ const diagram = layer("margin", box.margin, layer("border", box.border, layer("padding", box.padding, content)));
1667
+ t1 = "studio-box-model";
1668
+ t2 = "Box model";
1669
+ t3 = box.position ? layer("position", box.position, diagram) : diagram;
1670
+ t4 = (hasRowGap || hasColumnGap) && /* @__PURE__ */ jsx("div", {
1671
+ className: "studio-box-gaps",
1672
+ "aria-label": "Layout gaps",
1673
+ children: /* @__PURE__ */ jsxs("div", {
1674
+ className: "studio-gap-grid",
1675
+ style: {
1676
+ gridTemplateColumns: `minmax(0,1fr) ${hasColumnGap ? 28 : 0}px minmax(0,1fr)`,
1677
+ gridTemplateRows: `20px ${hasRowGap ? 22 : 0}px 20px`
1678
+ },
1679
+ children: [
1680
+ /* @__PURE__ */ jsx("i", {}),
1681
+ /* @__PURE__ */ jsx("i", {}),
1682
+ /* @__PURE__ */ jsx("i", {}),
1683
+ /* @__PURE__ */ jsx("i", {}),
1684
+ hasColumnGap && value_1(box.gap.column, "Column gap", "studio-gap-number is-column", tokenFor("Column gap"), "gap.column"),
1685
+ hasRowGap && value_1(box.gap.row, "Row gap", "studio-gap-number is-row", tokenFor("Row gap"), "gap.row")
1686
+ ]
1687
+ })
1688
+ });
1689
+ $[0] = box.border;
1690
+ $[1] = box.content.height;
1691
+ $[2] = box.content.width;
1692
+ $[3] = box.gap.column;
1693
+ $[4] = box.gap.row;
1694
+ $[5] = box.margin;
1695
+ $[6] = box.padding;
1696
+ $[7] = box.position;
1697
+ $[8] = box.radius;
1698
+ $[9] = onHighlight;
1699
+ $[10] = onSelect;
1700
+ $[11] = snapshot.groups;
1701
+ $[12] = t1;
1702
+ $[13] = t2;
1703
+ $[14] = t3;
1704
+ $[15] = t4;
1705
+ } else {
1706
+ t1 = $[12];
1707
+ t2 = $[13];
1708
+ t3 = $[14];
1709
+ t4 = $[15];
1710
+ }
1711
+ let t5;
1712
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
1713
+ t5 = /* @__PURE__ */ jsx("figcaption", { children: "Box model · px" });
1714
+ $[33] = t5;
1715
+ } else t5 = $[33];
1716
+ let t6;
1717
+ if ($[34] !== t1 || $[35] !== t2 || $[36] !== t3 || $[37] !== t4) {
1718
+ t6 = /* @__PURE__ */ jsxs("figure", {
1719
+ className: t1,
1720
+ "aria-label": t2,
1721
+ children: [
1722
+ t3,
1723
+ t4,
1724
+ t5
1725
+ ]
1726
+ });
1727
+ $[34] = t1;
1728
+ $[35] = t2;
1729
+ $[36] = t3;
1730
+ $[37] = t4;
1731
+ $[38] = t6;
1732
+ } else t6 = $[38];
1733
+ return t6;
1734
+ }
1735
+ function _temp5$1(value_0) {
1736
+ return value_0 !== "normal" && value_0.split(/\s+/).some(_temp4$3);
1737
+ }
1738
+ function _temp4$3(part) {
1739
+ return parseFloat(part) !== 0 && Number.isFinite(parseFloat(part));
1740
+ }
1741
+ function _temp3$3(group) {
1742
+ return group.properties;
1743
+ }
1744
+ function _temp2$4(value) {
1745
+ return value.replace(/(-?\d*\.?\d+)px/g, _temp$6);
1746
+ }
1747
+ function _temp$6(_, amount) {
1748
+ return String(Math.round(Number(amount) * 10) / 10);
1749
+ }
1750
+ //#endregion
721
1751
  //#region src/configurator/ConfigurationLauncher.tsx
722
1752
  function ConfigurationLauncher({ position, onOpen }) {
723
1753
  const ref = useRef(null);
@@ -4066,7 +5096,7 @@ function groupKeyFor(section, name, defaults) {
4066
5096
  const textStyle = section === "Typography" ? name.match(/^--text-(.+?)(?:--.+)?$/)?.[1] : void 0;
4067
5097
  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";
4068
5098
  }
4069
- const ComponentGallery = lazy(() => import("../ComponentGallery-C2tjrHWn.js"));
5099
+ const ComponentGallery = lazy(() => import("../ComponentGallery-Dp0kZVZM.js"));
4070
5100
  function ComponentPreview(t0) {
4071
5101
  const $ = c(14);
4072
5102
  const { value, mode, inspector } = t0;
@@ -4401,7 +5431,7 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, onPopout,
4401
5431
  useLayoutEffect(() => {
4402
5432
  const frame = requestAnimationFrame(() => {
4403
5433
  editorRef.current?.scrollTo({ top: memory.current.editorScroll ?? 0 });
4404
- previewRef.current?.scrollTo({ top: memory.current.previewScroll ?? 0 });
5434
+ previewRef.current?.querySelector(".studio-inspector-canvas")?.scrollTo({ top: memory.current.previewScroll ?? 0 });
4405
5435
  });
4406
5436
  return () => cancelAnimationFrame(frame);
4407
5437
  }, [memory]);
@@ -5143,26 +6173,34 @@ function ConfigurationModalContent({ memory, windowBounds, poppedOut, onPopout,
5143
6173
  })]
5144
6174
  })]
5145
6175
  }),
5146
- section === "Variants & overrides" || isTokenSection(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
5147
- variants: cvaVariants,
5148
- setVariants: setCvaVariants,
5149
- section,
5150
- slot: cvaSlot,
5151
- mode,
5152
- entries: visibleGroups.flatMap(([, group_6]) => group_6.entries)
5153
- }) : /* @__PURE__ */ jsx(ComponentPreview, {
5154
- value: draft,
5155
- mode,
5156
- inspector: {
5157
- isKnown: isInspectable,
5158
- describe: describeToken,
5159
- onSelect: focusToken,
5160
- revision: draft
5161
- }
6176
+ /* @__PURE__ */ jsx(PreviewInspector, {
6177
+ revision: draft,
6178
+ isKnown: isInspectable,
6179
+ onSelect: focusToken,
6180
+ onScroll: (scrollTop) => {
6181
+ memory.current.previewScroll = scrollTop;
6182
+ },
6183
+ children: section === "Variants & overrides" || isTokenSection(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
6184
+ variants: cvaVariants,
6185
+ setVariants: setCvaVariants,
6186
+ section,
6187
+ slot: cvaSlot,
6188
+ mode,
6189
+ entries: visibleGroups.flatMap(([, group_6]) => group_6.entries)
6190
+ }) : /* @__PURE__ */ jsx(ComponentPreview, {
6191
+ value: draft,
6192
+ mode,
6193
+ inspector: {
6194
+ isKnown: isInspectable,
6195
+ describe: describeToken,
6196
+ onSelect: focusToken,
6197
+ revision: draft
6198
+ }
6199
+ })
5162
6200
  }),
5163
6201
  /* @__PURE__ */ jsx("p", {
5164
6202
  className: "studio-preview-note",
5165
- children: section === "Variants & overrides" || previewMode === "focused" ? "Preview follows the current section. Variant controls affect only the preview." : "Click a component to inspect its padding, gaps and radius."
6203
+ 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."
5166
6204
  })
5167
6205
  ]
5168
6206
  }),