@weasel-js/ui 1.3.0-pre.0 → 1.4.0-pre.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 (251) hide show
  1. package/dist/chunks/{ActionBar-BTev_ZZl.js → ActionBar-D4N1o4LB.js} +2 -2
  2. package/dist/chunks/{ActionBar-BTev_ZZl.js.map → ActionBar-D4N1o4LB.js.map} +1 -1
  3. package/dist/chunks/{ActionsBar-gTuCtkv8.js → ActionsBar-B-gWm0NE.js} +3 -3
  4. package/dist/chunks/{ActionsBar-gTuCtkv8.js.map → ActionsBar-B-gWm0NE.js.map} +1 -1
  5. package/dist/chunks/{Badge-9dPfvYOk.js → Badge-BXTDs-zi.js} +1 -1
  6. package/dist/chunks/{Badge-9dPfvYOk.js.map → Badge-BXTDs-zi.js.map} +1 -1
  7. package/dist/chunks/{BandEditor-DKbcHG2_.js → BandEditor-D13ybQN_.js} +1 -1
  8. package/dist/chunks/{BandEditor-DKbcHG2_.js.map → BandEditor-D13ybQN_.js.map} +1 -1
  9. package/dist/chunks/{Button-CIu40Epu.js → Button-0OdcoOMx.js} +1 -1
  10. package/dist/chunks/{Button-CIu40Epu.js.map → Button-0OdcoOMx.js.map} +1 -1
  11. package/dist/chunks/{Callout-CHs98djt.js → Callout-DAFusbzz.js} +1 -1
  12. package/dist/chunks/Callout-DAFusbzz.js.map +1 -0
  13. package/dist/chunks/{Checkbox-BLEw-wEb.js → Checkbox-BePa_djO.js} +1 -1
  14. package/dist/chunks/{Checkbox-BLEw-wEb.js.map → Checkbox-BePa_djO.js.map} +1 -1
  15. package/dist/chunks/{ColorField-D1t-BdSa.js → ColorField-CKbnsEUN.js} +2 -2
  16. package/dist/chunks/{ColorField-D1t-BdSa.js.map → ColorField-CKbnsEUN.js.map} +1 -1
  17. package/dist/chunks/{ComboBox-cvdKolWv.js → ComboBox-B6QS8y3j.js} +2 -2
  18. package/dist/chunks/{ComboBox-cvdKolWv.js.map → ComboBox-B6QS8y3j.js.map} +1 -1
  19. package/dist/chunks/{CurveEditor-BaA-PabB.js → CurveEditor-COJ6WK9K.js} +3 -2
  20. package/dist/chunks/{CurveEditor-BaA-PabB.js.map → CurveEditor-COJ6WK9K.js.map} +1 -1
  21. package/dist/chunks/DataGrid-BWZZUekH.js +107 -0
  22. package/dist/chunks/DataGrid-BWZZUekH.js.map +1 -0
  23. package/dist/chunks/DetentSlider-CXIeTHaM.js +83 -0
  24. package/dist/chunks/DetentSlider-CXIeTHaM.js.map +1 -0
  25. package/dist/chunks/{Dialog-DC1x46Sq.js → Dialog-CQAZ7hS7.js} +1 -1
  26. package/dist/chunks/{Dialog-DC1x46Sq.js.map → Dialog-CQAZ7hS7.js.map} +1 -1
  27. package/dist/chunks/DragHandleGlyph--2zsZzA2.js +47 -0
  28. package/dist/chunks/DragHandleGlyph--2zsZzA2.js.map +1 -0
  29. package/dist/chunks/{Field-BjFl_yng.js → Field-BCcTt6Fd.js} +1 -1
  30. package/dist/chunks/{Field-BjFl_yng.js.map → Field-BCcTt6Fd.js.map} +1 -1
  31. package/dist/chunks/FontFamilySelect-DwkwRYrr.js +29 -0
  32. package/dist/chunks/FontFamilySelect-DwkwRYrr.js.map +1 -0
  33. package/dist/chunks/{GradientEditor-BJRD0n1g.js → GradientEditor-FwNdxxf-.js} +4 -4
  34. package/dist/chunks/{GradientEditor-BJRD0n1g.js.map → GradientEditor-FwNdxxf-.js.map} +1 -1
  35. package/dist/chunks/{PaintInput-Cggm9OIl.js → Icon-CxoJb_bw.js} +17 -127
  36. package/dist/chunks/Icon-CxoJb_bw.js.map +1 -0
  37. package/dist/chunks/{InlineRange-C6UYKxLD.js → InlineRange-mb19EGOI.js} +1 -1
  38. package/dist/chunks/{InlineRange-C6UYKxLD.js.map → InlineRange-mb19EGOI.js.map} +1 -1
  39. package/dist/chunks/{Input-DhWBgpRx.js → Input-DRUeowbz.js} +2 -2
  40. package/dist/chunks/{Input-DhWBgpRx.js.map → Input-DRUeowbz.js.map} +1 -1
  41. package/dist/chunks/ItemList-BUTk9E8-.js +42 -0
  42. package/dist/chunks/ItemList-BUTk9E8-.js.map +1 -0
  43. package/dist/chunks/{Keycaps-BhCKdyws.js → Keycaps-DszN5Dwl.js} +1 -1
  44. package/dist/chunks/{Keycaps-BhCKdyws.js.map → Keycaps-DszN5Dwl.js.map} +1 -1
  45. package/dist/chunks/LayerStack-htMwIsJ6.js +145 -0
  46. package/dist/chunks/LayerStack-htMwIsJ6.js.map +1 -0
  47. package/dist/chunks/{NumberField-ZdVa4bpJ.js → NumberField-CQ7OJORF.js} +2 -2
  48. package/dist/chunks/{NumberField-ZdVa4bpJ.js.map → NumberField-CQ7OJORF.js.map} +1 -1
  49. package/dist/chunks/{OptionsBar-DahCI4Aq.js → OptionsBar-efIwfqYe.js} +3 -3
  50. package/dist/chunks/{OptionsBar-DahCI4Aq.js.map → OptionsBar-efIwfqYe.js.map} +1 -1
  51. package/dist/chunks/PaintInput-CgZR3B0r.js +118 -0
  52. package/dist/chunks/PaintInput-CgZR3B0r.js.map +1 -0
  53. package/dist/chunks/{PatternPicker-B63SlDoF.js → PatternPicker-v9BFsaMM.js} +2 -2
  54. package/dist/chunks/{PatternPicker-B63SlDoF.js.map → PatternPicker-v9BFsaMM.js.map} +1 -1
  55. package/dist/chunks/Plot2D-B08SYGQV.js +134 -0
  56. package/dist/chunks/Plot2D-B08SYGQV.js.map +1 -0
  57. package/dist/chunks/{PointPlotter-CLd9u5Bq.js → PointPlotter-DEh7a3xB.js} +2 -2
  58. package/dist/chunks/{PointPlotter-CLd9u5Bq.js.map → PointPlotter-DEh7a3xB.js.map} +1 -1
  59. package/dist/chunks/{Powerline-DhQJYaUg.js → Powerline-M1Q3Hx5E.js} +2 -2
  60. package/dist/chunks/{Powerline-DhQJYaUg.js.map → Powerline-M1Q3Hx5E.js.map} +1 -1
  61. package/dist/chunks/{Prefs-BSJ0lMmJ.js → Prefs-C2qhxnmt.js} +11 -11
  62. package/dist/chunks/{Prefs-BSJ0lMmJ.js.map → Prefs-C2qhxnmt.js.map} +1 -1
  63. package/dist/chunks/Properties-CFRJ8mYH.js +655 -0
  64. package/dist/chunks/Properties-CFRJ8mYH.js.map +1 -0
  65. package/dist/chunks/{RadioGroup-vtwjRiUm.js → RadioGroup-B8eMJ6lu.js} +2 -2
  66. package/dist/chunks/{RadioGroup-vtwjRiUm.js.map → RadioGroup-B8eMJ6lu.js.map} +1 -1
  67. package/dist/chunks/{RangeSlider-B-n_7AgJ.js → RangeSlider-JczhglgA.js} +1 -1
  68. package/dist/chunks/RangeSlider-JczhglgA.js.map +1 -0
  69. package/dist/chunks/{ResizeHandle--ZExnMfa.js → ResizeHandle-CXBXV6Px.js} +1 -1
  70. package/dist/chunks/{ResizeHandle--ZExnMfa.js.map → ResizeHandle-CXBXV6Px.js.map} +1 -1
  71. package/dist/chunks/{Select--BVTi-j0.js → Select-g8PhE010.js} +2 -2
  72. package/dist/chunks/{Select--BVTi-j0.js.map → Select-g8PhE010.js.map} +1 -1
  73. package/dist/chunks/SelectionPanel-Cl18SdD6.js +561 -0
  74. package/dist/chunks/SelectionPanel-Cl18SdD6.js.map +1 -0
  75. package/dist/chunks/{Sidebar-CtwBdr4n.js → Sidebar-mWGsndWw.js} +1 -1
  76. package/dist/chunks/{Sidebar-CtwBdr4n.js.map → Sidebar-mWGsndWw.js.map} +1 -1
  77. package/dist/chunks/SidebarPanel-B2d0erLv.js +59 -0
  78. package/dist/chunks/SidebarPanel-B2d0erLv.js.map +1 -0
  79. package/dist/chunks/Slider-BbbmHE0c.js +291 -0
  80. package/dist/chunks/Slider-BbbmHE0c.js.map +1 -0
  81. package/dist/chunks/{StatusBar-D_wu-SZh.js → StatusBar-xxCcWsfq.js} +1 -1
  82. package/dist/chunks/{StatusBar-D_wu-SZh.js.map → StatusBar-xxCcWsfq.js.map} +1 -1
  83. package/dist/chunks/{Switch-CtZwp5zm.js → Switch-QviBb61l.js} +1 -1
  84. package/dist/chunks/{Switch-CtZwp5zm.js.map → Switch-QviBb61l.js.map} +1 -1
  85. package/dist/chunks/{Tabs-lB0IB4TX.js → Tabs-DT-dIt6d.js} +1 -1
  86. package/dist/chunks/{Tabs-lB0IB4TX.js.map → Tabs-DT-dIt6d.js.map} +1 -1
  87. package/dist/chunks/Timeline-DsLeV5I1.js +894 -0
  88. package/dist/chunks/Timeline-DsLeV5I1.js.map +1 -0
  89. package/dist/chunks/{Toast-hr9BYsho.js → Toast-CfkiN0Nv.js} +1 -1
  90. package/dist/chunks/{Toast-hr9BYsho.js.map → Toast-CfkiN0Nv.js.map} +1 -1
  91. package/dist/chunks/{ToggleBar-BxgWq-wO.js → ToggleBar-D0veW91s.js} +2 -2
  92. package/dist/chunks/{ToggleBar-BxgWq-wO.js.map → ToggleBar-D0veW91s.js.map} +1 -1
  93. package/dist/chunks/{ToolButton-CJrPjbsj.js → ToolButton-CLoR9Z4o.js} +2 -2
  94. package/dist/chunks/{ToolButton-CJrPjbsj.js.map → ToolButton-CLoR9Z4o.js.map} +1 -1
  95. package/dist/chunks/{ToolGroup-D_lDzkvU.js → ToolGroup-BnE23mcA.js} +1 -1
  96. package/dist/chunks/{ToolGroup-D_lDzkvU.js.map → ToolGroup-BnE23mcA.js.map} +1 -1
  97. package/dist/chunks/{ToolOptionsBar-BA6Sb3U2.js → ToolOptionsBar-ByHX7y1M.js} +1 -1
  98. package/dist/chunks/{ToolOptionsBar-BA6Sb3U2.js.map → ToolOptionsBar-ByHX7y1M.js.map} +1 -1
  99. package/dist/chunks/{ToolPalette-TMvkaJwr.js → ToolPalette-W-rAsomq.js} +5 -5
  100. package/dist/chunks/{ToolPalette-TMvkaJwr.js.map → ToolPalette-W-rAsomq.js.map} +1 -1
  101. package/dist/chunks/{Tooltip-Di7vxbFa.js → Tooltip-Bq8Hvj4r.js} +1 -1
  102. package/dist/chunks/{Tooltip-Di7vxbFa.js.map → Tooltip-Bq8Hvj4r.js.map} +1 -1
  103. package/dist/chunks/dlog-CMYiRF3Q.js +38 -0
  104. package/dist/chunks/dlog-CMYiRF3Q.js.map +1 -0
  105. package/dist/chunks/icons-CdLHgzV8.js +144 -0
  106. package/dist/chunks/icons-CdLHgzV8.js.map +1 -0
  107. package/dist/chunks/{keyGlyph-DNpLxF8u.js → keyGlyph-BLFMKZgF.js} +1 -1
  108. package/dist/chunks/{keyGlyph-DNpLxF8u.js.map → keyGlyph-BLFMKZgF.js.map} +1 -1
  109. package/dist/chunks/number-D3TDawLC.js +18 -0
  110. package/dist/chunks/number-D3TDawLC.js.map +1 -0
  111. package/dist/chunks/{segmentedControl.module-D4b7x19O.js → segmentedControl.module-XADeq9e5.js} +1 -1
  112. package/dist/chunks/{segmentedControl.module-D4b7x19O.js.map → segmentedControl.module-XADeq9e5.js.map} +1 -1
  113. package/dist/chunks/useReorderDragList-nQMVwNBd.js +109 -0
  114. package/dist/chunks/useReorderDragList-nQMVwNBd.js.map +1 -0
  115. package/dist/chunks/{useRovingTabIndex-CQz8EiKh.js → useRovingTabIndex-ByjY4lnw.js} +1 -1
  116. package/dist/chunks/{useRovingTabIndex-CQz8EiKh.js.map → useRovingTabIndex-ByjY4lnw.js.map} +1 -1
  117. package/dist/components/ActionBar/index.js +1 -1
  118. package/dist/components/ActionsBar/index.js +1 -1
  119. package/dist/components/Badge/index.js +1 -1
  120. package/dist/components/BandEditor/index.js +1 -1
  121. package/dist/components/Button/index.js +1 -1
  122. package/dist/components/Callout/Callout.d.ts +3 -3
  123. package/dist/components/Callout/index.js +1 -1
  124. package/dist/components/Checkbox/index.js +1 -1
  125. package/dist/components/ColorField/index.js +1 -1
  126. package/dist/components/ComboBox/index.js +1 -1
  127. package/dist/components/CurveEditor/index.js +1 -1
  128. package/dist/components/DataGrid/index.js +1 -1
  129. package/dist/components/DetentSlider/DetentSlider.d.ts +52 -0
  130. package/dist/components/DetentSlider/DetentSlider.d.ts.map +1 -0
  131. package/dist/components/DetentSlider/index.d.ts +3 -0
  132. package/dist/components/DetentSlider/index.d.ts.map +1 -0
  133. package/dist/components/DetentSlider/index.js +2 -0
  134. package/dist/components/Dialog/index.js +1 -1
  135. package/dist/components/DragHandleGlyph/DragHandleGlyph.d.ts +12 -0
  136. package/dist/components/DragHandleGlyph/DragHandleGlyph.d.ts.map +1 -0
  137. package/dist/components/DragHandleGlyph/index.d.ts +3 -0
  138. package/dist/components/DragHandleGlyph/index.d.ts.map +1 -0
  139. package/dist/components/DragHandleGlyph/index.js +2 -0
  140. package/dist/components/Field/index.js +1 -1
  141. package/dist/components/FontFamilySelect/FontFamilySelect.d.ts +15 -0
  142. package/dist/components/FontFamilySelect/FontFamilySelect.d.ts.map +1 -0
  143. package/dist/components/FontFamilySelect/index.d.ts +3 -0
  144. package/dist/components/FontFamilySelect/index.d.ts.map +1 -0
  145. package/dist/components/FontFamilySelect/index.js +2 -0
  146. package/dist/components/GradientEditor/index.js +1 -1
  147. package/dist/components/InlineRange/index.js +1 -1
  148. package/dist/components/Input/index.js +1 -1
  149. package/dist/components/ItemList/ItemList.d.ts +45 -0
  150. package/dist/components/ItemList/ItemList.d.ts.map +1 -0
  151. package/dist/components/ItemList/index.d.ts +3 -0
  152. package/dist/components/ItemList/index.d.ts.map +1 -0
  153. package/dist/components/ItemList/index.js +2 -0
  154. package/dist/components/Keycaps/index.js +2 -2
  155. package/dist/components/LayerStack/LayerStack.d.ts +49 -0
  156. package/dist/components/LayerStack/LayerStack.d.ts.map +1 -0
  157. package/dist/components/LayerStack/index.d.ts +2 -0
  158. package/dist/components/LayerStack/index.d.ts.map +1 -0
  159. package/dist/components/LayerStack/index.js +2 -0
  160. package/dist/components/NumberField/index.js +1 -1
  161. package/dist/components/OptionsBar/index.js +1 -1
  162. package/dist/components/PaintInput/index.js +1 -1
  163. package/dist/components/PatternPicker/index.js +1 -1
  164. package/dist/components/Plot2D/index.js +1 -1
  165. package/dist/components/PointPlotter/index.js +1 -1
  166. package/dist/components/Powerline/index.js +2 -2
  167. package/dist/components/Prefs/index.js +1 -1
  168. package/dist/components/Properties/CurveField.d.ts +37 -0
  169. package/dist/components/Properties/CurveField.d.ts.map +1 -0
  170. package/dist/components/Properties/EffectCard.d.ts +68 -0
  171. package/dist/components/Properties/EffectCard.d.ts.map +1 -0
  172. package/dist/components/Properties/PropertyGroup.d.ts +24 -0
  173. package/dist/components/Properties/PropertyGroup.d.ts.map +1 -0
  174. package/dist/components/Properties/PropertyPanel.d.ts +195 -0
  175. package/dist/components/Properties/PropertyPanel.d.ts.map +1 -0
  176. package/dist/components/Properties/index.d.ts +9 -0
  177. package/dist/components/Properties/index.d.ts.map +1 -0
  178. package/dist/components/Properties/index.js +2 -0
  179. package/dist/components/Properties/storyLayouts.d.ts +11 -0
  180. package/dist/components/Properties/storyLayouts.d.ts.map +1 -0
  181. package/dist/components/RadioGroup/index.js +1 -1
  182. package/dist/components/RangeSlider/RangeSlider.d.ts +2 -2
  183. package/dist/components/RangeSlider/index.js +1 -1
  184. package/dist/components/ResizeHandle/index.js +1 -1
  185. package/dist/components/Select/index.js +1 -1
  186. package/dist/components/SelectionPanel/SelectionPanel.d.ts.map +1 -1
  187. package/dist/components/SelectionPanel/index.js +1 -1
  188. package/dist/components/Sidebar/index.js +1 -1
  189. package/dist/components/SidebarPanel/SidebarPanel.d.ts.map +1 -1
  190. package/dist/components/SidebarPanel/index.js +1 -1
  191. package/dist/components/Slider/Slider.d.ts +16 -1
  192. package/dist/components/Slider/Slider.d.ts.map +1 -1
  193. package/dist/components/Slider/index.js +1 -1
  194. package/dist/components/StatusBar/index.js +1 -1
  195. package/dist/components/Switch/index.js +1 -1
  196. package/dist/components/Tabs/index.js +1 -1
  197. package/dist/components/Timeline/AnimatedTimeline.d.ts +15 -0
  198. package/dist/components/Timeline/AnimatedTimeline.d.ts.map +1 -0
  199. package/dist/components/Timeline/EasingPicker.d.ts +8 -0
  200. package/dist/components/Timeline/EasingPicker.d.ts.map +1 -0
  201. package/dist/components/Timeline/Lane.d.ts +28 -0
  202. package/dist/components/Timeline/Lane.d.ts.map +1 -0
  203. package/dist/components/Timeline/Ruler.d.ts +12 -0
  204. package/dist/components/Timeline/Ruler.d.ts.map +1 -0
  205. package/dist/components/Timeline/Timeline.d.ts +39 -0
  206. package/dist/components/Timeline/Timeline.d.ts.map +1 -0
  207. package/dist/components/Timeline/Transport.d.ts +14 -0
  208. package/dist/components/Timeline/Transport.d.ts.map +1 -0
  209. package/dist/components/Timeline/easingSpec.d.ts +16 -0
  210. package/dist/components/Timeline/easingSpec.d.ts.map +1 -0
  211. package/dist/components/Timeline/index.d.ts +11 -0
  212. package/dist/components/Timeline/index.d.ts.map +1 -0
  213. package/dist/components/Timeline/index.js +2 -0
  214. package/dist/components/Timeline/keys.d.ts +34 -0
  215. package/dist/components/Timeline/keys.d.ts.map +1 -0
  216. package/dist/components/Timeline/lanes.d.ts +24 -0
  217. package/dist/components/Timeline/lanes.d.ts.map +1 -0
  218. package/dist/components/Timeline/timeScale.d.ts +31 -0
  219. package/dist/components/Timeline/timeScale.d.ts.map +1 -0
  220. package/dist/components/Toast/index.js +1 -1
  221. package/dist/components/ToggleBar/index.js +1 -1
  222. package/dist/components/ToolButton/index.js +1 -1
  223. package/dist/components/ToolGroup/index.js +1 -1
  224. package/dist/components/ToolOptionsBar/index.js +1 -1
  225. package/dist/components/ToolPalette/index.js +1 -1
  226. package/dist/components/Tooltip/index.js +1 -1
  227. package/dist/format/number.d.ts +13 -0
  228. package/dist/format/number.d.ts.map +1 -1
  229. package/dist/icons/index.d.ts +3 -1
  230. package/dist/icons/index.d.ts.map +1 -1
  231. package/dist/icons/paths.d.ts +2 -0
  232. package/dist/icons/paths.d.ts.map +1 -1
  233. package/dist/index.d.ts +8 -1
  234. package/dist/index.d.ts.map +1 -1
  235. package/dist/index.js +63 -184
  236. package/dist/index.js.map +1 -1
  237. package/dist/style.css +1 -1
  238. package/package.json +5 -4
  239. package/dist/chunks/Callout-CHs98djt.js.map +0 -1
  240. package/dist/chunks/DataGrid-D15I779H.js +0 -210
  241. package/dist/chunks/DataGrid-D15I779H.js.map +0 -1
  242. package/dist/chunks/PaintInput-Cggm9OIl.js.map +0 -1
  243. package/dist/chunks/Plot2D-sPXTw_-l.js +0 -168
  244. package/dist/chunks/Plot2D-sPXTw_-l.js.map +0 -1
  245. package/dist/chunks/RangeSlider-B-n_7AgJ.js.map +0 -1
  246. package/dist/chunks/SelectionPanel-C7kygTFE.js +0 -446
  247. package/dist/chunks/SelectionPanel-C7kygTFE.js.map +0 -1
  248. package/dist/chunks/SidebarPanel-AeSc7wNR.js +0 -59
  249. package/dist/chunks/SidebarPanel-AeSc7wNR.js.map +0 -1
  250. package/dist/chunks/Slider-cxWR47gi.js +0 -259
  251. package/dist/chunks/Slider-cxWR47gi.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ //#region src/dlog.ts
2
+ var e = ["weasel.debug", "weaseldraw.debug"], t = null;
3
+ function n() {
4
+ let t = {
5
+ all: !1,
6
+ set: /* @__PURE__ */ new Set()
7
+ };
8
+ if (typeof localStorage > "u") return t;
9
+ try {
10
+ for (let t of e) {
11
+ let e = localStorage.getItem(t);
12
+ if (!(e == null || e === "")) return e === "1" || e === "true" || e === "*" ? {
13
+ all: !0,
14
+ set: /* @__PURE__ */ new Set()
15
+ } : {
16
+ all: !1,
17
+ set: new Set(e.split(/[\s,]+/).filter(Boolean))
18
+ };
19
+ }
20
+ return t;
21
+ } catch {
22
+ return t;
23
+ }
24
+ }
25
+ function r() {
26
+ return t === null && (t = n()), t;
27
+ }
28
+ function i(e) {
29
+ let t = r();
30
+ return t.all || t.set.has(e);
31
+ }
32
+ function a(e, ...t) {
33
+ i(e) && console.debug(`[${e}]`, ...t);
34
+ }
35
+ //#endregion
36
+ export { i as n, a as t };
37
+
38
+ //# sourceMappingURL=dlog-CMYiRF3Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dlog-CMYiRF3Q.js","names":[],"sources":["../../src/dlog.ts"],"sourcesContent":["/**\n * Namespaced, opt-in console tracing. Off by default; production builds\n * may strip the calls entirely depending on the bundler.\n *\n * Enable in the browser:\n *\n * localStorage.setItem('weasel.debug', '*') // all namespaces\n * localStorage.setItem('weasel.debug', 'curve-editor') // just curve editor\n * localStorage.setItem('weasel.debug', 'curve-editor,layer-stack')\n *\n * Each component picks a stable namespace and calls `dlog(namespace, ...)`.\n * Useful for tracing pointer/event flows that are hard to capture\n * post-hoc (drag handlers, gesture sequences, selection mutations).\n *\n * The flag is read once and cached for the page session — reload to\n * pick up changes. Cheap hot-path checks (one nullish-coalesce + Set\n * lookup) so leaving calls in place is fine.\n *\n * Mirrors `src/debug/flag.ts` in the kit. Two impls live here because\n * weasel-ui doesn't depend on the kit, but both read the same\n * localStorage keys so behavior is uniform. See the kit copy for the\n * canonical list of kit-level namespaces.\n *\n * Known weasel-ui namespaces:\n * - plot2d — Plot2D mount / unmount\n * - curve-editor — CurveEditor pointer flow\n */\n\nconst KEYS = ['weasel.debug', 'weaseldraw.debug'] as const;\n\ninterface Cached {\n all: boolean;\n set: Set<string>;\n}\n\nlet cached: Cached | null = null;\n\nfunction read(): Cached {\n const empty: Cached = { all: false, set: new Set() };\n if (typeof localStorage === 'undefined') return empty;\n try {\n for (const k of KEYS) {\n const v = localStorage.getItem(k);\n if (v == null || v === '') continue;\n if (v === '1' || v === 'true' || v === '*') return { all: true, set: new Set() };\n return { all: false, set: new Set(v.split(/[\\s,]+/).filter(Boolean)) };\n }\n return empty;\n } catch {\n return empty;\n }\n}\n\nfunction get(): Cached {\n if (cached === null) cached = read();\n return cached;\n}\n\n/** True when `namespace` (or `*`) is enabled. */\nexport function isDebugEnabled(namespace: string): boolean {\n const c = get();\n return c.all || c.set.has(namespace);\n}\n\n/** Conditional `console.debug` — no-op unless `namespace` (or `*`) is enabled.\n * Each call is prefixed with `[namespace]` so the source is searchable. */\nexport function dlog(namespace: string, ...args: unknown[]): void {\n if (!isDebugEnabled(namespace)) return;\n // eslint-disable-next-line no-console\n console.debug(`[${namespace}]`, ...args);\n}\n"],"mappings":";AA4BA,IAAM,IAAO,CAAC,gBAAgB,mBAAmB,EAO7C,IAAwB;AAE5B,SAAS,IAAe;CACtB,IAAM,IAAgB;EAAE,KAAK;EAAO,qBAAK,IAAI,KAAK;EAAE;AACpD,KAAI,OAAO,eAAiB,IAAa,QAAO;AAChD,KAAI;AACF,OAAK,IAAM,KAAK,GAAM;GACpB,IAAM,IAAI,aAAa,QAAQ,EAAE;AAC7B,cAAK,QAAQ,MAAM,IAEvB,QADI,MAAM,OAAO,MAAM,UAAU,MAAM,MAAY;IAAE,KAAK;IAAM,qBAAK,IAAI,KAAK;IAAE,GACzE;IAAE,KAAK;IAAO,KAAK,IAAI,IAAI,EAAE,MAAM,SAAS,CAAC,OAAO,QAAQ,CAAC;IAAE;;AAExE,SAAO;SACD;AACN,SAAO;;;AAIX,SAAS,IAAc;AAErB,QADI,MAAW,SAAM,IAAS,GAAM,GAC7B;;AAIT,SAAgB,EAAe,GAA4B;CACzD,IAAM,IAAI,GAAK;AACf,QAAO,EAAE,OAAO,EAAE,IAAI,IAAI,EAAU;;AAKtC,SAAgB,EAAK,GAAmB,GAAG,GAAuB;AAC3D,GAAe,EAAU,IAE9B,QAAQ,MAAM,IAAI,EAAU,IAAI,GAAG,EAAK"}
@@ -0,0 +1,144 @@
1
+ import { t as e } from "./Icon-CxoJb_bw.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import { ArrowIcon as n, EllipseIcon as r, EyedropperIcon as i, HandIcon as a, ImageIcon as o, LassoIcon as s, LineIcon as c, PenIcon as l, PencilIcon as u, PolygonIcon as d, RectIcon as f, SelectIcon as p, StarIcon as m, TextIcon as h, UnknownIcon as g } from "@weasel-js/core";
4
+ //#region src/icons/index.tsx
5
+ var _ = (n) => /* @__PURE__ */ t(e, {
6
+ name: "clone",
7
+ ...n
8
+ }), v = (n) => /* @__PURE__ */ t(e, {
9
+ name: "reset",
10
+ ...n
11
+ }), y = (n) => /* @__PURE__ */ t(e, {
12
+ name: "close",
13
+ ...n
14
+ }), b = (n) => /* @__PURE__ */ t(e, {
15
+ name: "export",
16
+ ...n
17
+ }), x = (n) => /* @__PURE__ */ t(e, {
18
+ name: "zoomIn",
19
+ ...n
20
+ }), S = (n) => /* @__PURE__ */ t(e, {
21
+ name: "pan",
22
+ ...n
23
+ }), C = (n) => /* @__PURE__ */ t(e, {
24
+ name: "add",
25
+ ...n
26
+ }), w = (n) => /* @__PURE__ */ t(e, {
27
+ name: "remove",
28
+ ...n
29
+ }), T = (n) => /* @__PURE__ */ t(e, {
30
+ name: "delete",
31
+ ...n
32
+ }), E = (n) => /* @__PURE__ */ t(e, {
33
+ name: "sort",
34
+ ...n
35
+ }), D = (n) => /* @__PURE__ */ t(e, {
36
+ name: "undo",
37
+ ...n
38
+ }), O = (n) => /* @__PURE__ */ t(e, {
39
+ name: "redo",
40
+ ...n
41
+ }), k = (n) => /* @__PURE__ */ t(e, {
42
+ name: "zoomOut",
43
+ ...n
44
+ }), A = (n) => /* @__PURE__ */ t(e, {
45
+ name: "fit",
46
+ ...n
47
+ }), j = (n) => /* @__PURE__ */ t(e, {
48
+ name: "snapshot",
49
+ ...n
50
+ }), ee = (n) => /* @__PURE__ */ t(e, {
51
+ name: "play",
52
+ ...n
53
+ }), M = (n) => /* @__PURE__ */ t(e, {
54
+ name: "pause",
55
+ ...n
56
+ }), N = (n) => /* @__PURE__ */ t(e, {
57
+ name: "stop",
58
+ ...n
59
+ }), P = (n) => /* @__PURE__ */ t(e, {
60
+ name: "step",
61
+ ...n
62
+ }), F = (n) => /* @__PURE__ */ t(e, {
63
+ name: "crosshair",
64
+ ...n
65
+ }), I = (n) => /* @__PURE__ */ t(e, {
66
+ name: "fullscreen",
67
+ ...n
68
+ }), L = (n) => /* @__PURE__ */ t(e, {
69
+ name: "compare",
70
+ ...n
71
+ }), R = (n) => /* @__PURE__ */ t(e, {
72
+ name: "filter",
73
+ ...n
74
+ }), z = (n) => /* @__PURE__ */ t(e, {
75
+ name: "search",
76
+ ...n
77
+ }), B = (n) => /* @__PURE__ */ t(e, {
78
+ name: "loupe",
79
+ ...n
80
+ }), V = (n) => /* @__PURE__ */ t(e, {
81
+ name: "layers",
82
+ ...n
83
+ }), H = (n) => /* @__PURE__ */ t(e, {
84
+ name: "lock",
85
+ ...n
86
+ }), U = (n) => /* @__PURE__ */ t(e, {
87
+ name: "unlock",
88
+ ...n
89
+ }), W = (n) => /* @__PURE__ */ t(e, {
90
+ name: "visible",
91
+ ...n
92
+ }), G = (n) => /* @__PURE__ */ t(e, {
93
+ name: "hidden",
94
+ ...n
95
+ }), K = (n) => /* @__PURE__ */ t(e, {
96
+ name: "pin",
97
+ ...n
98
+ }), q = (n) => /* @__PURE__ */ t(e, {
99
+ name: "link",
100
+ ...n
101
+ }), J = (n) => /* @__PURE__ */ t(e, {
102
+ name: "collapse",
103
+ ...n
104
+ }), Y = (n) => /* @__PURE__ */ t(e, {
105
+ name: "expand",
106
+ ...n
107
+ }), X = (n) => /* @__PURE__ */ t(e, {
108
+ name: "chevron",
109
+ ...n
110
+ }), Z = (n) => /* @__PURE__ */ t(e, {
111
+ name: "tune",
112
+ ...n
113
+ }), Q = (n) => /* @__PURE__ */ t(e, {
114
+ name: "grid",
115
+ ...n
116
+ }), $ = (n) => /* @__PURE__ */ t(e, {
117
+ name: "snap",
118
+ ...n
119
+ }), te = (n) => /* @__PURE__ */ t(e, {
120
+ name: "measure",
121
+ ...n
122
+ }), ne = (n) => /* @__PURE__ */ t(e, {
123
+ name: "randomize",
124
+ ...n
125
+ }), re = (n) => /* @__PURE__ */ t(e, {
126
+ name: "refresh",
127
+ ...n
128
+ }), ie = (n) => /* @__PURE__ */ t(e, {
129
+ name: "info",
130
+ ...n
131
+ }), ae = (n) => /* @__PURE__ */ t(e, {
132
+ name: "warning",
133
+ ...n
134
+ }), oe = (n) => /* @__PURE__ */ t(e, {
135
+ name: "error",
136
+ ...n
137
+ }), se = (n) => /* @__PURE__ */ t(e, {
138
+ name: "busy",
139
+ ...n
140
+ });
141
+ //#endregion
142
+ export { Z as $, te as A, O as B, ie as C, q as D, c as E, K as F, p as G, w as H, ee as I, E as J, $ as K, d as L, M, l as N, H as O, u as P, h as Q, ne as R, o as S, V as T, v as U, re as V, z as W, P as X, m as Y, N as Z, A as _, _ as a, x as at, a as b, L as c, r as d, D as et, oe as f, R as g, i as h, X as i, ae as it, S as j, B as k, F as l, b as m, n, U as nt, y as o, k as ot, Y as p, j as q, se as r, W as rt, J as s, C as t, g as tt, T as u, I as v, s as w, G as x, Q as y, f as z };
143
+
144
+ //# sourceMappingURL=icons-CdLHgzV8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons-CdLHgzV8.js","names":[],"sources":["../../src/icons/index.tsx"],"sourcesContent":["import { Icon, type IconProps } from './Icon';\n\nexport { Icon } from './Icon';\nexport type { IconProps } from './Icon';\nexport { ICON_PATHS } from './paths';\nexport type { IconName } from './paths';\n\n// Tool glyphs live in @weasel-js/core because core needs them for\n// `Tool.presentation.icon` defaults and cannot depend on this package.\n// Re-exported here so consumers have one import site for the whole set.\nexport {\n SelectIcon, LassoIcon, RectIcon, EllipseIcon, ImageIcon, EyedropperIcon,\n LineIcon, ArrowIcon, PolygonIcon, StarIcon, PencilIcon, TextIcon, PenIcon, HandIcon,\n UnknownIcon,\n} from '@weasel-js/core';\n\nexport const CloneIcon = (p: IconProps) => <Icon name=\"clone\" {...p} />;\nexport const ResetIcon = (p: IconProps) => <Icon name=\"reset\" {...p} />;\nexport const CloseIcon = (p: IconProps) => <Icon name=\"close\" {...p} />;\nexport const ExportIcon = (p: IconProps) => <Icon name=\"export\" {...p} />;\nexport const ZoomInIcon = (p: IconProps) => <Icon name=\"zoomIn\" {...p} />;\nexport const PanIcon = (p: IconProps) => <Icon name=\"pan\" {...p} />;\nexport const AddIcon = (p: IconProps) => <Icon name=\"add\" {...p} />;\nexport const RemoveIcon = (p: IconProps) => <Icon name=\"remove\" {...p} />;\nexport const DeleteIcon = (p: IconProps) => <Icon name=\"delete\" {...p} />;\nexport const SortIcon = (p: IconProps) => <Icon name=\"sort\" {...p} />;\nexport const UndoIcon = (p: IconProps) => <Icon name=\"undo\" {...p} />;\nexport const RedoIcon = (p: IconProps) => <Icon name=\"redo\" {...p} />;\nexport const ZoomOutIcon = (p: IconProps) => <Icon name=\"zoomOut\" {...p} />;\nexport const FitIcon = (p: IconProps) => <Icon name=\"fit\" {...p} />;\nexport const SnapshotIcon = (p: IconProps) => <Icon name=\"snapshot\" {...p} />;\nexport const PlayIcon = (p: IconProps) => <Icon name=\"play\" {...p} />;\nexport const PauseIcon = (p: IconProps) => <Icon name=\"pause\" {...p} />;\nexport const StopIcon = (p: IconProps) => <Icon name=\"stop\" {...p} />;\nexport const StepIcon = (p: IconProps) => <Icon name=\"step\" {...p} />;\nexport const CrosshairIcon = (p: IconProps) => <Icon name=\"crosshair\" {...p} />;\nexport const FullscreenIcon = (p: IconProps) => <Icon name=\"fullscreen\" {...p} />;\nexport const CompareIcon = (p: IconProps) => <Icon name=\"compare\" {...p} />;\nexport const FilterIcon = (p: IconProps) => <Icon name=\"filter\" {...p} />;\nexport const SearchIcon = (p: IconProps) => <Icon name=\"search\" {...p} />;\nexport const LoupeIcon = (p: IconProps) => <Icon name=\"loupe\" {...p} />;\nexport const LayersIcon = (p: IconProps) => <Icon name=\"layers\" {...p} />;\nexport const LockIcon = (p: IconProps) => <Icon name=\"lock\" {...p} />;\nexport const UnlockIcon = (p: IconProps) => <Icon name=\"unlock\" {...p} />;\nexport const VisibleIcon = (p: IconProps) => <Icon name=\"visible\" {...p} />;\nexport const HiddenIcon = (p: IconProps) => <Icon name=\"hidden\" {...p} />;\nexport const PinIcon = (p: IconProps) => <Icon name=\"pin\" {...p} />;\nexport const LinkIcon = (p: IconProps) => <Icon name=\"link\" {...p} />;\nexport const CollapseIcon = (p: IconProps) => <Icon name=\"collapse\" {...p} />;\nexport const ExpandIcon = (p: IconProps) => <Icon name=\"expand\" {...p} />;\nexport const ChevronIcon = (p: IconProps) => <Icon name=\"chevron\" {...p} />;\nexport const TuneIcon = (p: IconProps) => <Icon name=\"tune\" {...p} />;\nexport const GridIcon = (p: IconProps) => <Icon name=\"grid\" {...p} />;\nexport const SnapIcon = (p: IconProps) => <Icon name=\"snap\" {...p} />;\nexport const MeasureIcon = (p: IconProps) => <Icon name=\"measure\" {...p} />;\nexport const RandomizeIcon = (p: IconProps) => <Icon name=\"randomize\" {...p} />;\nexport const RefreshIcon = (p: IconProps) => <Icon name=\"refresh\" {...p} />;\nexport const InfoIcon = (p: IconProps) => <Icon name=\"info\" {...p} />;\nexport const WarningIcon = (p: IconProps) => <Icon name=\"warning\" {...p} />;\nexport const ErrorIcon = (p: IconProps) => <Icon name=\"error\" {...p} />;\nexport const BusyIcon = (p: IconProps) => <Icon name=\"busy\" {...p} />;\n"],"mappings":"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"}
@@ -19,4 +19,4 @@ function e(e) {
19
19
  //#endregion
20
20
  export { e as t };
21
21
 
22
- //# sourceMappingURL=keyGlyph-DNpLxF8u.js.map
22
+ //# sourceMappingURL=keyGlyph-BLFMKZgF.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyGlyph-DNpLxF8u.js","names":[],"sources":["../../src/components/Keycaps/keyGlyph.ts"],"sourcesContent":["/** Apple-style glyph for a DOM `KeyboardEvent.key` value. Covers escape,\n * delete/backspace, arrows, enter/return, tab, space. Unknown keys are\n * upper-cased (so `'a'` reads as `A` on a keycap) and returned unchanged\n * otherwise — making this safe to apply uniformly without a `has-glyph`\n * check at the call site. */\nexport function keyGlyph(rawKey: string): string {\n switch (rawKey) {\n case 'Escape': return '⎋';\n case 'Backspace': return '⌫';\n case 'Delete': return '⌦';\n case 'ArrowUp': return '↑';\n case 'ArrowDown': return '↓';\n case 'ArrowLeft': return '←';\n case 'ArrowRight': return '→';\n case 'Enter':\n case 'Return': return '↵';\n case 'Tab': return '⇥';\n case ' ':\n case 'Space': return '␣';\n default: return rawKey.toUpperCase();\n }\n}\n"],"mappings":";AAKA,SAAgB,EAAS,GAAwB;AAC/C,SAAQ,GAAR;EACE,KAAK,SAAU,QAAO;EACtB,KAAK,YAAa,QAAO;EACzB,KAAK,SAAU,QAAO;EACtB,KAAK,UAAW,QAAO;EACvB,KAAK,YAAa,QAAO;EACzB,KAAK,YAAa,QAAO;EACzB,KAAK,aAAc,QAAO;EAC1B,KAAK;EACL,KAAK,SAAU,QAAO;EACtB,KAAK,MAAO,QAAO;EACnB,KAAK;EACL,KAAK,QAAS,QAAO;EACrB,QAAS,QAAO,EAAO,aAAa"}
1
+ {"version":3,"file":"keyGlyph-BLFMKZgF.js","names":[],"sources":["../../src/components/Keycaps/keyGlyph.ts"],"sourcesContent":["/** Apple-style glyph for a DOM `KeyboardEvent.key` value. Covers escape,\n * delete/backspace, arrows, enter/return, tab, space. Unknown keys are\n * upper-cased (so `'a'` reads as `A` on a keycap) and returned unchanged\n * otherwise — making this safe to apply uniformly without a `has-glyph`\n * check at the call site. */\nexport function keyGlyph(rawKey: string): string {\n switch (rawKey) {\n case 'Escape': return '⎋';\n case 'Backspace': return '⌫';\n case 'Delete': return '⌦';\n case 'ArrowUp': return '↑';\n case 'ArrowDown': return '↓';\n case 'ArrowLeft': return '←';\n case 'ArrowRight': return '→';\n case 'Enter':\n case 'Return': return '↵';\n case 'Tab': return '⇥';\n case ' ':\n case 'Space': return '␣';\n default: return rawKey.toUpperCase();\n }\n}\n"],"mappings":";AAKA,SAAgB,EAAS,GAAwB;AAC/C,SAAQ,GAAR;EACE,KAAK,SAAU,QAAO;EACtB,KAAK,YAAa,QAAO;EACzB,KAAK,SAAU,QAAO;EACtB,KAAK,UAAW,QAAO;EACvB,KAAK,YAAa,QAAO;EACzB,KAAK,YAAa,QAAO;EACzB,KAAK,aAAc,QAAO;EAC1B,KAAK;EACL,KAAK,SAAU,QAAO;EACtB,KAAK,MAAO,QAAO;EACnB,KAAK;EACL,KAAK,QAAS,QAAO;EACrB,QAAS,QAAO,EAAO,aAAa"}
@@ -0,0 +1,18 @@
1
+ //#region src/format/number.ts
2
+ var e = "−";
3
+ function t(e, t) {
4
+ return (Number.isFinite(e) ? e.toLocaleString(void 0, t) : String(e)).replace(/^-/, "−");
5
+ }
6
+ function n(e) {
7
+ return Number(e.replace("−", "-"));
8
+ }
9
+ function r(e) {
10
+ return String(e).replace(/^-/, "−");
11
+ }
12
+ function i(e) {
13
+ return Number.isFinite(e) ? e <= 2 ? `${r(Math.round(e * 100))}%` : e >= 100 ? `${Math.round(e).toLocaleString("en-US")}x` : `${r(Math.round(e * 10) / 10)}x` : String(e);
14
+ }
15
+ //#endregion
16
+ export { n as i, t as n, i as r, e as t };
17
+
18
+ //# sourceMappingURL=number-D3TDawLC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-D3TDawLC.js","names":[],"sources":["../../src/format/number.ts"],"sourcesContent":["/**\n * Display-formatter for numbers. Use this anywhere a number is shown to\n * a user. The whole point: negative values get prefixed with the real\n * MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that\n * `toLocaleString` and template literals produce by default.\n *\n * U+2212 is the same visual width as `+` and reads as a sign rather\n * than a hyphen — columns of signed numbers align cleanly and the\n * glyph doesn't get confused with a bullet or list dash.\n */\nexport const MINUS_SIGN = '−';\n\n/**\n * Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII\n * hyphen `toLocaleString` emits. Non-finite values stringify as-is.\n */\nexport function formatNumber(value: number, options?: Intl.NumberFormatOptions): string {\n const formatted = Number.isFinite(value)\n ? value.toLocaleString(undefined, options)\n : String(value);\n return formatted.replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Parses a string that may carry {@link MINUS_SIGN} in place of the ASCII\n * hyphen. The inverse of {@link formatNumber} for any editing surface that\n * renders its value through it and reads the edited text back.\n */\nexport function parseSignedNumber(text: string): number {\n return Number(text.replace(MINUS_SIGN, '-'));\n}\n\n/** {@link String} with the leading ASCII hyphen swapped for {@link MINUS_SIGN}.\n * Locale-independent, unlike `toLocaleString`. */\nfunction signedString(value: number): string {\n return String(value).replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Formats a zoom factor for display. Below 2x a percentage reads naturally;\n * past it the numbers get long and a multiplier is what people say out loud,\n * so 250% shows as `2.5x`. Past 100x a tenth is noise, so the decimal is\n * dropped and thousands are grouped: `1009.74` reads as `1,010x`.\n */\nexport function formatZoom(zoom: number): string {\n if (!Number.isFinite(zoom)) return String(zoom);\n if (zoom <= 2) return `${signedString(Math.round(zoom * 100))}%`;\n if (zoom >= 100) return `${Math.round(zoom).toLocaleString('en-US')}x`;\n return `${signedString(Math.round(zoom * 10) / 10)}x`;\n}\n"],"mappings":";AAUA,IAAa,IAAa;AAM1B,SAAgB,EAAa,GAAe,GAA4C;AAItF,SAHkB,OAAO,SAAS,EAAM,GACpC,EAAM,eAAe,KAAA,GAAW,EAAQ,GACxC,OAAO,EAAM,EACA,QAAQ,MAAA,IAAiB;;AAQ5C,SAAgB,EAAkB,GAAsB;AACtD,QAAO,OAAO,EAAK,QAAA,KAAoB,IAAI,CAAC;;AAK9C,SAAS,EAAa,GAAuB;AAC3C,QAAO,OAAO,EAAM,CAAC,QAAQ,MAAA,IAAiB;;AAShD,SAAgB,EAAW,GAAsB;AAI/C,QAHK,OAAO,SAAS,EAAK,GACtB,KAAQ,IAAU,GAAG,EAAa,KAAK,MAAM,IAAO,IAAI,CAAC,CAAC,KAC1D,KAAQ,MAAY,GAAG,KAAK,MAAM,EAAK,CAAC,eAAe,QAAQ,CAAC,KAC7D,GAAG,EAAa,KAAK,MAAM,IAAO,GAAG,GAAG,GAAG,CAAC,KAHhB,OAAO,EAAK"}
@@ -8,4 +8,4 @@ var e = {
8
8
  //#endregion
9
9
  export { e as t };
10
10
 
11
- //# sourceMappingURL=segmentedControl.module-D4b7x19O.js.map
11
+ //# sourceMappingURL=segmentedControl.module-XADeq9e5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"segmentedControl.module-D4b7x19O.js","names":[],"sources":["../../src/components/segmentedControl.module.css"],"sourcesContent":["/* Shared by ActionsBar and OptionsBar, which look identical and differ only\n in what a segment does. Lives here rather than in either component so\n neither owns the other's styling.\n\n Aqua-glass segmented control. The track is a pill-shaped well; the\n selected segment becomes a tinted glass cylinder that reads as the same\n \"lozenge\" family as the standalone Button. Visual params come from the\n `--btn-*` custom properties (see Button.module.css) so the Button Lab\n can tune both surfaces with one set of sliders. */\n.root {\n display: inline-flex;\n height: var(--tb-h, var(--wzl-control-h, 24px));\n padding: 2px;\n background: linear-gradient(\n 180deg,\n rgba(0, 0, 0, 0.18) 0%,\n rgba(0, 0, 0, 0.05) 100%\n );\n border-radius: var(--wzl-radius-pill);\n /* Clip segments to the track outline so interior corners read crisp and\n the selected segment's glass treatment doesn't paint over the rounded\n outer pixels. */\n overflow: hidden;\n box-shadow:\n inset 0 1px 2px rgba(0, 0, 0, 0.4),\n 0 1px 0 rgba(255, 255, 255, 0.06);\n user-select: none;\n -webkit-user-select: none;\n touch-action: none;\n}\n\n.segment {\n position: relative;\n flex: 1 1 0;\n min-width: 0;\n padding: 0 12px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n margin: 0;\n font-family: var(--wzl-font-ui);\n font-weight: var(--wzl-font-weight-normal);\n font-size: var(--btn-fontsize, var(--wzl-font-size));\n line-height: 1;\n color: var(--wzl-fg-muted);\n cursor: pointer;\n /* Only round the outer corners of the bar — middle segments stay square\n so the seams between them don't render as facing parentheses. */\n border-radius: 0;\n isolation: isolate;\n overflow: hidden;\n transition: color var(--wzl-motion-fast);\n}\n\n.segment:first-child {\n border-radius: var(--wzl-radius-pill) 0 0 var(--wzl-radius-pill);\n}\n\n.segment:last-child {\n border-radius: 0 var(--wzl-radius-pill) var(--wzl-radius-pill) 0;\n}\n\n.segment:only-child {\n border-radius: var(--wzl-radius-pill);\n}\n\n.segment:focus-visible {\n outline: 2px solid var(--wzl-accent);\n outline-offset: -2px;\n}\n\n.segment:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.segment:hover:not(:disabled):not(.segmentSelected) {\n color: var(--wzl-fg);\n}\n\n/* Selected segment — full Aqua glass cylinder. Mirrors Button.variant_primary. */\n.segmentSelected {\n background: linear-gradient(\n 180deg,\n color-mix(in srgb, var(--wzl-accent) var(--btn-top-alpha, 45%), transparent) 0%,\n color-mix(in srgb, var(--wzl-accent) var(--btn-upper-alpha, 70%), transparent) calc(var(--btn-equator, 52%) - var(--btn-equator-spread, 12%)),\n color-mix(in srgb, var(--wzl-accent) var(--btn-equator-tint, 95%), white) var(--btn-equator, 52%),\n var(--wzl-accent) calc(var(--btn-equator, 52%) + var(--btn-equator-spread, 12%) * 1.6),\n color-mix(in srgb, var(--wzl-accent) var(--btn-base-tint, 70%), black) 100%\n );\n backdrop-filter: blur(var(--btn-blur, 6px)) saturate(var(--btn-saturate, 1.3));\n -webkit-backdrop-filter: blur(var(--btn-blur, 6px)) saturate(var(--btn-saturate, 1.3));\n color: var(--wzl-fg-on-accent);\n text-shadow:\n 0 1px 0 rgba(0, 0, 0, var(--btn-text-shadow, 0.35)),\n var(--btn-text-inset-x, 0px) var(--btn-text-inset-y, 1px) 0 rgba(0, 0, 0, var(--btn-text-inset, 0.55)),\n 0 0 6px rgba(0, 0, 0, calc(var(--btn-text-shadow, 0.35) * 0.5));\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, var(--btn-inset-hi, 0.42)),\n inset 0 -1px 2px rgba(0, 0, 0, var(--btn-inset-lo, 0.3)),\n 0 0 0 1px rgba(0, 0, 0, var(--btn-rim, 0.22)),\n 0 1px 2px rgba(0, 0, 0, var(--btn-drop-near, 0.3)),\n 0 2px 4px rgba(0, 0, 0, calc(var(--btn-drop-far, 0.18) * 0.8));\n}\n\n/* Specular gloss on the selected segment. Top corners inherit the\n segment's radius so they hug the upper edge cleanly; bottom corners\n are flattened so the gloss ends in a straight line at the equator\n instead of two little curves that read as `)(` brackets. */\n.segmentSelected::before {\n content: '';\n position: absolute;\n inset: 1px 1px var(--btn-gloss-bottom, 50%) 1px;\n border-radius: inherit;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, var(--btn-gloss-top, 0.42)) 0%,\n rgba(255, 255, 255, var(--btn-gloss-mid, 0.12)) 60%,\n rgba(255, 255, 255, 0) 100%\n );\n pointer-events: none;\n z-index: 1;\n}\n\n.segmentSelected > * {\n position: relative;\n z-index: 2;\n}\n\n/* Small variant — ~60% of the default height, with proportionally reduced\n padding and font. Sized for dense surfaces (lab control panels, inline\n filters, etc.). */\n.size_sm {\n height: 17px;\n padding: 1px;\n}\n\n.size_sm .segment {\n padding: 0 8px;\n font-size: var(--wzl-font-size-sm);\n}\n\n/* Minimal variant — strips the pill track, glass selected state, inset\n shadows, and outer padding. Used in dense diagnostic surfaces (dispatch\n trace, lab inspectors) where the bar must read as plain text controls. */\n.variant_minimal {\n height: auto;\n padding: 0;\n background: none;\n border-radius: 0;\n box-shadow: none;\n gap: 2px;\n}\n\n.variant_minimal .segment {\n padding: 0 4px;\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-medium);\n line-height: 1.4;\n border-radius: var(--wzl-radius-sm);\n color: var(--wzl-fg-muted);\n transition: none;\n}\n\n.variant_minimal .segment:first-child,\n.variant_minimal .segment:last-child,\n.variant_minimal .segment:only-child {\n border-radius: var(--wzl-radius-sm);\n}\n\n.variant_minimal .segment:hover:not(:disabled):not(.segmentSelected) {\n color: var(--wzl-fg);\n background: var(--wzl-surface-hover);\n}\n\n.variant_minimal .segmentSelected {\n background: none;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n color: var(--wzl-accent-fg, var(--wzl-accent));\n text-shadow: none;\n box-shadow: none;\n font-weight: var(--wzl-font-weight-medium);\n}\n\n.variant_minimal .segmentSelected::before {\n content: none;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"segmentedControl.module-XADeq9e5.js","names":[],"sources":["../../src/components/segmentedControl.module.css"],"sourcesContent":["/* Shared by ActionsBar and OptionsBar, which look identical and differ only\n in what a segment does. Lives here rather than in either component so\n neither owns the other's styling.\n\n Aqua-glass segmented control. The track is a pill-shaped well; the\n selected segment becomes a tinted glass cylinder that reads as the same\n \"lozenge\" family as the standalone Button. Visual params come from the\n `--btn-*` custom properties (see Button.module.css) so the Button Lab\n can tune both surfaces with one set of sliders. */\n.root {\n display: inline-flex;\n height: var(--tb-h, var(--wzl-control-h, 24px));\n padding: 2px;\n background: linear-gradient(\n 180deg,\n rgba(0, 0, 0, 0.18) 0%,\n rgba(0, 0, 0, 0.05) 100%\n );\n border-radius: var(--wzl-radius-pill);\n /* Clip segments to the track outline so interior corners read crisp and\n the selected segment's glass treatment doesn't paint over the rounded\n outer pixels. */\n overflow: hidden;\n box-shadow:\n inset 0 1px 2px rgba(0, 0, 0, 0.4),\n 0 1px 0 rgba(255, 255, 255, 0.06);\n user-select: none;\n -webkit-user-select: none;\n touch-action: none;\n}\n\n.segment {\n position: relative;\n flex: 1 1 0;\n min-width: 0;\n padding: 0 12px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n margin: 0;\n font-family: var(--wzl-font-ui);\n font-weight: var(--wzl-font-weight-normal);\n font-size: var(--btn-fontsize, var(--wzl-font-size));\n line-height: 1;\n color: var(--wzl-fg-muted);\n cursor: pointer;\n /* Only round the outer corners of the bar — middle segments stay square\n so the seams between them don't render as facing parentheses. */\n border-radius: 0;\n isolation: isolate;\n overflow: hidden;\n transition: color var(--wzl-motion-fast);\n}\n\n.segment:first-child {\n border-radius: var(--wzl-radius-pill) 0 0 var(--wzl-radius-pill);\n}\n\n.segment:last-child {\n border-radius: 0 var(--wzl-radius-pill) var(--wzl-radius-pill) 0;\n}\n\n.segment:only-child {\n border-radius: var(--wzl-radius-pill);\n}\n\n.segment:focus-visible {\n outline: 2px solid var(--wzl-accent);\n outline-offset: -2px;\n}\n\n.segment:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.segment:hover:not(:disabled):not(.segmentSelected) {\n color: var(--wzl-fg);\n}\n\n/* Selected segment — full Aqua glass cylinder. Mirrors Button.variant_primary. */\n.segmentSelected {\n background: linear-gradient(\n 180deg,\n color-mix(in srgb, var(--wzl-accent) var(--btn-top-alpha, 45%), transparent) 0%,\n color-mix(in srgb, var(--wzl-accent) var(--btn-upper-alpha, 70%), transparent) calc(var(--btn-equator, 52%) - var(--btn-equator-spread, 12%)),\n color-mix(in srgb, var(--wzl-accent) var(--btn-equator-tint, 95%), white) var(--btn-equator, 52%),\n var(--wzl-accent) calc(var(--btn-equator, 52%) + var(--btn-equator-spread, 12%) * 1.6),\n color-mix(in srgb, var(--wzl-accent) var(--btn-base-tint, 70%), black) 100%\n );\n backdrop-filter: blur(var(--btn-blur, 6px)) saturate(var(--btn-saturate, 1.3));\n -webkit-backdrop-filter: blur(var(--btn-blur, 6px)) saturate(var(--btn-saturate, 1.3));\n color: var(--wzl-fg-on-accent);\n text-shadow:\n 0 1px 0 rgba(0, 0, 0, var(--btn-text-shadow, 0.35)),\n var(--btn-text-inset-x, 0px) var(--btn-text-inset-y, 1px) 0 rgba(0, 0, 0, var(--btn-text-inset, 0.55)),\n 0 0 6px rgba(0, 0, 0, calc(var(--btn-text-shadow, 0.35) * 0.5));\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, var(--btn-inset-hi, 0.42)),\n inset 0 -1px 2px rgba(0, 0, 0, var(--btn-inset-lo, 0.3)),\n 0 0 0 1px rgba(0, 0, 0, var(--btn-rim, 0.22)),\n 0 1px 2px rgba(0, 0, 0, var(--btn-drop-near, 0.3)),\n 0 2px 4px rgba(0, 0, 0, calc(var(--btn-drop-far, 0.18) * 0.8));\n}\n\n/* Specular gloss on the selected segment. Top corners inherit the\n segment's radius so they hug the upper edge cleanly; bottom corners\n are flattened so the gloss ends in a straight line at the equator\n instead of two little curves that read as `)(` brackets. */\n.segmentSelected::before {\n content: '';\n position: absolute;\n inset: 1px 1px var(--btn-gloss-bottom, 50%) 1px;\n border-radius: inherit;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, var(--btn-gloss-top, 0.42)) 0%,\n rgba(255, 255, 255, var(--btn-gloss-mid, 0.12)) 60%,\n rgba(255, 255, 255, 0) 100%\n );\n pointer-events: none;\n z-index: 1;\n}\n\n.segmentSelected > * {\n position: relative;\n z-index: 2;\n}\n\n/* Small variant — ~60% of the default height, with proportionally reduced\n padding and font. Sized for dense surfaces (lab control panels, inline\n filters, etc.). */\n.size_sm {\n height: 17px;\n padding: 1px;\n}\n\n.size_sm .segment {\n padding: 0 8px;\n font-size: var(--wzl-font-size-sm);\n}\n\n/* Minimal variant — strips the pill track, glass selected state, inset\n shadows, and outer padding. Used in dense diagnostic surfaces (dispatch\n trace, lab inspectors) where the bar must read as plain text controls. */\n.variant_minimal {\n height: auto;\n padding: 0;\n background: none;\n border-radius: 0;\n box-shadow: none;\n gap: 2px;\n}\n\n.variant_minimal .segment {\n padding: 0 4px;\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-medium);\n line-height: 1.4;\n border-radius: var(--wzl-radius-sm);\n color: var(--wzl-fg-muted);\n transition: none;\n}\n\n.variant_minimal .segment:first-child,\n.variant_minimal .segment:last-child,\n.variant_minimal .segment:only-child {\n border-radius: var(--wzl-radius-sm);\n}\n\n.variant_minimal .segment:hover:not(:disabled):not(.segmentSelected) {\n color: var(--wzl-fg);\n background: var(--wzl-surface-hover);\n}\n\n.variant_minimal .segmentSelected {\n background: none;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n color: var(--wzl-accent-fg, var(--wzl-accent));\n text-shadow: none;\n box-shadow: none;\n font-weight: var(--wzl-font-weight-medium);\n}\n\n.variant_minimal .segmentSelected::before {\n content: none;\n}\n"],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { useCallback as e, useRef as t, useState as n } from "react";
2
+ //#region src/useReorderDragList.ts
3
+ function r(e, t) {
4
+ let n = 0;
5
+ for (let r = t - 1; r >= 0; r--) if (e[r]?.locked) {
6
+ n = r + 1;
7
+ break;
8
+ }
9
+ let r = e.length;
10
+ for (let n = t + 1; n < e.length; n++) if (e[n]?.locked) {
11
+ r = n;
12
+ break;
13
+ }
14
+ return [n, r];
15
+ }
16
+ function i(i) {
17
+ let { threshold: a = 4 } = i, o = t(i);
18
+ o.current = i;
19
+ let s = t(null), c = t(null), l = t(null), [u, d] = n({
20
+ draggedIds: null,
21
+ targetIndex: null
22
+ }), f = e((e, t) => {
23
+ let [n, i] = r(o.current.items, t), a = s.current;
24
+ if (!a) return n;
25
+ let c = Array.from(a.children), l = c.length;
26
+ for (let t = 0; t < c.length; t++) {
27
+ let n = c[t];
28
+ if (n && e < n.getBoundingClientRect().bottom) {
29
+ l = t;
30
+ break;
31
+ }
32
+ }
33
+ return Math.max(n, Math.min(l, i));
34
+ }, []), p = e((e) => {
35
+ s.current = e;
36
+ }, []), m = e((e, t, n) => {
37
+ if (!o.current.items[t]?.locked) {
38
+ try {
39
+ n.currentTarget.setPointerCapture?.(n.pointerId);
40
+ } catch {}
41
+ c.current = {
42
+ id: e,
43
+ sourceIndex: t,
44
+ startX: n.clientX,
45
+ startY: n.clientY,
46
+ pointerId: n.pointerId
47
+ };
48
+ }
49
+ }, []), h = e(() => {
50
+ c.current = null, l.current = null, d({
51
+ draggedIds: null,
52
+ targetIndex: null
53
+ });
54
+ }, []);
55
+ return {
56
+ rowProps: (e, t) => ({ onPointerDown: (n) => m(e, t, n) }),
57
+ containerProps: {
58
+ ref: p,
59
+ onPointerMove: e((e) => {
60
+ let t = l.current;
61
+ if (t) {
62
+ let n = f(e.clientY, t.sourceIndex);
63
+ n !== t.targetIndex && (t.targetIndex = n, d({
64
+ draggedIds: t.draggedIds,
65
+ targetIndex: n
66
+ }));
67
+ return;
68
+ }
69
+ let n = c.current;
70
+ if (!n) return;
71
+ let i = e.clientX - n.startX, s = e.clientY - n.startY;
72
+ if (Math.hypot(i, s) < a) return;
73
+ let u = o.current.selectedIds, p = u.includes(n.id), [m, h] = r(o.current.items, n.sourceIndex), g = (p ? [...u] : [n.id]).filter((e) => {
74
+ let t = o.current.items.findIndex((t) => t.id === e);
75
+ return t >= m && t < h;
76
+ }), _ = f(e.clientY, n.sourceIndex);
77
+ l.current = {
78
+ ...n,
79
+ draggedIds: g,
80
+ targetIndex: _
81
+ }, d({
82
+ draggedIds: g,
83
+ targetIndex: _
84
+ });
85
+ }, [f, a]),
86
+ onPointerUp: e((e) => {
87
+ let t = l.current;
88
+ if (!t) {
89
+ h();
90
+ return;
91
+ }
92
+ let n = f(e.clientY, t.sourceIndex), r = o.current.items, i = t.draggedIds.map((e) => r.findIndex((t) => t.id === e)).filter((e) => e >= 0).sort((e, t) => e - t), a = i.length > 0 && i.every((e, t) => {
93
+ if (t === 0) return !0;
94
+ let n = i[t - 1];
95
+ return n !== void 0 && e === n + 1;
96
+ }), s = i[0], c = i[i.length - 1];
97
+ a && s !== void 0 && c !== void 0 && n >= s && n <= c + 1 || o.current.onReorder(t.draggedIds, n), h();
98
+ }, [f, h]),
99
+ onPointerCancel: e(() => {
100
+ h();
101
+ }, [h])
102
+ },
103
+ state: u
104
+ };
105
+ }
106
+ //#endregion
107
+ export { i as t };
108
+
109
+ //# sourceMappingURL=useReorderDragList-nQMVwNBd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useReorderDragList-nQMVwNBd.js","names":[],"sources":["../../src/useReorderDragList.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport type { ReactNode, PointerEvent as ReactPointerEvent, RefCallback } from 'react';\n\n/** One row in a reorderable list. */\nexport interface LayerListItem {\n id: string;\n label: ReactNode;\n /** Locked rows cannot be dragged, cannot be crossed by drops, and\n * never combine with other rows in a multi-selection. */\n locked?: boolean;\n /** Optional color swatch rendered before the label. Any CSS color string. */\n swatch?: string;\n}\n\n/**\n * Options for {@link useReorderDragList}. `onReorder` receives the dragged ids\n * and the index they were dropped at, measured against the pre-drag `items`.\n */\nexport interface UseReorderDragListOptions {\n items: LayerListItem[];\n selectedIds: string[];\n onReorder(ids: string[], targetIndex: number): void;\n /** Pointer-move distance (px) before pending drag engages. Default 4. */\n threshold?: number;\n}\n\n/**\n * Live drag state for rendering feedback: which ids are being dragged and the\n * insertion index the drop would use. Both `null` when no drag is engaged.\n */\nexport interface ReorderDragState {\n draggedIds: string[] | null;\n targetIndex: number | null;\n}\n\n/**\n * Props to spread onto the list container and each row, plus the live\n * {@link ReorderDragState}.\n */\nexport interface ReorderDragHandlers {\n rowProps(id: string, index: number): { onPointerDown(e: ReactPointerEvent): void };\n containerProps: {\n ref: RefCallback<HTMLElement>;\n onPointerMove(e: ReactPointerEvent): void;\n onPointerUp(e: ReactPointerEvent): void;\n onPointerCancel(e: ReactPointerEvent): void;\n };\n state: ReorderDragState;\n}\n\ninterface PendingState {\n id: string;\n sourceIndex: number;\n startX: number;\n startY: number;\n pointerId: number;\n}\n\ninterface ActiveState extends PendingState {\n draggedIds: string[];\n targetIndex: number;\n}\n\n/**\n * The half-open run of indices a row at `sourceIndex` may be dropped into:\n * bounded by the nearest locked row above and below it, so a locked row is a\n * wall in both directions rather than a global ceiling.\n */\nfunction unlockedSegment(items: readonly LayerListItem[], sourceIndex: number): [number, number] {\n let lo = 0;\n for (let i = sourceIndex - 1; i >= 0; i--) {\n if (items[i]?.locked) { lo = i + 1; break; }\n }\n let hi = items.length;\n for (let i = sourceIndex + 1; i < items.length; i++) {\n if (items[i]?.locked) { hi = i; break; }\n }\n return [lo, hi];\n}\n\n/**\n * Drag-to-reorder for a vertical list of rows. Dragging a row that is part of\n * the current selection drags the whole selection; dragging any other row\n * drags just that row. Locked rows can neither be dragged nor crossed by a\n * drop. A drop that would leave a contiguous block where it already is does\n * not call `onReorder`.\n *\n * The pointer is captured on the row, so a drag that leaves the list still\n * tracks and still releases cleanly.\n */\nexport function useReorderDragList(opts: UseReorderDragListOptions): ReorderDragHandlers {\n const { threshold = 4 } = opts;\n const optsRef = useRef(opts);\n optsRef.current = opts;\n const containerRef = useRef<HTMLElement | null>(null);\n const pendingRef = useRef<PendingState | null>(null);\n const activeRef = useRef<ActiveState | null>(null);\n const [state, setState] = useState<ReorderDragState>({ draggedIds: null, targetIndex: null });\n\n const computeTargetIndex = useCallback((clientY: number, sourceIndex: number): number => {\n const [lo, hi] = unlockedSegment(optsRef.current.items, sourceIndex);\n const c = containerRef.current;\n if (!c) return lo;\n const rows = Array.from(c.children) as HTMLElement[];\n let raw = rows.length;\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n if (!row) continue;\n const r = row.getBoundingClientRect();\n if (clientY < r.bottom) { raw = i; break; }\n }\n return Math.max(lo, Math.min(raw, hi));\n }, []);\n\n const refCb = useCallback<RefCallback<HTMLElement>>((el) => {\n containerRef.current = el;\n }, []);\n\n const onPointerDownRow = useCallback((id: string, index: number, e: ReactPointerEvent) => {\n // Locked items cannot be dragged — skip recording the pending state so\n // pointer-move cannot engage. Plain click still works because LayerList\n // tracks click intent in its own ref, separate from drag candidacy.\n const item = optsRef.current.items[index];\n if (item?.locked) return;\n // Capture the pointer to the row so subsequent move/up events keep firing\n // (on the row, bubbling to the container) even when the user drags\n // outside the list's bounding box. Without capture, releasing outside\n // the container leaves the drag state stuck because pointerup fires on\n // the document, not the list.\n try { (e.currentTarget as Element).setPointerCapture?.(e.pointerId); } catch { /* unsupported / already captured */ }\n pendingRef.current = {\n id,\n sourceIndex: index,\n startX: e.clientX,\n startY: e.clientY,\n pointerId: e.pointerId,\n };\n }, []);\n\n const reset = useCallback(() => {\n pendingRef.current = null;\n activeRef.current = null;\n setState({ draggedIds: null, targetIndex: null });\n }, []);\n\n const onPointerMove = useCallback((e: ReactPointerEvent) => {\n const active = activeRef.current;\n if (active) {\n const targetIndex = computeTargetIndex(e.clientY, active.sourceIndex);\n if (targetIndex !== active.targetIndex) {\n active.targetIndex = targetIndex;\n setState({ draggedIds: active.draggedIds, targetIndex });\n }\n return;\n }\n const pending = pendingRef.current;\n if (!pending) return;\n const dx = e.clientX - pending.startX;\n const dy = e.clientY - pending.startY;\n if (Math.hypot(dx, dy) < threshold) return;\n // Engage.\n const selected = optsRef.current.selectedIds;\n const inSelection = selected.includes(pending.id);\n const [lo, hi] = unlockedSegment(optsRef.current.items, pending.sourceIndex);\n const draggedIds = (inSelection ? [...selected] : [pending.id]).filter((id) => {\n const i = optsRef.current.items.findIndex((it) => it.id === id);\n return i >= lo && i < hi;\n });\n const targetIndex = computeTargetIndex(e.clientY, pending.sourceIndex);\n activeRef.current = { ...pending, draggedIds, targetIndex };\n setState({ draggedIds, targetIndex });\n }, [computeTargetIndex, threshold]);\n\n const onPointerUp = useCallback((e: ReactPointerEvent) => {\n const active = activeRef.current;\n if (!active) {\n reset();\n return;\n }\n const targetIndex = computeTargetIndex(e.clientY, active.sourceIndex);\n // Skip no-op: target lands inside the dragged-ids contiguous block.\n const items = optsRef.current.items;\n const indices = active.draggedIds\n .map((id) => items.findIndex((it) => it.id === id))\n .filter((i) => i >= 0)\n .sort((a, b) => a - b);\n const isContiguous =\n indices.length > 0 &&\n indices.every((v, i) => {\n if (i === 0) return true;\n const prev = indices[i - 1];\n return prev !== undefined && v === prev + 1;\n });\n const first = indices[0];\n const last = indices[indices.length - 1];\n const wouldBeNoop =\n isContiguous &&\n first !== undefined &&\n last !== undefined &&\n targetIndex >= first &&\n targetIndex <= last + 1;\n if (!wouldBeNoop) {\n optsRef.current.onReorder(active.draggedIds, targetIndex);\n }\n reset();\n }, [computeTargetIndex, reset]);\n\n const onPointerCancel = useCallback(() => {\n reset();\n }, [reset]);\n\n return {\n rowProps: (id, index) => ({\n onPointerDown: (e) => onPointerDownRow(id, index, e),\n }),\n containerProps: {\n ref: refCb,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n },\n state,\n };\n}\n"],"mappings":"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"}
@@ -62,4 +62,4 @@ function a(a) {
62
62
  //#endregion
63
63
  export { a as t };
64
64
 
65
- //# sourceMappingURL=useRovingTabIndex-CQz8EiKh.js.map
65
+ //# sourceMappingURL=useRovingTabIndex-ByjY4lnw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRovingTabIndex-CQz8EiKh.js","names":[],"sources":["../../src/useRovingTabIndex.ts"],"sourcesContent":["import { useRef, type KeyboardEvent as ReactKeyboardEvent, type RefObject } from 'react';\n\n/** The only thing the hook needs to know about a bar's items: which are\n * skipped by arrow navigation. */\nexport type RovingItem = { disabled?: boolean };\n\n/** Options for {@link useRovingTabIndex}. */\nexport type UseRovingTabIndexOptions = {\n /** In the same order as the elements carrying `itemClassName`. */\n items: readonly RovingItem[];\n /** Class on the focusable element of each item, inside the container the\n * returned `rootRef` is attached to. Their DOM order must match `items`. */\n itemClassName: string;\n /** Index that carries `tabIndex=0`. Defaults to the first enabled item; a\n * radiogroup-style bar passes its selected index so Tab lands on the\n * current value. */\n tabStopIndex?: number;\n /** Called with the new index as arrow/Home/End focus moves, before focus\n * moves. This is where a selection-follows-focus bar commits the value. */\n onNavigate?: (index: number) => void;\n /** Space/Enter on the item at `index`. When omitted the keypress is left\n * alone, which on a native `<button>` produces an ordinary click. */\n onActivate?: (index: number) => void;\n};\n\n/**\n * What {@link useRovingTabIndex} returns: a container ref plus the per-item\n * `tabIndex` and `onKeyDown` values to spread onto each item.\n */\nexport type RovingTabIndex<T extends HTMLElement = HTMLDivElement> = {\n /** Attach to the container element that holds the items. */\n rootRef: RefObject<T | null>;\n /** `tabIndex` value for the item at `index`. */\n tabIndexFor: (index: number) => 0 | -1;\n /** `onKeyDown` for the item at `index`. */\n onKeyDown: (index: number) => (e: ReactKeyboardEvent<HTMLElement>) => void;\n};\n\nfunction firstEnabledIndex(items: readonly RovingItem[]): number {\n for (let i = 0; i < items.length; i++) if (!items[i].disabled) return i;\n return -1;\n}\n\nfunction lastEnabledIndex(items: readonly RovingItem[]): number {\n for (let i = items.length - 1; i >= 0; i--) if (!items[i].disabled) return i;\n return -1;\n}\n\nfunction nextEnabledIndex(items: readonly RovingItem[], from: number): number {\n const n = items.length;\n for (let k = 1; k <= n; k++) {\n const i = (from + k + n) % n;\n if (!items[i].disabled) return i;\n }\n return from;\n}\n\nfunction prevEnabledIndex(items: readonly RovingItem[], from: number): number {\n const n = items.length;\n for (let k = 1; k <= n; k++) {\n const i = (from - k + n) % n;\n if (!items[i].disabled) return i;\n }\n return from;\n}\n\n/**\n * Roving tabindex for a bar of items: one item is in the tab order, and the\n * arrow keys move focus among the rest, skipping disabled ones and wrapping\n * at both ends. Home and End go to the first and last enabled item. Both axes\n * navigate, so the same bar works laid out either way.\n *\n * Backs `ActionsBar`, `OptionsBar`, and `ToggleBar`.\n *\n * **When a bar should not use this.** Only when the bar owns its items. A\n * container of arbitrary compound controls — a number field, a select, a\n * color field — must leave the arrow keys alone, because those controls edit\n * their own value with them; taking the arrows over would break the control\n * to navigate between controls. `ToolOptionsBar` is that case and keeps plain\n * DOM tab order. A bar whose items are all simple buttons is the case this\n * hook is for.\n *\n * With every item disabled there is no tab stop and the bar drops out of the\n * tab order entirely.\n */\nexport function useRovingTabIndex<T extends HTMLElement = HTMLDivElement>(\n options: UseRovingTabIndexOptions,\n): RovingTabIndex<T> {\n const { items, itemClassName, onNavigate, onActivate } = options;\n const rootRef = useRef<T | null>(null);\n\n const tabStopIndex = options.tabStopIndex ?? firstEnabledIndex(items);\n\n const focusItem = (index: number): void => {\n const root = rootRef.current;\n if (!root) return;\n const elements = root.querySelectorAll<HTMLElement>(`.${itemClassName}`);\n elements[index]?.focus();\n };\n\n const onKeyDown = (index: number) => (e: ReactKeyboardEvent<HTMLElement>): void => {\n let nextIndex = -1;\n switch (e.key) {\n case 'ArrowLeft':\n case 'ArrowUp':\n nextIndex = prevEnabledIndex(items, index);\n break;\n case 'ArrowRight':\n case 'ArrowDown':\n nextIndex = nextEnabledIndex(items, index);\n break;\n case 'Home':\n nextIndex = firstEnabledIndex(items);\n break;\n case 'End':\n nextIndex = lastEnabledIndex(items);\n break;\n case ' ':\n case 'Enter':\n if (onActivate) {\n e.preventDefault();\n onActivate(index);\n }\n return;\n default:\n return;\n }\n if (nextIndex < 0 || nextIndex === index) return;\n e.preventDefault();\n onNavigate?.(nextIndex);\n focusItem(nextIndex);\n };\n\n return {\n rootRef,\n tabIndexFor: (index: number) => (index === tabStopIndex ? 0 : -1),\n onKeyDown,\n };\n}\n"],"mappings":";;AAsCA,SAAS,EAAkB,GAAsC;AAC/D,MAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,IAAK,KAAI,CAAC,EAAM,GAAG,SAAU,QAAO;AACtE,QAAO;;AAGT,SAAS,EAAiB,GAAsC;AAC9D,MAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,IAAK,KAAI,CAAC,EAAM,GAAG,SAAU,QAAO;AAC3E,QAAO;;AAGT,SAAS,EAAiB,GAA8B,GAAsB;CAC5E,IAAM,IAAI,EAAM;AAChB,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,KAAK,IAAO,IAAI,KAAK;AAC3B,MAAI,CAAC,EAAM,GAAG,SAAU,QAAO;;AAEjC,QAAO;;AAGT,SAAS,EAAiB,GAA8B,GAAsB;CAC5E,IAAM,IAAI,EAAM;AAChB,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,KAAK,IAAO,IAAI,KAAK;AAC3B,MAAI,CAAC,EAAM,GAAG,SAAU,QAAO;;AAEjC,QAAO;;AAsBT,SAAgB,EACd,GACmB;CACnB,IAAM,EAAE,UAAO,kBAAe,eAAY,kBAAe,GACnD,IAAU,EAAiB,KAAK,EAEhC,IAAe,EAAQ,gBAAgB,EAAkB,EAAM,EAE/D,KAAa,MAAwB;EACzC,IAAM,IAAO,EAAQ;AAChB,OACY,EAAK,iBAA8B,IAAI,IACxD,CAAS,IAAQ,OAAO;;AAoC1B,QAAO;EACL;EACA,cAAc,MAAmB,MAAU,IAAe,IAAI;EAC9D,YApCiB,OAAmB,MAA6C;GACjF,IAAI,IAAY;AAChB,WAAQ,EAAE,KAAV;IACE,KAAK;IACL,KAAK;AACH,SAAY,EAAiB,GAAO,EAAM;AAC1C;IACF,KAAK;IACL,KAAK;AACH,SAAY,EAAiB,GAAO,EAAM;AAC1C;IACF,KAAK;AACH,SAAY,EAAkB,EAAM;AACpC;IACF,KAAK;AACH,SAAY,EAAiB,EAAM;AACnC;IACF,KAAK;IACL,KAAK;AACH,KAAI,MACF,EAAE,gBAAgB,EAClB,EAAW,EAAM;AAEnB;IACF,QACE;;AAEA,OAAY,KAAK,MAAc,MACnC,EAAE,gBAAgB,EAClB,IAAa,EAAU,EACvB,EAAU,EAAU;;EAOrB"}
1
+ {"version":3,"file":"useRovingTabIndex-ByjY4lnw.js","names":[],"sources":["../../src/useRovingTabIndex.ts"],"sourcesContent":["import { useRef, type KeyboardEvent as ReactKeyboardEvent, type RefObject } from 'react';\n\n/** The only thing the hook needs to know about a bar's items: which are\n * skipped by arrow navigation. */\nexport type RovingItem = { disabled?: boolean };\n\n/** Options for {@link useRovingTabIndex}. */\nexport type UseRovingTabIndexOptions = {\n /** In the same order as the elements carrying `itemClassName`. */\n items: readonly RovingItem[];\n /** Class on the focusable element of each item, inside the container the\n * returned `rootRef` is attached to. Their DOM order must match `items`. */\n itemClassName: string;\n /** Index that carries `tabIndex=0`. Defaults to the first enabled item; a\n * radiogroup-style bar passes its selected index so Tab lands on the\n * current value. */\n tabStopIndex?: number;\n /** Called with the new index as arrow/Home/End focus moves, before focus\n * moves. This is where a selection-follows-focus bar commits the value. */\n onNavigate?: (index: number) => void;\n /** Space/Enter on the item at `index`. When omitted the keypress is left\n * alone, which on a native `<button>` produces an ordinary click. */\n onActivate?: (index: number) => void;\n};\n\n/**\n * What {@link useRovingTabIndex} returns: a container ref plus the per-item\n * `tabIndex` and `onKeyDown` values to spread onto each item.\n */\nexport type RovingTabIndex<T extends HTMLElement = HTMLDivElement> = {\n /** Attach to the container element that holds the items. */\n rootRef: RefObject<T | null>;\n /** `tabIndex` value for the item at `index`. */\n tabIndexFor: (index: number) => 0 | -1;\n /** `onKeyDown` for the item at `index`. */\n onKeyDown: (index: number) => (e: ReactKeyboardEvent<HTMLElement>) => void;\n};\n\nfunction firstEnabledIndex(items: readonly RovingItem[]): number {\n for (let i = 0; i < items.length; i++) if (!items[i].disabled) return i;\n return -1;\n}\n\nfunction lastEnabledIndex(items: readonly RovingItem[]): number {\n for (let i = items.length - 1; i >= 0; i--) if (!items[i].disabled) return i;\n return -1;\n}\n\nfunction nextEnabledIndex(items: readonly RovingItem[], from: number): number {\n const n = items.length;\n for (let k = 1; k <= n; k++) {\n const i = (from + k + n) % n;\n if (!items[i].disabled) return i;\n }\n return from;\n}\n\nfunction prevEnabledIndex(items: readonly RovingItem[], from: number): number {\n const n = items.length;\n for (let k = 1; k <= n; k++) {\n const i = (from - k + n) % n;\n if (!items[i].disabled) return i;\n }\n return from;\n}\n\n/**\n * Roving tabindex for a bar of items: one item is in the tab order, and the\n * arrow keys move focus among the rest, skipping disabled ones and wrapping\n * at both ends. Home and End go to the first and last enabled item. Both axes\n * navigate, so the same bar works laid out either way.\n *\n * Backs `ActionsBar`, `OptionsBar`, and `ToggleBar`.\n *\n * **When a bar should not use this.** Only when the bar owns its items. A\n * container of arbitrary compound controls — a number field, a select, a\n * color field — must leave the arrow keys alone, because those controls edit\n * their own value with them; taking the arrows over would break the control\n * to navigate between controls. `ToolOptionsBar` is that case and keeps plain\n * DOM tab order. A bar whose items are all simple buttons is the case this\n * hook is for.\n *\n * With every item disabled there is no tab stop and the bar drops out of the\n * tab order entirely.\n */\nexport function useRovingTabIndex<T extends HTMLElement = HTMLDivElement>(\n options: UseRovingTabIndexOptions,\n): RovingTabIndex<T> {\n const { items, itemClassName, onNavigate, onActivate } = options;\n const rootRef = useRef<T | null>(null);\n\n const tabStopIndex = options.tabStopIndex ?? firstEnabledIndex(items);\n\n const focusItem = (index: number): void => {\n const root = rootRef.current;\n if (!root) return;\n const elements = root.querySelectorAll<HTMLElement>(`.${itemClassName}`);\n elements[index]?.focus();\n };\n\n const onKeyDown = (index: number) => (e: ReactKeyboardEvent<HTMLElement>): void => {\n let nextIndex = -1;\n switch (e.key) {\n case 'ArrowLeft':\n case 'ArrowUp':\n nextIndex = prevEnabledIndex(items, index);\n break;\n case 'ArrowRight':\n case 'ArrowDown':\n nextIndex = nextEnabledIndex(items, index);\n break;\n case 'Home':\n nextIndex = firstEnabledIndex(items);\n break;\n case 'End':\n nextIndex = lastEnabledIndex(items);\n break;\n case ' ':\n case 'Enter':\n if (onActivate) {\n e.preventDefault();\n onActivate(index);\n }\n return;\n default:\n return;\n }\n if (nextIndex < 0 || nextIndex === index) return;\n e.preventDefault();\n onNavigate?.(nextIndex);\n focusItem(nextIndex);\n };\n\n return {\n rootRef,\n tabIndexFor: (index: number) => (index === tabStopIndex ? 0 : -1),\n onKeyDown,\n };\n}\n"],"mappings":";;AAsCA,SAAS,EAAkB,GAAsC;AAC/D,MAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,IAAK,KAAI,CAAC,EAAM,GAAG,SAAU,QAAO;AACtE,QAAO;;AAGT,SAAS,EAAiB,GAAsC;AAC9D,MAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,IAAK,KAAI,CAAC,EAAM,GAAG,SAAU,QAAO;AAC3E,QAAO;;AAGT,SAAS,EAAiB,GAA8B,GAAsB;CAC5E,IAAM,IAAI,EAAM;AAChB,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,KAAK,IAAO,IAAI,KAAK;AAC3B,MAAI,CAAC,EAAM,GAAG,SAAU,QAAO;;AAEjC,QAAO;;AAGT,SAAS,EAAiB,GAA8B,GAAsB;CAC5E,IAAM,IAAI,EAAM;AAChB,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,KAAK,IAAO,IAAI,KAAK;AAC3B,MAAI,CAAC,EAAM,GAAG,SAAU,QAAO;;AAEjC,QAAO;;AAsBT,SAAgB,EACd,GACmB;CACnB,IAAM,EAAE,UAAO,kBAAe,eAAY,kBAAe,GACnD,IAAU,EAAiB,KAAK,EAEhC,IAAe,EAAQ,gBAAgB,EAAkB,EAAM,EAE/D,KAAa,MAAwB;EACzC,IAAM,IAAO,EAAQ;AAChB,OACY,EAAK,iBAA8B,IAAI,IACxD,CAAS,IAAQ,OAAO;;AAoC1B,QAAO;EACL;EACA,cAAc,MAAmB,MAAU,IAAe,IAAI;EAC9D,YApCiB,OAAmB,MAA6C;GACjF,IAAI,IAAY;AAChB,WAAQ,EAAE,KAAV;IACE,KAAK;IACL,KAAK;AACH,SAAY,EAAiB,GAAO,EAAM;AAC1C;IACF,KAAK;IACL,KAAK;AACH,SAAY,EAAiB,GAAO,EAAM;AAC1C;IACF,KAAK;AACH,SAAY,EAAkB,EAAM;AACpC;IACF,KAAK;AACH,SAAY,EAAiB,EAAM;AACnC;IACF,KAAK;IACL,KAAK;AACH,KAAI,MACF,EAAE,gBAAgB,EAClB,EAAW,EAAM;AAEnB;IACF,QACE;;AAEA,OAAY,KAAK,MAAc,MACnC,EAAE,gBAAgB,EAClB,IAAa,EAAU,EACvB,EAAU,EAAU;;EAOrB"}
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/ActionBar-BTev_ZZl.js";
1
+ import { t as e } from "../../chunks/ActionBar-D4N1o4LB.js";
2
2
  export { e as ActionBar };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/ActionsBar-gTuCtkv8.js";
1
+ import { t as e } from "../../chunks/ActionsBar-B-gWm0NE.js";
2
2
  export { e as ActionsBar };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/Badge-9dPfvYOk.js";
1
+ import { t as e } from "../../chunks/Badge-BXTDs-zi.js";
2
2
  export { e as Badge };
@@ -1,2 +1,2 @@
1
- import { n as e, r as t, t as n } from "../../chunks/BandEditor-DKbcHG2_.js";
1
+ import { n as e, r as t, t as n } from "../../chunks/BandEditor-D13ybQN_.js";
2
2
  export { n as BandEditor, e as linearScale, t as logScale };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/Button-CIu40Epu.js";
1
+ import { t as e } from "../../chunks/Button-0OdcoOMx.js";
2
2
  export { e as Button };
@@ -29,9 +29,9 @@ export type CalloutProps = Omit<RACPopoverProps, 'children' | 'className' | 'isN
29
29
  modal?: boolean;
30
30
  /**
31
31
  * Show the × button. Defaults to `!modal`. In programmatic
32
- * `triggerRef`/`anchorRect` modes the close button requires either
33
- * controlled open (`isOpen` + `onOpenChange`) or `onDismiss`; with only
34
- * `defaultOpen` it has no open-state setter to call and cannot close.
32
+ * `triggerRef`/`anchorRect` modes the close button needs controlled open
33
+ * (`isOpen` + `onOpenChange`); with only `defaultOpen` it has no open-state
34
+ * setter to call and cannot close.
35
35
  */
36
36
  showCloseButton?: boolean;
37
37
  /**
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "../../chunks/Callout-CHs98djt.js";
1
+ import { n as e, t } from "../../chunks/Callout-DAFusbzz.js";
2
2
  export { t as Callout, e as CalloutTrigger };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/Checkbox-BLEw-wEb.js";
1
+ import { t as e } from "../../chunks/Checkbox-BePa_djO.js";
2
2
  export { e as Checkbox };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/ColorField-D1t-BdSa.js";
1
+ import { t as e } from "../../chunks/ColorField-CKbnsEUN.js";
2
2
  export { e as ColorField };
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "../../chunks/ComboBox-cvdKolWv.js";
1
+ import { n as e, t } from "../../chunks/ComboBox-B6QS8y3j.js";
2
2
  export { t as ComboBox, e as ComboBoxItem };
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "../../chunks/CurveEditor-BaA-PabB.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "../../chunks/CurveEditor-COJ6WK9K.js";
2
2
  export { n as CurveEditor, i as LayeredCurveEditor, t as createFunctionLayer, a as createSetCurveOp, e as functionLayerState, r as sampleByInterpolation };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/DataGrid-D15I779H.js";
1
+ import { t as e } from "../../chunks/DataGrid-BWZZUekH.js";
2
2
  export { e as DataGrid };
@@ -0,0 +1,52 @@
1
+ import { type ReactElement, type ReactNode } from 'react';
2
+ /** What a detent can carry. Narrowed so identity comparison and React keys
3
+ * both work without a keying callback. */
4
+ export type DetentValue = string | number;
5
+ /** One detent on a {@link DetentSlider}. */
6
+ export type DetentItem<V extends DetentValue = number> = {
7
+ value: V;
8
+ /** Drawn under the detent. Defaults to `formatLabel(value)`, then `value`. */
9
+ label?: ReactNode;
10
+ /** Spoken form, when the drawn label is not the right thing to say. */
11
+ ariaLabel?: string;
12
+ };
13
+ /**
14
+ * Props for {@link DetentSlider}.
15
+ *
16
+ * `items` takes bare values or `DetentItem`s interchangeably — a bare value is
17
+ * a detent with no label of its own.
18
+ *
19
+ * `onChange` fires on every detent the control passes through, including
20
+ * mid-drag: each one is a complete, legal choice, so there is no in-flight
21
+ * value to withhold. `onCommit` fires once the gesture that changed things
22
+ * ends, and is the one to write to history.
23
+ */
24
+ export type DetentSliderProps<V extends DetentValue = number> = {
25
+ items: readonly (V | DetentItem<V>)[];
26
+ value: V;
27
+ onChange: (value: V, index: number) => void;
28
+ onCommit?: (value: V, index: number) => void;
29
+ formatLabel?: (value: V, index: number) => ReactNode;
30
+ labels?: 'all' | 'ends' | 'none';
31
+ trackHeight?: number;
32
+ ariaLabel?: string;
33
+ className?: string;
34
+ };
35
+ /**
36
+ * Slider over a fixed list of values: one detent per value, evenly spaced, the
37
+ * thumb resting on one of them.
38
+ *
39
+ * This is the shape to reach for when a numeric option has a small set of
40
+ * allowed values along a line — playback rate, zoom step, stroke weight — in
41
+ * place of a dropdown, which hides the ordering and the extent of the range
42
+ * behind a click.
43
+ *
44
+ * The track addresses the *index* of `items`, not the value, which is what
45
+ * makes the detents evenly spaced no matter how the values are distributed:
46
+ * a geometric rate list (0.25/0.5/1/2/4) laid out linearly would crowd four
47
+ * of its five detents into the first fifth of the track and leave the most
48
+ * used one nearly unhittable. Since the index is meaningless to a screen
49
+ * reader, the value is published as `aria-valuetext`.
50
+ */
51
+ export declare function DetentSlider<V extends DetentValue = number>(props: DetentSliderProps<V>): ReactElement;
52
+ //# sourceMappingURL=DetentSlider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DetentSlider.d.ts","sourceRoot":"","sources":["../../../src/components/DetentSlider/DetentSlider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI7E;2CAC2C;AAC3C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,4CAA4C;AAC5C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,MAAM,IAAI;IACvD,KAAK,EAAE,CAAC,CAAC;IACT,8EAA8E;IAC9E,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,MAAM,IAAI;IAC9D,KAAK,EAAE,SAAS,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAkCF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,GAAG,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,YAAY,CAkFtG"}
@@ -0,0 +1,3 @@
1
+ export { DetentSlider } from './DetentSlider';
2
+ export type { DetentSliderProps, DetentItem, DetentValue } from './DetentSlider';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DetentSlider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { t as e } from "../../chunks/DetentSlider-CXIeTHaM.js";
2
+ export { e as DetentSlider };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../chunks/Dialog-DC1x46Sq.js";
1
+ import { t as e } from "../../chunks/Dialog-CQAZ7hS7.js";
2
2
  export { e as Dialog };