@weasel-js/ui 1.7.2 → 1.8.0

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 (155) hide show
  1. package/dist/chunks/{Callout-BUn0dP_S.js → Callout-DpTO3fkb.js} +10 -10
  2. package/dist/chunks/Callout-DpTO3fkb.js.map +1 -0
  3. package/dist/chunks/{Checkbox-DFn-x0JO.js → Checkbox-d4IfhiXh.js} +2 -2
  4. package/dist/chunks/{Checkbox-DFn-x0JO.js.map → Checkbox-d4IfhiXh.js.map} +1 -1
  5. package/dist/chunks/{CloseButton-BmNmRVtb.js → CloseButton-wb7Or5Eg.js} +2 -2
  6. package/dist/chunks/{CloseButton-BmNmRVtb.js.map → CloseButton-wb7Or5Eg.js.map} +1 -1
  7. package/dist/chunks/{ColorModeControl-DaVJ-SyX.js → ColorModeControl-DET6Itwq.js} +3 -3
  8. package/dist/chunks/{ColorModeControl-DaVJ-SyX.js.map → ColorModeControl-DET6Itwq.js.map} +1 -1
  9. package/dist/chunks/{DataGrid-CmHJe57v.js → DataGrid-B6IS9vUk.js} +2 -2
  10. package/dist/chunks/{DataGrid-CmHJe57v.js.map → DataGrid-B6IS9vUk.js.map} +1 -1
  11. package/dist/chunks/{DetentSlider-DNTAk8xP.js → DetentSlider-D40V8Oma.js} +2 -2
  12. package/dist/chunks/{DetentSlider-DNTAk8xP.js.map → DetentSlider-D40V8Oma.js.map} +1 -1
  13. package/dist/chunks/{Dialog-DKfsk5VN.js → Dialog-h-5MeYpu.js} +9 -9
  14. package/dist/chunks/{Dialog-DKfsk5VN.js.map → Dialog-h-5MeYpu.js.map} +1 -1
  15. package/dist/chunks/{Disclosure-Ch2KxYuB.js → Disclosure-CpWt87nO.js} +7 -7
  16. package/dist/chunks/{Disclosure-Ch2KxYuB.js.map → Disclosure-CpWt87nO.js.map} +1 -1
  17. package/dist/chunks/FitLabel-BzZGkWfL.js +76 -0
  18. package/dist/chunks/FitLabel-BzZGkWfL.js.map +1 -0
  19. package/dist/chunks/{GradientEditor-DD2OjQtn.js → GradientEditor-vz771M-N.js} +4 -4
  20. package/dist/chunks/{GradientEditor-DD2OjQtn.js.map → GradientEditor-vz771M-N.js.map} +1 -1
  21. package/dist/chunks/{Icon--B1ME-6c.js → Icon-DPRUIo3G.js} +4 -1
  22. package/dist/chunks/Icon-DPRUIo3G.js.map +1 -0
  23. package/dist/chunks/{Jog-BrkzdGV2.js → Jog-TE6QI9i1.js} +3 -3
  24. package/dist/chunks/{Jog-BrkzdGV2.js.map → Jog-TE6QI9i1.js.map} +1 -1
  25. package/dist/chunks/{LayerList-Bxj1N6bj.js → LayerList-BXTAjK-4.js} +6 -6
  26. package/dist/chunks/{LayerList-Bxj1N6bj.js.map → LayerList-BXTAjK-4.js.map} +1 -1
  27. package/dist/chunks/{ListEditor-OQDzG4A5.js → ListEditor-DGtwj99m.js} +2 -2
  28. package/dist/chunks/{ListEditor-OQDzG4A5.js.map → ListEditor-DGtwj99m.js.map} +1 -1
  29. package/dist/chunks/{MeshEditor-DWpvg8H6.js → MeshEditor-8CRsu-Td.js} +2 -2
  30. package/dist/chunks/{MeshEditor-DWpvg8H6.js.map → MeshEditor-8CRsu-Td.js.map} +1 -1
  31. package/dist/chunks/{NumberField-DS0WSiin.js → NumberField-BXFrOi5M.js} +8 -5
  32. package/dist/chunks/{NumberField-DS0WSiin.js.map → NumberField-BXFrOi5M.js.map} +1 -1
  33. package/dist/chunks/{PaintField-BdmQM53v.js → PaintField-DX4uYlF9.js} +2 -2
  34. package/dist/chunks/{PaintField-BdmQM53v.js.map → PaintField-DX4uYlF9.js.map} +1 -1
  35. package/dist/chunks/{PaintInput-DaQMeBsI.js → PaintInput-CWyOJXUM.js} +5 -5
  36. package/dist/chunks/{PaintInput-DaQMeBsI.js.map → PaintInput-CWyOJXUM.js.map} +1 -1
  37. package/dist/chunks/{PatternPicker-B3HcMZWg.js → PatternPicker-0j51aDJ3.js} +9 -9
  38. package/dist/chunks/PatternPicker-0j51aDJ3.js.map +1 -0
  39. package/dist/chunks/{Prefs-C4MZ28SX.js → Prefs-gbjYqvSD.js} +41 -41
  40. package/dist/chunks/Prefs-gbjYqvSD.js.map +1 -0
  41. package/dist/chunks/{Properties-DseN56WI.js → Properties-BbNuMiic.js} +4 -4
  42. package/dist/chunks/{Properties-DseN56WI.js.map → Properties-BbNuMiic.js.map} +1 -1
  43. package/dist/chunks/PropertyField-CWUtNK1w.js +751 -0
  44. package/dist/chunks/PropertyField-CWUtNK1w.js.map +1 -0
  45. package/dist/chunks/{SelectionPanel-C3WzyaZV.js → SelectionPanel-BpUqP75b.js} +2 -2
  46. package/dist/chunks/{SelectionPanel-C3WzyaZV.js.map → SelectionPanel-BpUqP75b.js.map} +1 -1
  47. package/dist/chunks/{SidebarPanel-AXQ0jRDx.js → SidebarPanel--dJ-k9-V.js} +3 -3
  48. package/dist/chunks/{SidebarPanel-AXQ0jRDx.js.map → SidebarPanel--dJ-k9-V.js.map} +1 -1
  49. package/dist/chunks/Slider-CHBQ8uUC.js +439 -0
  50. package/dist/chunks/Slider-CHBQ8uUC.js.map +1 -0
  51. package/dist/chunks/{SwatchGrid-9ZPiDmxd.js → SwatchGrid-DxK9e_IV.js} +3 -3
  52. package/dist/chunks/SwatchGrid-DxK9e_IV.js.map +1 -0
  53. package/dist/chunks/{SwatchStrip-Bi9iPLoh.js → SwatchStrip-BY6A511W.js} +2 -2
  54. package/dist/chunks/{SwatchStrip-Bi9iPLoh.js.map → SwatchStrip-BY6A511W.js.map} +1 -1
  55. package/dist/chunks/{ThemeSwitcher-DiBmMh_B.js → ThemeSwitcher-tnATkIo1.js} +2 -2
  56. package/dist/chunks/{ThemeSwitcher-DiBmMh_B.js.map → ThemeSwitcher-tnATkIo1.js.map} +1 -1
  57. package/dist/chunks/{Timeline-sMCH2fah.js → Timeline-FlLUm8nd.js} +4 -4
  58. package/dist/chunks/{Timeline-sMCH2fah.js.map → Timeline-FlLUm8nd.js.map} +1 -1
  59. package/dist/chunks/{Toast-C3ozq11V.js → Toast-CuHkT0x0.js} +2 -2
  60. package/dist/chunks/{Toast-C3ozq11V.js.map → Toast-CuHkT0x0.js.map} +1 -1
  61. package/dist/chunks/ToggleBar-BZ4Gk1IU.js +84 -0
  62. package/dist/chunks/ToggleBar-BZ4Gk1IU.js.map +1 -0
  63. package/dist/chunks/{TokenPanel-WtKGY2Db.js → TokenPanel-DongdiZM.js} +23 -23
  64. package/dist/chunks/{TokenPanel-WtKGY2Db.js.map → TokenPanel-DongdiZM.js.map} +1 -1
  65. package/dist/chunks/ToolOptionsBar-wTPJFfOn.js +94 -0
  66. package/dist/chunks/ToolOptionsBar-wTPJFfOn.js.map +1 -0
  67. package/dist/chunks/{Tree-Cc8lIzgM.js → Tree-hzIbj2q1.js} +2 -2
  68. package/dist/chunks/{Tree-Cc8lIzgM.js.map → Tree-hzIbj2q1.js.map} +1 -1
  69. package/dist/chunks/checkbox.module-Dcx8ILgR.js +5 -0
  70. package/dist/chunks/checkbox.module-Dcx8ILgR.js.map +1 -0
  71. package/dist/chunks/{icons-Dr2-r30x.js → icons-CofIOTiI.js} +2 -2
  72. package/dist/chunks/{icons-Dr2-r30x.js.map → icons-CofIOTiI.js.map} +1 -1
  73. package/dist/chunks/{model-qsAFK7_0.js → model-qQj8Ny9w.js} +134 -133
  74. package/dist/chunks/model-qQj8Ny9w.js.map +1 -0
  75. package/dist/chunks/{prefField-BE_Ytr2H.js → prefField-CCm_nzlM.js} +81 -75
  76. package/dist/chunks/prefField-CCm_nzlM.js.map +1 -0
  77. package/dist/components/Callout/index.js +1 -1
  78. package/dist/components/Checkbox/index.js +1 -1
  79. package/dist/components/CloseButton/index.js +1 -1
  80. package/dist/components/ColorModeControl/index.js +1 -1
  81. package/dist/components/DataGrid/index.js +1 -1
  82. package/dist/components/DetentSlider/index.js +1 -1
  83. package/dist/components/Dialog/index.js +1 -1
  84. package/dist/components/Disclosure/index.js +1 -1
  85. package/dist/components/FitLabel/FitLabel.d.ts +41 -0
  86. package/dist/components/FitLabel/FitLabel.d.ts.map +1 -0
  87. package/dist/components/FitLabel/index.d.ts +3 -0
  88. package/dist/components/FitLabel/index.d.ts.map +1 -0
  89. package/dist/components/FitLabel/index.js +2 -0
  90. package/dist/components/GradientEditor/index.js +1 -1
  91. package/dist/components/InlineRange/InlineRange.d.ts +1 -1
  92. package/dist/components/Jog/index.js +1 -1
  93. package/dist/components/LayerList/index.js +1 -1
  94. package/dist/components/ListEditor/index.js +1 -1
  95. package/dist/components/MeshEditor/index.js +1 -1
  96. package/dist/components/NumberField/UnitField.d.ts.map +1 -1
  97. package/dist/components/NumberField/index.js +1 -1
  98. package/dist/components/PaintField/index.js +1 -1
  99. package/dist/components/PaintInput/index.js +1 -1
  100. package/dist/components/PatternPicker/index.js +1 -1
  101. package/dist/components/Prefs/index.js +2 -2
  102. package/dist/components/Prefs/prefField.d.ts.map +1 -1
  103. package/dist/components/Properties/NumberControls.d.ts +16 -0
  104. package/dist/components/Properties/NumberControls.d.ts.map +1 -0
  105. package/dist/components/Properties/PropertyField.d.ts +18 -8
  106. package/dist/components/Properties/PropertyField.d.ts.map +1 -1
  107. package/dist/components/Properties/index.js +2 -2
  108. package/dist/components/SelectionPanel/index.js +2 -2
  109. package/dist/components/SelectionPanel/renderLeaf.d.ts.map +1 -1
  110. package/dist/components/SidebarPanel/index.js +1 -1
  111. package/dist/components/Slider/Slider.d.ts +6 -0
  112. package/dist/components/Slider/Slider.d.ts.map +1 -1
  113. package/dist/components/Slider/index.js +1 -1
  114. package/dist/components/SwatchGrid/index.js +1 -1
  115. package/dist/components/SwatchStrip/index.js +1 -1
  116. package/dist/components/ThemeSwitcher/index.js +1 -1
  117. package/dist/components/Timeline/index.js +1 -1
  118. package/dist/components/Toast/index.js +1 -1
  119. package/dist/components/ToggleBar/ToggleBar.d.ts.map +1 -1
  120. package/dist/components/ToggleBar/index.js +1 -1
  121. package/dist/components/TokenPanel/index.js +1 -1
  122. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts +1 -1
  123. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts.map +1 -1
  124. package/dist/components/ToolOptionsBar/index.js +1 -1
  125. package/dist/components/Tree/index.js +1 -1
  126. package/dist/components/stanceCss.d.ts +6 -0
  127. package/dist/components/stanceCss.d.ts.map +1 -1
  128. package/dist/components/stanceSurfaces.d.ts.map +1 -1
  129. package/dist/endless.d.ts +7 -0
  130. package/dist/endless.d.ts.map +1 -0
  131. package/dist/icons/paths.d.ts +2 -0
  132. package/dist/icons/paths.d.ts.map +1 -1
  133. package/dist/index.d.ts +1 -0
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +72 -70
  136. package/dist/index.js.map +1 -1
  137. package/dist/style.css +1 -1
  138. package/package.json +9 -9
  139. package/dist/chunks/Callout-BUn0dP_S.js.map +0 -1
  140. package/dist/chunks/Icon--B1ME-6c.js.map +0 -1
  141. package/dist/chunks/PatternPicker-B3HcMZWg.js.map +0 -1
  142. package/dist/chunks/Prefs-C4MZ28SX.js.map +0 -1
  143. package/dist/chunks/PropertyField-BbNqK8xr.js +0 -743
  144. package/dist/chunks/PropertyField-BbNqK8xr.js.map +0 -1
  145. package/dist/chunks/Slider-DSrlMEq8.js +0 -389
  146. package/dist/chunks/Slider-DSrlMEq8.js.map +0 -1
  147. package/dist/chunks/SwatchGrid-9ZPiDmxd.js.map +0 -1
  148. package/dist/chunks/ToggleBar-Z2jZiguF.js +0 -80
  149. package/dist/chunks/ToggleBar-Z2jZiguF.js.map +0 -1
  150. package/dist/chunks/ToolOptionsBar-CZTYPoC2.js +0 -88
  151. package/dist/chunks/ToolOptionsBar-CZTYPoC2.js.map +0 -1
  152. package/dist/chunks/checkbox.module-DLQV9tMX.js +0 -5
  153. package/dist/chunks/checkbox.module-DLQV9tMX.js.map +0 -1
  154. package/dist/chunks/model-qsAFK7_0.js.map +0 -1
  155. package/dist/chunks/prefField-BE_Ytr2H.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TokenPanel-WtKGY2Db.js","names":["s","_Fragment","NumberField","Select","Input","Button","TooltipTrigger","Tooltip","Tooltip$1","TooltipTrigger$1","Button$1","Select$1","Input$1","NumberField$1","ToggleBar","HEX","RGB","COLOR_FUNCTION","KEYWORDS","browserSupports","value","parsesAsColor","v","supports","hexOf","digits","d","rgb","n","paint","serialized","onBlack","toHex","direct","browser","TokenPanel_module_default","round2","refitScale","first","amounts","scale","last","spans","kind","a","TOKEN_CATEGORIES","TYPE_SCALE","tokenCategory","token","AMOUNT","DIMENSION","DURATION","NUMBER","LENGTH","BEZIER","GRADIENT","LAYERS","PARTS","isShadow","parts","layer","lengths","part","rest","inferTokenType","splitUnit","match","bezierPoints","x1","y1","x2","y2","WEIGHTS","NUMBER_FORMAT","SCALAR","familyKindOf","itemsOf","counts","tokens","families","items","key","familySize","family","stepLabels","split","names","name","shared","segments","Curve","points","top","bottom","label","TokenControl","hex","useMemo","type","Fragment","amount","set","options","weight","event","TokenRow","memo","useCallback","onChange","b","Family","picked","setPicked","useState","t","group","Focusable","current","ScaleStep","showUnit","factor","onFactorChange","next","RULES","ScaleRuleControls","param","rule","base","onScaleChange","unit","Scale","labels","units","overridden","generator","at","i","j","f","Section","title","DisclosureRow","open","item","scales","TokenPanel","ownCollapsed","setOwnCollapsed","closed","collapsed","byCategory","sections","category","categorize","density","className","inSection","id","prev","onCollapsedChange"],"sources":["../../src/components/TokenPanel/color.ts","../../src/components/TokenPanel/TokenPanel.module.css","../../src/components/TokenPanel/tokenTypes.ts","../../src/components/TokenPanel/TokenPanel.tsx"],"sourcesContent":["const HEX = /^#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i;\nconst RGB = /^rgba?\\(\\s*(\\d{1,3})[\\s,]+(\\d{1,3})[\\s,]+(\\d{1,3})\\b/i;\nconst COLOR_FUNCTION = /^(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix)\\(.+\\)$/i;\nconst KEYWORDS = new Set([\n 'transparent',\n 'currentcolor',\n 'black',\n 'white',\n 'gray',\n 'silver',\n 'red',\n 'orange',\n 'yellow',\n 'gold',\n 'lime',\n 'green',\n 'teal',\n 'cyan',\n 'blue',\n 'navy',\n 'purple',\n 'magenta',\n 'pink',\n 'brown',\n]);\n\ntype Supports = ((value: string) => boolean) | null;\n\nfunction browserSupports(): Supports {\n return typeof CSS !== 'undefined' && typeof CSS.supports === 'function'\n ? (value) => CSS.supports('color', value)\n : null;\n}\n\n/** Whether `value` is a CSS color — the browser's answer where it has `CSS.supports`, a small parser's otherwise. */\nexport function parsesAsColor(value: string, supports: Supports = browserSupports()): boolean {\n const v = value.trim();\n // `CSS.supports` accepts any `var()` for any property.\n if (!v || v.includes('var(')) return false;\n if (supports) return supports(v);\n return HEX.test(v) || COLOR_FUNCTION.test(v) || KEYWORDS.has(v.toLowerCase());\n}\n\nfunction hexOf(v: string): string | null {\n if (HEX.test(v)) {\n const digits = v.slice(1).toLowerCase();\n return `#${digits.length <= 4 ? [...digits.slice(0, 3)].map((d) => d + d).join('') : digits.slice(0, 6)}`;\n }\n const rgb = RGB.exec(v);\n return rgb\n ? `#${rgb\n .slice(1, 4)\n .map((n) => Math.min(255, Number(n)).toString(16).padStart(2, '0'))\n .join('')}`\n : null;\n}\n\nlet paint: CanvasRenderingContext2D | null | undefined;\n\n/** The browser's serialization of a color, through a canvas fill style; null where it has none or rejects `value`. */\nfunction serialized(value: string): string | null {\n if (paint === undefined) {\n try {\n paint = document.createElement('canvas').getContext('2d');\n } catch {\n paint = null;\n }\n }\n if (!paint) return null;\n // A rejected value leaves the previous fill style, so two different ones tell a rejection apart.\n paint.fillStyle = '#000000';\n paint.fillStyle = value;\n const onBlack = String(paint.fillStyle);\n paint.fillStyle = '#ffffff';\n paint.fillStyle = value;\n return onBlack === String(paint.fillStyle) ? onBlack : null;\n}\n\n/** `value` as the `#rrggbb` a color input takes, alpha dropped; null when it cannot be converted. */\nexport function toHex(value: string): string | null {\n const v = value.trim();\n const direct = hexOf(v);\n if (direct) return direct;\n const browser = typeof document === 'undefined' ? null : serialized(v);\n return browser && browser !== v ? hexOf(browser) : null;\n}\n",".panel {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.section {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.section + .section {\n border-top: var(--wzl-border-w) solid var(--wzl-line-subtle);\n}\n\n.sectionHead {\n padding-block: var(--wzl-space-xs);\n color: var(--wzl-fg-muted);\n font-family: var(--wzl-font-display);\n font-size: var(--wzl-font-size-sm);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.sectionBody {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-sm);\n padding-block-end: var(--wzl-space-sm);\n}\n\n.row,\n.family {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.name {\n overflow: hidden;\n color: var(--wzl-fg-muted);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.edit {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-xs);\n min-width: 0;\n}\n\n.field {\n --wzl-font-ui: var(--wzl-font-mono);\n flex: 1;\n min-width: 0;\n}\n\n.number {\n flex: 1;\n min-width: 0;\n}\n\n.unit {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-sm);\n}\n\n/* Padding inflates a native color input past its box in Chrome. */\n.swatchInput {\n box-sizing: border-box;\n flex-shrink: 0;\n width: 18px;\n height: 14px;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: var(--wzl-radius-sm);\n cursor: pointer;\n}\n\n.chip {\n flex-shrink: 0;\n width: 18px;\n height: 14px;\n background: var(--token-color);\n border-radius: var(--wzl-radius-sm);\n box-shadow: inset 0 0 0 1px var(--wzl-line);\n}\n\n.curve {\n flex-shrink: 0;\n width: 24px;\n /* Square easing-curve artwork: not-a-control */\n height: 24px;\n color: var(--wzl-fg);\n}\n\n.strip {\n display: flex;\n height: var(--wzl-control-h);\n overflow: hidden;\n border: var(--wzl-border-w) solid var(--wzl-line);\n border-radius: var(--wzl-radius-sm);\n}\n\n.swatch {\n flex: 1 1 0;\n min-width: 0;\n height: 100%;\n padding: 0;\n background: var(--token-color);\n border: 0;\n border-radius: 0;\n cursor: pointer;\n}\n\n.swatch[data-overridden] {\n box-shadow: inset 0 -3px 0 var(--wzl-accent);\n}\n\n.swatch[aria-pressed='true'],\n.swatch:focus-visible {\n position: relative;\n z-index: 1;\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n/* A group of sizes: its name over a grid of steps, each labeled by what its name adds. */\n.scale {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.scaleHead {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-xs);\n min-width: 0;\n}\n\n.steps {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(4rem, 1fr));\n gap: var(--wzl-space-1) var(--wzl-space-xs);\n}\n\n.rule {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-xs) var(--wzl-space-sm);\n min-width: 0;\n}\n\n.ruleLabel {\n color: var(--wzl-fg-subtle);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-2xs);\n}\n\n.rule .number {\n flex: 0 1 5ch;\n text-align: end;\n}\n\n.step {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.stepLabel {\n overflow: hidden;\n text-align: end;\n color: var(--wzl-fg-subtle);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-2xs);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.step[data-overridden] .stepLabel {\n color: var(--wzl-accent-fg);\n}\n\n.stepEdit {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.step > .stepEdit + .stepEdit {\n margin-block-start: var(--wzl-space-1);\n}\n\n.stepEdit .number {\n text-align: end;\n}\n\n/* Tight: a token to a line, with the names on a fixed rail so the values read\n down the panel as a column. A stacked row spends its height on the name and\n lets the field take the whole width, which a set of ninety cannot afford. */\n.tight .sectionBody {\n gap: var(--wzl-space-1);\n padding-block-end: var(--wzl-space-xs);\n}\n\n.tight .row {\n flex-direction: row;\n align-items: center;\n gap: var(--wzl-space-xs);\n}\n\n.tight .row > .name {\n flex: 0 0 11rem;\n}\n\n.tight .edit {\n flex: 1 1 auto;\n}\n\n.tight .field,\n.tight .number {\n flex: 0 1 16rem;\n}\n\n.tight .scale {\n display: grid;\n grid-template-columns: 11rem minmax(0, 1fr);\n align-items: start;\n column-gap: var(--wzl-space-xs);\n}\n\n/* Grid rather than a row, so a picked swatch's editor still spans the full width. */\n.tight .family {\n display: grid;\n grid-template-columns: 11rem minmax(0, 1fr);\n align-items: center;\n column-gap: var(--wzl-space-xs);\n row-gap: var(--wzl-space-1);\n}\n\n.tight .family > .row {\n grid-column: 1 / -1;\n}\n\n.tight .strip {\n height: 16px;\n}\n\n.tight .curve {\n width: 16px;\n height: 16px;\n}\n","import { parsesAsColor } from './color';\n\n/** A design token as `TokenPanel` edits it. */\nexport interface TokenEntry {\n /** The custom property, e.g. `--wzl-gray-50`. */\n name: string;\n /** A DTCG type name. A type the panel has no control for edits as text. */\n type: string;\n /** Tokens sharing a group sit together; a color group large enough draws as one row of swatches. */\n group: string;\n value: string;\n /** Whether `value` overrides the token's own, which offers Reset. */\n overridden?: boolean;\n description?: string;\n}\n\n/** How a scale's steps follow from its base: one multiplier per step, a constant ratio, or a constant step. */\nexport type TokenScaleRule =\n | { kind: 'factors'; factors: readonly number[] }\n | { kind: 'ratio'; ratio: number }\n | { kind: 'step'; step: number };\n\n/** A group whose steps are generated from a base, so the panel edits the base and the rule rather than each step. */\nexport interface TokenScale {\n /** The generated tokens, smallest first. Anything else in the group draws as an ordinary step. */\n tokens: readonly string[];\n base: number;\n rule: TokenScaleRule;\n}\n\nconst round2 = (n: number) => Math.round(n * 100) / 100;\n\n/**\n * The same scale under another rule, fitted to the amounts its steps have now.\n * A ratio or step counts from the first step, so switching to one moves the\n * base there.\n */\nexport function refitScale(scale: TokenScale, kind: TokenScaleRule['kind'], amounts: readonly number[]): TokenScale {\n const first = amounts[0] ?? scale.base;\n const last = amounts.at(-1) ?? first;\n const spans = Math.max(1, amounts.length - 1);\n switch (kind) {\n case 'factors':\n return { ...scale, rule: { kind, factors: amounts.map((a) => (scale.base ? round2(a / scale.base) : 1)) } };\n case 'ratio':\n return { ...scale, base: first, rule: { kind, ratio: first > 0 ? round2((last / first) ** (1 / spans)) : 1 } };\n case 'step':\n return { ...scale, base: first, rule: { kind, step: round2((last - first) / spans) } };\n }\n}\n\n/** A section of the token panel; `tokenCategory` files each token under one. */\nexport type TokenCategory ='color' | 'type' | 'size' | 'motion' | 'depth' | 'other';\n\n/** The panel's sections, in the order it draws them. */\nexport const TOKEN_CATEGORIES: readonly { id: TokenCategory; title: string }[] = [\n { id: 'color', title: 'Color' },\n { id: 'type', title: 'Type' },\n { id: 'size', title: 'Size' },\n { id: 'motion', title: 'Motion' },\n { id: 'depth', title: 'Depth' },\n { id: 'other', title: 'Other' },\n];\n\nconst TYPE_SCALE = /^(?:font|tracking|leading|letter|line-height)/;\n\n/** The section a token is filed under: by its type, and for a bare dimension or number by its group. */\nexport function tokenCategory(token: TokenEntry): TokenCategory {\n switch (token.type) {\n case 'color':\n return 'color';\n case 'fontFamily':\n case 'fontWeight':\n return 'type';\n case 'duration':\n case 'cubicBezier':\n return 'motion';\n case 'shadow':\n case 'gradient':\n return 'depth';\n case 'dimension':\n case 'number':\n if (TYPE_SCALE.test(token.group)) return 'type';\n if (token.type === 'number' && (token.group === 'z' || token.group === 'z-index')) return 'depth';\n return 'size';\n default:\n return 'other';\n }\n}\n\nconst AMOUNT = String.raw`-?(?:\\d+\\.?\\d*|\\.\\d+)`;\nconst DIMENSION = new RegExp(\n `^${AMOUNT}(?:px|rem|em|%|ch|ex|lh|rlh|vh|vw|vmin|vmax|svh|lvh|dvh|cqw|cqh|pt|pc|cm|mm|in|q)$`,\n 'i',\n);\nconst DURATION = new RegExp(`^${AMOUNT}m?s$`);\nconst NUMBER = new RegExp(`^${AMOUNT}$`);\nconst LENGTH = new RegExp(`^${AMOUNT}(?:px|rem|em)?$`);\nconst BEZIER = new RegExp(`^cubic-bezier\\\\(\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*\\\\)$`, 'i');\nconst GRADIENT = /^(?:repeating-)?(?:linear|radial|conic)-gradient\\(/i;\n/** Commas outside parentheses: a shadow's layers, not a color function's arguments. */\nconst LAYERS = /,(?![^(]*\\))/;\nconst PARTS = /[a-z-]+\\([^)]*\\)|\\S+/gi;\n\nfunction isShadow(value: string): boolean {\n return value.split(LAYERS).every((layer) => {\n const parts = layer.trim().replace(/^inset\\s+/i, '').match(PARTS) ?? [];\n const lengths = parts.filter((part) => LENGTH.test(part));\n const rest = parts.filter((part) => !LENGTH.test(part));\n return lengths.length >= 2 && lengths.length <= 4 && rest.length <= 1 && rest.every((part) => parsesAsColor(part));\n });\n}\n\n/** A DTCG type read off the shape of a value, for a token that arrives without one. `'string'` when nothing fits. */\nexport function inferTokenType(value: string): string {\n const v = value.trim();\n if (!v) return 'string';\n if (DURATION.test(v)) return 'duration';\n if (DIMENSION.test(v)) return 'dimension';\n if (NUMBER.test(v)) return 'number';\n if (BEZIER.test(v)) return 'cubicBezier';\n if (GRADIENT.test(v)) return 'gradient';\n if (parsesAsColor(v)) return 'color';\n if (isShadow(v)) return 'shadow';\n return 'string';\n}\n\n/** A number and its unit, or null for a value that is not one. */\nexport function splitUnit(value: string): { amount: number; unit: string } | null {\n const match = new RegExp(`^(${AMOUNT})([a-z%]*)$`, 'i').exec(value.trim());\n return match ? { amount: Number(match[1]), unit: match[2] ?? '' } : null;\n}\n\n/** The four control points of a `cubic-bezier()`, or null for any other easing. */\nexport function bezierPoints(value: string): readonly [number, number, number, number] | null {\n const match = BEZIER.exec(value.trim());\n if (!match) return null;\n const [x1, y1, x2, y2] = match.slice(1, 5).map(Number) as [number, number, number, number];\n return [x1, y1, x2, y2];\n}\n","import { type CSSProperties, memo, useCallback, useMemo, useState } from 'react';\nimport { Focusable } from 'react-aria-components';\nimport { Button } from '../Button';\nimport { DisclosureRow } from '../Disclosure';\nimport { Input } from '../Input';\nimport { NumberField } from '../NumberField';\nimport { Select } from '../Select';\nimport { ToggleBar, type ToggleBarItem } from '../ToggleBar';\nimport { Tooltip, TooltipTrigger } from '../Tooltip';\nimport { toHex } from './color';\nimport s from './TokenPanel.module.css';\nimport {\n bezierPoints,\n refitScale,\n splitUnit,\n TOKEN_CATEGORIES,\n type TokenCategory,\n type TokenEntry,\n type TokenScale,\n type TokenScaleRule,\n tokenCategory,\n} from './tokenTypes';\n\ntype OnChange = (name: string, value: string | null) => void;\n\n/** Props for `<TokenPanel>`. */\nexport interface TokenPanelProps {\n tokens: readonly TokenEntry[];\n /** A token's new value, or null to drop its override. Keep it stable: rows re-render only when it or their token changes. */\n onChange: OnChange;\n /** Sections held closed, by category. Omit to let the panel keep that state itself. */\n collapsed?: Readonly<Partial<Record<TokenCategory, boolean>>>;\n onCollapsedChange?: (category: TokenCategory, collapsed: boolean) => void;\n /** Groups generated from a base, by group name. Such a group edits its base and rule above its steps. */\n scales?: Readonly<Record<string, TokenScale>>;\n /** A scale's new base or rule. The panel does not regenerate the steps; the consumer does, through `onChange`. */\n onScaleChange?: (group: string, scale: TokenScale) => void;\n /** Files a token under a section. Defaults to `tokenCategory`. */\n categorize?: (token: TokenEntry) => TokenCategory;\n /** The fewest colors, or sizes, sharing a group that draw as one row of swatches or one grid of steps. Default 3. */\n familySize?: number;\n /**\n * Row layout. `tight` puts a token on one line — name, control, Reset — with the\n * names on a fixed rail so the values read down the panel as a column, and caps\n * the field rather than letting it span the panel. Default `normal` stacks the\n * control under its name.\n */\n density?: 'tight' | 'normal';\n className?: string;\n}\n\nconst WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];\nconst NUMBER_FORMAT = { maximumFractionDigits: 4, useGrouping: false } as const;\n\ntype FamilyKind = 'family' | 'scale';\ntype Item = { kind: 'row'; token: TokenEntry } | { kind: FamilyKind; group: string; tokens: TokenEntry[] };\n\nconst SCALAR = new Set(['dimension', 'duration', 'number']);\n\nfunction familyKindOf(token: TokenEntry): FamilyKind | null {\n if (token.type === 'color') return 'family';\n return SCALAR.has(token.type) && splitUnit(token.value) ? 'scale' : null;\n}\n\nfunction itemsOf(tokens: readonly TokenEntry[], familySize: number): Item[] {\n const counts = new Map<string, number>();\n for (const token of tokens) {\n const kind = familyKindOf(token);\n if (kind) counts.set(`${kind}:${token.group}`, (counts.get(`${kind}:${token.group}`) ?? 0) + 1);\n }\n const families = new Map<string, Extract<Item, { kind: FamilyKind }>>();\n const items: Item[] = [];\n for (const token of tokens) {\n const kind = familyKindOf(token);\n const key = `${kind}:${token.group}`;\n if (!kind || (counts.get(key) ?? 0) < familySize) {\n items.push({ kind: 'row', token });\n continue;\n }\n let family = families.get(key);\n if (!family) {\n family = { kind, group: token.group, tokens: [] };\n families.set(key, family);\n items.push(family);\n }\n family.tokens.push(token);\n }\n return items;\n}\n\n/** Each name's segments past those every name in the set shares; a name that is all shared keeps its last. */\nfunction stepLabels(names: readonly string[]): string[] {\n const split = names.map((name) => name.replace(/^--/, '').split('-'));\n let shared = 0;\n while (split.every((segments) => segments.length > shared && segments[shared] === split[0]?.[shared])) shared++;\n return split.map((segments) => segments.slice(shared).join('-') || (segments.at(-1) ?? ''));\n}\n\nfunction Curve({ points, label }: { points: readonly [number, number, number, number]; label: string }) {\n const [x1, y1, x2, y2] = points;\n // y is flipped so the curve rises, and the box grows to hold an overshoot.\n const top = Math.min(0, 1 - y1, 1 - y2);\n const bottom = Math.max(1, 1 - y1, 1 - y2);\n return (\n <svg className={s.curve} viewBox={`-0.1 ${top - 0.1} 1.2 ${bottom - top + 0.2}`} role=\"img\" aria-label={label}>\n <path d={`M0 1 C${x1} ${1 - y1} ${x2} ${1 - y2} 1 0`} fill=\"none\" stroke=\"currentColor\" strokeWidth={0.08} />\n </svg>\n );\n}\n\nfunction TokenControl({ token, set }: { token: TokenEntry; set: (value: string) => void }) {\n const { name, type, value } = token;\n const label = `${name} value`;\n const hex = useMemo(() => (type === 'color' ? toHex(value) : null), [type, value]);\n\n if (type === 'dimension' || type === 'duration' || type === 'number') {\n const split = splitUnit(value);\n if (split) {\n return (\n <>\n <NumberField\n className={s.number}\n aria-label={label}\n value={split.amount}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(amount) => {\n if (Number.isFinite(amount)) set(`${amount}${split.unit}`);\n }}\n />\n {split.unit ? <span className={s.unit}>{split.unit}</span> : null}\n </>\n );\n }\n }\n\n if (type === 'fontWeight') {\n const options = (WEIGHTS.includes(value) ? WEIGHTS : [...WEIGHTS, value]).map((weight) => ({\n value: weight,\n label: weight,\n }));\n return <Select aria-label={name} width=\"fit\" selectedKey={value} options={options} onSelectionChange={set} />;\n }\n\n const points = type === 'cubicBezier' ? bezierPoints(value) : null;\n return (\n <>\n {points ? <Curve points={points} label={`${name} curve`} /> : null}\n <Input\n className={s.field}\n aria-label={label}\n value={value}\n onChange={set}\n leadingAdornment={\n type !== 'color' ? undefined : hex ? (\n <input\n type=\"color\"\n className={s.swatchInput}\n aria-label={`${name} color`}\n value={hex}\n onChange={(event) => set(event.target.value)}\n />\n ) : (\n <span className={s.chip} style={{ '--token-color': value } as CSSProperties} aria-hidden=\"true\" />\n )\n }\n />\n </>\n );\n}\n\nconst TokenRow = memo(\n function TokenRow({ token, onChange }: { token: TokenEntry; onChange: OnChange }) {\n const set = useCallback((value: string) => onChange(token.name, value), [onChange, token.name]);\n return (\n <div className={s.row} role=\"group\" aria-label={token.name}>\n <span className={s.name} title={token.description || token.name}>\n {token.name}\n </span>\n <div className={s.edit}>\n <TokenControl token={token} set={set} />\n {token.overridden ? (\n <Button variant=\"ghost\" size=\"sm\" ariaLabel={`Reset ${token.name}`} onClick={() => onChange(token.name, null)}>\n Reset\n </Button>\n ) : null}\n </div>\n </div>\n );\n },\n // Consumers rebuild their entries each render; a row only has to redraw when what it shows changed.\n (a, b) =>\n a.onChange === b.onChange &&\n a.token.name === b.token.name &&\n a.token.type === b.token.type &&\n a.token.value === b.token.value &&\n a.token.overridden === b.token.overridden &&\n a.token.description === b.token.description,\n);\n\nfunction Family({ group, tokens, onChange }: { group: string; tokens: readonly TokenEntry[]; onChange: OnChange }) {\n const [picked, setPicked] = useState<string | null>(null);\n const token = tokens.find((t) => t.name === picked) ?? null;\n return (\n <div className={s.family} role=\"group\" aria-label={group}>\n <span className={s.name}>{group}</span>\n <div className={s.strip}>\n {tokens.map((t) => (\n <TooltipTrigger key={t.name} delay={0}>\n <Focusable>\n <button\n type=\"button\"\n className={s.swatch}\n style={{ '--token-color': t.value } as CSSProperties}\n aria-label={t.name}\n aria-pressed={t.name === picked}\n data-overridden={t.overridden ? '' : undefined}\n onClick={() => setPicked((current) => (current === t.name ? null : t.name))}\n />\n </Focusable>\n <Tooltip>{t.name}</Tooltip>\n </TooltipTrigger>\n ))}\n </div>\n {token ? <TokenRow token={token} onChange={onChange} /> : null}\n </div>\n );\n}\n\nfunction ScaleStep({\n token,\n label,\n showUnit,\n factor,\n onChange,\n onFactorChange,\n}: {\n token: TokenEntry;\n label: string;\n showUnit: boolean;\n factor?: number;\n onChange: OnChange;\n onFactorChange?: (factor: number) => void;\n}) {\n const split = splitUnit(token.value);\n if (!split) return null;\n return (\n <div className={s.step} title={token.description || token.name} data-overridden={token.overridden ? '' : undefined}>\n <span className={s.stepLabel}>{label}</span>\n <span className={s.stepEdit}>\n <NumberField\n className={s.number}\n aria-label={`${token.name} value`}\n value={split.amount}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(amount) => {\n if (Number.isFinite(amount)) onChange(token.name, `${amount}${split.unit}`);\n }}\n />\n {showUnit && split.unit ? <span className={s.unit}>{split.unit}</span> : null}\n </span>\n {factor !== undefined && onFactorChange ? (\n <span className={s.stepEdit}>\n <span className={s.unit}>×</span>\n <NumberField\n className={s.number}\n aria-label={`${token.name} factor`}\n value={factor}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(next) => {\n if (Number.isFinite(next)) onFactorChange(next);\n }}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\nconst RULES: readonly ToggleBarItem<TokenScaleRule['kind']>[] = [\n { value: 'factors', label: 'each', ariaLabel: 'factors' },\n { value: 'ratio', label: 'ratio' },\n { value: 'step', label: 'step' },\n];\n\nfunction ScaleRuleControls({\n group,\n scale,\n unit,\n amounts,\n onScaleChange,\n}: {\n group: string;\n scale: TokenScale;\n unit: string;\n amounts: readonly number[];\n onScaleChange: (scale: TokenScale) => void;\n}) {\n const { rule } = scale;\n const param =\n rule.kind === 'ratio'\n ? { key: 'ratio' as const, value: rule.ratio }\n : rule.kind === 'step'\n ? { key: 'step' as const, value: rule.step }\n : null;\n return (\n <div className={s.rule}>\n <span className={s.stepEdit}>\n <span className={s.ruleLabel}>base</span>\n <NumberField\n className={s.number}\n aria-label={`${group} base`}\n value={scale.base}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(base) => {\n if (Number.isFinite(base)) onScaleChange({ ...scale, base });\n }}\n />\n {unit ? <span className={s.unit}>{unit}</span> : null}\n </span>\n <ToggleBar\n ariaLabel={`${group} rule`}\n size=\"sm\"\n items={RULES}\n value={rule.kind}\n onChange={(kind) => {\n if (kind && kind !== rule.kind) onScaleChange(refitScale(scale, kind, amounts));\n }}\n />\n {param ? (\n <span className={s.stepEdit}>\n {param.key === 'ratio' ? <span className={s.unit}>×</span> : <span className={s.unit}>+</span>}\n <NumberField\n className={s.number}\n aria-label={`${group} ${param.key}`}\n value={param.value}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(value) => {\n if (Number.isFinite(value)) onScaleChange({ ...scale, rule: { kind: param.key, [param.key]: value } as TokenScaleRule });\n }}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\nfunction Scale({\n group,\n tokens,\n generator,\n onChange,\n onScaleChange,\n}: {\n group: string;\n tokens: readonly TokenEntry[];\n generator?: TokenScale;\n onChange: OnChange;\n onScaleChange?: (group: string, scale: TokenScale) => void;\n}) {\n const labels = useMemo(() => stepLabels(tokens.map((t) => t.name)), [tokens]);\n const units = new Set(tokens.map((t) => splitUnit(t.value)?.unit ?? ''));\n const unit = units.size === 1 ? [...units][0] : null;\n const overridden = tokens.filter((t) => t.overridden);\n return (\n <div className={s.scale} role=\"group\" aria-label={group}>\n <span className={s.scaleHead}>\n <span className={s.name}>{group}</span>\n {unit ? <span className={s.unit}>{unit}</span> : null}\n {overridden.length > 0 ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n ariaLabel={`Reset ${group}`}\n onClick={() => {\n for (const t of overridden) onChange(t.name, null);\n }}\n >\n Reset\n </Button>\n ) : null}\n </span>\n {generator && onScaleChange ? (\n <ScaleRuleControls\n group={group}\n scale={generator}\n unit={unit ?? ''}\n amounts={generator.tokens.map(\n (name) => splitUnit(tokens.find((t) => t.name === name)?.value ?? '')?.amount ?? generator.base,\n )}\n onScaleChange={(next) => onScaleChange(group, next)}\n />\n ) : null}\n <div className={s.steps}>\n {tokens.map((t, i) => {\n const rule = generator?.rule;\n const at = generator ? generator.tokens.indexOf(t.name) : -1;\n const factor = rule?.kind === 'factors' && at >= 0 ? rule.factors[at] : undefined;\n return (\n <ScaleStep\n key={t.name}\n token={t}\n label={labels[i] ?? t.name}\n showUnit={unit === null}\n factor={factor}\n onChange={onChange}\n onFactorChange={\n generator && onScaleChange && rule?.kind === 'factors'\n ? (next) =>\n onScaleChange(group, {\n ...generator,\n rule: { kind: 'factors', factors: rule.factors.map((f, j) => (j === at ? next : f)) },\n })\n : undefined\n }\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction Section({\n title,\n open,\n onToggle,\n tokens,\n familySize,\n scales,\n onChange,\n onScaleChange,\n}: {\n title: string;\n open: boolean;\n onToggle: () => void;\n tokens: readonly TokenEntry[];\n familySize: number;\n scales?: Readonly<Record<string, TokenScale>>;\n onChange: OnChange;\n onScaleChange?: (group: string, scale: TokenScale) => void;\n}) {\n const items = useMemo(() => itemsOf(tokens, familySize), [tokens, familySize]);\n return (\n <section className={s.section} aria-label={title}>\n <DisclosureRow className={s.sectionHead} open={open} onToggle={onToggle} label={title}>\n <span aria-hidden=\"true\">{title}</span>\n </DisclosureRow>\n {open ? (\n <div className={s.sectionBody}>\n {items.map((item) =>\n item.kind === 'row' ? (\n <TokenRow key={item.token.name} token={item.token} onChange={onChange} />\n ) : item.kind === 'scale' ? (\n <Scale\n key={`scale:${item.group}`}\n group={item.group}\n tokens={item.tokens}\n generator={scales?.[item.group]}\n onChange={onChange}\n onScaleChange={onScaleChange}\n />\n ) : (\n <Family key={`family:${item.group}`} group={item.group} tokens={item.tokens} onChange={onChange} />\n ),\n )}\n </div>\n ) : null}\n </section>\n );\n}\n\n/**\n * Edits a set of design tokens by type: collapsible sections by category, a\n * color group drawn as one row of swatches sized to fit, a group of sizes drawn\n * as one grid of numbers labeled by step — with its base and rule above it when\n * `scales` says how it is generated — and a control for each\n * type — a number with its unit for dimensions and durations, the nine weights\n * for a font weight, a curve beside a `cubic-bezier()`, a swatch beside a color,\n * and text for everything else.\n */\nexport function TokenPanel({\n tokens,\n onChange,\n collapsed,\n onCollapsedChange,\n scales,\n onScaleChange,\n categorize = tokenCategory,\n familySize = 3,\n density = 'normal',\n className,\n}: TokenPanelProps) {\n const [ownCollapsed, setOwnCollapsed] = useState<Partial<Record<TokenCategory, boolean>>>({});\n const closed = collapsed ?? ownCollapsed;\n const byCategory = useMemo(() => {\n const sections = new Map<TokenCategory, TokenEntry[]>();\n for (const token of tokens) {\n const category = categorize(token);\n sections.set(category, [...(sections.get(category) ?? []), token]);\n }\n return sections;\n }, [tokens, categorize]);\n\n return (\n <div className={[s.panel, density === 'tight' && s.tight, className].filter(Boolean).join(' ')}>\n {TOKEN_CATEGORIES.map(({ id, title }) => {\n const inSection = byCategory.get(id);\n if (!inSection) return null;\n const open = !closed[id];\n return (\n <Section\n key={id}\n title={title}\n open={open}\n onToggle={() => {\n if (collapsed === undefined) setOwnCollapsed((prev) => ({ ...prev, [id]: open }));\n onCollapsedChange?.(id, open);\n }}\n tokens={inSection}\n familySize={familySize}\n scales={scales}\n onChange={onChange}\n onScaleChange={onScaleChange}\n />\n );\n })}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TokenPanel-DongdiZM.js","names":["s","_Fragment","NumberField","Select","Input","Button","TooltipTrigger","Tooltip","Tooltip$1","TooltipTrigger$1","Button$1","Select$1","Input$1","ToggleBar","NumberField$1","HEX","RGB","COLOR_FUNCTION","KEYWORDS","browserSupports","value","parsesAsColor","v","supports","hexOf","digits","d","rgb","n","paint","serialized","onBlack","toHex","direct","browser","TokenPanel_module_default","round2","refitScale","first","amounts","scale","last","spans","kind","a","TOKEN_CATEGORIES","TYPE_SCALE","tokenCategory","token","AMOUNT","DIMENSION","DURATION","NUMBER","LENGTH","BEZIER","GRADIENT","LAYERS","PARTS","isShadow","parts","layer","lengths","part","rest","inferTokenType","splitUnit","match","bezierPoints","x1","y1","x2","y2","WEIGHTS","NUMBER_FORMAT","SCALAR","familyKindOf","itemsOf","counts","tokens","families","items","key","familySize","family","stepLabels","split","names","name","shared","segments","Curve","points","top","bottom","label","TokenControl","hex","useMemo","type","Fragment","amount","set","options","weight","event","TokenRow","memo","useCallback","onChange","b","Family","picked","setPicked","useState","t","group","Focusable","current","ScaleStep","showUnit","factor","onFactorChange","next","RULES","ScaleRuleControls","param","rule","base","onScaleChange","unit","Scale","labels","units","overridden","generator","at","i","j","f","Section","title","DisclosureRow","open","item","scales","TokenPanel","ownCollapsed","setOwnCollapsed","closed","collapsed","byCategory","sections","category","categorize","density","className","inSection","id","prev","onCollapsedChange"],"sources":["../../src/components/TokenPanel/color.ts","../../src/components/TokenPanel/TokenPanel.module.css","../../src/components/TokenPanel/tokenTypes.ts","../../src/components/TokenPanel/TokenPanel.tsx"],"sourcesContent":["const HEX = /^#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i;\nconst RGB = /^rgba?\\(\\s*(\\d{1,3})[\\s,]+(\\d{1,3})[\\s,]+(\\d{1,3})\\b/i;\nconst COLOR_FUNCTION = /^(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix)\\(.+\\)$/i;\nconst KEYWORDS = new Set([\n 'transparent',\n 'currentcolor',\n 'black',\n 'white',\n 'gray',\n 'silver',\n 'red',\n 'orange',\n 'yellow',\n 'gold',\n 'lime',\n 'green',\n 'teal',\n 'cyan',\n 'blue',\n 'navy',\n 'purple',\n 'magenta',\n 'pink',\n 'brown',\n]);\n\ntype Supports = ((value: string) => boolean) | null;\n\nfunction browserSupports(): Supports {\n return typeof CSS !== 'undefined' && typeof CSS.supports === 'function'\n ? (value) => CSS.supports('color', value)\n : null;\n}\n\n/** Whether `value` is a CSS color — the browser's answer where it has `CSS.supports`, a small parser's otherwise. */\nexport function parsesAsColor(value: string, supports: Supports = browserSupports()): boolean {\n const v = value.trim();\n // `CSS.supports` accepts any `var()` for any property.\n if (!v || v.includes('var(')) return false;\n if (supports) return supports(v);\n return HEX.test(v) || COLOR_FUNCTION.test(v) || KEYWORDS.has(v.toLowerCase());\n}\n\nfunction hexOf(v: string): string | null {\n if (HEX.test(v)) {\n const digits = v.slice(1).toLowerCase();\n return `#${digits.length <= 4 ? [...digits.slice(0, 3)].map((d) => d + d).join('') : digits.slice(0, 6)}`;\n }\n const rgb = RGB.exec(v);\n return rgb\n ? `#${rgb\n .slice(1, 4)\n .map((n) => Math.min(255, Number(n)).toString(16).padStart(2, '0'))\n .join('')}`\n : null;\n}\n\nlet paint: CanvasRenderingContext2D | null | undefined;\n\n/** The browser's serialization of a color, through a canvas fill style; null where it has none or rejects `value`. */\nfunction serialized(value: string): string | null {\n if (paint === undefined) {\n try {\n paint = document.createElement('canvas').getContext('2d');\n } catch {\n paint = null;\n }\n }\n if (!paint) return null;\n // A rejected value leaves the previous fill style, so two different ones tell a rejection apart.\n paint.fillStyle = '#000000';\n paint.fillStyle = value;\n const onBlack = String(paint.fillStyle);\n paint.fillStyle = '#ffffff';\n paint.fillStyle = value;\n return onBlack === String(paint.fillStyle) ? onBlack : null;\n}\n\n/** `value` as the `#rrggbb` a color input takes, alpha dropped; null when it cannot be converted. */\nexport function toHex(value: string): string | null {\n const v = value.trim();\n const direct = hexOf(v);\n if (direct) return direct;\n const browser = typeof document === 'undefined' ? null : serialized(v);\n return browser && browser !== v ? hexOf(browser) : null;\n}\n",".panel {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.section {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.section + .section {\n border-top: var(--wzl-border-w) solid var(--wzl-line-subtle);\n}\n\n.sectionHead {\n padding-block: var(--wzl-space-xs);\n color: var(--wzl-fg-muted);\n font-family: var(--wzl-font-display);\n font-size: var(--wzl-font-size-sm);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.sectionBody {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-sm);\n padding-block-end: var(--wzl-space-sm);\n}\n\n.row,\n.family {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.name {\n overflow: hidden;\n color: var(--wzl-fg-muted);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.edit {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-xs);\n min-width: 0;\n}\n\n.field {\n --wzl-font-ui: var(--wzl-font-mono);\n flex: 1;\n min-width: 0;\n}\n\n.number {\n flex: 1;\n min-width: 0;\n}\n\n.unit {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-sm);\n}\n\n/* Padding inflates a native color input past its box in Chrome. */\n.swatchInput {\n box-sizing: border-box;\n flex-shrink: 0;\n width: 18px;\n height: 14px;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: var(--wzl-radius-sm);\n cursor: pointer;\n}\n\n.chip {\n flex-shrink: 0;\n width: 18px;\n height: 14px;\n background: var(--token-color);\n border-radius: var(--wzl-radius-sm);\n box-shadow: inset 0 0 0 1px var(--wzl-line);\n}\n\n.curve {\n flex-shrink: 0;\n width: 24px;\n /* Square easing-curve artwork: not-a-control */\n height: 24px;\n color: var(--wzl-fg);\n}\n\n.strip {\n display: flex;\n height: var(--wzl-control-h);\n overflow: hidden;\n border: var(--wzl-border-w) solid var(--wzl-line);\n border-radius: var(--wzl-radius-sm);\n}\n\n.swatch {\n flex: 1 1 0;\n min-width: 0;\n height: 100%;\n padding: 0;\n background: var(--token-color);\n border: 0;\n border-radius: 0;\n cursor: pointer;\n}\n\n.swatch[data-overridden] {\n box-shadow: inset 0 -3px 0 var(--wzl-accent);\n}\n\n.swatch[aria-pressed='true'],\n.swatch:focus-visible {\n position: relative;\n z-index: 1;\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n/* A group of sizes: its name over a grid of steps, each labeled by what its name adds. */\n.scale {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.scaleHead {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-xs);\n min-width: 0;\n}\n\n.steps {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(4rem, 1fr));\n gap: var(--wzl-space-1) var(--wzl-space-xs);\n}\n\n.rule {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-xs) var(--wzl-space-sm);\n min-width: 0;\n}\n\n.ruleLabel {\n color: var(--wzl-fg-subtle);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-2xs);\n}\n\n.rule .number {\n flex: 0 1 5ch;\n text-align: end;\n}\n\n.step {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.stepLabel {\n overflow: hidden;\n text-align: end;\n color: var(--wzl-fg-subtle);\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-2xs);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.step[data-overridden] .stepLabel {\n color: var(--wzl-accent-fg);\n}\n\n.stepEdit {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-1);\n min-width: 0;\n}\n\n.step > .stepEdit + .stepEdit {\n margin-block-start: var(--wzl-space-1);\n}\n\n.stepEdit .number {\n text-align: end;\n}\n\n/* Tight: a token to a line, with the names on a fixed rail so the values read\n down the panel as a column. A stacked row spends its height on the name and\n lets the field take the whole width, which a set of ninety cannot afford. */\n.tight .sectionBody {\n gap: var(--wzl-space-1);\n padding-block-end: var(--wzl-space-xs);\n}\n\n.tight .row {\n flex-direction: row;\n align-items: center;\n gap: var(--wzl-space-xs);\n}\n\n.tight .row > .name {\n flex: 0 0 11rem;\n}\n\n.tight .edit {\n flex: 1 1 auto;\n}\n\n.tight .field,\n.tight .number {\n flex: 0 1 16rem;\n}\n\n.tight .scale {\n display: grid;\n grid-template-columns: 11rem minmax(0, 1fr);\n align-items: start;\n column-gap: var(--wzl-space-xs);\n}\n\n/* Grid rather than a row, so a picked swatch's editor still spans the full width. */\n.tight .family {\n display: grid;\n grid-template-columns: 11rem minmax(0, 1fr);\n align-items: center;\n column-gap: var(--wzl-space-xs);\n row-gap: var(--wzl-space-1);\n}\n\n.tight .family > .row {\n grid-column: 1 / -1;\n}\n\n.tight .strip {\n height: 16px;\n}\n\n.tight .curve {\n width: 16px;\n height: 16px;\n}\n","import { parsesAsColor } from './color';\n\n/** A design token as `TokenPanel` edits it. */\nexport interface TokenEntry {\n /** The custom property, e.g. `--wzl-gray-50`. */\n name: string;\n /** A DTCG type name. A type the panel has no control for edits as text. */\n type: string;\n /** Tokens sharing a group sit together; a color group large enough draws as one row of swatches. */\n group: string;\n value: string;\n /** Whether `value` overrides the token's own, which offers Reset. */\n overridden?: boolean;\n description?: string;\n}\n\n/** How a scale's steps follow from its base: one multiplier per step, a constant ratio, or a constant step. */\nexport type TokenScaleRule =\n | { kind: 'factors'; factors: readonly number[] }\n | { kind: 'ratio'; ratio: number }\n | { kind: 'step'; step: number };\n\n/** A group whose steps are generated from a base, so the panel edits the base and the rule rather than each step. */\nexport interface TokenScale {\n /** The generated tokens, smallest first. Anything else in the group draws as an ordinary step. */\n tokens: readonly string[];\n base: number;\n rule: TokenScaleRule;\n}\n\nconst round2 = (n: number) => Math.round(n * 100) / 100;\n\n/**\n * The same scale under another rule, fitted to the amounts its steps have now.\n * A ratio or step counts from the first step, so switching to one moves the\n * base there.\n */\nexport function refitScale(scale: TokenScale, kind: TokenScaleRule['kind'], amounts: readonly number[]): TokenScale {\n const first = amounts[0] ?? scale.base;\n const last = amounts.at(-1) ?? first;\n const spans = Math.max(1, amounts.length - 1);\n switch (kind) {\n case 'factors':\n return { ...scale, rule: { kind, factors: amounts.map((a) => (scale.base ? round2(a / scale.base) : 1)) } };\n case 'ratio':\n return { ...scale, base: first, rule: { kind, ratio: first > 0 ? round2((last / first) ** (1 / spans)) : 1 } };\n case 'step':\n return { ...scale, base: first, rule: { kind, step: round2((last - first) / spans) } };\n }\n}\n\n/** A section of the token panel; `tokenCategory` files each token under one. */\nexport type TokenCategory ='color' | 'type' | 'size' | 'motion' | 'depth' | 'other';\n\n/** The panel's sections, in the order it draws them. */\nexport const TOKEN_CATEGORIES: readonly { id: TokenCategory; title: string }[] = [\n { id: 'color', title: 'Color' },\n { id: 'type', title: 'Type' },\n { id: 'size', title: 'Size' },\n { id: 'motion', title: 'Motion' },\n { id: 'depth', title: 'Depth' },\n { id: 'other', title: 'Other' },\n];\n\nconst TYPE_SCALE = /^(?:font|tracking|leading|letter|line-height)/;\n\n/** The section a token is filed under: by its type, and for a bare dimension or number by its group. */\nexport function tokenCategory(token: TokenEntry): TokenCategory {\n switch (token.type) {\n case 'color':\n return 'color';\n case 'fontFamily':\n case 'fontWeight':\n return 'type';\n case 'duration':\n case 'cubicBezier':\n return 'motion';\n case 'shadow':\n case 'gradient':\n return 'depth';\n case 'dimension':\n case 'number':\n if (TYPE_SCALE.test(token.group)) return 'type';\n if (token.type === 'number' && (token.group === 'z' || token.group === 'z-index')) return 'depth';\n return 'size';\n default:\n return 'other';\n }\n}\n\nconst AMOUNT = String.raw`-?(?:\\d+\\.?\\d*|\\.\\d+)`;\nconst DIMENSION = new RegExp(\n `^${AMOUNT}(?:px|rem|em|%|ch|ex|lh|rlh|vh|vw|vmin|vmax|svh|lvh|dvh|cqw|cqh|pt|pc|cm|mm|in|q)$`,\n 'i',\n);\nconst DURATION = new RegExp(`^${AMOUNT}m?s$`);\nconst NUMBER = new RegExp(`^${AMOUNT}$`);\nconst LENGTH = new RegExp(`^${AMOUNT}(?:px|rem|em)?$`);\nconst BEZIER = new RegExp(`^cubic-bezier\\\\(\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*,\\\\s*(${AMOUNT})\\\\s*\\\\)$`, 'i');\nconst GRADIENT = /^(?:repeating-)?(?:linear|radial|conic)-gradient\\(/i;\n/** Commas outside parentheses: a shadow's layers, not a color function's arguments. */\nconst LAYERS = /,(?![^(]*\\))/;\nconst PARTS = /[a-z-]+\\([^)]*\\)|\\S+/gi;\n\nfunction isShadow(value: string): boolean {\n return value.split(LAYERS).every((layer) => {\n const parts = layer.trim().replace(/^inset\\s+/i, '').match(PARTS) ?? [];\n const lengths = parts.filter((part) => LENGTH.test(part));\n const rest = parts.filter((part) => !LENGTH.test(part));\n return lengths.length >= 2 && lengths.length <= 4 && rest.length <= 1 && rest.every((part) => parsesAsColor(part));\n });\n}\n\n/** A DTCG type read off the shape of a value, for a token that arrives without one. `'string'` when nothing fits. */\nexport function inferTokenType(value: string): string {\n const v = value.trim();\n if (!v) return 'string';\n if (DURATION.test(v)) return 'duration';\n if (DIMENSION.test(v)) return 'dimension';\n if (NUMBER.test(v)) return 'number';\n if (BEZIER.test(v)) return 'cubicBezier';\n if (GRADIENT.test(v)) return 'gradient';\n if (parsesAsColor(v)) return 'color';\n if (isShadow(v)) return 'shadow';\n return 'string';\n}\n\n/** A number and its unit, or null for a value that is not one. */\nexport function splitUnit(value: string): { amount: number; unit: string } | null {\n const match = new RegExp(`^(${AMOUNT})([a-z%]*)$`, 'i').exec(value.trim());\n return match ? { amount: Number(match[1]), unit: match[2] ?? '' } : null;\n}\n\n/** The four control points of a `cubic-bezier()`, or null for any other easing. */\nexport function bezierPoints(value: string): readonly [number, number, number, number] | null {\n const match = BEZIER.exec(value.trim());\n if (!match) return null;\n const [x1, y1, x2, y2] = match.slice(1, 5).map(Number) as [number, number, number, number];\n return [x1, y1, x2, y2];\n}\n","import { type CSSProperties, memo, useCallback, useMemo, useState } from 'react';\nimport { Focusable } from 'react-aria-components';\nimport { Button } from '../Button';\nimport { DisclosureRow } from '../Disclosure';\nimport { Input } from '../Input';\nimport { NumberField } from '../NumberField';\nimport { Select } from '../Select';\nimport { ToggleBar, type ToggleBarItem } from '../ToggleBar';\nimport { Tooltip, TooltipTrigger } from '../Tooltip';\nimport { toHex } from './color';\nimport s from './TokenPanel.module.css';\nimport {\n bezierPoints,\n refitScale,\n splitUnit,\n TOKEN_CATEGORIES,\n type TokenCategory,\n type TokenEntry,\n type TokenScale,\n type TokenScaleRule,\n tokenCategory,\n} from './tokenTypes';\n\ntype OnChange = (name: string, value: string | null) => void;\n\n/** Props for `<TokenPanel>`. */\nexport interface TokenPanelProps {\n tokens: readonly TokenEntry[];\n /** A token's new value, or null to drop its override. Keep it stable: rows re-render only when it or their token changes. */\n onChange: OnChange;\n /** Sections held closed, by category. Omit to let the panel keep that state itself. */\n collapsed?: Readonly<Partial<Record<TokenCategory, boolean>>>;\n onCollapsedChange?: (category: TokenCategory, collapsed: boolean) => void;\n /** Groups generated from a base, by group name. Such a group edits its base and rule above its steps. */\n scales?: Readonly<Record<string, TokenScale>>;\n /** A scale's new base or rule. The panel does not regenerate the steps; the consumer does, through `onChange`. */\n onScaleChange?: (group: string, scale: TokenScale) => void;\n /** Files a token under a section. Defaults to `tokenCategory`. */\n categorize?: (token: TokenEntry) => TokenCategory;\n /** The fewest colors, or sizes, sharing a group that draw as one row of swatches or one grid of steps. Default 3. */\n familySize?: number;\n /**\n * Row layout. `tight` puts a token on one line — name, control, Reset — with the\n * names on a fixed rail so the values read down the panel as a column, and caps\n * the field rather than letting it span the panel. Default `normal` stacks the\n * control under its name.\n */\n density?: 'tight' | 'normal';\n className?: string;\n}\n\nconst WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];\nconst NUMBER_FORMAT = { maximumFractionDigits: 4, useGrouping: false } as const;\n\ntype FamilyKind = 'family' | 'scale';\ntype Item = { kind: 'row'; token: TokenEntry } | { kind: FamilyKind; group: string; tokens: TokenEntry[] };\n\nconst SCALAR = new Set(['dimension', 'duration', 'number']);\n\nfunction familyKindOf(token: TokenEntry): FamilyKind | null {\n if (token.type === 'color') return 'family';\n return SCALAR.has(token.type) && splitUnit(token.value) ? 'scale' : null;\n}\n\nfunction itemsOf(tokens: readonly TokenEntry[], familySize: number): Item[] {\n const counts = new Map<string, number>();\n for (const token of tokens) {\n const kind = familyKindOf(token);\n if (kind) counts.set(`${kind}:${token.group}`, (counts.get(`${kind}:${token.group}`) ?? 0) + 1);\n }\n const families = new Map<string, Extract<Item, { kind: FamilyKind }>>();\n const items: Item[] = [];\n for (const token of tokens) {\n const kind = familyKindOf(token);\n const key = `${kind}:${token.group}`;\n if (!kind || (counts.get(key) ?? 0) < familySize) {\n items.push({ kind: 'row', token });\n continue;\n }\n let family = families.get(key);\n if (!family) {\n family = { kind, group: token.group, tokens: [] };\n families.set(key, family);\n items.push(family);\n }\n family.tokens.push(token);\n }\n return items;\n}\n\n/** Each name's segments past those every name in the set shares; a name that is all shared keeps its last. */\nfunction stepLabels(names: readonly string[]): string[] {\n const split = names.map((name) => name.replace(/^--/, '').split('-'));\n let shared = 0;\n while (split.every((segments) => segments.length > shared && segments[shared] === split[0]?.[shared])) shared++;\n return split.map((segments) => segments.slice(shared).join('-') || (segments.at(-1) ?? ''));\n}\n\nfunction Curve({ points, label }: { points: readonly [number, number, number, number]; label: string }) {\n const [x1, y1, x2, y2] = points;\n // y is flipped so the curve rises, and the box grows to hold an overshoot.\n const top = Math.min(0, 1 - y1, 1 - y2);\n const bottom = Math.max(1, 1 - y1, 1 - y2);\n return (\n <svg className={s.curve} viewBox={`-0.1 ${top - 0.1} 1.2 ${bottom - top + 0.2}`} role=\"img\" aria-label={label}>\n <path d={`M0 1 C${x1} ${1 - y1} ${x2} ${1 - y2} 1 0`} fill=\"none\" stroke=\"currentColor\" strokeWidth={0.08} />\n </svg>\n );\n}\n\nfunction TokenControl({ token, set }: { token: TokenEntry; set: (value: string) => void }) {\n const { name, type, value } = token;\n const label = `${name} value`;\n const hex = useMemo(() => (type === 'color' ? toHex(value) : null), [type, value]);\n\n if (type === 'dimension' || type === 'duration' || type === 'number') {\n const split = splitUnit(value);\n if (split) {\n return (\n <>\n <NumberField\n className={s.number}\n aria-label={label}\n value={split.amount}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(amount) => {\n if (Number.isFinite(amount)) set(`${amount}${split.unit}`);\n }}\n />\n {split.unit ? <span className={s.unit}>{split.unit}</span> : null}\n </>\n );\n }\n }\n\n if (type === 'fontWeight') {\n const options = (WEIGHTS.includes(value) ? WEIGHTS : [...WEIGHTS, value]).map((weight) => ({\n value: weight,\n label: weight,\n }));\n return <Select aria-label={name} width=\"fit\" selectedKey={value} options={options} onSelectionChange={set} />;\n }\n\n const points = type === 'cubicBezier' ? bezierPoints(value) : null;\n return (\n <>\n {points ? <Curve points={points} label={`${name} curve`} /> : null}\n <Input\n className={s.field}\n aria-label={label}\n value={value}\n onChange={set}\n leadingAdornment={\n type !== 'color' ? undefined : hex ? (\n <input\n type=\"color\"\n className={s.swatchInput}\n aria-label={`${name} color`}\n value={hex}\n onChange={(event) => set(event.target.value)}\n />\n ) : (\n <span className={s.chip} style={{ '--token-color': value } as CSSProperties} aria-hidden=\"true\" />\n )\n }\n />\n </>\n );\n}\n\nconst TokenRow = memo(\n function TokenRow({ token, onChange }: { token: TokenEntry; onChange: OnChange }) {\n const set = useCallback((value: string) => onChange(token.name, value), [onChange, token.name]);\n return (\n <div className={s.row} role=\"group\" aria-label={token.name}>\n <span className={s.name} title={token.description || token.name}>\n {token.name}\n </span>\n <div className={s.edit}>\n <TokenControl token={token} set={set} />\n {token.overridden ? (\n <Button variant=\"ghost\" size=\"sm\" ariaLabel={`Reset ${token.name}`} onClick={() => onChange(token.name, null)}>\n Reset\n </Button>\n ) : null}\n </div>\n </div>\n );\n },\n // Consumers rebuild their entries each render; a row only has to redraw when what it shows changed.\n (a, b) =>\n a.onChange === b.onChange &&\n a.token.name === b.token.name &&\n a.token.type === b.token.type &&\n a.token.value === b.token.value &&\n a.token.overridden === b.token.overridden &&\n a.token.description === b.token.description,\n);\n\nfunction Family({ group, tokens, onChange }: { group: string; tokens: readonly TokenEntry[]; onChange: OnChange }) {\n const [picked, setPicked] = useState<string | null>(null);\n const token = tokens.find((t) => t.name === picked) ?? null;\n return (\n <div className={s.family} role=\"group\" aria-label={group}>\n <span className={s.name}>{group}</span>\n <div className={s.strip}>\n {tokens.map((t) => (\n <TooltipTrigger key={t.name} delay={0}>\n <Focusable>\n <button\n type=\"button\"\n className={s.swatch}\n style={{ '--token-color': t.value } as CSSProperties}\n aria-label={t.name}\n aria-pressed={t.name === picked}\n data-overridden={t.overridden ? '' : undefined}\n onClick={() => setPicked((current) => (current === t.name ? null : t.name))}\n />\n </Focusable>\n <Tooltip>{t.name}</Tooltip>\n </TooltipTrigger>\n ))}\n </div>\n {token ? <TokenRow token={token} onChange={onChange} /> : null}\n </div>\n );\n}\n\nfunction ScaleStep({\n token,\n label,\n showUnit,\n factor,\n onChange,\n onFactorChange,\n}: {\n token: TokenEntry;\n label: string;\n showUnit: boolean;\n factor?: number;\n onChange: OnChange;\n onFactorChange?: (factor: number) => void;\n}) {\n const split = splitUnit(token.value);\n if (!split) return null;\n return (\n <div className={s.step} title={token.description || token.name} data-overridden={token.overridden ? '' : undefined}>\n <span className={s.stepLabel}>{label}</span>\n <span className={s.stepEdit}>\n <NumberField\n className={s.number}\n aria-label={`${token.name} value`}\n value={split.amount}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(amount) => {\n if (Number.isFinite(amount)) onChange(token.name, `${amount}${split.unit}`);\n }}\n />\n {showUnit && split.unit ? <span className={s.unit}>{split.unit}</span> : null}\n </span>\n {factor !== undefined && onFactorChange ? (\n <span className={s.stepEdit}>\n <span className={s.unit}>×</span>\n <NumberField\n className={s.number}\n aria-label={`${token.name} factor`}\n value={factor}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(next) => {\n if (Number.isFinite(next)) onFactorChange(next);\n }}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\nconst RULES: readonly ToggleBarItem<TokenScaleRule['kind']>[] = [\n { value: 'factors', label: 'each', ariaLabel: 'factors' },\n { value: 'ratio', label: 'ratio' },\n { value: 'step', label: 'step' },\n];\n\nfunction ScaleRuleControls({\n group,\n scale,\n unit,\n amounts,\n onScaleChange,\n}: {\n group: string;\n scale: TokenScale;\n unit: string;\n amounts: readonly number[];\n onScaleChange: (scale: TokenScale) => void;\n}) {\n const { rule } = scale;\n const param =\n rule.kind === 'ratio'\n ? { key: 'ratio' as const, value: rule.ratio }\n : rule.kind === 'step'\n ? { key: 'step' as const, value: rule.step }\n : null;\n return (\n <div className={s.rule}>\n <span className={s.stepEdit}>\n <span className={s.ruleLabel}>base</span>\n <NumberField\n className={s.number}\n aria-label={`${group} base`}\n value={scale.base}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(base) => {\n if (Number.isFinite(base)) onScaleChange({ ...scale, base });\n }}\n />\n {unit ? <span className={s.unit}>{unit}</span> : null}\n </span>\n <ToggleBar\n ariaLabel={`${group} rule`}\n size=\"sm\"\n items={RULES}\n value={rule.kind}\n onChange={(kind) => {\n if (kind && kind !== rule.kind) onScaleChange(refitScale(scale, kind, amounts));\n }}\n />\n {param ? (\n <span className={s.stepEdit}>\n {param.key === 'ratio' ? <span className={s.unit}>×</span> : <span className={s.unit}>+</span>}\n <NumberField\n className={s.number}\n aria-label={`${group} ${param.key}`}\n value={param.value}\n hideSteppers\n formatOptions={NUMBER_FORMAT}\n onChange={(value) => {\n if (Number.isFinite(value)) onScaleChange({ ...scale, rule: { kind: param.key, [param.key]: value } as TokenScaleRule });\n }}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\nfunction Scale({\n group,\n tokens,\n generator,\n onChange,\n onScaleChange,\n}: {\n group: string;\n tokens: readonly TokenEntry[];\n generator?: TokenScale;\n onChange: OnChange;\n onScaleChange?: (group: string, scale: TokenScale) => void;\n}) {\n const labels = useMemo(() => stepLabels(tokens.map((t) => t.name)), [tokens]);\n const units = new Set(tokens.map((t) => splitUnit(t.value)?.unit ?? ''));\n const unit = units.size === 1 ? [...units][0] : null;\n const overridden = tokens.filter((t) => t.overridden);\n return (\n <div className={s.scale} role=\"group\" aria-label={group}>\n <span className={s.scaleHead}>\n <span className={s.name}>{group}</span>\n {unit ? <span className={s.unit}>{unit}</span> : null}\n {overridden.length > 0 ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n ariaLabel={`Reset ${group}`}\n onClick={() => {\n for (const t of overridden) onChange(t.name, null);\n }}\n >\n Reset\n </Button>\n ) : null}\n </span>\n {generator && onScaleChange ? (\n <ScaleRuleControls\n group={group}\n scale={generator}\n unit={unit ?? ''}\n amounts={generator.tokens.map(\n (name) => splitUnit(tokens.find((t) => t.name === name)?.value ?? '')?.amount ?? generator.base,\n )}\n onScaleChange={(next) => onScaleChange(group, next)}\n />\n ) : null}\n <div className={s.steps}>\n {tokens.map((t, i) => {\n const rule = generator?.rule;\n const at = generator ? generator.tokens.indexOf(t.name) : -1;\n const factor = rule?.kind === 'factors' && at >= 0 ? rule.factors[at] : undefined;\n return (\n <ScaleStep\n key={t.name}\n token={t}\n label={labels[i] ?? t.name}\n showUnit={unit === null}\n factor={factor}\n onChange={onChange}\n onFactorChange={\n generator && onScaleChange && rule?.kind === 'factors'\n ? (next) =>\n onScaleChange(group, {\n ...generator,\n rule: { kind: 'factors', factors: rule.factors.map((f, j) => (j === at ? next : f)) },\n })\n : undefined\n }\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction Section({\n title,\n open,\n onToggle,\n tokens,\n familySize,\n scales,\n onChange,\n onScaleChange,\n}: {\n title: string;\n open: boolean;\n onToggle: () => void;\n tokens: readonly TokenEntry[];\n familySize: number;\n scales?: Readonly<Record<string, TokenScale>>;\n onChange: OnChange;\n onScaleChange?: (group: string, scale: TokenScale) => void;\n}) {\n const items = useMemo(() => itemsOf(tokens, familySize), [tokens, familySize]);\n return (\n <section className={s.section} aria-label={title}>\n <DisclosureRow className={s.sectionHead} open={open} onToggle={onToggle} label={title}>\n <span aria-hidden=\"true\">{title}</span>\n </DisclosureRow>\n {open ? (\n <div className={s.sectionBody}>\n {items.map((item) =>\n item.kind === 'row' ? (\n <TokenRow key={item.token.name} token={item.token} onChange={onChange} />\n ) : item.kind === 'scale' ? (\n <Scale\n key={`scale:${item.group}`}\n group={item.group}\n tokens={item.tokens}\n generator={scales?.[item.group]}\n onChange={onChange}\n onScaleChange={onScaleChange}\n />\n ) : (\n <Family key={`family:${item.group}`} group={item.group} tokens={item.tokens} onChange={onChange} />\n ),\n )}\n </div>\n ) : null}\n </section>\n );\n}\n\n/**\n * Edits a set of design tokens by type: collapsible sections by category, a\n * color group drawn as one row of swatches sized to fit, a group of sizes drawn\n * as one grid of numbers labeled by step — with its base and rule above it when\n * `scales` says how it is generated — and a control for each\n * type — a number with its unit for dimensions and durations, the nine weights\n * for a font weight, a curve beside a `cubic-bezier()`, a swatch beside a color,\n * and text for everything else.\n */\nexport function TokenPanel({\n tokens,\n onChange,\n collapsed,\n onCollapsedChange,\n scales,\n onScaleChange,\n categorize = tokenCategory,\n familySize = 3,\n density = 'normal',\n className,\n}: TokenPanelProps) {\n const [ownCollapsed, setOwnCollapsed] = useState<Partial<Record<TokenCategory, boolean>>>({});\n const closed = collapsed ?? ownCollapsed;\n const byCategory = useMemo(() => {\n const sections = new Map<TokenCategory, TokenEntry[]>();\n for (const token of tokens) {\n const category = categorize(token);\n sections.set(category, [...(sections.get(category) ?? []), token]);\n }\n return sections;\n }, [tokens, categorize]);\n\n return (\n <div className={[s.panel, density === 'tight' && s.tight, className].filter(Boolean).join(' ')}>\n {TOKEN_CATEGORIES.map(({ id, title }) => {\n const inSection = byCategory.get(id);\n if (!inSection) return null;\n const open = !closed[id];\n return (\n <Section\n key={id}\n title={title}\n open={open}\n onToggle={() => {\n if (collapsed === undefined) setOwnCollapsed((prev) => ({ ...prev, [id]: open }));\n onCollapsedChange?.(id, open);\n }}\n tokens={inSection}\n familySize={familySize}\n scales={scales}\n onChange={onChange}\n onScaleChange={onScaleChange}\n />\n );\n })}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { i as e, n as t, r as n, t as r } from "./FitLabel-BzZGkWfL.js";
2
+ import { a as i, c as a, d as o, u as s } from "./model-qQj8Ny9w.js";
3
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
4
+ import { useRef as d } from "react";
5
+ var f = {
6
+ root: "_root_1h7p0_13",
7
+ label: "_label_1h7p0_25",
8
+ controls: "_controls_1h7p0_6",
9
+ cell: "_cell_1h7p0_68",
10
+ cellLabel: "_cellLabel_1h7p0_74"
11
+ };
12
+ //#endregion
13
+ //#region src/components/ToolOptionsBar/ToolOptionsBar.tsx
14
+ function p(n) {
15
+ let { label: r, schema: i, values: a, onChange: o, mixed: s, renderers: c, children: p, className: g } = n, _ = [f.root, g].filter(Boolean).join(" "), v = d(null), y = e(v);
16
+ return /* @__PURE__ */ u("div", {
17
+ className: _,
18
+ role: "toolbar",
19
+ "aria-label": r,
20
+ children: [r !== void 0 && /* @__PURE__ */ l("span", {
21
+ className: f.label,
22
+ children: r
23
+ }), /* @__PURE__ */ l("div", {
24
+ className: f.controls,
25
+ ref: v,
26
+ children: /* @__PURE__ */ u(t, {
27
+ value: y,
28
+ children: [i !== void 0 && m(i).map((e) => /* @__PURE__ */ l(h, {
29
+ row: e,
30
+ values: a,
31
+ mixed: s,
32
+ renderers: c,
33
+ onChange: o
34
+ }, e.leaves[0].path)), p]
35
+ })
36
+ })]
37
+ });
38
+ }
39
+ function m(e) {
40
+ let t = [], n = (e, r) => {
41
+ for (let [a, o] of Object.entries(e.children)) {
42
+ let e = r === "" ? a : `${r}.${a}`;
43
+ i(o) ? n(o, e) : o.hidden !== !0 && t.push({
44
+ path: e,
45
+ leaf: o
46
+ });
47
+ }
48
+ };
49
+ return n(e, ""), a(t);
50
+ }
51
+ function h({ row: e, values: t, mixed: i, renderers: a, onChange: s }) {
52
+ let d = e.leaves.map((e) => _(e, e.leaf.name, t, i, a, s));
53
+ return /* @__PURE__ */ l(c, { children: o(d, a).map((e) => /* @__PURE__ */ u("span", {
54
+ className: f.cell,
55
+ children: [g(e.leaf) && /* @__PURE__ */ l("span", {
56
+ className: f.cellLabel,
57
+ "aria-hidden": "true",
58
+ children: /* @__PURE__ */ l(r, { forms: n(e.leaf.name, e.leaf.short) })
59
+ }), e.content]
60
+ }, e.key)) });
61
+ }
62
+ function g(e) {
63
+ return e.kind === "number" || e.kind === "string";
64
+ }
65
+ function _(e, t, n, r, i, a) {
66
+ let { path: o, leaf: c } = e, l = r?.has(o) === !0, u = {
67
+ path: o,
68
+ pref: c,
69
+ value: l ? void 0 : n?.[o],
70
+ mixed: l,
71
+ unset: !l && n?.[o] === void 0,
72
+ each: l ? [] : [n?.[o]],
73
+ setValue: (e) => a?.(o, e),
74
+ update: (e) => a?.(o, e(l ? void 0 : n?.[o])),
75
+ valueAt: (e) => ({
76
+ value: n?.[e],
77
+ mixed: r?.has(e) === !0
78
+ })
79
+ };
80
+ return {
81
+ key: o,
82
+ leaf: c,
83
+ ctx: u,
84
+ ariaLabel: t,
85
+ render: () => {
86
+ let e = i?.[o] ?? i?.[c.kind];
87
+ return e ? e(u) : s(u, t, i, o);
88
+ }
89
+ };
90
+ }
91
+ //#endregion
92
+ export { p as t };
93
+
94
+ //# sourceMappingURL=ToolOptionsBar-wTPJFfOn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolOptionsBar-wTPJFfOn.js","names":["s","_Fragment","useFitScope","FitScope","labelForms","FitLabel","isGroup","pairRows","renderCells","renderBuiltin","ToolOptionsBar_module_default","ToolOptionsBar","props","cls","className","controls","useRef","fit","label","schema","barRows","BarRow","row","children","leaves","collect","key","child","group","path","prefix","cells","barCell","panelLeaf","values","mixed","renderers","onChange","Fragment","needsLabel","cell","leaf","isMixed","ctx","v","fn","p","custom","ariaLabel"],"sources":["../../src/components/ToolOptionsBar/ToolOptionsBar.module.css","../../src/components/ToolOptionsBar/ToolOptionsBar.tsx"],"sourcesContent":["/* Horizontal strip reserved above the workspace for contextual tool\n options. Fixed height so mounting/unmounting content never resizes\n the workspace beneath it — that's the whole reason this row exists\n as permanent chrome rather than an on-demand overlay.\n\n Overflow: when controls exceed the available width, `.controls`\n scrolls horizontally rather than wrapping (which would grow the row\n and defeat the fixed-height guarantee above) or clipping (which\n would hide controls with no way to reach them). A flyout/long-press\n affordance was considered and rejected — grouped, directly visible\n layouts are preferred in this repo. */\n\n.root {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-4);\n height: var(--wzl-tb-height);\n padding: 0 var(--wzl-space-4);\n background: var(--wzl-surface);\n border-bottom: 1px solid var(--wzl-border);\n color: var(--wzl-fg);\n overflow: hidden;\n}\n\n.label {\n flex: 0 0 auto;\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n.controls {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-3);\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n}\n\n/* Firefox gets a thin scrollbar for free via `scrollbar-width` above.\n * Chromium/WebKit need it spelled out — on a classic (non-overlay)\n * scrollbar theme (default on Windows Chrome/Edge), an unstyled\n * horizontal scrollbar is ~15-17px tall and renders *inside* this box,\n * clipping/off-centering the row's controls. That would reintroduce the\n * exact height instability the scroll-over-wrap overflow choice above\n * exists to avoid — just at the row's inner edge instead of its outer\n * one. Pin it thin and out of the way instead. */\n.controls::-webkit-scrollbar {\n height: 4px;\n}\n.controls::-webkit-scrollbar-track {\n background: transparent;\n}\n.controls::-webkit-scrollbar-thumb {\n background: var(--wzl-border);\n border-radius: var(--wzl-radius-sm);\n}\n\n/* A schema-drawn control sits on the line as-is; the cell exists only to keep\n it from being squeezed by the row's flex context. */\n.cell {\n display: flex;\n align-items: center;\n flex: none;\n}\n\n.cellLabel {\n flex: none;\n margin-right: var(--wzl-space-2);\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n/* Fields are read beside their label on one line, so they carry only the\n digits they need rather than the panel's column width. */\n.controls {\n --wzl-number-field-width: 5ch;\n}\n\n/* The strip decides how much room a control gets, because its budget is one\n line rather than a column: a field carries the digits it needs and an\n opacity track stops short of pushing its neighbours off the end. Both are\n the panel's widths otherwise, which are sized for a two-column grid. */\n.cell input[type='text'] {\n inline-size: var(--wzl-number-field-width, 5ch);\n}\n\n.cell input[type='range'] {\n inline-size: 64px;\n flex: none;\n}\n","import { useRef, type ReactNode } from 'react';\nimport type { ToolPrefGroup, ToolPrefLeaf } from '@weasel-js/core';\nimport {\n renderBuiltin,\n renderCells,\n type LeafCell,\n type PropertyRenderContext,\n type PropertyRenderer,\n} from '../SelectionPanel/renderLeaf';\nimport { isGroup, pairRows, type PanelLeaf, type PanelRow } from '../SelectionPanel/model';\nimport { FitLabel, FitScope, labelForms, useFitScope } from '../FitLabel/FitLabel';\nimport s from './ToolOptionsBar.module.css';\n\n/** Props for {@link ToolOptionsBar}. */\nexport interface ToolOptionsBarProps {\n /**\n * Context label for the row — e.g. the active tool's name. Rendered\n * before the children and doubles as the toolbar's `aria-label`. Omit\n * it and the row still renders (it's a permanently reserved slot), just\n * without an accessible name.\n *\n * Using `label` for both the visible text and `aria-label` means a\n * screen reader announces it twice when landing on the toolbar (\"Text,\n * toolbar\", then \"Text\" again when browsing into the visible span).\n * `aria-labelledby` would avoid the echo at the cost of id plumbing and\n * an awkward no-`id`-to-point-at case when `label` is omitted. The\n * double-announcement is common enough for labeled landmark regions\n * that it's left as-is — considered, not missed.\n */\n label?: string;\n /**\n * The active tool's options. Leaves draw through the same leaf → control\n * mapping `SelectionPanel` uses, so a kind gets its control decided in one\n * place; groups organize without drawing, since the bar is one line.\n */\n schema?: ToolPrefGroup;\n /** Each leaf's value, keyed by dotted path. A path with no entry is unset. */\n values?: Readonly<Record<string, unknown>>;\n /** A leaf edit, as the dotted path it was declared at and its new value. */\n onChange?: (path: string, value: unknown) => void;\n /** Paths whose sources disagree — drawn as the control's mixed state. */\n mixed?: ReadonlySet<string>;\n /** Control overrides, by dotted path or by leaf kind, as the panel takes. */\n renderers?: Record<string, PropertyRenderer>;\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * Horizontal strip reserved above the workspace for contextual tool options.\n * Given a `schema` it draws the active tool's options itself; the children\n * slot stays open for a tenant that is not a tool's options at all, such as\n * loupe controls.\n *\n * The row always renders, even empty, because the app reserves its height\n * permanently rather than mounting it on demand — mounting mid-edit would\n * resize the workspace under a canvas that's sized to the page.\n *\n * `role=\"toolbar\"` without roving tabindex: the ARIA authoring practices\n * expect arrow-key roving focus across a toolbar's items, but a bar of\n * compound controls (`NumberField`, `Select`, `ColorField`) must leave the\n * arrow keys to them — they edit their own value with them. That is true of\n * schema-drawn controls as much as of arbitrary children, so the bar keeps\n * plain DOM tab order and `useRovingTabIndex` documents this as its opt-out.\n */\nexport function ToolOptionsBar(props: ToolOptionsBarProps) {\n const { label, schema, values, onChange, mixed, renderers, children, className } = props;\n const cls = [s.root, className].filter(Boolean).join(' ');\n // Every label on the line shortens together before the strip scrolls.\n const controls = useRef<HTMLDivElement>(null);\n const fit = useFitScope(controls);\n return (\n <div className={cls} role=\"toolbar\" aria-label={label}>\n {label !== undefined && <span className={s.label}>{label}</span>}\n <div className={s.controls} ref={controls}>\n <FitScope value={fit}>\n {schema !== undefined &&\n barRows(schema).map((row) => (\n <BarRow\n key={row.leaves[0]!.path}\n row={row}\n values={values}\n mixed={mixed}\n renderers={renderers}\n onChange={onChange}\n />\n ))}\n {children}\n </FitScope>\n </div>\n </div>\n );\n}\n\n/**\n * The schema's visible leaves as rows, addressed by dotted path. Groups are\n * organizational here — a bar is one line, so a nested group contributes its\n * leaves and no chrome — but its path segment still names them, so a leaf\n * reads back at the path the tool declared it at.\n */\nfunction barRows(schema: ToolPrefGroup): PanelRow[] {\n const leaves: PanelLeaf[] = [];\n const collect = (group: ToolPrefGroup, prefix: string): void => {\n for (const [key, child] of Object.entries(group.children)) {\n const path = prefix === '' ? key : `${prefix}.${key}`;\n if (isGroup(child)) collect(child, path);\n else if (child.hidden !== true) leaves.push({ path, leaf: child });\n }\n };\n collect(schema, '');\n return pairRows(leaves);\n}\n\n/** One row of the bar: a single control, or a run of flags as one bar. */\nfunction BarRow({\n row,\n values,\n mixed,\n renderers,\n onChange,\n}: {\n row: PanelRow;\n values: Readonly<Record<string, unknown>> | undefined;\n mixed: ReadonlySet<string> | undefined;\n renderers: Record<string, PropertyRenderer> | undefined;\n onChange: ((path: string, value: unknown) => void) | undefined;\n}) {\n // The bar draws no row label, so a control carries its own name rather than\n // the panel's qualified \"<pair> <leaf>\" — the run's bar carries the pair.\n const cells = row.leaves.map((panelLeaf) =>\n barCell(panelLeaf, panelLeaf.leaf.name, values, mixed, renderers, onChange),\n );\n return (\n <>\n {renderCells(cells, renderers).map((cell) => (\n <span key={cell.key} className={s.cell}>\n {needsLabel(cell.leaf) && (\n <span className={s.cellLabel} aria-hidden=\"true\">\n <FitLabel forms={labelForms(cell.leaf.name, cell.leaf.short)} />\n </span>\n )}\n {cell.content}\n </span>\n ))}\n </>\n );\n}\n\n/**\n * Whether a control needs telling from its neighbours in words.\n *\n * Only a bare value box does: a number or a string is a box of characters,\n * and two of them side by side are indistinguishable. Everything else shows\n * what it is — a swatch is a color, a font picker names the family, a flag\n * run and a segmented control label their own segments — so a word in front\n * would repeat what the control already says. `name` stays the accessible\n * name either way, so this costs a screen reader nothing.\n */\nfunction needsLabel(leaf: ToolPrefLeaf): boolean {\n return leaf.kind === 'number' || leaf.kind === 'string';\n}\n\nfunction barCell(\n panelLeaf: PanelLeaf,\n ariaLabel: string,\n values: Readonly<Record<string, unknown>> | undefined,\n mixed: ReadonlySet<string> | undefined,\n renderers: Record<string, PropertyRenderer> | undefined,\n onChange: ((path: string, value: unknown) => void) | undefined,\n): LeafCell {\n const { path, leaf } = panelLeaf;\n const isMixed = mixed?.has(path) === true;\n const ctx: PropertyRenderContext = {\n path,\n pref: leaf,\n value: isMixed ? undefined : values?.[path],\n mixed: isMixed,\n unset: !isMixed && values?.[path] === undefined,\n each: isMixed ? [] : [values?.[path]],\n setValue: (v) => onChange?.(path, v),\n // One set of values, so there is one prior value to derive from.\n update: (fn) => onChange?.(path, fn(isMixed ? undefined : values?.[path])),\n valueAt: (p) => ({ value: values?.[p], mixed: mixed?.has(p) === true }),\n };\n return {\n key: path,\n leaf: leaf as ToolPrefLeaf,\n ctx,\n ariaLabel,\n render: () => {\n const custom = renderers?.[path] ?? renderers?.[leaf.kind];\n return custom ? custom(ctx) : renderBuiltin(ctx, ariaLabel, renderers, path);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as e } from "./Disclosure-Ch2KxYuB.js";
1
+ import { n as e } from "./Disclosure-CpWt87nO.js";
2
2
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
3
  import { forwardRef as r, useId as i, useMemo as a, useRef as o, useState as s } from "react";
4
4
  var c = {
@@ -200,4 +200,4 @@ function h(e, t, n) {
200
200
  //#endregion
201
201
  export { d as n, f as r, u as t };
202
202
 
203
- //# sourceMappingURL=Tree-Cc8lIzgM.js.map
203
+ //# sourceMappingURL=Tree-hzIbj2q1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tree-Cc8lIzgM.js","names":["s","DisclosureMark","Tree_module_default","TYPEAHEAD_MS","Tree","forwardRef","ariaLabel","ariaLabelledBy","expanded","setExpanded","useControlledSet","expandedIds","defaultExpandedIds","onExpandedChange","selected","setSelected","selectedIds","defaultSelectedIds","onSelectionChange","selectable","selectionMode","baseId","useId","visible","useMemo","out","walk","node","list","level","nodes","indexOf","v","i","items","useRef","focusId","setFocusId","useState","anchor","typed","stopId","className","empty","focus","id","toggle","next","select","mods","a","b","x","activate","onAction","onKeyDown","e","open","modsOf","typeAhead","now","t","want","start","from","k","textOf","onRowClick","onTwistyClick","itemRef","el","seq","renderLevel","n","branch","labelId","trailingId","pos","filterTree","changed","match","kids","treeBranchIds","own","setOwn","initial","value","onChange"],"sources":["../../src/components/Tree/Tree.module.css","../../src/components/Tree/Tree.tsx"],"sourcesContent":[".tree,\n.group {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.tree {\n user-select: none;\n -webkit-user-select: none;\n width: 100%;\n}\n\n/* One twisty and one gap, so a child's twisty sits under its parent's label. */\n.group {\n padding-inline-start: var(--wzl-tree-indent, calc(var(--wzl-control-h-xs) + var(--wzl-space-2)));\n}\n\n.item {\n outline: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-2);\n padding: 0 var(--wzl-space-2) 0 0;\n height: var(--wzl-control-h);\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg);\n border-radius: var(--wzl-radius-sm);\n cursor: default;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.row:hover {\n background: var(--wzl-surface);\n}\n\n.item:focus-visible > .row {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n.item[aria-selected='true'] > .row {\n background: var(--wzl-border);\n}\n\n.item[data-muted] > .row {\n color: var(--wzl-fg-subtle);\n}\n\n.item[aria-disabled='true'] > .row {\n color: var(--wzl-fg-subtle);\n cursor: not-allowed;\n}\n\n/* A leaf keeps the empty box, so labels at one level line up whether or not\n their rows are branches. */\n.twisty {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--wzl-control-h-xs);\n align-self: stretch;\n color: var(--wzl-fg-muted);\n}\n\n.row:hover > .twisty {\n color: var(--wzl-fg);\n}\n\n.leading {\n flex: none;\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.trailing {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: var(--wzl-space-2);\n}\n\n.empty {\n padding: var(--wzl-space-6) var(--wzl-space-4);\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg-subtle);\n font-style: italic;\n}\n","import {\n forwardRef,\n useId,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport type { PressModifiers } from '../../useReorderDragList';\nimport { DisclosureMark } from '../Disclosure';\nimport s from './Tree.module.css';\n\n/** One node. A node with `children` is a branch, even when the array is empty. */\nexport interface TreeNode {\n /** Unique across the whole tree. */\n id: string;\n label: ReactNode;\n /** What type-ahead matches against. Defaults to `label` when that is a string. */\n textValue?: string;\n /** Decoration before the label — an icon. Not a control. */\n leading?: ReactNode;\n /** Decoration after the label — a count badge. Not a control. Read as part\n * of the row's accessible name. */\n trailing?: ReactNode;\n children?: readonly TreeNode[];\n /** Present but not in effect. */\n muted?: boolean;\n /** Focusable and announced, but cannot be activated, expanded or selected. */\n disabled?: boolean;\n className?: string;\n}\n\n/** Whether and how rows are selectable. */\nexport type TreeSelectionMode = 'none' | 'single' | 'multiple';\n\n/** Props for {@link Tree}. */\nexport interface TreeProps {\n nodes: readonly TreeNode[];\n /** Shown in place of the tree when `nodes` is empty. */\n empty?: ReactNode;\n className?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n\n /** Open branches, controlled. */\n expandedIds?: Iterable<string>;\n /** Open branches on first render, when uncontrolled. */\n defaultExpandedIds?: Iterable<string>;\n /** The whole set a toggle would produce. Called whether or not controlled. */\n onExpandedChange?(ids: Set<string>): void;\n\n /** Default `'none'`. `'multiple'` adds to the selection with Cmd/Ctrl and\n * extends it over visible rows with Shift. */\n selectionMode?: TreeSelectionMode;\n /** Selected rows, controlled. */\n selectedIds?: Iterable<string>;\n /** Selected rows on first render, when uncontrolled. */\n defaultSelectedIds?: Iterable<string>;\n /** The whole set an activation would produce, when it differs. */\n onSelectionChange?(ids: Set<string>): void;\n\n /** A row was activated — click, Enter or Space — with the modifiers held. */\n onAction?(id: string, mods: PressModifiers): void;\n}\n\ninterface Visible {\n node: TreeNode;\n parentId: string | null;\n level: number;\n}\n\nconst TYPEAHEAD_MS = 500;\n\n/**\n * A hierarchy of rows that expand and collapse: a file tree, a registry\n * browser, an outline.\n *\n * **Semantics.** WAI-ARIA `tree`: each node is a `treeitem` carrying\n * `aria-level`, `aria-setsize` and `aria-posinset`; a branch carries\n * `aria-expanded` and nests its children in a `group`, which is rendered only\n * while the branch is open. `aria-selected` appears only when `selectionMode`\n * is set. A treeitem may not contain interactive content, so `leading` and\n * `trailing` are decoration — an icon, a count — and the twisty is a drawn\n * `DisclosureMark`, not a button.\n *\n * **Keyboard.** One treeitem is in the tab order: the one last focused, else\n * the first selected, else the first. Up/Down move between visible rows,\n * Home/End go to the first and last. Right opens a closed branch, then moves\n * into it; Left closes an open branch, else moves to the parent. Enter and\n * Space activate, as a click does. Typing moves to the next row whose text\n * starts with what was typed.\n *\n * **Activating** a row — click, Enter, Space — toggles it if it is a branch,\n * selects it under `selectionMode`, and calls `onAction`. Clicking the twisty\n * only toggles.\n *\n * **Filtering** is the consumer's: narrow `nodes` with `filterTree`, and pass\n * `treeBranchIds` of the result as `expandedIds` so every match shows.\n */\nexport const Tree = forwardRef(function Tree(\n {\n nodes, empty, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy,\n expandedIds, defaultExpandedIds, onExpandedChange,\n selectionMode = 'none', selectedIds, defaultSelectedIds, onSelectionChange,\n onAction,\n }: TreeProps,\n ref: Ref<HTMLUListElement>,\n) {\n const [expanded, setExpanded] = useControlledSet(expandedIds, defaultExpandedIds, onExpandedChange);\n const [selected, setSelected] = useControlledSet(selectedIds, defaultSelectedIds, onSelectionChange);\n const selectable = selectionMode !== 'none';\n const baseId = useId();\n\n const visible = useMemo(() => {\n const out: Visible[] = [];\n const walk = (list: readonly TreeNode[], parentId: string | null, level: number) => {\n for (const node of list) {\n out.push({ node, parentId, level });\n if (node.children && expanded.has(node.id)) walk(node.children, node.id, level + 1);\n }\n };\n walk(nodes, null, 1);\n return out;\n }, [nodes, expanded]);\n const indexOf = useMemo(() => new Map(visible.map((v, i) => [v.node.id, i])), [visible]);\n\n const items = useRef(new Map<string, HTMLLIElement>());\n const [focusId, setFocusId] = useState<string | null>(null);\n const anchor = useRef<string | null>(null);\n const typed = useRef({ text: '', at: 0 });\n\n const stopId = focusId != null && indexOf.has(focusId)\n ? focusId\n : (visible.find((v) => selectable && selected.has(v.node.id)) ?? visible[0])?.node.id;\n\n if (nodes.length === 0) {\n return <div className={[s.empty, className].filter(Boolean).join(' ')}>{empty ?? '—'}</div>;\n }\n\n const focus = (id: string | undefined) => { if (id != null) items.current.get(id)?.focus(); };\n\n const toggle = (node: TreeNode) => {\n if (!node.children || node.disabled) return;\n const next = new Set(expanded);\n if (next.has(node.id)) next.delete(node.id);\n else next.add(node.id);\n setExpanded(next);\n };\n\n const select = (id: string, mods: PressModifiers) => {\n let next: Set<string>;\n if (selectionMode === 'multiple' && mods.shiftKey && anchor.current != null && indexOf.has(anchor.current)) {\n const a = indexOf.get(anchor.current)!;\n const b = indexOf.get(id)!;\n next = new Set(visible.slice(Math.min(a, b), Math.max(a, b) + 1)\n .filter((v) => !v.node.disabled).map((v) => v.node.id));\n } else if (selectionMode === 'multiple' && (mods.metaKey || mods.ctrlKey)) {\n next = new Set(selected);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n anchor.current = id;\n } else {\n next = new Set([id]);\n anchor.current = id;\n }\n if (next.size !== selected.size || [...next].some((x) => !selected.has(x))) setSelected(next);\n };\n\n const activate = (node: TreeNode, mods: PressModifiers) => {\n if (node.disabled) return;\n toggle(node);\n if (selectable) select(node.id, mods);\n onAction?.(node.id, mods);\n };\n\n const onKeyDown = (v: Visible) => (e: KeyboardEvent<HTMLLIElement>) => {\n if (e.target !== e.currentTarget) return;\n const i = indexOf.get(v.node.id)!;\n const { node } = v;\n const open = !!node.children && expanded.has(node.id);\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focus(visible[Math.min(i + 1, visible.length - 1)].node.id);\n return;\n case 'ArrowUp':\n e.preventDefault();\n focus(visible[Math.max(i - 1, 0)].node.id);\n return;\n case 'Home':\n e.preventDefault();\n focus(visible[0].node.id);\n return;\n case 'End':\n e.preventDefault();\n focus(visible[visible.length - 1].node.id);\n return;\n case 'ArrowRight':\n if (!node.children) return;\n e.preventDefault();\n if (!open) toggle(node);\n else focus(node.children[0]?.id);\n return;\n case 'ArrowLeft':\n e.preventDefault();\n if (open) toggle(node);\n else focus(v.parentId ?? undefined);\n return;\n case 'Enter':\n case ' ':\n e.preventDefault();\n activate(node, modsOf(e));\n return;\n default:\n if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;\n typeAhead(e, i);\n }\n };\n\n const typeAhead = (e: KeyboardEvent, from: number) => {\n const now = Date.now();\n const t = typed.current;\n t.text = now - t.at > TYPEAHEAD_MS ? e.key : t.text + e.key;\n t.at = now;\n const want = t.text.toLowerCase();\n // A fresh first letter looks past the current row; a longer prefix may still match it.\n const start = t.text.length === 1 ? from + 1 : from;\n for (let k = 0; k < visible.length; k++) {\n const v = visible[(start + k) % visible.length];\n if (textOf(v.node).toLowerCase().startsWith(want)) {\n e.preventDefault();\n focus(v.node.id);\n return;\n }\n }\n };\n\n const onRowClick = (node: TreeNode) => (e: MouseEvent<HTMLDivElement>) => activate(node, modsOf(e));\n\n const onTwistyClick = (node: TreeNode) => (e: MouseEvent<HTMLSpanElement>) => {\n e.stopPropagation();\n toggle(node);\n };\n\n const itemRef = (id: string) => (el: HTMLLIElement | null) => {\n if (el) items.current.set(id, el);\n else items.current.delete(id);\n };\n\n let seq = 0;\n const renderLevel = (list: readonly TreeNode[], parentId: string | null, level: number): ReactNode =>\n list.map((node, pos) => {\n const n = seq++;\n const branch = !!node.children;\n const open = branch && expanded.has(node.id);\n const labelId = `${baseId}-${n}`;\n const trailingId = node.trailing != null ? `${baseId}-${n}-t` : undefined;\n return (\n <li\n key={node.id}\n ref={itemRef(node.id)}\n role=\"treeitem\"\n className={[s.item, node.className].filter(Boolean).join(' ')}\n aria-level={level}\n aria-setsize={list.length}\n aria-posinset={pos + 1}\n aria-expanded={branch ? open : undefined}\n aria-selected={selectable ? selected.has(node.id) : undefined}\n aria-disabled={node.disabled || undefined}\n aria-labelledby={trailingId ? `${labelId} ${trailingId}` : labelId}\n data-muted={node.muted ? 'true' : undefined}\n tabIndex={node.id === stopId ? 0 : -1}\n onKeyDown={onKeyDown({ node, parentId, level })}\n onFocus={(e) => { if (e.target === e.currentTarget) setFocusId(node.id); }}\n >\n <div className={s.row} onClick={onRowClick(node)}>\n <span className={s.twisty} aria-hidden=\"true\" onClick={branch ? onTwistyClick(node) : undefined}>\n {branch && <DisclosureMark open={open} />}\n </span>\n {node.leading != null && <span className={s.leading}>{node.leading}</span>}\n <span id={labelId} className={s.label}>{node.label}</span>\n {trailingId && <span id={trailingId} className={s.trailing}>{node.trailing}</span>}\n </div>\n {open && node.children!.length > 0 && (\n <ul role=\"group\" className={s.group}>\n {renderLevel(node.children!, node.id, level + 1)}\n </ul>\n )}\n </li>\n );\n });\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n className={[s.tree, className].filter(Boolean).join(' ')}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-multiselectable={selectionMode === 'multiple' || undefined}\n >\n {renderLevel(nodes, null, 1)}\n </ul>\n );\n});\n\n/**\n * `nodes` narrowed to those `match` accepts, plus their ancestors. A matching\n * node keeps its whole subtree; a branch with no match inside it is dropped.\n * Returns `nodes` itself when nothing is dropped.\n */\nexport function filterTree(\n nodes: readonly TreeNode[],\n match: (node: TreeNode) => boolean,\n): readonly TreeNode[] {\n let changed = false;\n const out: TreeNode[] = [];\n for (const node of nodes) {\n if (match(node)) {\n out.push(node);\n continue;\n }\n const kids = node.children ? filterTree(node.children, match) : [];\n if (kids.length === 0) {\n changed = true;\n continue;\n }\n if (kids !== node.children) changed = true;\n out.push(kids === node.children ? node : { ...node, children: kids });\n }\n return changed ? out : nodes;\n}\n\n/** Every branch id in `nodes`, depth first — `expandedIds` for a tree with everything open. */\nexport function treeBranchIds(nodes: readonly TreeNode[]): string[] {\n const out: string[] = [];\n const walk = (list: readonly TreeNode[]) => {\n for (const node of list) {\n if (!node.children) continue;\n out.push(node.id);\n walk(node.children);\n }\n };\n walk(nodes);\n return out;\n}\n\nfunction textOf(node: TreeNode): string {\n return node.textValue ?? (typeof node.label === 'string' ? node.label : '');\n}\n\nfunction modsOf(e: { shiftKey: boolean; ctrlKey: boolean; metaKey: boolean; altKey: boolean }): PressModifiers {\n return { shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, altKey: e.altKey };\n}\n\nfunction useControlledSet(\n value: Iterable<string> | undefined,\n initial: Iterable<string> | undefined,\n onChange: ((ids: Set<string>) => void) | undefined,\n): [ReadonlySet<string>, (next: Set<string>) => void] {\n const [own, setOwn] = useState<ReadonlySet<string>>(() => new Set(initial));\n const controlled = useMemo(() => (value === undefined ? undefined : new Set(value)), [value]);\n const set = (next: Set<string>) => {\n if (value === undefined) setOwn(next);\n onChange?.(next);\n };\n return [controlled ?? own, set];\n}\n"],"mappings":";;;;;;;;;;;;;GC0EMG,IAAe,KA4BRC,IAAOC,EAAW,SAC7B,EACE,UAAO,UAAO,cACd,cAAcC,GAAW,mBAAmBC,GAC5C,gBAAa,uBAAoB,qBACjC,mBAAgB,QAAQ,gBAAa,uBAAoB,sBACzD,eAEF,GACA;CACA,IAAM,CAACC,GAAUC,KAAeC,EAAiBC,GAAaC,GAAoBC,CAAgB,GAC5F,CAACC,GAAUC,KAAeL,EAAiBM,GAAaC,GAAoBC,CAAiB,GAC7FC,IAAaC,MAAkB,QAC/BC,IAASC,EAAM,GAEfC,IAAUC,QAAc;EAC5B,IAAMC,IAAiB,CAAC,GAClBC,KAAQ,GAA2B,GAAyB,MAAkB;GAClF,KAAK,IAAMC,KAAQC,GAEjB,AADAH,EAAI,KAAK;IAAE;IAAM;IAAU;GAAM,CAAC,GAC9BE,EAAK,YAAYnB,EAAS,IAAImB,EAAK,EAAE,KAAGD,EAAKC,EAAK,UAAUA,EAAK,IAAIE,IAAQ,CAAC;EAEtF;EAEA,OADAH,EAAKI,GAAO,MAAM,CAAC,GACZL;CACT,GAAG,CAACK,GAAOtB,CAAQ,CAAC,GACduB,IAAUP,QAAc,IAAI,IAAID,EAAQ,KAAK,GAAG,MAAM,CAACS,EAAE,KAAK,IAAIC,CAAC,CAAC,CAAC,GAAG,CAACV,CAAO,CAAC,GAEjFW,IAAQC,kBAAO,IAAI,IAA2B,CAAC,GAC/C,CAACC,GAASC,KAAcC,EAAwB,IAAI,GACpDC,IAASJ,EAAsB,IAAI,GACnCK,IAAQL,EAAO;EAAE,MAAM;EAAI,IAAI;CAAE,CAAC,GAElCM,IAASL,KAAW,QAAQL,EAAQ,IAAIK,CAAO,IACjDA,KACCb,EAAQ,MAAM,MAAMJ,KAAcL,EAAS,IAAIkB,EAAE,KAAK,EAAE,CAAC,KAAKT,EAAQ,GAAA,EAAK,KAAK;CAErF,IAAIO,EAAM,WAAW,GACnB,OAAO,kBAAC,OAAD;EAAK,WAAW,CAAC9B,EAAE,OAAO0C,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAAI,UAAAC,KAAS;CAAS,CAAA;CAG5F,IAAMC,KAAS,MAA2B;EAAE,AAAIC,KAAM,QAAMX,EAAM,QAAQ,IAAIW,CAAE,CAAC,EAAE,MAAM;CAAG,GAEtFC,KAAU,MAAmB;EACjC,IAAI,CAACnB,EAAK,YAAYA,EAAK,UAAU;EACrC,IAAMoB,IAAO,IAAI,IAAIvC,CAAQ;EAG7B,AAFIuC,EAAK,IAAIpB,EAAK,EAAE,IAAGoB,EAAK,OAAOpB,EAAK,EAAE,IACrCoB,EAAK,IAAIpB,EAAK,EAAE,GACrBlB,EAAYsC,CAAI;CAClB,GAEMC,KAAU,GAAY,MAAyB;EACnD,IAAID;EACJ,IAAI3B,MAAkB,cAAc6B,EAAK,YAAYV,EAAO,WAAW,QAAQR,EAAQ,IAAIQ,EAAO,OAAO,GAAG;GAC1G,IAAMW,IAAInB,EAAQ,IAAIQ,EAAO,OAAO,GAC9BY,IAAIpB,EAAQ,IAAIc,CAAE;GACxB,IAAO,IAAI,IAAItB,EAAQ,MAAM,KAAK,IAAI2B,GAAGC,CAAC,GAAG,KAAK,IAAID,GAAGC,CAAC,IAAI,CAAC,CAAC,CAC7D,QAAQ,MAAM,CAACnB,EAAE,KAAK,QAAQ,CAAC,CAAC,KAAK,MAAMA,EAAE,KAAK,EAAE,CAAC;EAC1D,OAAO,AAAIZ,MAAkB,eAAe6B,EAAK,WAAWA,EAAK,YAC/D,IAAO,IAAI,IAAInC,CAAQ,GACnBiC,EAAK,IAAIF,CAAE,IAAGE,EAAK,OAAOF,CAAE,IAC3BE,EAAK,IAAIF,CAAE,GAChB,EAAO,UAAUA,MAEjB,oBAAO,IAAI,IAAI,CAACA,CAAE,CAAC,GACnB,EAAO,UAAUA;EAEnB,CAAIE,EAAK,SAASjC,EAAS,QAAQ,CAAC,GAAGiC,CAAI,CAAC,CAAC,MAAM,MAAM,CAACjC,EAAS,IAAIsC,CAAC,CAAC,MAAGrC,EAAYgC,CAAI;CAC9F,GAEMM,KAAY,GAAgB,MAAyB;EACzD,AAAI1B,EAAK,aACTmB,EAAOnB,CAAI,GACPR,KAAY6B,EAAOrB,EAAK,IAAIsB,CAAI,GACpCK,IAAW3B,EAAK,IAAIsB,CAAI;CAC1B,GAEMM,KAAa,OAAgB,MAAoC;EACrE,IAAIC,EAAE,WAAWA,EAAE,eAAe;EAClC,IAAMvB,IAAIF,EAAQ,IAAIC,EAAE,KAAK,EAAE,GACzB,EAAE,YAASA,GACXyB,IAAO,CAAC,CAAC9B,EAAK,YAAYnB,EAAS,IAAImB,EAAK,EAAE;EACpD,QAAQ6B,EAAE,KAAV;GACE,KAAK;IAEH,AADAA,EAAE,eAAe,GACjBZ,EAAMrB,EAAQ,KAAK,IAAIU,IAAI,GAAGV,EAAQ,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;IAC1D;GACF,KAAK;IAEH,AADAiC,EAAE,eAAe,GACjBZ,EAAMrB,EAAQ,KAAK,IAAIU,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;IACzC;GACF,KAAK;IAEH,AADAuB,EAAE,eAAe,GACjBZ,EAAMrB,EAAQ,EAAE,CAAC,KAAK,EAAE;IACxB;GACF,KAAK;IAEH,AADAiC,EAAE,eAAe,GACjBZ,EAAMrB,EAAQA,EAAQ,SAAS,EAAE,CAAC,KAAK,EAAE;IACzC;GACF,KAAK;IACH,IAAI,CAACI,EAAK,UAAU;IAEpB,AADA6B,EAAE,eAAe,GACZC,IACAb,EAAMjB,EAAK,SAAS,EAAE,EAAE,EAAE,IADpBmB,EAAOnB,CAAI;IAEtB;GACF,KAAK;IAEH,AADA6B,EAAE,eAAe,GACbC,IAAMX,EAAOnB,CAAI,IAChBiB,EAAMZ,EAAE,YAAY,KAAA,CAAS;IAClC;GACF,KAAK;GACL,KAAK;IAEH,AADAwB,EAAE,eAAe,GACjBH,EAAS1B,GAAM+B,EAAOF,CAAC,CAAC;IACxB;GACF;IACE,IAAIA,EAAE,IAAI,WAAW,KAAKA,EAAE,WAAWA,EAAE,WAAWA,EAAE,QAAQ;IAC9D,EAAUA,GAAGvB,CAAC;EAClB;CACF,GAEM0B,KAAa,GAAkB,MAAiB;EACpD,IAAMC,IAAM,KAAK,IAAI,GACfC,IAAIrB,EAAM;EAEhB,AADA,EAAE,OAAOoB,IAAMC,EAAE,KAAK1D,IAAe,EAAE,MAAM0D,EAAE,OAAO,EAAE,KACxD,EAAE,KAAKD;EACP,IAAME,IAAOD,EAAE,KAAK,YAAY,GAE1BE,IAAQF,EAAE,KAAK,WAAW,IAAIG,IAAO,IAAIA;EAC/C,KAAK,IAAIC,IAAI,GAAGA,IAAI1C,EAAQ,QAAQ,KAAK;GACvC,IAAMS,IAAIT,GAASwC,IAAQE,KAAK1C,EAAQ;GACxC,IAAI2C,EAAOlC,EAAE,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,WAAW8B,CAAI,GAAG;IAEjD,AADA,EAAE,eAAe,GACjBlB,EAAMZ,EAAE,KAAK,EAAE;IACf;GACF;EACF;CACF,GAEMmC,KAAc,OAAoB,MAAkCd,EAAS1B,GAAM+B,EAAOF,CAAC,CAAC,GAE5FY,KAAiB,OAAoB,MAAmC;EAE5E,AADAZ,EAAE,gBAAgB,GAClBV,EAAOnB,CAAI;CACb,GAEM0C,KAAW,OAAgB,MAA6B;EAC5D,AAAIC,IAAIpC,EAAM,QAAQ,IAAIW,GAAIyB,CAAE,IAC3BpC,EAAM,QAAQ,OAAOW,CAAE;CAC9B,GAEI0B,IAAM,GACJC,KAAe,GAA2B,GAAyB,MACvE5C,EAAK,KAAK,GAAM,MAAQ;EACtB,IAAM6C,IAAI,KACJC,IAAS,CAAC,CAAC/C,EAAK,UAChB8B,IAAOiB,KAAUlE,EAAS,IAAImB,EAAK,EAAE,GACrCgD,IAAU,GAAGtD,EAAO,GAAGoD,KACvBG,IAAajD,EAAK,YAAY,OAA4B,KAAA,IAArB,GAAGN,EAAO,GAAGoD,EAAE;EAC1D,OACE,kBAAC,MAAD;GAEE,KAAKJ,EAAQ1C,EAAK,EAAE;GACpB,MAAK;GACL,WAAW,CAAC3B,EAAE,MAAM2B,EAAK,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;GAC5D,cAAYE;GACZ,gBAAcD,EAAK;GACnB,iBAAeiD,IAAM;GACrB,iBAAeH,IAASjB,IAAO,KAAA;GAC/B,iBAAetC,IAAaL,EAAS,IAAIa,EAAK,EAAE,IAAI,KAAA;GACpD,iBAAeA,EAAK,YAAY,KAAA;GAChC,mBAAiBiD,IAAa,GAAGD,EAAQ,GAAGC,MAAeD;GAC3D,cAAYhD,EAAK,QAAQ,SAAS,KAAA;GAClC,UAAUA,EAAK,OAAOc,IAAS,IAAI;GACnC,WAAWc,EAAU;IAAE;IAAM;IAAU;GAAM,CAAC;GAC9C,UAAU,MAAM;IAAE,AAAI,EAAE,WAAW,EAAE,iBAAelB,EAAWV,EAAK,EAAE;GAAG;GAf3E,UAAA,CAiBE,kBAAC,OAAD;IAAK,WAAW3B,EAAE;IAAK,SAASmE,EAAWxC,CAAI;IAA/C,UAAA;KACE,kBAAC,QAAD;MAAM,WAAW3B,EAAE;MAAQ,eAAY;MAAO,SAAS0E,IAASN,EAAczC,CAAI,IAAI,KAAA;MACnF,UAAA+C,KAAU,kBAACzE,GAAD,EAAsB,QAAO,CAAA;KACpC,CAAA;KACL0B,EAAK,WAAW,QAAQ,kBAAC,QAAD;MAAM,WAAW3B,EAAE;MAAU,UAAA2B,EAAK;KAAc,CAAA;KACzE,kBAAC,QAAD;MAAM,IAAIgD;MAAS,WAAW3E,EAAE;MAAQ,UAAA2B,EAAK;KAAY,CAAA;KACxDiD,KAAc,kBAAC,QAAD;MAAM,IAAIA;MAAY,WAAW5E,EAAE;MAAW,UAAA2B,EAAK;KAAe,CAAA;IAC9E;GACJ,CAAA,GAAA8B,KAAQ9B,EAAK,SAAU,SAAS,KAC/B,kBAAC,MAAD;IAAI,MAAK;IAAQ,WAAW3B,EAAE;IAC3B,UAAAwE,EAAY7C,EAAK,UAAWA,EAAK,IAAIE,IAAQ,CAAC;GAC7C,CAAA,CAEJ;EA7BG,GAAAF,EAAK,EA6BR;CAER,CAAC;CAEH,OACE,kBAAC,MAAD;EACO;EACL,MAAK;EACL,WAAW,CAAC3B,EAAE,MAAM0C,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACvD,cAAYpC;EACZ,mBAAiBC;EACjB,wBAAsBa,MAAkB,cAAc,KAAA;EAErD,UAAAoD,EAAY1C,GAAO,MAAM,CAAC;CACzB,CAAA;AAER,CAAC;AAOD,SAAgBgD,EACd,GACA,GACqB;CACrB,IAAIC,IAAU,IACRtD,IAAkB,CAAC;CACzB,KAAK,IAAME,KAAQG,GAAO;EACxB,IAAIkD,EAAMrD,CAAI,GAAG;GACf,EAAI,KAAKA,CAAI;GACb;EACF;EACA,IAAMsD,IAAOtD,EAAK,WAAWmD,EAAWnD,EAAK,UAAUqD,CAAK,IAAI,CAAC;EACjE,IAAIC,EAAK,WAAW,GAAG;GACrB,IAAU;GACV;EACF;EAEA,AADIA,MAAStD,EAAK,aAAU,IAAU,KACtCF,EAAI,KAAKwD,MAAStD,EAAK,WAAWA,IAAO;GAAE,GAAGA;GAAM,UAAUsD;EAAK,CAAC;CACtE;CACA,OAAOF,IAAUtD,IAAMK;AACzB;AAGA,SAAgBoD,EAAc,GAAsC;CAClE,IAAMzD,IAAgB,CAAC,GACjBC,KAAQ,MAA8B;EAC1C,KAAK,IAAMC,KAAQC,GACjB,AAAKD,EAAK,aACVF,EAAI,KAAKE,EAAK,EAAE,GAChBD,EAAKC,EAAK,QAAQ;CAEtB;CAEA,OADAD,EAAKI,CAAK,GACHL;AACT;AAEA,SAASyC,EAAO,GAAwB;CACtC,OAAOvC,EAAK,cAAc,OAAOA,EAAK,SAAU,WAAWA,EAAK,QAAQ;AAC1E;AAEA,SAAS+B,EAAO,GAA+F;CAC7G,OAAO;EAAE,UAAU,EAAE;EAAU,SAAS,EAAE;EAAS,SAAS,EAAE;EAAS,QAAQ,EAAE;CAAO;AAC1F;AAEA,SAAShD,EACP,GACA,GACA,GACoD;CACpD,IAAM,CAACyE,GAAKC,KAAU9C,QAAoC,IAAI,IAAI+C,CAAO,CAAC;CAM1E,OAAO,CALY7D,QAAe8D,MAAU,KAAA,IAAY,KAAA,IAAY,IAAI,IAAIA,CAAK,GAAI,CAACA,CAAK,CAKnF,KAAcH,IAJT,MAAsB;EAEjC,AADIG,MAAU,KAAA,KAAWF,EAAOrC,CAAI,GACpCwC,IAAWxC,CAAI;CACjB,CAC8B;AAChC"}
1
+ {"version":3,"file":"Tree-hzIbj2q1.js","names":["s","DisclosureMark","Tree_module_default","TYPEAHEAD_MS","Tree","forwardRef","ariaLabel","ariaLabelledBy","expanded","setExpanded","useControlledSet","expandedIds","defaultExpandedIds","onExpandedChange","selected","setSelected","selectedIds","defaultSelectedIds","onSelectionChange","selectable","selectionMode","baseId","useId","visible","useMemo","out","walk","node","list","level","nodes","indexOf","v","i","items","useRef","focusId","setFocusId","useState","anchor","typed","stopId","className","empty","focus","id","toggle","next","select","mods","a","b","x","activate","onAction","onKeyDown","e","open","modsOf","typeAhead","now","t","want","start","from","k","textOf","onRowClick","onTwistyClick","itemRef","el","seq","renderLevel","n","branch","labelId","trailingId","pos","filterTree","changed","match","kids","treeBranchIds","own","setOwn","initial","value","onChange"],"sources":["../../src/components/Tree/Tree.module.css","../../src/components/Tree/Tree.tsx"],"sourcesContent":[".tree,\n.group {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.tree {\n user-select: none;\n -webkit-user-select: none;\n width: 100%;\n}\n\n/* One twisty and one gap, so a child's twisty sits under its parent's label. */\n.group {\n padding-inline-start: var(--wzl-tree-indent, calc(var(--wzl-control-h-xs) + var(--wzl-space-2)));\n}\n\n.item {\n outline: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-2);\n padding: 0 var(--wzl-space-2) 0 0;\n height: var(--wzl-control-h);\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg);\n border-radius: var(--wzl-radius-sm);\n cursor: default;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.row:hover {\n background: var(--wzl-surface);\n}\n\n.item:focus-visible > .row {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n.item[aria-selected='true'] > .row {\n background: var(--wzl-border);\n}\n\n.item[data-muted] > .row {\n color: var(--wzl-fg-subtle);\n}\n\n.item[aria-disabled='true'] > .row {\n color: var(--wzl-fg-subtle);\n cursor: not-allowed;\n}\n\n/* A leaf keeps the empty box, so labels at one level line up whether or not\n their rows are branches. */\n.twisty {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--wzl-control-h-xs);\n align-self: stretch;\n color: var(--wzl-fg-muted);\n}\n\n.row:hover > .twisty {\n color: var(--wzl-fg);\n}\n\n.leading {\n flex: none;\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.trailing {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: var(--wzl-space-2);\n}\n\n.empty {\n padding: var(--wzl-space-6) var(--wzl-space-4);\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg-subtle);\n font-style: italic;\n}\n","import {\n forwardRef,\n useId,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport type { PressModifiers } from '../../useReorderDragList';\nimport { DisclosureMark } from '../Disclosure';\nimport s from './Tree.module.css';\n\n/** One node. A node with `children` is a branch, even when the array is empty. */\nexport interface TreeNode {\n /** Unique across the whole tree. */\n id: string;\n label: ReactNode;\n /** What type-ahead matches against. Defaults to `label` when that is a string. */\n textValue?: string;\n /** Decoration before the label — an icon. Not a control. */\n leading?: ReactNode;\n /** Decoration after the label — a count badge. Not a control. Read as part\n * of the row's accessible name. */\n trailing?: ReactNode;\n children?: readonly TreeNode[];\n /** Present but not in effect. */\n muted?: boolean;\n /** Focusable and announced, but cannot be activated, expanded or selected. */\n disabled?: boolean;\n className?: string;\n}\n\n/** Whether and how rows are selectable. */\nexport type TreeSelectionMode = 'none' | 'single' | 'multiple';\n\n/** Props for {@link Tree}. */\nexport interface TreeProps {\n nodes: readonly TreeNode[];\n /** Shown in place of the tree when `nodes` is empty. */\n empty?: ReactNode;\n className?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n\n /** Open branches, controlled. */\n expandedIds?: Iterable<string>;\n /** Open branches on first render, when uncontrolled. */\n defaultExpandedIds?: Iterable<string>;\n /** The whole set a toggle would produce. Called whether or not controlled. */\n onExpandedChange?(ids: Set<string>): void;\n\n /** Default `'none'`. `'multiple'` adds to the selection with Cmd/Ctrl and\n * extends it over visible rows with Shift. */\n selectionMode?: TreeSelectionMode;\n /** Selected rows, controlled. */\n selectedIds?: Iterable<string>;\n /** Selected rows on first render, when uncontrolled. */\n defaultSelectedIds?: Iterable<string>;\n /** The whole set an activation would produce, when it differs. */\n onSelectionChange?(ids: Set<string>): void;\n\n /** A row was activated — click, Enter or Space — with the modifiers held. */\n onAction?(id: string, mods: PressModifiers): void;\n}\n\ninterface Visible {\n node: TreeNode;\n parentId: string | null;\n level: number;\n}\n\nconst TYPEAHEAD_MS = 500;\n\n/**\n * A hierarchy of rows that expand and collapse: a file tree, a registry\n * browser, an outline.\n *\n * **Semantics.** WAI-ARIA `tree`: each node is a `treeitem` carrying\n * `aria-level`, `aria-setsize` and `aria-posinset`; a branch carries\n * `aria-expanded` and nests its children in a `group`, which is rendered only\n * while the branch is open. `aria-selected` appears only when `selectionMode`\n * is set. A treeitem may not contain interactive content, so `leading` and\n * `trailing` are decoration — an icon, a count — and the twisty is a drawn\n * `DisclosureMark`, not a button.\n *\n * **Keyboard.** One treeitem is in the tab order: the one last focused, else\n * the first selected, else the first. Up/Down move between visible rows,\n * Home/End go to the first and last. Right opens a closed branch, then moves\n * into it; Left closes an open branch, else moves to the parent. Enter and\n * Space activate, as a click does. Typing moves to the next row whose text\n * starts with what was typed.\n *\n * **Activating** a row — click, Enter, Space — toggles it if it is a branch,\n * selects it under `selectionMode`, and calls `onAction`. Clicking the twisty\n * only toggles.\n *\n * **Filtering** is the consumer's: narrow `nodes` with `filterTree`, and pass\n * `treeBranchIds` of the result as `expandedIds` so every match shows.\n */\nexport const Tree = forwardRef(function Tree(\n {\n nodes, empty, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy,\n expandedIds, defaultExpandedIds, onExpandedChange,\n selectionMode = 'none', selectedIds, defaultSelectedIds, onSelectionChange,\n onAction,\n }: TreeProps,\n ref: Ref<HTMLUListElement>,\n) {\n const [expanded, setExpanded] = useControlledSet(expandedIds, defaultExpandedIds, onExpandedChange);\n const [selected, setSelected] = useControlledSet(selectedIds, defaultSelectedIds, onSelectionChange);\n const selectable = selectionMode !== 'none';\n const baseId = useId();\n\n const visible = useMemo(() => {\n const out: Visible[] = [];\n const walk = (list: readonly TreeNode[], parentId: string | null, level: number) => {\n for (const node of list) {\n out.push({ node, parentId, level });\n if (node.children && expanded.has(node.id)) walk(node.children, node.id, level + 1);\n }\n };\n walk(nodes, null, 1);\n return out;\n }, [nodes, expanded]);\n const indexOf = useMemo(() => new Map(visible.map((v, i) => [v.node.id, i])), [visible]);\n\n const items = useRef(new Map<string, HTMLLIElement>());\n const [focusId, setFocusId] = useState<string | null>(null);\n const anchor = useRef<string | null>(null);\n const typed = useRef({ text: '', at: 0 });\n\n const stopId = focusId != null && indexOf.has(focusId)\n ? focusId\n : (visible.find((v) => selectable && selected.has(v.node.id)) ?? visible[0])?.node.id;\n\n if (nodes.length === 0) {\n return <div className={[s.empty, className].filter(Boolean).join(' ')}>{empty ?? '—'}</div>;\n }\n\n const focus = (id: string | undefined) => { if (id != null) items.current.get(id)?.focus(); };\n\n const toggle = (node: TreeNode) => {\n if (!node.children || node.disabled) return;\n const next = new Set(expanded);\n if (next.has(node.id)) next.delete(node.id);\n else next.add(node.id);\n setExpanded(next);\n };\n\n const select = (id: string, mods: PressModifiers) => {\n let next: Set<string>;\n if (selectionMode === 'multiple' && mods.shiftKey && anchor.current != null && indexOf.has(anchor.current)) {\n const a = indexOf.get(anchor.current)!;\n const b = indexOf.get(id)!;\n next = new Set(visible.slice(Math.min(a, b), Math.max(a, b) + 1)\n .filter((v) => !v.node.disabled).map((v) => v.node.id));\n } else if (selectionMode === 'multiple' && (mods.metaKey || mods.ctrlKey)) {\n next = new Set(selected);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n anchor.current = id;\n } else {\n next = new Set([id]);\n anchor.current = id;\n }\n if (next.size !== selected.size || [...next].some((x) => !selected.has(x))) setSelected(next);\n };\n\n const activate = (node: TreeNode, mods: PressModifiers) => {\n if (node.disabled) return;\n toggle(node);\n if (selectable) select(node.id, mods);\n onAction?.(node.id, mods);\n };\n\n const onKeyDown = (v: Visible) => (e: KeyboardEvent<HTMLLIElement>) => {\n if (e.target !== e.currentTarget) return;\n const i = indexOf.get(v.node.id)!;\n const { node } = v;\n const open = !!node.children && expanded.has(node.id);\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focus(visible[Math.min(i + 1, visible.length - 1)].node.id);\n return;\n case 'ArrowUp':\n e.preventDefault();\n focus(visible[Math.max(i - 1, 0)].node.id);\n return;\n case 'Home':\n e.preventDefault();\n focus(visible[0].node.id);\n return;\n case 'End':\n e.preventDefault();\n focus(visible[visible.length - 1].node.id);\n return;\n case 'ArrowRight':\n if (!node.children) return;\n e.preventDefault();\n if (!open) toggle(node);\n else focus(node.children[0]?.id);\n return;\n case 'ArrowLeft':\n e.preventDefault();\n if (open) toggle(node);\n else focus(v.parentId ?? undefined);\n return;\n case 'Enter':\n case ' ':\n e.preventDefault();\n activate(node, modsOf(e));\n return;\n default:\n if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;\n typeAhead(e, i);\n }\n };\n\n const typeAhead = (e: KeyboardEvent, from: number) => {\n const now = Date.now();\n const t = typed.current;\n t.text = now - t.at > TYPEAHEAD_MS ? e.key : t.text + e.key;\n t.at = now;\n const want = t.text.toLowerCase();\n // A fresh first letter looks past the current row; a longer prefix may still match it.\n const start = t.text.length === 1 ? from + 1 : from;\n for (let k = 0; k < visible.length; k++) {\n const v = visible[(start + k) % visible.length];\n if (textOf(v.node).toLowerCase().startsWith(want)) {\n e.preventDefault();\n focus(v.node.id);\n return;\n }\n }\n };\n\n const onRowClick = (node: TreeNode) => (e: MouseEvent<HTMLDivElement>) => activate(node, modsOf(e));\n\n const onTwistyClick = (node: TreeNode) => (e: MouseEvent<HTMLSpanElement>) => {\n e.stopPropagation();\n toggle(node);\n };\n\n const itemRef = (id: string) => (el: HTMLLIElement | null) => {\n if (el) items.current.set(id, el);\n else items.current.delete(id);\n };\n\n let seq = 0;\n const renderLevel = (list: readonly TreeNode[], parentId: string | null, level: number): ReactNode =>\n list.map((node, pos) => {\n const n = seq++;\n const branch = !!node.children;\n const open = branch && expanded.has(node.id);\n const labelId = `${baseId}-${n}`;\n const trailingId = node.trailing != null ? `${baseId}-${n}-t` : undefined;\n return (\n <li\n key={node.id}\n ref={itemRef(node.id)}\n role=\"treeitem\"\n className={[s.item, node.className].filter(Boolean).join(' ')}\n aria-level={level}\n aria-setsize={list.length}\n aria-posinset={pos + 1}\n aria-expanded={branch ? open : undefined}\n aria-selected={selectable ? selected.has(node.id) : undefined}\n aria-disabled={node.disabled || undefined}\n aria-labelledby={trailingId ? `${labelId} ${trailingId}` : labelId}\n data-muted={node.muted ? 'true' : undefined}\n tabIndex={node.id === stopId ? 0 : -1}\n onKeyDown={onKeyDown({ node, parentId, level })}\n onFocus={(e) => { if (e.target === e.currentTarget) setFocusId(node.id); }}\n >\n <div className={s.row} onClick={onRowClick(node)}>\n <span className={s.twisty} aria-hidden=\"true\" onClick={branch ? onTwistyClick(node) : undefined}>\n {branch && <DisclosureMark open={open} />}\n </span>\n {node.leading != null && <span className={s.leading}>{node.leading}</span>}\n <span id={labelId} className={s.label}>{node.label}</span>\n {trailingId && <span id={trailingId} className={s.trailing}>{node.trailing}</span>}\n </div>\n {open && node.children!.length > 0 && (\n <ul role=\"group\" className={s.group}>\n {renderLevel(node.children!, node.id, level + 1)}\n </ul>\n )}\n </li>\n );\n });\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n className={[s.tree, className].filter(Boolean).join(' ')}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-multiselectable={selectionMode === 'multiple' || undefined}\n >\n {renderLevel(nodes, null, 1)}\n </ul>\n );\n});\n\n/**\n * `nodes` narrowed to those `match` accepts, plus their ancestors. A matching\n * node keeps its whole subtree; a branch with no match inside it is dropped.\n * Returns `nodes` itself when nothing is dropped.\n */\nexport function filterTree(\n nodes: readonly TreeNode[],\n match: (node: TreeNode) => boolean,\n): readonly TreeNode[] {\n let changed = false;\n const out: TreeNode[] = [];\n for (const node of nodes) {\n if (match(node)) {\n out.push(node);\n continue;\n }\n const kids = node.children ? filterTree(node.children, match) : [];\n if (kids.length === 0) {\n changed = true;\n continue;\n }\n if (kids !== node.children) changed = true;\n out.push(kids === node.children ? node : { ...node, children: kids });\n }\n return changed ? out : nodes;\n}\n\n/** Every branch id in `nodes`, depth first — `expandedIds` for a tree with everything open. */\nexport function treeBranchIds(nodes: readonly TreeNode[]): string[] {\n const out: string[] = [];\n const walk = (list: readonly TreeNode[]) => {\n for (const node of list) {\n if (!node.children) continue;\n out.push(node.id);\n walk(node.children);\n }\n };\n walk(nodes);\n return out;\n}\n\nfunction textOf(node: TreeNode): string {\n return node.textValue ?? (typeof node.label === 'string' ? node.label : '');\n}\n\nfunction modsOf(e: { shiftKey: boolean; ctrlKey: boolean; metaKey: boolean; altKey: boolean }): PressModifiers {\n return { shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, altKey: e.altKey };\n}\n\nfunction useControlledSet(\n value: Iterable<string> | undefined,\n initial: Iterable<string> | undefined,\n onChange: ((ids: Set<string>) => void) | undefined,\n): [ReadonlySet<string>, (next: Set<string>) => void] {\n const [own, setOwn] = useState<ReadonlySet<string>>(() => new Set(initial));\n const controlled = useMemo(() => (value === undefined ? undefined : new Set(value)), [value]);\n const set = (next: Set<string>) => {\n if (value === undefined) setOwn(next);\n onChange?.(next);\n };\n return [controlled ?? own, set];\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ var e = { checkbox: "_checkbox_tzhfz_4" };
2
+ //#endregion
3
+ export { e as t };
4
+
5
+ //# sourceMappingURL=checkbox.module-Dcx8ILgR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.module-Dcx8ILgR.js","names":["checkbox_module_default"],"sources":["../../src/components/checkbox.module.css"],"sourcesContent":["/* The one skin for a native <input type=\"checkbox\">. Imported by Checkbox and by\n the property rows, which render the same DOM. The box keys off the input's own\n pseudo-classes; a label's hover reaches its control's :hover. */\n.checkbox {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: 14px;\n height: 14px;\n margin: 0;\n /* Not the UA's fieldtext: the hover edge is --wzl-fg-muted, a step down from the text beside it. */\n color: inherit;\n background: var(--wzl-surface-sunken);\n border: 1px solid var(--wzl-border-strong);\n border-radius: var(--wzl-radius-sm);\n cursor: pointer;\n transition: background-color var(--wzl-motion-fast), border-color var(--wzl-motion-fast), box-shadow var(--wzl-motion-fast);\n}\n\n.checkbox:hover:not(:disabled) {\n border-color: var(--wzl-fg-muted);\n}\n\n.checkbox:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--wzl-focus-ring);\n}\n\n.checkbox:checked,\n.checkbox:indeterminate {\n background: var(--wzl-accent-strong);\n border-color: var(--wzl-accent-strong);\n}\n\n.checkbox[aria-invalid='true'] {\n border-color: var(--wzl-danger);\n}\n\n/* The mark is a mask filled with the on-accent color, so it follows the theme. */\n.checkbox:checked::before,\n.checkbox:indeterminate::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--wzl-fg-on-accent);\n -webkit-mask: var(--_check-mark) center / 100% 100% no-repeat;\n mask: var(--_check-mark) center / 100% 100% no-repeat;\n}\n\n.checkbox:checked {\n --_check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpolyline points='3,7.5 6,10.5 11,4.5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n}\n\n.checkbox:indeterminate {\n --_check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cline x1='3' y1='7' x2='11' y2='7' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\");\n}\n\n.checkbox:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n"],"mappings":""}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./Icon--B1ME-6c.js";
1
+ import { t as e } from "./Icon-DPRUIo3G.js";
2
2
  import { AlignBottomIcon as t, AlignCenterXIcon as n, AlignCenterYIcon as r, AlignLeftIcon as ee, AlignRightIcon as i, AlignTopIcon as a, ArrowIcon as o, BringForwardIcon as s, BringToFrontIcon as c, CopyIcon as l, CutIcon as u, DeleteIcon as d, DistributeHorizontalIcon as f, DistributeVerticalIcon as p, DuplicateIcon as m, EllipseIcon as h, EyedropperIcon as g, FlipXIcon as _, FlipYIcon as v, GroupIcon as y, HandIcon as b, ImageIcon as x, LassoIcon as S, LineIcon as C, PasteIcon as w, PenIcon as T, PencilIcon as E, PolygonIcon as D, RectIcon as O, RedoIcon as k, SelectIcon as A, SendBackwardIcon as j, SendToBackIcon as M, StarIcon as N, TextIcon as P, UndoIcon as F, UngroupIcon as I, UnknownIcon as L } from "@weasel-js/core";
3
3
  import { jsx as R } from "react/jsx-runtime";
4
4
  //#region src/icons/index.tsx
@@ -159,4 +159,4 @@ var z = (t) => /* @__PURE__ */ R(e, {
159
159
  //#endregion
160
160
  export { K as $, ue as A, I as At, Ae as B, p as C, ae as Ct, Se as D, P as Dt, Me as E, ie as Et, Te as F, U as Ft, Fe as G, pe as H, y as I, X as It, he as J, C as K, b as L, _ as M, ge as Mt, v as N, _e as Nt, H as O, we as Ot, ce as P, je as Pt, q as Q, ve as R, f as S, N as St, h as T, oe as Tt, Ie as U, S as V, Le as W, De as X, fe as Y, te as Z, le as _, j as _t, ee as a, E as at, u as b, Q as bt, o as c, D as ct, Ne as d, k as dt, me as et, Pe as f, ke as ft, xe as g, A as gt, V as h, de as ht, r as i, T as it, Z as j, L as jt, g as k, F as kt, s as l, Oe as lt, z as m, B as mt, t as n, w as nt, i as o, ye as ot, Ce as p, J as pt, be as q, n as r, re as rt, a as s, ne as st, G as t, W as tt, c as u, O as ut, l as v, M as vt, m as w, $ as wt, d as x, Y as xt, se as y, Ee as yt, x as z };
161
161
 
162
- //# sourceMappingURL=icons-Dr2-r30x.js.map
162
+ //# sourceMappingURL=icons-CofIOTiI.js.map