@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,20 +1,20 @@
1
1
  import { i as e } from "./portalHost-CE70wLzo.js";
2
2
  import { t } from "./stance-BFQpS_fL.js";
3
- import { t as n } from "./CloseButton-BmNmRVtb.js";
3
+ import { t as n } from "./CloseButton-wb7Or5Eg.js";
4
4
  import { useLatest as r } from "@weasel-js/core";
5
5
  import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
6
6
  import { useCallback as s, useEffect as c, useId as l, useRef as u } from "react";
7
7
  import { Dialog as d, DialogTrigger as f, Heading as p, OverlayArrow as m, Popover as h } from "react-aria-components";
8
8
  import { createPortal as g } from "react-dom";
9
9
  var _ = {
10
- anchor: "_anchor_w6dfg_1",
11
- popover: "_popover_w6dfg_6",
12
- arrow: "_arrow_w6dfg_204",
13
- dialog: "_dialog_w6dfg_223",
14
- header: "_header_w6dfg_230",
15
- title: "_title_w6dfg_237",
16
- body: "_body_w6dfg_248",
17
- footer: "_footer_w6dfg_255"
10
+ anchor: "_anchor_b47o7_1",
11
+ popover: "_popover_b47o7_6",
12
+ arrow: "_arrow_b47o7_208",
13
+ dialog: "_dialog_b47o7_227",
14
+ header: "_header_b47o7_234",
15
+ title: "_title_b47o7_241",
16
+ body: "_body_b47o7_252",
17
+ footer: "_footer_b47o7_259"
18
18
  };
19
19
  //#endregion
20
20
  //#region src/components/Callout/Callout.tsx
@@ -112,4 +112,4 @@ function v(f) {
112
112
  //#endregion
113
113
  export { f as n, v as t };
114
114
 
115
- //# sourceMappingURL=Callout-BUn0dP_S.js.map
115
+ //# sourceMappingURL=Callout-DpTO3fkb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Callout-DpTO3fkb.js","names":["_Fragment","s","RACPopover","RACDialog","useOverlayPortal","CloseButton","DialogTrigger$1","Callout_module_default","Callout","ariaLabel","ariaLabelledby","rest","props","anchorRef","useRef","stanced","useStance","portalAnchor","portalContainer","showClose","showCloseButton","modal","onDismissRef","useLatest","onDismiss","escapeListener","listeningTo","dialogRef","useCallback","node","titleId","useId","hasAnchorRect","anchorRect","popoverAriaLabelledby","title","popoverAriaLabel","Fragment","createPortal","Popover","triggerRef","shouldCloseOnInteractOutside","className","portalProps","OverlayArrow","Dialog","Heading","close","onOpenChange","footer"],"sources":["../../src/components/Callout/Callout.module.css","../../src/components/Callout/Callout.tsx"],"sourcesContent":[".anchor {\n position: fixed;\n pointer-events: none;\n}\n\n.popover {\n /* Above Dialog overlay (1000) and ToastRegion (1100) — RAC sets no z-index. */\n z-index: 1200;\n background: var(--_s-fill);\n border: var(--_s-border-width) var(--_s-border-style) var(--_s-border-color);\n border-radius: var(--_s-radius);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);\n color: var(--wzl-fg);\n font-family: var(--wzl-font-ui);\n max-width: 320px;\n transition: opacity var(--wzl-motion-fast);\n}\n\n.popover[data-entering],\n.popover[data-exiting] {\n opacity: 0;\n}\n\n/* BEGIN GENERATED stance rules: callout — `npm run gen:stances`, do not edit. */\n\n.popover {\n --wzl-tone: initial;\n}\n\n.popover {\n --_s-surface: var(--wzl-surface);\n --_s-border-color: var(--wzl-accent-strong);\n --_s-border-style: solid;\n --_s-border-width: 1px;\n --_s-radius: var(--wzl-radius-md);\n --_s-tone-mix: var(--wzl-panel-tone-mix);\n --_s-tone: var(--wzl-tone, var(--_s-surface));\n --_s-accent: var(--wzl-tone);\n --_s-title-font: var(--wzl-font-ui);\n --_s-title-weight: var(--wzl-font-weight-bold);\n --_s-title-size: var(--wzl-font-size);\n --_s-title-case: none;\n --_s-title-tracking: normal;\n --_s-title-color: var(--wzl-fg);\n}\n\n.popover[data-stance='scope'] {\n --_s-surface: var(--wzl-stance-scope-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-scope-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-scope-border-style, solid);\n --_s-border-width: var(--wzl-stance-scope-border-width, 1px);\n --_s-radius: var(--wzl-stance-scope-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-scope-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-scope-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-scope-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-scope-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-scope-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-scope-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-scope-title-case, none);\n --_s-title-tracking: var(--wzl-stance-scope-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-scope-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='aside'] {\n --_s-surface: var(--wzl-stance-aside-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-aside-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-aside-border-style, solid);\n --_s-border-width: var(--wzl-stance-aside-border-width, 1px);\n --_s-radius: var(--wzl-stance-aside-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-aside-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-aside-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-aside-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-aside-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-aside-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-aside-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-aside-title-case, none);\n --_s-title-tracking: var(--wzl-stance-aside-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-aside-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='advanced'] {\n --_s-surface: var(--wzl-stance-advanced-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-advanced-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-advanced-border-style, solid);\n --_s-border-width: var(--wzl-stance-advanced-border-width, 1px);\n --_s-radius: var(--wzl-stance-advanced-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-advanced-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-advanced-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-advanced-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-advanced-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-advanced-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-advanced-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-advanced-title-case, none);\n --_s-title-tracking: var(--wzl-stance-advanced-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-advanced-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='debug'] {\n --_s-surface: var(--wzl-stance-debug-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-debug-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-debug-border-style, solid);\n --_s-border-width: var(--wzl-stance-debug-border-width, 1px);\n --_s-radius: var(--wzl-stance-debug-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-debug-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-debug-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-debug-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-debug-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-debug-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-debug-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-debug-title-case, none);\n --_s-title-tracking: var(--wzl-stance-debug-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-debug-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='danger'] {\n --_s-surface: var(--wzl-stance-danger-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-danger-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-danger-border-style, solid);\n --_s-border-width: var(--wzl-stance-danger-border-width, 1px);\n --_s-radius: var(--wzl-stance-danger-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-danger-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-danger-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-danger-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-danger-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-danger-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-danger-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-danger-title-case, none);\n --_s-title-tracking: var(--wzl-stance-danger-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-danger-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='notice'] {\n --_s-surface: var(--wzl-stance-notice-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-notice-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-notice-border-style, solid);\n --_s-border-width: var(--wzl-stance-notice-border-width, 1px);\n --_s-radius: var(--wzl-stance-notice-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-notice-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-notice-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-notice-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-notice-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-notice-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-notice-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-notice-title-case, none);\n --_s-title-tracking: var(--wzl-stance-notice-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-notice-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='important'] {\n --_s-surface: var(--wzl-stance-important-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-important-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-important-border-style, solid);\n --_s-border-width: var(--wzl-stance-important-border-width, 1px);\n --_s-radius: var(--wzl-stance-important-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-important-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-important-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-important-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-important-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-important-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-important-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-important-title-case, none);\n --_s-title-tracking: var(--wzl-stance-important-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-important-title-color, var(--wzl-fg));\n}\n\n.popover[data-stance='preview'] {\n --_s-surface: var(--wzl-stance-preview-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-preview-border-color, var(--wzl-accent-strong));\n --_s-border-style: var(--wzl-stance-preview-border-style, solid);\n --_s-border-width: var(--wzl-stance-preview-border-width, 1px);\n --_s-radius: var(--wzl-stance-preview-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-preview-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-preview-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-preview-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-preview-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-preview-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-preview-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-preview-title-case, none);\n --_s-title-tracking: var(--wzl-stance-preview-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-preview-title-color, var(--wzl-fg));\n}\n\n.popover {\n --_s-fill: var(--_s-surface);\n}\n\n.popover[data-tone],\n.popover[data-stance] {\n --_s-fill: color-mix(in oklab, var(--_s-tone) var(--_s-tone-mix), var(--_s-surface));\n}\n\n.popover[data-tone] {\n --wzl-surface-sunken: oklch(from var(--_s-fill) calc(l - 0.06) c h);\n}\n\n.popover[data-tone] {\n --wzl-accent: var(--_s-accent);\n --wzl-accent-base: var(--_s-accent);\n --wzl-accent-strong: color-mix(in oklab, var(--_s-accent) 70%, var(--wzl-fg));\n --wzl-accent-soft: color-mix(in oklab, var(--_s-accent) 45%, var(--wzl-surface));\n --wzl-accent-hover: var(--wzl-accent-strong);\n --wzl-accent-fg: var(--wzl-accent-strong);\n --wzl-focus-ring: var(--wzl-accent-strong);\n}\n\n/* END GENERATED stance rules: callout */\n\n.arrow svg {\n display: block;\n fill: var(--_s-fill);\n stroke: var(--_s-border-color);\n stroke-width: 1;\n}\n\n.arrow[data-placement='bottom'] svg {\n transform: rotate(180deg);\n}\n\n.arrow[data-placement='left'] svg {\n transform: rotate(-90deg);\n}\n\n.arrow[data-placement='right'] svg {\n transform: rotate(90deg);\n}\n\n.dialog {\n outline: none;\n max-height: inherit;\n display: flex;\n flex-direction: column;\n}\n\n.header {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-5) var(--wzl-space-6) 0;\n}\n\n.title {\n margin: 0;\n flex: 1;\n font-family: var(--_s-title-font);\n font-size: var(--_s-title-size);\n font-weight: var(--_s-title-weight);\n text-transform: var(--_s-title-case);\n letter-spacing: var(--_s-title-tracking);\n color: var(--_s-title-color);\n}\n\n.body {\n padding: var(--wzl-space-4) var(--wzl-space-6) var(--wzl-space-5);\n font-size: var(--wzl-font-size);\n line-height: 1.4;\n overflow-y: auto;\n}\n\n.footer {\n display: flex;\n justify-content: flex-end;\n gap: var(--wzl-space-4);\n padding: 0 var(--wzl-space-6) var(--wzl-space-5);\n}\n","import { useCallback, useEffect, useId, useRef, type ReactNode, type RefObject } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useLatest } from '@weasel-js/core';\nimport {\n DialogTrigger,\n Popover as RACPopover,\n OverlayArrow,\n Dialog as RACDialog,\n Heading,\n type PopoverProps as RACPopoverProps,\n} from 'react-aria-components';\nimport { useOverlayPortal, type OverlayPortalProps, type WithoutPortalTarget } from '../../overlays/portalHost';\nimport { CloseButton } from '../CloseButton';\nimport { type StanceProps, useStance } from '../stance';\nimport s from './Callout.module.css';\n\n/**\n * Composition wrapper for press-to-open callouts:\n * `<CalloutTrigger><Pressable>…</Pressable><Callout>…</Callout></CalloutTrigger>`.\n * Re-exported RAC DialogTrigger — non-RAC trigger elements must be wrapped\n * in `<Pressable>` from react-aria-components.\n * In composed mode, put `defaultOpen` on `CalloutTrigger`, not `Callout` —\n * RAC detaches to local open state on the trigger, not the popover.\n */\nexport { DialogTrigger as CalloutTrigger };\n\n/** Props for {@link Callout}, on top of React Aria's `Popover` props. */\nexport type CalloutProps = Omit<\n WithoutPortalTarget<RACPopoverProps>,\n 'children' | 'className' | 'isNonModal' | 'triggerRef'\n> &\n OverlayPortalProps &\n StanceProps & {\n children?: ReactNode;\n className?: string;\n /** Optional heading rendered above the body. */\n title?: ReactNode;\n /** Footer slot — typically action buttons. */\n footer?: ReactNode;\n /**\n * `true` — blocks interaction with the rest of the app until dismissed;\n * inner dialog is `role=\"alertdialog\"`. `false` (default) — non-blocking:\n * the app stays interactive; Esc / outside click / close button dismiss.\n */\n modal?: boolean;\n /**\n * Show the close button. Defaults to `!modal`. In programmatic\n * `triggerRef`/`anchorRect` modes the close button needs controlled open\n * (`isOpen` + `onOpenChange`); with only `defaultOpen` it has no open-state\n * setter to call and cannot close.\n */\n showCloseButton?: boolean;\n /**\n * The user asked for this callout to go away — the close button or Escape.\n *\n * Distinct from `onOpenChange`, which a non-modal popover *also* fires when\n * interaction or focus merely leaves it. On a canvas that's every click on\n * the artwork, so a consumer that pins `isOpen` and treats `onOpenChange`\n * as dismissal retires messages nobody read. Use this instead: it fires\n * only on a deliberate act, and never on incidental focus loss.\n */\n onDismiss?: () => void;\n /** Anchor to an arbitrary element (programmatic use, with `isOpen`). */\n triggerRef?: RefObject<Element | null>;\n /**\n * Anchor to a client-coordinate rect — e.g. a scene node's on-screen box.\n * The callout re-anchors whenever this rect changes, so a consumer that\n * recomputes it on pan, zoom, or scene edits keeps the arrow on its target.\n * Takes precedence over `triggerRef`.\n */\n anchorRect?: { x: number; y: number; width: number; height: number };\n };\n\n/**\n * Anchored callout with an arrow pointing at its source — a trigger\n * element, an arbitrary `triggerRef`, or a client-space `anchorRect`.\n * Wraps React Aria Popover + Dialog; positioning, collision flipping,\n * dismissal, and focus behavior come from the underlying primitives.\n */\nexport function Callout(props: CalloutProps) {\n const {\n children,\n className,\n title,\n footer,\n stance = 'notice',\n tone,\n modal = false,\n showCloseButton,\n onDismiss,\n triggerRef,\n anchorRect,\n placement = 'top',\n offset = 12,\n maxHeight = 400,\n onOpenChange,\n shouldCloseOnInteractOutside,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n portalContainer,\n ...rest\n } = props;\n const anchorRef = useRef<HTMLSpanElement>(null);\n const stanced = useStance({ stance, tone });\n const { anchor: portalAnchor, portalProps } = useOverlayPortal(portalContainer);\n const showClose = showCloseButton ?? !modal;\n // Escape is a dismissal like the close button is. It can't ride on a React `onKeyDown`:\n // RAC's Dialog runs its props through filterDOMProps, which drops handlers\n // it doesn't know, so the listener goes on the section itself. RAC's own\n // Escape handling is untouched — this only adds the signal.\n const onDismissRef = useLatest(onDismiss);\n const escapeListener = useRef((e: KeyboardEvent) => {\n if (e.key === 'Escape') onDismissRef.current?.();\n });\n const listeningTo = useRef<HTMLElement | null>(null);\n const dialogRef = useCallback((node: HTMLElement | null) => {\n listeningTo.current?.removeEventListener('keydown', escapeListener.current);\n listeningTo.current = node;\n node?.addEventListener('keydown', escapeListener.current);\n }, []);\n const titleId = useId();\n // RAC positions on open and recomputes on scroll, resize, and a\n // ResizeObserver on the anchor — none of which fire when `anchorRect` is\n // merely *translated*, as it is when a consumer tracks a scene node across a\n // pan. (Zoom happens to work, since scaling also changes the anchor's size.)\n // Nudging RAC's own resize listener is the supported way to make it\n // recompute; there's no public updatePosition on Popover.\n const hasAnchorRect = anchorRect !== undefined;\n useEffect(() => {\n if (!hasAnchorRect || typeof window === 'undefined') return;\n window.dispatchEvent(new Event('resize'));\n }, [hasAnchorRect, anchorRect?.x, anchorRect?.y, anchorRect?.width, anchorRect?.height]);\n // RAC's popover role-heuristic misses alertdialog; label the outer role\n // it stamps. Upstream: react-spectrum Popover.mjs querySelector('[role=dialog]').\n const popoverAriaLabelledby =\n modal && title !== undefined ? titleId : ariaLabelledby;\n const popoverAriaLabel = modal ? ariaLabel : undefined;\n return (\n <>\n {portalAnchor}\n {/* Harmless while closed — RAC reads the ref only when the popover is open. */}\n {anchorRect !== undefined &&\n createPortal(\n <span\n ref={anchorRef}\n data-callout-anchor=\"\"\n className={s.anchor}\n aria-hidden=\"true\"\n // Dynamic geometry — inline style is the mechanism here, not styling.\n style={{\n left: anchorRect.x,\n top: anchorRect.y,\n width: anchorRect.width,\n height: anchorRect.height,\n }}\n />,\n document.body,\n )}\n <RACPopover\n {...rest}\n triggerRef={anchorRect !== undefined ? anchorRef : triggerRef}\n isNonModal={!modal}\n placement={placement}\n offset={offset}\n maxHeight={maxHeight}\n onOpenChange={onOpenChange}\n shouldCloseOnInteractOutside={\n shouldCloseOnInteractOutside ?? (modal ? () => false : undefined)\n }\n aria-label={popoverAriaLabel}\n aria-labelledby={popoverAriaLabelledby}\n className={[s.popover, className].filter(Boolean).join(' ')}\n {...stanced}\n data-weasel-overlay=\"\"\n {...portalProps}\n >\n <OverlayArrow className={s.arrow}>\n <svg width={12} height={12} viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path d=\"M0 0 L6 6 L12 0\" />\n </svg>\n </OverlayArrow>\n <RACDialog\n role={modal ? 'alertdialog' : 'dialog'}\n className={s.dialog}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n ref={dialogRef}\n >\n {({ close }) => (\n <>\n {(title !== undefined || showClose) && (\n <header className={s.header}>\n {title !== undefined && (\n <Heading id={titleId} slot=\"title\" className={s.title}>\n {title}\n </Heading>\n )}\n {showClose && (\n <CloseButton\n ariaLabel=\"Close callout\"\n onClick={() => {\n // `close()` resolves OverlayTriggerStateContext, only\n // provided by DialogTrigger (composed mode). In\n // triggerRef/anchorRect modes there is no such\n // context, so `close()` is a no-op there — the\n // controlled-open fallback below does the work.\n close();\n onOpenChange?.(false);\n onDismiss?.();\n }}\n />\n )}\n </header>\n )}\n <div className={s.body}>{children}</div>\n {footer !== undefined && <footer className={s.footer}>{footer}</footer>}\n </>\n )}\n </RACDialog>\n </RACPopover>\n </>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./checkbox.module-DLQV9tMX.js";
1
+ import { t as e } from "./checkbox.module-Dcx8ILgR.js";
2
2
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
3
  import { forwardRef as r, useEffect as i, useRef as a, useState as o } from "react";
4
4
  var s = {
@@ -34,4 +34,4 @@ var s = {
34
34
  //#endregion
35
35
  export { c as t };
36
36
 
37
- //# sourceMappingURL=Checkbox-DFn-x0JO.js.map
37
+ //# sourceMappingURL=Checkbox-d4IfhiXh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox-DFn-x0JO.js","names":["s","shared","checkbox_module_default","Checkbox_module_default","Checkbox","forwardRef","rest","props","uncontrolled","setUncontrolled","useState","defaultSelected","checked","isSelected","input","useRef","useEffect","isIndeterminate","className","isDisabled","isRequired","isInvalid","isReadOnly","onChange","children"],"sources":["../../src/components/Checkbox/Checkbox.module.css","../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["/* The box itself is `checkbox.module.css`, shared with the property rows; this\n is only the label around it. */\n.checkbox {\n display: inline-flex;\n align-items: center;\n gap: var(--wzl-space-4);\n cursor: pointer;\n font-family: var(--wzl-font-ui);\n font-size: var(--wzl-font-size);\n color: var(--wzl-fg);\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* The box dims itself on :disabled, so only the text is dimmed here. */\n.checkbox[data-disabled] {\n cursor: not-allowed;\n}\n\n.checkbox[data-disabled] .label {\n opacity: 0.5;\n}\n\n.label {\n line-height: 1.2;\n}\n","import {\n forwardRef,\n useEffect,\n useRef,\n useState,\n type FocusEventHandler,\n type ReactNode,\n type Ref,\n} from 'react';\nimport shared from '../checkbox.module.css';\nimport s from './Checkbox.module.css';\n\n/** Props for {@link Checkbox}. The label is passed as children. */\nexport type CheckboxProps = {\n children?: ReactNode;\n className?: string;\n /** Controlled selection. */\n isSelected?: boolean;\n /** Initial selection when uncontrolled. */\n defaultSelected?: boolean;\n onChange?: (isSelected: boolean) => void;\n /** Draws the mixed mark; the input's `indeterminate` is set to match. */\n isIndeterminate?: boolean;\n isDisabled?: boolean;\n /** Focusable and announced, but a click does not change it. */\n isReadOnly?: boolean;\n isInvalid?: boolean;\n isRequired?: boolean;\n name?: string;\n value?: string;\n id?: string;\n autoFocus?: boolean;\n onFocus?: FocusEventHandler<HTMLInputElement>;\n onBlur?: FocusEventHandler<HTMLInputElement>;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n};\n\n/**\n * Single checkbox: a native `<input type=\"checkbox\">` inside a `<label>`, the\n * box drawn by the shared checkbox skin. Supports indeterminate via\n * `isIndeterminate`. The label is supplied as children.\n */\nexport const Checkbox = forwardRef(function Checkbox(\n props: CheckboxProps,\n ref: Ref<HTMLLabelElement>,\n) {\n const {\n children,\n className,\n isSelected,\n defaultSelected = false,\n onChange,\n isIndeterminate = false,\n isDisabled,\n isReadOnly,\n isInvalid,\n isRequired,\n ...rest\n } = props;\n const [uncontrolled, setUncontrolled] = useState(defaultSelected);\n const checked = isSelected ?? uncontrolled;\n const input = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (input.current) input.current.indeterminate = isIndeterminate;\n });\n return (\n <label\n ref={ref}\n className={[s.checkbox, className].filter(Boolean).join(' ')}\n data-disabled={isDisabled || undefined}\n >\n <input\n {...rest}\n ref={input}\n type=\"checkbox\"\n className={shared.checkbox}\n checked={checked}\n disabled={isDisabled}\n required={isRequired}\n aria-invalid={isInvalid || undefined}\n aria-readonly={isReadOnly || undefined}\n onChange={(e) => {\n if (isReadOnly) return;\n if (isSelected === undefined) setUncontrolled(e.target.checked);\n onChange?.(e.target.checked);\n }}\n />\n {children !== undefined && <span className={s.label}>{children}</span>}\n </label>\n );\n});\n"],"mappings":";;;;;;GC4CaI,IAAWC,EAAW,SACjC,GACA,GACA;CACA,IAAM,EACJ,aACA,cACA,eACA,qBAAkB,IAClB,aACA,qBAAkB,IAClB,eACA,eACA,cACA,eACA,GAAGC,MACDC,GACE,CAACC,GAAcC,KAAmBC,EAASC,CAAe,GAC1DC,IAAUC,KAAcL,GACxBM,IAAQC,EAAyB,IAAI;CAI3C,OAHAC,QAAgB;EACd,AAAIF,EAAM,YAAS,EAAM,QAAQ,gBAAgBG;CACnD,CAAC,GAEC,kBAAC,SAAD;EACO;EACL,WAAW,CAACjB,EAAE,UAAUkB,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAC3D,iBAAeC,KAAc,KAAA;EAH/B,UAAA,CAKE,kBAAC,SAAD;GACE,GAAIb;GACJ,KAAKQ;GACL,MAAK;GACL,WAAWb,EAAO;GACT;GACT,UAAUkB;GACV,UAAUC;GACV,gBAAcC,KAAa,KAAA;GAC3B,iBAAeC,KAAc,KAAA;GAC7B,WAAW,MAAM;IACf,AAAIA,MACAT,MAAe,KAAA,KAAWJ,EAAgB,EAAE,OAAO,OAAO,GAC9Dc,IAAW,EAAE,OAAO,OAAO;GAC7B;EACD,CAAA,GACAC,MAAa,KAAA,KAAa,kBAAC,QAAD;GAAM,WAAWxB,EAAE;GAAQ;EAAe,CAAA,CAChE;;AAEX,CAAC"}
1
+ {"version":3,"file":"Checkbox-d4IfhiXh.js","names":["s","shared","checkbox_module_default","Checkbox_module_default","Checkbox","forwardRef","rest","props","uncontrolled","setUncontrolled","useState","defaultSelected","checked","isSelected","input","useRef","useEffect","isIndeterminate","className","isDisabled","isRequired","isInvalid","isReadOnly","onChange","children"],"sources":["../../src/components/Checkbox/Checkbox.module.css","../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["/* The box itself is `checkbox.module.css`, shared with the property rows; this\n is only the label around it. */\n.checkbox {\n display: inline-flex;\n align-items: center;\n gap: var(--wzl-space-4);\n cursor: pointer;\n font-family: var(--wzl-font-ui);\n font-size: var(--wzl-font-size);\n color: var(--wzl-fg);\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* The box dims itself on :disabled, so only the text is dimmed here. */\n.checkbox[data-disabled] {\n cursor: not-allowed;\n}\n\n.checkbox[data-disabled] .label {\n opacity: 0.5;\n}\n\n.label {\n line-height: 1.2;\n}\n","import {\n forwardRef,\n useEffect,\n useRef,\n useState,\n type FocusEventHandler,\n type ReactNode,\n type Ref,\n} from 'react';\nimport shared from '../checkbox.module.css';\nimport s from './Checkbox.module.css';\n\n/** Props for {@link Checkbox}. The label is passed as children. */\nexport type CheckboxProps = {\n children?: ReactNode;\n className?: string;\n /** Controlled selection. */\n isSelected?: boolean;\n /** Initial selection when uncontrolled. */\n defaultSelected?: boolean;\n onChange?: (isSelected: boolean) => void;\n /** Draws the mixed mark; the input's `indeterminate` is set to match. */\n isIndeterminate?: boolean;\n isDisabled?: boolean;\n /** Focusable and announced, but a click does not change it. */\n isReadOnly?: boolean;\n isInvalid?: boolean;\n isRequired?: boolean;\n name?: string;\n value?: string;\n id?: string;\n autoFocus?: boolean;\n onFocus?: FocusEventHandler<HTMLInputElement>;\n onBlur?: FocusEventHandler<HTMLInputElement>;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n};\n\n/**\n * Single checkbox: a native `<input type=\"checkbox\">` inside a `<label>`, the\n * box drawn by the shared checkbox skin. Supports indeterminate via\n * `isIndeterminate`. The label is supplied as children.\n */\nexport const Checkbox = forwardRef(function Checkbox(\n props: CheckboxProps,\n ref: Ref<HTMLLabelElement>,\n) {\n const {\n children,\n className,\n isSelected,\n defaultSelected = false,\n onChange,\n isIndeterminate = false,\n isDisabled,\n isReadOnly,\n isInvalid,\n isRequired,\n ...rest\n } = props;\n const [uncontrolled, setUncontrolled] = useState(defaultSelected);\n const checked = isSelected ?? uncontrolled;\n const input = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (input.current) input.current.indeterminate = isIndeterminate;\n });\n return (\n <label\n ref={ref}\n className={[s.checkbox, className].filter(Boolean).join(' ')}\n data-disabled={isDisabled || undefined}\n >\n <input\n {...rest}\n ref={input}\n type=\"checkbox\"\n className={shared.checkbox}\n checked={checked}\n disabled={isDisabled}\n required={isRequired}\n aria-invalid={isInvalid || undefined}\n aria-readonly={isReadOnly || undefined}\n onChange={(e) => {\n if (isReadOnly) return;\n if (isSelected === undefined) setUncontrolled(e.target.checked);\n onChange?.(e.target.checked);\n }}\n />\n {children !== undefined && <span className={s.label}>{children}</span>}\n </label>\n );\n});\n"],"mappings":";;;;;;GC4CaI,IAAWC,EAAW,SACjC,GACA,GACA;CACA,IAAM,EACJ,aACA,cACA,eACA,qBAAkB,IAClB,aACA,qBAAkB,IAClB,eACA,eACA,cACA,eACA,GAAGC,MACDC,GACE,CAACC,GAAcC,KAAmBC,EAASC,CAAe,GAC1DC,IAAUC,KAAcL,GACxBM,IAAQC,EAAyB,IAAI;CAI3C,OAHAC,QAAgB;EACd,AAAIF,EAAM,YAAS,EAAM,QAAQ,gBAAgBG;CACnD,CAAC,GAEC,kBAAC,SAAD;EACO;EACL,WAAW,CAACjB,EAAE,UAAUkB,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAC3D,iBAAeC,KAAc,KAAA;EAH/B,UAAA,CAKE,kBAAC,SAAD;GACE,GAAIb;GACJ,KAAKQ;GACL,MAAK;GACL,WAAWb,EAAO;GACT;GACT,UAAUkB;GACV,UAAUC;GACV,gBAAcC,KAAa,KAAA;GAC3B,iBAAeC,KAAc,KAAA;GAC7B,WAAW,MAAM;IACf,AAAIA,MACAT,MAAe,KAAA,KAAWJ,EAAgB,EAAE,OAAO,OAAO,GAC9Dc,IAAW,EAAE,OAAO,OAAO;GAC7B;EACD,CAAA,GACAC,MAAa,KAAA,KAAa,kBAAC,QAAD;GAAM,WAAWxB,EAAE;GAAQ;EAAe,CAAA,CAChE;;AAEX,CAAC"}
@@ -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 { t } from "./segmentTooltip-CGxCOWNz.js";
3
3
  import { jsx as n } from "react/jsx-runtime";
4
4
  import { forwardRef as r } from "react";
@@ -23,4 +23,4 @@ var i = { close: "_close_1xm1r_3" }, a = r(function({ ariaLabel: r, onClick: a,
23
23
  //#endregion
24
24
  export { a as t };
25
25
 
26
- //# sourceMappingURL=CloseButton-BmNmRVtb.js.map
26
+ //# sourceMappingURL=CloseButton-wb7Or5Eg.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CloseButton-BmNmRVtb.js","names":["s","Icon","CloseButton_module_default","CloseButton","forwardRef","SegmentTooltip","tooltip","className","ariaLabel"],"sources":["../../src/components/CloseButton/CloseButton.module.css","../../src/components/CloseButton/CloseButton.tsx"],"sourcesContent":["/* Sets its own height: a host's control-height default for bare buttons\n (labkit's) would otherwise stretch the square. */\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--wzl-icon-button-size);\n height: var(--wzl-icon-button-size);\n padding: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: var(--wzl-radius-sm);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n color: var(--wzl-fg-muted);\n cursor: pointer;\n}\n\n.close:hover:not(:disabled) {\n background: var(--wzl-surface-hover);\n border-color: transparent;\n color: var(--wzl-fg);\n}\n\n.close:active:not(:disabled) {\n background: var(--wzl-surface-pressed);\n}\n\n.close:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: 1px;\n}\n\n.close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport { Icon } from '../../icons/Icon';\nimport { SegmentTooltip } from '../segmentTooltip';\nimport s from './CloseButton.module.css';\n\n/** Props for {@link CloseButton}. */\nexport interface CloseButtonProps {\n /** Accessible name — what the press closes or removes: `Close dialog`,\n * `Remove Glow`. Required, since the button shows only a glyph. */\n ariaLabel: string;\n onClick?: ButtonHTMLAttributes<HTMLButtonElement>['onClick'];\n /** Kit tooltip content. None by default. */\n tooltip?: ReactNode;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The kit's close / dismiss / remove button: the `close` glyph at chrome size\n * in a square `--wzl-icon-button-size` target. Kit components that dismiss a\n * surface or remove a row draw their × with this.\n *\n * `ref` forwards to the underlying `<button>`.\n */\nexport const CloseButton = forwardRef(function CloseButton(\n { ariaLabel, onClick, tooltip, disabled, className }: CloseButtonProps,\n ref: Ref<HTMLButtonElement>,\n) {\n return (\n <SegmentTooltip content={tooltip} disabled={disabled}>\n <button\n ref={ref}\n type=\"button\"\n className={className ? `${s.close} ${className}` : s.close}\n aria-label={ariaLabel}\n disabled={disabled}\n onClick={onClick}\n >\n <Icon name=\"close\" size={16} />\n </button>\n </SegmentTooltip>\n );\n});\n"],"mappings":";;;;qCCwBaG,IAAcC,EAAW,SACpC,EAAE,cAAW,YAAS,YAAS,aAAU,gBACzC,GACA;CACA,OACE,kBAACC,GAAD;EAAgB,SAASC;EAAmB;EAC1C,UAAA,kBAAC,UAAD;GACO;GACL,MAAK;GACL,WAAWC,IAAY,GAAGP,EAAE,MAAM,GAAGO,MAAcP,EAAE;GACrD,cAAYQ;GACF;GACD;GAET,UAAA,kBAACP,GAAD;IAAM,MAAK;IAAQ,MAAM;GAAK,CAAA;EACxB,CAAA;CACM,CAAA;AAEpB,CAAC"}
1
+ {"version":3,"file":"CloseButton-wb7Or5Eg.js","names":["s","Icon","CloseButton_module_default","CloseButton","forwardRef","SegmentTooltip","tooltip","className","ariaLabel"],"sources":["../../src/components/CloseButton/CloseButton.module.css","../../src/components/CloseButton/CloseButton.tsx"],"sourcesContent":["/* Sets its own height: a host's control-height default for bare buttons\n (labkit's) would otherwise stretch the square. */\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--wzl-icon-button-size);\n height: var(--wzl-icon-button-size);\n padding: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: var(--wzl-radius-sm);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n color: var(--wzl-fg-muted);\n cursor: pointer;\n}\n\n.close:hover:not(:disabled) {\n background: var(--wzl-surface-hover);\n border-color: transparent;\n color: var(--wzl-fg);\n}\n\n.close:active:not(:disabled) {\n background: var(--wzl-surface-pressed);\n}\n\n.close:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: 1px;\n}\n\n.close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport { Icon } from '../../icons/Icon';\nimport { SegmentTooltip } from '../segmentTooltip';\nimport s from './CloseButton.module.css';\n\n/** Props for {@link CloseButton}. */\nexport interface CloseButtonProps {\n /** Accessible name — what the press closes or removes: `Close dialog`,\n * `Remove Glow`. Required, since the button shows only a glyph. */\n ariaLabel: string;\n onClick?: ButtonHTMLAttributes<HTMLButtonElement>['onClick'];\n /** Kit tooltip content. None by default. */\n tooltip?: ReactNode;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The kit's close / dismiss / remove button: the `close` glyph at chrome size\n * in a square `--wzl-icon-button-size` target. Kit components that dismiss a\n * surface or remove a row draw their × with this.\n *\n * `ref` forwards to the underlying `<button>`.\n */\nexport const CloseButton = forwardRef(function CloseButton(\n { ariaLabel, onClick, tooltip, disabled, className }: CloseButtonProps,\n ref: Ref<HTMLButtonElement>,\n) {\n return (\n <SegmentTooltip content={tooltip} disabled={disabled}>\n <button\n ref={ref}\n type=\"button\"\n className={className ? `${s.close} ${className}` : s.close}\n aria-label={ariaLabel}\n disabled={disabled}\n onClick={onClick}\n >\n <Icon name=\"close\" size={16} />\n </button>\n </SegmentTooltip>\n );\n});\n"],"mappings":";;;;qCCwBaG,IAAcC,EAAW,SACpC,EAAE,cAAW,YAAS,YAAS,aAAU,gBACzC,GACA;CACA,OACE,kBAACC,GAAD;EAAgB,SAASC;EAAmB;EAC1C,UAAA,kBAAC,UAAD;GACO;GACL,MAAK;GACL,WAAWC,IAAY,GAAGP,EAAE,MAAM,GAAGO,MAAcP,EAAE;GACrD,cAAYQ;GACF;GACD;GAET,UAAA,kBAACP,GAAD;IAAM,MAAK;IAAQ,MAAM;GAAK,CAAA;EACxB,CAAA;CACM,CAAA;AAEpB,CAAC"}
@@ -1,5 +1,5 @@
1
- import { $ as e, Q as t, Z as n } from "./icons-Dr2-r30x.js";
2
- import { t as r } from "./ToggleBar-Z2jZiguF.js";
1
+ import { $ as e, Q as t, Z as n } from "./icons-CofIOTiI.js";
2
+ import { t as r } from "./ToggleBar-BZ4Gk1IU.js";
3
3
  import { jsx as i } from "react/jsx-runtime";
4
4
  //#region src/components/ColorModeControl/ColorModeControl.tsx
5
5
  function a(r) {
@@ -44,4 +44,4 @@ function s({ value: e, onChange: t, ariaLabel: n = "Color mode", size: a, varian
44
44
  //#endregion
45
45
  export { s as t };
46
46
 
47
- //# sourceMappingURL=ColorModeControl-DaVJ-SyX.js.map
47
+ //# sourceMappingURL=ColorModeControl-DET6Itwq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ColorModeControl-DaVJ-SyX.js","names":["ModeLightIcon","ModeDarkIcon","ModeAutoIcon","ToggleBar","items","glyph","ITEMS","ColorModeControl","size","next","onChange"],"sources":["../../src/components/ColorModeControl/ColorModeControl.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { ColorModePreference } from '@weasel-js/theme';\nimport { ModeAutoIcon, ModeDarkIcon, ModeLightIcon } from '../../icons';\nimport { ToggleBar, type ToggleBarItem, type ToggleBarSize, type ToggleBarVariant } from '../ToggleBar/ToggleBar';\n\n/** Props for {@link ColorModeControl}. */\nexport interface ColorModeControlProps {\n value: ColorModePreference;\n onChange: (next: ColorModePreference) => void;\n /** Accessible name of the group. Defaults to `'Color mode'`. */\n ariaLabel?: string;\n size?: ToggleBarSize;\n variant?: ToggleBarVariant;\n className?: string;\n}\n\nfunction items(glyph: number): ToggleBarItem<ColorModePreference>[] {\n return [\n { value: 'auto', label: <ModeAutoIcon size={glyph} />, ariaLabel: 'Auto', tooltip: 'Auto — follow the system' },\n { value: 'light', label: <ModeLightIcon size={glyph} />, ariaLabel: 'Light', tooltip: 'Light' },\n { value: 'dark', label: <ModeDarkIcon size={glyph} />, ariaLabel: 'Dark', tooltip: 'Dark' },\n ];\n}\n\nconst ITEMS = { sm: items(12), md: items(14) };\n\n/**\n * The Auto / Light / Dark choice, as a three-way radiogroup of mode glyphs.\n * Controlled: pair it with `useColorModePreference` from\n * `@weasel-js/theme/react` and put the hook's resolved `mode` in the\n * `ThemeProvider` selection.\n */\nexport function ColorModeControl({\n value,\n onChange,\n ariaLabel = 'Color mode',\n size,\n variant,\n className,\n}: ColorModeControlProps): ReactElement {\n return (\n <ToggleBar\n items={ITEMS[size ?? 'md']}\n value={value}\n onChange={(next) => {\n if (next) onChange(next);\n }}\n ariaLabel={ariaLabel}\n size={size}\n variant={variant}\n className={className}\n />\n );\n}\n"],"mappings":";;;;AAgBA,SAASI,EAAM,GAAqD;CAClE,OAAO;EACL;GAAE,OAAO;GAAQ,OAAO,kBAACF,GAAD,EAAc,MAAMG,EAAQ,CAAA;GAAG,WAAW;GAAQ,SAAS;EAA2B;EAC9G;GAAE,OAAO;GAAS,OAAO,kBAACL,GAAD,EAAe,MAAMK,EAAQ,CAAA;GAAG,WAAW;GAAS,SAAS;EAAQ;EAC9F;GAAE,OAAO;GAAQ,OAAO,kBAACJ,GAAD,EAAc,MAAMI,EAAQ,CAAA;GAAG,WAAW;GAAQ,SAAS;EAAO;CAC5F;AACF;AAEA,IAAMC,IAAQ;CAAE,IAAIF,EAAM,EAAE;CAAG,IAAIA,EAAM,EAAE;AAAE;AAQ7C,SAAgBG,EAAiB,EAC/B,UACA,aACA,eAAY,cACZ,SACA,YACA,gBACsC;CACtC,OACE,kBAACJ,GAAD;EACE,OAAOG,EAAME,KAAQ;EACd;EACP,WAAW,MAAS;GAClB,AAAIC,KAAMC,EAASD,CAAI;EACzB;EACW;EACL;EACG;EACE;CACZ,CAAA;AAEL"}
1
+ {"version":3,"file":"ColorModeControl-DET6Itwq.js","names":["ModeLightIcon","ModeDarkIcon","ModeAutoIcon","ToggleBar","items","glyph","ITEMS","ColorModeControl","size","next","onChange"],"sources":["../../src/components/ColorModeControl/ColorModeControl.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { ColorModePreference } from '@weasel-js/theme';\nimport { ModeAutoIcon, ModeDarkIcon, ModeLightIcon } from '../../icons';\nimport { ToggleBar, type ToggleBarItem, type ToggleBarSize, type ToggleBarVariant } from '../ToggleBar/ToggleBar';\n\n/** Props for {@link ColorModeControl}. */\nexport interface ColorModeControlProps {\n value: ColorModePreference;\n onChange: (next: ColorModePreference) => void;\n /** Accessible name of the group. Defaults to `'Color mode'`. */\n ariaLabel?: string;\n size?: ToggleBarSize;\n variant?: ToggleBarVariant;\n className?: string;\n}\n\nfunction items(glyph: number): ToggleBarItem<ColorModePreference>[] {\n return [\n { value: 'auto', label: <ModeAutoIcon size={glyph} />, ariaLabel: 'Auto', tooltip: 'Auto — follow the system' },\n { value: 'light', label: <ModeLightIcon size={glyph} />, ariaLabel: 'Light', tooltip: 'Light' },\n { value: 'dark', label: <ModeDarkIcon size={glyph} />, ariaLabel: 'Dark', tooltip: 'Dark' },\n ];\n}\n\nconst ITEMS = { sm: items(12), md: items(14) };\n\n/**\n * The Auto / Light / Dark choice, as a three-way radiogroup of mode glyphs.\n * Controlled: pair it with `useColorModePreference` from\n * `@weasel-js/theme/react` and put the hook's resolved `mode` in the\n * `ThemeProvider` selection.\n */\nexport function ColorModeControl({\n value,\n onChange,\n ariaLabel = 'Color mode',\n size,\n variant,\n className,\n}: ColorModeControlProps): ReactElement {\n return (\n <ToggleBar\n items={ITEMS[size ?? 'md']}\n value={value}\n onChange={(next) => {\n if (next) onChange(next);\n }}\n ariaLabel={ariaLabel}\n size={size}\n variant={variant}\n className={className}\n />\n );\n}\n"],"mappings":";;;;AAgBA,SAASI,EAAM,GAAqD;CAClE,OAAO;EACL;GAAE,OAAO;GAAQ,OAAO,kBAACF,GAAD,EAAc,MAAMG,EAAQ,CAAA;GAAG,WAAW;GAAQ,SAAS;EAA2B;EAC9G;GAAE,OAAO;GAAS,OAAO,kBAACL,GAAD,EAAe,MAAMK,EAAQ,CAAA;GAAG,WAAW;GAAS,SAAS;EAAQ;EAC9F;GAAE,OAAO;GAAQ,OAAO,kBAACJ,GAAD,EAAc,MAAMI,EAAQ,CAAA;GAAG,WAAW;GAAQ,SAAS;EAAO;CAC5F;AACF;AAEA,IAAMC,IAAQ;CAAE,IAAIF,EAAM,EAAE;CAAG,IAAIA,EAAM,EAAE;AAAE;AAQ7C,SAAgBG,EAAiB,EAC/B,UACA,aACA,eAAY,cACZ,SACA,YACA,gBACsC;CACtC,OACE,kBAACJ,GAAD;EACE,OAAOG,EAAME,KAAQ;EACd;EACP,WAAW,MAAS;GAClB,AAAIC,KAAMC,EAASD,CAAI;EACzB;EACW;EACL;EACG;EACE;CACZ,CAAA;AAEL"}
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./useReorderDragList-CStYKjHl.js";
2
- import { t } from "./Disclosure-Ch2KxYuB.js";
2
+ import { t } from "./Disclosure-CpWt87nO.js";
3
3
  import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
4
4
  import { Fragment as a, useId as o, useMemo as s, useState as c } from "react";
5
5
  var l = {
@@ -154,4 +154,4 @@ function f(u) {
154
154
  //#endregion
155
155
  export { f as t };
156
156
 
157
- //# sourceMappingURL=DataGrid-CmHJe57v.js.map
157
+ //# sourceMappingURL=DataGrid-B6IS9vUk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataGrid-CmHJe57v.js","names":["s","_Fragment","Fragment","useReorderDragList","Fragment$1","DataGrid_module_default","INTERACTIVE","fromControl","hit","DataGrid","props","sort","setSort","useState","defaultSort","ownExpanded","setOwnExpanded","defaultExpandedIds","expanded","expandedIds","detailIdBase","useId","toggleExpanded","next","id","onExpandedChange","sortedRows","useMemo","rows","col","columns","c","get","row","dir","av","a","bv","b","cycleSort","cur","columnId","drag","r","onReorder","dragEnabled","detailEnabled","renderDetail","colCount","cls","className","sortable","active","indicator","Fragment","empty","isDragging","target","expandable","rowExpandable","isExpanded","detail","detailId","rowCls","onRowClick","i","rowClassName","e","Disclosure","content"],"sources":["../../src/components/DataGrid/DataGrid.module.css","../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":[".grid {\n position: relative;\n width: 100%;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--wzl-font-size-sm);\n}\n\n.table th,\n.table td {\n text-align: left;\n padding: 3px var(--wzl-space-3);\n vertical-align: middle;\n}\n.numeric {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n}\n.table .numeric {\n text-align: end;\n}\n.table tbody tr {\n border-bottom: 1px solid var(--wzl-line-subtle);\n}\n\n.table th {\n font-weight: var(--wzl-font-weight-bold);\n color: var(--wzl-fg-muted);\n position: sticky;\n top: 0;\n background: var(--wzl-surface);\n z-index: 1;\n border-bottom: 1px solid var(--wzl-border);\n}\n\n.sortButton {\n all: unset;\n cursor: pointer;\n user-select: none;\n display: block;\n width: 100%;\n}\n.sortButton:hover { color: var(--wzl-fg); }\n.sortButton:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n.sortActive { color: var(--wzl-fg); }\n\n.empty {\n color: var(--wzl-fg-muted);\n font-style: italic;\n padding: var(--wzl-space-4) 0;\n text-align: center;\n}\n\n/* Drag-handle column. */\n.handleCol { width: 14px; }\n.handleCell {\n width: 14px;\n cursor: grab;\n color: var(--wzl-fg-muted);\n user-select: none;\n text-align: center;\n}\n.handleCell:active { cursor: grabbing; }\n\n.dragging { opacity: 0.4; }\n\n.dropBefore > td { box-shadow: inset 0 2px 0 0 var(--wzl-accent); }\n.dropAfter > td { box-shadow: inset 0 -2px 0 0 var(--wzl-accent); }\n\n/* Row activation (`onRowClick`). */\n.clickable { cursor: pointer; }\n.clickable:hover > td { background: var(--wzl-surface-hover); }\n.clickable:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n/* Disclosure column and the detail row it opens. */\n.detailCol,\n.detailCell {\n width: var(--wzl-control-h-sm);\n padding-inline: 0;\n text-align: center;\n}\n.table .detailCell { padding-block: 0; }\n.detailRow > td {\n padding: var(--wzl-space-2) var(--wzl-space-3) var(--wzl-space-3);\n background: var(--wzl-surface-sunken);\n}\n","/**\n * Lightweight sortable data grid. Use for inspector tables — action\n * registries, route maps, telemetry rows. Intentionally narrow:\n *\n * - Sortable columns (click header to cycle asc → desc → none)\n * - Custom cell render via per-column `render`\n * - Optional drag handles for row reordering (when `onReorder` is set)\n * - Per-row class, row activation, and expandable full-width detail rows\n *\n * Not: virtual scrolling, column resizing, multi-column sort, filtering,\n * inline editing. Reach for a real grid library when you need those.\n */\nimport { Fragment, useId, useMemo, useState } from 'react';\nimport type { KeyboardEvent, MouseEvent, ReactNode } from 'react';\nimport { useReorderDragList } from '../../useReorderDragList';\nimport { Disclosure } from '../Disclosure';\nimport s from './DataGrid.module.css';\n\n/**\n * One column of a {@link DataGrid}. `id` doubles as the default property name\n * read off each row when no `accessor` is given.\n */\nexport interface DataGridColumn<Row> {\n id: string;\n header: ReactNode;\n /** Pull a sortable value from the row. Defaults to `(row as any)[column.id]`. */\n accessor?: (row: Row) => string | number | null | undefined;\n /** Render the cell. Defaults to `String(accessor(row) ?? '')`. */\n render?: (row: Row) => ReactNode;\n /** Default true. Set false to suppress the sort affordance on this column. */\n sortable?: boolean;\n /** Optional CSS class on every <td> in this column. */\n className?: string;\n /** A column of figures: equal-width digits, aligned to the end so the column\n * reads down. Header included, so its label sits over the numbers. */\n numeric?: boolean;\n}\n\n/** Props for {@link DataGrid}. */\nexport interface DataGridProps<Row extends { id: string }> {\n rows: readonly Row[];\n columns: readonly DataGridColumn<Row>[];\n /** Initial sort. Omit for unsorted (rows render in input order). */\n defaultSort?: { columnId: string; direction: 'asc' | 'desc' };\n /** Enable drag handles in a leading column. Receives the reorder spec\n * (the existing `useReorderDragList` semantics — see weasel-ui). */\n onReorder?: (ids: string[], targetIndex: number) => void;\n /** Empty-state row text. Default `'—'`. */\n empty?: ReactNode;\n className?: string;\n /** Extra class on a row's `<tr>`, for row-level state such as a verdict. */\n rowClassName?: (row: Row) => string | undefined;\n /**\n * Activate a row. Makes each row focusable: a click anywhere in it, or\n * Enter/Space while it has focus, calls this. Clicks and keys landing on a\n * control inside a cell (button, link, input, …) are left to that control.\n */\n onRowClick?: (row: Row) => void;\n /**\n * Content for a full-width detail row under `row`, shown while the row is\n * expanded. Setting it adds a leading disclosure column. Return `null` for\n * no detail row.\n */\n renderDetail?: (row: Row) => ReactNode;\n /** Which rows offer the disclosure. Default: every row. */\n rowExpandable?: (row: Row) => boolean;\n /** Expanded row ids, controlled. Pair with `onExpandedChange`. */\n expandedIds?: ReadonlySet<string>;\n /** Initially expanded row ids when uncontrolled. */\n defaultExpandedIds?: Iterable<string>;\n /** Called with the next expanded set when a disclosure toggles. */\n onExpandedChange?: (ids: ReadonlySet<string>) => void;\n}\n\ntype SortState = { columnId: string; direction: 'asc' | 'desc' } | null;\n\nconst INTERACTIVE = 'a[href], button, input, select, textarea, label, summary, [role=\"button\"], [contenteditable=\"true\"]';\n\n/** Did this event start on a control inside the row rather than on the row itself? */\nfunction fromControl(e: MouseEvent | KeyboardEvent): boolean {\n const target = e.target as Element | null;\n const hit = target?.closest?.(INTERACTIVE);\n return !!hit && e.currentTarget.contains(hit);\n}\n\n/**\n * Sortable table for inspector-style data. Rows are keyed by `id`. Clicking a\n * sortable header cycles ascending, descending, unsorted; nullish values sort\n * last regardless of direction. Passing `onReorder` adds a leading drag-handle\n * column — note that the drag indices it reports are into the *sorted* row\n * order, not the input order.\n */\nexport function DataGrid<Row extends { id: string }>(props: DataGridProps<Row>) {\n const {\n rows, columns, defaultSort, onReorder, empty = '—', className,\n rowClassName, onRowClick, renderDetail, rowExpandable, expandedIds, defaultExpandedIds, onExpandedChange,\n } = props;\n const [sort, setSort] = useState<SortState>(defaultSort ?? null);\n const [ownExpanded, setOwnExpanded] = useState<ReadonlySet<string>>(() => new Set(defaultExpandedIds));\n const expanded = expandedIds ?? ownExpanded;\n const detailIdBase = useId();\n\n const toggleExpanded = (id: string) => {\n const next = new Set(expanded);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n if (!expandedIds) setOwnExpanded(next);\n onExpandedChange?.(next);\n };\n\n const sortedRows = useMemo(() => {\n if (!sort) return [...rows];\n const col = columns.find((c) => c.id === sort.columnId);\n if (!col) return [...rows];\n const get = col.accessor ?? ((row: Row) => (row as unknown as Record<string, unknown>)[col.id] as string | number | null | undefined);\n const dir = sort.direction === 'asc' ? 1 : -1;\n return [...rows].sort((a, b) => {\n const av = get(a);\n const bv = get(b);\n if (av == null && bv == null) return 0;\n if (av == null) return 1;\n if (bv == null) return -1;\n if (av < bv) return -1 * dir;\n if (av > bv) return 1 * dir;\n return 0;\n });\n }, [rows, columns, sort]);\n\n const cycleSort = (columnId: string) => {\n setSort((cur) => {\n if (!cur || cur.columnId !== columnId) return { columnId, direction: 'asc' };\n if (cur.direction === 'asc') return { columnId, direction: 'desc' };\n return null;\n });\n };\n\n // Drag handles via useReorderDragList. Adapter: the hook expects\n // `{ id, label }`-shaped items; we map our rows to that shape (label\n // unused — the hook only uses id and locked).\n const drag = useReorderDragList({\n items: sortedRows.map((r) => ({ id: r.id, label: '' })),\n selectedIds: [],\n onReorder: onReorder ?? (() => {}),\n rowSelector: ':not([data-detail-of])',\n });\n const dragEnabled = !!onReorder;\n const detailEnabled = !!renderDetail;\n const colCount = columns.length + (dragEnabled ? 1 : 0) + (detailEnabled ? 1 : 0);\n\n const cls = [s.grid, className].filter(Boolean).join(' ');\n\n return (\n <div\n className={cls}\n >\n <table className={s.table}>\n <thead>\n <tr>\n {dragEnabled && <th className={s.handleCol} aria-label=\"drag\" />}\n {detailEnabled && <th className={s.detailCol} aria-label=\"details\" />}\n {columns.map((col) => {\n const sortable = col.sortable !== false;\n const active = sort?.columnId === col.id;\n const indicator = active ? (sort.direction === 'asc' ? ' ↑' : ' ↓') : '';\n return (\n <th\n key={col.id}\n className={[col.className, col.numeric && s.numeric, active && s.sortActive].filter(Boolean).join(' ') || undefined}\n aria-sort={sortable ? (active ? (sort.direction === 'asc' ? 'ascending' : 'descending') : 'none') : undefined}\n >\n {sortable ? (\n <button type=\"button\" className={s.sortButton} onClick={() => cycleSort(col.id)}>\n {col.header}{indicator}\n </button>\n ) : (\n <>{col.header}{indicator}</>\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody ref={dragEnabled ? (drag.containerProps.ref as React.RefCallback<HTMLTableSectionElement>) : undefined}>\n {sortedRows.length === 0 && (\n <tr>\n <td colSpan={colCount} className={s.empty}>\n {empty}\n </td>\n </tr>\n )}\n {sortedRows.map((row, i) => {\n const isDragging = drag.state.draggedIds?.includes(row.id) ?? false;\n const target = drag.state.targetIndex;\n const expandable = detailEnabled && (rowExpandable?.(row) ?? true);\n const isExpanded = expandable && expanded.has(row.id);\n const detail = isExpanded ? renderDetail!(row) : null;\n const detailId = `${detailIdBase}-detail-${row.id}`;\n const rowCls = [\n onRowClick && s.clickable,\n isDragging && s.dragging,\n target === i && s.dropBefore,\n target === sortedRows.length && i === sortedRows.length - 1 && s.dropAfter,\n rowClassName?.(row),\n ].filter(Boolean).join(' ');\n return (\n <Fragment key={row.id}>\n <tr\n className={rowCls || undefined}\n data-expanded={isExpanded || undefined}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={onRowClick ? (e) => { if (!fromControl(e)) onRowClick(row); } : undefined}\n onKeyDown={onRowClick ? (e) => {\n if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' ')) return;\n e.preventDefault();\n onRowClick(row);\n } : undefined}\n >\n {dragEnabled && (\n <td\n className={s.handleCell}\n onPointerDown={(e) => drag.rowProps(row.id, i).onPointerDown(e)}\n >\n <span aria-hidden=\"true\">⋮⋮</span>\n </td>\n )}\n {detailEnabled && (\n <td className={s.detailCell}>\n {expandable && (\n <Disclosure\n open={isExpanded}\n onToggle={() => toggleExpanded(row.id)}\n label={isExpanded ? 'Hide details' : 'Show details'}\n controls={detail != null ? detailId : undefined}\n />\n )}\n </td>\n )}\n {columns.map((col) => {\n const get = col.accessor ?? ((r: Row) => (r as unknown as Record<string, unknown>)[col.id] as string | number | null | undefined);\n const content = col.render ? col.render(row) : String(get(row) ?? '');\n return (\n <td key={col.id} className={[col.className, col.numeric && s.numeric].filter(Boolean).join(' ') || undefined}>\n {content}\n </td>\n );\n })}\n </tr>\n {detail != null && (\n <tr id={detailId} className={s.detailRow} data-detail-of={row.id}>\n <td colSpan={colCount}>{detail}</td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataGrid-B6IS9vUk.js","names":["s","_Fragment","Fragment","useReorderDragList","Fragment$1","DataGrid_module_default","INTERACTIVE","fromControl","hit","DataGrid","props","sort","setSort","useState","defaultSort","ownExpanded","setOwnExpanded","defaultExpandedIds","expanded","expandedIds","detailIdBase","useId","toggleExpanded","next","id","onExpandedChange","sortedRows","useMemo","rows","col","columns","c","get","row","dir","av","a","bv","b","cycleSort","cur","columnId","drag","r","onReorder","dragEnabled","detailEnabled","renderDetail","colCount","cls","className","sortable","active","indicator","Fragment","empty","isDragging","target","expandable","rowExpandable","isExpanded","detail","detailId","rowCls","onRowClick","i","rowClassName","e","Disclosure","content"],"sources":["../../src/components/DataGrid/DataGrid.module.css","../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":[".grid {\n position: relative;\n width: 100%;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--wzl-font-size-sm);\n}\n\n.table th,\n.table td {\n text-align: left;\n padding: 3px var(--wzl-space-3);\n vertical-align: middle;\n}\n.numeric {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n}\n.table .numeric {\n text-align: end;\n}\n.table tbody tr {\n border-bottom: 1px solid var(--wzl-line-subtle);\n}\n\n.table th {\n font-weight: var(--wzl-font-weight-bold);\n color: var(--wzl-fg-muted);\n position: sticky;\n top: 0;\n background: var(--wzl-surface);\n z-index: 1;\n border-bottom: 1px solid var(--wzl-border);\n}\n\n.sortButton {\n all: unset;\n cursor: pointer;\n user-select: none;\n display: block;\n width: 100%;\n}\n.sortButton:hover { color: var(--wzl-fg); }\n.sortButton:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n.sortActive { color: var(--wzl-fg); }\n\n.empty {\n color: var(--wzl-fg-muted);\n font-style: italic;\n padding: var(--wzl-space-4) 0;\n text-align: center;\n}\n\n/* Drag-handle column. */\n.handleCol { width: 14px; }\n.handleCell {\n width: 14px;\n cursor: grab;\n color: var(--wzl-fg-muted);\n user-select: none;\n text-align: center;\n}\n.handleCell:active { cursor: grabbing; }\n\n.dragging { opacity: 0.4; }\n\n.dropBefore > td { box-shadow: inset 0 2px 0 0 var(--wzl-accent); }\n.dropAfter > td { box-shadow: inset 0 -2px 0 0 var(--wzl-accent); }\n\n/* Row activation (`onRowClick`). */\n.clickable { cursor: pointer; }\n.clickable:hover > td { background: var(--wzl-surface-hover); }\n.clickable:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n/* Disclosure column and the detail row it opens. */\n.detailCol,\n.detailCell {\n width: var(--wzl-control-h-sm);\n padding-inline: 0;\n text-align: center;\n}\n.table .detailCell { padding-block: 0; }\n.detailRow > td {\n padding: var(--wzl-space-2) var(--wzl-space-3) var(--wzl-space-3);\n background: var(--wzl-surface-sunken);\n}\n","/**\n * Lightweight sortable data grid. Use for inspector tables — action\n * registries, route maps, telemetry rows. Intentionally narrow:\n *\n * - Sortable columns (click header to cycle asc → desc → none)\n * - Custom cell render via per-column `render`\n * - Optional drag handles for row reordering (when `onReorder` is set)\n * - Per-row class, row activation, and expandable full-width detail rows\n *\n * Not: virtual scrolling, column resizing, multi-column sort, filtering,\n * inline editing. Reach for a real grid library when you need those.\n */\nimport { Fragment, useId, useMemo, useState } from 'react';\nimport type { KeyboardEvent, MouseEvent, ReactNode } from 'react';\nimport { useReorderDragList } from '../../useReorderDragList';\nimport { Disclosure } from '../Disclosure';\nimport s from './DataGrid.module.css';\n\n/**\n * One column of a {@link DataGrid}. `id` doubles as the default property name\n * read off each row when no `accessor` is given.\n */\nexport interface DataGridColumn<Row> {\n id: string;\n header: ReactNode;\n /** Pull a sortable value from the row. Defaults to `(row as any)[column.id]`. */\n accessor?: (row: Row) => string | number | null | undefined;\n /** Render the cell. Defaults to `String(accessor(row) ?? '')`. */\n render?: (row: Row) => ReactNode;\n /** Default true. Set false to suppress the sort affordance on this column. */\n sortable?: boolean;\n /** Optional CSS class on every <td> in this column. */\n className?: string;\n /** A column of figures: equal-width digits, aligned to the end so the column\n * reads down. Header included, so its label sits over the numbers. */\n numeric?: boolean;\n}\n\n/** Props for {@link DataGrid}. */\nexport interface DataGridProps<Row extends { id: string }> {\n rows: readonly Row[];\n columns: readonly DataGridColumn<Row>[];\n /** Initial sort. Omit for unsorted (rows render in input order). */\n defaultSort?: { columnId: string; direction: 'asc' | 'desc' };\n /** Enable drag handles in a leading column. Receives the reorder spec\n * (the existing `useReorderDragList` semantics — see weasel-ui). */\n onReorder?: (ids: string[], targetIndex: number) => void;\n /** Empty-state row text. Default `'—'`. */\n empty?: ReactNode;\n className?: string;\n /** Extra class on a row's `<tr>`, for row-level state such as a verdict. */\n rowClassName?: (row: Row) => string | undefined;\n /**\n * Activate a row. Makes each row focusable: a click anywhere in it, or\n * Enter/Space while it has focus, calls this. Clicks and keys landing on a\n * control inside a cell (button, link, input, …) are left to that control.\n */\n onRowClick?: (row: Row) => void;\n /**\n * Content for a full-width detail row under `row`, shown while the row is\n * expanded. Setting it adds a leading disclosure column. Return `null` for\n * no detail row.\n */\n renderDetail?: (row: Row) => ReactNode;\n /** Which rows offer the disclosure. Default: every row. */\n rowExpandable?: (row: Row) => boolean;\n /** Expanded row ids, controlled. Pair with `onExpandedChange`. */\n expandedIds?: ReadonlySet<string>;\n /** Initially expanded row ids when uncontrolled. */\n defaultExpandedIds?: Iterable<string>;\n /** Called with the next expanded set when a disclosure toggles. */\n onExpandedChange?: (ids: ReadonlySet<string>) => void;\n}\n\ntype SortState = { columnId: string; direction: 'asc' | 'desc' } | null;\n\nconst INTERACTIVE = 'a[href], button, input, select, textarea, label, summary, [role=\"button\"], [contenteditable=\"true\"]';\n\n/** Did this event start on a control inside the row rather than on the row itself? */\nfunction fromControl(e: MouseEvent | KeyboardEvent): boolean {\n const target = e.target as Element | null;\n const hit = target?.closest?.(INTERACTIVE);\n return !!hit && e.currentTarget.contains(hit);\n}\n\n/**\n * Sortable table for inspector-style data. Rows are keyed by `id`. Clicking a\n * sortable header cycles ascending, descending, unsorted; nullish values sort\n * last regardless of direction. Passing `onReorder` adds a leading drag-handle\n * column — note that the drag indices it reports are into the *sorted* row\n * order, not the input order.\n */\nexport function DataGrid<Row extends { id: string }>(props: DataGridProps<Row>) {\n const {\n rows, columns, defaultSort, onReorder, empty = '—', className,\n rowClassName, onRowClick, renderDetail, rowExpandable, expandedIds, defaultExpandedIds, onExpandedChange,\n } = props;\n const [sort, setSort] = useState<SortState>(defaultSort ?? null);\n const [ownExpanded, setOwnExpanded] = useState<ReadonlySet<string>>(() => new Set(defaultExpandedIds));\n const expanded = expandedIds ?? ownExpanded;\n const detailIdBase = useId();\n\n const toggleExpanded = (id: string) => {\n const next = new Set(expanded);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n if (!expandedIds) setOwnExpanded(next);\n onExpandedChange?.(next);\n };\n\n const sortedRows = useMemo(() => {\n if (!sort) return [...rows];\n const col = columns.find((c) => c.id === sort.columnId);\n if (!col) return [...rows];\n const get = col.accessor ?? ((row: Row) => (row as unknown as Record<string, unknown>)[col.id] as string | number | null | undefined);\n const dir = sort.direction === 'asc' ? 1 : -1;\n return [...rows].sort((a, b) => {\n const av = get(a);\n const bv = get(b);\n if (av == null && bv == null) return 0;\n if (av == null) return 1;\n if (bv == null) return -1;\n if (av < bv) return -1 * dir;\n if (av > bv) return 1 * dir;\n return 0;\n });\n }, [rows, columns, sort]);\n\n const cycleSort = (columnId: string) => {\n setSort((cur) => {\n if (!cur || cur.columnId !== columnId) return { columnId, direction: 'asc' };\n if (cur.direction === 'asc') return { columnId, direction: 'desc' };\n return null;\n });\n };\n\n // Drag handles via useReorderDragList. Adapter: the hook expects\n // `{ id, label }`-shaped items; we map our rows to that shape (label\n // unused — the hook only uses id and locked).\n const drag = useReorderDragList({\n items: sortedRows.map((r) => ({ id: r.id, label: '' })),\n selectedIds: [],\n onReorder: onReorder ?? (() => {}),\n rowSelector: ':not([data-detail-of])',\n });\n const dragEnabled = !!onReorder;\n const detailEnabled = !!renderDetail;\n const colCount = columns.length + (dragEnabled ? 1 : 0) + (detailEnabled ? 1 : 0);\n\n const cls = [s.grid, className].filter(Boolean).join(' ');\n\n return (\n <div\n className={cls}\n >\n <table className={s.table}>\n <thead>\n <tr>\n {dragEnabled && <th className={s.handleCol} aria-label=\"drag\" />}\n {detailEnabled && <th className={s.detailCol} aria-label=\"details\" />}\n {columns.map((col) => {\n const sortable = col.sortable !== false;\n const active = sort?.columnId === col.id;\n const indicator = active ? (sort.direction === 'asc' ? ' ↑' : ' ↓') : '';\n return (\n <th\n key={col.id}\n className={[col.className, col.numeric && s.numeric, active && s.sortActive].filter(Boolean).join(' ') || undefined}\n aria-sort={sortable ? (active ? (sort.direction === 'asc' ? 'ascending' : 'descending') : 'none') : undefined}\n >\n {sortable ? (\n <button type=\"button\" className={s.sortButton} onClick={() => cycleSort(col.id)}>\n {col.header}{indicator}\n </button>\n ) : (\n <>{col.header}{indicator}</>\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody ref={dragEnabled ? (drag.containerProps.ref as React.RefCallback<HTMLTableSectionElement>) : undefined}>\n {sortedRows.length === 0 && (\n <tr>\n <td colSpan={colCount} className={s.empty}>\n {empty}\n </td>\n </tr>\n )}\n {sortedRows.map((row, i) => {\n const isDragging = drag.state.draggedIds?.includes(row.id) ?? false;\n const target = drag.state.targetIndex;\n const expandable = detailEnabled && (rowExpandable?.(row) ?? true);\n const isExpanded = expandable && expanded.has(row.id);\n const detail = isExpanded ? renderDetail!(row) : null;\n const detailId = `${detailIdBase}-detail-${row.id}`;\n const rowCls = [\n onRowClick && s.clickable,\n isDragging && s.dragging,\n target === i && s.dropBefore,\n target === sortedRows.length && i === sortedRows.length - 1 && s.dropAfter,\n rowClassName?.(row),\n ].filter(Boolean).join(' ');\n return (\n <Fragment key={row.id}>\n <tr\n className={rowCls || undefined}\n data-expanded={isExpanded || undefined}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={onRowClick ? (e) => { if (!fromControl(e)) onRowClick(row); } : undefined}\n onKeyDown={onRowClick ? (e) => {\n if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' ')) return;\n e.preventDefault();\n onRowClick(row);\n } : undefined}\n >\n {dragEnabled && (\n <td\n className={s.handleCell}\n onPointerDown={(e) => drag.rowProps(row.id, i).onPointerDown(e)}\n >\n <span aria-hidden=\"true\">⋮⋮</span>\n </td>\n )}\n {detailEnabled && (\n <td className={s.detailCell}>\n {expandable && (\n <Disclosure\n open={isExpanded}\n onToggle={() => toggleExpanded(row.id)}\n label={isExpanded ? 'Hide details' : 'Show details'}\n controls={detail != null ? detailId : undefined}\n />\n )}\n </td>\n )}\n {columns.map((col) => {\n const get = col.accessor ?? ((r: Row) => (r as unknown as Record<string, unknown>)[col.id] as string | number | null | undefined);\n const content = col.render ? col.render(row) : String(get(row) ?? '');\n return (\n <td key={col.id} className={[col.className, col.numeric && s.numeric].filter(Boolean).join(' ') || undefined}>\n {content}\n </td>\n );\n })}\n </tr>\n {detail != null && (\n <tr id={detailId} className={s.detailRow} data-detail-of={row.id}>\n <td colSpan={colCount}>{detail}</td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./Slider-DSrlMEq8.js";
1
+ import { t as e } from "./Slider-CHBQ8uUC.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  import { useEffect as n, useRef as r } from "react";
4
4
  var i = {
@@ -69,4 +69,4 @@ function c(c) {
69
69
  //#endregion
70
70
  export { c as t };
71
71
 
72
- //# sourceMappingURL=DetentSlider-DNTAk8xP.js.map
72
+ //# sourceMappingURL=DetentSlider-D40V8Oma.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DetentSlider-DNTAk8xP.js","names":["s","Slider","DetentSlider_module_default","normalize","items","it","resolveIndex","exact","value","best","bestGap","i","v","gap","plainText","label","fallback","DetentSlider","props","index","lastIndex","labelOf","item","formatLabel","liveRef","useRef","changedRef","handleInput","next","onChange","handleCommit","current","className","thumbs","stops"],"sources":["../../src/components/DetentSlider/DetentSlider.module.css","../../src/components/DetentSlider/DetentSlider.tsx"],"sourcesContent":[".root {\n position: relative;\n /* Read by Slider's track and stop marks. Detents run the full height of the\n * track so they read as notches rather than as tally marks beside it. */\n --rp-tick-inset: 0;\n --rp-tick-width: 1px;\n --rp-tick-color: var(--wzl-border-strong);\n --rp-track-cursor: pointer;\n font-family: var(--wzl-font-ui);\n}\n\n.slider {\n width: 100%;\n}\n\n","import { useEffect, useRef, type ReactElement, type ReactNode } from 'react';\nimport { Slider, type SliderStop, type Thumb } from '../Slider/Slider';\nimport s from './DetentSlider.module.css';\n\n/** What a detent can carry. Narrowed so identity comparison and React keys\n * both work without a keying callback. */\nexport type DetentValue = string | number;\n\n/** One detent on a {@link DetentSlider}. */\nexport type DetentItem<V extends DetentValue = number> = {\n value: V;\n /** Drawn under the detent. Defaults to `formatLabel(value)`, then `value`. */\n label?: ReactNode;\n /** Spoken form, when the drawn label is not the right thing to say. */\n ariaLabel?: string;\n};\n\n/**\n * Props for {@link DetentSlider}.\n *\n * `items` takes bare values or `DetentItem`s interchangeably — a bare value is\n * a detent with no label of its own.\n *\n * `onChange` fires on every detent the control passes through, including\n * mid-drag: each one is a complete, legal choice, so there is no in-flight\n * value to withhold. `onCommit` fires once the gesture that changed things\n * ends, and is the one to write to history.\n */\nexport type DetentSliderProps<V extends DetentValue = number> = {\n items: readonly (V | DetentItem<V>)[];\n value: V;\n onChange: (value: V, index: number) => void;\n onCommit?: (value: V, index: number) => void;\n formatLabel?: (value: V, index: number) => ReactNode;\n labels?: 'all' | 'ends' | 'none';\n trackHeight?: number;\n ariaLabel?: string;\n className?: string;\n};\n\nfunction normalize<V extends DetentValue>(items: readonly (V | DetentItem<V>)[]): DetentItem<V>[] {\n return items.map(it => (typeof it === 'object' && it !== null ? it : ({ value: it } as DetentItem<V>)));\n}\n\n/**\n * The detent `value` selects. An exact match wins; a number that matches none\n * lands on the nearest one, so a value arriving from a numeric field or an\n * older save renders where it belongs rather than silently reading as the\n * first detent.\n */\nfunction resolveIndex<V extends DetentValue>(items: readonly DetentItem<V>[], value: V): number {\n const exact = items.findIndex(it => it.value === value);\n if (exact !== -1) return exact;\n if (typeof value !== 'number') return 0;\n let best = 0;\n let bestGap = Infinity;\n for (let i = 0; i < items.length; i++) {\n const v = items[i].value;\n if (typeof v !== 'number') continue;\n const gap = Math.abs(v - value);\n if (gap < bestGap) {\n bestGap = gap;\n best = i;\n }\n }\n return best;\n}\n\nfunction plainText(label: ReactNode, fallback: DetentValue): string {\n return typeof label === 'string' || typeof label === 'number' ? String(label) : String(fallback);\n}\n\n/**\n * Slider over a fixed list of values: one detent per value, evenly spaced, the\n * thumb resting on one of them.\n *\n * This is the shape to reach for when an option has a small set of allowed\n * values along a line — playback rate, zoom step, quality — in place of a\n * dropdown, which hides the ordering and the extent of the range behind a\n * click. The values need only be ordered, not numeric.\n *\n * It is a strict {@link Slider} over the *index* of `items`, which keeps the\n * detents evenly spaced however the values are distributed. Since the index is\n * meaningless to a screen reader, the value is published as `aria-valuetext`.\n * For numbers that may also rest between the detents, use `Slider` directly\n * with `spacing=\"even\"` and magnetic stops.\n */\nexport function DetentSlider<V extends DetentValue = number>(props: DetentSliderProps<V>): ReactElement {\n const { value, onChange, onCommit, formatLabel, ariaLabel, className } = props;\n const items = normalize(props.items);\n const index = resolveIndex(items, value);\n const lastIndex = Math.max(0, items.length - 1);\n\n const labelOf = (item: DetentItem<V>, i: number): ReactNode =>\n item.label ?? formatLabel?.(item.value, i) ?? String(item.value);\n\n // Deduped separately: `live` suppresses the repeat reports a drag produces\n // while the pointer crosses one detent, `changed` keeps a press that chose\n // nothing from landing a no-op entry in the consumer's history.\n const liveRef = useRef(index);\n const changedRef = useRef(false);\n useEffect(() => {\n liveRef.current = index;\n }, [index]);\n\n const handleInput = (next: Thumb[]) => {\n const i = next[0].value;\n if (i === liveRef.current) return;\n liveRef.current = i;\n changedRef.current = true;\n onChange(items[i].value, i);\n };\n\n const handleCommit = (next: Thumb[]) => {\n if (!changedRef.current) return;\n changedRef.current = false;\n const i = next[0].value;\n onCommit?.(items[i].value, i);\n };\n\n const current = items[index];\n if (!current) return <div className={className ? `${s.root} ${className}` : s.root} />;\n\n const thumbs: Thumb[] = [\n { value: index, valueText: current.ariaLabel ?? plainText(labelOf(current, index), current.value) },\n ];\n\n const stops: SliderStop[] = items.map((item, i) => ({ value: i, label: labelOf(item, i) }));\n\n return (\n <div className={className ? `${s.root} ${className}` : s.root}>\n <Slider\n className={s.slider}\n min={0}\n max={lastIndex}\n stops={stops}\n snap=\"strict\"\n stopLabels={props.labels ?? 'all'}\n trackClick=\"move-nearest\"\n trackHeight={props.trackHeight ?? 8}\n ariaLabel={ariaLabel}\n thumbs={thumbs}\n onInput={handleInput}\n onChange={handleCommit}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;ACwCA,SAASG,EAAiC,GAAwD;CAChG,OAAOC,EAAM,KAAI,MAAO,OAAOC,KAAO,YAAYA,IAAcA,IAAM,EAAE,OAAOA,EAAG,CAAoB;AACxG;AAQA,SAASC,EAAoC,GAAiC,GAAkB;CAC9F,IAAMC,IAAQH,EAAM,WAAU,MAAMC,EAAG,UAAUG,CAAK;CACtD,IAAID,MAAU,IAAI,OAAOA;CACzB,IAAI,OAAOC,KAAU,UAAU,OAAO;CACtC,IAAIC,IAAO,GACPC,IAAU;CACd,KAAK,IAAIC,IAAI,GAAGA,IAAIP,EAAM,QAAQ,KAAK;EACrC,IAAMQ,IAAIR,EAAMO,EAAE,CAAC;EACnB,IAAI,OAAOC,KAAM,UAAU;EAC3B,IAAMC,IAAM,KAAK,IAAID,IAAIJ,CAAK;EAC9B,AAAIK,IAAMH,MACR,IAAUG,GACV,IAAOF;CAEX;CACA,OAAOF;AACT;AAEA,SAASK,EAAU,GAAkB,GAA+B;CAClE,OAAgE,OAAzD,OAAOC,KAAU,YAAY,OAAOA,KAAU,WAAkBA,IAAgBC,CAAQ;AACjG;AAiBA,SAAgBC,EAA6C,GAA2C;CACtG,IAAM,EAAE,UAAO,aAAU,aAAU,gBAAa,cAAW,iBAAcC,GACnEd,IAAQD,EAAUe,EAAM,KAAK,GAC7BC,IAAQb,EAAaF,GAAOI,CAAK,GACjCY,IAAY,KAAK,IAAI,GAAGhB,EAAM,SAAS,CAAC,GAExCiB,KAAW,GAAqB,MACpCC,EAAK,SAASC,IAAcD,EAAK,OAAOX,CAAC,KAAK,OAAOW,EAAK,KAAK,GAK3DE,IAAUC,EAAON,CAAK,GACtBO,IAAaD,EAAO,EAAK;CAC/B,QAAgB;EACd,EAAQ,UAAUN;CACpB,GAAG,CAACA,CAAK,CAAC;CAEV,IAAMQ,KAAe,MAAkB;EACrC,IAAMhB,IAAIiB,EAAK,EAAE,CAAC;EAClB,AAAIjB,MAAMa,EAAQ,YAClB,EAAQ,UAAUb,GAClB,EAAW,UAAU,IACrBkB,EAASzB,EAAMO,EAAE,CAAC,OAAOA,CAAC;CAC5B,GAEMmB,KAAgB,MAAkB;EACtC,IAAI,CAACJ,EAAW,SAAS;EACzB,EAAW,UAAU;EACrB,IAAMf,IAAIiB,EAAK,EAAE,CAAC;EAClB,IAAWxB,EAAMO,EAAE,CAAC,OAAOA,CAAC;CAC9B,GAEMoB,IAAU3B,EAAMe;CACtB,IAAI,CAACY,GAAS,OAAO,kBAAC,OAAD,EAAK,WAAWC,IAAY,GAAGhC,EAAE,KAAK,GAAGgC,MAAchC,EAAE,KAAO,CAAA;CAErF,IAAMiC,IAAkB,CACtB;EAAE,OAAOd;EAAO,WAAWY,EAAQ,aAAajB,EAAUO,EAAQU,GAASZ,CAAK,GAAGY,EAAQ,KAAK;CAAE,CACpG,GAEMG,IAAsB9B,EAAM,KAAK,GAAM,OAAO;EAAE,OAAOO;EAAG,OAAOU,EAAQC,GAAMX,CAAC;CAAE,EAAE;CAE1F,OACE,kBAAC,OAAD;EAAK,WAAWqB,IAAY,GAAGhC,EAAE,KAAK,GAAGgC,MAAchC,EAAE;EACvD,UAAA,kBAACC,GAAD;GACE,WAAWD,EAAE;GACb,KAAK;GACL,KAAKoB;GACE;GACP,MAAK;GACL,YAAYF,EAAM,UAAU;GAC5B,YAAW;GACX,aAAaA,EAAM,eAAe;GACvB;GACH;GACR,SAASS;GACT,UAAUG;EACX,CAAA;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"DetentSlider-D40V8Oma.js","names":["s","Slider","DetentSlider_module_default","normalize","items","it","resolveIndex","exact","value","best","bestGap","i","v","gap","plainText","label","fallback","DetentSlider","props","index","lastIndex","labelOf","item","formatLabel","liveRef","useRef","changedRef","handleInput","next","onChange","handleCommit","current","className","thumbs","stops"],"sources":["../../src/components/DetentSlider/DetentSlider.module.css","../../src/components/DetentSlider/DetentSlider.tsx"],"sourcesContent":[".root {\n position: relative;\n /* Read by Slider's track and stop marks. Detents run the full height of the\n * track so they read as notches rather than as tally marks beside it. */\n --rp-tick-inset: 0;\n --rp-tick-width: 1px;\n --rp-tick-color: var(--wzl-border-strong);\n --rp-track-cursor: pointer;\n font-family: var(--wzl-font-ui);\n}\n\n.slider {\n width: 100%;\n}\n\n","import { useEffect, useRef, type ReactElement, type ReactNode } from 'react';\nimport { Slider, type SliderStop, type Thumb } from '../Slider/Slider';\nimport s from './DetentSlider.module.css';\n\n/** What a detent can carry. Narrowed so identity comparison and React keys\n * both work without a keying callback. */\nexport type DetentValue = string | number;\n\n/** One detent on a {@link DetentSlider}. */\nexport type DetentItem<V extends DetentValue = number> = {\n value: V;\n /** Drawn under the detent. Defaults to `formatLabel(value)`, then `value`. */\n label?: ReactNode;\n /** Spoken form, when the drawn label is not the right thing to say. */\n ariaLabel?: string;\n};\n\n/**\n * Props for {@link DetentSlider}.\n *\n * `items` takes bare values or `DetentItem`s interchangeably — a bare value is\n * a detent with no label of its own.\n *\n * `onChange` fires on every detent the control passes through, including\n * mid-drag: each one is a complete, legal choice, so there is no in-flight\n * value to withhold. `onCommit` fires once the gesture that changed things\n * ends, and is the one to write to history.\n */\nexport type DetentSliderProps<V extends DetentValue = number> = {\n items: readonly (V | DetentItem<V>)[];\n value: V;\n onChange: (value: V, index: number) => void;\n onCommit?: (value: V, index: number) => void;\n formatLabel?: (value: V, index: number) => ReactNode;\n labels?: 'all' | 'ends' | 'none';\n trackHeight?: number;\n ariaLabel?: string;\n className?: string;\n};\n\nfunction normalize<V extends DetentValue>(items: readonly (V | DetentItem<V>)[]): DetentItem<V>[] {\n return items.map(it => (typeof it === 'object' && it !== null ? it : ({ value: it } as DetentItem<V>)));\n}\n\n/**\n * The detent `value` selects. An exact match wins; a number that matches none\n * lands on the nearest one, so a value arriving from a numeric field or an\n * older save renders where it belongs rather than silently reading as the\n * first detent.\n */\nfunction resolveIndex<V extends DetentValue>(items: readonly DetentItem<V>[], value: V): number {\n const exact = items.findIndex(it => it.value === value);\n if (exact !== -1) return exact;\n if (typeof value !== 'number') return 0;\n let best = 0;\n let bestGap = Infinity;\n for (let i = 0; i < items.length; i++) {\n const v = items[i].value;\n if (typeof v !== 'number') continue;\n const gap = Math.abs(v - value);\n if (gap < bestGap) {\n bestGap = gap;\n best = i;\n }\n }\n return best;\n}\n\nfunction plainText(label: ReactNode, fallback: DetentValue): string {\n return typeof label === 'string' || typeof label === 'number' ? String(label) : String(fallback);\n}\n\n/**\n * Slider over a fixed list of values: one detent per value, evenly spaced, the\n * thumb resting on one of them.\n *\n * This is the shape to reach for when an option has a small set of allowed\n * values along a line — playback rate, zoom step, quality — in place of a\n * dropdown, which hides the ordering and the extent of the range behind a\n * click. The values need only be ordered, not numeric.\n *\n * It is a strict {@link Slider} over the *index* of `items`, which keeps the\n * detents evenly spaced however the values are distributed. Since the index is\n * meaningless to a screen reader, the value is published as `aria-valuetext`.\n * For numbers that may also rest between the detents, use `Slider` directly\n * with `spacing=\"even\"` and magnetic stops.\n */\nexport function DetentSlider<V extends DetentValue = number>(props: DetentSliderProps<V>): ReactElement {\n const { value, onChange, onCommit, formatLabel, ariaLabel, className } = props;\n const items = normalize(props.items);\n const index = resolveIndex(items, value);\n const lastIndex = Math.max(0, items.length - 1);\n\n const labelOf = (item: DetentItem<V>, i: number): ReactNode =>\n item.label ?? formatLabel?.(item.value, i) ?? String(item.value);\n\n // Deduped separately: `live` suppresses the repeat reports a drag produces\n // while the pointer crosses one detent, `changed` keeps a press that chose\n // nothing from landing a no-op entry in the consumer's history.\n const liveRef = useRef(index);\n const changedRef = useRef(false);\n useEffect(() => {\n liveRef.current = index;\n }, [index]);\n\n const handleInput = (next: Thumb[]) => {\n const i = next[0].value;\n if (i === liveRef.current) return;\n liveRef.current = i;\n changedRef.current = true;\n onChange(items[i].value, i);\n };\n\n const handleCommit = (next: Thumb[]) => {\n if (!changedRef.current) return;\n changedRef.current = false;\n const i = next[0].value;\n onCommit?.(items[i].value, i);\n };\n\n const current = items[index];\n if (!current) return <div className={className ? `${s.root} ${className}` : s.root} />;\n\n const thumbs: Thumb[] = [\n { value: index, valueText: current.ariaLabel ?? plainText(labelOf(current, index), current.value) },\n ];\n\n const stops: SliderStop[] = items.map((item, i) => ({ value: i, label: labelOf(item, i) }));\n\n return (\n <div className={className ? `${s.root} ${className}` : s.root}>\n <Slider\n className={s.slider}\n min={0}\n max={lastIndex}\n stops={stops}\n snap=\"strict\"\n stopLabels={props.labels ?? 'all'}\n trackClick=\"move-nearest\"\n trackHeight={props.trackHeight ?? 8}\n ariaLabel={ariaLabel}\n thumbs={thumbs}\n onInput={handleInput}\n onChange={handleCommit}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;ACwCA,SAASG,EAAiC,GAAwD;CAChG,OAAOC,EAAM,KAAI,MAAO,OAAOC,KAAO,YAAYA,IAAcA,IAAM,EAAE,OAAOA,EAAG,CAAoB;AACxG;AAQA,SAASC,EAAoC,GAAiC,GAAkB;CAC9F,IAAMC,IAAQH,EAAM,WAAU,MAAMC,EAAG,UAAUG,CAAK;CACtD,IAAID,MAAU,IAAI,OAAOA;CACzB,IAAI,OAAOC,KAAU,UAAU,OAAO;CACtC,IAAIC,IAAO,GACPC,IAAU;CACd,KAAK,IAAIC,IAAI,GAAGA,IAAIP,EAAM,QAAQ,KAAK;EACrC,IAAMQ,IAAIR,EAAMO,EAAE,CAAC;EACnB,IAAI,OAAOC,KAAM,UAAU;EAC3B,IAAMC,IAAM,KAAK,IAAID,IAAIJ,CAAK;EAC9B,AAAIK,IAAMH,MACR,IAAUG,GACV,IAAOF;CAEX;CACA,OAAOF;AACT;AAEA,SAASK,EAAU,GAAkB,GAA+B;CAClE,OAAgE,OAAzD,OAAOC,KAAU,YAAY,OAAOA,KAAU,WAAkBA,IAAgBC,CAAQ;AACjG;AAiBA,SAAgBC,EAA6C,GAA2C;CACtG,IAAM,EAAE,UAAO,aAAU,aAAU,gBAAa,cAAW,iBAAcC,GACnEd,IAAQD,EAAUe,EAAM,KAAK,GAC7BC,IAAQb,EAAaF,GAAOI,CAAK,GACjCY,IAAY,KAAK,IAAI,GAAGhB,EAAM,SAAS,CAAC,GAExCiB,KAAW,GAAqB,MACpCC,EAAK,SAASC,IAAcD,EAAK,OAAOX,CAAC,KAAK,OAAOW,EAAK,KAAK,GAK3DE,IAAUC,EAAON,CAAK,GACtBO,IAAaD,EAAO,EAAK;CAC/B,QAAgB;EACd,EAAQ,UAAUN;CACpB,GAAG,CAACA,CAAK,CAAC;CAEV,IAAMQ,KAAe,MAAkB;EACrC,IAAMhB,IAAIiB,EAAK,EAAE,CAAC;EAClB,AAAIjB,MAAMa,EAAQ,YAClB,EAAQ,UAAUb,GAClB,EAAW,UAAU,IACrBkB,EAASzB,EAAMO,EAAE,CAAC,OAAOA,CAAC;CAC5B,GAEMmB,KAAgB,MAAkB;EACtC,IAAI,CAACJ,EAAW,SAAS;EACzB,EAAW,UAAU;EACrB,IAAMf,IAAIiB,EAAK,EAAE,CAAC;EAClB,IAAWxB,EAAMO,EAAE,CAAC,OAAOA,CAAC;CAC9B,GAEMoB,IAAU3B,EAAMe;CACtB,IAAI,CAACY,GAAS,OAAO,kBAAC,OAAD,EAAK,WAAWC,IAAY,GAAGhC,EAAE,KAAK,GAAGgC,MAAchC,EAAE,KAAO,CAAA;CAErF,IAAMiC,IAAkB,CACtB;EAAE,OAAOd;EAAO,WAAWY,EAAQ,aAAajB,EAAUO,EAAQU,GAASZ,CAAK,GAAGY,EAAQ,KAAK;CAAE,CACpG,GAEMG,IAAsB9B,EAAM,KAAK,GAAM,OAAO;EAAE,OAAOO;EAAG,OAAOU,EAAQC,GAAMX,CAAC;CAAE,EAAE;CAE1F,OACE,kBAAC,OAAD;EAAK,WAAWqB,IAAY,GAAGhC,EAAE,KAAK,GAAGgC,MAAchC,EAAE;EACvD,UAAA,kBAACC,GAAD;GACE,WAAWD,EAAE;GACb,KAAK;GACL,KAAKoB;GACE;GACP,MAAK;GACL,YAAYF,EAAM,UAAU;GAC5B,YAAW;GACX,aAAaA,EAAM,eAAe;GACvB;GACH;GACR,SAASS;GACT,UAAUG;EACX,CAAA;CACE,CAAA;AAET"}
@@ -1,16 +1,16 @@
1
1
  import { i as e } from "./portalHost-CE70wLzo.js";
2
2
  import { t } from "./stance-BFQpS_fL.js";
3
- import { t as n } from "./CloseButton-BmNmRVtb.js";
3
+ import { t as n } from "./CloseButton-wb7Or5Eg.js";
4
4
  import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
5
5
  import { Dialog as o, Heading as s, Modal as c, ModalOverlay as l } from "react-aria-components";
6
6
  var u = {
7
- overlay: "_overlay_153uj_1",
8
- modal: "_modal_153uj_29",
9
- dialog: "_dialog_153uj_223",
10
- header: "_header_153uj_231",
11
- title: "_title_153uj_240",
12
- body: "_body_153uj_251",
13
- footer: "_footer_153uj_266"
7
+ overlay: "_overlay_14syy_1",
8
+ modal: "_modal_14syy_29",
9
+ dialog: "_dialog_14syy_227",
10
+ header: "_header_14syy_235",
11
+ title: "_title_14syy_244",
12
+ body: "_body_14syy_255",
13
+ footer: "_footer_14syy_270"
14
14
  };
15
15
  //#endregion
16
16
  //#region src/components/Dialog/Dialog.tsx
@@ -60,4 +60,4 @@ function d(d) {
60
60
  //#endregion
61
61
  export { d as t };
62
62
 
63
- //# sourceMappingURL=Dialog-DKfsk5VN.js.map
63
+ //# sourceMappingURL=Dialog-h-5MeYpu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog-DKfsk5VN.js","names":["Dialog","_Fragment","s","RACModal","RACDialog","useOverlayPortal","CloseButton","Dialog_module_default","Dialog$1","rest","props","stanced","useStance","showClose","showCloseButton","onOpenChange","portalContainer","Fragment","anchor","ModalOverlay","portalProps","Modal","className","Dialog","title","Heading","close","bodyClassName","footer"],"sources":["../../src/components/Dialog/Dialog.module.css","../../src/components/Dialog/Dialog.tsx"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n opacity: 0;\n transition: opacity var(--wzl-motion-fast);\n}\n\n.overlay[data-entering] {\n opacity: 0;\n}\n\n.overlay[data-entering][data-rac] {\n opacity: 1;\n}\n\n.overlay[data-exiting] {\n opacity: 0;\n}\n\n.overlay[data-rac]:not([data-entering]):not([data-exiting]) {\n opacity: 1;\n}\n\n.modal {\n background: var(--_s-fill);\n border: var(--_s-border-width) var(--_s-border-style) var(--_s-border-color);\n border-radius: var(--_s-radius);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);\n color: var(--wzl-fg);\n font-family: var(--wzl-font-ui);\n max-width: min(900px, calc(100vw - 32px));\n max-height: calc(100vh - 32px);\n display: flex;\n flex-direction: column;\n outline: none;\n}\n\n/* BEGIN GENERATED stance rules: dialog — `npm run gen:stances`, do not edit. */\n\n.modal {\n --wzl-tone: initial;\n}\n\n.modal {\n --_s-surface: var(--wzl-surface);\n --_s-border-color: var(--wzl-border);\n --_s-border-style: solid;\n --_s-border-width: 1px;\n --_s-radius: var(--wzl-radius-md);\n --_s-tone-mix: var(--wzl-panel-tone-mix);\n --_s-tone: var(--wzl-tone, var(--_s-surface));\n --_s-accent: var(--wzl-tone);\n --_s-title-font: var(--wzl-font-ui);\n --_s-title-weight: var(--wzl-font-weight-bold);\n --_s-title-size: var(--wzl-font-size);\n --_s-title-case: none;\n --_s-title-tracking: normal;\n --_s-title-color: var(--wzl-fg);\n}\n\n.modal[data-stance='scope'] {\n --_s-surface: var(--wzl-stance-scope-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-scope-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-scope-border-style, solid);\n --_s-border-width: var(--wzl-stance-scope-border-width, 1px);\n --_s-radius: var(--wzl-stance-scope-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-scope-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-scope-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-scope-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-scope-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-scope-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-scope-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-scope-title-case, none);\n --_s-title-tracking: var(--wzl-stance-scope-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-scope-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='aside'] {\n --_s-surface: var(--wzl-stance-aside-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-aside-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-aside-border-style, solid);\n --_s-border-width: var(--wzl-stance-aside-border-width, 1px);\n --_s-radius: var(--wzl-stance-aside-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-aside-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-aside-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-aside-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-aside-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-aside-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-aside-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-aside-title-case, none);\n --_s-title-tracking: var(--wzl-stance-aside-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-aside-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='advanced'] {\n --_s-surface: var(--wzl-stance-advanced-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-advanced-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-advanced-border-style, solid);\n --_s-border-width: var(--wzl-stance-advanced-border-width, 1px);\n --_s-radius: var(--wzl-stance-advanced-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-advanced-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-advanced-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-advanced-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-advanced-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-advanced-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-advanced-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-advanced-title-case, none);\n --_s-title-tracking: var(--wzl-stance-advanced-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-advanced-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='debug'] {\n --_s-surface: var(--wzl-stance-debug-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-debug-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-debug-border-style, solid);\n --_s-border-width: var(--wzl-stance-debug-border-width, 1px);\n --_s-radius: var(--wzl-stance-debug-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-debug-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-debug-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-debug-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-debug-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-debug-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-debug-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-debug-title-case, none);\n --_s-title-tracking: var(--wzl-stance-debug-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-debug-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='danger'] {\n --_s-surface: var(--wzl-stance-danger-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-danger-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-danger-border-style, solid);\n --_s-border-width: var(--wzl-stance-danger-border-width, 1px);\n --_s-radius: var(--wzl-stance-danger-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-danger-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-danger-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-danger-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-danger-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-danger-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-danger-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-danger-title-case, none);\n --_s-title-tracking: var(--wzl-stance-danger-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-danger-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='notice'] {\n --_s-surface: var(--wzl-stance-notice-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-notice-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-notice-border-style, solid);\n --_s-border-width: var(--wzl-stance-notice-border-width, 1px);\n --_s-radius: var(--wzl-stance-notice-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-notice-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-notice-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-notice-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-notice-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-notice-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-notice-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-notice-title-case, none);\n --_s-title-tracking: var(--wzl-stance-notice-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-notice-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='important'] {\n --_s-surface: var(--wzl-stance-important-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-important-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-important-border-style, solid);\n --_s-border-width: var(--wzl-stance-important-border-width, 1px);\n --_s-radius: var(--wzl-stance-important-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-important-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-important-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-important-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-important-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-important-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-important-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-important-title-case, none);\n --_s-title-tracking: var(--wzl-stance-important-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-important-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='preview'] {\n --_s-surface: var(--wzl-stance-preview-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-preview-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-preview-border-style, solid);\n --_s-border-width: var(--wzl-stance-preview-border-width, 1px);\n --_s-radius: var(--wzl-stance-preview-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-preview-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-preview-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-preview-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-preview-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-preview-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-preview-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-preview-title-case, none);\n --_s-title-tracking: var(--wzl-stance-preview-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-preview-title-color, var(--wzl-fg));\n}\n\n.modal {\n --_s-fill: var(--_s-surface);\n}\n\n.modal[data-tone],\n.modal[data-stance] {\n --_s-fill: color-mix(in oklab, var(--_s-tone) var(--_s-tone-mix), var(--_s-surface));\n}\n\n.modal[data-tone] {\n --wzl-accent: var(--_s-accent);\n --wzl-accent-base: var(--_s-accent);\n --wzl-accent-strong: color-mix(in oklab, var(--_s-accent) 70%, var(--wzl-fg));\n --wzl-accent-soft: color-mix(in oklab, var(--_s-accent) 45%, var(--wzl-surface));\n --wzl-accent-hover: var(--wzl-accent-strong);\n --wzl-accent-fg: var(--wzl-accent-strong);\n --wzl-focus-ring: var(--wzl-accent-strong);\n}\n\n/* END GENERATED stance rules: dialog */\n\n.dialog {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1;\n outline: none;\n}\n\n.header {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-6);\n padding: var(--wzl-space-7) var(--wzl-space-8);\n border-bottom: 1px solid var(--wzl-border);\n flex: 0 0 auto;\n}\n\n.title {\n flex: 1;\n margin: 0;\n font-family: var(--_s-title-font);\n font-size: var(--_s-title-size);\n font-weight: var(--_s-title-weight);\n text-transform: var(--_s-title-case);\n letter-spacing: var(--_s-title-tracking);\n color: var(--_s-title-color);\n}\n\n.body {\n flex: 1;\n}\n\n/* Defaults, not rules: `bodyClassName` exists to turn these off for content\n that scrolls itself, and a plain class would tie with it on specificity and\n be decided by stylesheet order. `min-height` is here for the same reason —\n left in the rule above it silently beat a consumer class asking the body to\n hold a height, and the dialog resized itself around every pane. */\n:where(.body) {\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-8);\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-6) var(--wzl-space-8);\n border-top: 1px solid var(--wzl-border);\n flex: 0 0 auto;\n}\n","import type { ReactNode } from 'react';\nimport {\n Modal as RACModal,\n ModalOverlay,\n Dialog as RACDialog,\n Heading,\n type ModalOverlayProps,\n type DialogProps as RACDialogProps,\n} from 'react-aria-components';\nimport { useOverlayPortal, type OverlayPortalProps, type WithoutPortalTarget } from '../../overlays/portalHost';\nimport { CloseButton } from '../CloseButton';\nimport { type StanceProps, useStance } from '../stance';\nimport s from './Dialog.module.css';\n\n/** Props for {@link Dialog}, on top of React Aria's `ModalOverlay` props. */\nexport type DialogProps = Omit<\n WithoutPortalTarget<ModalOverlayProps>,\n 'children' | 'className'\n> &\n OverlayPortalProps &\n StanceProps & {\n /** Heading rendered in the dialog's default header. Omit when supplying\n * a custom `header` slot via children. */\n title?: ReactNode;\n /** Show the built-in close button. Defaults to true when `onOpenChange`\n * is wired so the user has an escape hatch. */\n showCloseButton?: boolean;\n /** Body content. */\n children?: ReactNode;\n /** Footer slot — typically action buttons. */\n footer?: ReactNode;\n /** ARIA role. Defaults to `dialog`. Use `alertdialog` for confirms. */\n role?: RACDialogProps['role'];\n /** Class applied to the modal box (inside the overlay). */\n className?: string;\n /** Class applied to the scrolling body. For content that owns its own\n * scrolling — a form with a fixed navigation rail beside a scrolling\n * pane — this is where the body's padding and overflow come off. */\n bodyClassName?: string;\n };\n\n/**\n * Modal dialog wrapping React Aria. Supplies a default header (title +\n * close), scrollable body, and footer slot. Pass `isOpen` + `onOpenChange`\n * for controlled visibility, or omit both and use a `<DialogTrigger>` from\n * `react-aria-components` upstream of this component.\n *\n * Escape, click-outside, focus trap, and scroll lock all come from the\n * underlying primitives. `stance` and `tone` work as on `<PropertyPanel>` —\n * a destructive confirm is `stance=\"danger\"`.\n */\nexport function Dialog(props: DialogProps) {\n const {\n title,\n showCloseButton,\n children,\n footer,\n role = 'dialog',\n className,\n bodyClassName,\n isOpen,\n onOpenChange,\n portalContainer,\n stance,\n tone,\n ...rest\n } = props;\n const stanced = useStance({ stance, tone });\n\n const showClose = showCloseButton ?? Boolean(onOpenChange);\n const { anchor, portalProps } = useOverlayPortal(portalContainer);\n\n return (\n <>\n {anchor}\n <ModalOverlay\n {...rest}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n className={s.overlay}\n data-weasel-overlay=\"\"\n {...portalProps}\n >\n <RACModal className={[s.modal, className].filter(Boolean).join(' ')} {...stanced}>\n <RACDialog role={role} className={s.dialog}>\n {({ close }) => (\n <>\n {(title !== undefined || showClose) && (\n <header className={s.header}>\n {title !== undefined && (\n <Heading slot=\"title\" className={s.title}>{title}</Heading>\n )}\n {showClose && (\n <CloseButton ariaLabel=\"Close dialog\" onClick={close} />\n )}\n </header>\n )}\n <div className={[s.body, bodyClassName].filter(Boolean).join(' ')}>{children}</div>\n {footer !== undefined && <footer className={s.footer}>{footer}</footer>}\n </>\n )}\n </RACDialog>\n </RACModal>\n </ModalOverlay>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;ACmDA,SAAgBA,EAAO,GAAoB;CACzC,IAAM,EACJ,UACA,oBACA,aACA,WACA,UAAO,UACP,cACA,kBACA,WACA,iBACA,oBACA,WACA,SACA,GAAGS,MACDC,GACEC,IAAUC,EAAU;EAAE;EAAQ;CAAK,CAAC,GAEpCC,IAAYC,KAAmB,EAAQC,GACvC,EAAE,WAAQ,mBAAgBV,EAAiBW,CAAe;CAEhE,OACE,kBAAAf,GAAA,EAAA,UAAA,CACGiB,GACD,kBAACC,GAAD;EACE,GAAIV;EACI;EACM;EACd,WAAWP,EAAE;EACb,uBAAoB;EACpB,GAAIkB;EAEJ,UAAA,kBAACjB,GAAD;GAAU,WAAW,CAACD,EAAE,OAAOoB,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;GAAG,GAAIX;GACvE,UAAA,kBAACP,GAAD;IAAiB;IAAM,WAAWF,EAAE;IAChC,WAAA,EAAE,eACF,kBAAAD,GAAA,EAAA,UAAA;MACIuB,MAAU,KAAA,KAAaX,MACvB,kBAAC,UAAD;MAAQ,WAAWX,EAAE;MAArB,UAAA,CACGsB,MAAU,KAAA,KACT,kBAACC,GAAD;OAAS,MAAK;OAAQ,WAAWvB,EAAE;OAAQ,UAAAsB;MAAe,CAAA,GAE3DX,KACC,kBAACP,GAAD;OAAa,WAAU;OAAe,SAASoB;MAAQ,CAAA,CAEnD;;KAEV,kBAAC,OAAD;MAAK,WAAW,CAACxB,EAAE,MAAMyB,CAAa,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;MAAI;KAAc,CAAA;KACjFC,MAAW,KAAA,KAAa,kBAAC,UAAD;MAAQ,WAAW1B,EAAE;MAAS,UAAA0B;KAAe,CAAA;IACtE,EAAA,CAAA;GAEK,CAAA;EACH,CAAA;CACE,CAAA,CACd,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"Dialog-h-5MeYpu.js","names":["Dialog","_Fragment","s","RACModal","RACDialog","useOverlayPortal","CloseButton","Dialog_module_default","Dialog$1","rest","props","stanced","useStance","showClose","showCloseButton","onOpenChange","portalContainer","Fragment","anchor","ModalOverlay","portalProps","Modal","className","Dialog","title","Heading","close","bodyClassName","footer"],"sources":["../../src/components/Dialog/Dialog.module.css","../../src/components/Dialog/Dialog.tsx"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n opacity: 0;\n transition: opacity var(--wzl-motion-fast);\n}\n\n.overlay[data-entering] {\n opacity: 0;\n}\n\n.overlay[data-entering][data-rac] {\n opacity: 1;\n}\n\n.overlay[data-exiting] {\n opacity: 0;\n}\n\n.overlay[data-rac]:not([data-entering]):not([data-exiting]) {\n opacity: 1;\n}\n\n.modal {\n background: var(--_s-fill);\n border: var(--_s-border-width) var(--_s-border-style) var(--_s-border-color);\n border-radius: var(--_s-radius);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);\n color: var(--wzl-fg);\n font-family: var(--wzl-font-ui);\n max-width: min(900px, calc(100vw - 32px));\n max-height: calc(100vh - 32px);\n display: flex;\n flex-direction: column;\n outline: none;\n}\n\n/* BEGIN GENERATED stance rules: dialog — `npm run gen:stances`, do not edit. */\n\n.modal {\n --wzl-tone: initial;\n}\n\n.modal {\n --_s-surface: var(--wzl-surface);\n --_s-border-color: var(--wzl-border);\n --_s-border-style: solid;\n --_s-border-width: 1px;\n --_s-radius: var(--wzl-radius-md);\n --_s-tone-mix: var(--wzl-panel-tone-mix);\n --_s-tone: var(--wzl-tone, var(--_s-surface));\n --_s-accent: var(--wzl-tone);\n --_s-title-font: var(--wzl-font-ui);\n --_s-title-weight: var(--wzl-font-weight-bold);\n --_s-title-size: var(--wzl-font-size);\n --_s-title-case: none;\n --_s-title-tracking: normal;\n --_s-title-color: var(--wzl-fg);\n}\n\n.modal[data-stance='scope'] {\n --_s-surface: var(--wzl-stance-scope-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-scope-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-scope-border-style, solid);\n --_s-border-width: var(--wzl-stance-scope-border-width, 1px);\n --_s-radius: var(--wzl-stance-scope-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-scope-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-scope-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-scope-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-scope-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-scope-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-scope-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-scope-title-case, none);\n --_s-title-tracking: var(--wzl-stance-scope-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-scope-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='aside'] {\n --_s-surface: var(--wzl-stance-aside-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-aside-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-aside-border-style, solid);\n --_s-border-width: var(--wzl-stance-aside-border-width, 1px);\n --_s-radius: var(--wzl-stance-aside-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-aside-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-aside-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-aside-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-aside-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-aside-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-aside-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-aside-title-case, none);\n --_s-title-tracking: var(--wzl-stance-aside-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-aside-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='advanced'] {\n --_s-surface: var(--wzl-stance-advanced-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-advanced-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-advanced-border-style, solid);\n --_s-border-width: var(--wzl-stance-advanced-border-width, 1px);\n --_s-radius: var(--wzl-stance-advanced-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-advanced-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-advanced-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-advanced-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-advanced-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-advanced-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-advanced-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-advanced-title-case, none);\n --_s-title-tracking: var(--wzl-stance-advanced-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-advanced-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='debug'] {\n --_s-surface: var(--wzl-stance-debug-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-debug-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-debug-border-style, solid);\n --_s-border-width: var(--wzl-stance-debug-border-width, 1px);\n --_s-radius: var(--wzl-stance-debug-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-debug-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-debug-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-debug-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-debug-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-debug-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-debug-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-debug-title-case, none);\n --_s-title-tracking: var(--wzl-stance-debug-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-debug-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='danger'] {\n --_s-surface: var(--wzl-stance-danger-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-danger-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-danger-border-style, solid);\n --_s-border-width: var(--wzl-stance-danger-border-width, 1px);\n --_s-radius: var(--wzl-stance-danger-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-danger-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-danger-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-danger-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-danger-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-danger-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-danger-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-danger-title-case, none);\n --_s-title-tracking: var(--wzl-stance-danger-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-danger-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='notice'] {\n --_s-surface: var(--wzl-stance-notice-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-notice-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-notice-border-style, solid);\n --_s-border-width: var(--wzl-stance-notice-border-width, 1px);\n --_s-radius: var(--wzl-stance-notice-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-notice-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-notice-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-notice-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-notice-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-notice-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-notice-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-notice-title-case, none);\n --_s-title-tracking: var(--wzl-stance-notice-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-notice-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='important'] {\n --_s-surface: var(--wzl-stance-important-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-important-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-important-border-style, solid);\n --_s-border-width: var(--wzl-stance-important-border-width, 1px);\n --_s-radius: var(--wzl-stance-important-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-important-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-important-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-important-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-important-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-important-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-important-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-important-title-case, none);\n --_s-title-tracking: var(--wzl-stance-important-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-important-title-color, var(--wzl-fg));\n}\n\n.modal[data-stance='preview'] {\n --_s-surface: var(--wzl-stance-preview-surface, var(--wzl-surface));\n --_s-border-color: var(--wzl-stance-preview-border-color, var(--wzl-border));\n --_s-border-style: var(--wzl-stance-preview-border-style, solid);\n --_s-border-width: var(--wzl-stance-preview-border-width, 1px);\n --_s-radius: var(--wzl-stance-preview-radius, var(--wzl-radius-md));\n --_s-tone-mix: var(--wzl-stance-preview-tone-mix, var(--wzl-panel-tone-mix));\n --_s-tone: var(--wzl-tone, var(--wzl-stance-preview-tone, var(--_s-surface)));\n --_s-accent: var(--wzl-stance-preview-accent, var(--wzl-tone));\n --_s-title-font: var(--wzl-stance-preview-title-font, var(--wzl-font-ui));\n --_s-title-weight: var(--wzl-stance-preview-title-weight, var(--wzl-font-weight-bold));\n --_s-title-size: var(--wzl-stance-preview-title-size, var(--wzl-font-size));\n --_s-title-case: var(--wzl-stance-preview-title-case, none);\n --_s-title-tracking: var(--wzl-stance-preview-title-tracking, normal);\n --_s-title-color: var(--wzl-stance-preview-title-color, var(--wzl-fg));\n}\n\n.modal {\n --_s-fill: var(--_s-surface);\n}\n\n.modal[data-tone],\n.modal[data-stance] {\n --_s-fill: color-mix(in oklab, var(--_s-tone) var(--_s-tone-mix), var(--_s-surface));\n}\n\n.modal[data-tone] {\n --wzl-surface-sunken: oklch(from var(--_s-fill) calc(l - 0.06) c h);\n}\n\n.modal[data-tone] {\n --wzl-accent: var(--_s-accent);\n --wzl-accent-base: var(--_s-accent);\n --wzl-accent-strong: color-mix(in oklab, var(--_s-accent) 70%, var(--wzl-fg));\n --wzl-accent-soft: color-mix(in oklab, var(--_s-accent) 45%, var(--wzl-surface));\n --wzl-accent-hover: var(--wzl-accent-strong);\n --wzl-accent-fg: var(--wzl-accent-strong);\n --wzl-focus-ring: var(--wzl-accent-strong);\n}\n\n/* END GENERATED stance rules: dialog */\n\n.dialog {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1;\n outline: none;\n}\n\n.header {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-6);\n padding: var(--wzl-space-7) var(--wzl-space-8);\n border-bottom: 1px solid var(--wzl-border);\n flex: 0 0 auto;\n}\n\n.title {\n flex: 1;\n margin: 0;\n font-family: var(--_s-title-font);\n font-size: var(--_s-title-size);\n font-weight: var(--_s-title-weight);\n text-transform: var(--_s-title-case);\n letter-spacing: var(--_s-title-tracking);\n color: var(--_s-title-color);\n}\n\n.body {\n flex: 1;\n}\n\n/* Defaults, not rules: `bodyClassName` exists to turn these off for content\n that scrolls itself, and a plain class would tie with it on specificity and\n be decided by stylesheet order. `min-height` is here for the same reason —\n left in the rule above it silently beat a consumer class asking the body to\n hold a height, and the dialog resized itself around every pane. */\n:where(.body) {\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-8);\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-6) var(--wzl-space-8);\n border-top: 1px solid var(--wzl-border);\n flex: 0 0 auto;\n}\n","import type { ReactNode } from 'react';\nimport {\n Modal as RACModal,\n ModalOverlay,\n Dialog as RACDialog,\n Heading,\n type ModalOverlayProps,\n type DialogProps as RACDialogProps,\n} from 'react-aria-components';\nimport { useOverlayPortal, type OverlayPortalProps, type WithoutPortalTarget } from '../../overlays/portalHost';\nimport { CloseButton } from '../CloseButton';\nimport { type StanceProps, useStance } from '../stance';\nimport s from './Dialog.module.css';\n\n/** Props for {@link Dialog}, on top of React Aria's `ModalOverlay` props. */\nexport type DialogProps = Omit<\n WithoutPortalTarget<ModalOverlayProps>,\n 'children' | 'className'\n> &\n OverlayPortalProps &\n StanceProps & {\n /** Heading rendered in the dialog's default header. Omit when supplying\n * a custom `header` slot via children. */\n title?: ReactNode;\n /** Show the built-in close button. Defaults to true when `onOpenChange`\n * is wired so the user has an escape hatch. */\n showCloseButton?: boolean;\n /** Body content. */\n children?: ReactNode;\n /** Footer slot — typically action buttons. */\n footer?: ReactNode;\n /** ARIA role. Defaults to `dialog`. Use `alertdialog` for confirms. */\n role?: RACDialogProps['role'];\n /** Class applied to the modal box (inside the overlay). */\n className?: string;\n /** Class applied to the scrolling body. For content that owns its own\n * scrolling — a form with a fixed navigation rail beside a scrolling\n * pane — this is where the body's padding and overflow come off. */\n bodyClassName?: string;\n };\n\n/**\n * Modal dialog wrapping React Aria. Supplies a default header (title +\n * close), scrollable body, and footer slot. Pass `isOpen` + `onOpenChange`\n * for controlled visibility, or omit both and use a `<DialogTrigger>` from\n * `react-aria-components` upstream of this component.\n *\n * Escape, click-outside, focus trap, and scroll lock all come from the\n * underlying primitives. `stance` and `tone` work as on `<PropertyPanel>` —\n * a destructive confirm is `stance=\"danger\"`.\n */\nexport function Dialog(props: DialogProps) {\n const {\n title,\n showCloseButton,\n children,\n footer,\n role = 'dialog',\n className,\n bodyClassName,\n isOpen,\n onOpenChange,\n portalContainer,\n stance,\n tone,\n ...rest\n } = props;\n const stanced = useStance({ stance, tone });\n\n const showClose = showCloseButton ?? Boolean(onOpenChange);\n const { anchor, portalProps } = useOverlayPortal(portalContainer);\n\n return (\n <>\n {anchor}\n <ModalOverlay\n {...rest}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n className={s.overlay}\n data-weasel-overlay=\"\"\n {...portalProps}\n >\n <RACModal className={[s.modal, className].filter(Boolean).join(' ')} {...stanced}>\n <RACDialog role={role} className={s.dialog}>\n {({ close }) => (\n <>\n {(title !== undefined || showClose) && (\n <header className={s.header}>\n {title !== undefined && (\n <Heading slot=\"title\" className={s.title}>{title}</Heading>\n )}\n {showClose && (\n <CloseButton ariaLabel=\"Close dialog\" onClick={close} />\n )}\n </header>\n )}\n <div className={[s.body, bodyClassName].filter(Boolean).join(' ')}>{children}</div>\n {footer !== undefined && <footer className={s.footer}>{footer}</footer>}\n </>\n )}\n </RACDialog>\n </RACModal>\n </ModalOverlay>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;ACmDA,SAAgBA,EAAO,GAAoB;CACzC,IAAM,EACJ,UACA,oBACA,aACA,WACA,UAAO,UACP,cACA,kBACA,WACA,iBACA,oBACA,WACA,SACA,GAAGS,MACDC,GACEC,IAAUC,EAAU;EAAE;EAAQ;CAAK,CAAC,GAEpCC,IAAYC,KAAmB,EAAQC,GACvC,EAAE,WAAQ,mBAAgBV,EAAiBW,CAAe;CAEhE,OACE,kBAAAf,GAAA,EAAA,UAAA,CACGiB,GACD,kBAACC,GAAD;EACE,GAAIV;EACI;EACM;EACd,WAAWP,EAAE;EACb,uBAAoB;EACpB,GAAIkB;EAEJ,UAAA,kBAACjB,GAAD;GAAU,WAAW,CAACD,EAAE,OAAOoB,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;GAAG,GAAIX;GACvE,UAAA,kBAACP,GAAD;IAAiB;IAAM,WAAWF,EAAE;IAChC,WAAA,EAAE,eACF,kBAAAD,GAAA,EAAA,UAAA;MACIuB,MAAU,KAAA,KAAaX,MACvB,kBAAC,UAAD;MAAQ,WAAWX,EAAE;MAArB,UAAA,CACGsB,MAAU,KAAA,KACT,kBAACC,GAAD;OAAS,MAAK;OAAQ,WAAWvB,EAAE;OAAQ,UAAAsB;MAAe,CAAA,GAE3DX,KACC,kBAACP,GAAD;OAAa,WAAU;OAAe,SAASoB;MAAQ,CAAA,CAEnD;;KAEV,kBAAC,OAAD;MAAK,WAAW,CAACxB,EAAE,MAAMyB,CAAa,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;MAAI;KAAc,CAAA;KACjFC,MAAW,KAAA,KAAa,kBAAC,UAAD;MAAQ,WAAW1B,EAAE;MAAS,UAAA0B;KAAe,CAAA;IACtE,EAAA,CAAA;GAEK,CAAA;EACH,CAAA;CACE,CAAA,CACd,EAAA,CAAA;AAEN"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  var n = {
3
- twisty: "_twisty_486xw_1",
4
- mark: "_mark_486xw_29",
5
- lozenge: "_lozenge_486xw_34",
6
- sign: "_sign_486xw_47",
7
- row: "_row_486xw_59",
8
- rowBody: "_rowBody_486xw_67"
3
+ twisty: "_twisty_gcy0c_1",
4
+ mark: "_mark_gcy0c_31",
5
+ lozenge: "_lozenge_gcy0c_36",
6
+ sign: "_sign_gcy0c_49",
7
+ row: "_row_gcy0c_61",
8
+ rowBody: "_rowBody_gcy0c_69"
9
9
  };
10
10
  //#endregion
11
11
  //#region src/components/Disclosure/Disclosure.tsx
@@ -55,4 +55,4 @@ function a({ children: r, className: a, ...o }) {
55
55
  //#endregion
56
56
  export { r as n, a as r, i as t };
57
57
 
58
- //# sourceMappingURL=Disclosure-Ch2KxYuB.js.map
58
+ //# sourceMappingURL=Disclosure-CpWt87nO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Disclosure-Ch2KxYuB.js","names":["s","Disclosure_module_default","DisclosureMark","className","size","open","Disclosure","controls","label","onToggle","DisclosureRow","twisty"],"sources":["../../src/components/Disclosure/Disclosure.module.css","../../src/components/Disclosure/Disclosure.tsx"],"sourcesContent":[".twisty {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* A floor, not a size: a control sized to a 12px glyph is a 12px target,\n which is under every pointer-size guideline there is. Stated as a minimum\n so a larger mark grows the target with it rather than being shrunk to fit\n — a flex item's default `flex-shrink: 1` would otherwise crush it. */\n min-width: var(--wzl-disclosure-target, var(--wzl-control-h-sm));\n min-height: var(--wzl-disclosure-target, var(--wzl-control-h-sm));\n padding: 0;\n border: 0;\n border-radius: var(--wzl-radius-sm);\n background: none;\n line-height: 1;\n cursor: pointer;\n}\n\n.twisty:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n.twisty:disabled {\n cursor: not-allowed;\n}\n\n.mark {\n display: block;\n flex: none;\n}\n\n.lozenge {\n fill: var(--wzl-disclosure-fill, var(--wzl-accent-fg));\n transition: fill var(--wzl-motion-fast) var(--wzl-ease-out-cubic);\n}\n\n.twisty:hover:not(:disabled) .lozenge {\n fill: color-mix(in oklab, var(--wzl-disclosure-fill, var(--wzl-accent-fg)), white 15%);\n}\n\n.twisty:disabled .lozenge {\n fill: var(--wzl-fg-subtle);\n}\n\n.sign {\n fill: none;\n stroke: var(--wzl-fg-on-accent);\n stroke-width: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .lozenge {\n transition: none;\n }\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-disclosure-gap, 4px);\n}\n\n/* The row's content takes the rest and is allowed to shrink; the twisty is\n not, so a long label truncates rather than crushing the control. */\n.rowBody {\n flex: 1 1 auto;\n min-width: 0;\n}\n","import type { ReactNode } from 'react';\nimport s from './Disclosure.module.css';\n\n/** Props for `<DisclosureMark>`. */\nexport interface DisclosureMarkProps {\n /** Whether the section it stands for is open: `−` when open, `+` when shut. */\n open: boolean;\n /** Mark size in px, square. Default 13. */\n size?: number;\n className?: string;\n}\n\n/**\n * The fold mark alone: a dark violet rounded square holding a `+` while its section is\n * shut and a `−` while it is open. Decorative — it carries no role or label —\n * for a row that is itself the control, such as a tree item or a header\n * button. Anywhere the mark has to be the control, use `<Disclosure>`.\n *\n * Deliberately not part of the icon register, on the same grounds as\n * `DragGrip`: that register is outline strokes at a fixed weight, and\n * this mark is filled.\n */\nexport function DisclosureMark({ open, size = 13, className }: DisclosureMarkProps) {\n return (\n <svg\n className={className ? `${s.mark} ${className}` : s.mark}\n viewBox=\"0 0 13 13\"\n width={size}\n height={size}\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <rect className={s.lozenge} width=\"13\" height=\"13\" rx=\"3\" />\n {/* One-unit bars centered on 6.5 in an odd box, so at the default size\n both edges land on the pixel grid rather than blurring across it. */}\n <path className={s.sign} d={open ? 'M3 6.5 H10' : 'M3 6.5 H10 M6.5 3 V10'} />\n </svg>\n );\n}\n\n/** Props for `<Disclosure>`. */\nexport interface DisclosureProps {\n /** Whether the section it controls is open. The consumer owns this. */\n open: boolean;\n onToggle: () => void;\n /**\n * Names the section, for a screen reader. The control has no text of its\n * own, so without this it announces as an unlabeled button.\n */\n label: string;\n /**\n * `id` of the element this expands. Sets `aria-controls`, which lets a\n * screen reader move to the revealed content.\n */\n controls?: string;\n /** Mark size in px. The hit target is at least 20px and grows with it.\n * Default 13. */\n size?: number;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The twisty on a collapsible section: a `<DisclosureMark>` in a button.\n *\n * Presentational — it holds no open/closed state and renders no children.\n * The consumer owns the state and the panel; this is the control that toggles\n * it, and `aria-expanded` is what ties the two together.\n *\n * Three things it settles that a hand-rolled twisty keeps getting wrong. The\n * mark is drawn rather than typed, because `--wzl-font-ui` carries no ▸/▾ and\n * a text glyph falls back to whatever the system offers at whatever size that\n * font renders it. The hit target is larger than the mark. And it is a sibling\n * of the row's label rather than a child, so clicking to expand does not\n * actuate the label's own control.\n */\nexport function Disclosure({ open, onToggle, label, controls, size = 13, disabled, className }: DisclosureProps) {\n return (\n <button\n type=\"button\"\n className={className ? `${s.twisty} ${className}` : s.twisty}\n aria-expanded={open}\n aria-controls={controls}\n aria-label={label}\n disabled={disabled}\n onClick={onToggle}\n >\n <DisclosureMark open={open} size={size} />\n </button>\n );\n}\n\n/** Props for `<DisclosureRow>`. */\nexport interface DisclosureRowProps extends Omit<DisclosureProps, 'className'> {\n /** The row's own content — a label, a checkbox, a count. */\n children: ReactNode;\n className?: string;\n}\n\n/**\n * A `<Disclosure>` and a row of content beside it, laid out so the twisty\n * leads and the content takes the rest.\n *\n * The layout is the point: the twisty sits *outside* whatever the row puts in\n * it, so a row whose content is a `<label>` wrapping a checkbox stays\n * clickable as a label without the twisty actuating it.\n */\nexport function DisclosureRow({ children, className, ...twisty }: DisclosureRowProps) {\n return (\n <div className={className ? `${s.row} ${className}` : s.row}>\n <Disclosure {...twisty} />\n <div className={s.rowBody}>{children}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;ACsBA,SAAgBE,EAAe,EAAE,SAAM,UAAO,IAAI,gBAAkC;CAClF,OACE,kBAAC,OAAD;EACE,WAAWC,IAAY,GAAGH,EAAE,KAAK,GAAGG,MAAcH,EAAE;EACpD,SAAQ;EACR,OAAOI;EACP,QAAQA;EACR,eAAY;EACZ,WAAU;EANZ,UAAA,CAQE,kBAAC,QAAD;GAAM,WAAWJ,EAAE;GAAS,OAAM;GAAK,QAAO;GAAK,IAAG;EAAK,CAAA,GAG3D,kBAAC,QAAD;GAAM,WAAWA,EAAE;GAAM,GAAGK,IAAO,eAAe;EAA0B,CAAA,CACzE;;AAET;AAsCA,SAAgBC,EAAW,EAAE,SAAM,aAAU,UAAO,aAAU,UAAO,IAAI,aAAU,gBAA8B;CAC/G,OACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAWH,IAAY,GAAGH,EAAE,OAAO,GAAGG,MAAcH,EAAE;EACtD,iBAAeK;EACf,iBAAeE;EACf,cAAYC;EACF;EACV,SAASC;EAET,UAAA,kBAACP,GAAD;GAAsB;GAAY;EAAO,CAAA;CACnC,CAAA;AAEZ;AAiBA,SAAgBQ,EAAc,EAAE,aAAU,cAAW,GAAGC,KAA8B;CACpF,OACE,kBAAC,OAAD;EAAK,WAAWR,IAAY,GAAGH,EAAE,IAAI,GAAGG,MAAcH,EAAE;EAAxD,UAAA,CACE,kBAACM,GAAD,EAAY,GAAIK,EAAS,CAAA,GACzB,kBAAC,OAAD;GAAK,WAAWX,EAAE;GAAU;EAAc,CAAA,CACvC;;AAET"}
1
+ {"version":3,"file":"Disclosure-CpWt87nO.js","names":["s","Disclosure_module_default","DisclosureMark","className","size","open","Disclosure","controls","label","onToggle","DisclosureRow","twisty"],"sources":["../../src/components/Disclosure/Disclosure.module.css","../../src/components/Disclosure/Disclosure.tsx"],"sourcesContent":[".twisty {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* A floor, not a size: a control sized to a 12px glyph is a 12px target,\n which is under every pointer-size guideline there is. Stated as a minimum\n so a larger mark grows the target with it rather than being shrunk to fit\n — a flex item's default `flex-shrink: 1` would otherwise crush it. */\n min-width: var(--wzl-disclosure-target, var(--wzl-control-h-sm));\n min-height: var(--wzl-disclosure-target, var(--wzl-control-h-sm));\n padding: 0;\n border: 0;\n border-radius: var(--wzl-radius-sm);\n background: none;\n /* Not the UA's buttontext: the disabled fill is --wzl-fg-subtle, a step down from the text beside it. */\n color: inherit;\n line-height: 1;\n cursor: pointer;\n}\n\n.twisty:focus-visible {\n outline: 2px solid var(--wzl-focus-ring);\n outline-offset: -2px;\n}\n\n.twisty:disabled {\n cursor: not-allowed;\n}\n\n.mark {\n display: block;\n flex: none;\n}\n\n.lozenge {\n fill: var(--wzl-disclosure-fill, var(--wzl-accent-fg));\n transition: fill var(--wzl-motion-fast) var(--wzl-ease-out-cubic);\n}\n\n.twisty:hover:not(:disabled) .lozenge {\n fill: color-mix(in oklab, var(--wzl-disclosure-fill, var(--wzl-accent-fg)), white 15%);\n}\n\n.twisty:disabled .lozenge {\n fill: var(--wzl-fg-subtle);\n}\n\n.sign {\n fill: none;\n stroke: var(--wzl-fg-on-accent);\n stroke-width: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .lozenge {\n transition: none;\n }\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-disclosure-gap, 4px);\n}\n\n/* The row's content takes the rest and is allowed to shrink; the twisty is\n not, so a long label truncates rather than crushing the control. */\n.rowBody {\n flex: 1 1 auto;\n min-width: 0;\n}\n","import type { ReactNode } from 'react';\nimport s from './Disclosure.module.css';\n\n/** Props for `<DisclosureMark>`. */\nexport interface DisclosureMarkProps {\n /** Whether the section it stands for is open: `−` when open, `+` when shut. */\n open: boolean;\n /** Mark size in px, square. Default 13. */\n size?: number;\n className?: string;\n}\n\n/**\n * The fold mark alone: a dark violet rounded square holding a `+` while its section is\n * shut and a `−` while it is open. Decorative — it carries no role or label —\n * for a row that is itself the control, such as a tree item or a header\n * button. Anywhere the mark has to be the control, use `<Disclosure>`.\n *\n * Deliberately not part of the icon register, on the same grounds as\n * `DragGrip`: that register is outline strokes at a fixed weight, and\n * this mark is filled.\n */\nexport function DisclosureMark({ open, size = 13, className }: DisclosureMarkProps) {\n return (\n <svg\n className={className ? `${s.mark} ${className}` : s.mark}\n viewBox=\"0 0 13 13\"\n width={size}\n height={size}\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <rect className={s.lozenge} width=\"13\" height=\"13\" rx=\"3\" />\n {/* One-unit bars centered on 6.5 in an odd box, so at the default size\n both edges land on the pixel grid rather than blurring across it. */}\n <path className={s.sign} d={open ? 'M3 6.5 H10' : 'M3 6.5 H10 M6.5 3 V10'} />\n </svg>\n );\n}\n\n/** Props for `<Disclosure>`. */\nexport interface DisclosureProps {\n /** Whether the section it controls is open. The consumer owns this. */\n open: boolean;\n onToggle: () => void;\n /**\n * Names the section, for a screen reader. The control has no text of its\n * own, so without this it announces as an unlabeled button.\n */\n label: string;\n /**\n * `id` of the element this expands. Sets `aria-controls`, which lets a\n * screen reader move to the revealed content.\n */\n controls?: string;\n /** Mark size in px. The hit target is at least 20px and grows with it.\n * Default 13. */\n size?: number;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The twisty on a collapsible section: a `<DisclosureMark>` in a button.\n *\n * Presentational — it holds no open/closed state and renders no children.\n * The consumer owns the state and the panel; this is the control that toggles\n * it, and `aria-expanded` is what ties the two together.\n *\n * Three things it settles that a hand-rolled twisty keeps getting wrong. The\n * mark is drawn rather than typed, because `--wzl-font-ui` carries no ▸/▾ and\n * a text glyph falls back to whatever the system offers at whatever size that\n * font renders it. The hit target is larger than the mark. And it is a sibling\n * of the row's label rather than a child, so clicking to expand does not\n * actuate the label's own control.\n */\nexport function Disclosure({ open, onToggle, label, controls, size = 13, disabled, className }: DisclosureProps) {\n return (\n <button\n type=\"button\"\n className={className ? `${s.twisty} ${className}` : s.twisty}\n aria-expanded={open}\n aria-controls={controls}\n aria-label={label}\n disabled={disabled}\n onClick={onToggle}\n >\n <DisclosureMark open={open} size={size} />\n </button>\n );\n}\n\n/** Props for `<DisclosureRow>`. */\nexport interface DisclosureRowProps extends Omit<DisclosureProps, 'className'> {\n /** The row's own content — a label, a checkbox, a count. */\n children: ReactNode;\n className?: string;\n}\n\n/**\n * A `<Disclosure>` and a row of content beside it, laid out so the twisty\n * leads and the content takes the rest.\n *\n * The layout is the point: the twisty sits *outside* whatever the row puts in\n * it, so a row whose content is a `<label>` wrapping a checkbox stays\n * clickable as a label without the twisty actuating it.\n */\nexport function DisclosureRow({ children, className, ...twisty }: DisclosureRowProps) {\n return (\n <div className={className ? `${s.row} ${className}` : s.row}>\n <Disclosure {...twisty} />\n <div className={s.rowBody}>{children}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;ACsBA,SAAgBE,EAAe,EAAE,SAAM,UAAO,IAAI,gBAAkC;CAClF,OACE,kBAAC,OAAD;EACE,WAAWC,IAAY,GAAGH,EAAE,KAAK,GAAGG,MAAcH,EAAE;EACpD,SAAQ;EACR,OAAOI;EACP,QAAQA;EACR,eAAY;EACZ,WAAU;EANZ,UAAA,CAQE,kBAAC,QAAD;GAAM,WAAWJ,EAAE;GAAS,OAAM;GAAK,QAAO;GAAK,IAAG;EAAK,CAAA,GAG3D,kBAAC,QAAD;GAAM,WAAWA,EAAE;GAAM,GAAGK,IAAO,eAAe;EAA0B,CAAA,CACzE;;AAET;AAsCA,SAAgBC,EAAW,EAAE,SAAM,aAAU,UAAO,aAAU,UAAO,IAAI,aAAU,gBAA8B;CAC/G,OACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAWH,IAAY,GAAGH,EAAE,OAAO,GAAGG,MAAcH,EAAE;EACtD,iBAAeK;EACf,iBAAeE;EACf,cAAYC;EACF;EACV,SAASC;EAET,UAAA,kBAACP,GAAD;GAAsB;GAAY;EAAO,CAAA;CACnC,CAAA;AAEZ;AAiBA,SAAgBQ,EAAc,EAAE,aAAU,cAAW,GAAGC,KAA8B;CACpF,OACE,kBAAC,OAAD;EAAK,WAAWR,IAAY,GAAGH,EAAE,IAAI,GAAGG,MAAcH,EAAE;EAAxD,UAAA,CACE,kBAACM,GAAD,EAAY,GAAIK,EAAS,CAAA,GACzB,kBAAC,OAAD;GAAK,WAAWX,EAAE;GAAU;EAAc,CAAA,CACvC;;AAET"}