@povio/ui 5.0.0-rc.3 → 5.0.0-rc.4

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.
Files changed (126) hide show
  1. package/README.md +6 -2
  2. package/dist/{Breadcrumbs-CbKzAq1v.js → Breadcrumbs-FF8hMfXd.js} +1 -1
  3. package/dist/{Calendar-CVSQH-rC.js → Calendar-BTjajO6i.js} +6 -136
  4. package/dist/{Checkbox-BU0d702K.js → Checkbox-CV1ILXXO.js} +1 -1
  5. package/dist/{CheckboxCheckmark-usHsolNj.js → CheckboxCheckmark-CpC3wlMs.js} +1 -1
  6. package/dist/{ComponentGallery-DIFeJqGx.js → ComponentGallery-BWiPGUL8.js} +1343 -206
  7. package/dist/{DatePicker-D95gDPhg.js → DatePicker-DOLL7mkc.js} +12 -12
  8. package/dist/{DatePickerInput-CX6NYim4.js → DatePickerInput-BLBcySA2.js} +8 -7
  9. package/dist/{DateRangePicker-_uTQk_ae.js → DateRangePicker-BF-1CztH.js} +13 -185
  10. package/dist/{DateTimePicker-BB058Z34.js → DateTimePicker-Cj0qvJUz.js} +12 -12
  11. package/dist/{FileInput-C0-6bw4w.js → FileInput-Br5DQaGQ.js} +3 -2
  12. package/dist/{FileTrigger-CDXcQthK.js → FileTrigger-Cthk5_Wp.js} +1 -30
  13. package/dist/{FileUpload-DDpYMn8f.js → FileUpload--7ub3EZO.js} +3 -2
  14. package/dist/{FormField-U_-d4V_g.js → FormField-B99dLt8o.js} +1 -1
  15. package/dist/{FormFieldHeaderTooltip-DXbuu88v.js → FormFieldHeaderTooltip-BV2Ju4oB.js} +1 -1
  16. package/dist/{InlineTooltipWrapper-Bpmd--e7.js → InlineTooltipWrapper-BpApaGXV.js} +1 -1
  17. package/dist/{InputItem-D-KuiNSc.js → InputItem-CIxbTxZu.js} +10 -10
  18. package/dist/{Inputs-j3JmcLWR.js → Inputs-DJSKiaWY.js} +1 -1
  19. package/dist/NumberFormatter-CLDS_LRZ.js +265 -0
  20. package/dist/{NumberRangeInput-C-8U05wF.js → NumberRangeInput-B8-LHfg3.js} +6 -5
  21. package/dist/{RadioGroup-B7_pNwn9.js → RadioGroup-DOw3PRoX.js} +1 -1
  22. package/dist/{RichTextEditor-D9-B1Cze.js → RichTextEditor-D4yN7Wj7.js} +2 -2
  23. package/dist/{Select-CkujlTjm.js → Select-UR0ec2Ux.js} +2 -2
  24. package/dist/{Slider-BHPl0OPy.js → Slider-CzEmKYBF.js} +1 -1
  25. package/dist/{Table-BDNSuEWc.js → Table-piX1SWvN.js} +1 -1
  26. package/dist/{TextArea-DqHDiRGJ.js → TextArea-D8WkKsGn.js} +3 -3
  27. package/dist/{TimePicker-DQ6JCkGB.js → TimePicker-C4taAOFQ.js} +10 -9
  28. package/dist/{ToggleGroup-DX0VYXwP.js → ToggleGroup-DOk27fgI.js} +5 -66
  29. package/dist/{Tooltip-B9DKcYvr.js → Tooltip-CpG1nz7Y.js} +2 -2
  30. package/dist/{TooltipWrapper-DznDgVJB.js → TooltipWrapper-3jyN0Wss.js} +1 -1
  31. package/dist/components/autocomplete.js +2 -2
  32. package/dist/components/breadcrumbs.js +1 -1
  33. package/dist/components/checkbox-group.js +3 -3
  34. package/dist/components/checkbox.js +1 -1
  35. package/dist/components/date-picker.js +1 -1
  36. package/dist/components/date-range-picker.js +1 -1
  37. package/dist/components/date-time-picker.js +1 -1
  38. package/dist/components/file-input.js +1 -1
  39. package/dist/components/file-upload-container.js +1 -1
  40. package/dist/components/file-upload.js +1 -1
  41. package/dist/components/form-field.js +1 -1
  42. package/dist/components/icon-button.js +1 -1
  43. package/dist/components/input.js +4 -4
  44. package/dist/components/number-field.js +7 -6
  45. package/dist/components/number-range-input.js +1 -1
  46. package/dist/components/pagination.js +32 -28
  47. package/dist/components/query-autocomplete.js +1 -1
  48. package/dist/components/query-select.js +2 -2
  49. package/dist/components/radio-group.js +1 -1
  50. package/dist/components/select.js +1 -1
  51. package/dist/components/slider.js +1 -1
  52. package/dist/components/text-area.js +1 -1
  53. package/dist/components/time-picker.js +1 -1
  54. package/dist/components/toggle-group.js +1 -1
  55. package/dist/components/tooltip-ellipsis.js +1 -1
  56. package/dist/components/tooltip.js +1 -1
  57. package/dist/config/ui-configurator-theme.js +1 -1
  58. package/dist/config/ui-configurator.js +1081 -257
  59. package/dist/config/ui-router.js +1 -1
  60. package/dist/{datePickerValue.utils-CUzkWie8.js → datePickerValue.utils-DCgoSrP3.js} +5 -5
  61. package/dist/hooks/use-filters.js +1 -1
  62. package/dist/index.js +15 -15
  63. package/dist/numberStatic.utils-BX50PSee.js +421 -0
  64. package/dist/rhf/checkbox.js +1 -1
  65. package/dist/rhf/date-picker.js +1 -1
  66. package/dist/rhf/date-range-picker.js +1 -1
  67. package/dist/rhf/date-time-picker.js +1 -1
  68. package/dist/rhf/file-input.js +1 -1
  69. package/dist/rhf/file-upload.js +1 -1
  70. package/dist/rhf/number-range-input.js +1 -1
  71. package/dist/rhf/radio-group.js +1 -1
  72. package/dist/rhf/rich-text-editor.js +1 -1
  73. package/dist/rhf/select.js +1 -1
  74. package/dist/rhf/slider.js +1 -1
  75. package/dist/rhf/text-area.js +1 -1
  76. package/dist/rhf/time-picker.js +1 -1
  77. package/dist/rhf/toggle-group.js +1 -1
  78. package/dist/rhf.js +15 -15
  79. package/dist/rich-text-editor.js +1 -1
  80. package/dist/{router.context-B0jTMtE0.js → router.context-B4FvsTim.js} +2 -2
  81. package/dist/staticDateTimeSegments-DtU63_dw.js +1764 -0
  82. package/dist/{staticSelect.utils-BemUyaaA.js → staticSelect.utils-uHa8f_c6.js} +5 -144
  83. package/dist/styles/configurator.css +731 -218
  84. package/dist/{table.cva-BikE8qJH.js → table.cva-DlMT-zLD.js} +2 -3
  85. package/dist/tanstack/checkbox.js +1 -1
  86. package/dist/tanstack/date-picker.js +1 -1
  87. package/dist/tanstack/date-range-picker.js +1 -1
  88. package/dist/tanstack/date-time-picker.js +1 -1
  89. package/dist/tanstack/file-input.js +1 -1
  90. package/dist/tanstack/file-upload.js +1 -1
  91. package/dist/tanstack/form.js +1 -1
  92. package/dist/tanstack/inputs.js +1 -1
  93. package/dist/tanstack/number-range-input.js +1 -1
  94. package/dist/tanstack/radio-group.js +1 -1
  95. package/dist/tanstack/rich-text-editor.js +1 -1
  96. package/dist/tanstack/select.js +1 -1
  97. package/dist/tanstack/slider.js +1 -1
  98. package/dist/tanstack/table.js +2 -2
  99. package/dist/tanstack/text-area.js +1 -1
  100. package/dist/tanstack/time-picker.js +1 -1
  101. package/dist/tanstack/toggle-group.js +1 -1
  102. package/dist/tanstack.js +27 -27
  103. package/dist/theme-model-DtYPxNvH.js +406 -0
  104. package/dist/upload-CXU83BJ4.js +30 -0
  105. package/dist/useControlledState-CzXkZCX8.js +30 -0
  106. package/dist/{useFieldAccessibility-B4MVL6fz.js → useFieldAccessibility-ScC6Mtd5.js} +2 -2
  107. package/dist/{useFilters-kkEUFKmQ.js → useFilters-XNH27Md2.js} +1 -1
  108. package/dist/{useFormAutosave-Mg-tdwMh.js → useFormAutosave-DfuP7drj.js} +1 -1
  109. package/dist/{useStaticInputHandoff-CvSBPUB3.js → useStaticInputHandoff-NeZVnci-.js} +3 -3
  110. package/dist/{useTableColumnConfig-gfVame8v.js → useTableColumnConfig-BTGZiluz.js} +3 -3
  111. package/package.json +1 -1
  112. package/src/configurator/README.md +3 -3
  113. package/dist/FocusScope-CO9oJ1sc.js +0 -343
  114. package/dist/chain-DIXr2VAT.js +0 -10
  115. package/dist/focusSafely-DCGrr2bb.js +0 -447
  116. package/dist/getScrollParent-kSR7EtoT.js +0 -47
  117. package/dist/numberStatic.utils-BMgRzyd3.js +0 -902
  118. package/dist/openLink-CQhMhfzO.js +0 -121
  119. package/dist/platform-BXNIIAfU.js +0 -42
  120. package/dist/staticDateTimeSegments-CsCE9Buo.js +0 -3604
  121. package/dist/theme-model-C-QMCksE.js +0 -136
  122. package/dist/useControlledState-DQxX6LMN.js +0 -189
  123. package/dist/useFocusable-Bd0UsrQ7.js +0 -63
  124. package/dist/useFormValidationState-D3z-gafz.js +0 -1341
  125. package/dist/useLayoutEffect-B2-1tbPJ.js +0 -83
  126. package/dist/useSyncRef-RGMv0rXK.js +0 -338
@@ -4,9 +4,9 @@ import { t as Check } from "../check-DYMBkp_Z.js";
4
4
  import { t as ChevronDown } from "../chevron-down-B4Pr8bD3.js";
5
5
  import { t as ChevronRight } from "../chevron-right-3nKJR5Bb.js";
6
6
  import { t as Info } from "../info-iUmX3uDk.js";
7
- import { a as checkboxDefinition, i as checkboxContentWrapperDefinition, o as checkboxGroupLabelDefinition, r as checkboxContentRowDefinition, s as checkboxIconDefinition } from "../CheckboxCheckmark-usHsolNj.js";
7
+ import { a as checkboxDefinition, i as checkboxContentWrapperDefinition, o as checkboxGroupLabelDefinition, r as checkboxContentRowDefinition, s as checkboxIconDefinition, u as Minus } from "../CheckboxCheckmark-CpC3wlMs.js";
8
8
  import { i as Search, n as selectListBoxItemDefinition, r as selectInputTagsContentWrapperDefinition, t as selectPopoverDefinition } from "../selectDesktop.cva-CHAMxhfO.js";
9
- import { t as X } from "../x-B6vfz8Ps.js";
9
+ import { t as Upload } from "../upload-CXU83BJ4.js";
10
10
  import { t as clsx } from "../clsx-CnD0nOiA.js";
11
11
  import { n as StyleMergeUtils, r as cva, t as UIOverrides } from "../uiOverrides.context-BTCH9y5a.js";
12
12
  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";
@@ -16,12 +16,12 @@ import { n as $7705c033048f6da7$export$353f5b6fc5456de1, t as $7705c033048f6da7$
16
16
  import { t as $2ec61d1d4f780267$export$a8a3e93435678ff9 } from "../Heading-nI1_VOaE.js";
17
17
  import { t as $efe09c6d1c304b50$export$9afb8bc826b033ea } from "../Text-D2MPZ3sY.js";
18
18
  import { n as $1f3c3b1a70cec653$export$ff05c3ac10437e03, t as $cdaed739b1139372$export$c24727297075ec6a } from "../Form-DlQcyN1f.js";
19
- import { t as Checkbox } from "../Checkbox-BU0d702K.js";
19
+ import { t as Checkbox } from "../Checkbox-CV1ILXXO.js";
20
20
  import { a as $928221da08ecbc62$export$dca12b0bb56e4fc, i as $928221da08ecbc62$export$a11e76429ed99b4, n as $928221da08ecbc62$export$7c5906fe4f1f2af2, r as $928221da08ecbc62$export$7ff8f37d2d81a48d, t as $928221da08ecbc62$export$41f133550aa26f48 } from "../ListBox-CL8Ar4Q_.js";
21
21
  import { n as $8b8d26808cb8cb53$export$8948f78d83984c69, t as $8b8d26808cb8cb53$export$2b77a92f1a5ad772 } from "../Modal-w60dVQcb.js";
22
- import { i as radioDefinition, n as radioContentRowDefinition, r as radioContentWrapperDefinition, t as RadioGroup } from "../RadioGroup-B7_pNwn9.js";
22
+ import { i as radioDefinition, n as radioContentRowDefinition, r as radioContentWrapperDefinition, t as RadioGroup } from "../RadioGroup-DOw3PRoX.js";
23
23
  import { n as switchDefinition, t as Switch } from "../Switch-CqnGEdeD.js";
24
- import { n as textAreaWrapperDefinition, t as TextArea } from "../TextArea-DqHDiRGJ.js";
24
+ import { n as textAreaWrapperDefinition, t as TextArea } from "../TextArea-D8WkKsGn.js";
25
25
  import { a as breadcrumbsDefinition, i as breadcrumbSegmentDefinition, n as breadcrumbIconDefinition, r as breadcrumbItemDefinition, t as breadcrumbChevronDefinition } from "../breadcrumbs.cva-7zzdDhVR.js";
26
26
  import { i as menuPopoverWrapperDefinition, n as menuItemDefinition, r as menuPopoverDefinition, t as dropdownMenuDefinition } from "../dropdownMenu.cva-DvEmX0bs.js";
27
27
  import { i as tooltipTextDefinition, n as tooltipPointerHorizontalDefinition, r as tooltipPointerVerticalDefinition, t as tooltipDefinition } from "../tooltip.cva-BIzlOXHH.js";
@@ -30,7 +30,7 @@ import { a as buttonSizeDefinition, i as buttonIconSizeDefinition, n as buttonCo
30
30
  import { r as badgeButtonDefinition } from "../badgeButton.cva-CvN4CTx5.js";
31
31
  import { BadgeButton } from "../components/badge-button.js";
32
32
  import { n as formFieldErrorDefinition } from "../FormFieldError-DeOHHLo2.js";
33
- import { a as formFieldHeaderDefinition, i as labelDefinition, n as formFieldHelperDefinition } from "../FormField-U_-d4V_g.js";
33
+ import { a as formFieldHeaderDefinition, i as labelDefinition, n as formFieldHelperDefinition } from "../FormField-B99dLt8o.js";
34
34
  import { n as tagDefinition, t as Tag } from "../Tag-DPg5sL1Z.js";
35
35
  import { a as inputSizeDefinition, i as inputSideDefinition, n as inputClearClassDefinition, r as inputContentWrapperDefinition, t as inputBaseDefinition } from "../input.cva-DJA8ovm_.js";
36
36
  import { t as popoverDefinition } from "../popover.cva-Bhud1wnp.js";
@@ -44,10 +44,10 @@ import { a as stepperSeparatorDefinition, i as stepperNumberDefinition, n as ste
44
44
  import { i as dialogOverlayDefinition, n as dialogMainDefinition, t as dialogContentDefinition } from "../dialog.cva-COhDZaVl.js";
45
45
  import { i as alertDefinition, n as statusIconDefinition, r as statusSeparatorDefinition, t as Alert } from "../Alert-CnvEb1D_.js";
46
46
  import { a as toastDefinition, i as toastContainerDefinition } from "../toast.cva-C_L_RffH.js";
47
- import { a as tableHeaderTextDefinition, i as tableHeadRowDefinition, n as tableDataDefinition, o as tableRowDefinition, r as tableHeadDataDefinition, s as theadDefinition, t as tableCellTextDefinition } from "../table.cva-BikE8qJH.js";
47
+ import { a as tableHeaderTextDefinition, i as tableHeadRowDefinition, n as tableDataDefinition, o as tableRowDefinition, r as tableHeadDataDefinition, s as theadDefinition, t as tableCellTextDefinition } from "../table.cva-DlMT-zLD.js";
48
48
  import { t as linkDefinition } from "../link.cva-DMTHZiJG.js";
49
49
  import { t as tooltipWrapperTriggerDefinition } from "../tooltipWrapper.cva-BBQ4ic3D.js";
50
- import { a as groupFor, c as labelFor, d as runtimeCss, f as toHex, i as generateShades, l as parseThemeCss, m as validToken, n as emptyTheme, o as groups, p as toRgb, r as exportCss, s as isRgb, t as baseColorNames, u as previewTokens } from "../theme-model-C-QMCksE.js";
50
+ 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
51
  import $ahdqC$react, { Suspense, createContext, lazy, use, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
52
52
  import { c } from "react/compiler-runtime";
53
53
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -492,7 +492,7 @@ function UIConfigurationProvider(t0) {
492
492
  if ($[0] !== applied) {
493
493
  t1 = () => {
494
494
  setDraft(structuredClone(applied));
495
- setRevision(_temp$5);
495
+ setRevision(_temp$6);
496
496
  setOpen(true);
497
497
  };
498
498
  $[0] = applied;
@@ -602,7 +602,7 @@ function UIConfigurationProvider(t0) {
602
602
  } else t10 = $[33];
603
603
  return t10;
604
604
  }
605
- function _temp$5(value) {
605
+ function _temp$6(value) {
606
606
  return value + 1;
607
607
  }
608
608
  function useUIConfiguration() {
@@ -630,7 +630,7 @@ function CvaPreview(t0) {
630
630
  component = slot.split(".")[0];
631
631
  const props = {
632
632
  ...definition?.config.defaultVariants,
633
- ...Object.fromEntries(Object.entries(variants).filter(_temp$4).map(_temp2$1))
633
+ ...Object.fromEntries(Object.entries(variants).filter(_temp$5).map(_temp2$2))
634
634
  };
635
635
  const classes = (key, t4) => {
636
636
  const extra = t4 === void 0 ? {} : t4;
@@ -761,7 +761,7 @@ function CvaPreview(t0) {
761
761
  sample = /* @__PURE__ */ jsx("a", {
762
762
  className: exact,
763
763
  href: "#preview",
764
- onClick: _temp3$1,
764
+ onClick: _temp3$2,
765
765
  children: "Example link"
766
766
  });
767
767
  break bb0;
@@ -1272,7 +1272,7 @@ function CvaPreview(t0) {
1272
1272
  children: [/* @__PURE__ */ jsx("option", {
1273
1273
  value: "",
1274
1274
  children: "Default"
1275
- }), Object.keys(options).map(_temp4$1)]
1275
+ }), Object.keys(options).map(_temp4$2)]
1276
1276
  })] }, name_1);
1277
1277
  });
1278
1278
  $[56] = setVariants;
@@ -1389,17 +1389,17 @@ function CvaPreview(t0) {
1389
1389
  } else t13 = $[83];
1390
1390
  return t13;
1391
1391
  }
1392
- function _temp4$1(value_2) {
1392
+ function _temp4$2(value_2) {
1393
1393
  return /* @__PURE__ */ jsx("option", { children: value_2 }, value_2);
1394
1394
  }
1395
- function _temp3$1(event_1) {
1395
+ function _temp3$2(event_1) {
1396
1396
  return event_1.preventDefault();
1397
1397
  }
1398
- function _temp2$1(t0) {
1398
+ function _temp2$2(t0) {
1399
1399
  const [name, value_0] = t0;
1400
1400
  return [name, value_0 === "true" ? true : value_0 === "false" ? false : value_0];
1401
1401
  }
1402
- function _temp$4(t0) {
1402
+ function _temp$5(t0) {
1403
1403
  const [, value] = t0;
1404
1404
  return value !== "";
1405
1405
  }
@@ -1447,7 +1447,7 @@ function ContextualPreview(t0) {
1447
1447
  background: name_0.endsWith("-base") && (/^\d+\s+\d+\s+\d+$/.test(original_0) || original_0.startsWith("var(")) ? `rgb(${value})` : value,
1448
1448
  height: 44
1449
1449
  };
1450
- else if (section === "Typography") {
1450
+ else if (section === "Typography" || section === "Font size") {
1451
1451
  style = name_0.startsWith("--text-") ? {
1452
1452
  fontSize: value,
1453
1453
  lineHeight: `var(${name_0}--line-height, 1.4)`,
@@ -1555,7 +1555,7 @@ function ClassField(t0) {
1555
1555
  onFocus,
1556
1556
  onChange: t4,
1557
1557
  onBlur: t5,
1558
- onKeyDown: _temp$3
1558
+ onKeyDown: _temp$4
1559
1559
  });
1560
1560
  $[10] = label;
1561
1561
  $[11] = onFocus;
@@ -1576,7 +1576,7 @@ function ClassField(t0) {
1576
1576
  } else t7 = $[17];
1577
1577
  return t7;
1578
1578
  }
1579
- function _temp$3(event_0) {
1579
+ function _temp$4(event_0) {
1580
1580
  if (event_0.key === "Enter" && !event_0.nativeEvent.isComposing) {
1581
1581
  event_0.preventDefault();
1582
1582
  event_0.currentTarget.parentElement?.focus();
@@ -1607,7 +1607,7 @@ function CvaEditor(t0) {
1607
1607
  let update;
1608
1608
  if ($[2] !== component || $[3] !== draft.overrides || $[4] !== inheritedOverrides || $[5] !== setDraft || $[6] !== setSlot || $[7] !== slot) {
1609
1609
  slots = Object.keys(cvaDefinitions);
1610
- const components = [...new Set(slots.map(_temp2))];
1610
+ const components = [...new Set(slots.map(_temp2$1))];
1611
1611
  let t10;
1612
1612
  if ($[20] !== inheritedOverrides || $[21] !== slot) {
1613
1613
  t10 = resolveCvaDefinition(slot, inheritedOverrides);
@@ -1650,7 +1650,7 @@ function CvaEditor(t0) {
1650
1650
  const next_0 = event.target.value;
1651
1651
  setSlot(slots.find((key_0) => key_0.startsWith(`${next_0}.`)));
1652
1652
  };
1653
- t5 = components.map(_temp3);
1653
+ t5 = components.map(_temp3$1);
1654
1654
  $[2] = component;
1655
1655
  $[3] = draft.overrides;
1656
1656
  $[4] = inheritedOverrides;
@@ -1721,7 +1721,7 @@ function CvaEditor(t0) {
1721
1721
  } else t13 = $[39];
1722
1722
  let t14;
1723
1723
  if ($[40] !== component || $[41] !== slots) {
1724
- t14 = slots.filter((key_1) => key_1.startsWith(`${component}.`)).map(_temp4);
1724
+ t14 = slots.filter((key_1) => key_1.startsWith(`${component}.`)).map(_temp4$1);
1725
1725
  $[40] = component;
1726
1726
  $[41] = slots;
1727
1727
  $[42] = t14;
@@ -1899,19 +1899,19 @@ function _temp5(value_1) {
1899
1899
  children: value_1
1900
1900
  }, value_1);
1901
1901
  }
1902
- function _temp4(key_2) {
1902
+ function _temp4$1(key_2) {
1903
1903
  return /* @__PURE__ */ jsx("option", {
1904
1904
  value: key_2,
1905
1905
  children: title(key_2.split(".")[1])
1906
1906
  }, key_2);
1907
1907
  }
1908
- function _temp3(name) {
1908
+ function _temp3$1(name) {
1909
1909
  return /* @__PURE__ */ jsx("option", {
1910
1910
  value: name,
1911
1911
  children: title(name)
1912
1912
  }, name);
1913
1913
  }
1914
- function _temp2(key) {
1914
+ function _temp2$1(key) {
1915
1915
  return key.split(".")[0];
1916
1916
  }
1917
1917
  //#endregion
@@ -2019,7 +2019,7 @@ function AlphaColorField(t0) {
2019
2019
  setPercentText(null);
2020
2020
  if (Number.isFinite(entered_0)) onChange(`#${color}${toAlpha(entered_0)}`);
2021
2021
  };
2022
- const blurOnEnter = _temp$2;
2022
+ const blurOnEnter = _temp$3;
2023
2023
  const t1 = `#${color}`;
2024
2024
  let t2;
2025
2025
  if ($[0] !== t1 || $[1] !== value) {
@@ -2121,7 +2121,7 @@ function AlphaColorField(t0) {
2121
2121
  ]
2122
2122
  });
2123
2123
  }
2124
- function _temp$2(event) {
2124
+ function _temp$3(event) {
2125
2125
  if (event.key === "Enter" && !event.nativeEvent.isComposing) event.currentTarget.blur();
2126
2126
  }
2127
2127
  //#endregion
@@ -2220,7 +2220,7 @@ function PaletteSelect(t0) {
2220
2220
  } else t6 = $[14];
2221
2221
  let t7;
2222
2222
  if ($[15] !== options) {
2223
- t7 = paletteFamilies(options).map(_temp$1);
2223
+ t7 = paletteFamilies(options).map(_temp$2);
2224
2224
  $[15] = options;
2225
2225
  $[16] = t7;
2226
2226
  } else t7 = $[16];
@@ -2271,7 +2271,7 @@ function PaletteSelect(t0) {
2271
2271
  } else t10 = $[27];
2272
2272
  return t10;
2273
2273
  }
2274
- function _temp$1(t0) {
2274
+ function _temp$2(t0) {
2275
2275
  const { family: name, steps } = t0;
2276
2276
  return /* @__PURE__ */ jsxs($928221da08ecbc62$export$dca12b0bb56e4fc, {
2277
2277
  id: name,
@@ -2413,6 +2413,692 @@ function PanelResizeHandle(t0) {
2413
2413
  return t8;
2414
2414
  }
2415
2415
  //#endregion
2416
+ //#region src/configurator/FontRoleCard.tsx
2417
+ const unquote = (family) => family.trim().replace(/^["']|["']$/g, "");
2418
+ /** Generic stacks that are available everywhere, for apps without their own fonts. */
2419
+ const systemFonts = [
2420
+ {
2421
+ name: "system:sans",
2422
+ label: "System sans-serif",
2423
+ value: "system-ui, sans-serif",
2424
+ group: "System fonts"
2425
+ },
2426
+ {
2427
+ name: "system:serif",
2428
+ label: "System serif",
2429
+ value: "ui-serif, Georgia, serif",
2430
+ group: "System fonts"
2431
+ },
2432
+ {
2433
+ name: "system:mono",
2434
+ label: "System monospace",
2435
+ value: "ui-monospace, monospace",
2436
+ group: "System fonts"
2437
+ }
2438
+ ];
2439
+ /**
2440
+ * The font families the app has loaded (its `@font-face` rules, such as Fontsource packages). A family with a matching
2441
+ * `--font-<name>-base` variable is referenced through it, so the theme keeps a single place that names the font.
2442
+ */
2443
+ function useLoadedFonts() {
2444
+ const $ = c(7);
2445
+ let t0;
2446
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2447
+ t0 = [];
2448
+ $[0] = t0;
2449
+ } else t0 = $[0];
2450
+ const [fonts, setFonts] = useState(t0);
2451
+ const [revision, setRevision] = useState(0);
2452
+ let t1;
2453
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
2454
+ t1 = () => setRevision(_temp$1);
2455
+ $[1] = t1;
2456
+ } else t1 = $[1];
2457
+ const refresh = t1;
2458
+ let t2;
2459
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
2460
+ t2 = () => {
2461
+ let active = true;
2462
+ document.fonts.ready.then(() => {
2463
+ if (!active) return;
2464
+ const root = getComputedStyle(document.documentElement);
2465
+ const families = [...new Set([...document.fonts].map(_temp2))];
2466
+ setFonts(families.map((family) => {
2467
+ const base = `--font-${family.split(/\s+/)[0].toLowerCase()}-base`;
2468
+ const value_0 = unquote(root.getPropertyValue(base)) === family ? `var(${base}), sans-serif` : `"${family}", sans-serif`;
2469
+ const group = uploadedFamilies.has(family) ? "Uploaded fonts" : "Loaded fonts";
2470
+ return {
2471
+ name: `loaded:${family}`,
2472
+ label: familyName(value_0),
2473
+ value: value_0,
2474
+ group
2475
+ };
2476
+ }));
2477
+ });
2478
+ return () => {
2479
+ active = false;
2480
+ };
2481
+ };
2482
+ $[2] = t2;
2483
+ } else t2 = $[2];
2484
+ let t3;
2485
+ if ($[3] !== revision) {
2486
+ t3 = [revision];
2487
+ $[3] = revision;
2488
+ $[4] = t3;
2489
+ } else t3 = $[4];
2490
+ useEffect(t2, t3);
2491
+ let t4;
2492
+ if ($[5] !== fonts) {
2493
+ t4 = [fonts, refresh];
2494
+ $[5] = fonts;
2495
+ $[6] = t4;
2496
+ } else t4 = $[6];
2497
+ return t4;
2498
+ }
2499
+ /** Families added through the upload button in this page session. */
2500
+ function _temp2(face) {
2501
+ return unquote(face.family);
2502
+ }
2503
+ function _temp$1(value) {
2504
+ return value + 1;
2505
+ }
2506
+ const uploadedFamilies = /* @__PURE__ */ new Set();
2507
+ const fontFileTypes = ".woff2,.woff,.ttf,.otf";
2508
+ /**
2509
+ * Registers a font file with the page through the FontFace API, so it can be picked for a role and previewed right
2510
+ * away. The family is named after the file. It lasts for this page session; the app still needs the file and an
2511
+ * `@font-face` rule for a saved theme to use it.
2512
+ */
2513
+ function FontUpload(t0) {
2514
+ const $ = c(8);
2515
+ const { onUpload } = t0;
2516
+ const inputRef = useRef(null);
2517
+ const [message, setMessage] = useState("");
2518
+ let t1;
2519
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2520
+ t1 = /* @__PURE__ */ jsxs("button", {
2521
+ type: "button",
2522
+ className: "studio-gallery-back",
2523
+ onClick: () => inputRef.current?.click(),
2524
+ children: [/* @__PURE__ */ jsx(Upload, {
2525
+ size: 13,
2526
+ "aria-hidden": "true"
2527
+ }), "Upload font"]
2528
+ });
2529
+ $[0] = t1;
2530
+ } else t1 = $[0];
2531
+ let t2;
2532
+ if ($[1] !== onUpload) {
2533
+ t2 = /* @__PURE__ */ jsx("input", {
2534
+ ref: inputRef,
2535
+ type: "file",
2536
+ accept: fontFileTypes,
2537
+ hidden: true,
2538
+ onChange: async (event) => {
2539
+ const file = event.target.files?.[0];
2540
+ event.target.value = "";
2541
+ if (!file) return;
2542
+ const family = file.name.replace(/\.[^.]+$/, "").replace(/[-_]+/g, " ").trim();
2543
+ try {
2544
+ const face = await new FontFace(family, await file.arrayBuffer()).load();
2545
+ document.fonts.add(face);
2546
+ uploadedFamilies.add(family);
2547
+ onUpload(family);
2548
+ setMessage(`Added ${family}. Pick it for Heading or Body above.`);
2549
+ } catch {
2550
+ setMessage(`${file.name} is not a font this browser can read. Use WOFF2, WOFF, TTF or OTF.`);
2551
+ }
2552
+ }
2553
+ });
2554
+ $[1] = onUpload;
2555
+ $[2] = t2;
2556
+ } else t2 = $[2];
2557
+ const t3 = message || "WOFF2, WOFF, TTF or OTF. Uploaded fonts last for this session; add the file to your app with @font-face before saving the theme.";
2558
+ let t4;
2559
+ if ($[3] !== t3) {
2560
+ t4 = /* @__PURE__ */ jsx("p", {
2561
+ className: "studio-font-upload-note",
2562
+ role: "status",
2563
+ children: t3
2564
+ });
2565
+ $[3] = t3;
2566
+ $[4] = t4;
2567
+ } else t4 = $[4];
2568
+ let t5;
2569
+ if ($[5] !== t2 || $[6] !== t4) {
2570
+ t5 = /* @__PURE__ */ jsxs("div", {
2571
+ className: "studio-font-upload",
2572
+ children: [
2573
+ t1,
2574
+ t2,
2575
+ t4
2576
+ ]
2577
+ });
2578
+ $[5] = t2;
2579
+ $[6] = t4;
2580
+ $[7] = t5;
2581
+ } else t5 = $[7];
2582
+ return t5;
2583
+ }
2584
+ /** The family name a font stack starts with, such as "Inter" for `var(--font-inter-base), sans-serif`. */
2585
+ function familyName(value) {
2586
+ const first = value.split(",")[0].trim();
2587
+ return (first.match(/^var\(--font-([\w-]+?)(?:-base)?\)$/)?.[1] ?? unquote(first)).replace(/(^|-)(\w)/g, (_, dash, letter) => `${dash ? " " : ""}${letter.toUpperCase()}`);
2588
+ }
2589
+ /**
2590
+ * A font role (heading, body) shown as a card with its family name and a sample; the whole card opens a list of the
2591
+ * theme's font families, like a design tool's font picker.
2592
+ */
2593
+ function FontRoleCard(t0) {
2594
+ const $ = c(44);
2595
+ const { label, value, options, changed, onChange, onReset } = t0;
2596
+ let t1;
2597
+ if ($[0] !== options || $[1] !== value) {
2598
+ let t2;
2599
+ if ($[3] !== value) {
2600
+ t2 = (option) => option.value === value;
2601
+ $[3] = value;
2602
+ $[4] = t2;
2603
+ } else t2 = $[4];
2604
+ t1 = options.find(t2);
2605
+ $[0] = options;
2606
+ $[1] = value;
2607
+ $[2] = t1;
2608
+ } else t1 = $[2];
2609
+ const selected = t1;
2610
+ let t2;
2611
+ if ($[5] !== label) {
2612
+ t2 = /* @__PURE__ */ jsx("span", { children: label });
2613
+ $[5] = label;
2614
+ $[6] = t2;
2615
+ } else t2 = $[6];
2616
+ let t3;
2617
+ if ($[7] !== selected?.label || $[8] !== value) {
2618
+ t3 = selected?.label ?? familyName(value);
2619
+ $[7] = selected?.label;
2620
+ $[8] = value;
2621
+ $[9] = t3;
2622
+ } else t3 = $[9];
2623
+ let t4;
2624
+ if ($[10] !== t3) {
2625
+ t4 = /* @__PURE__ */ jsx("strong", { children: t3 });
2626
+ $[10] = t3;
2627
+ $[11] = t4;
2628
+ } else t4 = $[11];
2629
+ let t5;
2630
+ if ($[12] !== t2 || $[13] !== t4) {
2631
+ t5 = /* @__PURE__ */ jsxs("span", {
2632
+ className: "studio-font-role-text",
2633
+ children: [t2, t4]
2634
+ });
2635
+ $[12] = t2;
2636
+ $[13] = t4;
2637
+ $[14] = t5;
2638
+ } else t5 = $[14];
2639
+ let t6;
2640
+ if ($[15] !== value) {
2641
+ t6 = /* @__PURE__ */ jsx("span", {
2642
+ className: "studio-font-role-sample",
2643
+ style: { fontFamily: value },
2644
+ "aria-hidden": "true",
2645
+ children: "Aa"
2646
+ });
2647
+ $[15] = value;
2648
+ $[16] = t6;
2649
+ } else t6 = $[16];
2650
+ const t7 = `${label} font`;
2651
+ const t8 = selected?.name ?? "";
2652
+ let t9;
2653
+ if ($[17] !== onChange || $[18] !== options) {
2654
+ t9 = (event) => {
2655
+ const option_0 = options.find((t10) => {
2656
+ const { name } = t10;
2657
+ return name === event.target.value;
2658
+ });
2659
+ if (option_0) onChange(option_0.value);
2660
+ };
2661
+ $[17] = onChange;
2662
+ $[18] = options;
2663
+ $[19] = t9;
2664
+ } else t9 = $[19];
2665
+ let t10;
2666
+ if ($[20] !== selected) {
2667
+ t10 = !selected && /* @__PURE__ */ jsx("option", {
2668
+ value: "",
2669
+ disabled: true,
2670
+ children: "Custom"
2671
+ });
2672
+ $[20] = selected;
2673
+ $[21] = t10;
2674
+ } else t10 = $[21];
2675
+ let t11;
2676
+ if ($[22] !== options) {
2677
+ t11 = new Set(options.map(_temp3));
2678
+ $[22] = options;
2679
+ $[23] = t11;
2680
+ } else t11 = $[23];
2681
+ let t12;
2682
+ if ($[24] !== t11) {
2683
+ t12 = [...t11];
2684
+ $[24] = t11;
2685
+ $[25] = t12;
2686
+ } else t12 = $[25];
2687
+ let t13;
2688
+ if ($[26] !== options || $[27] !== t12) {
2689
+ t13 = t12.map((group_0) => /* @__PURE__ */ jsx("optgroup", {
2690
+ label: group_0,
2691
+ children: options.filter((option_1) => option_1.group === group_0).map(_temp4)
2692
+ }, group_0));
2693
+ $[26] = options;
2694
+ $[27] = t12;
2695
+ $[28] = t13;
2696
+ } else t13 = $[28];
2697
+ let t14;
2698
+ if ($[29] !== t10 || $[30] !== t13 || $[31] !== t7 || $[32] !== t8 || $[33] !== t9) {
2699
+ t14 = /* @__PURE__ */ jsxs("select", {
2700
+ className: "studio-font-role-select",
2701
+ "aria-label": t7,
2702
+ value: t8,
2703
+ onChange: t9,
2704
+ children: [t10, t13]
2705
+ });
2706
+ $[29] = t10;
2707
+ $[30] = t13;
2708
+ $[31] = t7;
2709
+ $[32] = t8;
2710
+ $[33] = t9;
2711
+ $[34] = t14;
2712
+ } else t14 = $[34];
2713
+ let t15;
2714
+ if ($[35] !== changed || $[36] !== label || $[37] !== onReset) {
2715
+ t15 = changed && /* @__PURE__ */ jsx("button", {
2716
+ type: "button",
2717
+ className: "studio-font-role-reset",
2718
+ "aria-label": `Reset ${label} font`,
2719
+ title: "Reset to the theme default",
2720
+ onClick: onReset,
2721
+ children: /* @__PURE__ */ jsx(RotateCcw, {
2722
+ size: 13,
2723
+ "aria-hidden": "true"
2724
+ })
2725
+ });
2726
+ $[35] = changed;
2727
+ $[36] = label;
2728
+ $[37] = onReset;
2729
+ $[38] = t15;
2730
+ } else t15 = $[38];
2731
+ let t16;
2732
+ if ($[39] !== t14 || $[40] !== t15 || $[41] !== t5 || $[42] !== t6) {
2733
+ t16 = /* @__PURE__ */ jsxs("div", {
2734
+ className: "studio-font-role",
2735
+ children: [
2736
+ t5,
2737
+ t6,
2738
+ t14,
2739
+ t15
2740
+ ]
2741
+ });
2742
+ $[39] = t14;
2743
+ $[40] = t15;
2744
+ $[41] = t5;
2745
+ $[42] = t6;
2746
+ $[43] = t16;
2747
+ } else t16 = $[43];
2748
+ return t16;
2749
+ }
2750
+ function _temp4(option_2) {
2751
+ return /* @__PURE__ */ jsx("option", {
2752
+ value: option_2.name,
2753
+ children: option_2.label
2754
+ }, option_2.name);
2755
+ }
2756
+ function _temp3(t0) {
2757
+ const { group } = t0;
2758
+ return group;
2759
+ }
2760
+ //#endregion
2761
+ //#region src/configurator/LayoutScaleControl.tsx
2762
+ const copy = {
2763
+ Radius: {
2764
+ title: "Global rounding",
2765
+ description: "Scales every radius from the theme defaults"
2766
+ },
2767
+ Spacing: {
2768
+ title: "Global spacing",
2769
+ description: "Scales padding and gaps from the theme defaults"
2770
+ },
2771
+ Sizing: {
2772
+ title: "Global sizing",
2773
+ description: "Scales button and input heights, avatars, icons, minimum widths and container widths"
2774
+ },
2775
+ "Font size": {
2776
+ title: "Global font size",
2777
+ description: "Scales every text style; line heights follow"
2778
+ }
2779
+ };
2780
+ /**
2781
+ * Steps every token of a layout tab up or down together. A custom level means individual tokens were edited, so the
2782
+ * next step starts again from the theme defaults.
2783
+ */
2784
+ function LayoutScaleControl(t0) {
2785
+ const $ = c(50);
2786
+ const { kind, level, onChange } = t0;
2787
+ const { levels, defaultLevel } = layoutScales[kind];
2788
+ const current = level ?? defaultLevel;
2789
+ const factor = level === void 0 ? 1 : levels[level].factor;
2790
+ const { title, description } = copy[kind];
2791
+ let t1;
2792
+ if ($[0] !== kind) {
2793
+ t1 = kind.toLowerCase().replace(" ", "-");
2794
+ $[0] = kind;
2795
+ $[1] = t1;
2796
+ } else t1 = $[1];
2797
+ const t2 = `studio-rounding-preview studio-scale-preview-${t1}`;
2798
+ let t3;
2799
+ if ($[2] !== factor || $[3] !== kind) {
2800
+ t3 = kind === "Radius" ? { borderTopLeftRadius: factor === Infinity ? "999px" : `${factor * 6}px` } : kind === "Spacing" ? { gap: `${Math.round(factor * 4)}px` } : kind === "Font size" ? { fontSize: `${Math.round(factor * 14)}px` } : { scale: String(factor) };
2801
+ $[2] = factor;
2802
+ $[3] = kind;
2803
+ $[4] = t3;
2804
+ } else t3 = $[4];
2805
+ const t4 = kind === "Font size" && "Aa";
2806
+ let t5;
2807
+ if ($[5] !== kind) {
2808
+ t5 = kind === "Spacing" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("i", {}), /* @__PURE__ */ jsx("i", {})] });
2809
+ $[5] = kind;
2810
+ $[6] = t5;
2811
+ } else t5 = $[6];
2812
+ let t6;
2813
+ if ($[7] !== t2 || $[8] !== t3 || $[9] !== t4 || $[10] !== t5) {
2814
+ t6 = /* @__PURE__ */ jsxs("span", {
2815
+ className: t2,
2816
+ "aria-hidden": "true",
2817
+ style: t3,
2818
+ children: [t4, t5]
2819
+ });
2820
+ $[7] = t2;
2821
+ $[8] = t3;
2822
+ $[9] = t4;
2823
+ $[10] = t5;
2824
+ $[11] = t6;
2825
+ } else t6 = $[11];
2826
+ let t7;
2827
+ if ($[12] !== title) {
2828
+ t7 = /* @__PURE__ */ jsx("strong", { children: title });
2829
+ $[12] = title;
2830
+ $[13] = t7;
2831
+ } else t7 = $[13];
2832
+ let t8;
2833
+ if ($[14] !== description) {
2834
+ t8 = /* @__PURE__ */ jsx("span", { children: description });
2835
+ $[14] = description;
2836
+ $[15] = t8;
2837
+ } else t8 = $[15];
2838
+ let t9;
2839
+ if ($[16] !== t7 || $[17] !== t8) {
2840
+ t9 = /* @__PURE__ */ jsxs("div", {
2841
+ className: "studio-rounding-text",
2842
+ children: [t7, t8]
2843
+ });
2844
+ $[16] = t7;
2845
+ $[17] = t8;
2846
+ $[18] = t9;
2847
+ } else t9 = $[18];
2848
+ let t10;
2849
+ if ($[19] !== title) {
2850
+ t10 = title.toLowerCase();
2851
+ $[19] = title;
2852
+ $[20] = t10;
2853
+ } else t10 = $[20];
2854
+ const t11 = `Decrease ${t10}`;
2855
+ const t12 = level === 0;
2856
+ let t13;
2857
+ if ($[21] !== current || $[22] !== onChange) {
2858
+ t13 = () => onChange(current - 1);
2859
+ $[21] = current;
2860
+ $[22] = onChange;
2861
+ $[23] = t13;
2862
+ } else t13 = $[23];
2863
+ let t14;
2864
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
2865
+ t14 = /* @__PURE__ */ jsx(Minus, {
2866
+ size: 13,
2867
+ "aria-hidden": "true"
2868
+ });
2869
+ $[24] = t14;
2870
+ } else t14 = $[24];
2871
+ let t15;
2872
+ if ($[25] !== t11 || $[26] !== t12 || $[27] !== t13) {
2873
+ t15 = /* @__PURE__ */ jsx("button", {
2874
+ type: "button",
2875
+ "aria-label": t11,
2876
+ disabled: t12,
2877
+ onClick: t13,
2878
+ children: t14
2879
+ });
2880
+ $[25] = t11;
2881
+ $[26] = t12;
2882
+ $[27] = t13;
2883
+ $[28] = t15;
2884
+ } else t15 = $[28];
2885
+ const t16 = level === void 0 ? "Custom" : levels[level].label;
2886
+ let t17;
2887
+ if ($[29] !== t16) {
2888
+ t17 = /* @__PURE__ */ jsx("output", {
2889
+ "aria-live": "polite",
2890
+ children: t16
2891
+ });
2892
+ $[29] = t16;
2893
+ $[30] = t17;
2894
+ } else t17 = $[30];
2895
+ let t18;
2896
+ if ($[31] !== title) {
2897
+ t18 = title.toLowerCase();
2898
+ $[31] = title;
2899
+ $[32] = t18;
2900
+ } else t18 = $[32];
2901
+ const t19 = `Increase ${t18}`;
2902
+ const t20 = level === levels.length - 1;
2903
+ let t21;
2904
+ if ($[33] !== current || $[34] !== onChange) {
2905
+ t21 = () => onChange(current + 1);
2906
+ $[33] = current;
2907
+ $[34] = onChange;
2908
+ $[35] = t21;
2909
+ } else t21 = $[35];
2910
+ let t22;
2911
+ if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
2912
+ t22 = /* @__PURE__ */ jsx(Plus, {
2913
+ size: 13,
2914
+ "aria-hidden": "true"
2915
+ });
2916
+ $[36] = t22;
2917
+ } else t22 = $[36];
2918
+ let t23;
2919
+ if ($[37] !== t19 || $[38] !== t20 || $[39] !== t21) {
2920
+ t23 = /* @__PURE__ */ jsx("button", {
2921
+ type: "button",
2922
+ "aria-label": t19,
2923
+ disabled: t20,
2924
+ onClick: t21,
2925
+ children: t22
2926
+ });
2927
+ $[37] = t19;
2928
+ $[38] = t20;
2929
+ $[39] = t21;
2930
+ $[40] = t23;
2931
+ } else t23 = $[40];
2932
+ let t24;
2933
+ if ($[41] !== t15 || $[42] !== t17 || $[43] !== t23) {
2934
+ t24 = /* @__PURE__ */ jsxs("div", {
2935
+ className: "studio-rounding-stepper",
2936
+ children: [
2937
+ t15,
2938
+ t17,
2939
+ t23
2940
+ ]
2941
+ });
2942
+ $[41] = t15;
2943
+ $[42] = t17;
2944
+ $[43] = t23;
2945
+ $[44] = t24;
2946
+ } else t24 = $[44];
2947
+ let t25;
2948
+ if ($[45] !== t24 || $[46] !== t6 || $[47] !== t9 || $[48] !== title) {
2949
+ t25 = /* @__PURE__ */ jsxs("div", {
2950
+ className: "studio-rounding",
2951
+ role: "group",
2952
+ "aria-label": title,
2953
+ children: [
2954
+ t6,
2955
+ t9,
2956
+ t24
2957
+ ]
2958
+ });
2959
+ $[45] = t24;
2960
+ $[46] = t6;
2961
+ $[47] = t9;
2962
+ $[48] = title;
2963
+ $[49] = t25;
2964
+ } else t25 = $[49];
2965
+ return t25;
2966
+ }
2967
+ //#endregion
2968
+ //#region src/configurator/presets.ts
2969
+ /** Both copies of a token that Tailwind reads as `--spacing-*` (padding, height) and `--container-*` (width). */
2970
+ const layoutPair = (name, value) => ({
2971
+ [`--spacing-${name}`]: value,
2972
+ [`--container-${name}`]: value
2973
+ });
2974
+ /** Tailwind's neutral scale, as RGB channels for one of the theme's base palettes. */
2975
+ const neutralPalette = (palette) => Object.fromEntries(Object.entries({
2976
+ 50: "250 250 250",
2977
+ 100: "245 245 245",
2978
+ 200: "229 229 229",
2979
+ 300: "212 212 212",
2980
+ 400: "161 161 161",
2981
+ 500: "115 115 115",
2982
+ 600: "82 82 82",
2983
+ 700: "64 64 64",
2984
+ 800: "38 38 38",
2985
+ 900: "23 23 23",
2986
+ 950: "10 10 10"
2987
+ }).map(([step, value]) => [`--${palette}-${step}-base`, value]));
2988
+ const themePresets = [{
2989
+ id: "shadcn",
2990
+ label: "shadcn/ui",
2991
+ description: "Neutral palette, near-black primary, Geist 14px, 8px controls radius, 36px buttons and inputs.",
2992
+ edits: {
2993
+ light: {
2994
+ ...neutralPalette("primary"),
2995
+ ...neutralPalette("neutral"),
2996
+ "--surface-default-background-base": "var(--neutral-10-base)",
2997
+ "--surface-default-card-base": "var(--neutral-10-base)",
2998
+ "--surface-default-card-foreground-base": "var(--neutral-950-base)",
2999
+ "--surface-default-foreground-base": "var(--neutral-950-base)",
3000
+ "--surface-default-popover-foreground-base": "var(--neutral-500-base)",
3001
+ "--border-default-subtle-base": "var(--neutral-200-base)",
3002
+ "--border-default-input-base": "var(--neutral-200-base)",
3003
+ "--interactive-primary-background-base": "var(--neutral-900-base)",
3004
+ "--interactive-primary-foreground-base": "var(--neutral-50-base)",
3005
+ "--interactive-subtle-primary-background-base": "var(--neutral-100-base)",
3006
+ "--interactive-subtle-primary-foreground-base": "var(--neutral-900-base)",
3007
+ "--interactive-subtle-secondary-background-base": "var(--neutral-100-base)",
3008
+ "--interactive-subtle-secondary-foreground-base": "var(--neutral-900-base)",
3009
+ "--interactive-ring-base": "var(--neutral-400-base)",
3010
+ "--states-hover-opacity": "10%"
3011
+ },
3012
+ dark: {
3013
+ "--surface-default-background-base": "var(--neutral-950-base)",
3014
+ "--surface-default-card-base": "var(--neutral-900-base)",
3015
+ "--surface-default-card-foreground-base": "var(--neutral-50-base)",
3016
+ "--surface-default-foreground-base": "var(--neutral-50-base)",
3017
+ "--surface-default-popover-foreground-base": "var(--neutral-400-base)",
3018
+ "--border-default-subtle-base": "var(--neutral-800-base)",
3019
+ "--border-default-input-base": "var(--neutral-700-base)",
3020
+ "--interactive-primary-background-base": "var(--neutral-200-base)",
3021
+ "--interactive-primary-foreground-base": "var(--neutral-900-base)",
3022
+ "--interactive-subtle-primary-background-base": "var(--neutral-800-base)",
3023
+ "--interactive-subtle-primary-foreground-base": "var(--neutral-50-base)",
3024
+ "--interactive-subtle-secondary-background-base": "var(--neutral-800-base)",
3025
+ "--interactive-subtle-secondary-foreground-base": "var(--neutral-50-base)",
3026
+ "--interactive-ring-base": "var(--neutral-500-base)",
3027
+ "--states-hover-opacity": "10%"
3028
+ },
3029
+ theme: {
3030
+ "--font-titles": "var(--font-geist-base, \"Geist Variable\"), sans-serif",
3031
+ "--font-body": "var(--font-geist-base, \"Geist Variable\"), sans-serif",
3032
+ "--text-body": "0.875rem",
3033
+ "--text-body--line-height": "1.4286",
3034
+ "--radius-global-rounding-xs": "0.25rem",
3035
+ "--radius-global-rounding-s": "0.375rem",
3036
+ "--radius-global-rounding-m": "0.5rem",
3037
+ "--radius-global-rounding-l": "0.625rem",
3038
+ "--radius-global-rounding-xl": "0.875rem",
3039
+ "--radius-button-rounding-default": "0.5rem",
3040
+ "--radius-button-rounding-small": "0.5rem",
3041
+ "--radius-button-focus-rounding-default": "0.625rem",
3042
+ "--radius-button-focus-rounding-small": "0.625rem",
3043
+ "--radius-input-rounding-default": "0.5rem",
3044
+ "--radius-floating-label-input-rounding-default": "0.5rem",
3045
+ "--radius-list-rounding-dropdown": "0.5rem",
3046
+ "--radius-tooltip-rounding-default": "0.5rem",
3047
+ "--radius-badge-rounding-default": "0.5rem",
3048
+ "--radius-toast-rounding-default": "0.5rem",
3049
+ "--radius-modal-rounding-default": "0.625rem",
3050
+ "--radius-alert-rounding-default": "0.625rem",
3051
+ "--radius-file-upload-container-rounding-default": "0.625rem",
3052
+ "--radius-file-upload-file-card-rounding-default": "0.5rem",
3053
+ "--radius-segmented-control-rounding-segment": "0.5rem",
3054
+ "--radius-segmented-control-rounding-segmented-control": "0.625rem",
3055
+ ...layoutPair("button-height-default", "0.4375rem"),
3056
+ ...layoutPair("button-height-small", "0.3125rem"),
3057
+ ...layoutPair("button-side-default", "1rem"),
3058
+ ...layoutPair("button-side-small", "0.75rem")
3059
+ }
3060
+ }
3061
+ }, {
3062
+ id: "compact",
3063
+ label: "Compact",
3064
+ description: "Keeps your colors and fonts. 36px default and 28px small controls, padding and gaps at ×0.75.",
3065
+ edits: (defaults) => ({
3066
+ light: {},
3067
+ dark: {},
3068
+ theme: {
3069
+ ...layoutScales.Spacing.scale(defaults, spacingLevels.findIndex(({ factor }) => factor === .75)),
3070
+ ...layoutPair("button-height-default", "0.4375rem"),
3071
+ ...layoutPair("button-height-small", "0.1875rem")
3072
+ }
3073
+ })
3074
+ }];
3075
+ /**
3076
+ * A preset's edits for this theme: tokens the theme does not define are skipped, and values equal to the theme's own
3077
+ * are left out, so the result reads like edits made by hand.
3078
+ */
3079
+ function presetEdits(preset, defaults) {
3080
+ const edits = emptyTheme();
3081
+ const values = typeof preset.edits === "function" ? preset.edits(defaults) : preset.edits;
3082
+ for (const bucket of [
3083
+ "light",
3084
+ "dark",
3085
+ "theme"
3086
+ ]) for (const [name, value] of Object.entries(values[bucket])) if (name in defaults[bucket] && defaults[bucket][name] !== value) edits[bucket][name] = value;
3087
+ return edits;
3088
+ }
3089
+ /** Whether the current edits are exactly this preset applied to the theme. */
3090
+ function isPresetActive(preset, defaults, current) {
3091
+ const expected = presetEdits(preset, defaults);
3092
+ return [
3093
+ "light",
3094
+ "dark",
3095
+ "theme"
3096
+ ].every((bucket) => {
3097
+ const [a, b] = [expected[bucket], current[bucket]];
3098
+ return Object.keys(a).length === Object.keys(b).length && Object.entries(a).every(([name, value]) => b[name] === value);
3099
+ });
3100
+ }
3101
+ //#endregion
2416
3102
  //#region src/configurator/ShadesGenerator.tsx
2417
3103
  /**
2418
3104
  * Generates a whole base palette scale from one color, which becomes its 500 step.
@@ -2618,56 +3304,6 @@ function _temp(t0) {
2618
3304
  return step;
2619
3305
  }
2620
3306
  //#endregion
2621
- //#region src/configurator/TwLogo.tsx
2622
- /** The TW mark (from the admin app's `LogoSmall`), cropped to its outline for the configurator's top bar. */
2623
- const TwLogo = (props) => {
2624
- const $ = c(5);
2625
- let t0;
2626
- let t1;
2627
- let t2;
2628
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2629
- t0 = /* @__PURE__ */ jsx("path", {
2630
- d: "M20.5919 21H13.2263V22.1988H16.1963V27.9876H17.6327V22.1988H20.5919V21Z",
2631
- fill: "#2B51D4"
2632
- });
2633
- t1 = /* @__PURE__ */ jsx("path", {
2634
- d: "M21.1681 21L24.1165 27.9876H25.8769L27.9931 22.5165L30.0997 27.9876H31.8601L34.7761 21H33.2209L30.962 26.6031L28.8145 21H27.1621L25.0145 26.6031L22.7557 21H21.1681Z",
2635
- fill: "#2B51D4"
2636
- });
2637
- t2 = /* @__PURE__ */ jsx("path", {
2638
- fillRule: "evenodd",
2639
- clipRule: "evenodd",
2640
- d: "M10.2002 19.2C10.2002 18.2059 11.0061 17.4 12.0002 17.4H36.0002C36.9943 17.4 37.8002 18.2059 37.8002 19.2V29.4C37.8002 30.3941 36.9943 31.2 36.0002 31.2H12.0002C11.0061 31.2 10.2002 30.3941 10.2002 29.4V19.2ZM12.0002 18.6H36.0002C36.3316 18.6 36.6002 18.8686 36.6002 19.2V29.4C36.6002 29.7314 36.3316 30 36.0002 30H12.0002C11.6688 30 11.4002 29.7314 11.4002 29.4V19.2C11.4002 18.8686 11.6688 18.6 12.0002 18.6Z",
2641
- fill: "#2B51D4"
2642
- });
2643
- $[0] = t0;
2644
- $[1] = t1;
2645
- $[2] = t2;
2646
- } else {
2647
- t0 = $[0];
2648
- t1 = $[1];
2649
- t2 = $[2];
2650
- }
2651
- let t3;
2652
- if ($[3] !== props) {
2653
- t3 = /* @__PURE__ */ jsxs("svg", {
2654
- viewBox: "10.2 17.4 27.6 13.8",
2655
- fill: "none",
2656
- xmlns: "http://www.w3.org/2000/svg",
2657
- "aria-hidden": "true",
2658
- ...props,
2659
- children: [
2660
- t0,
2661
- t1,
2662
- t2
2663
- ]
2664
- });
2665
- $[3] = props;
2666
- $[4] = t3;
2667
- } else t3 = $[4];
2668
- return t3;
2669
- };
2670
- //#endregion
2671
3307
  //#region src/configurator/UIConfigurator.tsx
2672
3308
  const colorNamespaces = {
2673
3309
  surface: "Surfaces",
@@ -2691,6 +3327,7 @@ const componentNamespaces = [
2691
3327
  ["avatar", "Avatars"],
2692
3328
  ["table", "Tables"],
2693
3329
  ["alert", "Alerts"],
3330
+ ["badge", "Badges"],
2694
3331
  ["pill", "Pills"],
2695
3332
  ["progress", "Progress"],
2696
3333
  ["slider", "Sliders"],
@@ -2726,12 +3363,46 @@ const textStylesTab = "Text styles";
2726
3363
  const typographyTabFor = (groupKey) => groupKey.startsWith("--text-") ? textStylesTab : groupKey;
2727
3364
  const baseSystemTab = "Base system";
2728
3365
  const semanticPaletteTab = "Semantic palette";
3366
+ /** Radius, spacing and sizing share one Layout tab, with a sub-tab each. */
3367
+ const navSections = [
3368
+ "Colors",
3369
+ "Typography",
3370
+ "Layout",
3371
+ "Effects"
3372
+ ];
3373
+ const isLayoutKind = (section) => layoutKinds.includes(section);
3374
+ /** The editor section that lists a token; font sizes open in Typography, their home section. */
3375
+ function sectionFor(name) {
3376
+ const kind = layoutKindFor(name);
3377
+ return kind && kind !== "Font size" ? kind : groupFor(name);
3378
+ }
3379
+ /** Presets, component defaults, CVA overrides and export share one Advanced tab, with a sub-tab each. */
3380
+ const advancedSections = [
3381
+ ["Presets", "Presets"],
3382
+ ["Components", "Defaults & behavior"],
3383
+ ["Variants & overrides", "Variants & overrides"],
3384
+ ["Export", "Export"]
3385
+ ];
3386
+ const isAdvancedSection = (section) => advancedSections.some(([key]) => key === section);
3387
+ /** The app's own theme, so a preset can be undone without resetting component settings. */
3388
+ const appThemePreset = {
3389
+ id: "app",
3390
+ label: "App theme",
3391
+ description: "The theme defined in this app's theme.css, without edits.",
3392
+ edits: {
3393
+ light: {},
3394
+ dark: {},
3395
+ theme: {}
3396
+ }
3397
+ };
3398
+ /** Sections that list theme tokens; Font size lists the Typography font sizes again under Layout. */
3399
+ const isTokenSection = (section) => groups.includes(section) || isLayoutKind(section);
2729
3400
  /** The editor group a token is listed under within its section. */
2730
3401
  function groupKeyFor(section, name, defaults) {
2731
3402
  const textStyle = section === "Typography" ? name.match(/^--text-(.+?)(?:--.+)?$/)?.[1] : void 0;
2732
3403
  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";
2733
3404
  }
2734
- const ComponentGallery = lazy(() => import("../ComponentGallery-DIFeJqGx.js"));
3405
+ const ComponentGallery = lazy(() => import("../ComponentGallery-BWiPGUL8.js"));
2735
3406
  function ComponentPreview(t0) {
2736
3407
  const $ = c(14);
2737
3408
  const { value, mode, inspector } = t0;
@@ -2822,7 +3493,7 @@ function TokenField({ name, value, original, changed, onChange, onReset, onValid
2822
3493
  setSyncedValue(value);
2823
3494
  if (!invalid) setText(value);
2824
3495
  }
2825
- const hasSizePresets = /^-?(?:\d*\.)?\d+(?:rem|px)$/.test(original);
3496
+ const hasSizePresets = /^-?(?:\d*\.)?\d+(?:rem|px)$/.test(original) || !!aliasOptions?.length;
2826
3497
  const literalSize = hasSizePresets ? text.trim().match(/^(-?(?:\d*\.)?\d+)(rem|px)$/) : null;
2827
3498
  const rootFontSize = typeof document === "undefined" ? 16 : parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
2828
3499
  const storedUnit = original.endsWith("px") ? "px" : "rem";
@@ -2934,7 +3605,7 @@ function TokenField({ name, value, original, changed, onChange, onReset, onValid
2934
3605
  /* @__PURE__ */ jsx("option", {
2935
3606
  value: "",
2936
3607
  disabled: true,
2937
- children: "⌄"
3608
+ children: "Choose a size"
2938
3609
  }),
2939
3610
  !!aliasOptions?.length && /* @__PURE__ */ jsx("optgroup", {
2940
3611
  label: "Global tokens",
@@ -2980,7 +3651,8 @@ function ConfigurationModalContent({ memory }) {
2980
3651
  const { defaults, draft, setDraft, isOpen, cancel, apply, revision } = useUIConfiguration();
2981
3652
  const remembered = memory.current;
2982
3653
  const [mode, setMode] = useState(remembered.mode ?? "light");
2983
- const [sizeUnit, setSizeUnit] = useState("px");
3654
+ const [sizeUnit, setSizeUnit] = useState(remembered.sizeUnit ?? "px");
3655
+ const [loadedFonts, refreshLoadedFonts] = useLoadedFonts();
2984
3656
  const [editorWidth, setEditorWidth] = useState(remembered.editorWidth);
2985
3657
  const [confirmingReset, setConfirmingReset] = useState(false);
2986
3658
  const [nothingToReset, setNothingToReset] = useState(false);
@@ -3012,7 +3684,8 @@ function ConfigurationModalContent({ memory }) {
3012
3684
  cvaSlot,
3013
3685
  previewMode,
3014
3686
  exportTab,
3015
- editorWidth
3687
+ editorWidth,
3688
+ sizeUnit
3016
3689
  });
3017
3690
  }, [
3018
3691
  memory,
@@ -3023,7 +3696,8 @@ function ConfigurationModalContent({ memory }) {
3023
3696
  cvaSlot,
3024
3697
  previewMode,
3025
3698
  exportTab,
3026
- editorWidth
3699
+ editorWidth,
3700
+ sizeUnit
3027
3701
  ]);
3028
3702
  useLayoutEffect(() => {
3029
3703
  const frame = requestAnimationFrame(() => {
@@ -3037,6 +3711,14 @@ function ConfigurationModalContent({ memory }) {
3037
3711
  const config = inherited;
3038
3712
  const exportText = exportTab === "css" ? exportCss(draft.theme, defaults) : exportTab === "overrides" ? exportCvaEdits(draft.overrides) : `import { UIConfig } from "@povio/ui/ui-config";\n\nconst config = ${JSON.stringify(draft.config, null, 2)} satisfies Partial<UIConfig.Options>;\n\n// Wrap your application:\n// <UIConfig.Provider config={config}>{children}</UIConfig.Provider>\n`;
3039
3713
  const changeSection = (next) => {
3714
+ if (isLayoutKind(next)) setSectionTabs((current) => ({
3715
+ ...current,
3716
+ Layout: next
3717
+ }));
3718
+ if (isAdvancedSection(next)) setSectionTabs((current_0) => ({
3719
+ ...current_0,
3720
+ Advanced: next
3721
+ }));
3040
3722
  setSection(next);
3041
3723
  setSearch("");
3042
3724
  setMessage("");
@@ -3045,7 +3727,7 @@ function ConfigurationModalContent({ memory }) {
3045
3727
  const [highlightedToken, setHighlightedToken] = useState(null);
3046
3728
  const isInspectable = useCallback((name) => (name in defaults.theme || name in defaults.light || name in defaults.dark) && groups.includes(groupFor(name)) && !name.startsWith("--color-"), [defaults]);
3047
3729
  const describeToken = useCallback((name_0) => {
3048
- const section_0 = groupFor(name_0);
3730
+ const section_0 = sectionFor(name_0);
3049
3731
  const bucket = mode === "dark" && name_0 in defaults.dark ? "dark" : name_0 in defaults.light ? "light" : "theme";
3050
3732
  const value_0 = draft.theme[bucket][name_0] ?? defaults[bucket][name_0];
3051
3733
  return `${groupKeyFor(section_0, name_0, defaults)} · ${componentToken(name_0).label} · ${value_0}`;
@@ -3055,22 +3737,27 @@ function ConfigurationModalContent({ memory }) {
3055
3737
  mode
3056
3738
  ]);
3057
3739
  /** Opens the editor on a token picked in the inspector: its section, its group, scrolled into view and highlighted. */
3058
- const focusToken = useCallback((name_1) => {
3059
- const next_0 = groupFor(name_1);
3740
+ const focusToken = useCallback((picked) => {
3741
+ const name_1 = listedLayoutToken(picked, defaults);
3742
+ const next_0 = sectionFor(name_1);
3743
+ if (isLayoutKind(next_0)) setSectionTabs((current_1) => ({
3744
+ ...current_1,
3745
+ Layout: next_0
3746
+ }));
3060
3747
  setSection(next_0);
3061
3748
  setSearch("");
3062
3749
  setMessage("");
3063
3750
  const key = groupKeyFor(next_0, name_1, defaults);
3064
- setExpandedGroups((current) => ({
3065
- ...current,
3751
+ setExpandedGroups((current_2) => ({
3752
+ ...current_2,
3066
3753
  [`${next_0}:${key}`]: true
3067
3754
  }));
3068
- if (next_0 === "Typography") setSectionTabs((current_0) => ({
3069
- ...current_0,
3755
+ if (next_0 === "Typography") setSectionTabs((current_3) => ({
3756
+ ...current_3,
3070
3757
  Typography: typographyTabFor(key)
3071
3758
  }));
3072
- if (next_0 === "Colors") setSectionTabs((current_1) => ({
3073
- ...current_1,
3759
+ if (next_0 === "Colors") setSectionTabs((current_4) => ({
3760
+ ...current_4,
3074
3761
  Colors: baseColorNames(defaults).has(name_1) ? baseSystemTab : semanticPaletteTab
3075
3762
  }));
3076
3763
  setHighlightedToken(name_1);
@@ -3085,8 +3772,8 @@ function ConfigurationModalContent({ memory }) {
3085
3772
  });
3086
3773
  return () => cancelAnimationFrame(frame_0);
3087
3774
  }, [highlightedToken, section]);
3088
- const validity = (name_2, invalid, value_1 = "") => setInvalidFields((current_2) => {
3089
- const next_1 = { ...current_2 };
3775
+ const validity = (name_2, invalid, value_1 = "") => setInvalidFields((current_5) => {
3776
+ const next_1 = { ...current_5 };
3090
3777
  if (invalid) next_1[name_2] = value_1;
3091
3778
  else delete next_1[name_2];
3092
3779
  return next_1;
@@ -3099,51 +3786,82 @@ function ConfigurationModalContent({ memory }) {
3099
3786
  };
3100
3787
  const setToken = (name_3, value_3) => {
3101
3788
  const bucket_0 = mode === "dark" && name_3 in defaults.dark ? "dark" : name_3 in defaults.light ? "light" : "theme";
3102
- setDraft((current_3) => {
3103
- const tokens_0 = { ...current_3.theme[bucket_0] };
3104
- if (value_3 === void 0 || value_3 === defaults[bucket_0][name_3]) delete tokens_0[name_3];
3105
- else tokens_0[name_3] = value_3;
3789
+ const linked = bucket_0 === "theme" && !value_3?.startsWith("var(") ? linkedLayoutTokens(name_3, defaults) : [];
3790
+ setDraft((current_6) => {
3791
+ const tokens_0 = { ...current_6.theme[bucket_0] };
3792
+ for (const token of [name_3, ...linked]) if (value_3 === void 0 || value_3 === defaults[bucket_0][token]) delete tokens_0[token];
3793
+ else tokens_0[token] = value_3;
3106
3794
  return {
3107
- ...current_3,
3795
+ ...current_6,
3108
3796
  theme: {
3109
- ...current_3.theme,
3797
+ ...current_6.theme,
3110
3798
  [bucket_0]: tokens_0
3111
3799
  }
3112
3800
  };
3113
3801
  });
3114
3802
  };
3115
- const setComponent = (key_0, field, value_4) => {
3116
- setDraft((current_4) => ({
3117
- ...current_4,
3803
+ const setLayoutLevel = (kind, level) => setDraft((current_7) => {
3804
+ const tokens_1 = { ...current_7.theme.theme };
3805
+ for (const [name_4, value_4] of Object.entries(layoutScales[kind].scale(defaults, level))) if (value_4 === defaults.theme[name_4]) delete tokens_1[name_4];
3806
+ else tokens_1[name_4] = value_4;
3807
+ return {
3808
+ ...current_7,
3809
+ theme: {
3810
+ ...current_7.theme,
3811
+ theme: tokens_1
3812
+ }
3813
+ };
3814
+ });
3815
+ const applyPreset = (preset) => {
3816
+ setDraft((current_8) => ({
3817
+ ...current_8,
3818
+ theme: presetEdits(preset, defaults)
3819
+ }));
3820
+ setInvalidFields({});
3821
+ setResetRevision((value_5) => value_5 + 1);
3822
+ setMessage(`${preset.label} preset applied. Apply settings to keep it.`);
3823
+ };
3824
+ const setComponent = (key_0, field, value_6) => {
3825
+ setDraft((current_9) => ({
3826
+ ...current_9,
3118
3827
  config: {
3119
- ...current_4.config,
3828
+ ...current_9.config,
3120
3829
  [key_0]: {
3121
- ...current_4.config[key_0],
3122
- [field]: value_4
3830
+ ...current_9.config[key_0],
3831
+ [field]: value_6
3123
3832
  }
3124
3833
  }
3125
3834
  }));
3126
3835
  };
3127
- const radiusAliasOptions = Object.keys(defaults.theme).filter((name_4) => name_4.startsWith("--radius-global-rounding-")).map((name_5) => ({
3128
- name: name_5,
3129
- label: `Global ${name_5.replace("--radius-global-rounding-", "").toUpperCase()}`,
3130
- value: draft.theme.theme[name_5] ?? defaults.theme[name_5]
3836
+ const radiusAliasOptions = Object.keys(defaults.theme).filter((name_5) => name_5.startsWith("--radius-global-rounding-")).map((name_6) => ({
3837
+ name: name_6,
3838
+ label: `Global ${name_6.replace("--radius-global-rounding-", "").toUpperCase()}`,
3839
+ value: draft.theme.theme[name_6] ?? defaults.theme[name_6]
3131
3840
  }));
3841
+ const controlHeightAliasOptions = (name_7) => {
3842
+ const counterpart = controlHeightCounterpart(name_7);
3843
+ if (!counterpart || defaults.theme[name_7] !== `var(${counterpart})`) return void 0;
3844
+ return [{
3845
+ name: counterpart,
3846
+ label: `Button ${counterpart.replace(/^.*-height-/, "")}`,
3847
+ value: draft.theme.theme[counterpart] ?? defaults.theme[counterpart]
3848
+ }];
3849
+ };
3132
3850
  const palette = baseColorNames(defaults);
3133
- const paletteOptions = [...palette].map((name_6) => ({
3134
- name: name_6,
3135
- value: draft.theme.light[name_6] ?? defaults.light[name_6]
3851
+ const paletteOptions = [...palette].map((name_8) => ({
3852
+ name: name_8,
3853
+ value: draft.theme.light[name_8] ?? defaults.light[name_8]
3136
3854
  }));
3137
3855
  const sectionEntries = Object.entries({
3138
3856
  ...defaults.light,
3139
3857
  ...mode === "dark" ? defaults.dark : {},
3140
3858
  ...defaults.theme
3141
- }).filter(([name_7]) => groupFor(name_7) === section && !name_7.startsWith("--color-"));
3859
+ }).filter(([name_9]) => (section === "Font size" ? isFontSizeToken(name_9) : section === "Spacing" || section === "Sizing" ? layoutKindFor(name_9) === section && listedLayoutToken(name_9, defaults) === name_9 : groupFor(name_9) === section) && !name_9.startsWith("--color-"));
3142
3860
  const groupedEntries = /* @__PURE__ */ new Map();
3143
3861
  for (const entry of sectionEntries) {
3144
- const [name_8] = entry;
3145
- const textStyle = section === "Typography" ? name_8.match(/^--text-(.+?)(?:--.+)?$/)?.[1] : void 0;
3146
- const key_1 = groupKeyFor(section, name_8, defaults);
3862
+ const [name_10] = entry;
3863
+ const textStyle = section === "Typography" ? name_10.match(/^--text-(.+?)(?:--.+)?$/)?.[1] : void 0;
3864
+ const key_1 = groupKeyFor(section, name_10, defaults);
3147
3865
  if (!groupedEntries.has(key_1)) groupedEntries.set(key_1, {
3148
3866
  title: textStyle ? textStyle.replaceAll("-", " ") : key_1 === "tokens" ? "" : key_1,
3149
3867
  compact: !!textStyle,
@@ -3151,28 +3869,28 @@ function ConfigurationModalContent({ memory }) {
3151
3869
  });
3152
3870
  groupedEntries.get(key_1).entries.push(entry);
3153
3871
  }
3154
- const paletteStep = (name_9) => Number(name_9.match(/-(\d+)-base$/)?.[1]);
3155
- const isPaletteGroup = (entries) => entries.every(([name_10]) => palette.has(name_10));
3872
+ const paletteStep = (name_11) => Number(name_11.match(/-(\d+)-base$/)?.[1]);
3873
+ const isPaletteGroup = (entries) => entries.every(([name_12]) => palette.has(name_12));
3156
3874
  for (const group of groupedEntries.values()) if (isPaletteGroup(group.entries)) group.entries.sort(([left], [right]) => paletteStep(right) - paletteStep(left));
3157
- const paletteValue = (name_11) => draft.theme.light[name_11] ?? defaults.light[name_11];
3875
+ const paletteValue = (name_13) => draft.theme.light[name_13] ?? defaults.light[name_13];
3158
3876
  const renderPaletteShades = (title, entries_0) => {
3159
- const base = paletteValue((entries_0.find(([name_12]) => paletteStep(name_12) === 500) ?? entries_0[Math.floor(entries_0.length / 2)])[0]);
3877
+ const base = paletteValue((entries_0.find(([name_14]) => paletteStep(name_14) === 500) ?? entries_0[Math.floor(entries_0.length / 2)])[0]);
3160
3878
  return /* @__PURE__ */ jsx(ShadesGenerator, {
3161
3879
  title,
3162
- steps: entries_0.map(([name_13]) => ({
3163
- name: name_13,
3164
- step: paletteStep(name_13)
3880
+ steps: entries_0.map(([name_15]) => ({
3881
+ name: name_15,
3882
+ step: paletteStep(name_15)
3165
3883
  })),
3166
3884
  initial: base,
3167
3885
  onApply: (values) => {
3168
- for (const [name_14, value_5] of Object.entries(values)) setToken(name_14, value_5);
3886
+ for (const [name_16, value_7] of Object.entries(values)) setToken(name_16, value_7);
3169
3887
  }
3170
3888
  }, base);
3171
3889
  };
3172
- const tokenGroups = [...groupedEntries.entries()].filter(([key_2, group_0]) => `${key_2} ${group_0.title} ${group_0.entries.map(([name_15]) => `${name_15} ${labelFor(name_15)}`).join(" ")}`.toLowerCase().includes(search.toLowerCase().trim()));
3890
+ const tokenGroups = [...groupedEntries.entries()].filter(([key_2, group_0]) => `${key_2} ${group_0.title} ${group_0.entries.map(([name_17]) => `${name_17} ${labelFor(name_17)}`).join(" ")}`.toLowerCase().includes(search.toLowerCase().trim()));
3173
3891
  const visibleGroups = section === "Typography" ? tokenGroups : tokenGroups.map(([key_3, group_1]) => [key_3, {
3174
3892
  ...group_1,
3175
- entries: group_1.entries.filter(([name_16]) => `${group_1.title} ${name_16} ${labelFor(name_16)}`.toLowerCase().includes(search.toLowerCase().trim()))
3893
+ entries: group_1.entries.filter(([name_18]) => `${group_1.title} ${name_18} ${labelFor(name_18)}`.toLowerCase().includes(search.toLowerCase().trim()))
3176
3894
  }]).filter(([, group_2]) => group_2.entries.length);
3177
3895
  const groupRank = (key_4) => key_4 === "Global" ? -1 : key_4 === "Base scale" ? 1 : 0;
3178
3896
  const sectionKeys = [...groupedEntries.keys()].sort((a, b) => groupRank(a) - groupRank(b));
@@ -3187,52 +3905,97 @@ function ConfigurationModalContent({ memory }) {
3187
3905
  const collapsibleKeys = sectionKeys.filter(inActiveTab);
3188
3906
  const primaryGroup = collapsibleKeys[0];
3189
3907
  const isExpanded = (key_8) => searching || (expandedGroups[`${section}:${key_8}`] ?? key_8 === primaryGroup);
3190
- const toggleGroup = (key_9) => setExpandedGroups((current_5) => ({
3191
- ...current_5,
3908
+ const toggleGroup = (key_9) => setExpandedGroups((current_10) => ({
3909
+ ...current_10,
3192
3910
  [`${section}:${key_9}`]: !isExpanded(key_9)
3193
3911
  }));
3194
3912
  const allExpanded = collapsibleKeys.every(isExpanded);
3195
- const setAllGroups = (expanded) => setExpandedGroups((current_6) => ({
3196
- ...current_6,
3913
+ const setAllGroups = (expanded) => setExpandedGroups((current_11) => ({
3914
+ ...current_11,
3197
3915
  ...Object.fromEntries(collapsibleKeys.map((key_10) => [`${section}:${key_10}`, expanded]))
3198
3916
  }));
3199
- const groupChanged = (entries_1) => entries_1.some(([name_17]) => {
3200
- const bucket_1 = mode === "dark" && name_17 in defaults.dark ? "dark" : name_17 in defaults.light ? "light" : "theme";
3201
- return name_17 in draft.theme[bucket_1];
3917
+ const groupChanged = (entries_1) => entries_1.some(([name_19]) => {
3918
+ const bucket_1 = mode === "dark" && name_19 in defaults.dark ? "dark" : name_19 in defaults.light ? "light" : "theme";
3919
+ return name_19 in draft.theme[bucket_1];
3202
3920
  });
3203
3921
  /** The current font size of a text style's line height or letter spacing token. */
3204
- const fontSizeFor = (name_18) => {
3205
- const fontSizeName = name_18.match(/^(--text-.+?)--(?:line-height|letter-spacing)$/)?.[1];
3922
+ const fontSizeFor = (name_20) => {
3923
+ const fontSizeName = name_20.match(/^(--text-.+?)--(?:line-height|letter-spacing)$/)?.[1];
3206
3924
  if (!fontSizeName) return void 0;
3207
3925
  const bucket_2 = mode === "dark" && fontSizeName in defaults.dark ? "dark" : fontSizeName in defaults.light ? "light" : "theme";
3208
3926
  return draft.theme[bucket_2][fontSizeName] ?? defaults[bucket_2][fontSizeName];
3209
3927
  };
3210
- const renderToken = ([name_19, original], compact = false) => {
3211
- const bucket_3 = mode === "dark" && name_19 in defaults.dark ? "dark" : name_19 in defaults.light ? "light" : "theme";
3212
- const compactLabel = compact ? name_19.endsWith("--line-height") ? "Line height" : name_19.endsWith("--letter-spacing") ? "Letter spacing" : "Font size" : section === "Colors" ? palette.has(name_19) ? labelFor(name_19).split(" ").slice(1).join(" ") : labelFor(name_19).replace(/^(surface|border|interactive|support|states|shadow) /, "") : section === "Spacing" || section === "Radius" || section === "Sizing" ? componentToken(name_19).label : section === "Effects" ? effectToken(name_19).label : void 0;
3928
+ const renderToken = ([name_21, original], compact = false) => {
3929
+ const bucket_3 = mode === "dark" && name_21 in defaults.dark ? "dark" : name_21 in defaults.light ? "light" : "theme";
3930
+ const compactLabel = compact ? name_21.endsWith("--line-height") ? "Line height" : name_21.endsWith("--letter-spacing") ? "Letter spacing" : "Font size" : section === "Colors" ? palette.has(name_21) ? labelFor(name_21).split(" ").slice(1).join(" ") : labelFor(name_21).replace(/^(surface|border|interactive|support|states|shadow) /, "") : section === "Spacing" || section === "Radius" || section === "Sizing" ? componentToken(name_21).label : section === "Font size" ? name_21.replace(/^--text-/, "").replaceAll("-", " ") : section === "Effects" ? effectToken(name_21).label : void 0;
3213
3931
  return /* @__PURE__ */ jsx(TokenField, {
3214
- name: name_19,
3932
+ name: name_21,
3215
3933
  original,
3216
3934
  compactLabel,
3217
3935
  sizeUnit,
3218
- fontSize: fontSizeFor(name_19),
3219
- highlighted: highlightedToken === name_19,
3936
+ fontSize: fontSizeFor(name_21),
3937
+ highlighted: highlightedToken === name_21,
3220
3938
  paletteOptions: section === "Colors" && /^var\(--[\w-]+\)$/.test(original) ? paletteOptions : void 0,
3221
- aliasOptions: section === "Radius" && !name_19.startsWith("--radius-global-") && componentToken(name_19).title !== "Base scale" ? radiusAliasOptions : void 0,
3222
- value: draft.theme[bucket_3][name_19] ?? original,
3223
- changed: name_19 in draft.theme[bucket_3],
3224
- onChange: (value_6) => {
3225
- setToken(name_19, value_6);
3226
- const lineHeight = `${name_19}--line-height`;
3227
- if (/^--text-[\w-]+$/.test(name_19) && !name_19.includes("--", 2) && (lineHeight in defaults.theme || lineHeight in defaults.light)) setToken(lineHeight, fontSizeLineHeight);
3939
+ aliasOptions: section === "Radius" && !name_21.startsWith("--radius-global-") && componentToken(name_21).title !== "Base scale" ? radiusAliasOptions : controlHeightAliasOptions(name_21),
3940
+ value: draft.theme[bucket_3][name_21] ?? original,
3941
+ changed: name_21 in draft.theme[bucket_3],
3942
+ onChange: (value_8) => {
3943
+ setToken(name_21, value_8);
3944
+ const lineHeight = `${name_21}--line-height`;
3945
+ if (/^--text-[\w-]+$/.test(name_21) && !name_21.includes("--", 2) && (lineHeight in defaults.theme || lineHeight in defaults.light)) setToken(lineHeight, fontSizeLineHeight);
3228
3946
  },
3229
- onReset: () => setToken(name_19),
3230
- invalidValue: invalidFields[`${bucket_3}:${name_19}`],
3231
- onValidity: (field_0, invalid_0, value_7) => validity(`${bucket_3}:${field_0}`, invalid_0, value_7)
3232
- }, `${revision}-${resetRevision}-${mode}-${name_19}`);
3947
+ onReset: () => setToken(name_21),
3948
+ invalidValue: invalidFields[`${bucket_3}:${name_21}`],
3949
+ onValidity: (field_0, invalid_0, value_9) => validity(`${bucket_3}:${field_0}`, invalid_0, value_9)
3950
+ }, `${revision}-${resetRevision}-${mode}-${name_21}`);
3233
3951
  };
3234
- const showTabs = sectionTabList.length > 1 && groups.includes(section);
3235
- const toggleAllButton = groups.includes(section) && !flatTab && collapsibleKeys.length > 1 && /* @__PURE__ */ jsxs("button", {
3952
+ const layoutSection = isLayoutKind(section) ? section : void 0;
3953
+ const advancedSection = isAdvancedSection(section) ? section : void 0;
3954
+ const lastLayoutSection = isLayoutKind(sectionTabs.Layout ?? "") ? sectionTabs.Layout : layoutKinds[0];
3955
+ /**
3956
+ * Font roles (heading, body) lead as picker cards; the families they choose from follow below a divider. A family
3957
+ * token points at its own `-base` font (`--font-inter` → `--font-inter-base`); any other font token is a role.
3958
+ */
3959
+ const renderFontFamilies = (entries_2) => {
3960
+ const isFamily = ([name_22, value_10]) => value_10.includes(`var(${name_22}-base)`);
3961
+ const families = entries_2.filter(isFamily);
3962
+ const roles = entries_2.filter((entry_0) => !isFamily(entry_0));
3963
+ const themeFonts = families.map(([name_23]) => ({
3964
+ name: name_23,
3965
+ label: familyName(name_23.replace(/^--font-/, "")),
3966
+ value: draft.theme.theme[name_23] ?? defaults.theme[name_23],
3967
+ group: "Theme fonts"
3968
+ }));
3969
+ const options = [
3970
+ ...themeFonts,
3971
+ ...loadedFonts.filter((font) => !themeFonts.some(({ value: value_11 }) => value_11 === font.value)),
3972
+ ...systemFonts
3973
+ ];
3974
+ const roleLabels = {
3975
+ "--font-titles": "Heading",
3976
+ "--font-body": "Body"
3977
+ };
3978
+ return /* @__PURE__ */ jsxs("div", {
3979
+ className: "studio-font-families",
3980
+ children: [
3981
+ /* @__PURE__ */ jsx("div", {
3982
+ className: "studio-font-roles",
3983
+ children: roles.map(([name_24, original_0]) => /* @__PURE__ */ jsx(FontRoleCard, {
3984
+ label: roleLabels[name_24] ?? labelFor(name_24).replace(/^font /, ""),
3985
+ value: draft.theme.theme[name_24] ?? original_0,
3986
+ options,
3987
+ changed: name_24 in draft.theme.theme,
3988
+ onChange: (value_12) => setToken(name_24, value_12),
3989
+ onReset: () => setToken(name_24)
3990
+ }, `${revision}-${resetRevision}-${name_24}`))
3991
+ }),
3992
+ /* @__PURE__ */ jsx(FontUpload, { onUpload: refreshLoadedFonts }),
3993
+ !!families.length && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("hr", { className: "studio-font-divider" }), families.map((entry_1) => renderToken(entry_1))] })
3994
+ ]
3995
+ }, "font-families");
3996
+ };
3997
+ const showTabs = sectionTabList.length > 1 && isTokenSection(section);
3998
+ const toggleAllButton = isTokenSection(section) && !flatTab && collapsibleKeys.length > 1 && /* @__PURE__ */ jsxs("button", {
3236
3999
  type: "button",
3237
4000
  className: "studio-toggle-all",
3238
4001
  disabled: searching,
@@ -3242,13 +4005,13 @@ function ConfigurationModalContent({ memory }) {
3242
4005
  "aria-hidden": "true"
3243
4006
  }), allExpanded ? "Collapse all" : "Expand all"]
3244
4007
  });
3245
- const selectControl = (label, key_11, field_1, options) => /* @__PURE__ */ jsxs("label", {
4008
+ const selectControl = (label, key_11, field_1, options_0) => /* @__PURE__ */ jsxs("label", {
3246
4009
  className: "studio-setting",
3247
4010
  children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("select", {
3248
4011
  "aria-label": label,
3249
4012
  value: String(config[key_11][field_1]),
3250
4013
  onChange: (event) => setComponent(key_11, field_1, event.target.value),
3251
- children: options.map((option) => /* @__PURE__ */ jsx("option", { children: option }, option))
4014
+ children: options_0.map((option) => /* @__PURE__ */ jsx("option", { children: option }, option))
3252
4015
  })]
3253
4016
  }, `${key_11}-${field_1}`);
3254
4017
  return /* @__PURE__ */ jsx($8b8d26808cb8cb53$export$8948f78d83984c69, {
@@ -3262,24 +4025,25 @@ function ConfigurationModalContent({ memory }) {
3262
4025
  className: "studio-modal",
3263
4026
  children: /* @__PURE__ */ jsxs($f2ff30fde7b014be$export$3ddf2d174ce01153, {
3264
4027
  className: "studio-dialog",
4028
+ style: { "--studio-editor-track": editorWidth ? `minmax(260px, ${editorWidth}px)` : void 0 },
3265
4029
  children: [
3266
4030
  /* @__PURE__ */ jsxs("header", {
3267
4031
  className: "studio-topbar",
3268
4032
  children: [
3269
- /* @__PURE__ */ jsxs("div", {
4033
+ /* @__PURE__ */ jsx("div", {
3270
4034
  className: "studio-title",
3271
- children: [/* @__PURE__ */ jsx(TwLogo, { className: "studio-topbar-logo" }), /* @__PURE__ */ jsx($2ec61d1d4f780267$export$a8a3e93435678ff9, {
4035
+ children: /* @__PURE__ */ jsx($2ec61d1d4f780267$export$a8a3e93435678ff9, {
3272
4036
  slot: "title",
3273
- children: "UI configuration"
3274
- })]
4037
+ children: "Povio UI Configuration"
4038
+ })
3275
4039
  }),
3276
4040
  /* @__PURE__ */ jsxs("nav", {
3277
4041
  className: "studio-nav",
3278
4042
  "aria-label": "Configuration sections",
3279
4043
  children: [
3280
- groups.map((group_3) => /* @__PURE__ */ jsx("button", {
3281
- "aria-current": section === group_3 ? "page" : void 0,
3282
- onClick: () => changeSection(group_3),
4044
+ navSections.map((group_3) => /* @__PURE__ */ jsx("button", {
4045
+ "aria-current": (group_3 === "Layout" ? isLayoutKind(section) : section === group_3) ? "page" : void 0,
4046
+ onClick: () => changeSection(group_3 === "Layout" ? lastLayoutSection : group_3),
3283
4047
  children: group_3
3284
4048
  }, group_3)),
3285
4049
  /* @__PURE__ */ jsx("span", {
@@ -3287,75 +4051,54 @@ function ConfigurationModalContent({ memory }) {
3287
4051
  "aria-hidden": "true"
3288
4052
  }),
3289
4053
  /* @__PURE__ */ jsx("button", {
3290
- "aria-current": section === "Components" ? "page" : void 0,
3291
- onClick: () => changeSection("Components"),
3292
- children: "Defaults & behavior"
3293
- }),
3294
- /* @__PURE__ */ jsx("button", {
3295
- "aria-current": section === "Variants & overrides" ? "page" : void 0,
3296
- onClick: () => changeSection("Variants & overrides"),
3297
- children: "Variants & overrides"
3298
- }),
3299
- /* @__PURE__ */ jsx("span", {
3300
- className: "studio-nav-divider",
3301
- "aria-hidden": "true"
3302
- }),
3303
- /* @__PURE__ */ jsx("button", {
3304
- "aria-current": section === "Export" ? "page" : void 0,
3305
- onClick: () => changeSection("Export"),
3306
- children: "Export"
4054
+ "aria-current": advancedSection ? "page" : void 0,
4055
+ onClick: () => changeSection(isAdvancedSection(sectionTabs.Advanced ?? "") ? sectionTabs.Advanced : advancedSections[0][0]),
4056
+ children: "Advanced"
3307
4057
  })
3308
4058
  ]
3309
4059
  }),
3310
- /* @__PURE__ */ jsxs("div", {
4060
+ /* @__PURE__ */ jsx("div", {
3311
4061
  className: "studio-topbar-controls",
3312
- children: [
3313
- /* @__PURE__ */ jsxs("label", {
3314
- className: "studio-search",
3315
- children: [/* @__PURE__ */ jsx(Search, { size: 14 }), /* @__PURE__ */ jsx("input", {
3316
- "aria-label": "Search tokens",
3317
- placeholder: "Search tokens",
3318
- value: search,
3319
- disabled: !groups.includes(section),
3320
- onChange: (event_0) => setSearch(event_0.target.value)
3321
- })]
3322
- }),
3323
- /* @__PURE__ */ jsx("div", {
3324
- className: "studio-mode studio-unit-mode",
3325
- role: "group",
3326
- "aria-label": "Size units",
3327
- children: ["rem", "px"].map((unit) => /* @__PURE__ */ jsx("button", {
3328
- type: "button",
3329
- "aria-pressed": sizeUnit === unit,
3330
- onClick: () => setSizeUnit(unit),
3331
- children: unit
3332
- }, unit))
3333
- }),
3334
- /* @__PURE__ */ jsx(ColorModeSwitch, {
3335
- value: mode,
3336
- onChange: setMode
3337
- }),
3338
- /* @__PURE__ */ jsx("button", {
3339
- className: "studio-icon",
3340
- "aria-label": "Close configuration without applying",
3341
- onClick: () => cancel(),
3342
- children: /* @__PURE__ */ jsx(X, { size: 17 })
3343
- })
3344
- ]
4062
+ children: /* @__PURE__ */ jsxs("label", {
4063
+ className: "studio-search",
4064
+ children: [/* @__PURE__ */ jsx(Search, { size: 14 }), /* @__PURE__ */ jsx("input", {
4065
+ "aria-label": "Search tokens",
4066
+ placeholder: "Search tokens",
4067
+ value: search,
4068
+ disabled: !isTokenSection(section),
4069
+ onChange: (event_0) => setSearch(event_0.target.value)
4070
+ })]
4071
+ })
3345
4072
  })
3346
4073
  ]
3347
4074
  }),
3348
4075
  /* @__PURE__ */ jsxs("div", {
3349
4076
  ref: bodyRef,
3350
4077
  className: "studio-body",
3351
- style: { "--studio-editor-track": editorWidth ? `minmax(260px, ${editorWidth}px)` : void 0 },
3352
4078
  children: [
3353
4079
  /* @__PURE__ */ jsxs("main", {
3354
4080
  ref: editorRef,
3355
4081
  className: "studio-editor",
3356
4082
  onScroll: (event_1) => memory.current.editorScroll = event_1.currentTarget.scrollTop,
3357
4083
  children: [
3358
- showTabs ? /* @__PURE__ */ jsxs("div", {
4084
+ layoutSection ? /* @__PURE__ */ jsxs("div", {
4085
+ className: "studio-subtabs-bar",
4086
+ children: [/* @__PURE__ */ jsx("div", {
4087
+ className: "studio-subtabs",
4088
+ role: "tablist",
4089
+ "aria-label": "Layout tokens",
4090
+ children: layoutKinds.map((kind_0) => /* @__PURE__ */ jsxs("button", {
4091
+ type: "button",
4092
+ role: "tab",
4093
+ "aria-selected": kind_0 === section,
4094
+ onClick: () => changeSection(kind_0),
4095
+ children: [kind_0, Object.keys(draft.theme.theme).some((name_25) => layoutKindFor(name_25) === kind_0) && /* @__PURE__ */ jsx("span", {
4096
+ className: "studio-group-changed",
4097
+ "aria-label": "has changes"
4098
+ })]
4099
+ }, kind_0))
4100
+ }), toggleAllButton]
4101
+ }) : showTabs ? /* @__PURE__ */ jsxs("div", {
3359
4102
  className: "studio-subtabs-bar",
3360
4103
  children: [/* @__PURE__ */ jsx("div", {
3361
4104
  className: "studio-subtabs",
@@ -3366,8 +4109,8 @@ function ConfigurationModalContent({ memory }) {
3366
4109
  role: "tab",
3367
4110
  "aria-selected": !searching && tab_0 === activeSectionTab,
3368
4111
  disabled: searching,
3369
- onClick: () => setSectionTabs((current_7) => ({
3370
- ...current_7,
4112
+ onClick: () => setSectionTabs((current_12) => ({
4113
+ ...current_12,
3371
4114
  [section]: tab_0
3372
4115
  })),
3373
4116
  children: [tab_0, groupChanged([...groupedEntries].filter(([key_12]) => tabFor(key_12) === tab_0).flatMap(([, group_4]) => group_4.entries)) && /* @__PURE__ */ jsx("span", {
@@ -3376,20 +4119,41 @@ function ConfigurationModalContent({ memory }) {
3376
4119
  })]
3377
4120
  }, tab_0))
3378
4121
  }), toggleAllButton]
4122
+ }) : advancedSection ? /* @__PURE__ */ jsx("div", {
4123
+ className: "studio-subtabs-bar",
4124
+ children: /* @__PURE__ */ jsx("div", {
4125
+ className: "studio-subtabs",
4126
+ role: "tablist",
4127
+ "aria-label": "Advanced settings",
4128
+ children: advancedSections.map(([key_13, label_0]) => /* @__PURE__ */ jsxs("button", {
4129
+ type: "button",
4130
+ role: "tab",
4131
+ "aria-selected": key_13 === section,
4132
+ onClick: () => changeSection(key_13),
4133
+ 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", {
4134
+ className: "studio-group-changed",
4135
+ "aria-label": "has changes"
4136
+ })]
4137
+ }, key_13))
4138
+ })
3379
4139
  }) : /* @__PURE__ */ jsxs("div", {
3380
4140
  className: "studio-editor-heading",
3381
- children: [/* @__PURE__ */ jsx("h2", { children: section === "Components" ? "Defaults & behavior" : section }), toggleAllButton]
4141
+ children: [/* @__PURE__ */ jsx("h2", { children: section }), toggleAllButton]
3382
4142
  }),
3383
- groups.includes(section) && /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs("div", {
4143
+ isTokenSection(section) && /* @__PURE__ */ jsxs(Fragment$1, { children: [layoutSection && !searching && /* @__PURE__ */ jsx(LayoutScaleControl, {
4144
+ kind: layoutSection,
4145
+ level: layoutLevelFor(defaults, draft.theme.theme, layoutSection),
4146
+ onChange: (level_0) => setLayoutLevel(layoutSection, level_0)
4147
+ }, layoutSection), /* @__PURE__ */ jsxs("div", {
3384
4148
  className: `studio-token-list ${section !== "Typography" ? "studio-token-list-inline" : "studio-token-list-rows"}`,
3385
- children: [orderedGroups.map(([key_13, group_5]) => group_5.title && !flatTab ? /* @__PURE__ */ jsxs("fieldset", {
3386
- className: `studio-token-group ${group_5.compact ? "studio-type-style" : ""} ${!isExpanded(key_13) ? "is-collapsed" : ""}`,
4149
+ children: [orderedGroups.map(([key_14, group_5]) => group_5.title && !flatTab ? /* @__PURE__ */ jsxs("fieldset", {
4150
+ className: `studio-token-group ${group_5.compact ? "studio-type-style" : ""} ${!isExpanded(key_14) ? "is-collapsed" : ""}`,
3387
4151
  children: [/* @__PURE__ */ jsxs("legend", { children: [/* @__PURE__ */ jsxs("button", {
3388
4152
  type: "button",
3389
4153
  className: "studio-group-toggle",
3390
- "aria-expanded": isExpanded(key_13),
3391
- "aria-controls": `group-${section}-${key_13.replaceAll(" ", "-")}`,
3392
- onClick: () => toggleGroup(key_13),
4154
+ "aria-expanded": isExpanded(key_14),
4155
+ "aria-controls": `group-${section}-${key_14.replaceAll(" ", "-")}`,
4156
+ onClick: () => toggleGroup(key_14),
3393
4157
  children: [
3394
4158
  /* @__PURE__ */ jsx(ChevronRight, {
3395
4159
  size: 14,
@@ -3410,7 +4174,7 @@ function ConfigurationModalContent({ memory }) {
3410
4174
  title: "Reset every shade in this palette to its default",
3411
4175
  disabled: !groupChanged(group_5.entries),
3412
4176
  onClick: () => {
3413
- for (const [name_20] of group_5.entries) setToken(name_20);
4177
+ for (const [name_26] of group_5.entries) setToken(name_26);
3414
4178
  },
3415
4179
  children: /* @__PURE__ */ jsx(RotateCcw, {
3416
4180
  size: 13,
@@ -3418,13 +4182,13 @@ function ConfigurationModalContent({ memory }) {
3418
4182
  })
3419
4183
  })
3420
4184
  })] }), /* @__PURE__ */ jsxs("div", {
3421
- id: `group-${section}-${key_13.replaceAll(" ", "-")}`,
3422
- hidden: !isExpanded(key_13),
4185
+ id: `group-${section}-${key_14.replaceAll(" ", "-")}`,
4186
+ hidden: !isExpanded(key_14),
3423
4187
  className: group_5.compact ? "studio-type-fields" : void 0,
3424
- children: [section === "Colors" && isPaletteGroup(group_5.entries) && renderPaletteShades(group_5.title, group_5.entries), group_5.entries.map((entry_0) => renderToken(entry_0, group_5.compact))]
4188
+ children: [section === "Colors" && isPaletteGroup(group_5.entries) && renderPaletteShades(group_5.title, group_5.entries), group_5.entries.map((entry_2) => renderToken(entry_2, group_5.compact))]
3425
4189
  })]
3426
- }, key_13) : group_5.entries.map((entry_1) => renderToken(entry_1))), !orderedGroups.length && /* @__PURE__ */ jsx("p", { children: "No matching tokens. Try a component name such as “button”." })]
3427
- }) }),
4190
+ }, key_14) : section === "Typography" && key_14 === "Font families" ? renderFontFamilies(group_5.entries) : group_5.entries.map((entry_3) => renderToken(entry_3))), !orderedGroups.length && /* @__PURE__ */ jsx("p", { children: "No matching tokens. Try a component name such as “button”." })]
4191
+ })] }),
3428
4192
  section === "Variants & overrides" && /* @__PURE__ */ jsx(CvaEditor, {
3429
4193
  slot: cvaSlot,
3430
4194
  setSlot: (slot) => {
@@ -3433,9 +4197,63 @@ function ConfigurationModalContent({ memory }) {
3433
4197
  },
3434
4198
  onPreview: setCvaVariants
3435
4199
  }),
4200
+ section === "Presets" && /* @__PURE__ */ jsxs("div", {
4201
+ className: "studio-presets",
4202
+ children: [/* @__PURE__ */ jsx("p", {
4203
+ className: "studio-presets-intro",
4204
+ 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."
4205
+ }), [appThemePreset, ...themePresets].map((preset_0) => {
4206
+ const active = isPresetActive(preset_0, defaults, draft.theme);
4207
+ const colors = presetEdits(preset_0, defaults).light;
4208
+ const swatch = (name_27) => `rgb(${colors[name_27] ?? defaults.light[name_27]})`;
4209
+ return /* @__PURE__ */ jsxs("div", {
4210
+ className: `studio-preset ${active ? "is-active" : ""}`,
4211
+ children: [
4212
+ /* @__PURE__ */ jsx("span", {
4213
+ className: "studio-preset-swatches",
4214
+ "aria-hidden": "true",
4215
+ children: [
4216
+ 50,
4217
+ 200,
4218
+ 500,
4219
+ 900,
4220
+ 950
4221
+ ].map((step) => /* @__PURE__ */ jsx("i", { style: { background: swatch(`--neutral-${step}-base`) } }, step))
4222
+ }),
4223
+ /* @__PURE__ */ jsxs("span", {
4224
+ className: "studio-preset-text",
4225
+ children: [/* @__PURE__ */ jsx("strong", { children: preset_0.label }), /* @__PURE__ */ jsx("span", { children: preset_0.description })]
4226
+ }),
4227
+ /* @__PURE__ */ jsx("button", {
4228
+ type: "button",
4229
+ className: active ? void 0 : "studio-primary",
4230
+ disabled: active,
4231
+ onClick: () => applyPreset(preset_0),
4232
+ children: active ? "Active" : "Apply preset"
4233
+ })
4234
+ ]
4235
+ }, preset_0.id);
4236
+ })]
4237
+ }),
3436
4238
  section === "Components" && /* @__PURE__ */ jsxs("div", {
3437
4239
  className: "studio-settings",
3438
4240
  children: [
4241
+ /* @__PURE__ */ jsx("h3", { children: "Editor" }),
4242
+ /* @__PURE__ */ jsxs("label", {
4243
+ className: "studio-setting",
4244
+ children: [/* @__PURE__ */ jsx("span", { children: "Size units" }), /* @__PURE__ */ jsxs("select", {
4245
+ "aria-label": "Size units",
4246
+ value: sizeUnit,
4247
+ onChange: (event_2) => setSizeUnit(event_2.target.value),
4248
+ children: [/* @__PURE__ */ jsx("option", {
4249
+ value: "px",
4250
+ children: "px"
4251
+ }), /* @__PURE__ */ jsx("option", {
4252
+ value: "rem",
4253
+ children: "rem"
4254
+ })]
4255
+ })]
4256
+ }),
3439
4257
  /* @__PURE__ */ jsx("h3", { children: "Buttons" }),
3440
4258
  selectControl("Appearance", "button", "variant", [
3441
4259
  "contained",
@@ -3471,7 +4289,7 @@ function ConfigurationModalContent({ memory }) {
3471
4289
  }[field_2] }), /* @__PURE__ */ jsx("input", {
3472
4290
  type: "checkbox",
3473
4291
  checked: config.input[field_2],
3474
- onChange: (event_2) => setComponent("input", field_2, event_2.target.checked)
4292
+ onChange: (event_3) => setComponent("input", field_2, event_3.target.checked)
3475
4293
  })]
3476
4294
  }, field_2)),
3477
4295
  /* @__PURE__ */ jsx("h3", { children: "Rendering" }),
@@ -3480,11 +4298,11 @@ function ConfigurationModalContent({ memory }) {
3480
4298
  children: [/* @__PURE__ */ jsxs("span", { children: ["Use static inputs until interaction", /* @__PURE__ */ jsx("small", { children: "Reduce work when rendering large forms." })] }), /* @__PURE__ */ jsx("input", {
3481
4299
  type: "checkbox",
3482
4300
  checked: config.renderStaticInput,
3483
- onChange: (event_3) => setDraft((current_8) => ({
3484
- ...current_8,
4301
+ onChange: (event_4) => setDraft((current_13) => ({
4302
+ ...current_13,
3485
4303
  config: {
3486
- ...current_8.config,
3487
- renderStaticInput: event_3.target.checked
4304
+ ...current_13.config,
4305
+ renderStaticInput: event_4.target.checked
3488
4306
  }
3489
4307
  }))
3490
4308
  })]
@@ -3581,28 +4399,34 @@ function ConfigurationModalContent({ memory }) {
3581
4399
  /* @__PURE__ */ jsxs("aside", {
3582
4400
  ref: previewRef,
3583
4401
  className: "studio-preview",
3584
- onScroll: (event_4) => memory.current.previewScroll = event_4.currentTarget.scrollTop,
4402
+ onScroll: (event_5) => memory.current.previewScroll = event_5.currentTarget.scrollTop,
3585
4403
  children: [
3586
4404
  /* @__PURE__ */ jsxs("div", {
3587
4405
  className: "studio-preview-heading",
3588
- children: [/* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("i", {}), " LIVE PREVIEW"] }), groups.includes(section) && /* @__PURE__ */ jsxs("div", {
3589
- className: "studio-preview-modes",
3590
- role: "group",
3591
- "aria-label": "Preview mode",
3592
- children: [/* @__PURE__ */ jsx("button", {
3593
- type: "button",
3594
- "aria-pressed": previewMode === "gallery",
3595
- onClick: () => setPreviewMode("gallery"),
3596
- children: "Gallery"
3597
- }), /* @__PURE__ */ jsx("button", {
3598
- type: "button",
3599
- "aria-pressed": previewMode === "focused",
3600
- onClick: () => setPreviewMode("focused"),
3601
- children: "Token preview"
4406
+ children: [/* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("i", {}), " LIVE PREVIEW"] }), /* @__PURE__ */ jsxs("div", {
4407
+ className: "studio-preview-actions",
4408
+ children: [/* @__PURE__ */ jsx(ColorModeSwitch, {
4409
+ value: mode,
4410
+ onChange: setMode
4411
+ }), isTokenSection(section) && /* @__PURE__ */ jsxs("div", {
4412
+ className: "studio-mode studio-preview-modes",
4413
+ role: "group",
4414
+ "aria-label": "Preview mode",
4415
+ children: [/* @__PURE__ */ jsx("button", {
4416
+ type: "button",
4417
+ "aria-pressed": previewMode === "gallery",
4418
+ onClick: () => setPreviewMode("gallery"),
4419
+ children: "Gallery"
4420
+ }), /* @__PURE__ */ jsx("button", {
4421
+ type: "button",
4422
+ "aria-pressed": previewMode === "focused",
4423
+ onClick: () => setPreviewMode("focused"),
4424
+ children: "Token preview"
4425
+ })]
3602
4426
  })]
3603
4427
  })]
3604
4428
  }),
3605
- section === "Variants & overrides" || groups.includes(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
4429
+ section === "Variants & overrides" || isTokenSection(section) && previewMode === "focused" ? /* @__PURE__ */ jsx(ContextualPreview, {
3606
4430
  variants: cvaVariants,
3607
4431
  setVariants: setCvaVariants,
3608
4432
  section,
@@ -3630,7 +4454,7 @@ function ConfigurationModalContent({ memory }) {
3630
4454
  column: 2,
3631
4455
  width: editorWidth,
3632
4456
  min: 260,
3633
- max: () => (bodyRef.current?.clientWidth ?? 0) - 320,
4457
+ max: () => (bodyRef.current?.parentElement?.clientWidth ?? 0) - 320,
3634
4458
  onResize: setEditorWidth,
3635
4459
  onReset: () => setEditorWidth(void 0)
3636
4460
  })