@weasel-js/ui 1.7.3 → 1.8.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 (306) hide show
  1. package/dist/chunks/{ActionBar-xA73vzzF.js → ActionBar-CfXS7-9f.js} +2 -2
  2. package/dist/chunks/{ActionBar-xA73vzzF.js.map → ActionBar-CfXS7-9f.js.map} +1 -1
  3. package/dist/chunks/{Badge-jYQjrTKc.js → Badge-4ShpqA0h.js} +2 -2
  4. package/dist/chunks/{Badge-jYQjrTKc.js.map → Badge-4ShpqA0h.js.map} +1 -1
  5. package/dist/chunks/{Badge-CTc9Lkwn.js → Badge-qkV9EqKs.js} +6 -2
  6. package/dist/chunks/Badge-qkV9EqKs.js.map +1 -0
  7. package/dist/chunks/{Button-XB-T75YL.js → Button-CQA-K1g9.js} +17 -17
  8. package/dist/chunks/Button-CQA-K1g9.js.map +1 -0
  9. package/dist/chunks/Button-KF-qSGtA.js +11 -0
  10. package/dist/chunks/Button-KF-qSGtA.js.map +1 -0
  11. package/dist/chunks/{ButtonBar-CIMKPPRS.js → ButtonBar-B-cYuoem.js} +10 -4
  12. package/dist/chunks/ButtonBar-B-cYuoem.js.map +1 -0
  13. package/dist/chunks/{Callout-BUn0dP_S.js → Callout-VyYDIP7w.js} +26 -26
  14. package/dist/chunks/Callout-VyYDIP7w.js.map +1 -0
  15. package/dist/chunks/{Checkbox-DFn-x0JO.js → Checkbox-d4IfhiXh.js} +2 -2
  16. package/dist/chunks/{Checkbox-DFn-x0JO.js.map → Checkbox-d4IfhiXh.js.map} +1 -1
  17. package/dist/chunks/{CloseButton-BmNmRVtb.js → CloseButton-CKarkTT9.js} +3 -3
  18. package/dist/chunks/{CloseButton-BmNmRVtb.js.map → CloseButton-CKarkTT9.js.map} +1 -1
  19. package/dist/chunks/{Code-AsKpgnv6.js → Code-ChwKP1V0.js} +8 -2
  20. package/dist/chunks/Code-ChwKP1V0.js.map +1 -0
  21. package/dist/chunks/{ColorModeControl-DaVJ-SyX.js → ColorModeControl-CH9PmDlT.js} +6 -6
  22. package/dist/chunks/{ColorModeControl-DaVJ-SyX.js.map → ColorModeControl-CH9PmDlT.js.map} +1 -1
  23. package/dist/chunks/{ComboBox-DKln_mOd.js → ComboBox-BMj_IKBj.js} +4 -4
  24. package/dist/chunks/ComboBox-BMj_IKBj.js.map +1 -0
  25. package/dist/chunks/{DataGrid-CmHJe57v.js → DataGrid-CjiVKoaA.js} +3 -3
  26. package/dist/chunks/{DataGrid-CmHJe57v.js.map → DataGrid-CjiVKoaA.js.map} +1 -1
  27. package/dist/chunks/{DetentSlider-DNTAk8xP.js → DetentSlider-D40V8Oma.js} +2 -2
  28. package/dist/chunks/{DetentSlider-DNTAk8xP.js.map → DetentSlider-D40V8Oma.js.map} +1 -1
  29. package/dist/chunks/{Dialog-DKfsk5VN.js → Dialog-Du4POZ52.js} +12 -12
  30. package/dist/chunks/Dialog-Du4POZ52.js.map +1 -0
  31. package/dist/chunks/{Disclosure-Ch2KxYuB.js → Disclosure-CpWt87nO.js} +7 -7
  32. package/dist/chunks/{Disclosure-Ch2KxYuB.js.map → Disclosure-CpWt87nO.js.map} +1 -1
  33. package/dist/chunks/{DragGhost-BeYDJyLZ.js → DragGhost-_IpuN_xM.js} +2 -2
  34. package/dist/chunks/{DragGhost-BeYDJyLZ.js.map → DragGhost-_IpuN_xM.js.map} +1 -1
  35. package/dist/chunks/{FallthroughDiagram-CS1IhQaU.js → FallthroughDiagram-Cn6QLWKA.js} +9 -9
  36. package/dist/chunks/{FallthroughDiagram-CS1IhQaU.js.map → FallthroughDiagram-Cn6QLWKA.js.map} +1 -1
  37. package/dist/chunks/{FillStrokeSwatch-C4h3rUFM.js → FillStrokeSwatch-BkUhlpQL.js} +2 -2
  38. package/dist/chunks/{FillStrokeSwatch-C4h3rUFM.js.map → FillStrokeSwatch-BkUhlpQL.js.map} +1 -1
  39. package/dist/chunks/FitLabel-BzZGkWfL.js +76 -0
  40. package/dist/chunks/FitLabel-BzZGkWfL.js.map +1 -0
  41. package/dist/chunks/{FontFamilySelect-DEvMXyZd.js → FontFamilySelect-CXN7O2-p.js} +2 -2
  42. package/dist/chunks/{FontFamilySelect-DEvMXyZd.js.map → FontFamilySelect-CXN7O2-p.js.map} +1 -1
  43. package/dist/chunks/{FontWeightSelect-BLQ_LMJF.js → FontWeightSelect-BBuJGe_2.js} +2 -2
  44. package/dist/chunks/{FontWeightSelect-BLQ_LMJF.js.map → FontWeightSelect-BBuJGe_2.js.map} +1 -1
  45. package/dist/chunks/{GestureRoute-BXESrHI0.js → GestureRoute-BqHUrGeQ.js} +13 -13
  46. package/dist/chunks/{GestureRoute-BXESrHI0.js.map → GestureRoute-BqHUrGeQ.js.map} +1 -1
  47. package/dist/chunks/{GradientEditor-DD2OjQtn.js → GradientEditor-DX4sb1Hf.js} +4 -4
  48. package/dist/chunks/{GradientEditor-DD2OjQtn.js.map → GradientEditor-DX4sb1Hf.js.map} +1 -1
  49. package/dist/chunks/{Icon--B1ME-6c.js → Icon-BfqYtAX5.js} +33 -1
  50. package/dist/chunks/Icon-BfqYtAX5.js.map +1 -0
  51. package/dist/chunks/{ItemList-CRu9y7hL.js → ItemList-nbakLf3N.js} +32 -32
  52. package/dist/chunks/ItemList-nbakLf3N.js.map +1 -0
  53. package/dist/chunks/{Jog-BrkzdGV2.js → Jog-BU0xuM3G.js} +7 -7
  54. package/dist/chunks/{Jog-BrkzdGV2.js.map → Jog-BU0xuM3G.js.map} +1 -1
  55. package/dist/chunks/{Keycaps-C-FJyG8k.js → Keycaps-CM-gOj0e.js} +8 -2
  56. package/dist/chunks/Keycaps-CM-gOj0e.js.map +1 -0
  57. package/dist/chunks/LayerList-vfAoImxX.js +432 -0
  58. package/dist/chunks/LayerList-vfAoImxX.js.map +1 -0
  59. package/dist/chunks/{ListEditor-OQDzG4A5.js → ListEditor-BAKs47bN.js} +3 -3
  60. package/dist/chunks/{ListEditor-OQDzG4A5.js.map → ListEditor-BAKs47bN.js.map} +1 -1
  61. package/dist/chunks/{MenuButton-TAFg88Lp.js → MenuButton-CJGdhwGr.js} +5 -5
  62. package/dist/chunks/MenuButton-CJGdhwGr.js.map +1 -0
  63. package/dist/chunks/{MeshEditor-DWpvg8H6.js → MeshEditor-rhf7cXfG.js} +2 -2
  64. package/dist/chunks/{MeshEditor-DWpvg8H6.js.map → MeshEditor-rhf7cXfG.js.map} +1 -1
  65. package/dist/chunks/{NumberField-DS0WSiin.js → NumberField-BXFrOi5M.js} +8 -5
  66. package/dist/chunks/{NumberField-DS0WSiin.js.map → NumberField-BXFrOi5M.js.map} +1 -1
  67. package/dist/chunks/{OptionsBar-DeTAjVb7.js → OptionsBar-DyTXbev-.js} +9 -3
  68. package/dist/chunks/OptionsBar-DyTXbev-.js.map +1 -0
  69. package/dist/chunks/{PaintField-BdmQM53v.js → PaintField--GbF8sL7.js} +7 -7
  70. package/dist/chunks/PaintField--GbF8sL7.js.map +1 -0
  71. package/dist/chunks/{PaintInput-DaQMeBsI.js → PaintInput-DSS5IjXn.js} +5 -5
  72. package/dist/chunks/{PaintInput-DaQMeBsI.js.map → PaintInput-DSS5IjXn.js.map} +1 -1
  73. package/dist/chunks/{PatternPicker-B3HcMZWg.js → PatternPicker-82DCUvUk.js} +9 -9
  74. package/dist/chunks/PatternPicker-82DCUvUk.js.map +1 -0
  75. package/dist/chunks/{Powerline-6wIFmDik.js → Powerline-CogJv9VU.js} +2 -2
  76. package/dist/chunks/{Powerline-6wIFmDik.js.map → Powerline-CogJv9VU.js.map} +1 -1
  77. package/dist/chunks/{Prefs-BnVEyfWO.js → Prefs-BSSKOvPa.js} +41 -41
  78. package/dist/chunks/Prefs-BSSKOvPa.js.map +1 -0
  79. package/dist/chunks/{Properties-BoG2MMHR.js → Properties-DteSVEWs.js} +5 -5
  80. package/dist/chunks/{Properties-BoG2MMHR.js.map → Properties-DteSVEWs.js.map} +1 -1
  81. package/dist/chunks/PropertyField-CLbUOynA.js +751 -0
  82. package/dist/chunks/PropertyField-CLbUOynA.js.map +1 -0
  83. package/dist/chunks/{Select-ouV8O6cp.js → Select-BhHwjNsb.js} +13 -13
  84. package/dist/chunks/Select-BhHwjNsb.js.map +1 -0
  85. package/dist/chunks/{SelectionPanel-COZ6z9_P.js → SelectionPanel-B6HinSdB.js} +2 -2
  86. package/dist/chunks/{SelectionPanel-COZ6z9_P.js.map → SelectionPanel-B6HinSdB.js.map} +1 -1
  87. package/dist/chunks/{SidebarPanel-AXQ0jRDx.js → SidebarPanel-P3a8tIIj.js} +3 -3
  88. package/dist/chunks/{SidebarPanel-AXQ0jRDx.js.map → SidebarPanel-P3a8tIIj.js.map} +1 -1
  89. package/dist/chunks/Slider-CHBQ8uUC.js +439 -0
  90. package/dist/chunks/Slider-CHBQ8uUC.js.map +1 -0
  91. package/dist/chunks/{StatusBar-BEOfOX0D.js → StatusBar-DEh7J2Gj.js} +14 -9
  92. package/dist/chunks/StatusBar-DEh7J2Gj.js.map +1 -0
  93. package/dist/chunks/{SwatchGrid-9ZPiDmxd.js → SwatchGrid-DxK9e_IV.js} +3 -3
  94. package/dist/chunks/SwatchGrid-DxK9e_IV.js.map +1 -0
  95. package/dist/chunks/{SwatchStrip-Bi9iPLoh.js → SwatchStrip-D7YNn_p0.js} +3 -3
  96. package/dist/chunks/{SwatchStrip-Bi9iPLoh.js.map → SwatchStrip-D7YNn_p0.js.map} +1 -1
  97. package/dist/chunks/{ThemeSwitcher-DiBmMh_B.js → ThemeSwitcher-BJWP1l87.js} +6 -6
  98. package/dist/chunks/{ThemeSwitcher-DiBmMh_B.js.map → ThemeSwitcher-BJWP1l87.js.map} +1 -1
  99. package/dist/chunks/{Timeline-sMCH2fah.js → Timeline-CisRg82u.js} +4 -4
  100. package/dist/chunks/{Timeline-sMCH2fah.js.map → Timeline-CisRg82u.js.map} +1 -1
  101. package/dist/chunks/{Toast-C3ozq11V.js → Toast-DhkU9Z0b.js} +3 -3
  102. package/dist/chunks/{Toast-C3ozq11V.js.map → Toast-DhkU9Z0b.js.map} +1 -1
  103. package/dist/chunks/ToggleBar-CRc2k89_.js +10 -0
  104. package/dist/chunks/ToggleBar-CRc2k89_.js.map +1 -0
  105. package/dist/chunks/ToggleBar-CfYbMK3x.js +84 -0
  106. package/dist/chunks/ToggleBar-CfYbMK3x.js.map +1 -0
  107. package/dist/chunks/{TokenPanel-WtKGY2Db.js → TokenPanel-cL37E39j.js} +26 -26
  108. package/dist/chunks/{TokenPanel-WtKGY2Db.js.map → TokenPanel-cL37E39j.js.map} +1 -1
  109. package/dist/chunks/{ToolButton-BURp4YIO.js → ToolButton-Bo7WH1wt.js} +2 -2
  110. package/dist/chunks/{ToolButton-BURp4YIO.js.map → ToolButton-Bo7WH1wt.js.map} +1 -1
  111. package/dist/chunks/ToolOptionsBar-DmhzrOmd.js +94 -0
  112. package/dist/chunks/ToolOptionsBar-DmhzrOmd.js.map +1 -0
  113. package/dist/chunks/{ToolPalette-DKDFWOX-.js → ToolPalette-BTD84k9C.js} +2 -2
  114. package/dist/chunks/{ToolPalette-DKDFWOX-.js.map → ToolPalette-BTD84k9C.js.map} +1 -1
  115. package/dist/chunks/{Tooltip-C6eFCYxw.js → Tooltip-DljsPEQG.js} +4 -4
  116. package/dist/chunks/Tooltip-DljsPEQG.js.map +1 -0
  117. package/dist/chunks/Tree-B_PW6K-W.js +215 -0
  118. package/dist/chunks/Tree-B_PW6K-W.js.map +1 -0
  119. package/dist/chunks/checkbox.module-Dcx8ILgR.js +5 -0
  120. package/dist/chunks/checkbox.module-Dcx8ILgR.js.map +1 -0
  121. package/dist/chunks/{icons-Dr2-r30x.js → icons-B_fPKEis.js} +52 -43
  122. package/dist/chunks/icons-B_fPKEis.js.map +1 -0
  123. package/dist/chunks/{model-B6zuQg6b.js → model-Ca0f95r0.js} +134 -133
  124. package/dist/chunks/model-Ca0f95r0.js.map +1 -0
  125. package/dist/chunks/{portalHost-CE70wLzo.js → portalHost-RUQPxIoW.js} +3 -2
  126. package/dist/chunks/{portalHost-CE70wLzo.js.map → portalHost-RUQPxIoW.js.map} +1 -1
  127. package/dist/chunks/{prefField-BE_Ytr2H.js → prefField-DPPbAmRR.js} +81 -75
  128. package/dist/chunks/prefField-DPPbAmRR.js.map +1 -0
  129. package/dist/chunks/{segmentTooltip-CGxCOWNz.js → segmentTooltip-8VBPNgEc.js} +2 -2
  130. package/dist/chunks/{segmentTooltip-CGxCOWNz.js.map → segmentTooltip-8VBPNgEc.js.map} +1 -1
  131. package/dist/chunks/segmentedControl.module-62qjNWJk.js +11 -0
  132. package/dist/chunks/{segmentedControl.module-BzGXUL5G.js.map → segmentedControl.module-62qjNWJk.js.map} +1 -1
  133. package/dist/chunks/{useReorderDragList-CStYKjHl.js → useReorderDragList-DnqqvRGK.js} +38 -30
  134. package/dist/chunks/useReorderDragList-DnqqvRGK.js.map +1 -0
  135. package/dist/components/ActionBar/index.js +1 -1
  136. package/dist/components/Badge/index.d.ts +1 -0
  137. package/dist/components/Badge/index.d.ts.map +1 -1
  138. package/dist/components/Badge/index.js +3 -3
  139. package/dist/components/Badge/variantIcons.d.ts +5 -0
  140. package/dist/components/Badge/variantIcons.d.ts.map +1 -0
  141. package/dist/components/Button/index.d.ts +1 -0
  142. package/dist/components/Button/index.d.ts.map +1 -1
  143. package/dist/components/Button/index.js +3 -2
  144. package/dist/components/Button/variantIcons.d.ts +5 -0
  145. package/dist/components/Button/variantIcons.d.ts.map +1 -0
  146. package/dist/components/ButtonBar/index.d.ts +1 -0
  147. package/dist/components/ButtonBar/index.d.ts.map +1 -1
  148. package/dist/components/ButtonBar/index.js +2 -2
  149. package/dist/components/ButtonBar/variantIcons.d.ts +5 -0
  150. package/dist/components/ButtonBar/variantIcons.d.ts.map +1 -0
  151. package/dist/components/Callout/Callout.d.ts.map +1 -1
  152. package/dist/components/Callout/index.js +1 -1
  153. package/dist/components/Checkbox/index.js +1 -1
  154. package/dist/components/CloseButton/index.js +1 -1
  155. package/dist/components/Code/index.d.ts +1 -0
  156. package/dist/components/Code/index.d.ts.map +1 -1
  157. package/dist/components/Code/index.js +2 -2
  158. package/dist/components/Code/variantIcons.d.ts +5 -0
  159. package/dist/components/Code/variantIcons.d.ts.map +1 -0
  160. package/dist/components/ColorModeControl/index.js +1 -1
  161. package/dist/components/ComboBox/ComboBox.d.ts.map +1 -1
  162. package/dist/components/ComboBox/index.js +1 -1
  163. package/dist/components/DataGrid/index.js +1 -1
  164. package/dist/components/DetentSlider/index.js +1 -1
  165. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  166. package/dist/components/Dialog/index.js +1 -1
  167. package/dist/components/Disclosure/index.js +1 -1
  168. package/dist/components/DragGhost/index.js +1 -1
  169. package/dist/components/FallthroughDiagram/index.js +1 -1
  170. package/dist/components/FillStrokeSwatch/index.js +1 -1
  171. package/dist/components/FitLabel/FitLabel.d.ts +41 -0
  172. package/dist/components/FitLabel/FitLabel.d.ts.map +1 -0
  173. package/dist/components/FitLabel/index.d.ts +3 -0
  174. package/dist/components/FitLabel/index.d.ts.map +1 -0
  175. package/dist/components/FitLabel/index.js +2 -0
  176. package/dist/components/FontFamilySelect/index.js +1 -1
  177. package/dist/components/FontWeightSelect/index.js +1 -1
  178. package/dist/components/GestureRoute/index.js +1 -1
  179. package/dist/components/GradientEditor/index.js +1 -1
  180. package/dist/components/InlineRange/InlineRange.d.ts +1 -1
  181. package/dist/components/ItemList/index.js +1 -1
  182. package/dist/components/Jog/index.js +1 -1
  183. package/dist/components/Keycaps/index.d.ts +1 -0
  184. package/dist/components/Keycaps/index.d.ts.map +1 -1
  185. package/dist/components/Keycaps/index.js +2 -2
  186. package/dist/components/Keycaps/variantIcons.d.ts +5 -0
  187. package/dist/components/Keycaps/variantIcons.d.ts.map +1 -0
  188. package/dist/components/LayerList/LayerList.d.ts.map +1 -1
  189. package/dist/components/LayerList/index.js +1 -1
  190. package/dist/components/ListEditor/index.js +1 -1
  191. package/dist/components/MenuButton/MenuButton.d.ts.map +1 -1
  192. package/dist/components/MenuButton/index.js +1 -1
  193. package/dist/components/MeshEditor/index.js +1 -1
  194. package/dist/components/NumberField/UnitField.d.ts.map +1 -1
  195. package/dist/components/NumberField/index.js +1 -1
  196. package/dist/components/OptionsBar/index.d.ts +1 -0
  197. package/dist/components/OptionsBar/index.d.ts.map +1 -1
  198. package/dist/components/OptionsBar/index.js +2 -2
  199. package/dist/components/OptionsBar/variantIcons.d.ts +5 -0
  200. package/dist/components/OptionsBar/variantIcons.d.ts.map +1 -0
  201. package/dist/components/PaintField/PaintField.d.ts.map +1 -1
  202. package/dist/components/PaintField/index.js +1 -1
  203. package/dist/components/PaintInput/index.js +1 -1
  204. package/dist/components/PatternPicker/index.js +1 -1
  205. package/dist/components/Powerline/index.js +2 -2
  206. package/dist/components/Prefs/index.js +2 -2
  207. package/dist/components/Prefs/prefField.d.ts.map +1 -1
  208. package/dist/components/Properties/NumberControls.d.ts +16 -0
  209. package/dist/components/Properties/NumberControls.d.ts.map +1 -0
  210. package/dist/components/Properties/PropertyField.d.ts +18 -8
  211. package/dist/components/Properties/PropertyField.d.ts.map +1 -1
  212. package/dist/components/Properties/index.js +2 -2
  213. package/dist/components/Select/Select.d.ts.map +1 -1
  214. package/dist/components/Select/index.js +1 -1
  215. package/dist/components/SelectionPanel/index.js +2 -2
  216. package/dist/components/SelectionPanel/renderLeaf.d.ts.map +1 -1
  217. package/dist/components/SidebarPanel/index.js +1 -1
  218. package/dist/components/Slider/Slider.d.ts +6 -0
  219. package/dist/components/Slider/Slider.d.ts.map +1 -1
  220. package/dist/components/Slider/index.js +1 -1
  221. package/dist/components/StatusBar/StatusBar.d.ts +2 -0
  222. package/dist/components/StatusBar/StatusBar.d.ts.map +1 -1
  223. package/dist/components/StatusBar/index.js +1 -1
  224. package/dist/components/SwatchGrid/index.js +1 -1
  225. package/dist/components/SwatchStrip/index.js +1 -1
  226. package/dist/components/ThemeSwitcher/index.js +1 -1
  227. package/dist/components/Timeline/index.js +1 -1
  228. package/dist/components/Toast/index.js +1 -1
  229. package/dist/components/ToggleBar/ToggleBar.d.ts.map +1 -1
  230. package/dist/components/ToggleBar/index.d.ts +1 -0
  231. package/dist/components/ToggleBar/index.d.ts.map +1 -1
  232. package/dist/components/ToggleBar/index.js +3 -2
  233. package/dist/components/ToggleBar/variantIcons.d.ts +5 -0
  234. package/dist/components/ToggleBar/variantIcons.d.ts.map +1 -0
  235. package/dist/components/TokenPanel/index.js +1 -1
  236. package/dist/components/ToolButton/index.js +1 -1
  237. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts +1 -1
  238. package/dist/components/ToolOptionsBar/ToolOptionsBar.d.ts.map +1 -1
  239. package/dist/components/ToolOptionsBar/index.js +1 -1
  240. package/dist/components/ToolPalette/index.js +1 -1
  241. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  242. package/dist/components/Tooltip/index.js +1 -1
  243. package/dist/components/Tree/Tree.d.ts +1 -1
  244. package/dist/components/Tree/Tree.d.ts.map +1 -1
  245. package/dist/components/Tree/index.js +1 -1
  246. package/dist/components/stanceCss.d.ts +6 -0
  247. package/dist/components/stanceCss.d.ts.map +1 -1
  248. package/dist/components/stanceSurfaces.d.ts.map +1 -1
  249. package/dist/endless.d.ts +7 -0
  250. package/dist/endless.d.ts.map +1 -0
  251. package/dist/icons/index.d.ts +6 -0
  252. package/dist/icons/index.d.ts.map +1 -1
  253. package/dist/icons/paths.d.ts +14 -0
  254. package/dist/icons/paths.d.ts.map +1 -1
  255. package/dist/index.d.ts +1 -0
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +101 -97
  258. package/dist/index.js.map +1 -1
  259. package/dist/overlays/portalHost.d.ts +10 -4
  260. package/dist/overlays/portalHost.d.ts.map +1 -1
  261. package/dist/style.css +1 -1
  262. package/dist/useReorderDragList.d.ts +3 -0
  263. package/dist/useReorderDragList.d.ts.map +1 -1
  264. package/package.json +10 -9
  265. package/dist/chunks/Badge-CTc9Lkwn.js.map +0 -1
  266. package/dist/chunks/Button-XB-T75YL.js.map +0 -1
  267. package/dist/chunks/ButtonBar-CIMKPPRS.js.map +0 -1
  268. package/dist/chunks/Callout-BUn0dP_S.js.map +0 -1
  269. package/dist/chunks/Code-AsKpgnv6.js.map +0 -1
  270. package/dist/chunks/ComboBox-DKln_mOd.js.map +0 -1
  271. package/dist/chunks/Dialog-DKfsk5VN.js.map +0 -1
  272. package/dist/chunks/Icon--B1ME-6c.js.map +0 -1
  273. package/dist/chunks/ItemList-CRu9y7hL.js.map +0 -1
  274. package/dist/chunks/Keycaps-C-FJyG8k.js.map +0 -1
  275. package/dist/chunks/LayerList-BqeWFuGc.js +0 -421
  276. package/dist/chunks/LayerList-BqeWFuGc.js.map +0 -1
  277. package/dist/chunks/MenuButton-TAFg88Lp.js.map +0 -1
  278. package/dist/chunks/OptionsBar-DeTAjVb7.js.map +0 -1
  279. package/dist/chunks/PaintField-BdmQM53v.js.map +0 -1
  280. package/dist/chunks/PatternPicker-B3HcMZWg.js.map +0 -1
  281. package/dist/chunks/Prefs-BnVEyfWO.js.map +0 -1
  282. package/dist/chunks/PropertyField-PMrqBA0n.js +0 -743
  283. package/dist/chunks/PropertyField-PMrqBA0n.js.map +0 -1
  284. package/dist/chunks/Select-ouV8O6cp.js.map +0 -1
  285. package/dist/chunks/Slider-DSrlMEq8.js +0 -389
  286. package/dist/chunks/Slider-DSrlMEq8.js.map +0 -1
  287. package/dist/chunks/StatusBar-BEOfOX0D.js.map +0 -1
  288. package/dist/chunks/SwatchGrid-9ZPiDmxd.js.map +0 -1
  289. package/dist/chunks/ToggleBar-Z2jZiguF.js +0 -80
  290. package/dist/chunks/ToggleBar-Z2jZiguF.js.map +0 -1
  291. package/dist/chunks/ToolOptionsBar-BJKwnemU.js +0 -88
  292. package/dist/chunks/ToolOptionsBar-BJKwnemU.js.map +0 -1
  293. package/dist/chunks/Tooltip-C6eFCYxw.js.map +0 -1
  294. package/dist/chunks/Tree-Cc8lIzgM.js +0 -203
  295. package/dist/chunks/Tree-Cc8lIzgM.js.map +0 -1
  296. package/dist/chunks/checkbox.module-DLQV9tMX.js +0 -5
  297. package/dist/chunks/checkbox.module-DLQV9tMX.js.map +0 -1
  298. package/dist/chunks/icons-Dr2-r30x.js.map +0 -1
  299. package/dist/chunks/interactiveTarget-BNZmTow2.js +0 -24
  300. package/dist/chunks/interactiveTarget-BNZmTow2.js.map +0 -1
  301. package/dist/chunks/model-B6zuQg6b.js.map +0 -1
  302. package/dist/chunks/prefField-BE_Ytr2H.js.map +0 -1
  303. package/dist/chunks/segmentedControl.module-BzGXUL5G.js +0 -11
  304. package/dist/chunks/useReorderDragList-CStYKjHl.js.map +0 -1
  305. package/dist/interactiveTarget.d.ts +0 -9
  306. package/dist/interactiveTarget.d.ts.map +0 -1
@@ -0,0 +1,76 @@
1
+ import { Fragment as e, jsx as t } from "react/jsx-runtime";
2
+ import { createContext as n, useCallback as r, useContext as i, useLayoutEffect as a, useMemo as o, useRef as s, useState as c } from "react";
3
+ import { flushSync as l } from "react-dom";
4
+ //#region src/components/FitLabel/FitLabel.tsx
5
+ function u(e, t) {
6
+ let n = e == null || e === "" ? [] : [e];
7
+ return t === void 0 ? n : [...n, ...t];
8
+ }
9
+ var d = n(null);
10
+ function f({ value: e, children: n }) {
11
+ return /* @__PURE__ */ t(d.Provider, {
12
+ value: e,
13
+ children: n
14
+ });
15
+ }
16
+ var p = (e) => e !== null && e.scrollWidth > e.clientWidth;
17
+ function m(e) {
18
+ let t = i(d), [n, u] = c(0), [f, m] = c([]), h = s(/* @__PURE__ */ new Map()), g = s(null), _ = f.reduce((e, t) => Math.max(e, t), 0), v = t?.register, y = r((e) => {
19
+ let t = Symbol("fit-label");
20
+ h.current.set(t, e), m([...h.current.values()]);
21
+ let n = v?.(e);
22
+ return () => {
23
+ h.current.delete(t), m([...h.current.values()]), n?.();
24
+ };
25
+ }, [v]), b = s(n);
26
+ a(() => {
27
+ b.current = n;
28
+ }, [n]);
29
+ let x = r(() => {
30
+ let t = e.current;
31
+ if (!t || b.current >= _ - 1) return !1;
32
+ let n = t.parentElement;
33
+ return !p(t) && !p(n) ? !1 : (g.current = {
34
+ self: t.clientWidth,
35
+ parent: n?.clientWidth ?? 0
36
+ }, !0);
37
+ }, [e, _]), S = s(f);
38
+ a(() => {
39
+ if (S.current !== f && (S.current = f, g.current = null, n !== 0)) {
40
+ u(0);
41
+ return;
42
+ }
43
+ x() && u(n + 1);
44
+ }, [
45
+ f,
46
+ n,
47
+ x
48
+ ]), a(() => {
49
+ let t = e.current;
50
+ if (!t || _ < 2 || typeof ResizeObserver > "u") return;
51
+ let n = t.parentElement, r = new ResizeObserver(() => {
52
+ let e = g.current;
53
+ e !== null && (t.clientWidth > e.self + .5 || n !== null && n.clientWidth > e.parent + .5) ? (g.current = null, l(() => u(0))) : x() && l(() => u((e) => e + 1));
54
+ });
55
+ return r.observe(t), n && r.observe(n), () => r.disconnect();
56
+ }, [
57
+ e,
58
+ _,
59
+ x
60
+ ]);
61
+ let C = Math.max(n, t?.step ?? 0);
62
+ return o(() => ({
63
+ step: C,
64
+ register: y
65
+ }), [C, y]);
66
+ }
67
+ function h({ forms: n }) {
68
+ let r = i(d), o = r?.register, s = n.length;
69
+ a(() => o?.(s), [o, s]);
70
+ let c = r?.step ?? 0;
71
+ return /* @__PURE__ */ t(e, { children: n[Math.min(c, s - 1)] });
72
+ }
73
+ //#endregion
74
+ export { m as i, f as n, u as r, h as t };
75
+
76
+ //# sourceMappingURL=FitLabel-BzZGkWfL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FitLabel-BzZGkWfL.js","names":["_Fragment","labelForms","head","name","short","FitContext","createContext","FitScope","overflows","el","useFitScope","outer","useContext","own","setOwn","useState","labels","setLabels","counted","useRef","steppedAt","depth","max","d","outerRegister","register","useCallback","id","labelDepth","releaseOuter","ownRef","shouldStep","ref","parent","fittedFor","useLayoutEffect","observer","at","flushSync","s","step","useMemo","FitLabel","scope","forms","Fragment"],"sources":["../../src/components/FitLabel/FitLabel.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { flushSync } from 'react-dom';\n\n/**\n * A label's forms, longest first: the canonical name, then each shorter form a\n * surface may fall back to. `name` stays the control's accessible name whichever\n * form is shown.\n */\nexport function labelForms(name: ReactNode, short?: readonly ReactNode[]): readonly ReactNode[] {\n const head = name === undefined || name === null || name === '' ? [] : [name];\n return short === undefined ? head : [...head, ...short];\n}\n\n/** What a {@link FitScope} tells the labels inside it. */\nexport interface FitScopeValue {\n /** How many forms down every label in the scope steps. */\n readonly step: number;\n /** Counts a label holding `depth` forms toward the scope; returns its release. */\n readonly register: (depth: number) => () => void;\n}\n\nconst FitContext = createContext<FitScopeValue | null>(null);\n\n/** Hands a {@link useFitScope} result to the {@link FitLabel}s beneath it. */\nexport function FitScope({ value, children }: { value: FitScopeValue; children?: ReactNode }) {\n return <FitContext.Provider value={value}>{children}</FitContext.Provider>;\n}\n\nconst overflows = (el: Element | null): boolean => el !== null && el.scrollWidth > el.clientWidth;\n\n/**\n * Fits the {@link FitLabel}s under `ref` to the room they are given.\n *\n * Every label steps down together, one form at a time, until neither `ref`'s\n * element nor its parent overflows or no label has a shorter form left: the\n * element overflowing itself is a control squeezed below its content, and its\n * parent overflowing is one that will not shrink at all. Each label takes its\n * form at the step, or its last where it has fewer. The room growing past the\n * size it had when a step was taken starts again from the full forms.\n *\n * A scope nested in another steps at least as far as the outer one, so a\n * control inside a strip shortens along with the strip.\n */\nexport function useFitScope(ref: RefObject<HTMLElement | null>): FitScopeValue {\n const outer = useContext(FitContext);\n const [own, setOwn] = useState(0);\n const [labels, setLabels] = useState<readonly number[]>([]);\n const counted = useRef(new Map<symbol, number>());\n // Room sizes when the last step was taken: growing past them retries the\n // full forms, while the shrink a step itself causes does not.\n const steppedAt = useRef<{ self: number; parent: number } | null>(null);\n\n const depth = labels.reduce((max, d) => Math.max(max, d), 0);\n const outerRegister = outer?.register;\n const register = useCallback(\n (labelDepth: number) => {\n const id = Symbol('fit-label');\n counted.current.set(id, labelDepth);\n setLabels([...counted.current.values()]);\n const releaseOuter = outerRegister?.(labelDepth);\n return () => {\n counted.current.delete(id);\n setLabels([...counted.current.values()]);\n releaseOuter?.();\n };\n },\n [outerRegister],\n );\n\n const ownRef = useRef(own);\n useLayoutEffect(() => {\n ownRef.current = own;\n }, [own]);\n /** Whether the room overflows and a label has a shorter form left; records the room if so. */\n const shouldStep = useCallback((): boolean => {\n const el = ref.current;\n if (!el || ownRef.current >= depth - 1) return false;\n const parent = el.parentElement;\n if (!overflows(el) && !overflows(parent)) return false;\n steppedAt.current = { self: el.clientWidth, parent: parent?.clientWidth ?? 0 };\n return true;\n }, [ref, depth]);\n\n // A label set that changed may fit at a longer form than the old one did.\n const fittedFor = useRef(labels);\n useLayoutEffect(() => {\n if (fittedFor.current !== labels) {\n fittedFor.current = labels;\n steppedAt.current = null;\n if (own !== 0) {\n setOwn(0);\n return;\n }\n }\n if (shouldStep()) setOwn(own + 1);\n }, [labels, own, shouldStep]);\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || depth < 2 || typeof ResizeObserver === 'undefined') return;\n const parent = el.parentElement;\n const observer = new ResizeObserver(() => {\n const at = steppedAt.current;\n const grew =\n at !== null &&\n (el.clientWidth > at.self + 0.5 || (parent !== null && parent.clientWidth > at.parent + 0.5));\n if (grew) {\n steppedAt.current = null;\n flushSync(() => setOwn(0));\n } else if (shouldStep()) {\n flushSync(() => setOwn((s) => s + 1));\n }\n });\n observer.observe(el);\n if (parent) observer.observe(parent);\n return () => observer.disconnect();\n }, [ref, depth, shouldStep]);\n\n const step = Math.max(own, outer?.step ?? 0);\n return useMemo(() => ({ step, register }), [step, register]);\n}\n\n/**\n * One label that shortens to fit: the form at the enclosing {@link FitScope}'s\n * step, or its last where it has fewer. Outside any scope it shows the first.\n */\nexport function FitLabel({ forms }: { forms: readonly ReactNode[] }) {\n const scope = useContext(FitContext);\n const register = scope?.register;\n const depth = forms.length;\n useLayoutEffect(() => register?.(depth), [register, depth]);\n const step = scope?.step ?? 0;\n return <>{forms[Math.min(step, depth - 1)]}</>;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./Select-ouV8O6cp.js";
1
+ import { t as e } from "./Select-BhHwjNsb.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  import { listCanvasFonts as n, listFonts as r, resolveFontVariant as i } from "@weasel-js/font";
4
4
  //#region src/components/FontFamilySelect/FontFamilySelect.tsx
@@ -26,4 +26,4 @@ function o(i) {
26
26
  //#endregion
27
27
  export { o as t };
28
28
 
29
- //# sourceMappingURL=FontFamilySelect-DEvMXyZd.js.map
29
+ //# sourceMappingURL=FontFamilySelect-CXN7O2-p.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FontFamilySelect-DEvMXyZd.js","names":["Select","unregisteredLabel","resolveFontVariant","family","weight","style","substituted","FontFamilySelect","props","baked","listFonts","canvas","listCanvasFonts","f","c","available","options","value","fontStyle","mixed","onChange"],"sources":["../../src/components/FontFamilySelect/FontFamilySelect.tsx"],"sourcesContent":["import { listCanvasFonts, listFonts, resolveFontVariant } from '@weasel-js/font';\nimport { Select } from '../Select';\n\n/** Props for {@link FontFamilySelect}. */\nexport interface FontFamilySelectProps {\n /** Current family, or `undefined` when the sources disagree (`mixed`). */\n value?: string;\n /** Indeterminate presentation — the aggregated sources name different families. */\n mixed?: boolean;\n onChange: (family: string) => void;\n /** The weight / style the text actually renders at, so the substitution\n * probe reports the variant that paints rather than a nominal 400/normal. */\n weight?: number;\n fontStyle?: 'normal' | 'italic';\n 'aria-label'?: string;\n className?: string;\n}\n\n/** Label for a value that isn't in the registry: name the substitute when the\n * fallback chain found one, otherwise say only what is known. */\nfunction unregisteredLabel(family: string, weight: number, style: 'normal' | 'italic'): string {\n const { substituted } = resolveFontVariant(family, weight, style);\n return substituted\n ? `${family} — not loaded, showing ${substituted.resolved}`\n : `${family} — not loaded`;\n}\n\n/**\n * Font-family picker driven by the live font registry.\n *\n * **What it offers.** Both tiers that can actually paint: `listFonts()` for\n * families with a baked atlas, and `listCanvasFonts()` for families the\n * dynamic canvas-SDF tier will serve. Offer what will render, invent\n * nothing — and `listCanvasFonts` reports service rather than membership,\n * so a family auto-enrolled under a policy that is no longer in force\n * doesn't appear.\n *\n * **What it does with a value it can't offer.** Nothing about the model\n * stops a node from naming a family that was never registered — a pasted\n * node, an imported SVG, a document from a session that loaded more fonts.\n * The control keeps that value visible as its own entry and names what is\n * actually painting instead, read structurally off\n * `resolveFontVariant().substituted`. Dropping the value would silently\n * rewrite the document on the next edit; showing it bare would claim a font\n * is in use that isn't.\n */\nexport function FontFamilySelect(props: FontFamilySelectProps) {\n const { value, mixed = false, onChange, weight = 400, fontStyle = 'normal', className } = props;\n // Both tiers that actually render: families with a baked atlas, and\n // families the dynamic canvas-SDF tier will serve. Neither list is a guess\n // — `listCanvasFonts` reports what the registry will really route, so a\n // family reaches this menu only if it can paint.\n const baked = listFonts();\n const canvas = listCanvasFonts().filter((c) => !baked.some((f) => f.family === c.family));\n const available = [...baked.map((f) => f.family), ...canvas.map((c) => c.family)];\n const options = available.map((family) => ({ value: family, label: family }));\n if (value !== undefined && !available.includes(value)) {\n options.push({ value, label: unregisteredLabel(value, weight, fontStyle) });\n }\n return (\n <Select<string>\n className={className}\n options={options}\n selectedKey={mixed ? null : (value ?? null)}\n placeholder={mixed ? 'Mixed' : undefined}\n onSelectionChange={onChange}\n aria-label={props['aria-label'] ?? 'Font'}\n />\n );\n}\n"],"mappings":";;;;AAoBA,SAASC,EAAkB,GAAgB,GAAgB,GAAoC;CAC7F,IAAM,EAAE,mBAAgBC,EAAmBC,GAAQC,GAAQC,CAAK;CAChE,OAAOC,IACH,GAAGH,EAAO,yBAAyBG,EAAY,aAC/C,GAAGH,EAAO;AAChB;AAqBA,SAAgBI,EAAiB,GAA8B;CAC7D,IAAM,EAAE,UAAO,WAAQ,IAAO,aAAU,YAAS,KAAK,eAAY,UAAU,iBAAcC,GAKpFC,IAAQC,EAAU,GAClBC,IAASC,EAAgB,CAAC,CAAC,QAAQ,MAAM,CAACH,EAAM,MAAM,MAAMI,EAAE,WAAWC,EAAE,MAAM,CAAC,GAClFC,IAAY,CAAC,GAAGN,EAAM,KAAK,MAAMI,EAAE,MAAM,GAAG,GAAGF,EAAO,KAAK,MAAMG,EAAE,MAAM,CAAC,GAC1EE,IAAUD,EAAU,KAAK,OAAY;EAAE,OAAOZ;EAAQ,OAAOA;CAAO,EAAE;CAI5E,OAHIc,MAAU,KAAA,KAAa,CAACF,EAAU,SAASE,CAAK,KAClDD,EAAQ,KAAK;EAAE;EAAO,OAAOf,EAAkBgB,GAAOb,GAAQc,CAAS;CAAE,CAAC,GAG1E,kBAAClB,GAAD;EACa;EACF;EACT,aAAamB,IAAQ,OAAQF,KAAS;EACtC,aAAaE,IAAQ,UAAU,KAAA;EAC/B,mBAAmBC;EACnB,cAAYZ,EAAM,iBAAiB;CACpC,CAAA;AAEL"}
1
+ {"version":3,"file":"FontFamilySelect-CXN7O2-p.js","names":["Select","unregisteredLabel","resolveFontVariant","family","weight","style","substituted","FontFamilySelect","props","baked","listFonts","canvas","listCanvasFonts","f","c","available","options","value","fontStyle","mixed","onChange"],"sources":["../../src/components/FontFamilySelect/FontFamilySelect.tsx"],"sourcesContent":["import { listCanvasFonts, listFonts, resolveFontVariant } from '@weasel-js/font';\nimport { Select } from '../Select';\n\n/** Props for {@link FontFamilySelect}. */\nexport interface FontFamilySelectProps {\n /** Current family, or `undefined` when the sources disagree (`mixed`). */\n value?: string;\n /** Indeterminate presentation — the aggregated sources name different families. */\n mixed?: boolean;\n onChange: (family: string) => void;\n /** The weight / style the text actually renders at, so the substitution\n * probe reports the variant that paints rather than a nominal 400/normal. */\n weight?: number;\n fontStyle?: 'normal' | 'italic';\n 'aria-label'?: string;\n className?: string;\n}\n\n/** Label for a value that isn't in the registry: name the substitute when the\n * fallback chain found one, otherwise say only what is known. */\nfunction unregisteredLabel(family: string, weight: number, style: 'normal' | 'italic'): string {\n const { substituted } = resolveFontVariant(family, weight, style);\n return substituted\n ? `${family} — not loaded, showing ${substituted.resolved}`\n : `${family} — not loaded`;\n}\n\n/**\n * Font-family picker driven by the live font registry.\n *\n * **What it offers.** Both tiers that can actually paint: `listFonts()` for\n * families with a baked atlas, and `listCanvasFonts()` for families the\n * dynamic canvas-SDF tier will serve. Offer what will render, invent\n * nothing — and `listCanvasFonts` reports service rather than membership,\n * so a family auto-enrolled under a policy that is no longer in force\n * doesn't appear.\n *\n * **What it does with a value it can't offer.** Nothing about the model\n * stops a node from naming a family that was never registered — a pasted\n * node, an imported SVG, a document from a session that loaded more fonts.\n * The control keeps that value visible as its own entry and names what is\n * actually painting instead, read structurally off\n * `resolveFontVariant().substituted`. Dropping the value would silently\n * rewrite the document on the next edit; showing it bare would claim a font\n * is in use that isn't.\n */\nexport function FontFamilySelect(props: FontFamilySelectProps) {\n const { value, mixed = false, onChange, weight = 400, fontStyle = 'normal', className } = props;\n // Both tiers that actually render: families with a baked atlas, and\n // families the dynamic canvas-SDF tier will serve. Neither list is a guess\n // — `listCanvasFonts` reports what the registry will really route, so a\n // family reaches this menu only if it can paint.\n const baked = listFonts();\n const canvas = listCanvasFonts().filter((c) => !baked.some((f) => f.family === c.family));\n const available = [...baked.map((f) => f.family), ...canvas.map((c) => c.family)];\n const options = available.map((family) => ({ value: family, label: family }));\n if (value !== undefined && !available.includes(value)) {\n options.push({ value, label: unregisteredLabel(value, weight, fontStyle) });\n }\n return (\n <Select<string>\n className={className}\n options={options}\n selectedKey={mixed ? null : (value ?? null)}\n placeholder={mixed ? 'Mixed' : undefined}\n onSelectionChange={onChange}\n aria-label={props['aria-label'] ?? 'Font'}\n />\n );\n}\n"],"mappings":";;;;AAoBA,SAASC,EAAkB,GAAgB,GAAgB,GAAoC;CAC7F,IAAM,EAAE,mBAAgBC,EAAmBC,GAAQC,GAAQC,CAAK;CAChE,OAAOC,IACH,GAAGH,EAAO,yBAAyBG,EAAY,aAC/C,GAAGH,EAAO;AAChB;AAqBA,SAAgBI,EAAiB,GAA8B;CAC7D,IAAM,EAAE,UAAO,WAAQ,IAAO,aAAU,YAAS,KAAK,eAAY,UAAU,iBAAcC,GAKpFC,IAAQC,EAAU,GAClBC,IAASC,EAAgB,CAAC,CAAC,QAAQ,MAAM,CAACH,EAAM,MAAM,MAAMI,EAAE,WAAWC,EAAE,MAAM,CAAC,GAClFC,IAAY,CAAC,GAAGN,EAAM,KAAK,MAAMI,EAAE,MAAM,GAAG,GAAGF,EAAO,KAAK,MAAMG,EAAE,MAAM,CAAC,GAC1EE,IAAUD,EAAU,KAAK,OAAY;EAAE,OAAOZ;EAAQ,OAAOA;CAAO,EAAE;CAI5E,OAHIc,MAAU,KAAA,KAAa,CAACF,EAAU,SAASE,CAAK,KAClDD,EAAQ,KAAK;EAAE;EAAO,OAAOf,EAAkBgB,GAAOb,GAAQc,CAAS;CAAE,CAAC,GAG1E,kBAAClB,GAAD;EACa;EACF;EACT,aAAamB,IAAQ,OAAQF,KAAS;EACtC,aAAaE,IAAQ,UAAU,KAAA;EAC/B,mBAAmBC;EACnB,cAAYZ,EAAM,iBAAiB;CACpC,CAAA;AAEL"}
@@ -1,4 +1,4 @@
1
- import { t as e } from "./Select-ouV8O6cp.js";
1
+ import { t as e } from "./Select-BhHwjNsb.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  import { listFontWeights as n } from "@weasel-js/font";
4
4
  //#region src/components/FontWeightSelect/FontWeightSelect.tsx
@@ -46,4 +46,4 @@ function o(i) {
46
46
  //#endregion
47
47
  export { a as n, o as t };
48
48
 
49
- //# sourceMappingURL=FontWeightSelect-BLQ_LMJF.js.map
49
+ //# sourceMappingURL=FontWeightSelect-BBuJGe_2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FontWeightSelect-BLQ_LMJF.js","names":["Select","CSS_WEIGHTS","NAMES","fontWeightLabel","name","weight","FontWeightSelect","props","registered","family","listFontWeights","weights","value","mixed","options","a","b","w","onChange","key"],"sources":["../../src/components/FontWeightSelect/FontWeightSelect.tsx"],"sourcesContent":["import { listFontWeights } from '@weasel-js/font';\nimport { Select } from '../Select';\n\n/** Props for {@link FontWeightSelect}. */\nexport interface FontWeightSelectProps {\n /** Current weight, or `undefined` when the sources disagree (`mixed`). */\n value?: number;\n /** Indeterminate presentation — the aggregated sources differ in weight. */\n mixed?: boolean;\n /** The family whose weights to offer. Absent offers the CSS weights. */\n family?: string;\n onChange: (weight: number) => void;\n 'aria-label'?: string;\n className?: string;\n}\n\nconst CSS_WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900] as const;\n\nconst NAMES: Readonly<Record<number, string>> = {\n 100: 'Thin',\n 200: 'Extra Light',\n 300: 'Light',\n 400: 'Regular',\n 500: 'Medium',\n 600: 'Semibold',\n 700: 'Bold',\n 800: 'Extra Bold',\n 900: 'Black',\n};\n\n/** A weight as the picker lists it: the number, then its common name. */\nexport function fontWeightLabel(weight: number): string {\n const name = NAMES[weight];\n return name ? `${weight} ${name}` : String(weight);\n}\n\n/**\n * Font-weight picker for one family, driven by the live font registry.\n *\n * It offers the weights `listFontWeights` reports for `family` — the faces\n * that will actually paint rather than be faked. A family with none on file\n * (the canvas tier, which rasterizes any weight it is asked for, or no family\n * at all because the selection spans several) gets the nine CSS weights. A\n * value outside the list is kept as its own entry, as `FontFamilySelect` keeps\n * an unregistered family: dropping it would rewrite the text on the next edit.\n */\nexport function FontWeightSelect(props: FontWeightSelectProps) {\n const { value, mixed = false, family, onChange, className } = props;\n const registered = family === undefined ? [] : listFontWeights(family);\n const weights = new Set<number>(registered.length > 0 ? registered : CSS_WEIGHTS);\n if (value !== undefined && !mixed) weights.add(value);\n const options = [...weights]\n .sort((a, b) => a - b)\n .map((w) => ({ value: String(w), label: fontWeightLabel(w) }));\n return (\n <Select<string>\n className={className}\n options={options}\n selectedKey={mixed || value === undefined ? null : String(value)}\n placeholder={mixed ? 'Mixed' : undefined}\n onSelectionChange={(key) => onChange(Number(key))}\n aria-label={props['aria-label'] ?? 'Weight'}\n />\n );\n}\n"],"mappings":";;;;AAgBA,IAAMC,IAAc;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,GAE1DC,IAA0C;CAC9C,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAGA,SAAgBC,EAAgB,GAAwB;CACtD,IAAMC,IAAOF,EAAMG;CACnB,OAAOD,IAAO,GAAGC,EAAO,GAAGD,MAAS,OAAOC,CAAM;AACnD;AAYA,SAAgBC,EAAiB,GAA8B;CAC7D,IAAM,EAAE,UAAO,WAAQ,IAAO,WAAQ,aAAU,iBAAcC,GACxDC,IAAaC,MAAW,KAAA,IAAY,CAAC,IAAIC,EAAgBD,CAAM,GAC/DE,IAAU,IAAI,IAAYH,EAAW,SAAS,IAAIA,IAAaP,CAAW;CAChF,AAAIW,MAAU,KAAA,KAAa,CAACC,KAAOF,EAAQ,IAAIC,CAAK;CACpD,IAAME,IAAU,CAAC,GAAGH,CAAO,CAAC,CACzB,MAAM,GAAG,MAAMI,IAAIC,CAAC,CAAC,CACrB,KAAK,OAAO;EAAE,OAAO,OAAOC,CAAC;EAAG,OAAOd,EAAgBc,CAAC;CAAE,EAAE;CAC/D,OACE,kBAACjB,GAAD;EACa;EACF;EACT,aAAaa,KAASD,MAAU,KAAA,IAAY,OAAO,OAAOA,CAAK;EAC/D,aAAaC,IAAQ,UAAU,KAAA;EAC/B,oBAAoB,MAAQK,EAAS,OAAOC,CAAG,CAAC;EAChD,cAAYZ,EAAM,iBAAiB;CACpC,CAAA;AAEL"}
1
+ {"version":3,"file":"FontWeightSelect-BBuJGe_2.js","names":["Select","CSS_WEIGHTS","NAMES","fontWeightLabel","name","weight","FontWeightSelect","props","registered","family","listFontWeights","weights","value","mixed","options","a","b","w","onChange","key"],"sources":["../../src/components/FontWeightSelect/FontWeightSelect.tsx"],"sourcesContent":["import { listFontWeights } from '@weasel-js/font';\nimport { Select } from '../Select';\n\n/** Props for {@link FontWeightSelect}. */\nexport interface FontWeightSelectProps {\n /** Current weight, or `undefined` when the sources disagree (`mixed`). */\n value?: number;\n /** Indeterminate presentation — the aggregated sources differ in weight. */\n mixed?: boolean;\n /** The family whose weights to offer. Absent offers the CSS weights. */\n family?: string;\n onChange: (weight: number) => void;\n 'aria-label'?: string;\n className?: string;\n}\n\nconst CSS_WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900] as const;\n\nconst NAMES: Readonly<Record<number, string>> = {\n 100: 'Thin',\n 200: 'Extra Light',\n 300: 'Light',\n 400: 'Regular',\n 500: 'Medium',\n 600: 'Semibold',\n 700: 'Bold',\n 800: 'Extra Bold',\n 900: 'Black',\n};\n\n/** A weight as the picker lists it: the number, then its common name. */\nexport function fontWeightLabel(weight: number): string {\n const name = NAMES[weight];\n return name ? `${weight} ${name}` : String(weight);\n}\n\n/**\n * Font-weight picker for one family, driven by the live font registry.\n *\n * It offers the weights `listFontWeights` reports for `family` — the faces\n * that will actually paint rather than be faked. A family with none on file\n * (the canvas tier, which rasterizes any weight it is asked for, or no family\n * at all because the selection spans several) gets the nine CSS weights. A\n * value outside the list is kept as its own entry, as `FontFamilySelect` keeps\n * an unregistered family: dropping it would rewrite the text on the next edit.\n */\nexport function FontWeightSelect(props: FontWeightSelectProps) {\n const { value, mixed = false, family, onChange, className } = props;\n const registered = family === undefined ? [] : listFontWeights(family);\n const weights = new Set<number>(registered.length > 0 ? registered : CSS_WEIGHTS);\n if (value !== undefined && !mixed) weights.add(value);\n const options = [...weights]\n .sort((a, b) => a - b)\n .map((w) => ({ value: String(w), label: fontWeightLabel(w) }));\n return (\n <Select<string>\n className={className}\n options={options}\n selectedKey={mixed || value === undefined ? null : String(value)}\n placeholder={mixed ? 'Mixed' : undefined}\n onSelectionChange={(key) => onChange(Number(key))}\n aria-label={props['aria-label'] ?? 'Weight'}\n />\n );\n}\n"],"mappings":";;;;AAgBA,IAAMC,IAAc;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,GAE1DC,IAA0C;CAC9C,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAGA,SAAgBC,EAAgB,GAAwB;CACtD,IAAMC,IAAOF,EAAMG;CACnB,OAAOD,IAAO,GAAGC,EAAO,GAAGD,MAAS,OAAOC,CAAM;AACnD;AAYA,SAAgBC,EAAiB,GAA8B;CAC7D,IAAM,EAAE,UAAO,WAAQ,IAAO,WAAQ,aAAU,iBAAcC,GACxDC,IAAaC,MAAW,KAAA,IAAY,CAAC,IAAIC,EAAgBD,CAAM,GAC/DE,IAAU,IAAI,IAAYH,EAAW,SAAS,IAAIA,IAAaP,CAAW;CAChF,AAAIW,MAAU,KAAA,KAAa,CAACC,KAAOF,EAAQ,IAAIC,CAAK;CACpD,IAAME,IAAU,CAAC,GAAGH,CAAO,CAAC,CACzB,MAAM,GAAG,MAAMI,IAAIC,CAAC,CAAC,CACrB,KAAK,OAAO;EAAE,OAAO,OAAOC,CAAC;EAAG,OAAOd,EAAgBc,CAAC;CAAE,EAAE;CAC/D,OACE,kBAACjB,GAAD;EACa;EACF;EACT,aAAaa,KAASD,MAAU,KAAA,IAAY,OAAO,OAAOA,CAAK;EAC/D,aAAaC,IAAQ,UAAU,KAAA;EAC/B,oBAAoB,MAAQK,EAAS,OAAOC,CAAG,CAAC;EAChD,cAAYZ,EAAM,iBAAiB;CACpC,CAAA;AAEL"}
@@ -1,5 +1,5 @@
1
- import { o as e, r as t, s as n } from "./Keycaps-C-FJyG8k.js";
2
- import { t as r } from "./Powerline-6wIFmDik.js";
1
+ import { c as e, i as t, s as n } from "./Keycaps-CM-gOj0e.js";
2
+ import { t as r } from "./Powerline-CogJv9VU.js";
3
3
  import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
4
4
  import { getGestureDescriptor as s, parseRoute as c } from "@weasel-js/core/routing";
5
5
  var l = {
@@ -12,19 +12,19 @@ var l = {
12
12
  "ctrl",
13
13
  "meta"
14
14
  ];
15
- function d(e) {
16
- let t = [];
17
- for (let n of u) {
18
- let r = e[n];
19
- r !== void 0 && t.push({
20
- name: n,
15
+ function d(t) {
16
+ let n = [];
17
+ for (let e of u) {
18
+ let r = t[e];
19
+ r !== void 0 && n.push({
20
+ name: e,
21
21
  optional: r === "optional"
22
22
  });
23
23
  }
24
- if (t.length !== 0) return n(t);
24
+ if (n.length !== 0) return e(n);
25
25
  }
26
- function f(n) {
27
- let r = c(n), u = s(r.gesture), f = !!u.arg && r.arg !== void 0, p = f && u.arg?.name === "key", m = f && u.arg?.default !== void 0 && r.arg === u.arg.default, h = u.hasTarget && r.target !== void 0, g = h && r.target === "*", _ = d(r.modifiers), v = [];
26
+ function f(e) {
27
+ let r = c(e), u = s(r.gesture), f = !!u.arg && r.arg !== void 0, p = f && u.arg?.name === "key", m = f && u.arg?.default !== void 0 && r.arg === u.arg.default, h = u.hasTarget && r.target !== void 0, g = h && r.target === "*", _ = d(r.modifiers), v = [];
28
28
  for (let e of r.phases) e.channel !== "&" && v.push({
29
29
  text: e.channel,
30
30
  status: "neutral",
@@ -39,7 +39,7 @@ function f(n) {
39
39
  r.gesture,
40
40
  " ",
41
41
  /* @__PURE__ */ a(t, {
42
- label: e(r.arg).label,
42
+ label: n(r.arg).label,
43
43
  variant: "minimal",
44
44
  className: l.keyCap
45
45
  })
@@ -79,4 +79,4 @@ function p({ route: e, "aria-label": t, ...n }) {
79
79
  //#endregion
80
80
  export { f as n, p as t };
81
81
 
82
- //# sourceMappingURL=GestureRoute-BXESrHI0.js.map
82
+ //# sourceMappingURL=GestureRoute-BqHUrGeQ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GestureRoute-BXESrHI0.js","names":["_Fragment","s","keySpecFromKey","KeyCap","keySpecsFromMods","Powerline","GestureRoute_module_default","MOD_DISPLAY_ORDER","modifierKeys","specs","name","req","modifiers","gestureRouteSegments","parsed","parseRoute","route","desc","getGestureDescriptor","hasArg","argIsKey","argIsDefault","hasTarget","targetIsWildcard","modKeys","segments","p","Fragment","text","k","i","GestureRoute","ariaLabel","rest"],"sources":["../../src/components/GestureRoute/GestureRoute.module.css","../../src/components/GestureRoute/GestureRoute.tsx"],"sourcesContent":[".muted { opacity: 0.55; }\n/* A gesture segment baseline-aligns its text; a KeyCap inside it has its own box and sits off-center without this. */\n.keyCap { align-self: center; }\n","import {\n getGestureDescriptor,\n parseRoute,\n type GestureName,\n type ModifierKey,\n type ParsedModifiers,\n} from '@weasel-js/core/routing';\nimport { Powerline, type PowerlineProps, type PowerlineSegment } from '../Powerline';\nimport { KeyCap, keySpecFromKey, keySpecsFromMods, type KeySpec, type LogicalModSpec } from '../Keycaps';\nimport s from './GestureRoute.module.css';\n\nconst MOD_DISPLAY_ORDER: readonly ModifierKey[] = ['mod', 'shift', 'alt', 'ctrl', 'meta'];\n\nfunction modifierKeys(modifiers: ParsedModifiers): readonly KeySpec[] | undefined {\n const specs: LogicalModSpec[] = [];\n for (const name of MOD_DISPLAY_ORDER) {\n const req = modifiers[name];\n if (req !== undefined) specs.push({ name, optional: req === 'optional' });\n }\n if (specs.length === 0) return undefined;\n return keySpecsFromMods(specs);\n}\n\n/**\n * The segments {@link GestureRoute} draws for a route string: phase atoms, then\n * `gesture(arg)`, then the held modifiers as one chord, then the target.\n * A descriptor's default arg and a wildcard target stay visible, muted, so\n * the strip shows the whole binding.\n */\nexport function gestureRouteSegments(route: string): PowerlineSegment[] {\n const parsed = parseRoute(route);\n const desc = getGestureDescriptor(parsed.gesture as GestureName);\n const hasArg = !!desc.arg && parsed.arg !== undefined;\n const argIsKey = hasArg && desc.arg?.name === 'key';\n const argIsDefault = hasArg && desc.arg?.default !== undefined && parsed.arg === desc.arg.default;\n const hasTarget = desc.hasTarget && parsed.target !== undefined;\n const targetIsWildcard = hasTarget && parsed.target === '*';\n const modKeys = modifierKeys(parsed.modifiers);\n\n const segments: PowerlineSegment[] = [];\n for (const p of parsed.phases) {\n if (p.channel !== '&') segments.push({ text: p.channel, status: 'neutral', variant: 'subtle' });\n segments.push({ text: p.phase, status: 'accent', variant: 'subtle' });\n }\n segments.push({\n text: hasArg ? (\n argIsKey ? (\n <>\n {parsed.gesture}{' '}\n <KeyCap label={keySpecFromKey(parsed.arg!).label} variant=\"minimal\" className={s.keyCap} />\n </>\n ) : (\n <>\n {parsed.gesture}\n <span className={argIsDefault ? s.muted : undefined}>({parsed.arg})</span>\n </>\n )\n ) : parsed.gesture,\n status: 'info',\n variant: 'outline',\n });\n if (modKeys) {\n // `+` marks a required modifier and `?` an optional one, so `+mod ?shift` reads `+⌘?⇧`.\n const text = modKeys.map((k) => `${k.optional ? '?' : '+'}${k.label}`).join('');\n segments.push({ text, status: 'muted', variant: 'solid' });\n }\n if (hasTarget) {\n segments.push({\n text: parsed.target,\n status: 'muted',\n variant: targetIsWildcard ? 'subtle' : 'outline',\n });\n }\n for (let i = 0; i < segments.length - 1; i++) segments[i].endCap = 'chevron';\n return segments;\n}\n\n/** Props for {@link GestureRoute}. */\nexport interface GestureRouteProps extends Omit<PowerlineProps, 'segments'> {\n /** A route in the dispatcher's grammar, e.g. `[initial] drag => node +shift`. */\n route: string;\n}\n\n/**\n * A dispatcher route drawn as a {@link Powerline}: phase, gesture, modifiers\n * and target as one chevron-linked chain.\n */\nexport function GestureRoute({ route, 'aria-label': ariaLabel, ...rest }: GestureRouteProps) {\n return <Powerline {...rest} segments={gestureRouteSegments(route)} aria-label={ariaLabel ?? route} />;\n}\n"],"mappings":";;;;;;;GCWMO,IAA4C;CAAC;CAAO;CAAS;CAAO;CAAQ;AAAM;AAExF,SAASC,EAAa,GAA4D;CAChF,IAAMC,IAA0B,CAAC;CACjC,KAAK,IAAMC,KAAQH,GAAmB;EACpC,IAAMI,IAAMC,EAAUF;EACtB,AAAIC,MAAQ,KAAA,KAAWF,EAAM,KAAK;GAAE;GAAM,UAAUE,MAAQ;EAAW,CAAC;CAC1E;CACA,IAAIF,EAAM,WAAW,GACrB,OAAOL,EAAiBK,CAAK;AAC/B;AAQA,SAAgBI,EAAqB,GAAmC;CACtE,IAAMC,IAASC,EAAWC,CAAK,GACzBC,IAAOC,EAAqBJ,EAAO,OAAsB,GACzDK,IAAS,CAAC,CAACF,EAAK,OAAOH,EAAO,QAAQ,KAAA,GACtCM,IAAWD,KAAUF,EAAK,KAAK,SAAS,OACxCI,IAAeF,KAAUF,EAAK,KAAK,YAAY,KAAA,KAAaH,EAAO,QAAQG,EAAK,IAAI,SACpFK,IAAYL,EAAK,aAAaH,EAAO,WAAW,KAAA,GAChDS,IAAmBD,KAAaR,EAAO,WAAW,KAClDU,IAAUhB,EAAaM,EAAO,SAAS,GAEvCW,IAA+B,CAAC;CACtC,KAAK,IAAMC,KAAKZ,EAAO,QAErB,AADIY,EAAE,YAAY,OAAKD,EAAS,KAAK;EAAE,MAAMC,EAAE;EAAS,QAAQ;EAAW,SAAS;CAAS,CAAC,GAC9FD,EAAS,KAAK;EAAE,MAAMC,EAAE;EAAO,QAAQ;EAAU,SAAS;CAAS,CAAC;CAmBtE,IAjBAD,EAAS,KAAK;EACZ,MAAMN,IACJC,IACE,kBAAApB,GAAA,EAAA,UAAA;GACGc,EAAO;GAAS;GACjB,kBAACX,GAAD;IAAQ,OAAOD,EAAeY,EAAO,GAAI,CAAC,CAAC;IAAO,SAAQ;IAAU,WAAWb,EAAE;GAAS,CAAA;EAC1F,EAAA,CAAA,IAEF,kBAAAD,GAAA,EAAA,UAAA,CACGc,EAAO,SACR,kBAAC,QAAD;GAAM,WAAWO,IAAepB,EAAE,QAAQ,KAAA;GAA1C,UAAA;IAAqD;IAAEa,EAAO;IAAI;GAAO;EACzE,CAAA,CAAA,EAAA,CAAA,IAEFA,EAAO;EACX,QAAQ;EACR,SAAS;CACX,CAAC,GACGU,GAAS;EAEX,IAAMI,IAAOJ,EAAQ,KAAK,MAAM,GAAGK,EAAE,WAAW,MAAM,MAAMA,EAAE,OAAO,CAAC,CAAC,KAAK,EAAE;EAC9E,EAAS,KAAK;GAAE;GAAM,QAAQ;GAAS,SAAS;EAAQ,CAAC;CAC3D;CACA,AAAIP,KACFG,EAAS,KAAK;EACZ,MAAMX,EAAO;EACb,QAAQ;EACR,SAASS,IAAmB,WAAW;CACzC,CAAC;CAEH,KAAK,IAAIO,IAAI,GAAGA,IAAIL,EAAS,SAAS,GAAG,KAAK,EAASK,EAAE,CAAC,SAAS;CACnE,OAAOL;AACT;AAYA,SAAgBM,EAAa,EAAE,UAAO,cAAcC,GAAW,GAAGC,KAA2B;CAC3F,OAAO,kBAAC5B,GAAD;EAAW,GAAI4B;EAAM,UAAUpB,EAAqBG,CAAK;EAAG,cAAYgB,KAAahB;CAAQ,CAAA;AACtG"}
1
+ {"version":3,"file":"GestureRoute-BqHUrGeQ.js","names":["_Fragment","s","keySpecsFromMods","KeyCap","keySpecFromKey","Powerline","GestureRoute_module_default","MOD_DISPLAY_ORDER","modifierKeys","specs","name","req","modifiers","gestureRouteSegments","parsed","parseRoute","route","desc","getGestureDescriptor","hasArg","argIsKey","argIsDefault","hasTarget","targetIsWildcard","modKeys","segments","p","Fragment","text","k","i","GestureRoute","ariaLabel","rest"],"sources":["../../src/components/GestureRoute/GestureRoute.module.css","../../src/components/GestureRoute/GestureRoute.tsx"],"sourcesContent":[".muted { opacity: 0.55; }\n/* A gesture segment baseline-aligns its text; a KeyCap inside it has its own box and sits off-center without this. */\n.keyCap { align-self: center; }\n","import {\n getGestureDescriptor,\n parseRoute,\n type GestureName,\n type ModifierKey,\n type ParsedModifiers,\n} from '@weasel-js/core/routing';\nimport { Powerline, type PowerlineProps, type PowerlineSegment } from '../Powerline';\nimport { KeyCap, keySpecFromKey, keySpecsFromMods, type KeySpec, type LogicalModSpec } from '../Keycaps';\nimport s from './GestureRoute.module.css';\n\nconst MOD_DISPLAY_ORDER: readonly ModifierKey[] = ['mod', 'shift', 'alt', 'ctrl', 'meta'];\n\nfunction modifierKeys(modifiers: ParsedModifiers): readonly KeySpec[] | undefined {\n const specs: LogicalModSpec[] = [];\n for (const name of MOD_DISPLAY_ORDER) {\n const req = modifiers[name];\n if (req !== undefined) specs.push({ name, optional: req === 'optional' });\n }\n if (specs.length === 0) return undefined;\n return keySpecsFromMods(specs);\n}\n\n/**\n * The segments {@link GestureRoute} draws for a route string: phase atoms, then\n * `gesture(arg)`, then the held modifiers as one chord, then the target.\n * A descriptor's default arg and a wildcard target stay visible, muted, so\n * the strip shows the whole binding.\n */\nexport function gestureRouteSegments(route: string): PowerlineSegment[] {\n const parsed = parseRoute(route);\n const desc = getGestureDescriptor(parsed.gesture as GestureName);\n const hasArg = !!desc.arg && parsed.arg !== undefined;\n const argIsKey = hasArg && desc.arg?.name === 'key';\n const argIsDefault = hasArg && desc.arg?.default !== undefined && parsed.arg === desc.arg.default;\n const hasTarget = desc.hasTarget && parsed.target !== undefined;\n const targetIsWildcard = hasTarget && parsed.target === '*';\n const modKeys = modifierKeys(parsed.modifiers);\n\n const segments: PowerlineSegment[] = [];\n for (const p of parsed.phases) {\n if (p.channel !== '&') segments.push({ text: p.channel, status: 'neutral', variant: 'subtle' });\n segments.push({ text: p.phase, status: 'accent', variant: 'subtle' });\n }\n segments.push({\n text: hasArg ? (\n argIsKey ? (\n <>\n {parsed.gesture}{' '}\n <KeyCap label={keySpecFromKey(parsed.arg!).label} variant=\"minimal\" className={s.keyCap} />\n </>\n ) : (\n <>\n {parsed.gesture}\n <span className={argIsDefault ? s.muted : undefined}>({parsed.arg})</span>\n </>\n )\n ) : parsed.gesture,\n status: 'info',\n variant: 'outline',\n });\n if (modKeys) {\n // `+` marks a required modifier and `?` an optional one, so `+mod ?shift` reads `+⌘?⇧`.\n const text = modKeys.map((k) => `${k.optional ? '?' : '+'}${k.label}`).join('');\n segments.push({ text, status: 'muted', variant: 'solid' });\n }\n if (hasTarget) {\n segments.push({\n text: parsed.target,\n status: 'muted',\n variant: targetIsWildcard ? 'subtle' : 'outline',\n });\n }\n for (let i = 0; i < segments.length - 1; i++) segments[i].endCap = 'chevron';\n return segments;\n}\n\n/** Props for {@link GestureRoute}. */\nexport interface GestureRouteProps extends Omit<PowerlineProps, 'segments'> {\n /** A route in the dispatcher's grammar, e.g. `[initial] drag => node +shift`. */\n route: string;\n}\n\n/**\n * A dispatcher route drawn as a {@link Powerline}: phase, gesture, modifiers\n * and target as one chevron-linked chain.\n */\nexport function GestureRoute({ route, 'aria-label': ariaLabel, ...rest }: GestureRouteProps) {\n return <Powerline {...rest} segments={gestureRouteSegments(route)} aria-label={ariaLabel ?? route} />;\n}\n"],"mappings":";;;;;;;GCWMO,IAA4C;CAAC;CAAO;CAAS;CAAO;CAAQ;AAAM;AAExF,SAASC,EAAa,GAA4D;CAChF,IAAMC,IAA0B,CAAC;CACjC,KAAK,IAAMC,KAAQH,GAAmB;EACpC,IAAMI,IAAMC,EAAUF;EACtB,AAAIC,MAAQ,KAAA,KAAWF,EAAM,KAAK;GAAE;GAAM,UAAUE,MAAQ;EAAW,CAAC;CAC1E;CACA,IAAIF,EAAM,WAAW,GACrB,OAAOP,EAAiBO,CAAK;AAC/B;AAQA,SAAgBI,EAAqB,GAAmC;CACtE,IAAMC,IAASC,EAAWC,CAAK,GACzBC,IAAOC,EAAqBJ,EAAO,OAAsB,GACzDK,IAAS,CAAC,CAACF,EAAK,OAAOH,EAAO,QAAQ,KAAA,GACtCM,IAAWD,KAAUF,EAAK,KAAK,SAAS,OACxCI,IAAeF,KAAUF,EAAK,KAAK,YAAY,KAAA,KAAaH,EAAO,QAAQG,EAAK,IAAI,SACpFK,IAAYL,EAAK,aAAaH,EAAO,WAAW,KAAA,GAChDS,IAAmBD,KAAaR,EAAO,WAAW,KAClDU,IAAUhB,EAAaM,EAAO,SAAS,GAEvCW,IAA+B,CAAC;CACtC,KAAK,IAAMC,KAAKZ,EAAO,QAErB,AADIY,EAAE,YAAY,OAAKD,EAAS,KAAK;EAAE,MAAMC,EAAE;EAAS,QAAQ;EAAW,SAAS;CAAS,CAAC,GAC9FD,EAAS,KAAK;EAAE,MAAMC,EAAE;EAAO,QAAQ;EAAU,SAAS;CAAS,CAAC;CAmBtE,IAjBAD,EAAS,KAAK;EACZ,MAAMN,IACJC,IACE,kBAAApB,GAAA,EAAA,UAAA;GACGc,EAAO;GAAS;GACjB,kBAACX,GAAD;IAAQ,OAAOC,EAAeU,EAAO,GAAI,CAAC,CAAC;IAAO,SAAQ;IAAU,WAAWb,EAAE;GAAS,CAAA;EAC1F,EAAA,CAAA,IAEF,kBAAAD,GAAA,EAAA,UAAA,CACGc,EAAO,SACR,kBAAC,QAAD;GAAM,WAAWO,IAAepB,EAAE,QAAQ,KAAA;GAA1C,UAAA;IAAqD;IAAEa,EAAO;IAAI;GAAO;EACzE,CAAA,CAAA,EAAA,CAAA,IAEFA,EAAO;EACX,QAAQ;EACR,SAAS;CACX,CAAC,GACGU,GAAS;EAEX,IAAMI,IAAOJ,EAAQ,KAAK,MAAM,GAAGK,EAAE,WAAW,MAAM,MAAMA,EAAE,OAAO,CAAC,CAAC,KAAK,EAAE;EAC9E,EAAS,KAAK;GAAE;GAAM,QAAQ;GAAS,SAAS;EAAQ,CAAC;CAC3D;CACA,AAAIP,KACFG,EAAS,KAAK;EACZ,MAAMX,EAAO;EACb,QAAQ;EACR,SAASS,IAAmB,WAAW;CACzC,CAAC;CAEH,KAAK,IAAIO,IAAI,GAAGA,IAAIL,EAAS,SAAS,GAAG,KAAK,EAASK,EAAE,CAAC,SAAS;CACnE,OAAOL;AACT;AAYA,SAAgBM,EAAa,EAAE,UAAO,cAAcC,GAAW,GAAGC,KAA2B;CAC3F,OAAO,kBAAC5B,GAAD;EAAW,GAAI4B;EAAM,UAAUpB,EAAqBG,CAAK;EAAG,cAAYgB,KAAahB;CAAQ,CAAA;AACtG"}
@@ -1,7 +1,7 @@
1
1
  import { t as e } from "./ColorField-BwlelY26.js";
2
- import { t } from "./Slider-DSrlMEq8.js";
3
- import { t as n } from "./ToggleBar-Z2jZiguF.js";
4
- import { a as r, i, n as a, o, r as s, s as c, t as l } from "./MeshEditor-DWpvg8H6.js";
2
+ import { t } from "./Slider-CHBQ8uUC.js";
3
+ import { t as n } from "./ToggleBar-CfYbMK3x.js";
4
+ import { a as r, i, n as a, o, r as s, s as c, t as l } from "./MeshEditor-rhf7cXfG.js";
5
5
  import { fillInPoseFrame as u, fillToBoundsFrame as d, gradientGeometry as f, isGradientFill as p, sampleGradientStops as m, switchGradientKind as h, useGradientKinds as g, useNodeOverlayFrame as _, useOngoingAction as v, usePaintKind as y } from "@weasel-js/core";
6
6
  import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
7
7
  import "react";
@@ -322,4 +322,4 @@ function R(e, t, n) {
322
322
  //#endregion
323
323
  export { D as i, N as n, j as r, L as t };
324
324
 
325
- //# sourceMappingURL=GradientEditor-DD2OjQtn.js.map
325
+ //# sourceMappingURL=GradientEditor-DX4sb1Hf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GradientEditor-DD2OjQtn.js","names":["s","_Fragment","_Fragment","s","ColorField","ToggleBar","handleOverlay_module_default","DragPoint","Guide","isMeshPaint","MeshHandles","DEFAULT_HATCH","paintGradientTrack","opts","stops","i","samples","t","gradient","ctx","baseGradient","layers","activeRange","low","high","h","hatch","stripe","dimColor","dimOverlay","wL","wR","style","GradientEditor_module_default","SPACES","MIN_STOPS","GradientEditor","props","kind","value","space","entry","usePaintKind","kinds","useGradientKinds","svg","nativeSvgKind","spaces","nativeSvgSpace","item","switchKind","converted","switchGradientKind","next","onChange","className","kindSwitch","renderBody","spaceBar","spaceSwitch","Editor","Fragment","isGradientFill","StopsBody","MeshEditor","withStops","thumbs","stop","applyThumbs","setStopColor","index","ordered","a","b","Slider","onInput","at","sampleGradientStops","hex","GradientHandles","HandleOverlay","renderForKind","toScreen","toLocal","emit","phase","from","to","HANDLE_RADIUS","p","center","edge","screenRadius","local","radius","MIN_RADIUS","gradientGeometry","tip","angle","SceneGradientHandles","frame","useNodeOverlayFrame","scene","containerRef","nodeId","edit","useOngoingAction","slot","paint","paintOf","dispatch","normalized","fillToBoundsFrame","common","fillInPoseFrame","isMeshGradientFill","resolved","data"],"sources":["../../src/paintGradientTrack.tsx","../../src/components/GradientEditor/GradientEditor.module.css","../../src/components/GradientEditor/GradientEditor.tsx","../../src/components/GradientEditor/GradientHandles.tsx","../../src/components/GradientEditor/SceneGradientHandles.tsx"],"sourcesContent":["import type { ReactNode, CSSProperties } from 'react';\nimport type { TrackCtx } from './components/Slider';\n\n/**\n * Options for {@link paintGradientTrack}.\n *\n * `gradient` maps a normalized position along the slider's value span (0 to\n * 1) to a CSS color; `samples` is how many stops the resulting\n * linear-gradient uses. The ramp is laid on the same span as the thumbs, so a\n * thumb at 0.3 sits over `gradient(0.3)`; any track beyond the span takes the\n * end colors.\n * `activeRange`, given in the slider's own value units, keeps that span at\n * full strength and dims + hatches the rest.\n */\nexport type GradientTrackOpts = {\n gradient: (t: number) => string;\n samples?: number;\n activeRange?: [number, number];\n hatch?: {\n angleDeg?: number;\n stripe?: number;\n gap?: number;\n dim?: number;\n };\n};\n\nconst DEFAULT_HATCH = { angleDeg: 135, stripe: 2, gap: 4, dim: 75 };\n\n/**\n * Builds a `Slider` `renderTrack` function that paints the track as a\n * sampled color gradient, optionally dimming and hatching the portions\n * outside an active range.\n */\nexport function paintGradientTrack(opts: GradientTrackOpts): (ctx: TrackCtx) => ReactNode {\n const { gradient, samples = 16, activeRange, hatch } = opts;\n\n return (ctx: TrackCtx) => {\n const stops: string[] = [];\n for (let i = 0; i <= samples; i++) {\n const t = i / samples;\n stops.push(`${gradient(t)} ${ctx.fractionToPosition(t)}`);\n }\n const baseGradient = `linear-gradient(to right, ${stops.join(', ')})`;\n\n const layers: string[] = [];\n if (activeRange) {\n const low = ctx.valueToFraction(activeRange[0]);\n const high = ctx.valueToFraction(activeRange[1]);\n const h = { ...DEFAULT_HATCH, ...hatch };\n const stripe = `repeating-linear-gradient(${h.angleDeg}deg, transparent 0 ${h.stripe}px, var(--wzl-surface) ${h.stripe}px ${h.stripe + h.gap}px)`;\n const dimColor = `color-mix(in srgb, var(--wzl-surface) ${h.dim}%, transparent)`;\n const dimOverlay = `linear-gradient(${dimColor}, ${dimColor})`;\n\n if (low > 0) {\n const wL = ctx.fractionToPosition(low);\n layers.push(`${dimOverlay} left 0 / ${wL} 100% no-repeat`);\n layers.push(`${stripe} left 0 / ${wL} 100% no-repeat`);\n }\n if (high < 1) {\n const wR = `calc(100% - ${ctx.fractionToPosition(high)})`;\n layers.push(`${dimOverlay} right 0 / ${wR} 100% no-repeat`);\n layers.push(`${stripe} right 0 / ${wR} 100% no-repeat`);\n }\n }\n layers.push(baseGradient);\n\n const style: CSSProperties = {\n position: 'absolute',\n inset: 0,\n background: layers.join(', '),\n };\n return <div style={style} />;\n };\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n min-inline-size: 0;\n}\n\n.swatches {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-3);\n}\n\n/* Each stop's opacity slider would otherwise stretch the row to a width no\n * properties panel has; the chip stays legible, the slider yields. */\n.swatch {\n flex: 0 1 auto;\n min-inline-size: 0;\n}\n\n.noEditor {\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg-muted);\n}\n","import { type ReactElement, type ReactNode } from 'react';\nimport {\n isGradientFill,\n sampleGradientStops,\n switchGradientKind,\n useGradientKinds,\n usePaintKind,\n type ColorSpace,\n type FillStyle,\n type GradStop,\n type GradientFill,\n type PaintKind,\n} from '@weasel-js/core';\nimport { nativeSvgKind, nativeSvgSpace } from '@weasel-js/svg';\nimport { Slider, type Thumb } from '../Slider';\nimport { ColorField } from '../ColorField';\nimport { MeshEditor, isMeshPaint } from '../MeshEditor';\nimport { ToggleBar, type ToggleBarItem } from '../ToggleBar';\nimport { paintGradientTrack } from '../../paintGradientTrack';\nimport s from './GradientEditor.module.css';\n\nconst SPACES: readonly ToggleBarItem<ColorSpace>[] = [\n { value: 'rgb', label: 'sRGB' },\n { value: 'oklab', label: 'OKLab' },\n { value: 'oklch', label: 'OKLCh' },\n];\n\n/** Fewer than two stops is not a gradient any renderer can ramp between. */\nconst MIN_STOPS = 2;\n\n/**\n * Props for {@link GradientEditor}. `onInput` fires throughout a gesture and\n * `onChange` once at its end.\n */\nexport interface GradientEditorProps {\n /** The gradient being edited: a paint of any gradient kind — one that\n * `listGradientKinds` returns. */\n value: FillStyle;\n /**\n * Live value during a gesture — a stop drag, a color-picker scrub. Wire\n * it for preview; it fires many times per gesture and must not be\n * written to history.\n */\n onInput?: (next: FillStyle) => void;\n /** Committed value: one call per completed gesture. Pair with an\n * undoable write. */\n onChange: (next: FillStyle) => void;\n /** Show the kind switch — every registered gradient kind. Default true;\n * turn it off when the surrounding UI already owns the kind. */\n kindSwitch?: boolean;\n /** Show the sRGB / OKLab / OKLCh switch, which writes `interpolate`.\n * Default true. */\n spaceSwitch?: boolean;\n /**\n * Offer only what an SVG file carries natively: the linear and radial\n * gradients, which SVG has elements for, blended in sRGB, the only space\n * every SVG renderer honors. A conic or mesh gradient exports as a weasel\n * element that other renderers paint as one flat color, and an OKLab or\n * OKLCh blend exports as an attribute they ignore. A value already outside\n * that set keeps its own kind and space on offer, so it can be switched\n * back. Default false.\n */\n svg?: boolean;\n className?: string;\n}\n\ntype StopThumb = Thumb & { color: string };\n\n/**\n * Editor for a gradient's kind and colors: the stop list of a linear, radial\n * or conic gradient, a mesh's corner colors, or a registered kind's own\n * `Editor`. Switching kind goes through `switchGradientKind`, so the colors\n * carry across.\n *\n * Geometry (`from`/`to`, `center`, `radius`, `angle`) is deliberately not\n * edited here — on a canvas that belongs on the artwork, via\n * `<GradientHandles>`. This component owns the parts with no spatial\n * meaning, so it composes into a properties panel at any width.\n *\n * Stops are addressed by their position in `value.stops`, which is never\n * reordered — dragging one stop past another leaves both indices alone, so\n * a drag can cross a neighbour without the two swapping under the pointer.\n * Rendering sorts a copy.\n */\nexport function GradientEditor(props: GradientEditorProps): ReactElement {\n const { value, onInput, onChange, kindSwitch = true, spaceSwitch = true, svg = false, className } = props;\n const kind: PaintKind = value.fill ?? 'solid';\n const space: ColorSpace = (value as { interpolate?: ColorSpace }).interpolate ?? 'rgb';\n\n const entry = usePaintKind(kind);\n const kinds: readonly ToggleBarItem<PaintKind>[] = useGradientKinds()\n .filter((entry) => !svg || nativeSvgKind(entry.id) || entry.id === kind)\n .map((entry) => ({ value: entry.id, label: entry.label }));\n const spaces = SPACES.filter((item) => !svg || nativeSvgSpace(item.value) || item.value === space);\n\n const switchKind = (next: PaintKind): void => {\n const converted = switchGradientKind(value, next);\n if (converted && converted !== value) onChange(converted);\n };\n\n return (\n <div className={[s.root, className].filter(Boolean).join(' ')}>\n {kindSwitch && (\n <ToggleBar<PaintKind>\n items={kinds}\n value={kind}\n size=\"sm\"\n ariaLabel=\"Gradient kind\"\n onChange={(next) => next && switchKind(next)}\n />\n )}\n\n {renderBody()}\n </div>\n );\n\n function renderBody(): ReactElement {\n const spaceBar = spaceSwitch && spaces.length > 1 && (\n <ToggleBar<ColorSpace>\n items={spaces}\n value={space}\n size=\"sm\"\n ariaLabel=\"Blend space\"\n onChange={(next) => next && onChange({ ...value, interpolate: next } as FillStyle)}\n />\n );\n // A registered `Editor` wins even for a built-in id, as it does in `PaintInput`.\n if (entry?.Editor) {\n const Editor = entry.Editor;\n return <><Editor value={value} onInput={onInput} onChange={onChange} />{spaceBar}</>;\n }\n if (isGradientFill(value)) {\n return <StopsBody value={value} spaceBar={spaceBar} onInput={onInput} onChange={onChange} />;\n }\n if (isMeshPaint(value)) {\n return <><MeshEditor value={value} spaceSwitch={false} onInput={onInput} onChange={onChange} />{spaceBar}</>;\n }\n return <div className={s.noEditor}>{entry?.label ?? kind}: no editor</div>;\n }\n}\n\n/** The stop slider and swatch row of a linear, radial or conic gradient. */\nfunction StopsBody(props: {\n value: GradientFill;\n spaceBar: ReactNode;\n onInput?: (next: FillStyle) => void;\n onChange: (next: FillStyle) => void;\n}): ReactElement {\n const { value, spaceBar, onInput, onChange } = props;\n const stops = value.stops;\n const space = value.interpolate ?? 'rgb';\n\n const withStops = (next: GradStop[]): GradientFill => ({ ...value, stops: next });\n\n const thumbs: StopThumb[] = stops.map((stop) => ({ value: stop.offset, color: stop.color }));\n\n const applyThumbs = (next: StopThumb[]): GradStop[] =>\n next.map((t) => ({ offset: t.value, color: t.color }));\n\n const setStopColor = (index: number, color: string): GradStop[] =>\n stops.map((stop, i) => (i === index ? { ...stop, color } : stop));\n\n // Sorted view for the swatch row, carrying each stop's real index so a\n // recolor writes back to the right entry.\n const ordered = stops\n .map((stop, index) => ({ stop, index }))\n .sort((a, b) => a.stop.offset - b.stop.offset);\n\n return (\n <>\n <Slider<StopThumb>\n min={0}\n max={1}\n step={0.005}\n constraint=\"free\"\n thumbs={thumbs}\n ariaLabel=\"Gradient stops\"\n readoutPlacement=\"none\"\n onInput={(next) => onInput?.(withStops(applyThumbs(next)))}\n onChange={(next) => onChange(withStops(applyThumbs(next)))}\n onAddThumb={(at) => ({ value: at, color: sampleGradientStops(stops, at, space) })}\n onRemoveThumb={() => stops.length > MIN_STOPS}\n renderTrack={paintGradientTrack({\n gradient: (t) => sampleGradientStops(stops, t, space),\n // The track lerps between samples in sRGB whatever the gradient does,\n // so a hue arc needs more of them to not read as a straight line.\n samples: space === 'rgb' ? 32 : 64,\n })}\n />\n\n {spaceBar}\n\n <div className={s.swatches}>\n {ordered.map(({ stop, index }) => (\n <ColorField\n key={index}\n value={stop.color}\n alpha\n aria-label={`Stop ${index + 1} at ${Math.round(stop.offset * 100)}%`}\n className={s.swatch}\n onInput={(hex) => onInput?.(withStops(setStopColor(index, hex)))}\n onChange={(hex) => onChange(withStops(setStopColor(index, hex)))}\n />\n ))}\n </div>\n </>\n );\n}\n","import { type ReactElement, type ReactNode } from 'react';\nimport { gradientGeometry, type GradientFill } from '@weasel-js/core';\nimport { DragPoint, Guide, HandleOverlay, type EditPhase, type OverlayPoint as Point } from './handleOverlay';\nimport s from './handleOverlay.module.css';\n\n/**\n * Props for {@link GradientHandles}. `onInput` fires throughout a drag and\n * `onChange` once at its end.\n */\nexport interface GradientHandlesProps {\n /**\n * The gradient whose geometry these handles move, in a **resolved,\n * isotropic** frame — one where `radius` is a length in the same units as\n * `center.x` and a right angle is a right angle.\n *\n * A `units: 'bounds'` gradient is not such a frame: `x` and `y` are\n * fractions of two different lengths, so a circle there is an ellipse on\n * screen and polar math silently mixes scales. Resolve it first with\n * `fillInPoseFrame(fill, box)` and convert edits back with\n * `fillToBoundsFrame(next, box)`.\n */\n value: GradientFill;\n /**\n * Gradient space → overlay pixels. For a `units: 'local'` gradient this\n * is the node's local-to-screen transform; for `'world'`, the view.\n */\n toScreen: (p: Point) => Point;\n /** Overlay pixels → gradient space. Must invert `toScreen`. */\n toLocal: (p: Point) => Point;\n /** Live during a drag — wire for preview, do not write to history. */\n onInput?: (next: GradientFill) => void;\n /** Committed at drag end: one call per gesture. */\n onChange: (next: GradientFill) => void;\n /** Overlay size in CSS pixels. */\n width: number;\n height: number;\n className?: string;\n}\n\n/**\n * Direct-manipulation handles for a gradient's geometry, drawn as an SVG\n * overlay above a canvas: endpoints for linear, center and radius for\n * radial, center and angle arm for conic.\n *\n * Positioning is entirely the consumer's `toScreen` / `toLocal` — this\n * component never sees a view or a scene node, so the same handles serve a\n * node-local gradient, a world-space one, and a plain unzoomed preview.\n *\n * The overlay ignores pointer events except on the handles themselves, so\n * it can sit over live canvas content without swallowing tool input.\n */\nexport function GradientHandles(props: GradientHandlesProps): ReactElement {\n const { value, toScreen, toLocal, onInput, onChange, width, height, className } = props;\n\n return (\n <HandleOverlay width={width} height={height} className={className}>\n {renderForKind(value, toScreen, toLocal, onInput, onChange)}\n </HandleOverlay>\n );\n}\n\nfunction renderForKind(\n value: GradientFill,\n toScreen: (p: Point) => Point,\n toLocal: (p: Point) => Point,\n onInput: ((next: GradientFill) => void) | undefined,\n onChange: (next: GradientFill) => void,\n): ReactNode {\n const emit = (next: GradientFill, phase: EditPhase): void => {\n if (phase === 'input') onInput?.(next);\n else onChange(next);\n };\n\n if (value.fill === 'linear-gradient') {\n const from = toScreen(value.from);\n const to = toScreen(value.to);\n return (\n <>\n <Guide x1={from.x} y1={from.y} x2={to.x} y2={to.y} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={from}\n label=\"Gradient start\"\n onDrag={(p, phase) => emit({ ...value, from: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={to}\n label=\"Gradient end\"\n onDrag={(p, phase) => emit({ ...value, to: toLocal(p) }, phase)}\n />\n </>\n );\n }\n\n if (value.fill === 'radial-gradient') {\n const center = toScreen(value.center);\n // The radius handle rides the +x axis of gradient space, so it stays on\n // the drawn circle under a rotated or anisotropic transform.\n const edge = toScreen({ x: value.center.x + value.radius, y: value.center.y });\n const screenRadius = Math.hypot(edge.x - center.x, edge.y - center.y);\n return (\n <>\n <circle className={s.guide} cx={center.x} cy={center.y} r={screenRadius} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={center}\n label=\"Gradient center\"\n onDrag={(p, phase) => emit({ ...value, center: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={edge}\n label=\"Gradient radius\"\n onDrag={(p, phase) => {\n const local = toLocal(p);\n const radius = Math.hypot(local.x - value.center.x, local.y - value.center.y);\n emit({ ...value, radius: Math.max(MIN_RADIUS, radius) }, phase);\n }}\n />\n </>\n );\n }\n\n const center = toScreen(value.center);\n const { radius } = gradientGeometry(value);\n const tip = toScreen({\n x: value.center.x + Math.cos(value.angle) * radius,\n y: value.center.y + Math.sin(value.angle) * radius,\n });\n return (\n <>\n <Guide x1={center.x} y1={center.y} x2={tip.x} y2={tip.y} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={center}\n label=\"Gradient center\"\n onDrag={(p, phase) => emit({ ...value, center: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={tip}\n label=\"Gradient angle\"\n onDrag={(p, phase) => {\n const local = toLocal(p);\n const angle = Math.atan2(local.y - value.center.y, local.x - value.center.x);\n emit({ ...value, angle }, phase);\n }}\n />\n </>\n );\n}\n\n/** A radius of zero divides by zero in the shader's `t`; keep it off the floor. */\nconst MIN_RADIUS = 1;\n\nconst HANDLE_RADIUS = 7;\n","import { type ReactElement, type RefObject } from 'react';\nimport {\n fillInPoseFrame,\n fillToBoundsFrame,\n isGradientFill,\n useNodeOverlayFrame,\n useOngoingAction,\n type FillStyle,\n type GradientFill,\n type RectPose,\n type Scene,\n type Stroke,\n type View,\n} from '@weasel-js/core';\nimport { isMeshGradientFill, type MeshGradientFill } from '@weasel-js/core/mesh';\nimport { MeshHandles } from '../MeshEditor/MeshHandles';\nimport { GradientHandles } from './GradientHandles';\n\n/** The paint slots a node carries. Either may hold a gradient, and each has\n * its own action, so the overlay is told which one it is editing. */\nexport type PaintSlot = 'fill' | 'stroke';\n\n/** What `SceneGradientHandles` reads off a node. Every field is optional, so\n * any richer app data shape satisfies it. */\nexport interface PaintedNodeData {\n fill?: FillStyle | null;\n stroke?: Stroke | null;\n}\n\n/** Props for {@link SceneGradientHandles}. */\nexport interface SceneGradientHandlesProps<\n TData extends PaintedNodeData,\n TLayer extends string,\n TPose extends RectPose,\n> {\n scene: Scene<TData, TLayer, TPose>;\n /** The element the overlay is positioned in. Must be the canvas's own box,\n * or the handles land somewhere other than the paint. */\n containerRef: RefObject<HTMLElement | null>;\n /** The node whose paint is being edited — usually the lone selected id. */\n nodeId: string | null | undefined;\n /** Which of the node's two paints these handles move. */\n slot: PaintSlot;\n /** Current viewport; a thunk is re-read per projection. See\n * `useNodeOverlayFrame`. */\n view?: View | (() => View);\n className?: string;\n}\n\n/**\n * Scene-aware paint handles: on-canvas geometry handles for the gradient in\n * one node's `fill` or `stroke` — `GradientHandles` for the three ramps,\n * `MeshHandles` for a mesh — committed through the `setFill` / `setStroke`\n * actions as a single undo entry per drag.\n *\n * Renders nothing unless the targeted slot holds a gradient or a mesh. The\n * node stores its gradient in `units: 'bounds'` — fractions of its own box, so the paint\n * survives pan, zoom and resize — which is not a frame polar math can work\n * in; the handles get it resolved onto the box and every edit is normalized\n * back on the way out.\n *\n * `slot` is a prop rather than state the kit keeps: an app that edits fill\n * and stroke separately already knows which one has focus.\n */\nexport function SceneGradientHandles<\n TData extends PaintedNodeData,\n TLayer extends string,\n TPose extends RectPose,\n>(props: SceneGradientHandlesProps<TData, TLayer, TPose>): ReactElement | null {\n const { scene, containerRef, nodeId, slot, view, className } = props;\n const frame = useNodeOverlayFrame(scene, containerRef, nodeId, { view });\n const edit = useOngoingAction(slot === 'fill' ? 'setFill' : 'setStroke');\n\n const paint = frame ? paintOf(scene, nodeId, slot) : null;\n if (!frame || !paint) return null;\n\n const dispatch = (next: FillStyle, phase: 'input' | 'commit'): void => {\n const normalized = fillToBoundsFrame(next, frame.box);\n if (phase === 'commit') edit.commit({ paint: normalized });\n else edit.input({ paint: normalized });\n };\n const common = {\n toScreen: frame.toScreen,\n toLocal: frame.toLocal,\n width: frame.width,\n height: frame.height,\n className,\n onInput: (next: FillStyle) => dispatch(next, 'input'),\n onChange: (next: FillStyle) => dispatch(next, 'commit'),\n };\n\n if (isGradientFill(paint)) {\n return <GradientHandles value={fillInPoseFrame(paint, frame.box) as GradientFill} {...common} />;\n }\n if (isMeshGradientFill(paint)) {\n const resolved = fillInPoseFrame(paint, frame.box) as unknown as MeshGradientFill;\n // Still in the bounds frame means the mesh kind has not loaded, and\n // handles drawn now would sit in fractions of the box.\n if (resolved.units === 'bounds') return null;\n return <MeshHandles value={resolved} {...common} />;\n }\n return null;\n}\n\nfunction paintOf<TData extends PaintedNodeData, TLayer extends string, TPose extends RectPose>(\n scene: Scene<TData, TLayer, TPose>,\n nodeId: string | null | undefined,\n slot: PaintSlot,\n): FillStyle | null | undefined {\n if (nodeId == null) return undefined;\n const data = (scene.nodes as ReadonlyMap<string, { data: TData }>).get(nodeId)?.data;\n if (!data) return undefined;\n return slot === 'fill' ? data.fill : data.stroke?.paint;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"GradientEditor-DX4sb1Hf.js","names":["s","_Fragment","_Fragment","s","ColorField","ToggleBar","handleOverlay_module_default","DragPoint","Guide","isMeshPaint","MeshHandles","DEFAULT_HATCH","paintGradientTrack","opts","stops","i","samples","t","gradient","ctx","baseGradient","layers","activeRange","low","high","h","hatch","stripe","dimColor","dimOverlay","wL","wR","style","GradientEditor_module_default","SPACES","MIN_STOPS","GradientEditor","props","kind","value","space","entry","usePaintKind","kinds","useGradientKinds","svg","nativeSvgKind","spaces","nativeSvgSpace","item","switchKind","converted","switchGradientKind","next","onChange","className","kindSwitch","renderBody","spaceBar","spaceSwitch","Editor","Fragment","isGradientFill","StopsBody","MeshEditor","withStops","thumbs","stop","applyThumbs","setStopColor","index","ordered","a","b","Slider","onInput","at","sampleGradientStops","hex","GradientHandles","HandleOverlay","renderForKind","toScreen","toLocal","emit","phase","from","to","HANDLE_RADIUS","p","center","edge","screenRadius","local","radius","MIN_RADIUS","gradientGeometry","tip","angle","SceneGradientHandles","frame","useNodeOverlayFrame","scene","containerRef","nodeId","edit","useOngoingAction","slot","paint","paintOf","dispatch","normalized","fillToBoundsFrame","common","fillInPoseFrame","isMeshGradientFill","resolved","data"],"sources":["../../src/paintGradientTrack.tsx","../../src/components/GradientEditor/GradientEditor.module.css","../../src/components/GradientEditor/GradientEditor.tsx","../../src/components/GradientEditor/GradientHandles.tsx","../../src/components/GradientEditor/SceneGradientHandles.tsx"],"sourcesContent":["import type { ReactNode, CSSProperties } from 'react';\nimport type { TrackCtx } from './components/Slider';\n\n/**\n * Options for {@link paintGradientTrack}.\n *\n * `gradient` maps a normalized position along the slider's value span (0 to\n * 1) to a CSS color; `samples` is how many stops the resulting\n * linear-gradient uses. The ramp is laid on the same span as the thumbs, so a\n * thumb at 0.3 sits over `gradient(0.3)`; any track beyond the span takes the\n * end colors.\n * `activeRange`, given in the slider's own value units, keeps that span at\n * full strength and dims + hatches the rest.\n */\nexport type GradientTrackOpts = {\n gradient: (t: number) => string;\n samples?: number;\n activeRange?: [number, number];\n hatch?: {\n angleDeg?: number;\n stripe?: number;\n gap?: number;\n dim?: number;\n };\n};\n\nconst DEFAULT_HATCH = { angleDeg: 135, stripe: 2, gap: 4, dim: 75 };\n\n/**\n * Builds a `Slider` `renderTrack` function that paints the track as a\n * sampled color gradient, optionally dimming and hatching the portions\n * outside an active range.\n */\nexport function paintGradientTrack(opts: GradientTrackOpts): (ctx: TrackCtx) => ReactNode {\n const { gradient, samples = 16, activeRange, hatch } = opts;\n\n return (ctx: TrackCtx) => {\n const stops: string[] = [];\n for (let i = 0; i <= samples; i++) {\n const t = i / samples;\n stops.push(`${gradient(t)} ${ctx.fractionToPosition(t)}`);\n }\n const baseGradient = `linear-gradient(to right, ${stops.join(', ')})`;\n\n const layers: string[] = [];\n if (activeRange) {\n const low = ctx.valueToFraction(activeRange[0]);\n const high = ctx.valueToFraction(activeRange[1]);\n const h = { ...DEFAULT_HATCH, ...hatch };\n const stripe = `repeating-linear-gradient(${h.angleDeg}deg, transparent 0 ${h.stripe}px, var(--wzl-surface) ${h.stripe}px ${h.stripe + h.gap}px)`;\n const dimColor = `color-mix(in srgb, var(--wzl-surface) ${h.dim}%, transparent)`;\n const dimOverlay = `linear-gradient(${dimColor}, ${dimColor})`;\n\n if (low > 0) {\n const wL = ctx.fractionToPosition(low);\n layers.push(`${dimOverlay} left 0 / ${wL} 100% no-repeat`);\n layers.push(`${stripe} left 0 / ${wL} 100% no-repeat`);\n }\n if (high < 1) {\n const wR = `calc(100% - ${ctx.fractionToPosition(high)})`;\n layers.push(`${dimOverlay} right 0 / ${wR} 100% no-repeat`);\n layers.push(`${stripe} right 0 / ${wR} 100% no-repeat`);\n }\n }\n layers.push(baseGradient);\n\n const style: CSSProperties = {\n position: 'absolute',\n inset: 0,\n background: layers.join(', '),\n };\n return <div style={style} />;\n };\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n min-inline-size: 0;\n}\n\n.swatches {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-3);\n}\n\n/* Each stop's opacity slider would otherwise stretch the row to a width no\n * properties panel has; the chip stays legible, the slider yields. */\n.swatch {\n flex: 0 1 auto;\n min-inline-size: 0;\n}\n\n.noEditor {\n font-size: var(--wzl-font-size-sm);\n color: var(--wzl-fg-muted);\n}\n","import { type ReactElement, type ReactNode } from 'react';\nimport {\n isGradientFill,\n sampleGradientStops,\n switchGradientKind,\n useGradientKinds,\n usePaintKind,\n type ColorSpace,\n type FillStyle,\n type GradStop,\n type GradientFill,\n type PaintKind,\n} from '@weasel-js/core';\nimport { nativeSvgKind, nativeSvgSpace } from '@weasel-js/svg';\nimport { Slider, type Thumb } from '../Slider';\nimport { ColorField } from '../ColorField';\nimport { MeshEditor, isMeshPaint } from '../MeshEditor';\nimport { ToggleBar, type ToggleBarItem } from '../ToggleBar';\nimport { paintGradientTrack } from '../../paintGradientTrack';\nimport s from './GradientEditor.module.css';\n\nconst SPACES: readonly ToggleBarItem<ColorSpace>[] = [\n { value: 'rgb', label: 'sRGB' },\n { value: 'oklab', label: 'OKLab' },\n { value: 'oklch', label: 'OKLCh' },\n];\n\n/** Fewer than two stops is not a gradient any renderer can ramp between. */\nconst MIN_STOPS = 2;\n\n/**\n * Props for {@link GradientEditor}. `onInput` fires throughout a gesture and\n * `onChange` once at its end.\n */\nexport interface GradientEditorProps {\n /** The gradient being edited: a paint of any gradient kind — one that\n * `listGradientKinds` returns. */\n value: FillStyle;\n /**\n * Live value during a gesture — a stop drag, a color-picker scrub. Wire\n * it for preview; it fires many times per gesture and must not be\n * written to history.\n */\n onInput?: (next: FillStyle) => void;\n /** Committed value: one call per completed gesture. Pair with an\n * undoable write. */\n onChange: (next: FillStyle) => void;\n /** Show the kind switch — every registered gradient kind. Default true;\n * turn it off when the surrounding UI already owns the kind. */\n kindSwitch?: boolean;\n /** Show the sRGB / OKLab / OKLCh switch, which writes `interpolate`.\n * Default true. */\n spaceSwitch?: boolean;\n /**\n * Offer only what an SVG file carries natively: the linear and radial\n * gradients, which SVG has elements for, blended in sRGB, the only space\n * every SVG renderer honors. A conic or mesh gradient exports as a weasel\n * element that other renderers paint as one flat color, and an OKLab or\n * OKLCh blend exports as an attribute they ignore. A value already outside\n * that set keeps its own kind and space on offer, so it can be switched\n * back. Default false.\n */\n svg?: boolean;\n className?: string;\n}\n\ntype StopThumb = Thumb & { color: string };\n\n/**\n * Editor for a gradient's kind and colors: the stop list of a linear, radial\n * or conic gradient, a mesh's corner colors, or a registered kind's own\n * `Editor`. Switching kind goes through `switchGradientKind`, so the colors\n * carry across.\n *\n * Geometry (`from`/`to`, `center`, `radius`, `angle`) is deliberately not\n * edited here — on a canvas that belongs on the artwork, via\n * `<GradientHandles>`. This component owns the parts with no spatial\n * meaning, so it composes into a properties panel at any width.\n *\n * Stops are addressed by their position in `value.stops`, which is never\n * reordered — dragging one stop past another leaves both indices alone, so\n * a drag can cross a neighbour without the two swapping under the pointer.\n * Rendering sorts a copy.\n */\nexport function GradientEditor(props: GradientEditorProps): ReactElement {\n const { value, onInput, onChange, kindSwitch = true, spaceSwitch = true, svg = false, className } = props;\n const kind: PaintKind = value.fill ?? 'solid';\n const space: ColorSpace = (value as { interpolate?: ColorSpace }).interpolate ?? 'rgb';\n\n const entry = usePaintKind(kind);\n const kinds: readonly ToggleBarItem<PaintKind>[] = useGradientKinds()\n .filter((entry) => !svg || nativeSvgKind(entry.id) || entry.id === kind)\n .map((entry) => ({ value: entry.id, label: entry.label }));\n const spaces = SPACES.filter((item) => !svg || nativeSvgSpace(item.value) || item.value === space);\n\n const switchKind = (next: PaintKind): void => {\n const converted = switchGradientKind(value, next);\n if (converted && converted !== value) onChange(converted);\n };\n\n return (\n <div className={[s.root, className].filter(Boolean).join(' ')}>\n {kindSwitch && (\n <ToggleBar<PaintKind>\n items={kinds}\n value={kind}\n size=\"sm\"\n ariaLabel=\"Gradient kind\"\n onChange={(next) => next && switchKind(next)}\n />\n )}\n\n {renderBody()}\n </div>\n );\n\n function renderBody(): ReactElement {\n const spaceBar = spaceSwitch && spaces.length > 1 && (\n <ToggleBar<ColorSpace>\n items={spaces}\n value={space}\n size=\"sm\"\n ariaLabel=\"Blend space\"\n onChange={(next) => next && onChange({ ...value, interpolate: next } as FillStyle)}\n />\n );\n // A registered `Editor` wins even for a built-in id, as it does in `PaintInput`.\n if (entry?.Editor) {\n const Editor = entry.Editor;\n return <><Editor value={value} onInput={onInput} onChange={onChange} />{spaceBar}</>;\n }\n if (isGradientFill(value)) {\n return <StopsBody value={value} spaceBar={spaceBar} onInput={onInput} onChange={onChange} />;\n }\n if (isMeshPaint(value)) {\n return <><MeshEditor value={value} spaceSwitch={false} onInput={onInput} onChange={onChange} />{spaceBar}</>;\n }\n return <div className={s.noEditor}>{entry?.label ?? kind}: no editor</div>;\n }\n}\n\n/** The stop slider and swatch row of a linear, radial or conic gradient. */\nfunction StopsBody(props: {\n value: GradientFill;\n spaceBar: ReactNode;\n onInput?: (next: FillStyle) => void;\n onChange: (next: FillStyle) => void;\n}): ReactElement {\n const { value, spaceBar, onInput, onChange } = props;\n const stops = value.stops;\n const space = value.interpolate ?? 'rgb';\n\n const withStops = (next: GradStop[]): GradientFill => ({ ...value, stops: next });\n\n const thumbs: StopThumb[] = stops.map((stop) => ({ value: stop.offset, color: stop.color }));\n\n const applyThumbs = (next: StopThumb[]): GradStop[] =>\n next.map((t) => ({ offset: t.value, color: t.color }));\n\n const setStopColor = (index: number, color: string): GradStop[] =>\n stops.map((stop, i) => (i === index ? { ...stop, color } : stop));\n\n // Sorted view for the swatch row, carrying each stop's real index so a\n // recolor writes back to the right entry.\n const ordered = stops\n .map((stop, index) => ({ stop, index }))\n .sort((a, b) => a.stop.offset - b.stop.offset);\n\n return (\n <>\n <Slider<StopThumb>\n min={0}\n max={1}\n step={0.005}\n constraint=\"free\"\n thumbs={thumbs}\n ariaLabel=\"Gradient stops\"\n readoutPlacement=\"none\"\n onInput={(next) => onInput?.(withStops(applyThumbs(next)))}\n onChange={(next) => onChange(withStops(applyThumbs(next)))}\n onAddThumb={(at) => ({ value: at, color: sampleGradientStops(stops, at, space) })}\n onRemoveThumb={() => stops.length > MIN_STOPS}\n renderTrack={paintGradientTrack({\n gradient: (t) => sampleGradientStops(stops, t, space),\n // The track lerps between samples in sRGB whatever the gradient does,\n // so a hue arc needs more of them to not read as a straight line.\n samples: space === 'rgb' ? 32 : 64,\n })}\n />\n\n {spaceBar}\n\n <div className={s.swatches}>\n {ordered.map(({ stop, index }) => (\n <ColorField\n key={index}\n value={stop.color}\n alpha\n aria-label={`Stop ${index + 1} at ${Math.round(stop.offset * 100)}%`}\n className={s.swatch}\n onInput={(hex) => onInput?.(withStops(setStopColor(index, hex)))}\n onChange={(hex) => onChange(withStops(setStopColor(index, hex)))}\n />\n ))}\n </div>\n </>\n );\n}\n","import { type ReactElement, type ReactNode } from 'react';\nimport { gradientGeometry, type GradientFill } from '@weasel-js/core';\nimport { DragPoint, Guide, HandleOverlay, type EditPhase, type OverlayPoint as Point } from './handleOverlay';\nimport s from './handleOverlay.module.css';\n\n/**\n * Props for {@link GradientHandles}. `onInput` fires throughout a drag and\n * `onChange` once at its end.\n */\nexport interface GradientHandlesProps {\n /**\n * The gradient whose geometry these handles move, in a **resolved,\n * isotropic** frame — one where `radius` is a length in the same units as\n * `center.x` and a right angle is a right angle.\n *\n * A `units: 'bounds'` gradient is not such a frame: `x` and `y` are\n * fractions of two different lengths, so a circle there is an ellipse on\n * screen and polar math silently mixes scales. Resolve it first with\n * `fillInPoseFrame(fill, box)` and convert edits back with\n * `fillToBoundsFrame(next, box)`.\n */\n value: GradientFill;\n /**\n * Gradient space → overlay pixels. For a `units: 'local'` gradient this\n * is the node's local-to-screen transform; for `'world'`, the view.\n */\n toScreen: (p: Point) => Point;\n /** Overlay pixels → gradient space. Must invert `toScreen`. */\n toLocal: (p: Point) => Point;\n /** Live during a drag — wire for preview, do not write to history. */\n onInput?: (next: GradientFill) => void;\n /** Committed at drag end: one call per gesture. */\n onChange: (next: GradientFill) => void;\n /** Overlay size in CSS pixels. */\n width: number;\n height: number;\n className?: string;\n}\n\n/**\n * Direct-manipulation handles for a gradient's geometry, drawn as an SVG\n * overlay above a canvas: endpoints for linear, center and radius for\n * radial, center and angle arm for conic.\n *\n * Positioning is entirely the consumer's `toScreen` / `toLocal` — this\n * component never sees a view or a scene node, so the same handles serve a\n * node-local gradient, a world-space one, and a plain unzoomed preview.\n *\n * The overlay ignores pointer events except on the handles themselves, so\n * it can sit over live canvas content without swallowing tool input.\n */\nexport function GradientHandles(props: GradientHandlesProps): ReactElement {\n const { value, toScreen, toLocal, onInput, onChange, width, height, className } = props;\n\n return (\n <HandleOverlay width={width} height={height} className={className}>\n {renderForKind(value, toScreen, toLocal, onInput, onChange)}\n </HandleOverlay>\n );\n}\n\nfunction renderForKind(\n value: GradientFill,\n toScreen: (p: Point) => Point,\n toLocal: (p: Point) => Point,\n onInput: ((next: GradientFill) => void) | undefined,\n onChange: (next: GradientFill) => void,\n): ReactNode {\n const emit = (next: GradientFill, phase: EditPhase): void => {\n if (phase === 'input') onInput?.(next);\n else onChange(next);\n };\n\n if (value.fill === 'linear-gradient') {\n const from = toScreen(value.from);\n const to = toScreen(value.to);\n return (\n <>\n <Guide x1={from.x} y1={from.y} x2={to.x} y2={to.y} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={from}\n label=\"Gradient start\"\n onDrag={(p, phase) => emit({ ...value, from: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={to}\n label=\"Gradient end\"\n onDrag={(p, phase) => emit({ ...value, to: toLocal(p) }, phase)}\n />\n </>\n );\n }\n\n if (value.fill === 'radial-gradient') {\n const center = toScreen(value.center);\n // The radius handle rides the +x axis of gradient space, so it stays on\n // the drawn circle under a rotated or anisotropic transform.\n const edge = toScreen({ x: value.center.x + value.radius, y: value.center.y });\n const screenRadius = Math.hypot(edge.x - center.x, edge.y - center.y);\n return (\n <>\n <circle className={s.guide} cx={center.x} cy={center.y} r={screenRadius} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={center}\n label=\"Gradient center\"\n onDrag={(p, phase) => emit({ ...value, center: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={edge}\n label=\"Gradient radius\"\n onDrag={(p, phase) => {\n const local = toLocal(p);\n const radius = Math.hypot(local.x - value.center.x, local.y - value.center.y);\n emit({ ...value, radius: Math.max(MIN_RADIUS, radius) }, phase);\n }}\n />\n </>\n );\n }\n\n const center = toScreen(value.center);\n const { radius } = gradientGeometry(value);\n const tip = toScreen({\n x: value.center.x + Math.cos(value.angle) * radius,\n y: value.center.y + Math.sin(value.angle) * radius,\n });\n return (\n <>\n <Guide x1={center.x} y1={center.y} x2={tip.x} y2={tip.y} />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={center}\n label=\"Gradient center\"\n onDrag={(p, phase) => emit({ ...value, center: toLocal(p) }, phase)}\n />\n <DragPoint\n radius={HANDLE_RADIUS}\n at={tip}\n label=\"Gradient angle\"\n onDrag={(p, phase) => {\n const local = toLocal(p);\n const angle = Math.atan2(local.y - value.center.y, local.x - value.center.x);\n emit({ ...value, angle }, phase);\n }}\n />\n </>\n );\n}\n\n/** A radius of zero divides by zero in the shader's `t`; keep it off the floor. */\nconst MIN_RADIUS = 1;\n\nconst HANDLE_RADIUS = 7;\n","import { type ReactElement, type RefObject } from 'react';\nimport {\n fillInPoseFrame,\n fillToBoundsFrame,\n isGradientFill,\n useNodeOverlayFrame,\n useOngoingAction,\n type FillStyle,\n type GradientFill,\n type RectPose,\n type Scene,\n type Stroke,\n type View,\n} from '@weasel-js/core';\nimport { isMeshGradientFill, type MeshGradientFill } from '@weasel-js/core/mesh';\nimport { MeshHandles } from '../MeshEditor/MeshHandles';\nimport { GradientHandles } from './GradientHandles';\n\n/** The paint slots a node carries. Either may hold a gradient, and each has\n * its own action, so the overlay is told which one it is editing. */\nexport type PaintSlot = 'fill' | 'stroke';\n\n/** What `SceneGradientHandles` reads off a node. Every field is optional, so\n * any richer app data shape satisfies it. */\nexport interface PaintedNodeData {\n fill?: FillStyle | null;\n stroke?: Stroke | null;\n}\n\n/** Props for {@link SceneGradientHandles}. */\nexport interface SceneGradientHandlesProps<\n TData extends PaintedNodeData,\n TLayer extends string,\n TPose extends RectPose,\n> {\n scene: Scene<TData, TLayer, TPose>;\n /** The element the overlay is positioned in. Must be the canvas's own box,\n * or the handles land somewhere other than the paint. */\n containerRef: RefObject<HTMLElement | null>;\n /** The node whose paint is being edited — usually the lone selected id. */\n nodeId: string | null | undefined;\n /** Which of the node's two paints these handles move. */\n slot: PaintSlot;\n /** Current viewport; a thunk is re-read per projection. See\n * `useNodeOverlayFrame`. */\n view?: View | (() => View);\n className?: string;\n}\n\n/**\n * Scene-aware paint handles: on-canvas geometry handles for the gradient in\n * one node's `fill` or `stroke` — `GradientHandles` for the three ramps,\n * `MeshHandles` for a mesh — committed through the `setFill` / `setStroke`\n * actions as a single undo entry per drag.\n *\n * Renders nothing unless the targeted slot holds a gradient or a mesh. The\n * node stores its gradient in `units: 'bounds'` — fractions of its own box, so the paint\n * survives pan, zoom and resize — which is not a frame polar math can work\n * in; the handles get it resolved onto the box and every edit is normalized\n * back on the way out.\n *\n * `slot` is a prop rather than state the kit keeps: an app that edits fill\n * and stroke separately already knows which one has focus.\n */\nexport function SceneGradientHandles<\n TData extends PaintedNodeData,\n TLayer extends string,\n TPose extends RectPose,\n>(props: SceneGradientHandlesProps<TData, TLayer, TPose>): ReactElement | null {\n const { scene, containerRef, nodeId, slot, view, className } = props;\n const frame = useNodeOverlayFrame(scene, containerRef, nodeId, { view });\n const edit = useOngoingAction(slot === 'fill' ? 'setFill' : 'setStroke');\n\n const paint = frame ? paintOf(scene, nodeId, slot) : null;\n if (!frame || !paint) return null;\n\n const dispatch = (next: FillStyle, phase: 'input' | 'commit'): void => {\n const normalized = fillToBoundsFrame(next, frame.box);\n if (phase === 'commit') edit.commit({ paint: normalized });\n else edit.input({ paint: normalized });\n };\n const common = {\n toScreen: frame.toScreen,\n toLocal: frame.toLocal,\n width: frame.width,\n height: frame.height,\n className,\n onInput: (next: FillStyle) => dispatch(next, 'input'),\n onChange: (next: FillStyle) => dispatch(next, 'commit'),\n };\n\n if (isGradientFill(paint)) {\n return <GradientHandles value={fillInPoseFrame(paint, frame.box) as GradientFill} {...common} />;\n }\n if (isMeshGradientFill(paint)) {\n const resolved = fillInPoseFrame(paint, frame.box) as unknown as MeshGradientFill;\n // Still in the bounds frame means the mesh kind has not loaded, and\n // handles drawn now would sit in fractions of the box.\n if (resolved.units === 'bounds') return null;\n return <MeshHandles value={resolved} {...common} />;\n }\n return null;\n}\n\nfunction paintOf<TData extends PaintedNodeData, TLayer extends string, TPose extends RectPose>(\n scene: Scene<TData, TLayer, TPose>,\n nodeId: string | null | undefined,\n slot: PaintSlot,\n): FillStyle | null | undefined {\n if (nodeId == null) return undefined;\n const data = (scene.nodes as ReadonlyMap<string, { data: TData }>).get(nodeId)?.data;\n if (!data) return undefined;\n return slot === 'fill' ? data.fill : data.stroke?.paint;\n}\n"],"mappings":"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"}
@@ -9,6 +9,9 @@ var n = {
9
9
  zoomIn: "<circle cx=\"9\" cy=\"9\" r=\"5.4\"/><path d=\"M12.82 12.82 16.9 16.9\"/><path d=\"M9 6.7v4.6M6.7 9h4.6\"/>",
10
10
  zoomOut: "<circle cx=\"9\" cy=\"9\" r=\"5.4\"/><path d=\"M12.82 12.82 16.9 16.9\"/><path d=\"M6.7 9h4.6\"/>",
11
11
  fit: "<path d=\"M3.2 7.2V4.4A1.2 1.2 0 0 1 4.4 3.2h2.8M12.8 3.2h2.8A1.2 1.2 0 0 1 16.8 4.4v2.8M16.8 12.8v2.8a1.2 1.2 0 0 1-1.2 1.2h-2.8M7.2 16.8H4.4a1.2 1.2 0 0 1-1.2-1.2v-2.8\"/><rect x=\"7.4\" y=\"8.2\" width=\"5.2\" height=\"3.6\" rx=\"0.8\" stroke-width=\"1\"/>",
12
+ fitContain: "<rect x=\"1.875\" y=\"5.625\" width=\"16.25\" height=\"8.75\" rx=\"1\" stroke-width=\"1.25\"/><ellipse cx=\"10\" cy=\"10\" rx=\"3\" ry=\"3\"/>",
13
+ fitFill: "<rect x=\"1.875\" y=\"5.625\" width=\"16.25\" height=\"8.75\" rx=\"1\" stroke-width=\"1.25\"/><ellipse cx=\"10\" cy=\"10\" rx=\"6.75\" ry=\"6.75\"/>",
14
+ fitStretch: "<rect x=\"1.875\" y=\"5.625\" width=\"16.25\" height=\"8.75\" rx=\"1\" stroke-width=\"1.25\"/><ellipse cx=\"10\" cy=\"10\" rx=\"6.13\" ry=\"2.38\"/>",
12
15
  pan: "<path d=\"M10 8.1V3.2M10 11.9V16.8M8.1 10H3.2M11.9 10H16.8\"/><path d=\"M8.26 5.27 10 3.2 11.74 5.27M11.74 14.73 10 16.8 8.26 14.73M5.27 11.74 3.2 10 5.27 8.26M14.73 8.26 16.8 10 14.73 11.74\"/><circle cx=\"10\" cy=\"10\" r=\"1.9\"/>",
13
16
  filter: "<path d=\"M3.4 4.6h13.2L11.8 11v5.4L8.2 14.8V11z\"/>",
14
17
  add: "<path d=\"M10 4.9v10.2M4.9 10h10.2\"/>",
@@ -43,6 +46,7 @@ var n = {
43
46
  visible: "<path d=\"M2.6 10C4.6 6.6 7.1 5 10 5s5.4 1.6 7.4 5c-2 3.4-4.5 5-7.4 5s-5.4-1.6-7.4-5z\"/><circle cx=\"10\" cy=\"10\" r=\"2.2\"/>",
44
47
  hidden: "<path d=\"M2.6 10C4.6 6.6 7.1 5 10 5s5.4 1.6 7.4 5c-2 3.4-4.5 5-7.4 5s-5.4-1.6-7.4-5z\"/><circle cx=\"10\" cy=\"10\" r=\"2.2\"/><path d=\"M4.2 15.8 15.8 4.2\"/>",
45
48
  pin: "<path d=\"M8.2 3.4v5.2l-2 2.6h7.6l-2-2.6V3.4z\"/><path d=\"M7 3.4h6\"/><path d=\"M10 11.2v5.4\"/>",
49
+ bookmark: "<path d=\"M5.7 16.6V4.8a1.4 1.4 0 0 1 1.4-1.4h5.8a1.4 1.4 0 0 1 1.4 1.4V16.6L10 13.2Z\"/>",
46
50
  info: "<circle cx=\"10\" cy=\"10\" r=\"7\"/><path d=\"M10 9.4v4.4\"/><path d=\"M10 6.5h0\"/>",
47
51
  warning: "<path d=\"M10 3.4 17.4 16.2H2.6z\"/><path d=\"M10 8.4v3.4\"/><path d=\"M10 14h0\"/>",
48
52
  error: "<circle cx=\"10\" cy=\"10\" r=\"7\"/><path d=\"M7.6 7.6 12.4 12.4M12.4 7.6 7.6 12.4\"/>",
@@ -55,6 +59,15 @@ var n = {
55
59
  statusAccent: "<circle cx=\"10\" cy=\"10\" r=\"7\" fill=\"currentColor\"/>",
56
60
  statusNeutral: "<path d=\"M10 3A7 7 0 0 1 10 17Z\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"10\" cy=\"10\" r=\"7\"/>",
57
61
  statusMuted: "<path d=\"M11.44 3.15A7 7 0 0 0 8.56 3.15M4.79 5.33A7 7 0 0 0 3.35 7.82M3.35 12.18A7 7 0 0 0 4.79 14.67M8.56 16.85A7 7 0 0 0 11.44 16.85M15.21 14.67A7 7 0 0 0 16.65 12.18M16.65 7.82A7 7 0 0 0 15.21 5.33\"/>",
62
+ variantSolid: "<path d=\"M5.25 5H14.75A3.25 3.25 0 0 1 18 8.25V11.75A3.25 3.25 0 0 1 14.75 15H5.25A3.25 3.25 0 0 1 2 11.75V8.25A3.25 3.25 0 0 1 5.25 5ZM6.75 9.25H13.25A0.75 0.75 0 0 1 14 10V10A0.75 0.75 0 0 1 13.25 10.75H6.75A0.75 0.75 0 0 1 6 10V10A0.75 0.75 0 0 1 6.75 9.25Z\" fill=\"currentColor\" fill-rule=\"evenodd\" stroke=\"none\"/>",
63
+ variantOutline: "<rect x=\"2.75\" y=\"5.75\" width=\"14.5\" height=\"8.5\" rx=\"2.5\"/><path d=\"M6.75 10h6.5\"/>",
64
+ variantSubtle: "<path d=\"M5.25 5H14.75A3.25 3.25 0 0 1 18 8.25V11.75A3.25 3.25 0 0 1 14.75 15H5.25A3.25 3.25 0 0 1 2 11.75V8.25A3.25 3.25 0 0 1 5.25 5Z\" fill=\"currentColor\" fill-opacity=\"0.32\" stroke=\"none\"/><path d=\"M6.75 10h6.5\"/>",
65
+ variantGhost: "<rect x=\"2.75\" y=\"5.75\" width=\"14.5\" height=\"8.5\" rx=\"2.5\" stroke-dasharray=\"1.56 1.92\"/><path d=\"M6.75 10h6.5\"/>",
66
+ variantLink: "<path d=\"M6.75 10h6.5\"/><path d=\"M4.75 13.125h10.5\" stroke-width=\"1.25\"/>",
67
+ variantPlain: "<path d=\"M6.75 10h6.5\"/>",
68
+ variantSegmented: "<rect x=\"2.75\" y=\"6.75\" width=\"14.5\" height=\"6.5\" rx=\"3.25\"/><rect x=\"7.25\" y=\"8.5\" width=\"5.5\" height=\"3\" rx=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>",
69
+ variantSegmentedMinimal: "<rect x=\"7.25\" y=\"8.5\" width=\"5.5\" height=\"3\" rx=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M3.75 10h1.5M14.75 10h1.5\"/>",
70
+ variantSegmentedFlat: "<rect x=\"2.75\" y=\"6.75\" width=\"14.5\" height=\"6.5\" rx=\"1\"/><path d=\"M7.58 6.75v6.5M12.42 6.75v6.5\"/><rect x=\"7.58\" y=\"6.75\" width=\"4.84\" height=\"6.5\" fill=\"currentColor\" stroke=\"none\"/>",
58
71
  crosshair: "<circle cx=\"10\" cy=\"10\" r=\"5.6\"/><path d=\"M10 2.8v4.4M10 12.8v4.4M2.8 10h4.4M12.8 10h4.4\"/>",
59
72
  fullscreen: "<path d=\"M11.6 3.6h4.8v4.8M8.4 16.4H3.6v-4.8\"/><path d=\"M16.4 3.6 11.2 8.8M3.6 16.4 8.8 11.2\"/>",
60
73
  compare: "<rect x=\"3.4\" y=\"4.6\" width=\"13.2\" height=\"10.8\" rx=\"1.6\"/><path d=\"M10 4.6v10.8\" stroke-width=\"1\"/><path d=\"M5.2 7.6h3.4M5.2 10h2.6M5.2 12.4h3.4\" stroke-width=\"1\"/><path d=\"M11.4 7.6h3.4M11.4 10h3.4M11.4 12.4h1.8\" stroke-width=\"1\"/>",
@@ -224,6 +237,7 @@ var n = {
224
237
  d12: "<path d=\"M2.96 7.71L5.65 4.01L10 2.6L14.35 4.01L17.04 7.71L17.04 12.29L14.35 15.99L10 17.4L5.65 15.99L2.96 12.29Z\" stroke-linejoin=\"miter\" stroke-width=\"1\"/><path d=\"M10 5.43L10 2.6M14.35 8.59L10 5.43M17.04 7.71L14.35 8.59M14.35 8.59L12.69 13.7M5.65 8.59L10 5.43M7.31 13.7L5.65 8.59M12.69 13.7L7.31 13.7M5.65 8.59L2.96 7.71M14.35 15.99L12.69 13.7M5.65 15.99L7.31 13.7\" stroke-width=\"0.6\"/>",
225
238
  d20: "<path d=\"M3.59 13.7L3.59 6.3L10 2.6L16.41 6.3L16.41 13.7L10 17.4Z\" stroke-linejoin=\"miter\" stroke-width=\"1\"/><path d=\"M10 5.43L13.96 12.29M6.04 12.29L10 5.43M13.96 12.29L6.04 12.29M3.59 6.3L10 5.43M6.04 12.29L3.59 6.3M10 5.43L10 2.6M16.41 6.3L10 5.43M16.41 6.3L13.96 12.29M6.04 12.29L10 17.4M3.59 13.7L6.04 12.29M13.96 12.29L10 17.4M16.41 13.7L13.96 12.29\" stroke-width=\"0.6\"/>"
226
239
  }, r = {
240
+ bookmark: "<path d=\"M5.7 16.6V4.8a1.4 1.4 0 0 1 1.4-1.4h5.8a1.4 1.4 0 0 1 1.4 1.4V16.6L10 13.2Z\" fill=\"currentColor\" stroke=\"none\"/>",
227
241
  arcStraight: "<path d=\"M1.85 15L2.6 15H17.4L18.15 15L18.15 15.75L1.85 15.75Z\" fill=\"currentColor\" stroke=\"none\"/>",
228
242
  arcParabola: "<path d=\"M2.31 15.69L2.6 15Q10 -5 17.4 15L17.69 15.69L17.69 15.75L2.31 15.75Z\" fill=\"currentColor\" stroke=\"none\"/>",
229
243
  arcCircle: "<path d=\"M2.52 15.75L2.6 15A7.4 7.4 0 0 1 17.4 15L17.48 15.75L17.48 15.75L2.52 15.75Z\" fill=\"currentColor\" stroke=\"none\"/>",
@@ -350,6 +364,9 @@ var n = {
350
364
  "zoomIn",
351
365
  "zoomOut",
352
366
  "fit",
367
+ "fitContain",
368
+ "fitFill",
369
+ "fitStretch",
353
370
  "pan"
354
371
  ]
355
372
  },
@@ -409,6 +426,7 @@ var n = {
409
426
  "visible",
410
427
  "hidden",
411
428
  "pin",
429
+ "bookmark",
412
430
  "info",
413
431
  "warning",
414
432
  "error",
@@ -428,6 +446,20 @@ var n = {
428
446
  "statusMuted"
429
447
  ]
430
448
  },
449
+ {
450
+ label: "Component variants",
451
+ names: [
452
+ "variantSolid",
453
+ "variantOutline",
454
+ "variantSubtle",
455
+ "variantGhost",
456
+ "variantLink",
457
+ "variantPlain",
458
+ "variantSegmented",
459
+ "variantSegmentedMinimal",
460
+ "variantSegmentedFlat"
461
+ ]
462
+ },
431
463
  {
432
464
  label: "Instrument",
433
465
  names: [
@@ -556,4 +588,4 @@ function l({ name: e, className: i, size: s = 20, label: l, filled: u = !1, fill
556
588
  //#endregion
557
589
  export { n as a, i, a as n, r, l as t };
558
590
 
559
- //# sourceMappingURL=Icon--B1ME-6c.js.map
591
+ //# sourceMappingURL=Icon-BfqYtAX5.js.map