@weasel-js/ui 1.6.0 → 1.6.1

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 (438) hide show
  1. package/dist/chunks/{ActionBar-CYvfmEz0.js → ActionBar-DCq16yFA.js} +9 -9
  2. package/dist/chunks/ActionBar-DCq16yFA.js.map +1 -0
  3. package/dist/chunks/{Badge-DZ0lFs14.js → Badge-CyAIZSDo.js} +151 -151
  4. package/dist/chunks/Badge-CyAIZSDo.js.map +1 -0
  5. package/dist/chunks/{BandEditor-D-nVrVO4.js → BandEditor-Dhm_Xrlr.js} +5 -4
  6. package/dist/chunks/BandEditor-Dhm_Xrlr.js.map +1 -0
  7. package/dist/chunks/{Button-Dyp31jMt.js → Button-BIdXHQOx.js} +3 -3
  8. package/dist/chunks/Button-BIdXHQOx.js.map +1 -0
  9. package/dist/chunks/{ButtonBar-smZzFuEo.js → ButtonBar-D5Vi0aj_.js} +4 -4
  10. package/dist/chunks/ButtonBar-D5Vi0aj_.js.map +1 -0
  11. package/dist/chunks/{Callout-xLjnx7Mp.js → Callout-yEn9iPlh.js} +4 -4
  12. package/dist/chunks/Callout-yEn9iPlh.js.map +1 -0
  13. package/dist/chunks/{Checkbox-ChZz30Ds.js → Checkbox-DHXTUHO9.js} +1 -1
  14. package/dist/chunks/Checkbox-DHXTUHO9.js.map +1 -0
  15. package/dist/chunks/{Code-v4tDWuuN.js → Code-AsKpgnv6.js} +3 -3
  16. package/dist/chunks/Code-AsKpgnv6.js.map +1 -0
  17. package/dist/chunks/{ColorField-DJSCuSJv.js → ColorField-BcMcW8Sa.js} +3 -3
  18. package/dist/chunks/ColorField-BcMcW8Sa.js.map +1 -0
  19. package/dist/chunks/{ColorModeControl-JOEiqtE0.js → ColorModeControl-ke5PXbBa.js} +3 -3
  20. package/dist/chunks/ColorModeControl-ke5PXbBa.js.map +1 -0
  21. package/dist/chunks/{ComboBox-C1JgIpML.js → ComboBox-DpT8lc3p.js} +3 -3
  22. package/dist/chunks/ComboBox-DpT8lc3p.js.map +1 -0
  23. package/dist/chunks/{CurveEditor-f1R4kSbD.js → CurveEditor-BDJXjEvK.js} +35 -35
  24. package/dist/chunks/CurveEditor-BDJXjEvK.js.map +1 -0
  25. package/dist/chunks/{DataGrid-CZPrB_3a.js → DataGrid-D-dZj1BD.js} +13 -13
  26. package/dist/chunks/DataGrid-D-dZj1BD.js.map +1 -0
  27. package/dist/chunks/{DetailList-DHaXX4TG.js → DetailList-BMER1LUZ.js} +1 -1
  28. package/dist/chunks/DetailList-BMER1LUZ.js.map +1 -0
  29. package/dist/chunks/{DetentSlider-BYyaZha6.js → DetentSlider-CL8TlX3S.js} +2 -2
  30. package/dist/chunks/DetentSlider-CL8TlX3S.js.map +1 -0
  31. package/dist/chunks/{Dialog-GIvjoDQj.js → Dialog-BWyNMgpf.js} +3 -3
  32. package/dist/chunks/Dialog-BWyNMgpf.js.map +1 -0
  33. package/dist/chunks/{Disclosure-D79jhmh2.js → Disclosure-0G0uh2fa.js} +1 -1
  34. package/dist/chunks/Disclosure-0G0uh2fa.js.map +1 -0
  35. package/dist/chunks/{DragGhost-DcU7cOwy.js → DragGhost-B5_hb9W9.js} +2 -2
  36. package/dist/chunks/DragGhost-B5_hb9W9.js.map +1 -0
  37. package/dist/chunks/{DragHandleGlyph-BtBxHjZS.js → DragHandleGlyph-Dr7Fgo0I.js} +1 -1
  38. package/dist/chunks/DragHandleGlyph-Dr7Fgo0I.js.map +1 -0
  39. package/dist/chunks/{Field-xbqRmjsI.js → Field--onYxXTF.js} +7 -6
  40. package/dist/chunks/Field--onYxXTF.js.map +1 -0
  41. package/dist/chunks/{FillStrokeSwatch-BViKXIPx.js → FillStrokeSwatch-DNb0KXPk.js} +11 -11
  42. package/dist/chunks/FillStrokeSwatch-DNb0KXPk.js.map +1 -0
  43. package/dist/chunks/{FontFamilySelect-r9TV_xIH.js → FontFamilySelect-DXlMKWfK.js} +2 -2
  44. package/dist/chunks/FontFamilySelect-DXlMKWfK.js.map +1 -0
  45. package/dist/chunks/{GradientEditor-BRTxHG-W.js → GradientEditor-B3a-MsVJ.js} +8 -6
  46. package/dist/chunks/GradientEditor-B3a-MsVJ.js.map +1 -0
  47. package/dist/chunks/{Icon-BW0qv_U7.js → Icon-Cgzy8VgC.js} +2 -2
  48. package/dist/chunks/Icon-Cgzy8VgC.js.map +1 -0
  49. package/dist/chunks/{InlineRange-BwGFDhpT.js → InlineRange-eOj6JpJl.js} +1 -1
  50. package/dist/chunks/InlineRange-eOj6JpJl.js.map +1 -0
  51. package/dist/chunks/{Input-Bx2cuUbS.js → Input-CHmkfYaD.js} +2 -2
  52. package/dist/chunks/Input-CHmkfYaD.js.map +1 -0
  53. package/dist/chunks/{ItemList-DzJ2lK0R.js → ItemList-Cm-HUWCi.js} +6 -7
  54. package/dist/chunks/ItemList-Cm-HUWCi.js.map +1 -0
  55. package/dist/chunks/{ItemList.module-DDUXfuZL.js → ItemList.module-BSpCSxan.js} +1 -1
  56. package/dist/chunks/ItemList.module-BSpCSxan.js.map +1 -0
  57. package/dist/chunks/{Jog-LPoac9s4.js → Jog-DESxZ44P.js} +4 -4
  58. package/dist/chunks/Jog-DESxZ44P.js.map +1 -0
  59. package/dist/chunks/{Keycaps-CKiKOJnJ.js → Keycaps-C0H_v2gO.js} +2 -2
  60. package/dist/chunks/Keycaps-C0H_v2gO.js.map +1 -0
  61. package/dist/chunks/{LayerList-BeGrkLb9.js → LayerList-nz-QYvTF.js} +14 -14
  62. package/dist/chunks/LayerList-nz-QYvTF.js.map +1 -0
  63. package/dist/chunks/{ListEditor-C6zLzCsJ.js → ListEditor-BQ6AV3Ac.js} +2 -2
  64. package/dist/chunks/ListEditor-BQ6AV3Ac.js.map +1 -0
  65. package/dist/chunks/{MenuButton-BcdhrNGh.js → MenuButton-DtaGenKf.js} +3 -3
  66. package/dist/chunks/MenuButton-DtaGenKf.js.map +1 -0
  67. package/dist/chunks/{MeshEditor-BOOIFWnz.js → MeshEditor-qqGc6hlD.js} +4 -4
  68. package/dist/chunks/MeshEditor-qqGc6hlD.js.map +1 -0
  69. package/dist/chunks/{NumberField-C1Y7zP-a.js → NumberField-CwJOMmQR.js} +3 -3
  70. package/dist/chunks/NumberField-CwJOMmQR.js.map +1 -0
  71. package/dist/chunks/{OptionsBar-DlcagPYK.js → OptionsBar-DbzAgIln.js} +3 -3
  72. package/dist/chunks/OptionsBar-DbzAgIln.js.map +1 -0
  73. package/dist/chunks/{PaintField-B2mLRZa4.js → PaintField-DaJukRc6.js} +4 -4
  74. package/dist/chunks/PaintField-DaJukRc6.js.map +1 -0
  75. package/dist/chunks/{PaintInput-BFKhd83I.js → PaintInput-Byhna3H-.js} +7 -7
  76. package/dist/chunks/PaintInput-Byhna3H-.js.map +1 -0
  77. package/dist/chunks/{PatternPicker-DdfpxoQy.js → PatternPicker-B-cUt-JT.js} +2 -2
  78. package/dist/chunks/PatternPicker-B-cUt-JT.js.map +1 -0
  79. package/dist/chunks/{Plot2D-lyO7waPQ.js → Plot2D-CTXHkL5p.js} +13 -13
  80. package/dist/chunks/Plot2D-CTXHkL5p.js.map +1 -0
  81. package/dist/chunks/{PointPlotter-DGs9i5P-.js → PointPlotter-Bxo6haKe.js} +5 -4
  82. package/dist/chunks/PointPlotter-Bxo6haKe.js.map +1 -0
  83. package/dist/chunks/Powerline-ExO5GwEr.js +42 -0
  84. package/dist/chunks/Powerline-ExO5GwEr.js.map +1 -0
  85. package/dist/chunks/{Prefs-Ctu0H4-b.js → Prefs-DpqFKiwY.js} +18 -17
  86. package/dist/chunks/Prefs-DpqFKiwY.js.map +1 -0
  87. package/dist/chunks/{Properties-Bbneh1ws.js → Properties-D_KzDN9K.js} +13 -12
  88. package/dist/chunks/Properties-D_KzDN9K.js.map +1 -0
  89. package/dist/chunks/{PropertyField-CDb19d3F.js → PropertyField-DGCecAnV.js} +22 -20
  90. package/dist/chunks/PropertyField-DGCecAnV.js.map +1 -0
  91. package/dist/chunks/{RadioGroup-BK2mD6Q0.js → RadioGroup-Bh4-12e-.js} +2 -2
  92. package/dist/chunks/RadioGroup-Bh4-12e-.js.map +1 -0
  93. package/dist/chunks/{RangeSlider-BiRAOsTh.js → RangeSlider-BKRRTPTZ.js} +1 -1
  94. package/dist/chunks/RangeSlider-BKRRTPTZ.js.map +1 -0
  95. package/dist/chunks/{ResizeHandle-Cc6EOehs.js → ResizeHandle-BKT0XYpx.js} +7 -7
  96. package/dist/chunks/ResizeHandle-BKT0XYpx.js.map +1 -0
  97. package/dist/chunks/{Select-DVValBe1.js → Select-CzyfaXzp.js} +4 -4
  98. package/dist/chunks/Select-CzyfaXzp.js.map +1 -0
  99. package/dist/chunks/{SelectionPanel-C5LmZA7b.js → SelectionPanel-BgUM1h03.js} +2 -2
  100. package/dist/chunks/SelectionPanel-BgUM1h03.js.map +1 -0
  101. package/dist/chunks/{Sidebar-DKKd4R-x.js → Sidebar-BZ0m4afn.js} +8 -8
  102. package/dist/chunks/Sidebar-BZ0m4afn.js.map +1 -0
  103. package/dist/chunks/{SidebarPanel-u5NsuAZY.js → SidebarPanel-aoIqxbtq.js} +3 -3
  104. package/dist/chunks/SidebarPanel-aoIqxbtq.js.map +1 -0
  105. package/dist/chunks/{Slider-BwRrWHFW.js → Slider-CFwQYQ10.js} +60 -58
  106. package/dist/chunks/Slider-CFwQYQ10.js.map +1 -0
  107. package/dist/chunks/{StatusBar-CdPdmmda.js → StatusBar-DzoPDY4k.js} +8 -8
  108. package/dist/chunks/StatusBar-DzoPDY4k.js.map +1 -0
  109. package/dist/chunks/{SwatchGrid-C-Zx2Exd.js → SwatchGrid-BARC3rnF.js} +1 -1
  110. package/dist/chunks/SwatchGrid-BARC3rnF.js.map +1 -0
  111. package/dist/chunks/{Switch-DxF7TsEu.js → Switch-CSYmcM8y.js} +1 -1
  112. package/dist/chunks/Switch-CSYmcM8y.js.map +1 -0
  113. package/dist/chunks/{Tabs-GXEfoe3o.js → Tabs-BbpzLLdY.js} +1 -1
  114. package/dist/chunks/Tabs-BbpzLLdY.js.map +1 -0
  115. package/dist/chunks/{Timeline-SgmpQtUV.js → Timeline--58F7MED.js} +21 -21
  116. package/dist/chunks/Timeline--58F7MED.js.map +1 -0
  117. package/dist/chunks/{Toast-BfcljZz6.js → Toast-DNBb-24H.js} +1 -1
  118. package/dist/chunks/Toast-DNBb-24H.js.map +1 -0
  119. package/dist/chunks/{ToggleBar-Btnl5r7F.js → ToggleBar-DTjGeS0Q.js} +13 -11
  120. package/dist/chunks/ToggleBar-DTjGeS0Q.js.map +1 -0
  121. package/dist/chunks/{TokenPanel-5ajHEHha.js → TokenPanel-CMq7uydV.js} +21 -18
  122. package/dist/chunks/TokenPanel-CMq7uydV.js.map +1 -0
  123. package/dist/chunks/{ToolButton-rzqlFlAc.js → ToolButton-CR4sQlxF.js} +2 -2
  124. package/dist/chunks/ToolButton-CR4sQlxF.js.map +1 -0
  125. package/dist/chunks/{ToolGroup-4bUBV5k6.js → ToolGroup-Dpg1LN0l.js} +7 -7
  126. package/dist/chunks/ToolGroup-Dpg1LN0l.js.map +1 -0
  127. package/dist/chunks/{ToolOptionsBar-BF3TNXA3.js → ToolOptionsBar-CtzTlaN2.js} +6 -5
  128. package/dist/chunks/ToolOptionsBar-CtzTlaN2.js.map +1 -0
  129. package/dist/chunks/{ToolPalette-Uw4PvWwa.js → ToolPalette-CKG9qY6P.js} +6 -6
  130. package/dist/chunks/ToolPalette-CKG9qY6P.js.map +1 -0
  131. package/dist/chunks/{Tooltip-9XiJF937.js → Tooltip-Clg2mhSt.js} +2 -2
  132. package/dist/chunks/Tooltip-Clg2mhSt.js.map +1 -0
  133. package/dist/chunks/{Tree-BGt6P8tI.js → Tree-DVOtc9R5.js} +3 -3
  134. package/dist/chunks/Tree-DVOtc9R5.js.map +1 -0
  135. package/dist/chunks/{createKeyframeLayer-BzDRCrrh.js → createKeyframeLayer-Czj6Y235.js} +32 -32
  136. package/dist/chunks/createKeyframeLayer-Czj6Y235.js.map +1 -0
  137. package/dist/chunks/{dlog-CMYiRF3Q.js → dlog-F0I8KsIW.js} +2 -2
  138. package/dist/chunks/dlog-F0I8KsIW.js.map +1 -0
  139. package/dist/chunks/{formatShortcut-BoGqUoWi.js → formatShortcut-DRQrVThu.js} +2 -2
  140. package/dist/chunks/formatShortcut-DRQrVThu.js.map +1 -0
  141. package/dist/chunks/icons-Dk8SRS8g.js +162 -0
  142. package/dist/chunks/icons-Dk8SRS8g.js.map +1 -0
  143. package/dist/chunks/{interactiveTarget-C7QUBaJN.js → interactiveTarget-BNZmTow2.js} +1 -1
  144. package/dist/chunks/{interactiveTarget-C7QUBaJN.js.map → interactiveTarget-BNZmTow2.js.map} +1 -1
  145. package/dist/chunks/{keyGlyph-CLvUHU8c.js → keyGlyph-C0qTakG-.js} +1 -1
  146. package/dist/chunks/keyGlyph-C0qTakG-.js.map +1 -0
  147. package/dist/chunks/{model-BQMvTLnW.js → model-Du7Lta4C.js} +5 -5
  148. package/dist/chunks/model-Du7Lta4C.js.map +1 -0
  149. package/dist/chunks/{number-6S8IzXVt.js → number-D3NEx_8r.js} +1 -1
  150. package/dist/chunks/number-D3NEx_8r.js.map +1 -0
  151. package/dist/chunks/{paintPreview-DPtZS4yU.js → paintPreview-CuSZiHpR.js} +1 -1
  152. package/dist/chunks/paintPreview-CuSZiHpR.js.map +1 -0
  153. package/dist/chunks/{paintValue-Bz6AVuh3.js → paintValue-BpaGPjV3.js} +3 -3
  154. package/dist/chunks/paintValue-BpaGPjV3.js.map +1 -0
  155. package/dist/chunks/{portalHost-CjpCnuGU.js → portalHost-yTOVuCej.js} +1 -1
  156. package/dist/chunks/portalHost-yTOVuCej.js.map +1 -0
  157. package/dist/chunks/{prefField-CLkhrvYl.js → prefField-Dnl7nmjQ.js} +3 -3
  158. package/dist/chunks/prefField-Dnl7nmjQ.js.map +1 -0
  159. package/dist/chunks/{segmentTooltip-CAkZlW-t.js → segmentTooltip-CStYHKzd.js} +2 -2
  160. package/dist/chunks/segmentTooltip-CStYHKzd.js.map +1 -0
  161. package/dist/chunks/{segmentedControl.module-D2nw68Yo.js → segmentedControl.module-Bv7DEg8f.js} +1 -1
  162. package/dist/chunks/segmentedControl.module-Bv7DEg8f.js.map +1 -0
  163. package/dist/chunks/{snap-DC4Km8xG.js → snap-DRjbOiG9.js} +1 -1
  164. package/dist/chunks/snap-DRjbOiG9.js.map +1 -0
  165. package/dist/chunks/{stance-CarrcbbP.js → stance-BFQpS_fL.js} +1 -1
  166. package/dist/chunks/stance-BFQpS_fL.js.map +1 -0
  167. package/dist/chunks/{useReorderDragList-Dcezzgix.js → useReorderDragList-B_-5L5Gu.js} +2 -2
  168. package/dist/chunks/useReorderDragList-B_-5L5Gu.js.map +1 -0
  169. package/dist/chunks/{useRovingTabIndex-B4uJqiKP.js → useRovingTabIndex-Bp_hYm_h.js} +1 -1
  170. package/dist/chunks/useRovingTabIndex-Bp_hYm_h.js.map +1 -0
  171. package/dist/components/ActionBar/ActionBar.d.ts +1 -1
  172. package/dist/components/ActionBar/ActionBar.d.ts.map +1 -1
  173. package/dist/components/ActionBar/index.js +1 -1
  174. package/dist/components/Badge/index.js +1 -1
  175. package/dist/components/BandEditor/index.js +1 -1
  176. package/dist/components/Button/index.js +1 -1
  177. package/dist/components/ButtonBar/index.js +1 -1
  178. package/dist/components/Callout/Callout.d.ts +1 -1
  179. package/dist/components/Callout/Callout.d.ts.map +1 -1
  180. package/dist/components/Callout/index.js +1 -1
  181. package/dist/components/Checkbox/index.js +1 -1
  182. package/dist/components/Code/Code.d.ts +1 -1
  183. package/dist/components/Code/Code.d.ts.map +1 -1
  184. package/dist/components/Code/index.js +1 -1
  185. package/dist/components/ColorField/ColorField.d.ts +1 -1
  186. package/dist/components/ColorField/ColorField.d.ts.map +1 -1
  187. package/dist/components/ColorField/index.js +1 -1
  188. package/dist/components/ColorModeControl/index.js +1 -1
  189. package/dist/components/ComboBox/ComboBox.d.ts +2 -2
  190. package/dist/components/ComboBox/ComboBox.d.ts.map +1 -1
  191. package/dist/components/ComboBox/index.js +1 -1
  192. package/dist/components/CurveEditor/CurveEditor.d.ts +1 -1
  193. package/dist/components/CurveEditor/CurveEditor.d.ts.map +1 -1
  194. package/dist/components/CurveEditor/LayeredCurveEditor.d.ts +1 -1
  195. package/dist/components/CurveEditor/LayeredCurveEditor.d.ts.map +1 -1
  196. package/dist/components/CurveEditor/index.js +3 -3
  197. package/dist/components/DataGrid/DataGrid.d.ts +1 -1
  198. package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
  199. package/dist/components/DataGrid/index.js +1 -1
  200. package/dist/components/DetailList/DetailList.d.ts +2 -2
  201. package/dist/components/DetailList/DetailList.d.ts.map +1 -1
  202. package/dist/components/DetailList/index.js +1 -1
  203. package/dist/components/DetentSlider/index.js +1 -1
  204. package/dist/components/Dialog/Dialog.d.ts +1 -1
  205. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  206. package/dist/components/Dialog/index.js +1 -1
  207. package/dist/components/Disclosure/Disclosure.d.ts +3 -3
  208. package/dist/components/Disclosure/Disclosure.d.ts.map +1 -1
  209. package/dist/components/Disclosure/index.js +1 -1
  210. package/dist/components/DragGhost/index.js +1 -1
  211. package/dist/components/DragHandleGlyph/DragHandleGlyph.d.ts +1 -1
  212. package/dist/components/DragHandleGlyph/DragHandleGlyph.d.ts.map +1 -1
  213. package/dist/components/DragHandleGlyph/index.js +1 -1
  214. package/dist/components/Field/Field.d.ts +1 -1
  215. package/dist/components/Field/Field.d.ts.map +1 -1
  216. package/dist/components/Field/index.js +1 -1
  217. package/dist/components/FillStrokeSwatch/index.js +1 -1
  218. package/dist/components/FontFamilySelect/FontFamilySelect.d.ts +1 -1
  219. package/dist/components/FontFamilySelect/FontFamilySelect.d.ts.map +1 -1
  220. package/dist/components/FontFamilySelect/index.js +1 -1
  221. package/dist/components/GradientEditor/index.js +1 -1
  222. package/dist/components/InlineRange/index.js +1 -1
  223. package/dist/components/Input/index.js +1 -1
  224. package/dist/components/ItemList/index.js +1 -1
  225. package/dist/components/Jog/Jog.d.ts +1 -1
  226. package/dist/components/Jog/Jog.d.ts.map +1 -1
  227. package/dist/components/Jog/index.js +1 -1
  228. package/dist/components/Keycaps/Keycap.d.ts +1 -1
  229. package/dist/components/Keycaps/Keycap.d.ts.map +1 -1
  230. package/dist/components/Keycaps/Keycaps.d.ts +1 -1
  231. package/dist/components/Keycaps/Keycaps.d.ts.map +1 -1
  232. package/dist/components/Keycaps/index.js +2 -2
  233. package/dist/components/LayerList/LayerList.d.ts +1 -1
  234. package/dist/components/LayerList/LayerList.d.ts.map +1 -1
  235. package/dist/components/LayerList/index.js +1 -1
  236. package/dist/components/ListEditor/ListEditor.d.ts +1 -1
  237. package/dist/components/ListEditor/ListEditor.d.ts.map +1 -1
  238. package/dist/components/ListEditor/index.js +1 -1
  239. package/dist/components/MenuButton/MenuButton.d.ts +1 -1
  240. package/dist/components/MenuButton/MenuButton.d.ts.map +1 -1
  241. package/dist/components/MenuButton/index.js +1 -1
  242. package/dist/components/MeshEditor/index.js +1 -1
  243. package/dist/components/NumberField/UnitField.d.ts +1 -1
  244. package/dist/components/NumberField/UnitField.d.ts.map +1 -1
  245. package/dist/components/NumberField/index.js +1 -1
  246. package/dist/components/OptionsBar/index.js +1 -1
  247. package/dist/components/PaintField/index.js +1 -1
  248. package/dist/components/PaintInput/index.js +1 -1
  249. package/dist/components/PatternPicker/index.js +1 -1
  250. package/dist/components/Plot2D/index.js +1 -1
  251. package/dist/components/PointPlotter/PointPlotter.d.ts +1 -1
  252. package/dist/components/PointPlotter/PointPlotter.d.ts.map +1 -1
  253. package/dist/components/PointPlotter/index.js +1 -1
  254. package/dist/components/Powerline/Powerline.d.ts +1 -1
  255. package/dist/components/Powerline/Powerline.d.ts.map +1 -1
  256. package/dist/components/Powerline/index.js +2 -2
  257. package/dist/components/Prefs/PrefsDialog.d.ts +1 -1
  258. package/dist/components/Prefs/PrefsDialog.d.ts.map +1 -1
  259. package/dist/components/Prefs/PrefsForm.d.ts +1 -1
  260. package/dist/components/Prefs/PrefsForm.d.ts.map +1 -1
  261. package/dist/components/Prefs/PrefsPane.d.ts +1 -1
  262. package/dist/components/Prefs/PrefsPane.d.ts.map +1 -1
  263. package/dist/components/Prefs/PrefsRail.d.ts +1 -1
  264. package/dist/components/Prefs/PrefsRail.d.ts.map +1 -1
  265. package/dist/components/Prefs/PrefsRow.d.ts +1 -1
  266. package/dist/components/Prefs/PrefsRow.d.ts.map +1 -1
  267. package/dist/components/Prefs/index.js +2 -2
  268. package/dist/components/Properties/CurveField.d.ts +1 -1
  269. package/dist/components/Properties/CurveField.d.ts.map +1 -1
  270. package/dist/components/Properties/DialogRow.d.ts +1 -1
  271. package/dist/components/Properties/DialogRow.d.ts.map +1 -1
  272. package/dist/components/Properties/PropertyField.d.ts +2 -2
  273. package/dist/components/Properties/PropertyField.d.ts.map +1 -1
  274. package/dist/components/Properties/PropertyGroup.d.ts +1 -1
  275. package/dist/components/Properties/PropertyGroup.d.ts.map +1 -1
  276. package/dist/components/Properties/PropertyPanel.d.ts +4 -4
  277. package/dist/components/Properties/PropertyPanel.d.ts.map +1 -1
  278. package/dist/components/Properties/Subpanel.d.ts +1 -1
  279. package/dist/components/Properties/Subpanel.d.ts.map +1 -1
  280. package/dist/components/Properties/index.js +2 -2
  281. package/dist/components/Properties/storyLayouts.d.ts +1 -1
  282. package/dist/components/Properties/storyLayouts.d.ts.map +1 -1
  283. package/dist/components/RadioGroup/RadioGroup.d.ts +2 -2
  284. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  285. package/dist/components/RadioGroup/index.js +1 -1
  286. package/dist/components/RangeSlider/RangeSlider.d.ts +1 -1
  287. package/dist/components/RangeSlider/RangeSlider.d.ts.map +1 -1
  288. package/dist/components/RangeSlider/index.js +1 -1
  289. package/dist/components/ResizeHandle/ResizeHandle.d.ts +1 -1
  290. package/dist/components/ResizeHandle/ResizeHandle.d.ts.map +1 -1
  291. package/dist/components/ResizeHandle/index.js +1 -1
  292. package/dist/components/Select/Select.d.ts +3 -3
  293. package/dist/components/Select/Select.d.ts.map +1 -1
  294. package/dist/components/Select/index.js +1 -1
  295. package/dist/components/SelectionPanel/SelectionPanel.d.ts +1 -1
  296. package/dist/components/SelectionPanel/SelectionPanel.d.ts.map +1 -1
  297. package/dist/components/SelectionPanel/index.js +2 -2
  298. package/dist/components/Sidebar/Sidebar.d.ts +1 -1
  299. package/dist/components/Sidebar/Sidebar.d.ts.map +1 -1
  300. package/dist/components/Sidebar/index.js +1 -1
  301. package/dist/components/SidebarPanel/SidebarPanel.d.ts +1 -1
  302. package/dist/components/SidebarPanel/SidebarPanel.d.ts.map +1 -1
  303. package/dist/components/SidebarPanel/index.js +1 -1
  304. package/dist/components/Slider/Slider.d.ts +2 -1
  305. package/dist/components/Slider/Slider.d.ts.map +1 -1
  306. package/dist/components/Slider/index.js +1 -1
  307. package/dist/components/StatusBar/StatusBar.d.ts +3 -3
  308. package/dist/components/StatusBar/StatusBar.d.ts.map +1 -1
  309. package/dist/components/StatusBar/index.js +1 -1
  310. package/dist/components/SwatchGrid/index.js +1 -1
  311. package/dist/components/Switch/index.js +1 -1
  312. package/dist/components/Tabs/Tabs.d.ts +4 -4
  313. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  314. package/dist/components/Tabs/index.js +1 -1
  315. package/dist/components/Timeline/index.js +1 -1
  316. package/dist/components/Toast/Toast.d.ts +1 -1
  317. package/dist/components/Toast/Toast.d.ts.map +1 -1
  318. package/dist/components/Toast/index.js +1 -1
  319. package/dist/components/ToggleBar/index.js +1 -1
  320. package/dist/components/TokenPanel/TokenPanel.d.ts +1 -1
  321. package/dist/components/TokenPanel/TokenPanel.d.ts.map +1 -1
  322. package/dist/components/TokenPanel/index.js +1 -1
  323. package/dist/components/ToolButton/ToolButton.d.ts +1 -1
  324. package/dist/components/ToolButton/ToolButton.d.ts.map +1 -1
  325. package/dist/components/ToolButton/index.js +1 -1
  326. package/dist/components/ToolGroup/ToolGroup.d.ts +1 -1
  327. package/dist/components/ToolGroup/ToolGroup.d.ts.map +1 -1
  328. package/dist/components/ToolGroup/index.js +1 -1
  329. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts +1 -1
  330. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts.map +1 -1
  331. package/dist/components/ToolOptionsBar/index.js +1 -1
  332. package/dist/components/ToolPalette/ToolPalette.d.ts +1 -1
  333. package/dist/components/ToolPalette/ToolPalette.d.ts.map +1 -1
  334. package/dist/components/ToolPalette/index.js +2 -2
  335. package/dist/components/Tooltip/Tooltip.d.ts +2 -2
  336. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  337. package/dist/components/Tooltip/index.js +1 -1
  338. package/dist/components/Tree/index.js +1 -1
  339. package/dist/icons/Icon.d.ts +1 -1
  340. package/dist/icons/Icon.d.ts.map +1 -1
  341. package/dist/icons/ShapeKindIcon.d.ts +1 -1
  342. package/dist/icons/ShapeKindIcon.d.ts.map +1 -1
  343. package/dist/icons/index.d.ts +52 -52
  344. package/dist/icons/index.d.ts.map +1 -1
  345. package/dist/index.d.ts +1 -0
  346. package/dist/index.d.ts.map +1 -1
  347. package/dist/index.js +108 -89
  348. package/dist/index.js.map +1 -1
  349. package/dist/overlays/portalHost.d.ts +1 -1
  350. package/dist/overlays/portalHost.d.ts.map +1 -1
  351. package/dist/style.css +1 -1
  352. package/package.json +8 -8
  353. package/dist/chunks/ActionBar-CYvfmEz0.js.map +0 -1
  354. package/dist/chunks/Badge-DZ0lFs14.js.map +0 -1
  355. package/dist/chunks/BandEditor-D-nVrVO4.js.map +0 -1
  356. package/dist/chunks/Button-Dyp31jMt.js.map +0 -1
  357. package/dist/chunks/ButtonBar-smZzFuEo.js.map +0 -1
  358. package/dist/chunks/Callout-xLjnx7Mp.js.map +0 -1
  359. package/dist/chunks/Checkbox-ChZz30Ds.js.map +0 -1
  360. package/dist/chunks/Code-v4tDWuuN.js.map +0 -1
  361. package/dist/chunks/ColorField-DJSCuSJv.js.map +0 -1
  362. package/dist/chunks/ColorModeControl-JOEiqtE0.js.map +0 -1
  363. package/dist/chunks/ComboBox-C1JgIpML.js.map +0 -1
  364. package/dist/chunks/CurveEditor-f1R4kSbD.js.map +0 -1
  365. package/dist/chunks/DataGrid-CZPrB_3a.js.map +0 -1
  366. package/dist/chunks/DetailList-DHaXX4TG.js.map +0 -1
  367. package/dist/chunks/DetentSlider-BYyaZha6.js.map +0 -1
  368. package/dist/chunks/Dialog-GIvjoDQj.js.map +0 -1
  369. package/dist/chunks/Disclosure-D79jhmh2.js.map +0 -1
  370. package/dist/chunks/DragGhost-DcU7cOwy.js.map +0 -1
  371. package/dist/chunks/DragHandleGlyph-BtBxHjZS.js.map +0 -1
  372. package/dist/chunks/Field-xbqRmjsI.js.map +0 -1
  373. package/dist/chunks/FillStrokeSwatch-BViKXIPx.js.map +0 -1
  374. package/dist/chunks/FontFamilySelect-r9TV_xIH.js.map +0 -1
  375. package/dist/chunks/GradientEditor-BRTxHG-W.js.map +0 -1
  376. package/dist/chunks/Icon-BW0qv_U7.js.map +0 -1
  377. package/dist/chunks/InlineRange-BwGFDhpT.js.map +0 -1
  378. package/dist/chunks/Input-Bx2cuUbS.js.map +0 -1
  379. package/dist/chunks/ItemList-DzJ2lK0R.js.map +0 -1
  380. package/dist/chunks/ItemList.module-DDUXfuZL.js.map +0 -1
  381. package/dist/chunks/Jog-LPoac9s4.js.map +0 -1
  382. package/dist/chunks/Keycaps-CKiKOJnJ.js.map +0 -1
  383. package/dist/chunks/LayerList-BeGrkLb9.js.map +0 -1
  384. package/dist/chunks/ListEditor-C6zLzCsJ.js.map +0 -1
  385. package/dist/chunks/MenuButton-BcdhrNGh.js.map +0 -1
  386. package/dist/chunks/MeshEditor-BOOIFWnz.js.map +0 -1
  387. package/dist/chunks/NumberField-C1Y7zP-a.js.map +0 -1
  388. package/dist/chunks/OptionsBar-DlcagPYK.js.map +0 -1
  389. package/dist/chunks/PaintField-B2mLRZa4.js.map +0 -1
  390. package/dist/chunks/PaintInput-BFKhd83I.js.map +0 -1
  391. package/dist/chunks/PatternPicker-DdfpxoQy.js.map +0 -1
  392. package/dist/chunks/Plot2D-lyO7waPQ.js.map +0 -1
  393. package/dist/chunks/PointPlotter-DGs9i5P-.js.map +0 -1
  394. package/dist/chunks/Powerline-DBEPceLE.js +0 -38
  395. package/dist/chunks/Powerline-DBEPceLE.js.map +0 -1
  396. package/dist/chunks/Prefs-Ctu0H4-b.js.map +0 -1
  397. package/dist/chunks/Properties-Bbneh1ws.js.map +0 -1
  398. package/dist/chunks/PropertyField-CDb19d3F.js.map +0 -1
  399. package/dist/chunks/RadioGroup-BK2mD6Q0.js.map +0 -1
  400. package/dist/chunks/RangeSlider-BiRAOsTh.js.map +0 -1
  401. package/dist/chunks/ResizeHandle-Cc6EOehs.js.map +0 -1
  402. package/dist/chunks/Select-DVValBe1.js.map +0 -1
  403. package/dist/chunks/SelectionPanel-C5LmZA7b.js.map +0 -1
  404. package/dist/chunks/Sidebar-DKKd4R-x.js.map +0 -1
  405. package/dist/chunks/SidebarPanel-u5NsuAZY.js.map +0 -1
  406. package/dist/chunks/Slider-BwRrWHFW.js.map +0 -1
  407. package/dist/chunks/StatusBar-CdPdmmda.js.map +0 -1
  408. package/dist/chunks/SwatchGrid-C-Zx2Exd.js.map +0 -1
  409. package/dist/chunks/Switch-DxF7TsEu.js.map +0 -1
  410. package/dist/chunks/Tabs-GXEfoe3o.js.map +0 -1
  411. package/dist/chunks/Timeline-SgmpQtUV.js.map +0 -1
  412. package/dist/chunks/Toast-BfcljZz6.js.map +0 -1
  413. package/dist/chunks/ToggleBar-Btnl5r7F.js.map +0 -1
  414. package/dist/chunks/TokenPanel-5ajHEHha.js.map +0 -1
  415. package/dist/chunks/ToolButton-rzqlFlAc.js.map +0 -1
  416. package/dist/chunks/ToolGroup-4bUBV5k6.js.map +0 -1
  417. package/dist/chunks/ToolOptionsBar-BF3TNXA3.js.map +0 -1
  418. package/dist/chunks/ToolPalette-Uw4PvWwa.js.map +0 -1
  419. package/dist/chunks/Tooltip-9XiJF937.js.map +0 -1
  420. package/dist/chunks/Tree-BGt6P8tI.js.map +0 -1
  421. package/dist/chunks/createKeyframeLayer-BzDRCrrh.js.map +0 -1
  422. package/dist/chunks/dlog-CMYiRF3Q.js.map +0 -1
  423. package/dist/chunks/formatShortcut-BoGqUoWi.js.map +0 -1
  424. package/dist/chunks/icons-DbScMMqX.js +0 -179
  425. package/dist/chunks/icons-DbScMMqX.js.map +0 -1
  426. package/dist/chunks/keyGlyph-CLvUHU8c.js.map +0 -1
  427. package/dist/chunks/model-BQMvTLnW.js.map +0 -1
  428. package/dist/chunks/number-6S8IzXVt.js.map +0 -1
  429. package/dist/chunks/paintPreview-DPtZS4yU.js.map +0 -1
  430. package/dist/chunks/paintValue-Bz6AVuh3.js.map +0 -1
  431. package/dist/chunks/portalHost-CjpCnuGU.js.map +0 -1
  432. package/dist/chunks/prefField-CLkhrvYl.js.map +0 -1
  433. package/dist/chunks/segmentTooltip-CAkZlW-t.js.map +0 -1
  434. package/dist/chunks/segmentedControl.module-D2nw68Yo.js.map +0 -1
  435. package/dist/chunks/snap-DC4Km8xG.js.map +0 -1
  436. package/dist/chunks/stance-CarrcbbP.js.map +0 -1
  437. package/dist/chunks/useReorderDragList-Dcezzgix.js.map +0 -1
  438. package/dist/chunks/useRovingTabIndex-B4uJqiKP.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"number-6S8IzXVt.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/** Powers of ten a typed magnitude suffix stands for. */\nconst EXPONENTS: Record<string, number> = { k: 3, m: 6, b: 9, t: 12 };\n\n/**\n * Formats a number the way a `compact` readout shows it: below 1,000 at\n * `decimals` places, from 1,000 up at three significant figures with a magnitude\n * suffix (`40.0K`, `294K`, `2.00M`), so the readout holds one width whatever the\n * value. Always `en-US`, so {@link parseNumber} reads it back.\n */\nexport function formatCompact(value: number, decimals = 0): string {\n if (!Number.isFinite(value)) return formatNumber(value);\n const options: Intl.NumberFormatOptions =\n Math.abs(value) < 1000\n ? { useGrouping: false, minimumFractionDigits: decimals, maximumFractionDigits: decimals }\n : { notation: 'compact', minimumSignificantDigits: 3, maximumSignificantDigits: 3 };\n return value.toLocaleString('en-US', options).replace(/^-/, MINUS_SIGN);\n}\n\n/**\n * Reads a typed number: anything {@link parseSignedNumber} reads, plus\n * thousands commas in the `40,000` shape and a `k`/`m`/`b`/`t` suffix in either\n * case (`2.5m` is 2,500,000). Empty text is NaN rather than zero.\n *\n * Given `units` — a suffix mapped to the factor it scales by — a trailing unit\n * name is read first: the longest match wins, exact case before any case, and\n * a unit beats a magnitude suffix, so with `m` accepted `2m` is `2 * units.m`.\n */\nexport function parseNumber(text: string, units?: Readonly<UnitTable>): number {\n if (units) {\n const trimmed = text.trim();\n const name = unitSuffixOf(trimmed, units);\n if (name !== undefined) {\n const terms = compoundTermsOf(trimmed, units);\n if (terms !== undefined && terms.length > 1) return compoundValue(terms, trimmed, units);\n const { factor, offset } = scaleOf(units[name]!);\n return scaled(parseNumber(trimmed.slice(0, -name.length)), factor) + offset;\n }\n }\n let t = text.trim().replace(MINUS_SIGN, '-');\n const exponent = EXPONENTS[t.slice(-1).toLowerCase()];\n if (exponent !== undefined) t = t.slice(0, -1).trimEnd();\n if (/^[-+]?\\d{1,3}(,\\d{3})+(\\.\\d*)?$/.test(t)) t = t.replace(/,/g, '');\n if (!/\\d/.test(t)) return Number.NaN;\n // Scaled through the exponent rather than by multiplying: 1.1 * 1000 is 1100.0000000000002.\n return Number(exponent === undefined ? t : `${t}e${exponent}`);\n}\n\n/** One unit's conversion into the shown unit: a bare factor, or a scale that\n * also moves zero. Structurally the kit's `UnitEntry`, kept local so this\n * formatting helper stays free of the scene vocabulary. */\nexport type UnitTableEntry = number | { factor: number; offset?: number };\n/** Suffixes a person may type, each mapped to its conversion. */\nexport type UnitTable = Record<string, UnitTableEntry>;\n\n/** Divided by the reciprocal below 1: 12 * 0.1 is 1.2000000000000002, 12 / 10 is 1.2. */\nfunction scaled(n: number, factor: number): number {\n return factor < 1 ? n / (1 / factor) : n * factor;\n}\n\n/** A unit table entry's scale, with the bare-factor shorthand widened. */\nfunction scaleOf(entry: UnitTableEntry): { factor: number; offset: number } {\n return typeof entry === 'number'\n ? { factor: entry, offset: 0 }\n : { factor: entry.factor, offset: entry.offset ?? 0 };\n}\n\n/**\n * The unit names in `text`, in reading order, when every one of them closes a\n * `<number><unit>` term — which is what tells `5ft 3in` from a malformed\n * `5ft 3`. Undefined when the text is not a run of whole terms.\n */\nfunction compoundTermsOf(text: string, units: Readonly<UnitTable>): string[] | undefined {\n const names: string[] = [];\n let rest = text.trimEnd();\n while (rest !== '') {\n const name = unitSuffixOf(rest, units);\n if (name === undefined) return undefined;\n names.push(name);\n const before = rest.slice(0, -name.length);\n const m = /(\\d+(?:\\.\\d+)?|\\.\\d+)\\s*$/.exec(before);\n if (!m) return undefined;\n rest = before.slice(0, m.index).trimEnd();\n // A sign leads the whole value, so it ends the walk rather than a term.\n if (rest === '-' || rest === '+' || rest === MINUS_SIGN) rest = '';\n }\n return names.length === 0 ? undefined : names.reverse();\n}\n\n/**\n * `5ft 3in` as one number in the shown unit. Every term scales and they sum;\n * a leading sign carries across all of them, so `-5ft 3in` is −63in and not\n * −57. Offsets have no meaning in a sum — 1K + 2degC is not a temperature —\n * so a term carrying one makes the whole value unreadable.\n */\nfunction compoundValue(names: string[], text: string, units: Readonly<UnitTable>): number {\n const digits = text.match(/\\d+(?:\\.\\d+)?|\\.\\d+/g);\n if (!digits || digits.length !== names.length) return Number.NaN;\n const sign = /^\\s*[-\\u2212]/.test(text) ? -1 : 1;\n let total = 0;\n for (const [i, name] of names.entries()) {\n const { factor, offset } = scaleOf(units[name]!);\n if (offset !== 0) return Number.NaN;\n total += scaled(Number(digits[i]), factor);\n }\n return sign * total;\n}\n\n/** The longest unit name `text` ends with — exact case first, then any case. */\nfunction unitSuffixOf(text: string, units: Readonly<UnitTable>): string | undefined {\n const names = Object.keys(units).filter((n) => n !== '').sort((a, b) => b.length - a.length);\n const lower = text.toLowerCase();\n return names.find((n) => text.endsWith(n)) ?? names.find((n) => lower.endsWith(n.toLowerCase()));\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":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"paintPreview-DPtZS4yU.js","names":[],"sources":["../../src/paintPreview.ts"],"sourcesContent":["// A `FillStyle` as one CSS background string, for the swatches and chips that\n// stand in for a paint in a panel.\n//\n// The gradient kinds are sampled rather than translated stop for stop: CSS\n// blends its own stops in sRGB, so an OKLCh gradient handed over as two stops\n// would preview as the sRGB blend of its ends. Sampling through\n// `sampleGradientStops` in the paint's own space puts the curve into the\n// stops themselves, and the browser only interpolates the short hops between.\n\nimport { sampleGradientStops, type FillStyle } from '@weasel-js/core';\n\n/** Sample count along a previewed gradient. Enough that a hue arc reads as a\n * curve at chip size; a straight sRGB ramp would need a fraction of it. */\nconst SAMPLES = 24;\n\n/**\n * A mesh patch as four corner radials over a flat base.\n *\n * This is an approximation and cannot be anything else — CSS has no mesh, and\n * the real surface only exists once the renderer has baked it. Each corner\n * fades out across the chip and they composite to something bilinear-ish,\n * which is enough for a swatch to say \"this one, not that one\". Zero alpha is\n * written as `color-mix` with `transparent` so a named or packed-alpha color\n * works without being parsed here.\n */\nfunction meshPreview(paint: { patches?: { colors: string[] }[] }): string | undefined {\n const colors = paint.patches?.[0]?.colors;\n if (!colors || colors.length < 4) return undefined;\n const fade = (c: string): string => `color-mix(in srgb, ${c} 0%, transparent)`;\n const at: [string, string][] = [\n ['0% 0%', colors[0]], ['100% 0%', colors[1]],\n ['100% 100%', colors[2]], ['0% 100%', colors[3]],\n ];\n const layers = at.map(([pos, c]) =>\n `radial-gradient(farthest-corner at ${pos}, ${c}, ${fade(c)})`);\n // The base keeps the middle opaque where the four fades have all thinned.\n layers.push(`linear-gradient(to bottom, ${colors[0]}, ${colors[2]})`);\n return layers.join(', ');\n}\n\n/** CSS color stops across the whole ramp, in the gradient's own blend space. */\nfunction sampledStops(paint: Extract<FillStyle, { stops: unknown }>): string {\n const space = paint.interpolate ?? 'rgb';\n const out: string[] = [];\n for (let i = 0; i <= SAMPLES; i++) {\n const t = i / SAMPLES;\n out.push(`${sampleGradientStops(paint.stops, t, space)} ${(t * 100).toFixed(1)}%`);\n }\n return out.join(', ');\n}\n\nconst DEG = 180 / Math.PI;\n\n/** A fraction of the box as a CSS percentage. A gradient in absolute units has\n * no box to be a fraction of, so its geometry only ever approximates here. */\nfunction pct(v: number): string {\n return `${(v * 100).toFixed(1)}%`;\n}\n\n/**\n * `paint` as a CSS `background` value, or `undefined` for a paint with no CSS\n * form — a pattern, a registered kind — which a caller shows as a checker or\n * a placeholder rather than as an invented color.\n *\n * Gradient geometry is honored as far as CSS can carry it: the angle of a\n * linear gradient, the center of a radial or conic one. A paint in `'world'`\n * or `'local'` units is measured in the scene rather than in the chip, so its\n * preview shows the ramp and not the placement.\n */\nexport function paintPreviewCss(paint: FillStyle | null | undefined): string | undefined {\n if (paint == null) return undefined;\n const kind = paint.fill ?? 'solid';\n if (kind === 'solid') return (paint as { color: string }).color;\n\n if (paint.fill === 'linear-gradient') {\n const dx = paint.to.x - paint.from.x;\n const dy = paint.to.y - paint.from.y;\n // CSS measures from \"to top\", clockwise; the paint measures in a\n // y-down plane from +x.\n const angle = dx === 0 && dy === 0 ? 90 : Math.atan2(dx, -dy) * DEG;\n return `linear-gradient(${angle.toFixed(1)}deg, ${sampledStops(paint)})`;\n }\n if (paint.fill === 'radial-gradient') {\n const at = `at ${pct(paint.center.x)} ${pct(paint.center.y)}`;\n return `radial-gradient(circle ${at}, ${sampledStops(paint)})`;\n }\n if ((paint.fill as string) === 'mesh-gradient') {\n return meshPreview(paint as unknown as { patches?: { colors: string[] }[] });\n }\n if (paint.fill === 'conic-gradient') {\n // CSS starts a conic gradient at \"to top\"; the paint starts at +x.\n const from = (paint.angle * DEG + 90).toFixed(1);\n return `conic-gradient(from ${from}deg at ${pct(paint.center.x)} ${pct(paint.center.y)}, ${sampledStops(paint)})`;\n }\n return undefined;\n}\n"],"mappings":";;AAaA,IAAM,IAAU;AAYhB,SAAS,EAAY,GAAiE;CACpF,IAAM,IAAS,EAAM,UAAU,IAAI;AACnC,KAAI,CAAC,KAAU,EAAO,SAAS,EAAG;CAClC,IAAM,KAAQ,MAAsB,sBAAsB,EAAE,oBAKtD,IAAS;EAHb,CAAC,SAAS,EAAO,GAAG;EAAE,CAAC,WAAW,EAAO,GAAG;EAC5C,CAAC,aAAa,EAAO,GAAG;EAAE,CAAC,WAAW,EAAO,GAAG;EAEnC,CAAG,KAAK,CAAC,GAAK,OAC3B,sCAAsC,EAAI,IAAI,EAAE,IAAI,EAAK,EAAE,CAAC,GAAG;AAGjE,QADA,EAAO,KAAK,8BAA8B,EAAO,GAAG,IAAI,EAAO,GAAG,GAAG,EAC9D,EAAO,KAAK,KAAK;;AAI1B,SAAS,EAAa,GAAuD;CAC3E,IAAM,IAAQ,EAAM,eAAe,OAC7B,IAAgB,EAAE;AACxB,MAAK,IAAI,IAAI,GAAG,KAAK,GAAS,KAAK;EACjC,IAAM,IAAI,IAAI;AACd,IAAI,KAAK,GAAG,EAAoB,EAAM,OAAO,GAAG,EAAM,CAAC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC,GAAG;;AAEpF,QAAO,EAAI,KAAK,KAAK;;AAGvB,IAAM,IAAM,MAAM,KAAK;AAIvB,SAAS,EAAI,GAAmB;AAC9B,QAAO,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;;AAajC,SAAgB,EAAgB,GAAyD;AACnF,UAAS,MAEb;OADa,EAAM,QAAQ,aACd,QAAS,QAAQ,EAA4B;AAE1D,MAAI,EAAM,SAAS,mBAAmB;GACpC,IAAM,IAAK,EAAM,GAAG,IAAI,EAAM,KAAK,GAC7B,IAAK,EAAM,GAAG,IAAI,EAAM,KAAK;AAInC,UAAO,oBADO,MAAO,KAAK,MAAO,IAAI,KAAK,KAAK,MAAM,GAAI,CAAC,EAAG,GAAG,GAChC,QAAQ,EAAE,CAAC,OAAO,EAAa,EAAM,CAAC;;AAExE,MAAI,EAAM,SAAS,kBAEjB,QAAO,0BAA0B,MADhB,EAAI,EAAM,OAAO,EAAE,CAAC,GAAG,EAAI,EAAM,OAAO,EAAE,GACvB,IAAI,EAAa,EAAM,CAAC;AAE9D,MAAK,EAAM,SAAoB,gBAC7B,QAAO,EAAY,EAAyD;AAE9E,MAAI,EAAM,SAAS,iBAGjB,QAAO,wBADO,EAAM,QAAQ,IAAM,IAAI,QAAQ,EAChB,CAAK,SAAS,EAAI,EAAM,OAAO,EAAE,CAAC,GAAG,EAAI,EAAM,OAAO,EAAE,CAAC,IAAI,EAAa,EAAM,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"paintValue-Bz6AVuh3.js","names":[],"sources":["../../src/components/paintValue.ts"],"sourcesContent":["// Reading and writing the paint objects a property control may be pointed at.\n//\n// `data.fill` is a `FillStyle` and `data.stroke` a `Stroke`, so a control that\n// assumes either is a hex string reads `undefined` off it and writes a bare\n// string back over it. These helpers are what keep a control honest about the\n// shape it is holding.\n\n/** Whether a value is a `FillStyle` at all: an object naming a kind, or one\n * carrying a color, which is the solid member with its optional tag left off.\n * A pref's stored value is `unknown`, so this is what stands between a paint\n * control and a string someone saved there. */\nexport function isPaint(value: unknown): value is { fill?: string; color?: string } {\n if (typeof value !== 'object' || value === null) return false;\n const paint = value as { fill?: unknown; color?: unknown };\n return typeof paint.fill === 'string' || typeof paint.color === 'string';\n}\n\n/** The color of a solid paint, or `undefined` for anything else — including a\n * value that isn't a paint at all. `fill` is optional on the solid member of\n * the union, so the tag alone can't decide it. */\nexport function solidColorOf(value: unknown): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const paint = value as { fill?: string; color?: unknown };\n if (paint.fill !== undefined && paint.fill !== 'solid') return undefined;\n return typeof paint.color === 'string' ? paint.color : undefined;\n}\n\n/** The single color a stroke shows, or `undefined` when it has none to show —\n * a gradient or pattern stroke, or no stroke at all. */\nexport function strokeColorOf(value: unknown): string | undefined {\n if (typeof value !== 'object' || value === null || !('paint' in value)) return undefined;\n return solidColorOf((value as { paint: unknown }).paint);\n}\n"],"mappings":";AAWA,SAAgB,EAAQ,GAA4D;AAClF,KAAI,OAAO,KAAU,aAAY,EAAgB,QAAO;CACxD,IAAM,IAAQ;AACd,QAAO,OAAO,EAAM,QAAS,YAAY,OAAO,EAAM,SAAU;;AAMlE,SAAgB,EAAa,GAAoC;AAC/D,KAAI,OAAO,KAAU,aAAY,EAAgB;CACjD,IAAM,IAAQ;AACV,SAAM,SAAS,KAAA,KAAa,EAAM,SAAS,SAC/C,QAAO,OAAO,EAAM,SAAU,WAAW,EAAM,QAAQ,KAAA;;AAKzD,SAAgB,EAAc,GAAoC;AAC5D,cAAO,KAAU,aAAY,KAAkB,EAAE,WAAW,IAChE,QAAO,EAAc,EAA6B,MAAM"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"portalHost-CjpCnuGU.js","names":[],"sources":["../../src/overlays/portalHost.tsx"],"sourcesContent":["import { createContext, useContext, useState, type ReactElement, type ReactNode } from 'react';\n\n/**\n * Elements an overlay may portal into: anything a theme has been stamped on\n * (`applyTheme` / `<ThemeProvider>` write both attributes), plus anything\n * opting in with `data-wzl-portal-host`. The opt-in exists for a styling root\n * that sits *below* the themed element — labkit's `.lk-root` carries element\n * defaults the themed wrapper does not.\n */\nconst HOST_SELECTOR = '[data-wzl-portal-host],[data-wzl-theme],[data-wzl-mode]';\n\n/**\n * The nearest element `from` sits inside that can host a portalled overlay,\n * or `null` when there is none and the body is the only answer.\n */\nexport function nearestPortalHost(from: Element | null | undefined): HTMLElement | null {\n return (from?.closest(HOST_SELECTOR) as HTMLElement | null) ?? null;\n}\n\n/** `undefined` distinguishes \"no provider\" from a provider saying `null`. */\nconst OverlayPortalContext = createContext<Element | null | undefined>(undefined);\n\n/** Props for {@link OverlayPortalProvider}. */\nexport interface OverlayPortalProviderProps {\n /** Where overlays in this subtree portal. `null` means `document.body`. */\n container: Element | null;\n children: ReactNode;\n}\n\n/**\n * Sets the portal container for every weasel overlay rendered below it,\n * overriding the nearest-themed-ancestor default. An individual overlay's\n * own `portalContainer` prop still wins.\n */\nexport function OverlayPortalProvider({ container, children }: OverlayPortalProviderProps) {\n return (\n <OverlayPortalContext.Provider value={container}>{children}</OverlayPortalContext.Provider>\n );\n}\n\n/** The `portalContainer` prop every weasel overlay accepts. */\nexport interface OverlayPortalProps {\n /**\n * Where the overlay's portal mounts. Defaults to the nearest ancestor of\n * the overlay's own position that carries a weasel theme, so the overlay\n * resolves the same `--wzl-*` tokens as the control it belongs to. Pass\n * `null` for `document.body`.\n */\n portalContainer?: Element | null;\n}\n\n/** React Aria props minus the portal key a weasel overlay owns. */\nexport type WithoutPortalTarget<T> = Omit<T, 'UNSTABLE_portalContainer'>;\n\n/** Spread onto the React Aria overlay. The unstable key is spelled here and\n * nowhere else in the package, so an upstream rename lands in one file. */\nexport interface OverlayPortalTarget {\n UNSTABLE_portalContainer: Element | undefined;\n}\n\n/**\n * Resolves where an overlay should portal, and the anchor that answers it.\n *\n * The result goes to React Aria as `UNSTABLE_portalContainer`. Its documented\n * replacement, `UNSAFE_PortalProvider`, is not re-exported by\n * react-aria-components 1.18, and reaching past it to `react-aria` for the\n * provider risks a second copy of that package whose context the overlays\n * never read — a failure that shows up as an unthemed overlay, not an error.\n *\n * Render `anchor` at the component's own position in the tree — outside the\n * portal — and spread `portalProps` onto the React Aria overlay. The anchor\n * is what \"nearest themed ancestor\" is measured from; the first render has\n * none yet, so an overlay that mounts already open lands in its host on the\n * following render, before paint.\n */\nexport function useOverlayPortal(explicit?: Element | null): {\n anchor: ReactElement;\n portalProps: OverlayPortalTarget;\n} {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const fromProvider = useContext(OverlayPortalContext);\n\n const resolved =\n explicit !== undefined\n ? explicit\n : fromProvider !== undefined\n ? fromProvider\n : nearestPortalHost(anchorEl);\n\n return {\n anchor: <span hidden ref={setAnchorEl} />,\n portalProps: { UNSTABLE_portalContainer: resolved ?? undefined },\n };\n}\n"],"mappings":";;;AASA,IAAM,IAAgB;AAMtB,SAAgB,EAAkB,GAAsD;AACtF,QAAQ,GAAM,QAAQ,EAAc,IAA2B;;AAIjE,IAAM,IAAuB,EAA0C,KAAA,EAAU;AAcjF,SAAgB,EAAsB,EAAE,cAAW,eAAwC;AACzF,QACE,kBAAC,EAAqB,UAAtB;EAA+B,OAAO;EAAY;EAAyC,CAAA;;AAuC/F,SAAgB,EAAiB,GAG/B;CACA,IAAM,CAAC,GAAU,KAAe,EAA6B,KAAK,EAC5D,IAAe,EAAW,EAAqB,EAE/C,IACJ,MAAa,KAAA,IAET,MAAiB,KAAA,IAEf,EAAkB,EAAS,GAD3B,IAFF;AAKN,QAAO;EACL,QAAQ,kBAAC,QAAD;GAAM,QAAA;GAAO,KAAK;GAAe,CAAA;EACzC,aAAa,EAAE,0BAA0B,KAAY,KAAA,GAAW;EACjE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefField-CLkhrvYl.js","names":[],"sources":["../../src/components/Prefs/schema.ts","../../src/components/Prefs/prefField.tsx"],"sourcesContent":["// Preference-schema vocabulary for PrefsForm / PrefsDialog / SelectionPanel:\n// core's `ToolPref*` family under this package's names. Never re-declare them\n// here — this was a hand-kept structural copy until it drifted, and the\n// independence from `@weasel-js/core` it bought is long gone anyway.\n\nexport type {\n ToolPref as BuiltinPref,\n ToolPrefBoolean as PrefBoolean,\n ToolPrefBooleanControl as PrefBooleanControl,\n ToolPrefColor as PrefColor,\n ToolPrefCustom as PrefCustom,\n ToolPrefEnum as PrefEnum,\n ToolPrefEnumControl as PrefEnumControl,\n ToolPrefEnumEncoding as PrefEnumEncoding,\n ToolPrefGroup as PrefGroup,\n ToolPrefKind as PrefKind,\n ToolPrefLeaf as PrefLeaf,\n ToolPrefNumber as PrefNumber,\n ToolPrefNumberControl as PrefNumberControl,\n ToolPrefNumberFormat as PrefNumberFormat,\n ToolPrefNumberUnit as PrefNumberUnit,\n ToolPrefObject as PrefObject,\n ToolPrefPaint as PrefPaint,\n ToolPrefString as PrefString,\n ToolPrefStringControl as PrefStringControl,\n} from '@weasel-js/core';\n\nimport type { UnitTable } from '../../format/number';\nimport type { ToolPrefGroup, ToolPrefLeaf, ToolPrefNumber, ToolPrefNumberUnit as PrefNumberUnitType } from '@weasel-js/core';\n\n/**\n * A number leaf's bounds in the unit it is displayed in.\n *\n * Only what the leaf declares converts: an omitted bound has no stored\n * counterpart to put through the conversion, and its fallback — 0..100 for a\n * slider's track, a step of 1 — is a display-space number already. `min` and\n * `max` are points, so they convert the way the value does; `step` is a\n * distance, and a unit with an offset maps zero somewhere else, so converting\n * it as a point would scale it wrong. A decreasing conversion swaps which end\n * is the lower one.\n */\nexport function prefDisplayBounds(\n p: ToolPrefNumber,\n): { min?: number; max?: number; step: number } {\n if (!p.unit) return { min: p.min, max: p.max, step: p.step ?? 1 };\n const { toDisplay } = p.unit;\n const lo = p.min === undefined ? undefined : toDisplay(p.min);\n const hi = p.max === undefined ? undefined : toDisplay(p.max);\n const flipped = lo !== undefined && hi !== undefined && lo > hi;\n const step = p.step === undefined\n ? 1\n : Math.abs(toDisplay(p.step) - toDisplay(0)) || p.step;\n return { min: flipped ? hi : lo, max: flipped ? lo : hi, step };\n}\n\n/** What a unit leaf's field reads as typed text: its `accepts` table, and its\n * `suffix` as the display unit itself. */\nexport function prefUnitAccepts(unit: PrefNumberUnitType): Readonly<UnitTable> {\n return unit.suffix === undefined ? { ...unit.accepts } : { [unit.suffix]: 1, ...unit.accepts };\n}\n\n/** Distinguishes a leaf from a group while walking a schema tree. */\nexport function isPrefLeaf(node: ToolPrefLeaf | ToolPrefGroup): node is ToolPrefLeaf {\n return 'kind' in node;\n}\n\n/** Get the value at a dotted path inside a nested value tree. Returns\n * `undefined` when a segment is missing or hits a non-object. */\nexport function prefValueAtPath(values: unknown, path: string): unknown {\n let cur: unknown = values;\n for (const seg of path.split('.')) {\n if (cur == null || typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[seg];\n }\n return cur;\n}\n\n/**\n * Recursively drop `hidden` leaves (unless `showHidden`), pruning groups\n * that end up empty. Returns null when the entire subtree is hidden.\n */\nexport function visiblePrefSubtree<T extends ToolPrefLeaf | ToolPrefGroup>(\n node: T,\n showHidden: boolean,\n): T | null {\n if (isPrefLeaf(node)) return node.hidden && !showHidden ? null : node;\n const group = node as ToolPrefGroup;\n const children: Record<string, ToolPrefLeaf | ToolPrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = visiblePrefSubtree(child, showHidden);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0) return null;\n return { ...node, children };\n}\n\n/** One entry in a {@link PrefsForm} rail: a group the reader can navigate to. */\nexport interface PrefRailItem {\n /** Dotted path of the group. Empty for the entry holding loose root leaves. */\n path: string;\n name: string;\n /** 0 opens a pane; 1 scrolls within the open one. The rail goes no deeper. */\n depth: 0 | 1;\n /** Path of the depth-0 ancestor — its own path when `depth` is 0. */\n section: string;\n /** Leaves surviving the active filter, counted over the whole subtree. */\n matches: number;\n}\n\n/** Leaves anywhere under `node`, counted. */\nfunction countPrefLeaves(node: ToolPrefLeaf | ToolPrefGroup): number {\n if (isPrefLeaf(node)) return 1;\n let n = 0;\n for (const child of Object.values(node.children)) n += countPrefLeaves(child);\n return n;\n}\n\n/**\n * The rail's model for a schema: depth-0 groups, each followed by its depth-1\n * children. Deeper groups render inside a pane and get no entry — a schema\n * that nests ten deep still navigates two levels.\n *\n * Loose leaves directly under the root lead the list under an entry named for\n * the root itself, since they belong to no group that could name them.\n */\nexport function prefRailItems(root: ToolPrefGroup): PrefRailItem[] {\n const items: PrefRailItem[] = [];\n const loose = Object.values(root.children).filter(isPrefLeaf).length;\n if (loose > 0) {\n items.push({ path: '', name: root.name, depth: 0, section: '', matches: loose });\n }\n for (const [key, child] of Object.entries(root.children)) {\n if (isPrefLeaf(child)) continue;\n items.push({\n path: key,\n name: child.name,\n depth: 0,\n section: key,\n matches: countPrefLeaves(child),\n });\n for (const [subKey, sub] of Object.entries(child.children)) {\n if (isPrefLeaf(sub)) continue;\n items.push({\n path: `${key}.${subKey}`,\n name: sub.name,\n depth: 1,\n section: key,\n matches: countPrefLeaves(sub),\n });\n }\n }\n return items;\n}\n\n/** Whether one leaf answers to a filter query, by name, description or path. */\nfunction prefLeafMatches(pref: ToolPrefLeaf, path: string, query: string): boolean {\n if (pref.name.toLowerCase().includes(query)) return true;\n if (pref.description?.toLowerCase().includes(query)) return true;\n return path.toLowerCase().includes(query);\n}\n\n/**\n * Drop every leaf that does not answer to `query`, pruning groups left empty.\n * A group whose own name matches keeps all of its leaves — a reader who typed\n * the group's name is asking for the group, not for leaves repeating it.\n *\n * An empty or whitespace query matches everything, so a cleared field restores\n * the tree rather than emptying it.\n */\nexport function filterPrefSubtree<T extends ToolPrefLeaf | ToolPrefGroup>(\n node: T,\n query: string,\n path = '',\n): T | null {\n const q = query.trim().toLowerCase();\n if (q === '') return node;\n if (isPrefLeaf(node)) return prefLeafMatches(node, path, q) ? node : null;\n const group = node as ToolPrefGroup;\n if (group.name.toLowerCase().includes(q)) return node;\n const children: Record<string, ToolPrefLeaf | ToolPrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = filterPrefSubtree(child, q, path === '' ? key : `${path}.${key}`);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0) return null;\n return { ...node, children };\n}\n","import type { ReactNode } from 'react';\nimport { isBuiltinToolPref, type FillStyle } from '@weasel-js/core';\nimport { Icon } from '../../icons/Icon';\nimport { ICON_PATHS, type IconName } from '../../icons/paths';\nimport { isPaint } from '../paintValue';\nimport type { PropertyControlProps } from '../Properties/PropertyField';\nimport { prefDisplayBounds, prefUnitAccepts, type PrefLeaf } from './schema';\n\n/** What {@link prefFieldProps} is told about one leaf's value. */\nexport interface PrefFieldState {\n /** The value held at the leaf. `undefined` when `mixed` or `unset`. */\n value: unknown;\n mixed?: boolean;\n unset?: boolean;\n /** The object the leaf is a field of, for an enum `encoding` and a font's\n * weight and slant. `undefined` for a top-level leaf. */\n siblings?: Record<string, unknown>;\n /** Writes a value in the leaf's stored form. */\n setValue: (value: unknown) => void;\n /** A font family's weight and slant, where they are not `siblings`' own\n * `fontWeight` / `fontStyle`. */\n fontVariant?: { weight?: unknown; style?: unknown };\n}\n\n/**\n * A schema leaf as {@link PropertyControl} props: its value, bounds and\n * options in the form it is shown in, and a writer that stores what the\n * control reports in the form the leaf holds.\n *\n * The conversions every schema-driven surface needs live here once — a\n * number's display unit and its bounds, an enum's `encoding`, a color's\n * alpha, an icon resolved to a glyph. A leaf that is not a single control —\n * an `object`, whose fields each are, or an app-defined kind — returns\n * `null`, and the surface draws it.\n *\n * Spread the result and add what the surface decides: `chrome`, `name`, a\n * class, a different default `control`.\n */\nexport function prefFieldProps(leaf: PrefLeaf, state: PrefFieldState): PropertyControlProps | null {\n const { value, mixed = false, unset = false, siblings, setValue } = state;\n if (leaf.kind === 'font-family') {\n const weight = state.fontVariant ? state.fontVariant.weight : siblings?.fontWeight;\n const style = state.fontVariant ? state.fontVariant.style : siblings?.fontStyle;\n return {\n kind: 'font-family',\n value: typeof value === 'string' ? value : undefined,\n mixed,\n unset,\n onChange: setValue,\n weight: typeof weight === 'number' ? weight : undefined,\n fontStyle: style === 'italic' ? 'italic' : undefined,\n };\n }\n if (!isBuiltinToolPref(leaf)) return null;\n switch (leaf.kind) {\n case 'boolean':\n return {\n kind: 'boolean',\n control: leaf.control,\n value: typeof value === 'boolean' ? value : undefined,\n mixed,\n unset,\n glyph: glyphOf(leaf.icon) ?? leaf.short,\n onChange: setValue,\n };\n case 'number': {\n const unit = leaf.unit;\n const stored = typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n // `min`/`max`/`step` are declared in the stored unit, like the value, so\n // they convert with it — a leaf storing radians and showing degrees was\n // clamping typed degrees against 0..6.28.\n const bounds = prefDisplayBounds(leaf);\n const clamp = (n: number) =>\n Math.min(bounds.max ?? Infinity, Math.max(bounds.min ?? -Infinity, n));\n const store = (shown: number) => setValue(unit ? unit.fromDisplay(clamp(shown)) : clamp(shown));\n return {\n kind: 'number',\n control: leaf.control,\n value: stored === undefined ? undefined : unit ? unit.toDisplay(stored) : stored,\n mixed,\n unset,\n min: bounds.min,\n max: bounds.max,\n step: bounds.step,\n unit: unit?.suffix,\n accepts: unit ? prefUnitAccepts(unit) : undefined,\n notation: leaf.format,\n onChange: store,\n };\n }\n case 'string':\n return {\n kind: 'string',\n control: leaf.control,\n value: typeof value === 'string' ? value : '',\n mixed,\n unset,\n onChange: setValue,\n };\n case 'enum': {\n const encoding = leaf.encoding;\n // An encoded leaf stores something other than the option string (a dash\n // array), so the option comes from the encoding — and an absent field is\n // one of the things it reads (no dash is `solid`), which is why `unset`\n // does not blank it.\n const option = encoding\n ? mixed\n ? undefined\n : encoding.read(value, siblings)\n : mixed || unset\n ? undefined\n : typeof value === 'string'\n ? value\n : leaf.default;\n return {\n kind: 'enum',\n control: leaf.control,\n value: option,\n mixed,\n unset,\n options: leaf.options.map((o) => ({\n value: o.value,\n label: o.label,\n glyph: glyphOf(o.icon) ?? o.short,\n disabled: o.disabled,\n })),\n onChange: (next: string) => setValue(encoding ? encoding.write(next, siblings) : next),\n };\n }\n case 'color':\n return {\n kind: 'color',\n value: typeof value === 'string' ? value : leaf.default,\n mixed,\n unset,\n alpha: leaf.alpha ? true : undefined,\n onChange: setValue,\n };\n case 'paint': {\n // `??` would read an explicit `null` — \"no paint\" — as absent and show\n // the default over it. Unset shows the fallback actually in effect,\n // dimmed by the control: true, but not chosen.\n const paint =\n value === null\n ? null\n : isPaint(value)\n ? value\n : mixed\n ? undefined\n : isPaint(leaf.default)\n ? leaf.default\n : null;\n return {\n kind: 'paint',\n value: paint as FillStyle | null | undefined,\n mixed,\n unset,\n onChange: setValue,\n };\n }\n case 'object':\n return null;\n default: {\n // Not reachable while every built-in kind has an arm — and a new kind\n // that lacks one is a compile error here, never a blank row.\n const _exhaustive: never = leaf;\n throw new Error(\n `prefFieldProps: no control for built-in pref kind \"${(_exhaustive as { kind: string }).kind}\"`,\n );\n }\n }\n}\n\n/** A leaf's `icon` as a glyph, where the kit's icon set has it. */\nfunction glyphOf(icon: string | undefined): ReactNode {\n return icon && icon in ICON_PATHS ? <Icon name={icon as IconName} size={14} /> : undefined;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"segmentTooltip-CAkZlW-t.js","names":[],"sources":["../../src/components/segmentTooltip.tsx"],"sourcesContent":["import type { DOMAttributes, ReactElement, ReactNode } from 'react';\nimport { Focusable } from 'react-aria-components';\nimport { Tooltip, TooltipTrigger } from './Tooltip';\n\n/** The tooltip fields a segmented bar's item carries. */\nexport interface SegmentTooltipFields {\n /** Tooltip content. Overrides the name-plus-`shortcut` default. */\n tooltip?: ReactNode;\n /** Shortcut hint shown in the tooltip as `Name (⌘Z)`, the way `ToolButton`\n * and `ActionBar` show theirs. The name is `ariaLabel`, else a string\n * `label`. */\n shortcut?: string;\n}\n\n/** Tooltip content for an item, or `undefined` for none. */\nexport function segmentTooltipContent(\n item: SegmentTooltipFields & { label?: ReactNode; ariaLabel?: string },\n): ReactNode | undefined {\n if (item.tooltip !== undefined) return item.tooltip;\n if (!item.shortcut) return undefined;\n const name = item.ariaLabel ?? (typeof item.label === 'string' ? item.label : undefined);\n return name ? `${name} (${item.shortcut})` : item.shortcut;\n}\n\n/** Wraps a segment's `<button>` in a kit tooltip when there is content for one. */\nexport function SegmentTooltip({ content, disabled, children }: {\n content: ReactNode | undefined;\n disabled?: boolean;\n children: ReactElement<DOMAttributes<HTMLButtonElement>, 'button'>;\n}): ReactElement {\n if (content === undefined || content === null || content === false) return children;\n return (\n <TooltipTrigger isDisabled={disabled}>\n <Focusable isDisabled={disabled}>{children}</Focusable>\n <Tooltip>{content}</Tooltip>\n </TooltipTrigger>\n );\n}\n\n/** {@link SegmentTooltip} for a React Aria trigger (`Button` inside a\n * `MenuTrigger` or `Select`), which takes the tooltip's hover and focus props\n * itself and so needs no `Focusable` around it. */\nexport function TriggerTooltip({ content, disabled, children }: {\n content: ReactNode | undefined;\n disabled?: boolean;\n children: ReactElement;\n}): ReactElement {\n if (content === undefined || content === null || content === false) return children;\n return (\n <TooltipTrigger isDisabled={disabled}>\n {children}\n <Tooltip>{content}</Tooltip>\n </TooltipTrigger>\n );\n}\n"],"mappings":";;;;AAeA,SAAgB,EACd,GACuB;AACvB,KAAI,EAAK,YAAY,KAAA,EAAW,QAAO,EAAK;AAC5C,KAAI,CAAC,EAAK,SAAU;CACpB,IAAM,IAAO,EAAK,cAAc,OAAO,EAAK,SAAU,WAAW,EAAK,QAAQ,KAAA;AAC9E,QAAO,IAAO,GAAG,EAAK,IAAI,EAAK,SAAS,KAAK,EAAK;;AAIpD,SAAgB,EAAe,EAAE,YAAS,aAAU,eAInC;AAEf,QADI,KAAqC,QAAQ,MAAY,KAAc,IAEzE,kBAAC,GAAD;EAAgB,YAAY;YAA5B,CACE,kBAAC,GAAD;GAAW,YAAY;GAAW;GAAqB,CAAA,EACvD,kBAAC,GAAD,EAAA,UAAU,GAAkB,CAAA,CACb;;;AAOrB,SAAgB,EAAe,EAAE,YAAS,aAAU,eAInC;AAEf,QADI,KAAqC,QAAQ,MAAY,KAAc,IAEzE,kBAAC,GAAD;EAAgB,YAAY;YAA5B,CACG,GACD,kBAAC,GAAD,EAAA,UAAU,GAAkB,CAAA,CACb"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"segmentedControl.module-D2nw68Yo.js","names":[],"sources":["../../src/components/segmentedControl.module.css"],"sourcesContent":["/* Shared by ButtonBar 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: var(--wzl-space-1);\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 /* The track's stretch sizes a segment; without this, labkit's :where(button) height wins and overflows a small bar. */\n height: auto;\n padding: 0 var(--wzl-space-6);\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 var(--wzl-space-4);\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: var(--wzl-space-1);\n}\n\n.variant_minimal .segment {\n padding: 0 var(--wzl-space-2);\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 +0,0 @@
1
- {"version":3,"file":"snap-DC4Km8xG.js","names":[],"sources":["../../src/snap.ts"],"sourcesContent":["/** How close, in screen pixels, a drag has to come to a candidate to snap to it. */\nexport const SNAP_RADIUS_PX = 6;\n\n/** Snap `value` to the nearest candidate within `tolerance`, else return it. */\nexport function snapToNearest(value: number, candidates: readonly number[], tolerance: number): number {\n let best = value;\n let bestDist = tolerance;\n for (const c of candidates) {\n const d = Math.abs(c - value);\n if (d <= bestDist) {\n best = c;\n bestDist = d;\n }\n }\n return best;\n}\n"],"mappings":";AAIA,SAAgB,EAAc,GAAe,GAA+B,GAA2B;CACrG,IAAI,IAAO,GACP,IAAW;AACf,MAAK,IAAM,KAAK,GAAY;EAC1B,IAAM,IAAI,KAAK,IAAI,IAAI,EAAM;AAC7B,EAAI,KAAK,MACP,IAAO,GACP,IAAW;;AAGf,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"stance-CarrcbbP.js","names":[],"sources":["../../src/components/stance.ts"],"sourcesContent":["import { colorCssAt, type Stance } from '@weasel-js/theme';\nimport { useTones } from '@weasel-js/theme/react';\nimport type { CSSProperties } from 'react';\n\nexport type { Stance } from '@weasel-js/theme';\n\n/**\n * What a surface holds, and which of its peers it is. Every surface that takes\n * these takes both, and the theme decides how each looks.\n */\nexport interface StanceProps {\n /** The class of content the surface holds. Omitted, it draws as it always has. */\n stance?: Stance;\n /**\n * Which of its peers this is: an index into the theme's tone list, wrapping,\n * or a color given directly. Independent of `stance`, and allowed without one.\n */\n tone?: number | string;\n}\n\n/** The attributes a stanced surface renders, and the style carrying its resolved tone. */\nexport interface StanceAttrs {\n 'data-stance'?: Stance;\n 'data-tone'?: string;\n style?: CSSProperties;\n}\n\n/**\n * Resolves `stance` and `tone` for a surface's root element. The tone is\n * written inline as `--wzl-tone`; a tone-list index resolves through the nearest\n * `<ThemeProvider>`'s tones, as a custom-property reference where the list is\n * a theme ramp, so it follows the mode without a re-render.\n */\nexport function useStance({ stance, tone }: StanceProps): StanceAttrs {\n const ctx = useTones();\n if (stance === undefined && tone === undefined) return {};\n const color = tone === undefined ? undefined : typeof tone === 'number' ? colorCssAt(ctx.tones, tone, ctx) : tone;\n return {\n 'data-stance': stance,\n 'data-tone': tone === undefined ? undefined : String(tone),\n style: color === undefined ? undefined : ({ '--wzl-tone': color } as CSSProperties),\n };\n}\n"],"mappings":";;;AAiCA,SAAgB,EAAU,EAAE,WAAQ,WAAkC;CACpE,IAAM,IAAM,GAAU;AACtB,KAAI,MAAW,KAAA,KAAa,MAAS,KAAA,EAAW,QAAO,EAAE;CACzD,IAAM,IAAQ,MAAS,KAAA,IAAY,KAAA,IAAY,OAAO,KAAS,WAAW,EAAW,EAAI,OAAO,GAAM,EAAI,GAAG;AAC7G,QAAO;EACL,eAAe;EACf,aAAa,MAAS,KAAA,IAAY,KAAA,IAAY,OAAO,EAAK;EAC1D,OAAO,MAAU,KAAA,IAAY,KAAA,IAAa,EAAE,cAAc,GAAO;EAClE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"useReorderDragList-Dcezzgix.js","names":[],"sources":["../../src/useReorderDragList.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { ReactNode, PointerEvent as ReactPointerEvent, RefCallback } from 'react';\nimport { startThresholdDrag, type ThresholdDragHandle } from '@weasel-js/core';\nimport { isInControlWithin } from './interactiveTarget';\n\n/** One row in a reorderable list. */\nexport interface ReorderItem {\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}\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: ReorderItem[];\n selectedIds: string[];\n onReorder(ids: string[], targetIndex: number): void;\n /** A press that was released without ever engaging a drag — the click a\n * list row means by it. Fires for locked rows too, which can be selected\n * but not dragged. Modifiers are read at press, not at release. When this\n * is given, the DOM click that follows the press is dropped, so a row that\n * also handles `click` sees one press, not two. A press that starts on a\n * control inside the row (a toggle) is left to the control. */\n onPress?(id: string, mods: PressModifiers): void;\n /** Pointer-move distance (px) before pending drag engages. Default 4. */\n threshold?: number;\n /** Selector matching the container's children that are rows, for a list\n * that interleaves other elements (a table's detail rows). Default: every\n * child is a row. */\n rowSelector?: string;\n}\n\n/** Modifier keys held when a press began. */\nexport interface PressModifiers {\n shiftKey: boolean;\n ctrlKey: boolean;\n metaKey: boolean;\n altKey: boolean;\n}\n\n/**\n * Where a drag's ghost goes: the dragged rows, drawn again with their top-left\n * at a client-space point, so the row that was grabbed stays under the pointer\n * where it was picked up. `width` is the grabbed row's.\n */\nexport interface ReorderGhost {\n ids: readonly string[];\n left: number;\n top: number;\n width: number;\n}\n\n/**\n * Live drag state for rendering feedback: which ids are being dragged, the\n * insertion index the drop would use, and where their ghost goes. All `null`\n * when no drag is engaged.\n */\nexport interface ReorderDragState {\n draggedIds: string[] | null;\n targetIndex: number | null;\n ghost: ReorderGhost | null;\n}\n\nconst IDLE: ReorderDragState = { draggedIds: null, targetIndex: null, ghost: null };\n\n/**\n * A `ref` for the list container, an `onPointerDown` for each row, and the\n * live {@link ReorderDragState}. The container ref is required, not optional\n * decoration: it is what the drop index is measured against and what the\n * pointer session is opened on.\n */\nexport interface ReorderDragHandlers {\n rowProps(id: string, index: number): { onPointerDown(e: ReactPointerEvent): void };\n containerProps: {\n ref: RefCallback<HTMLElement>;\n };\n state: ReorderDragState;\n /**\n * Move the row at `index` one place up (`-1`) or down (`1`) — the keyboard\n * reorder. It moves what a drag of that row would: the whole selection if\n * the row is in it, else the row alone, never across a locked row. Calls\n * `onReorder` and returns `true`, or returns `false` when nothing can move.\n */\n nudge(id: string, index: number, delta: -1 | 1): boolean;\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 ReorderItem[], 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/** What a drag of the row at `index` carries: the selection within its segment if the row is selected, else the row. */\nfunction draggedIdsFor(\n items: readonly ReorderItem[],\n selectedIds: readonly string[],\n id: string,\n index: number,\n): string[] {\n const [lo, hi] = unlockedSegment(items, index);\n return (selectedIds.includes(id) ? [...selectedIds] : [id]).filter((x) => {\n const i = items.findIndex((it) => it.id === x);\n return i >= lo && i < hi;\n });\n}\n\n/** Would dropping `draggedIds` at `targetIndex` leave a contiguous block where it already is? */\nfunction isNoopDrop(items: readonly ReorderItem[], draggedIds: readonly string[], targetIndex: number): boolean {\n const indices = draggedIds\n .map((id) => items.findIndex((it) => it.id === id))\n .filter((i) => i >= 0)\n .sort((a, b) => a - b);\n const contiguous =\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 return contiguous\n && first !== undefined\n && last !== undefined\n && targetIndex >= first\n && targetIndex <= last + 1;\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 rows are the container's children, whatever they are: `ItemList` rows,\n * or the `PropertyGroup`s of a `PropertyList`. A row's `onPointerDown` can go\n * on the whole row or on a handle inside it.\n *\n * A press opens a `startThresholdDrag` on the *container*, which owns the\n * rest of the gesture: a drag that leaves the list still tracks, a release\n * anywhere still drops, and a release the window never delivered still ends\n * the drag. The container is the origin rather than the row because rows come\n * and go as the list re-renders, and a drag must outlive the row it grabbed.\n */\nexport function useReorderDragList(opts: UseReorderDragListOptions): ReorderDragHandlers {\n const optsRef = useRef(opts);\n optsRef.current = opts;\n const containerRef = useRef<HTMLElement | null>(null);\n const dragRef = useRef<ThresholdDragHandle | null>(null);\n const [state, setState] = useState<ReorderDragState>(IDLE);\n\n useEffect(() => () => { dragRef.current?.cancel(); }, []);\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 sel = optsRef.current.rowSelector;\n const rows = (sel ? Array.from(c.children).filter((el) => el.matches(sel)) : 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 reset = useCallback(() => {\n dragRef.current = null;\n setState(IDLE);\n }, []);\n\n const onPointerDownRow = useCallback((id: string, index: number, e: ReactPointerEvent) => {\n const container = containerRef.current;\n if (!container || dragRef.current) return;\n if (isInControlWithin(e.target, e.currentTarget as Element)) return;\n\n const mods: PressModifiers = {\n shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, altKey: e.altKey,\n };\n let draggedIds: string[] = [];\n let targetIndex = 0;\n // Where in the grabbed row the pointer went down, so the ghost keeps that point under it. The handler may sit on\n // a handle inside the row rather than the row itself, so the row is the container's child holding it.\n const pressed = e.currentTarget as Element;\n const rowEl = Array.from(container.children).find((child) => child.contains(pressed)) ?? pressed;\n const row = rowEl.getBoundingClientRect();\n const grab = { x: e.clientX - row.left, y: e.clientY - row.top };\n const ghostAt = (ev: { clientX: number; clientY: number }): ReorderGhost => ({\n ids: draggedIds,\n left: ev.clientX - grab.x,\n top: ev.clientY - grab.y,\n width: row.width,\n });\n\n dragRef.current = startThresholdDrag(e, {\n origin: container,\n // A locked row still opens a drag so its release reaches `onPress`, and\n // a threshold nothing can cross is what keeps it from ever engaging.\n threshold: optsRef.current.items[index]?.locked\n ? Number.POSITIVE_INFINITY\n : (optsRef.current.threshold ?? 4),\n onActivate: (ev) => {\n draggedIds = draggedIdsFor(optsRef.current.items, optsRef.current.selectedIds, id, index);\n targetIndex = computeTargetIndex(ev.clientY, index);\n setState({ draggedIds, targetIndex, ghost: ghostAt(ev) });\n },\n onMove: (ev) => {\n targetIndex = computeTargetIndex(ev.clientY, index);\n setState({ draggedIds, targetIndex, ghost: ghostAt(ev) });\n },\n onCommit: (ev) => {\n const drop = computeTargetIndex(ev.clientY, index);\n if (!isNoopDrop(optsRef.current.items, draggedIds, drop)) {\n optsRef.current.onReorder(draggedIds, drop);\n }\n reset();\n },\n onClick: () => {\n const { onPress } = optsRef.current;\n if (onPress) {\n onPress(id, mods);\n swallowNextClick(container);\n }\n reset();\n },\n // Every cancel reason — the browser's, a lost capture, an unmount —\n // says the gesture was interrupted rather than aimed, so the rows stay\n // where they were.\n onCancel: reset,\n });\n }, [computeTargetIndex, reset]);\n\n const nudge = useCallback((id: string, index: number, delta: -1 | 1): boolean => {\n const { items, selectedIds, onReorder } = optsRef.current;\n if (items[index]?.locked) return false;\n const ids = draggedIdsFor(items, selectedIds, id, index);\n const at = ids.map((x) => items.findIndex((it) => it.id === x)).sort((a, b) => a - b);\n const first = at[0];\n const last = at[at.length - 1];\n if (first === undefined || last === undefined) return false;\n const [lo, hi] = unlockedSegment(items, index);\n const target = delta < 0 ? first - 1 : last + 2;\n if (target < lo || target > hi || isNoopDrop(items, ids, target)) return false;\n onReorder(ids, target);\n return true;\n }, []);\n\n return {\n nudge,\n rowProps: (id, index) => ({\n onPointerDown: (e) => onPointerDownRow(id, index, e),\n }),\n containerProps: {\n ref: refCb,\n },\n state,\n };\n}\n\n/**\n * The session captured the pointer on the container, so browsers disagree on\n * where the release's click lands; it may still reach the row. `onPress` has\n * already reported this press, so that click is dropped rather than read as a\n * second one. It is dispatched in the same task as the release.\n */\nfunction swallowNextClick(container: HTMLElement): void {\n const swallow = (e: Event) => { e.stopPropagation(); };\n container.addEventListener('click', swallow, true);\n setTimeout(() => { container.removeEventListener('click', swallow, true); }, 0);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"useRovingTabIndex-B4uJqiKP.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 `ButtonBar`, `OptionsBar`, and `ToggleBar`.\n *\n * **When a bar should not use this.** What decides it is the items, not who\n * owns them. A container of 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: it draws its\n * own controls from a tool's schema now rather than taking arbitrary\n * children, and a schema-drawn number field eats arrows exactly as a\n * hand-placed one did, so it keeps plain DOM tab order. A bar whose items are\n * all simple buttons is the case this 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;;AAwBT,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"}