entangle-ui 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (563) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +7 -5
  3. package/dist/esm/assets/src/components/controls/Select/{Select.css.ts.vanilla-oZnFUorL.css → Select.css.ts.vanilla-Cpu2BvWL.css} +3 -0
  4. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyPanel.css.ts.vanilla-RYv_XgOu.css → PropertyPanel.css.ts.vanilla-Dpr_k5I3.css} +4 -1
  5. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyRow.css.ts.vanilla-C3YZnnHb.css → PropertyRow.css.ts.vanilla-pq1Uhd2a.css} +15 -8
  6. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertySection.css.ts.vanilla-DK12opZc.css → PropertySection.css.ts.vanilla-6MWWAqyd.css} +50 -32
  7. package/dist/esm/components/Icons/AddIcon.js.map +1 -1
  8. package/dist/esm/components/Icons/AiChatIcon.js.map +1 -1
  9. package/dist/esm/components/Icons/AiSparklesIcon.js.map +1 -1
  10. package/dist/esm/components/Icons/ArchiveIcon.js.map +1 -1
  11. package/dist/esm/components/Icons/ArrowDownIcon.js.map +1 -1
  12. package/dist/esm/components/Icons/ArrowLeftIcon.js.map +1 -1
  13. package/dist/esm/components/Icons/ArrowRightIcon.js.map +1 -1
  14. package/dist/esm/components/Icons/ArrowUpIcon.js.map +1 -1
  15. package/dist/esm/components/Icons/BookmarkIcon.js.map +1 -1
  16. package/dist/esm/components/Icons/BugIcon.js.map +1 -1
  17. package/dist/esm/components/Icons/BuildingIcon.js.map +1 -1
  18. package/dist/esm/components/Icons/CalendarIcon.js.map +1 -1
  19. package/dist/esm/components/Icons/CameraIcon.js +31 -0
  20. package/dist/esm/components/Icons/CameraIcon.js.map +1 -0
  21. package/dist/esm/components/Icons/CheckIcon.js.map +1 -1
  22. package/dist/esm/components/Icons/ChevronDownIcon.js.map +1 -1
  23. package/dist/esm/components/Icons/ChevronLeftIcon.js.map +1 -1
  24. package/dist/esm/components/Icons/ChevronRightIcon.js.map +1 -1
  25. package/dist/esm/components/Icons/ChevronUpIcon.js.map +1 -1
  26. package/dist/esm/components/Icons/CircleIcon.js.map +1 -1
  27. package/dist/esm/components/Icons/ClockIcon.js.map +1 -1
  28. package/dist/esm/components/Icons/CloseIcon.js.map +1 -1
  29. package/dist/esm/components/Icons/CloudUploadIcon.js.map +1 -1
  30. package/dist/esm/components/Icons/CodeIcon.js.map +1 -1
  31. package/dist/esm/components/Icons/CopyIcon.js.map +1 -1
  32. package/dist/esm/components/Icons/CubeIcon.js +31 -0
  33. package/dist/esm/components/Icons/CubeIcon.js.map +1 -0
  34. package/dist/esm/components/Icons/CutIcon.js.map +1 -1
  35. package/dist/esm/components/Icons/DotsHorizontalIcon.js.map +1 -1
  36. package/dist/esm/components/Icons/DotsVerticalIcon.js.map +1 -1
  37. package/dist/esm/components/Icons/DownloadIcon.js.map +1 -1
  38. package/dist/esm/components/Icons/EditIcon.js.map +1 -1
  39. package/dist/esm/components/Icons/ErrorIcon.js.map +1 -1
  40. package/dist/esm/components/Icons/ExternalLinkIcon.js.map +1 -1
  41. package/dist/esm/components/Icons/EyeDropperIcon.js.map +1 -1
  42. package/dist/esm/components/Icons/EyeIcon.js.map +1 -1
  43. package/dist/esm/components/Icons/FileTextIcon.js.map +1 -1
  44. package/dist/esm/components/Icons/FilterIcon.js.map +1 -1
  45. package/dist/esm/components/Icons/FirstIcon.js.map +1 -1
  46. package/dist/esm/components/Icons/FolderCogIcon.js.map +1 -1
  47. package/dist/esm/components/Icons/FolderIcon.js.map +1 -1
  48. package/dist/esm/components/Icons/FolderOpenIcon.js.map +1 -1
  49. package/dist/esm/components/Icons/FullscreenIcon.js.map +1 -1
  50. package/dist/esm/components/Icons/GitBranchIcon.js.map +1 -1
  51. package/dist/esm/components/Icons/GridIcon.js.map +1 -1
  52. package/dist/esm/components/Icons/HeartIcon.js.map +1 -1
  53. package/dist/esm/components/Icons/HelpIcon.js.map +1 -1
  54. package/dist/esm/components/Icons/HomeIcon.js.map +1 -1
  55. package/dist/esm/components/Icons/ImageIcon.js.map +1 -1
  56. package/dist/esm/components/Icons/InfoIcon.js.map +1 -1
  57. package/dist/esm/components/Icons/LastIcon.js.map +1 -1
  58. package/dist/esm/components/Icons/LinkIcon.js.map +1 -1
  59. package/dist/esm/components/Icons/ListIcon.js.map +1 -1
  60. package/dist/esm/components/Icons/LockIcon.js.map +1 -1
  61. package/dist/esm/components/Icons/MaximizeIcon.js.map +1 -1
  62. package/dist/esm/components/Icons/MenuIcon.js.map +1 -1
  63. package/dist/esm/components/Icons/MinimizeIcon.js.map +1 -1
  64. package/dist/esm/components/Icons/MinusIcon.js.map +1 -1
  65. package/dist/esm/components/Icons/OrbitIcon.js +31 -0
  66. package/dist/esm/components/Icons/OrbitIcon.js.map +1 -0
  67. package/dist/esm/components/Icons/PasteIcon.js.map +1 -1
  68. package/dist/esm/components/Icons/PauseIcon.js.map +1 -1
  69. package/dist/esm/components/Icons/PinIcon.js.map +1 -1
  70. package/dist/esm/components/Icons/PlayIcon.js.map +1 -1
  71. package/dist/esm/components/Icons/RedoIcon.js.map +1 -1
  72. package/dist/esm/components/Icons/RefreshIcon.js.map +1 -1
  73. package/dist/esm/components/Icons/RobotIcon.js.map +1 -1
  74. package/dist/esm/components/Icons/RotateIcon.js +32 -0
  75. package/dist/esm/components/Icons/RotateIcon.js.map +1 -0
  76. package/dist/esm/components/Icons/SaveIcon.js.map +1 -1
  77. package/dist/esm/components/Icons/SearchIcon.js.map +1 -1
  78. package/dist/esm/components/Icons/SendIcon.js.map +1 -1
  79. package/dist/esm/components/Icons/SettingsIcon.js.map +1 -1
  80. package/dist/esm/components/Icons/SortIcon.js.map +1 -1
  81. package/dist/esm/components/Icons/SpinIcon.js +32 -0
  82. package/dist/esm/components/Icons/SpinIcon.js.map +1 -0
  83. package/dist/esm/components/Icons/StarIcon.js.map +1 -1
  84. package/dist/esm/components/Icons/StopIcon.js.map +1 -1
  85. package/dist/esm/components/Icons/SuccessIcon.js.map +1 -1
  86. package/dist/esm/components/Icons/TagIcon.js.map +1 -1
  87. package/dist/esm/components/Icons/TangentAlignedIcon.js.map +1 -1
  88. package/dist/esm/components/Icons/TangentAutoIcon.js.map +1 -1
  89. package/dist/esm/components/Icons/TangentFreeIcon.js.map +1 -1
  90. package/dist/esm/components/Icons/TangentLinearIcon.js.map +1 -1
  91. package/dist/esm/components/Icons/TangentMirroredIcon.js.map +1 -1
  92. package/dist/esm/components/Icons/TangentStepIcon.js.map +1 -1
  93. package/dist/esm/components/Icons/TerminalIcon.js.map +1 -1
  94. package/dist/esm/components/Icons/TrashIcon.js.map +1 -1
  95. package/dist/esm/components/Icons/UndoIcon.js.map +1 -1
  96. package/dist/esm/components/Icons/UnlinkIcon.js.map +1 -1
  97. package/dist/esm/components/Icons/UnlockIcon.js.map +1 -1
  98. package/dist/esm/components/Icons/UploadIcon.js.map +1 -1
  99. package/dist/esm/components/Icons/UserIcon.js.map +1 -1
  100. package/dist/esm/components/Icons/UsersIcon.js.map +1 -1
  101. package/dist/esm/components/Icons/WarningIcon.js.map +1 -1
  102. package/dist/esm/components/Icons/ZoomFitIcon.js +32 -0
  103. package/dist/esm/components/Icons/ZoomFitIcon.js.map +1 -0
  104. package/dist/esm/components/Icons/ZoomInIcon.js.map +1 -1
  105. package/dist/esm/components/Icons/ZoomOutIcon.js.map +1 -1
  106. package/dist/esm/components/controls/CartesianPicker/CartesianPicker.js.map +1 -1
  107. package/dist/esm/components/controls/CartesianPicker/useCartesianInteraction.js.map +1 -1
  108. package/dist/esm/components/controls/CartesianPicker/useCartesianRenderer.js.map +1 -1
  109. package/dist/esm/components/controls/ColorPicker/AlphaSlider.js.map +1 -1
  110. package/dist/esm/components/controls/ColorPicker/ColorArea.js.map +1 -1
  111. package/dist/esm/components/controls/ColorPicker/ColorInputs.js.map +1 -1
  112. package/dist/esm/components/controls/ColorPicker/ColorPalette.js.map +1 -1
  113. package/dist/esm/components/controls/ColorPicker/ColorPicker.js.map +1 -1
  114. package/dist/esm/components/controls/ColorPicker/ColorPresets.js.map +1 -1
  115. package/dist/esm/components/controls/ColorPicker/ColorSwatch.js.map +1 -1
  116. package/dist/esm/components/controls/ColorPicker/EyeDropper.js.map +1 -1
  117. package/dist/esm/components/controls/ColorPicker/HueSlider.js.map +1 -1
  118. package/dist/esm/components/controls/ColorPicker/colorUtils.js.map +1 -1
  119. package/dist/esm/components/controls/ColorPicker/palettes/material.js.map +1 -1
  120. package/dist/esm/components/controls/ColorPicker/palettes/professional.js.map +1 -1
  121. package/dist/esm/components/controls/ColorPicker/palettes/tailwind.js.map +1 -1
  122. package/dist/esm/components/controls/ColorPicker/useColor.js.map +1 -1
  123. package/dist/esm/components/controls/Combobox/Combobox.js.map +1 -1
  124. package/dist/esm/components/controls/CurveEditor/CurveCanvas.js.map +1 -1
  125. package/dist/esm/components/controls/CurveEditor/CurveEditor.js.map +1 -1
  126. package/dist/esm/components/controls/CurveEditor/CurveToolbar.js.map +1 -1
  127. package/dist/esm/components/controls/CurveEditor/curvePresets.js.map +1 -1
  128. package/dist/esm/components/controls/CurveEditor/curveUtils.js.map +1 -1
  129. package/dist/esm/components/controls/CurveEditor/useCurveInteraction.js.map +1 -1
  130. package/dist/esm/components/controls/CurveEditor/useCurveRenderer.js.map +1 -1
  131. package/dist/esm/components/controls/FileTree/FileTree.js +7 -1
  132. package/dist/esm/components/controls/FileTree/FileTree.js.map +1 -1
  133. package/dist/esm/components/controls/FileTree/fileTreeIcons.js.map +1 -1
  134. package/dist/esm/components/controls/FileTree/fileTreeLabels.js.map +1 -1
  135. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js +1 -1
  136. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js.map +1 -1
  137. package/dist/esm/components/controls/FileUploader/FileUploader.js.map +1 -1
  138. package/dist/esm/components/controls/MultiSelect/MultiSelect.js.map +1 -1
  139. package/dist/esm/components/controls/NumberInput/NumberInput.js.map +1 -1
  140. package/dist/esm/components/controls/NumberInput/useNumberInput.js.map +1 -1
  141. package/dist/esm/components/controls/Select/Select.css.js +1 -1
  142. package/dist/esm/components/controls/Select/Select.js +15 -7
  143. package/dist/esm/components/controls/Select/Select.js.map +1 -1
  144. package/dist/esm/components/controls/Slider/Slider.js.map +1 -1
  145. package/dist/esm/components/controls/TagInput/TagInput.js.map +1 -1
  146. package/dist/esm/components/controls/TreeView/TreeNode.js +6 -0
  147. package/dist/esm/components/controls/TreeView/TreeNode.js.map +1 -1
  148. package/dist/esm/components/controls/TreeView/TreeView.js.map +1 -1
  149. package/dist/esm/components/controls/TreeView/useTreeState.js.map +1 -1
  150. package/dist/esm/components/controls/VectorInput/VectorInput.js +6 -0
  151. package/dist/esm/components/controls/VectorInput/VectorInput.js.map +1 -1
  152. package/dist/esm/components/data/DataTable/DataTable.js.map +1 -1
  153. package/dist/esm/components/editor/AssetBrowser/AssetBrowser.js.map +1 -1
  154. package/dist/esm/components/editor/AssetBrowser/AssetBrowserAnnouncementLive.js.map +1 -1
  155. package/dist/esm/components/editor/AssetBrowser/AssetBrowserBreadcrumbs.js.map +1 -1
  156. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js +6 -0
  157. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js.map +1 -1
  158. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContext.js.map +1 -1
  159. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContextMenu.js.map +1 -1
  160. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js +6 -0
  161. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js.map +1 -1
  162. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js +1 -1
  163. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js.map +1 -1
  164. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js +6 -0
  165. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js.map +1 -1
  166. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js +6 -0
  167. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js.map +1 -1
  168. package/dist/esm/components/editor/AssetBrowser/AssetBrowserRenameField.js.map +1 -1
  169. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSidebar.js.map +1 -1
  170. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStatusBar.js.map +1 -1
  171. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStore.js.map +1 -1
  172. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js +6 -0
  173. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js.map +1 -1
  174. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js +6 -0
  175. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js.map +1 -1
  176. package/dist/esm/components/editor/AssetBrowser/assetBrowserFilter.js.map +1 -1
  177. package/dist/esm/components/editor/AssetBrowser/assetBrowserFormat.js.map +1 -1
  178. package/dist/esm/components/editor/AssetBrowser/assetBrowserGeometry.js.map +1 -1
  179. package/dist/esm/components/editor/AssetBrowser/assetBrowserKeyboard.js.map +1 -1
  180. package/dist/esm/components/editor/AssetBrowser/assetBrowserLabels.js.map +1 -1
  181. package/dist/esm/components/editor/AssetBrowser/slots.js.map +1 -1
  182. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserAnnouncement.js.map +1 -1
  183. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js +1 -1
  184. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js.map +1 -1
  185. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js +1 -1
  186. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js.map +1 -1
  187. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js +1 -1
  188. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js.map +1 -1
  189. package/dist/esm/components/editor/AssetBrowser/useAssetGridKeyboardNav.js.map +1 -1
  190. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js +1 -1
  191. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js.map +1 -1
  192. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js +1 -1
  193. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js.map +1 -1
  194. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js +1 -1
  195. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js.map +1 -1
  196. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js +1 -1
  197. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js.map +1 -1
  198. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js +1 -1
  199. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js.map +1 -1
  200. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js +1 -1
  201. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js.map +1 -1
  202. package/dist/esm/components/editor/ChatPanel/ChatActionBar.js.map +1 -1
  203. package/dist/esm/components/editor/ChatPanel/ChatAttachment.js.map +1 -1
  204. package/dist/esm/components/editor/ChatPanel/ChatBubble.js.map +1 -1
  205. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js +6 -0
  206. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js.map +1 -1
  207. package/dist/esm/components/editor/ChatPanel/ChatContextChip.js.map +1 -1
  208. package/dist/esm/components/editor/ChatPanel/ChatEmptyState.js.map +1 -1
  209. package/dist/esm/components/editor/ChatPanel/ChatIcons.js.map +1 -1
  210. package/dist/esm/components/editor/ChatPanel/ChatInput.js +6 -0
  211. package/dist/esm/components/editor/ChatPanel/ChatInput.js.map +1 -1
  212. package/dist/esm/components/editor/ChatPanel/ChatInputToolbar.js.map +1 -1
  213. package/dist/esm/components/editor/ChatPanel/ChatMarkdownRenderer.js.map +1 -1
  214. package/dist/esm/components/editor/ChatPanel/ChatMessage.js +6 -0
  215. package/dist/esm/components/editor/ChatPanel/ChatMessage.js.map +1 -1
  216. package/dist/esm/components/editor/ChatPanel/ChatMessageList.js.map +1 -1
  217. package/dist/esm/components/editor/ChatPanel/ChatPanel.js.map +1 -1
  218. package/dist/esm/components/editor/ChatPanel/ChatToolCall.js.map +1 -1
  219. package/dist/esm/components/editor/ChatPanel/ChatTypingIndicator.js.map +1 -1
  220. package/dist/esm/components/editor/ChatPanel/useChatInput.js.map +1 -1
  221. package/dist/esm/components/editor/ChatPanel/useChatMessages.js.map +1 -1
  222. package/dist/esm/components/editor/ChatPanel/useChatScroll.js.map +1 -1
  223. package/dist/esm/components/editor/Minimap/Minimap.js +1 -1
  224. package/dist/esm/components/editor/Minimap/Minimap.js.map +1 -1
  225. package/dist/esm/components/editor/Minimap/Minimap.types.js.map +1 -1
  226. package/dist/esm/components/editor/Minimap/MinimapContext.js.map +1 -1
  227. package/dist/esm/components/editor/Minimap/MinimapCorner.js.map +1 -1
  228. package/dist/esm/components/editor/Minimap/MinimapFooter.js.map +1 -1
  229. package/dist/esm/components/editor/Minimap/MinimapStore.js.map +1 -1
  230. package/dist/esm/components/editor/Minimap/MinimapTitle.js.map +1 -1
  231. package/dist/esm/components/editor/Minimap/ViewportMinimap.js +1 -1
  232. package/dist/esm/components/editor/Minimap/ViewportMinimap.js.map +1 -1
  233. package/dist/esm/components/editor/Minimap/computeBoundsFromItems.js.map +1 -1
  234. package/dist/esm/components/editor/Minimap/index.js.map +1 -1
  235. package/dist/esm/components/editor/Minimap/minimapCoords.js.map +1 -1
  236. package/dist/esm/components/editor/Minimap/minimapDrawing.js.map +1 -1
  237. package/dist/esm/components/editor/Minimap/minimapHitTest.js.map +1 -1
  238. package/dist/esm/components/editor/Minimap/useMinimapGestures.js +1 -1
  239. package/dist/esm/components/editor/Minimap/useMinimapGestures.js.map +1 -1
  240. package/dist/esm/components/editor/NodeGraph/NodeGraph.js +1 -1
  241. package/dist/esm/components/editor/NodeGraph/NodeGraph.js.map +1 -1
  242. package/dist/esm/components/editor/NodeGraph/NodeGraph.types.js.map +1 -1
  243. package/dist/esm/components/editor/NodeGraph/NodeGraphContext.js.map +1 -1
  244. package/dist/esm/components/editor/NodeGraph/NodeGraphEdgeLabels.js.map +1 -1
  245. package/dist/esm/components/editor/NodeGraph/NodeGraphGroup.js.map +1 -1
  246. package/dist/esm/components/editor/NodeGraph/NodeGraphMinimap.js.map +1 -1
  247. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js +1 -1
  248. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js.map +1 -1
  249. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeContext.js.map +1 -1
  250. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeParts.js.map +1 -1
  251. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js +1 -1
  252. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js.map +1 -1
  253. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSectionContext.js.map +1 -1
  254. package/dist/esm/components/editor/NodeGraph/NodeGraphPin.js.map +1 -1
  255. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js +1 -1
  256. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js.map +1 -1
  257. package/dist/esm/components/editor/NodeGraph/NodeGraphPortVisual.js.map +1 -1
  258. package/dist/esm/components/editor/NodeGraph/NodeGraphSlots.js.map +1 -1
  259. package/dist/esm/components/editor/NodeGraph/NodeGraphSpawnPalette.js.map +1 -1
  260. package/dist/esm/components/editor/NodeGraph/NodeGraphStore.js.map +1 -1
  261. package/dist/esm/components/editor/NodeGraph/NodeGraphToolbar.js.map +1 -1
  262. package/dist/esm/components/editor/NodeGraph/createTypeMatchValidator.js.map +1 -1
  263. package/dist/esm/components/editor/NodeGraph/nodeGraphActions.js.map +1 -1
  264. package/dist/esm/components/editor/NodeGraph/nodeGraphDrawing.js.map +1 -1
  265. package/dist/esm/components/editor/NodeGraph/nodeGraphIds.js.map +1 -1
  266. package/dist/esm/components/editor/NodeGraph/nodeGraphMath.js.map +1 -1
  267. package/dist/esm/components/editor/NodeGraph/sortSlots.js.map +1 -1
  268. package/dist/esm/components/editor/NodeGraph/useDragGesture.js.map +1 -1
  269. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js +1 -1
  270. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js.map +1 -1
  271. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js +1 -1
  272. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js.map +1 -1
  273. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js +1 -1
  274. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js.map +1 -1
  275. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js +1 -1
  276. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js.map +1 -1
  277. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js +1 -1
  278. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js.map +1 -1
  279. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js +1 -1
  280. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js.map +1 -1
  281. package/dist/esm/components/editor/NodeGraph/useStoreSlice.js.map +1 -1
  282. package/dist/esm/components/editor/PropertyInspector/PropertyGroup.js.map +1 -1
  283. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js +4 -3
  284. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js.map +1 -1
  285. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js +5 -4
  286. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js.map +1 -1
  287. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js +7 -6
  288. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js.map +1 -1
  289. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js +18 -3
  290. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js.map +1 -1
  291. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js +11 -10
  292. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js.map +1 -1
  293. package/dist/esm/components/editor/PropertyInspector/PropertySection.js +29 -21
  294. package/dist/esm/components/editor/PropertyInspector/PropertySection.js.map +1 -1
  295. package/dist/esm/components/editor/PropertyInspector/usePropertyUndo.js.map +1 -1
  296. package/dist/esm/components/editor/Timeline/Timeline.js +1 -1
  297. package/dist/esm/components/editor/Timeline/Timeline.js.map +1 -1
  298. package/dist/esm/components/editor/Timeline/Timeline.types.js.map +1 -1
  299. package/dist/esm/components/editor/Timeline/TimelineContext.js.map +1 -1
  300. package/dist/esm/components/editor/Timeline/TimelineFooter.js.map +1 -1
  301. package/dist/esm/components/editor/Timeline/TimelineMinimap.js +1 -1
  302. package/dist/esm/components/editor/Timeline/TimelineMinimap.js.map +1 -1
  303. package/dist/esm/components/editor/Timeline/TimelineStore.js.map +1 -1
  304. package/dist/esm/components/editor/Timeline/TimelineToolbar.js.map +1 -1
  305. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js +1 -1
  306. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js.map +1 -1
  307. package/dist/esm/components/editor/Timeline/TimelineTrackScale.js.map +1 -1
  308. package/dist/esm/components/editor/Timeline/index.js.map +1 -1
  309. package/dist/esm/components/editor/Timeline/timelineCoords.js.map +1 -1
  310. package/dist/esm/components/editor/Timeline/timelineDrawing.js.map +1 -1
  311. package/dist/esm/components/editor/Timeline/timelineEdits.js.map +1 -1
  312. package/dist/esm/components/editor/Timeline/timelineHitTest.js.map +1 -1
  313. package/dist/esm/components/editor/Timeline/timelineLayout.js.map +1 -1
  314. package/dist/esm/components/editor/Timeline/timelineSelection.js.map +1 -1
  315. package/dist/esm/components/editor/Timeline/useTimelineDraw.js +1 -1
  316. package/dist/esm/components/editor/Timeline/useTimelineDraw.js.map +1 -1
  317. package/dist/esm/components/editor/Timeline/useTimelineGestures.js +1 -1
  318. package/dist/esm/components/editor/Timeline/useTimelineGestures.js.map +1 -1
  319. package/dist/esm/components/editor/Timeline/useTimelinePlayback.js.map +1 -1
  320. package/dist/esm/components/editor/TransformControl/TransformControl.js.map +1 -1
  321. package/dist/esm/components/editor/ViewportGizmo/ViewportGizmo.js.map +1 -1
  322. package/dist/esm/components/editor/ViewportGizmo/gizmoMath.js.map +1 -1
  323. package/dist/esm/components/editor/ViewportGizmo/useGizmoInteraction.js.map +1 -1
  324. package/dist/esm/components/editor/ViewportGizmo/useGizmoRenderer.js.map +1 -1
  325. package/dist/esm/components/feedback/Alert/Alert.js.map +1 -1
  326. package/dist/esm/components/feedback/Alert/AlertActions.js.map +1 -1
  327. package/dist/esm/components/feedback/Alert/AlertDescription.js.map +1 -1
  328. package/dist/esm/components/feedback/Alert/AlertTitle.js.map +1 -1
  329. package/dist/esm/components/feedback/CommandPalette/CommandPalette.js.map +1 -1
  330. package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js.map +1 -1
  331. package/dist/esm/components/feedback/CommandPalette/useRecentItems.js.map +1 -1
  332. package/dist/esm/components/feedback/Dialog/Dialog.js.map +1 -1
  333. package/dist/esm/components/feedback/Dialog/DialogBody.js.map +1 -1
  334. package/dist/esm/components/feedback/Dialog/DialogClose.js.map +1 -1
  335. package/dist/esm/components/feedback/Dialog/DialogFooter.js.map +1 -1
  336. package/dist/esm/components/feedback/Dialog/DialogHeader.js.map +1 -1
  337. package/dist/esm/components/feedback/Dialog/useDialogAnimation.js.map +1 -1
  338. package/dist/esm/components/feedback/Drawer/Drawer.js.map +1 -1
  339. package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js.map +1 -1
  340. package/dist/esm/components/feedback/EmptyState/EmptyState.js.map +1 -1
  341. package/dist/esm/components/feedback/LogView/LogView.js.map +1 -1
  342. package/dist/esm/components/feedback/LogView/LogViewBody.js.map +1 -1
  343. package/dist/esm/components/feedback/LogView/LogViewContext.js.map +1 -1
  344. package/dist/esm/components/feedback/LogView/LogViewParts.js.map +1 -1
  345. package/dist/esm/components/feedback/LogView/LogViewStore.js.map +1 -1
  346. package/dist/esm/components/feedback/LogView/logViewLabels.js.map +1 -1
  347. package/dist/esm/components/feedback/LogView/logViewLevels.js.map +1 -1
  348. package/dist/esm/components/feedback/LogView/logViewUtils.js.map +1 -1
  349. package/dist/esm/components/feedback/LogView/useFollowTail.js.map +1 -1
  350. package/dist/esm/components/feedback/LogView/useLogSelection.js.map +1 -1
  351. package/dist/esm/components/feedback/ProgressBar/CircularProgress.js.map +1 -1
  352. package/dist/esm/components/feedback/ProgressBar/ProgressBar.js.map +1 -1
  353. package/dist/esm/components/feedback/Skeleton/Skeleton.js.map +1 -1
  354. package/dist/esm/components/feedback/Skeleton/SkeletonGroup.js.map +1 -1
  355. package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js.map +1 -1
  356. package/dist/esm/components/feedback/Spinner/Spinner.js.map +1 -1
  357. package/dist/esm/components/feedback/Stat/Stat.js.map +1 -1
  358. package/dist/esm/components/feedback/Toast/ToastContainer.js.map +1 -1
  359. package/dist/esm/components/feedback/Toast/ToastItem.js.map +1 -1
  360. package/dist/esm/components/feedback/Toast/ToastProvider.js.map +1 -1
  361. package/dist/esm/components/feedback/Toast/useToast.js.map +1 -1
  362. package/dist/esm/components/form/FormHelperText.js.map +1 -1
  363. package/dist/esm/components/form/FormLabel.js.map +1 -1
  364. package/dist/esm/components/form/InputWrapper.js.map +1 -1
  365. package/dist/esm/components/layout/Accordion/Accordion.js.map +1 -1
  366. package/dist/esm/components/layout/Accordion/AccordionContent.js.map +1 -1
  367. package/dist/esm/components/layout/Accordion/AccordionItem.js.map +1 -1
  368. package/dist/esm/components/layout/Accordion/AccordionTrigger.js.map +1 -1
  369. package/dist/esm/components/layout/Card/Card.js.map +1 -1
  370. package/dist/esm/components/layout/Divider/Divider.js.map +1 -1
  371. package/dist/esm/components/layout/Flex/Flex.js.map +1 -1
  372. package/dist/esm/components/layout/Grid/Grid.js.map +1 -1
  373. package/dist/esm/components/layout/ListItem/ListItem.js.map +1 -1
  374. package/dist/esm/components/layout/PageHeader/PageHeader.js.map +1 -1
  375. package/dist/esm/components/layout/PanelSurface/PanelSurface.js.map +1 -1
  376. package/dist/esm/components/layout/ScrollArea/ScrollArea.js.map +1 -1
  377. package/dist/esm/components/layout/Spacer/Spacer.js.map +1 -1
  378. package/dist/esm/components/layout/SplitPane/SplitPane.js.map +1 -1
  379. package/dist/esm/components/layout/SplitPane/SplitPanePanel.js.map +1 -1
  380. package/dist/esm/components/layout/Stack/Stack.js.map +1 -1
  381. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js.map +1 -1
  382. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js.map +1 -1
  383. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbSeparator.js.map +1 -1
  384. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js +6 -0
  385. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js.map +1 -1
  386. package/dist/esm/components/navigation/ContextMenu/ContextMenu.js.map +1 -1
  387. package/dist/esm/components/navigation/Menu/Menu.js.map +1 -1
  388. package/dist/esm/components/navigation/Menu/MenuGapContext.js.map +1 -1
  389. package/dist/esm/components/navigation/Pagination/Pagination.js.map +1 -1
  390. package/dist/esm/components/navigation/Pagination/usePagination.js.map +1 -1
  391. package/dist/esm/components/navigation/PathBar/PathBar.js +7 -1
  392. package/dist/esm/components/navigation/PathBar/PathBar.js.map +1 -1
  393. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js +6 -0
  394. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js.map +1 -1
  395. package/dist/esm/components/navigation/PathBar/pathUtils.js.map +1 -1
  396. package/dist/esm/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -1
  397. package/dist/esm/components/navigation/SegmentedControl/SegmentedControlItem.js.map +1 -1
  398. package/dist/esm/components/navigation/Tabs/Tab.js.map +1 -1
  399. package/dist/esm/components/navigation/Tabs/TabList.js.map +1 -1
  400. package/dist/esm/components/navigation/Tabs/TabPanel.js.map +1 -1
  401. package/dist/esm/components/navigation/Tabs/Tabs.js.map +1 -1
  402. package/dist/esm/components/primitives/Avatar/Avatar.js +6 -0
  403. package/dist/esm/components/primitives/Avatar/Avatar.js.map +1 -1
  404. package/dist/esm/components/primitives/Avatar/AvatarGroup.js.map +1 -1
  405. package/dist/esm/components/primitives/Badge/Badge.js +6 -0
  406. package/dist/esm/components/primitives/Badge/Badge.js.map +1 -1
  407. package/dist/esm/components/primitives/Button/Button.js.map +1 -1
  408. package/dist/esm/components/primitives/Checkbox/Checkbox.js.map +1 -1
  409. package/dist/esm/components/primitives/Checkbox/CheckboxGroup.js.map +1 -1
  410. package/dist/esm/components/primitives/Code/Code.js.map +1 -1
  411. package/dist/esm/components/primitives/Collapsible/Collapsible.js.map +1 -1
  412. package/dist/esm/components/primitives/HoverCard/HoverCard.js.map +1 -1
  413. package/dist/esm/components/primitives/Icon/Icon.js.map +1 -1
  414. package/dist/esm/components/primitives/IconButton/IconButton.js.map +1 -1
  415. package/dist/esm/components/primitives/Input/Input.js.map +1 -1
  416. package/dist/esm/components/primitives/Kbd/Kbd.js.map +1 -1
  417. package/dist/esm/components/primitives/Link/Link.js.map +1 -1
  418. package/dist/esm/components/primitives/Paper/Paper.js.map +1 -1
  419. package/dist/esm/components/primitives/Popover/Popover.js.map +1 -1
  420. package/dist/esm/components/primitives/Popover/PopoverClose.js.map +1 -1
  421. package/dist/esm/components/primitives/Popover/PopoverContent.js.map +1 -1
  422. package/dist/esm/components/primitives/Popover/PopoverTrigger.js.map +1 -1
  423. package/dist/esm/components/primitives/Radio/Radio.js.map +1 -1
  424. package/dist/esm/components/primitives/Radio/RadioGroup.js.map +1 -1
  425. package/dist/esm/components/primitives/Switch/Switch.js.map +1 -1
  426. package/dist/esm/components/primitives/Text/Text.js.map +1 -1
  427. package/dist/esm/components/primitives/TextArea/TextArea.js.map +1 -1
  428. package/dist/esm/components/primitives/Tooltip/Arrow.js.map +1 -1
  429. package/dist/esm/components/primitives/Tooltip/Tooltip.js.map +1 -1
  430. package/dist/esm/components/primitives/Tooltip/utils.js.map +1 -1
  431. package/dist/esm/components/primitives/VisuallyHidden/VisuallyHidden.js.map +1 -1
  432. package/dist/esm/components/primitives/canvas/CanvasContainer.js.map +1 -1
  433. package/dist/esm/components/primitives/canvas/canvasCoords.js.map +1 -1
  434. package/dist/esm/components/primitives/canvas/canvasDrawing.js.map +1 -1
  435. package/dist/esm/components/primitives/canvas/canvasTheme.js.map +1 -1
  436. package/dist/esm/components/primitives/canvas/useCanvasRenderer.js.map +1 -1
  437. package/dist/esm/components/primitives/viewport/Viewport.js +1 -1
  438. package/dist/esm/components/primitives/viewport/Viewport.js.map +1 -1
  439. package/dist/esm/components/primitives/viewport/ViewportContext.js.map +1 -1
  440. package/dist/esm/components/primitives/viewport/ViewportLayer.js +1 -1
  441. package/dist/esm/components/primitives/viewport/ViewportLayer.js.map +1 -1
  442. package/dist/esm/components/primitives/viewport/ViewportOverlay.js.map +1 -1
  443. package/dist/esm/components/primitives/viewport/ViewportStore.js.map +1 -1
  444. package/dist/esm/components/primitives/viewport/ViewportWorld.js.map +1 -1
  445. package/dist/esm/components/primitives/viewport/useViewportGestures.js +1 -1
  446. package/dist/esm/components/primitives/viewport/useViewportGestures.js.map +1 -1
  447. package/dist/esm/components/primitives/viewport/viewportCoords.js.map +1 -1
  448. package/dist/esm/components/primitives/viewport/viewportMath.js.map +1 -1
  449. package/dist/esm/components/shell/AppShell/AppShell.js.map +1 -1
  450. package/dist/esm/components/shell/FloatingPanel/FloatingPanel.js.map +1 -1
  451. package/dist/esm/components/shell/MenuBar/MenuBar.js.map +1 -1
  452. package/dist/esm/components/shell/StatusBar/StatusBar.js.map +1 -1
  453. package/dist/esm/components/shell/Toolbar/Toolbar.js.map +1 -1
  454. package/dist/esm/context/KeyboardContext.js.map +1 -1
  455. package/dist/esm/hooks/useBreakpoint/useBreakpoint.js.map +1 -1
  456. package/dist/esm/hooks/useClickOutside/useClickOutside.js.map +1 -1
  457. package/dist/esm/hooks/useClipboard/useClipboard.js.map +1 -1
  458. package/dist/esm/hooks/useControlledState/useControlledState.js.map +1 -1
  459. package/dist/esm/hooks/useDebounced/useDebouncedCallback.js.map +1 -1
  460. package/dist/esm/hooks/useDebounced/useDebouncedValue.js.map +1 -1
  461. package/dist/esm/hooks/useDisclosure/useDisclosure.js.map +1 -1
  462. package/dist/esm/hooks/useEventCallback/useEventCallback.js.map +1 -1
  463. package/dist/esm/hooks/useFocusTrap/useFocusTrap.js.map +1 -1
  464. package/dist/esm/hooks/useHotkey/useHotkey.js.map +1 -1
  465. package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js.map +1 -1
  466. package/dist/esm/hooks/useIsMounted/useIsMounted.js.map +1 -1
  467. package/dist/esm/hooks/useKeyboard/useKeyboard.js.map +1 -1
  468. package/dist/esm/hooks/useKeyboard/utils.js.map +1 -1
  469. package/dist/esm/hooks/useLatest/useLatest.js.map +1 -1
  470. package/dist/esm/hooks/useListboxNav/useListboxNav.js.map +1 -1
  471. package/dist/esm/hooks/useMediaQuery/useMediaQuery.js.map +1 -1
  472. package/dist/esm/hooks/useMergedRef/useMergedRef.js.map +1 -1
  473. package/dist/esm/hooks/useNavigationHistory/useNavigationHistory.js.map +1 -1
  474. package/dist/esm/hooks/useResizeObserver/useResizeObserver.js.map +1 -1
  475. package/dist/esm/hooks/useTheme/useTheme.js +1 -1
  476. package/dist/esm/hooks/useTheme/useTheme.js.map +1 -1
  477. package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js.map +1 -1
  478. package/dist/esm/index.js +6 -0
  479. package/dist/esm/index.js.map +1 -1
  480. package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
  481. package/dist/esm/styles.js +3 -0
  482. package/dist/esm/styles.js.map +1 -0
  483. package/dist/esm/theme/ThemeProvider.js +5 -3
  484. package/dist/esm/theme/ThemeProvider.js.map +1 -1
  485. package/dist/esm/theme/VanillaThemeProvider.js.map +1 -1
  486. package/dist/esm/theme/breakpoints.js.map +1 -1
  487. package/dist/esm/theme/createCustomTheme.js +1 -1
  488. package/dist/esm/theme/createCustomTheme.js.map +1 -1
  489. package/dist/esm/theme/createLightTheme.js.map +1 -1
  490. package/dist/esm/theme/darkThemeValues.js.map +1 -1
  491. package/dist/esm/theme/lightThemeValues.js.map +1 -1
  492. package/dist/esm/theme/themeContractData.js.map +1 -1
  493. package/dist/esm/utils/cx.js.map +1 -1
  494. package/dist/esm/utils/devWarn.js.map +1 -1
  495. package/dist/esm/utils/mathExpression.js.map +1 -1
  496. package/dist/esm/utils/mathUtils.js.map +1 -1
  497. package/dist/esm/utils/objects.js.map +1 -1
  498. package/dist/esm/utils/platform.js.map +1 -1
  499. package/dist/tokens/tokens.dark.css +1 -1
  500. package/dist/tokens/tokens.json +1 -1
  501. package/dist/tokens/tokens.light.css +1 -1
  502. package/dist/types/components/Icons/CameraIcon.d.ts +34 -0
  503. package/dist/types/components/Icons/CubeIcon.d.ts +34 -0
  504. package/dist/types/components/Icons/OrbitIcon.d.ts +34 -0
  505. package/dist/types/components/Icons/RotateIcon.d.ts +35 -0
  506. package/dist/types/components/Icons/SpinIcon.d.ts +35 -0
  507. package/dist/types/components/Icons/ZoomFitIcon.d.ts +35 -0
  508. package/dist/types/components/controls/Select/Select.d.ts +1 -1
  509. package/dist/types/components/controls/Select/Select.types.d.ts +43 -9
  510. package/dist/types/components/editor/PropertyInspector/PropertyInspector.types.d.ts +49 -3
  511. package/dist/types/components/primitives/Button/Button.d.ts +1 -1
  512. package/dist/types/components/primitives/IconButton/IconButton.d.ts +1 -1
  513. package/dist/types/index.d.ts +6 -0
  514. package/dist/types/theme/ThemeProvider.d.ts +5 -3
  515. package/package.json +6 -2
  516. package/dist/esm/_virtual/_commonjsHelpers.js +0 -6
  517. package/dist/esm/_virtual/_commonjsHelpers.js.map +0 -1
  518. package/dist/esm/_virtual/cjs.js +0 -4
  519. package/dist/esm/_virtual/cjs.js.map +0 -1
  520. package/dist/esm/_virtual/cssesc.js +0 -8
  521. package/dist/esm/_virtual/cssesc.js.map +0 -1
  522. package/dist/esm/_virtual/picocolors.js +0 -8
  523. package/dist/esm/_virtual/picocolors.js.map +0 -1
  524. package/dist/esm/_virtual/picocolors2.js +0 -4
  525. package/dist/esm/_virtual/picocolors2.js.map +0 -1
  526. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js +0 -56
  527. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +0 -1
  528. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js +0 -46
  529. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js.map +0 -1
  530. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js +0 -13
  531. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js.map +0 -1
  532. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js +0 -962
  533. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js.map +0 -1
  534. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js +0 -309
  535. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js.map +0 -1
  536. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js +0 -18
  537. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js.map +0 -1
  538. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js +0 -23
  539. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js.map +0 -1
  540. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js +0 -1543
  541. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js.map +0 -1
  542. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js +0 -38
  543. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js.map +0 -1
  544. package/dist/esm/node_modules/css-what/lib/es/parse.js +0 -424
  545. package/dist/esm/node_modules/css-what/lib/es/parse.js.map +0 -1
  546. package/dist/esm/node_modules/css-what/lib/es/types.js +0 -29
  547. package/dist/esm/node_modules/css-what/lib/es/types.js.map +0 -1
  548. package/dist/esm/node_modules/cssesc/cssesc.js +0 -120
  549. package/dist/esm/node_modules/cssesc/cssesc.js.map +0 -1
  550. package/dist/esm/node_modules/dedent/dist/dedent.js +0 -100
  551. package/dist/esm/node_modules/dedent/dist/dedent.js.map +0 -1
  552. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js +0 -40
  553. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js.map +0 -1
  554. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js +0 -9
  555. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js.map +0 -1
  556. package/dist/esm/node_modules/deepmerge/dist/cjs.js +0 -143
  557. package/dist/esm/node_modules/deepmerge/dist/cjs.js.map +0 -1
  558. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js +0 -1386
  559. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js.map +0 -1
  560. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js +0 -102
  561. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js.map +0 -1
  562. package/dist/esm/node_modules/picocolors/picocolors.js +0 -87
  563. package/dist/esm/node_modules/picocolors/picocolors.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.js","sources":["../../../../../../src/components/primitives/TextArea/TextArea.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AAiBA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AA+BL;AACA;AACA;AACA;AACA;AAEA;;;;AAMA;AAEI;;;AAEK;AAAS;AAChB;AAIF;AACE;;AACA;AACA;;AAEA;;AAGA;AACE;;;AAGF;AAEA;;AAEA;;;AAIA;AACF;AAEA;;AAEE;AACF;AACA;;AAEE;AACF;AACA;AACE;AACA;;AACA;AACF;AAEA;AACA;AAEA;;;AA0BS;AAaL;AAGM;AACA;AACA;AACA;AACD;AAgBX;AAEA;;"}
1
+ {"version":3,"file":"TextArea.js","sources":["src/components/primitives/TextArea/TextArea.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback, useEffect, useId, useRef } from 'react';\n\nimport { FormHelperText } from '@/components/form/FormHelperText';\nimport { FormLabel } from '@/components/form/FormLabel';\nimport { cx } from '@/utils/cx';\n\nimport {\n textAreaContainerStyle,\n textAreaFooterStyle,\n textAreaRecipe,\n textAreaWrapperRecipe,\n} from './TextArea.css';\n\nimport type { TextAreaProps } from './TextArea.types';\n\n/**\n * Multi-line text input with optional auto-resize.\n *\n * Visual parity with `Input` — uses the same border, focus ring, and error\n * states. Auto-resize activates when `minRows` or `maxRows` is set and\n * disables the native resize handle.\n *\n * @example\n * ```tsx\n * <TextArea\n * label=\"Description\"\n * minRows={3}\n * maxRows={8}\n * value={value}\n * onChange={setValue}\n * showCount\n * maxLength={500}\n * />\n * ```\n */\nexport const TextArea: React.FC<TextAreaProps> = ({\n value,\n defaultValue,\n placeholder,\n size = 'md',\n disabled = false,\n error = false,\n required = false,\n readOnly = false,\n label,\n helperText,\n errorMessage,\n resize = 'vertical',\n rows = 3,\n minRows,\n maxRows,\n monospace = false,\n maxLength,\n showCount = false,\n className,\n style,\n onChange,\n onFocus,\n onBlur,\n onKeyDown,\n testId,\n ref,\n id,\n name,\n ...rest\n}) => {\n const [focused, setFocused] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? '');\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const autoId = useId();\n const inputId = id ?? autoId;\n\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internalValue;\n\n const autoSizeEnabled = minRows !== undefined || maxRows !== undefined;\n const effectiveResize = autoSizeEnabled ? 'none' : resize;\n\n const setRef = useCallback(\n (node: HTMLTextAreaElement | null) => {\n textareaRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref]\n );\n\n const autoResize = useCallback(() => {\n if (!autoSizeEnabled) return;\n const el = textareaRef.current;\n if (!el) return;\n\n el.style.height = 'auto';\n\n const measuredLineHeight = parseFloat(getComputedStyle(el).lineHeight);\n const lineHeight = Number.isFinite(measuredLineHeight)\n ? measuredLineHeight\n : 18;\n const minHeight = (minRows ?? 1) * lineHeight;\n const maxHeight = maxRows ? maxRows * lineHeight : Infinity;\n\n const next = Math.min(Math.max(el.scrollHeight, minHeight), maxHeight);\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }, [autoSizeEnabled, minRows, maxRows]);\n\n useEffect(() => {\n autoResize();\n }, [currentValue, autoResize]);\n\n const handleFocus = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setFocused(true);\n onFocus?.(event);\n };\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setFocused(false);\n onBlur?.(event);\n };\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const next = event.target.value;\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n const effectiveHelper = error && errorMessage ? errorMessage : helperText;\n const count = currentValue.length;\n\n return (\n <div className={cx(textAreaContainerStyle, className)} style={style}>\n {label && (\n <FormLabel htmlFor={inputId} disabled={disabled} required={required}>\n {label}\n </FormLabel>\n )}\n\n <div\n className={textAreaWrapperRecipe({ size, error, disabled, focused })}\n >\n <textarea\n ref={setRef}\n id={inputId}\n name={name}\n placeholder={placeholder}\n disabled={disabled}\n required={required}\n readOnly={readOnly}\n value={isControlled ? value : undefined}\n defaultValue={isControlled ? undefined : defaultValue}\n rows={autoSizeEnabled ? (minRows ?? rows) : rows}\n maxLength={maxLength}\n className={textAreaRecipe({\n size,\n monospace: monospace || undefined,\n })}\n style={{ resize: effectiveResize }}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n data-testid={testId}\n aria-invalid={error || undefined}\n {...rest}\n />\n </div>\n\n {(effectiveHelper !== undefined && effectiveHelper !== '') ||\n showCount ? (\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n gap: 8,\n }}\n >\n {effectiveHelper !== undefined && effectiveHelper !== '' ? (\n <FormHelperText error={error}>{effectiveHelper}</FormHelperText>\n ) : (\n <span />\n )}\n {showCount && (\n <div className={textAreaFooterStyle}>\n {maxLength !== undefined ? `${count}/${maxLength}` : count}\n </div>\n )}\n </div>\n ) : null}\n </div>\n );\n};\n\nTextArea.displayName = 'TextArea';\n"],"names":[],"mappings":";;;;;;;;AAiBA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AA+BL;AACA;AACA;AACA;AACA;AAEA;;;;AAMA;AAEI;;;AAEK;AAAS;AAChB;AAIF;AACE;;AACA;AACA;;AAEA;;AAGA;AACE;;;AAGF;AAEA;;AAEA;;;AAIA;AACF;AAEA;;AAEE;AACF;AACA;;AAEE;AACF;AACA;AACE;AACA;;AACA;AACF;AAEA;AACA;AAEA;;;AA0BS;AAaL;AAGM;AACA;AACA;AACA;AACD;AAgBX;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Arrow.js","sources":["../../../../../../src/components/primitives/Tooltip/Arrow.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;AASO;AACL;;AAQM;AACA;AACD;AASP;AAEO;AAcP;;"}
1
+ {"version":3,"file":"Arrow.js","sources":["src/components/primitives/Tooltip/Arrow.tsx"],"sourcesContent":["'use client';\n\nimport { Tooltip } from '@base-ui/react/tooltip';\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { arrowFillStyle, tooltipArrowStyle } from './Tooltip.css';\n\nexport const ArrowSvg = (props: React.ComponentProps<'svg'>) => {\n return (\n <svg\n width=\"20\"\n height=\"10\"\n viewBox=\"0 0 20 10\"\n fill=\"none\"\n style={{\n // Improve SVG rendering quality\n shapeRendering: 'geometricPrecision',\n imageRendering: 'crisp-edges',\n }}\n {...props}\n >\n <path\n className={arrowFillStyle}\n d=\"M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z\"\n />\n </svg>\n );\n};\n\nexport const StyledTooltipArrow = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof Tooltip.Arrow>\n>(({ className, ...props }, ref) => (\n <Tooltip.Arrow\n ref={ref}\n className={cx(\n tooltipArrowStyle,\n typeof className === 'string' ? className : undefined\n )}\n {...props}\n />\n));\n\nStyledTooltipArrow.displayName = 'StyledTooltipArrow';\n"],"names":[],"mappings":";;;;;;;AASO;AACL;;AAQM;AACA;AACD;AASP;AAEO;AAcP;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../../../../src/components/primitives/Tooltip/Tooltip.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;AA8HA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFG;AACI;;;AAuBH;;;;;;AAQA;AACI;AACE;AACA;AACA;AACqB;AACxB;AACH;;AAGF;;AASA;;;AAGE;AACA;;;AAGA;;;;AAKA;;;AAGI;;;;AAGF;;;;;AAMJ;;AAEE;;;;;AAMF;AAEE;AACA;;AAEF;AACA;;AAGE;;AAEG;AACH;;AAkCgB;AACA;;;AAoBpB;AAEA;;"}
1
+ {"version":3,"file":"Tooltip.js","sources":["src/components/primitives/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client';\n\n// src/components/primitives/Tooltip/Tooltip.tsx\nimport { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { ArrowSvg, StyledTooltipArrow } from './Arrow';\nimport { tooltipContentStyle, tooltipTriggerStyle } from './Tooltip.css';\nimport {\n CollisionAvoidance,\n TooltipAnimation,\n TooltipCollisionConfig,\n TooltipCollisionStrategy,\n TooltipPlacement,\n TooltipPositioner,\n BaseTooltipPositionerProps,\n BaseTooltipRootProps,\n} from './types';\nimport { parseCollisionStrategy, parsePlacement } from './utils';\n\nimport type { Prettify } from '@/types/utilities';\n\ninterface TooltipBaseProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'css' | 'title'\n> {\n /**\n * The trigger element that will show the tooltip on hover.\n * Must be a single React element or component.\n *\n * @example\n * <Button>Hover me</Button>\n * <IconButton><SaveIcon /></IconButton>\n */\n children: React.ReactElement;\n\n /**\n * The content to display in the tooltip.\n * Can be simple text or a complex React node for advanced customization.\n *\n * @example\n * \"Save file\"\n * <div><strong>Save</strong><br />Ctrl+S</div>\n */\n title: React.ReactNode;\n\n /**\n * Intuitive placement similar to MUI\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n\n /**\n * Collision handling strategy\n * @default \"smart\"\n */\n collision?: TooltipCollisionStrategy;\n\n /**\n * Advanced collision configuration for power users\n * When provided, overrides the collision strategy\n */\n collisionConfig?: TooltipCollisionConfig;\n\n /**\n * Advanced positioning configuration\n */\n positioner?: TooltipPositioner;\n\n /**\n * Animation configuration\n */\n animation?: TooltipAnimation;\n\n /**\n * Delay in milliseconds before showing the tooltip\n * @default 600\n */\n delay?: number;\n\n /**\n * Delay in milliseconds before hiding the tooltip\n * @default 0\n */\n closeDelay?: number;\n\n /**\n * Whether to show the arrow pointing to the trigger\n * @default true\n */\n arrow?: boolean;\n\n /**\n * Whether the tooltip is disabled\n * When true, tooltip will not appear\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Direct props passed to Base UI Root component\n * For power users who need full control\n */\n rootProps?: Partial<BaseTooltipRootProps>;\n\n /**\n * Direct props passed to Base UI Positioner component\n * For power users who need full control\n */\n positionerProps?: Partial<BaseTooltipPositionerProps>;\n\n /**\n * Test identifier for automated testing\n */\n testId?: string;\n\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Props for the Tooltip component with prettified type for better IntelliSense\n */\nexport type TooltipProps = Prettify<TooltipBaseProps>;\n\n/**\n * A tooltip component that displays contextual information on hover.\n *\n * Built on @base-ui/react for robust accessibility and positioning.\n * Provides an intuitive API similar to MUI with advanced positioning and collision handling.\n * Supports both simple text and complex React nodes for advanced tooltip content.\n *\n * @example\n * ```tsx\n * // Simple text tooltip\n * <Tooltip title=\"Save your work\">\n * <Button>Save</Button>\n * </Tooltip>\n *\n * // Intuitive positioning (MUI-style)\n * <Tooltip placement=\"bottom-start\" title=\"Menu options\">\n * <IconButton><MenuIcon /></IconButton>\n * </Tooltip>\n *\n * // Intelligent collision handling (new default)\n * <Tooltip collision=\"smart\" title=\"Intelligent positioning\">\n * <Button>Smart tooltip</Button>\n * </Tooltip>\n *\n * // Advanced collision configuration\n * <Tooltip\n * collisionConfig={{\n * side: 'flip',\n * align: 'shift',\n * fallbackAxisSide: 'start',\n * hideWhenDetached: true\n * }}\n * title=\"Custom collision handling\"\n * >\n * <Button>Advanced collision</Button>\n * </Tooltip>\n *\n * // Advanced positioning\n * <Tooltip\n * positioner={{\n * offset: 12,\n * padding: 10,\n * sticky: true,\n * boundary: '#container'\n * }}\n * title=\"Advanced positioning\"\n * >\n * <Button>Advanced</Button>\n * </Tooltip>\n *\n * // Custom animations\n * <Tooltip\n * animation={{\n * animated: true,\n * duration: 300,\n * easing: 'ease-in-out'\n * }}\n * title=\"Custom animation\"\n * >\n * <Button>Animated</Button>\n * </Tooltip>\n *\n * // Interactive tooltip\n * <Tooltip\n * hoverable={true}\n * closeDelay={300}\n * title={\n * <div>\n * <strong>Interactive Content</strong>\n * <br />\n * <button>Click me</button>\n * </div>\n * }\n * >\n * <Button>Hoverable tooltip</Button>\n * </Tooltip>\n *\n * // Full control with raw props\n * <Tooltip\n * arrow={false}\n * rootProps={{ trackCursorAxis: 'x' }}\n * positionerProps={{ arrowPadding: 20 }}\n * title=\"Full control\"\n * >\n * <Button>Power user</Button>\n * </Tooltip>\n * ```\n */\nexport const Tooltip: React.FC<TooltipProps> = ({\n children,\n title,\n placement = 'top',\n collision = 'smart',\n collisionConfig,\n positioner = {},\n animation = {},\n delay = 600,\n closeDelay = 0,\n arrow = true,\n disabled = false,\n rootProps = {},\n positionerProps = {},\n className,\n testId,\n id,\n style,\n ref,\n ...htmlProps\n}) => {\n // If disabled, return just the children without tooltip\n if (disabled) {\n return children;\n }\n\n // Parse placement into side and align\n const { side, align } = parsePlacement(placement);\n\n // Parse collision strategy or use custom config\n const collisionSettings = collisionConfig\n ? {\n collisionAvoidance: {\n side: collisionConfig.side ?? 'flip',\n align: collisionConfig.align ?? 'shift',\n fallbackAxisSide: collisionConfig.fallbackAxisSide ?? 'none',\n } as CollisionAvoidance,\n }\n : parseCollisionStrategy(collision);\n\n // Prepare positioner configuration\n const {\n offset = 8,\n padding = 8,\n sticky = false,\n boundary,\n trackCursor,\n } = positioner;\n\n // Prepare final positioner props\n const finalPositionerProps: Partial<BaseTooltipPositionerProps> = {\n side,\n align,\n sideOffset: offset,\n collisionPadding: padding,\n sticky,\n collisionAvoidance: collisionSettings.collisionAvoidance,\n ...positionerProps,\n };\n\n // Handle boundary if specified\n if (boundary) {\n if (typeof boundary === 'string') {\n const boundaryElement = document.querySelector(boundary);\n if (boundaryElement) {\n finalPositionerProps.collisionBoundary = boundaryElement;\n }\n } else {\n finalPositionerProps.collisionBoundary = boundary;\n }\n }\n\n // Handle cursor tracking. Copy into a local object instead of mutating the\n // caller-owned `rootProps` prop.\n const finalRootProps: Partial<BaseTooltipRootProps> = { ...rootProps };\n if (trackCursor) {\n finalRootProps.trackCursorAxis = trackCursor;\n }\n\n // Build animation transition style. Honors `prefers-reduced-motion: reduce`\n // by collapsing to `transition: none` regardless of caller-passed config —\n // user OS-level preference always wins over component config.\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n const animated = animation.animated !== false && !prefersReducedMotion;\n const duration = animation.duration ?? 200;\n const easing = animation.easing ?? 'ease-out';\n\n const animationStyle: React.CSSProperties = animated\n ? {\n transition: `opacity ${duration}ms ${easing}, transform ${duration}ms ${easing}`,\n }\n : { transition: 'none' };\n\n return (\n <BaseTooltip.Provider\n delay={delay}\n closeDelay={closeDelay}\n {...finalRootProps}\n >\n <BaseTooltip.Root>\n <BaseTooltip.Trigger\n render={props => (\n <div\n {...props}\n className={cx(tooltipTriggerStyle, props.className)}\n />\n )}\n >\n {children}\n </BaseTooltip.Trigger>\n\n <BaseTooltip.Portal>\n <BaseTooltip.Positioner {...finalPositionerProps}>\n <BaseTooltip.Popup\n render={props => (\n <div\n {...props}\n className={cx(\n tooltipContentStyle,\n className,\n props.className\n )}\n data-testid={testId}\n id={id}\n style={{\n ...animationStyle,\n ...style,\n ...props.style,\n }}\n ref={ref}\n {...htmlProps}\n >\n {title}\n {arrow && (\n <StyledTooltipArrow>\n <ArrowSvg />\n </StyledTooltipArrow>\n )}\n </div>\n )}\n />\n </BaseTooltip.Positioner>\n </BaseTooltip.Portal>\n </BaseTooltip.Root>\n </BaseTooltip.Provider>\n );\n};\n\nTooltip.displayName = 'Tooltip';\n"],"names":[],"mappings":";;;;;;;;AA8HA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFG;AACI;;;AAuBH;;;;;;AAQA;AACI;AACE;AACA;AACA;AACqB;AACxB;AACH;;AAGF;;AASA;;;AAGE;AACA;;;AAGA;;;;AAKA;;;AAGI;;;;AAGF;;;;;AAMJ;;AAEE;;;;;AAMF;AAEE;AACA;;AAEF;AACA;;AAGE;;AAEG;AACH;;AAkCgB;AACA;;;AAoBpB;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../../../src/components/primitives/Tooltip/utils.ts"],"sourcesContent":[null],"names":[],"mappings":"AAOA;;AAEG;AACI,MAAM,cAAc,GAAG,CAAC,SAA2B,KAAI;AAC5D,IAAA,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAGnD;AACD,IAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;AACxB;AAEA;;AAEG;AACI,MAAM,sBAAsB,GAAG,CACpC,QAAkC,KAIhC;IACF,QAAQ,QAAQ;AACd,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,MAAM;AACb,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,OAAO;AACb,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE,SAAS;AAC7B,gBAAA,gBAAgB,EAAE,IAAI;aACvB;AAEH,QAAA,KAAK,YAAY;YACf,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,OAAO;AAC1B,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE,SAAS;aAC9B;AAEH,QAAA;YACE,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,OAAO;AAC1B,iBAAA;aACF;;AAEP;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["src/components/primitives/Tooltip/utils.ts"],"sourcesContent":["import type {\n TooltipPlacement,\n TooltipCollisionStrategy,\n BaseTooltipPositionerProps,\n CollisionAvoidance,\n} from './types';\n\n/**\n * Convert our placement prop to Base UI side and align\n */\nexport const parsePlacement = (placement: TooltipPlacement) => {\n const [side, align = 'center'] = placement.split('-') as [\n BaseTooltipPositionerProps['side'],\n BaseTooltipPositionerProps['align']?,\n ];\n return { side, align };\n};\n\n/**\n * Convert collision strategy to Base UI CollisionAvoidance config\n */\nexport const parseCollisionStrategy = (\n strategy: TooltipCollisionStrategy\n): {\n collisionAvoidance: CollisionAvoidance;\n hideWhenDetached?: boolean;\n} => {\n switch (strategy) {\n case 'flip':\n return {\n collisionAvoidance: {\n side: 'flip',\n align: 'none',\n fallbackAxisSide: 'none',\n },\n };\n\n case 'shift':\n return {\n collisionAvoidance: {\n side: 'shift',\n align: 'shift',\n fallbackAxisSide: 'none',\n },\n };\n\n case 'hide':\n return {\n collisionAvoidance: undefined,\n hideWhenDetached: true,\n };\n\n case 'flip-shift':\n return {\n collisionAvoidance: {\n side: 'flip',\n align: 'shift',\n fallbackAxisSide: 'none',\n },\n };\n\n case 'smart':\n return {\n collisionAvoidance: {\n side: 'flip',\n align: 'shift',\n fallbackAxisSide: 'start',\n },\n };\n\n case 'none':\n return {\n collisionAvoidance: undefined,\n };\n\n default:\n return {\n collisionAvoidance: {\n side: 'flip',\n align: 'shift',\n fallbackAxisSide: 'start',\n },\n };\n }\n};\n"],"names":[],"mappings":"AAOA;;AAEG;AACI,MAAM,cAAc,GAAG,CAAC,SAA2B,KAAI;AAC5D,IAAA,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAGnD;AACD,IAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;AACxB;AAEA;;AAEG;AACI,MAAM,sBAAsB,GAAG,CACpC,QAAkC,KAIhC;IACF,QAAQ,QAAQ;AACd,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,MAAM;AACb,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,OAAO;AACb,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE,SAAS;AAC7B,gBAAA,gBAAgB,EAAE,IAAI;aACvB;AAEH,QAAA,KAAK,YAAY;YACf,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,MAAM;AACzB,iBAAA;aACF;AAEH,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,OAAO;AAC1B,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,kBAAkB,EAAE,SAAS;aAC9B;AAEH,QAAA;YACE,OAAO;AACL,gBAAA,kBAAkB,EAAE;AAClB,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,OAAO;AACd,oBAAA,gBAAgB,EAAE,OAAO;AAC1B,iBAAA;aACF;;AAEP;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"VisuallyHidden.js","sources":["../../../../../../src/components/primitives/VisuallyHidden/VisuallyHidden.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAaA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;AACI;AAWH;AAcF;AAGF;;"}
1
+ {"version":3,"file":"VisuallyHidden.js","sources":["src/components/primitives/VisuallyHidden/VisuallyHidden.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n visuallyHiddenStyle,\n visuallyHiddenFocusableStyle,\n} from './VisuallyHidden.css';\n\nimport type { VisuallyHiddenProps } from './VisuallyHidden.types';\n\n/**\n * Hides content visually while keeping it accessible to screen readers.\n *\n * Implements the canonical `sr-only` / `visually-hidden` pattern. Use it for\n * screen-reader-only labels, additional context next to icons, and\n * skip-to-content links (with `focusable`).\n *\n * Don't use this to hide content from sighted users for layout reasons —\n * that's `display: none`. This component keeps content in the accessibility\n * tree on purpose.\n *\n * @example\n * ```tsx\n * // SR-only label next to an icon-only button\n * <button>\n * <SearchIcon />\n * <VisuallyHidden>Search</VisuallyHidden>\n * </button>\n *\n * // Skip link revealed on focus\n * <VisuallyHidden as=\"a\" href=\"#main\" focusable>\n * Skip to content\n * </VisuallyHidden>\n * ```\n */\nexport const VisuallyHidden = /*#__PURE__*/ React.memo<VisuallyHiddenProps>(\n ({\n as: Component = 'span',\n focusable = false,\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n return (\n <Component\n ref={ref as React.Ref<never>}\n className={cx(\n focusable ? visuallyHiddenFocusableStyle : visuallyHiddenStyle,\n className\n )}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </Component>\n );\n }\n);\n\nVisuallyHidden.displayName = 'VisuallyHidden';\n"],"names":[],"mappings":";;;;;;AAaA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;AACI;AAWH;AAcF;AAGF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasContainer.js","sources":["../../../../../../src/components/primitives/canvas/CanvasContainer.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAcA;;;;;;;;;;;AAWG;AACI;AAeL;AAEA;AAKM;AACA;AACE;;;AAGH;AAsBP;AAEA;;"}
1
+ {"version":3,"file":"CanvasContainer.js","sources":["src/components/primitives/canvas/CanvasContainer.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, { useRef } from 'react';\n\nimport {\n canvasContainerRecipe,\n canvasContainerHeightVar,\n canvasRecipe,\n ariaLiveRegionStyle,\n} from './CanvasContainer.css';\n\nimport type { CanvasContainerProps } from './canvas.types';\n\n/**\n * Styled container + canvas + a11y live region.\n *\n * Provides the boilerplate every canvas control needs:\n * - Responsive or fixed-height container\n * - Canvas element with proper styling\n * - Screen reader announcements region\n * - Disabled opacity\n * - Focus-visible ring\n *\n * Does NOT manage rendering — consumers use useCanvasSetup + useCanvasRenderer.\n */\nexport const CanvasContainer: React.FC<CanvasContainerProps> = ({\n canvasRef,\n height = 200,\n responsive = false,\n disabled = false,\n role = 'application',\n ariaLabel,\n ariaRoledescription,\n liveAnnouncement,\n handlers,\n className,\n style,\n testId,\n id,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n return (\n <div\n ref={containerRef}\n className={`${canvasContainerRecipe({ responsive })}${className ? ` ${className}` : ''}`}\n style={{\n ...style,\n ...assignInlineVars({\n [canvasContainerHeightVar]: `${height}px`,\n }),\n minHeight: `${height}px`,\n }}\n id={id}\n data-testid={testId}\n >\n <canvas\n ref={canvasRef}\n className={canvasRecipe({ disabled })}\n role={role}\n aria-label={ariaLabel}\n aria-roledescription={ariaRoledescription}\n tabIndex={disabled ? -1 : 0}\n onPointerDown={handlers?.onPointerDown}\n onPointerMove={handlers?.onPointerMove}\n onPointerUp={handlers?.onPointerUp}\n onDoubleClick={handlers?.onDoubleClick}\n onKeyDown={handlers?.onKeyDown}\n />\n <div className={ariaLiveRegionStyle} aria-live=\"polite\" role=\"status\">\n {liveAnnouncement}\n </div>\n </div>\n );\n};\n\nCanvasContainer.displayName = 'CanvasContainer';\n"],"names":[],"mappings":";;;;;;AAcA;;;;;;;;;;;AAWG;AACI;AAeL;AAEA;AAKM;AACA;AACE;;;AAGH;AAsBP;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvasCoords.js","sources":["../../../../../../src/components/primitives/canvas/canvasCoords.ts"],"sourcesContent":[null],"names":[],"mappings":"AAEA;;;;AAIG;AACG,SAAU,cAAc,CAC5B,OAAe,EACf,OAAe,EACf,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EAAA;IAEpB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;IACrC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;AAErC,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAC7B,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAE7B,IAAA,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE,IAAI,WAAW;AACjD,IAAA,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,OAAO,IAAI,EAAE,IAAI,YAAY;AAElD,IAAA,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE;AACnB;AAEA;;;;AAIG;AACG,SAAU,cAAc,CAC5B,EAAU,EACV,EAAU,EACV,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EAAA;IAEpB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;IACrC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;AAErC,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAC7B,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;IAE7B,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,GAAG,WAAW,IAAI,EAAE;IACzC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,GAAG,YAAY,IAAI,EAAE;AAE1C,IAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE;AACjB;AAEA;;;;AAIG;SACa,YAAY,CAC1B,EAAU,EACV,EAAU,EACV,KAAc,EACd,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EACpB,cAAsB,EAAE,EAAA;AAExB,IAAA,MAAM,MAAM,GAAG,cAAc,CAC3B,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,EACP,QAAQ,EACR,WAAW,EACX,YAAY,CACb;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IACrE,OAAO,IAAI,IAAI,WAAW,GAAG,IAAI,GAAG,QAAQ;AAC9C;AAEA;;AAEG;AACG,SAAU,wBAAwB,CACtC,CAAuC,EACvC,MAAyB,EAAA;AAEzB,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE;IAC3C,OAAO;AACL,QAAA,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;AACzB,QAAA,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;KACzB;AACH;;;;"}
1
+ {"version":3,"file":"canvasCoords.js","sources":["src/components/primitives/canvas/canvasCoords.ts"],"sourcesContent":["import type { CanvasViewport, Point2D } from './canvas.types';\n\n/**\n * Convert domain coordinates to canvas pixel coordinates.\n *\n * Y axis is flipped: domain Y goes up, canvas Y goes down.\n */\nexport function domainToCanvas(\n domainX: number,\n domainY: number,\n viewport: CanvasViewport,\n canvasWidth: number,\n canvasHeight: number\n): { px: number; py: number } {\n const [vxMin, vxMax] = viewport.viewX;\n const [vyMin, vyMax] = viewport.viewY;\n\n const vw = vxMax - vxMin || 1;\n const vh = vyMax - vyMin || 1;\n\n const px = ((domainX - vxMin) / vw) * canvasWidth;\n const py = ((vyMax - domainY) / vh) * canvasHeight;\n\n return { px, py };\n}\n\n/**\n * Convert canvas pixel coordinates to domain coordinates.\n *\n * Inverse of domainToCanvas — Y axis is flipped.\n */\nexport function canvasToDomain(\n px: number,\n py: number,\n viewport: CanvasViewport,\n canvasWidth: number,\n canvasHeight: number\n): Point2D {\n const [vxMin, vxMax] = viewport.viewX;\n const [vyMin, vyMax] = viewport.viewY;\n\n const vw = vxMax - vxMin || 1;\n const vh = vyMax - vyMin || 1;\n\n const x = vxMin + (px / canvasWidth) * vw;\n const y = vyMax - (py / canvasHeight) * vh;\n\n return { x, y };\n}\n\n/**\n * Test whether a canvas pixel position is within tolerance of a domain point.\n *\n * @returns Distance in pixels, or Infinity if outside tolerance\n */\nexport function hitTestPoint(\n px: number,\n py: number,\n point: Point2D,\n viewport: CanvasViewport,\n canvasWidth: number,\n canvasHeight: number,\n tolerancePx: number = 10\n): number {\n const target = domainToCanvas(\n point.x,\n point.y,\n viewport,\n canvasWidth,\n canvasHeight\n );\n const dist = Math.sqrt((px - target.px) ** 2 + (py - target.py) ** 2);\n return dist <= tolerancePx ? dist : Infinity;\n}\n\n/**\n * Get the canvas-pixel position of a pointer event relative to the canvas.\n */\nexport function getCanvasPointerPosition(\n e: { clientX: number; clientY: number },\n canvas: HTMLCanvasElement\n): { px: number; py: number } {\n const rect = canvas.getBoundingClientRect();\n return {\n px: e.clientX - rect.left,\n py: e.clientY - rect.top,\n };\n}\n"],"names":[],"mappings":"AAEA;;;;AAIG;AACG,SAAU,cAAc,CAC5B,OAAe,EACf,OAAe,EACf,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EAAA;IAEpB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;IACrC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;AAErC,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAC7B,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAE7B,IAAA,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE,IAAI,WAAW;AACjD,IAAA,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,OAAO,IAAI,EAAE,IAAI,YAAY;AAElD,IAAA,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE;AACnB;AAEA;;;;AAIG;AACG,SAAU,cAAc,CAC5B,EAAU,EACV,EAAU,EACV,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EAAA;IAEpB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;IACrC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK;AAErC,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;AAC7B,IAAA,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,CAAC;IAE7B,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,GAAG,WAAW,IAAI,EAAE;IACzC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,GAAG,YAAY,IAAI,EAAE;AAE1C,IAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE;AACjB;AAEA;;;;AAIG;SACa,YAAY,CAC1B,EAAU,EACV,EAAU,EACV,KAAc,EACd,QAAwB,EACxB,WAAmB,EACnB,YAAoB,EACpB,cAAsB,EAAE,EAAA;AAExB,IAAA,MAAM,MAAM,GAAG,cAAc,CAC3B,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,CAAC,EACP,QAAQ,EACR,WAAW,EACX,YAAY,CACb;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IACrE,OAAO,IAAI,IAAI,WAAW,GAAG,IAAI,GAAG,QAAQ;AAC9C;AAEA;;AAEG;AACG,SAAU,wBAAwB,CACtC,CAAuC,EACvC,MAAyB,EAAA;AAEzB,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE;IAC3C,OAAO;AACL,QAAA,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;AACzB,QAAA,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;KACzB;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvasDrawing.js","sources":["../../../../../../src/components/primitives/canvas/canvasDrawing.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canvasDrawing.js","sources":["src/components/primitives/canvas/canvasDrawing.ts"],"sourcesContent":["import { clamp } from '@/utils/mathUtils';\n\nimport { domainToCanvas } from './canvasCoords';\n\nimport type {\n CanvasViewport,\n DomainBounds,\n CanvasThemeColors,\n GridOptions,\n AxisLabelOptions,\n CrosshairOptions,\n PointMarkerOptions,\n} from './canvas.types';\n\n/**\n * Format a number for axis labels.\n * Integers show as \"0\", \"1\". Clean fractions show as \"0.25\", \"0.5\".\n * Others show with minimal decimals needed.\n */\nexport function formatLabel(value: number, domainRange: number): string {\n const rounded = Math.round(value * 1e10) / 1e10;\n if (Number.isInteger(rounded)) return rounded.toFixed(0);\n\n if (domainRange <= 1) {\n const str = rounded.toFixed(2);\n if (str.endsWith('0')) return rounded.toFixed(1);\n return str;\n }\n\n if (domainRange <= 10) return rounded.toFixed(1);\n return rounded.toFixed(0);\n}\n\n/**\n * Draw grid lines at clean domain values.\n * Grid lines subdivide the domain range into equal parts.\n *\n * Extracted from CurveEditor's drawGrid — identical visual output.\n */\nexport function drawGrid(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n options: GridOptions\n): void {\n const { subdivisions, domain, viewport, opacity = 1 } = options;\n const { domainX, domainY } = domain;\n const dxRange = domainX[1] - domainX[0] || 1;\n const dyRange = domainY[1] - domainY[0] || 1;\n\n ctx.lineWidth = 1;\n\n // Vertical grid lines (subdivide domain X)\n const xStep = dxRange / subdivisions;\n for (let i = 0; i <= subdivisions; i++) {\n const domX = domainX[0] + i * xStep;\n const { px } = domainToCanvas(domX, 0, viewport, w, h);\n const isBound = i === 0 || i === subdivisions;\n ctx.globalAlpha = opacity * (isBound ? 0.25 : 0.12);\n ctx.strokeStyle = theme.borderDefault;\n ctx.beginPath();\n ctx.moveTo(Math.round(px) + 0.5, 0);\n ctx.lineTo(Math.round(px) + 0.5, h);\n ctx.stroke();\n }\n\n // Horizontal grid lines (subdivide domain Y)\n const yStep = dyRange / subdivisions;\n for (let i = 0; i <= subdivisions; i++) {\n const domY = domainY[0] + i * yStep;\n const { py } = domainToCanvas(0, domY, viewport, w, h);\n const isBound = i === 0 || i === subdivisions;\n ctx.globalAlpha = opacity * (isBound ? 0.25 : 0.12);\n ctx.strokeStyle = theme.borderDefault;\n ctx.beginPath();\n ctx.moveTo(0, Math.round(py) + 0.5);\n ctx.lineTo(w, Math.round(py) + 0.5);\n ctx.stroke();\n }\n}\n\n/**\n * Draw stronger lines at the domain boundaries (min/max on both axes).\n */\nexport function drawDomainBounds(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n domain: DomainBounds,\n viewport: CanvasViewport,\n opacity: number = 1\n): void {\n const { domainX, domainY } = domain;\n\n ctx.globalAlpha = opacity * 0.35;\n ctx.strokeStyle = theme.borderDefault;\n ctx.lineWidth = 1.5;\n\n const { px: pxMin } = domainToCanvas(domainX[0], 0, viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(Math.round(pxMin) + 0.5, 0);\n ctx.lineTo(Math.round(pxMin) + 0.5, h);\n ctx.stroke();\n\n const { px: pxMax } = domainToCanvas(domainX[1], 0, viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(Math.round(pxMax) + 0.5, 0);\n ctx.lineTo(Math.round(pxMax) + 0.5, h);\n ctx.stroke();\n\n const { py: pyMin } = domainToCanvas(0, domainY[0], viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(0, Math.round(pyMin) + 0.5);\n ctx.lineTo(w, Math.round(pyMin) + 0.5);\n ctx.stroke();\n\n const { py: pyMax } = domainToCanvas(0, domainY[1], viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(0, Math.round(pyMax) + 0.5);\n ctx.lineTo(w, Math.round(pyMax) + 0.5);\n ctx.stroke();\n}\n\n/**\n * Draw axis labels at clean domain values.\n *\n * Y labels on the left side, X labels at the bottom.\n * Extracted from CurveEditor's drawAxisLabels — identical layout algorithm.\n */\nexport function drawAxisLabels(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n options: AxisLabelOptions\n): void {\n const {\n subdivisions,\n domain,\n viewport,\n opacity = 1,\n labelX,\n labelY,\n } = options;\n const { domainX, domainY } = domain;\n const dxRange = domainX[1] - domainX[0] || 1;\n const dyRange = domainY[1] - domainY[0] || 1;\n\n const fontSize = theme.fontSizeXs;\n ctx.globalAlpha = opacity * 0.7;\n ctx.fillStyle = theme.textMuted;\n ctx.font = `${fontSize}px sans-serif`;\n\n const sidePadding = 4;\n const axisGap = 6;\n\n const { px: xAxisMin } = domainToCanvas(domainX[0], 0, viewport, w, h);\n const { px: xAxisMax } = domainToCanvas(domainX[1], 0, viewport, w, h);\n const { py: yAxisMin } = domainToCanvas(0, domainY[0], viewport, w, h);\n const { py: yAxisMax } = domainToCanvas(0, domainY[1], viewport, w, h);\n\n const xTickTop = clamp(\n yAxisMin + axisGap,\n yAxisMax + 2,\n h - fontSize - (labelX ? fontSize + 8 : 2)\n );\n const xAxisLabelTop = labelX\n ? clamp(xTickTop + fontSize + 4, 0, h - fontSize - 1)\n : 0;\n\n const yTickAnchorX = clamp(\n xAxisMin - axisGap,\n sidePadding + 1,\n w - sidePadding\n );\n const yTickMinY = fontSize / 2 + 2;\n const yTickMaxY = Math.max(yTickMinY, xTickTop - 2);\n const yAxisLabelTop = clamp(\n yAxisMax - fontSize - 4,\n sidePadding,\n Math.max(sidePadding, xTickTop - fontSize - 6)\n );\n\n // X axis labels (bottom, aligned to domain subdivisions)\n ctx.textBaseline = 'top';\n const xStep = dxRange / subdivisions;\n for (let i = 0; i <= subdivisions; i++) {\n const domX = domainX[0] + i * xStep;\n const { px } = domainToCanvas(domX, 0, viewport, w, h);\n const label = formatLabel(domX, dxRange);\n\n if (i === 0) {\n ctx.textAlign = 'left';\n ctx.fillText(label, xAxisMin + 2, xTickTop);\n } else if (i === subdivisions) {\n ctx.textAlign = 'right';\n ctx.fillText(label, xAxisMax - 2, xTickTop);\n } else {\n ctx.textAlign = 'center';\n ctx.fillText(label, clamp(px, xAxisMin + 2, xAxisMax - 2), xTickTop);\n }\n }\n\n // Y axis labels (left side, aligned to domain subdivisions)\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n const yStep = dyRange / subdivisions;\n for (let i = 0; i <= subdivisions; i++) {\n const domY = domainY[0] + i * yStep;\n const { py } = domainToCanvas(0, domY, viewport, w, h);\n const label = formatLabel(domY, dyRange);\n\n const clampedPy = clamp(py, yTickMinY, yTickMaxY);\n ctx.fillText(label, yTickAnchorX, clampedPy);\n }\n\n // Axis name labels\n if (labelX) {\n const textWidth = ctx.measureText(labelX).width;\n const x = clamp(\n xAxisMax + axisGap,\n sidePadding,\n w - sidePadding - textWidth\n );\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.fillText(labelX, x, xAxisLabelTop);\n }\n if (labelY) {\n const x = clamp(xAxisMin + axisGap, sidePadding, w - sidePadding);\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.fillText(labelY, x, yAxisLabelTop);\n }\n}\n\n/**\n * Draw crosshair lines through a point.\n *\n * Used by CartesianPicker to show the current selection.\n * Can be solid or dashed, full-span or limited to domain bounds.\n */\nexport function drawCrosshair(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n options: CrosshairOptions\n): void {\n const {\n point,\n viewport,\n lineStyle = 'dashed',\n lineWidth = 1,\n fullSpan = true,\n opacity = 1,\n } = options;\n\n const { px, py } = domainToCanvas(point.x, point.y, viewport, w, h);\n\n ctx.globalAlpha = opacity * 0.6;\n ctx.strokeStyle = theme.accentPrimary;\n ctx.lineWidth = lineWidth;\n\n if (lineStyle === 'dashed') {\n ctx.setLineDash([4, 4]);\n } else {\n ctx.setLineDash([]);\n }\n\n // Vertical line through point\n ctx.beginPath();\n ctx.moveTo(Math.round(px) + 0.5, fullSpan ? 0 : py - 20);\n ctx.lineTo(Math.round(px) + 0.5, fullSpan ? h : py + 20);\n ctx.stroke();\n\n // Horizontal line through point\n ctx.beginPath();\n ctx.moveTo(fullSpan ? 0 : px - 20, Math.round(py) + 0.5);\n ctx.lineTo(fullSpan ? w : px + 20, Math.round(py) + 0.5);\n ctx.stroke();\n\n ctx.setLineDash([]);\n}\n\n/**\n * Draw a circular point marker.\n *\n * Used by CartesianPicker for the selected point.\n * Supports hover and drag visual states.\n */\nexport function drawPointMarker(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n options: PointMarkerOptions\n): void {\n const {\n point,\n viewport,\n radius = 6,\n hovered = false,\n dragging = false,\n opacity = 1,\n } = options;\n\n const { px, py } = domainToCanvas(point.x, point.y, viewport, w, h);\n const effectiveRadius = hovered || dragging ? radius + 2 : radius;\n\n ctx.globalAlpha = opacity;\n\n // Outer ring\n ctx.beginPath();\n ctx.arc(px, py, effectiveRadius, 0, Math.PI * 2);\n ctx.fillStyle = dragging ? theme.accentPrimary : theme.backgroundSecondary;\n ctx.fill();\n ctx.strokeStyle = theme.accentPrimary;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Inner dot\n ctx.beginPath();\n ctx.arc(px, py, 2, 0, Math.PI * 2);\n ctx.fillStyle = theme.accentPrimary;\n ctx.fill();\n}\n\n/**\n * Draw axis origin lines (X=0 and Y=0 if visible within viewport).\n *\n * Useful for CartesianPicker where domain is centered on origin.\n */\nexport function drawOriginAxes(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: CanvasThemeColors,\n viewport: CanvasViewport,\n opacity: number = 1\n): void {\n const [vxMin, vxMax] = viewport.viewX;\n const [vyMin, vyMax] = viewport.viewY;\n\n ctx.globalAlpha = opacity * 0.5;\n ctx.strokeStyle = theme.textMuted;\n ctx.lineWidth = 1;\n\n // Y axis (x = 0) if in viewport\n if (vxMin <= 0 && vxMax >= 0) {\n const { px } = domainToCanvas(0, 0, viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(Math.round(px) + 0.5, 0);\n ctx.lineTo(Math.round(px) + 0.5, h);\n ctx.stroke();\n }\n\n // X axis (y = 0) if in viewport\n if (vyMin <= 0 && vyMax >= 0) {\n const { py } = domainToCanvas(0, 0, viewport, w, h);\n ctx.beginPath();\n ctx.moveTo(0, Math.round(py) + 0.5);\n ctx.lineTo(w, Math.round(py) + 0.5);\n ctx.stroke();\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvasTheme.js","sources":["../../../../../../src/components/primitives/canvas/canvasTheme.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;;;AAGG;AACH,SAAS,UAAU,CAAC,OAAgB,EAAE,MAAc,EAAA;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC;AAC5C,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,MAAM;AACzB,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;AACxB,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,MAAM;AAC3B,IAAA,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,MAAM;AAC7E;AAEA;;;;;;AAMG;AACG,SAAU,kBAAkB,CAChC,MAAyB,EAAA;IAEzB,OAAO;AACL,QAAA,mBAAmB,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;AACzE,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7D,QAAA,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACrD,QAAA,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACzD,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7D,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7D,QAAA,UAAU,EACR,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;KACpE;AACH;AAEA;;;AAGG;AACG,SAAU,eAAe,CAAC,OAAgB,EAAE,MAAc,EAAA;AAC9D,IAAA,OAAO,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;AACpC;;;;"}
1
+ {"version":3,"file":"canvasTheme.js","sources":["src/components/primitives/canvas/canvasTheme.ts"],"sourcesContent":["import { vars } from '@/theme/contract.css';\n\nimport type { CanvasThemeColors } from './canvas.types';\n\n/**\n * Resolve CSS variable references (e.g., `var(--etui-color-text-primary)`)\n * to their computed values via getComputedStyle.\n */\nfunction resolveVar(element: Element, cssVar: string): string {\n const match = cssVar.match(/var\\(([^)]+)\\)/);\n if (!match) return cssVar;\n const varName = match[1];\n if (!varName) return cssVar;\n return getComputedStyle(element).getPropertyValue(varName).trim() || cssVar;\n}\n\n/**\n * Resolve Vanilla Extract CSS variables from a canvas element to\n * actual color values for canvas 2D drawing.\n *\n * Canvas 2D contexts cannot read CSS variables — this resolves them\n * via getComputedStyle.\n */\nexport function resolveCanvasTheme(\n canvas: HTMLCanvasElement\n): CanvasThemeColors {\n return {\n backgroundSecondary: resolveVar(canvas, vars.colors.background.secondary),\n borderDefault: resolveVar(canvas, vars.colors.border.default),\n textMuted: resolveVar(canvas, vars.colors.text.muted),\n textPrimary: resolveVar(canvas, vars.colors.text.primary),\n textSecondary: resolveVar(canvas, vars.colors.text.secondary),\n accentPrimary: resolveVar(canvas, vars.colors.accent.primary),\n fontSizeXs:\n parseFloat(resolveVar(canvas, vars.typography.fontSize.xs)) || 10,\n };\n}\n\n/**\n * Resolve a single CSS variable reference string (e.g. `var(--etui-color-accent-primary)`)\n * to its computed value.\n */\nexport function resolveVarValue(element: Element, cssVar: string): string {\n return resolveVar(element, cssVar);\n}\n"],"names":[],"mappings":";;AAIA;;;AAGG;AACH,SAAS,UAAU,CAAC,OAAgB,EAAE,MAAc,EAAA;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC;AAC5C,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,MAAM;AACzB,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;AACxB,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,MAAM;AAC3B,IAAA,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,MAAM;AAC7E;AAEA;;;;;;AAMG;AACG,SAAU,kBAAkB,CAChC,MAAyB,EAAA;IAEzB,OAAO;AACL,QAAA,mBAAmB,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;AACzE,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7D,QAAA,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACrD,QAAA,WAAW,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACzD,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7D,QAAA,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7D,QAAA,UAAU,EACR,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;KACpE;AACH;AAEA;;;AAGG;AACG,SAAU,eAAe,CAAC,OAAgB,EAAE,MAAc,EAAA;AAC9D,IAAA,OAAO,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;AACpC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCanvasRenderer.js","sources":["../../../../../../src/components/primitives/canvas/useCanvasRenderer.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAaA;;;;;;;AAOG;AACG;;AAEJ;;;;;;;AASE;;AAEA;AACA;AAEA;AACE;AACF;AACF;AACF;;"}
1
+ {"version":3,"file":"useCanvasRenderer.js","sources":["src/components/primitives/canvas/useCanvasRenderer.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useCallback } from 'react';\n\ninterface UseCanvasRendererOptions {\n /** The draw function to call each frame. */\n draw: () => void;\n /** Dependencies array — when these change, the canvas re-renders */\n deps: unknown[];\n /** Whether rendering is paused @default false */\n paused?: boolean;\n}\n\n/**\n * Hook that manages a rAF-based render loop for canvas drawing.\n *\n * Calls the provided draw function whenever deps change.\n * Does NOT run continuously — only re-renders when deps trigger a change.\n *\n * Extracted from CurveEditor's useCurveRenderer rAF pattern.\n */\nexport function useCanvasRenderer(options: UseCanvasRendererOptions): void {\n const { draw, deps, paused = false } = options;\n const rafRef = useRef<number>(0);\n\n // This hook's contract is to re-run an arbitrary `draw` when caller-supplied\n // `deps` change, so the dependency list is intentionally dynamic rather than\n // a literal — the two rules below cannot model that generic pass-through.\n // eslint-disable-next-line react-hooks/exhaustive-deps, react-hooks/use-memo\n const stableDraw = useCallback(draw, deps);\n\n useEffect(() => {\n if (paused) return;\n\n cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(stableDraw);\n\n return () => {\n cancelAnimationFrame(rafRef.current);\n };\n }, [stableDraw, paused]);\n}\n"],"names":[],"mappings":";;;AAaA;;;;;;;AAOG;AACG;;AAEJ;;;;;;;AASE;;AAEA;AACA;AAEA;AACE;AACF;AACF;AACF;;"}
@@ -7,7 +7,7 @@ import { useControlledState } from '../../../hooks/useControlledState/useControl
7
7
  import { useResizeObserver } from '../../../hooks/useResizeObserver/useResizeObserver.js';
8
8
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
9
9
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
10
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
10
+ import '@vanilla-extract/css';
11
11
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
12
12
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
13
13
  import '../../../hooks/useNavigationHistory/useNavigationHistory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"Viewport.js","sources":["../../../../../../src/components/primitives/viewport/Viewport.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA2BA;AAEA;AACA;AACA;AACA;AACA;AAQA;AAGE;AACE;;AACmC;;AACA;;AACE;;;AAEA;AACvC;AACF;AAEA;;;;;AAMI;;AACA;;AACsB;;AACK;;AACE;AAC/B;AAEA;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AACI;AA4BL;;AAGA;;;;;;AAQG;AAIH;AAEI;AACA;AACA;AACA;AACD;AAGH;AAIA;AAEI;AACF;;;;AAOA;AACF;;;;;;;AASA;;AAEI;AACA;AACD;AACH;;;AAIE;AACA;;AACA;AACA;AACF;;AAGA;;AAGA;AACE;;;;;;;;;AASA;;;;;;AAMC;AACF;;AAGD;;;AAWA;AAEI;;AAEE;;;AAMN;;;AAaQ;AACD;AAqBT;AAEA;AAEA;;;;AAIG;AACH;AACE;AACA;AAIA;AAAW;AACX;;;;;;AAYF;;"}
1
+ {"version":3,"file":"Viewport.js","sources":["src/components/primitives/viewport/Viewport.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, {\n useCallback,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nimport { useControlledState, useResizeObserver } from '@/hooks';\nimport { cx } from '@/utils/cx';\nimport { clamp } from '@/utils/mathUtils';\n\nimport { useViewportGestures } from './useViewportGestures';\nimport {\n viewportRootRecipe,\n viewportHeightVar,\n marqueeRectStyle,\n} from './Viewport.css';\nimport { ViewportStoreContext, useViewportStore } from './ViewportContext';\nimport { ViewportStore } from './ViewportStore';\n\nimport type { ViewportProps, ViewportTransform } from './Viewport.types';\n\nconst IDENTITY_TRANSFORM: ViewportTransform = { x: 0, y: 0, zoom: 1 };\n\n// Stable empty defaults so `useViewportGestures` does not re-compute config\n// objects on every render when the consumer passes nothing.\nconst EMPTY_PAN = {};\nconst EMPTY_ZOOM = {};\nconst EMPTY_SELECTION = {};\n\ninterface CategorizedChildren {\n layers: React.ReactElement[];\n worldChildren: React.ReactElement[];\n overlayChildren: React.ReactElement[];\n}\n\nfunction getSlotKind(\n child: React.ReactElement\n): 'layer' | 'world' | 'overlay' | null {\n const displayName = (child.type as { displayName?: string } | undefined)\n ?.displayName;\n if (displayName === 'ViewportLayer') return 'layer';\n if (displayName === 'ViewportWorld') return 'world';\n if (displayName === 'ViewportOverlay') return 'overlay';\n // Compound components rendered in the overlay slot (e.g. <ViewportMinimap />).\n if (displayName === 'ViewportMinimap') return 'overlay';\n return null;\n}\n\nfunction categorizeChildren(children: React.ReactNode): CategorizedChildren {\n const layers: React.ReactElement[] = [];\n const worldChildren: React.ReactElement[] = [];\n const overlayChildren: React.ReactElement[] = [];\n\n React.Children.forEach(children, child => {\n if (!React.isValidElement(child)) return;\n const kind = getSlotKind(child);\n if (kind === 'layer') layers.push(child);\n else if (kind === 'world') worldChildren.push(child);\n else if (kind === 'overlay') overlayChildren.push(child);\n });\n\n return { layers, worldChildren, overlayChildren };\n}\n\n/**\n * Viewport — pan/zoom canvas + HTML container for editor-style surfaces\n * such as node graphs, timelines, and 2D world editors.\n *\n * Composes:\n * - Multiple perf-isolated `<ViewportLayer>` canvases (one draw cycle each).\n * - `<ViewportWorld>` for HTML positioned in world coordinates.\n * - `<ViewportOverlay>` for HTML pinned to the viewport (toolbars, minimap).\n *\n * Owns pan/zoom gestures (drag-to-pan, wheel-zoom-toward-cursor, optional\n * pinch and space-to-pan) and optional marquee selection. Transform is\n * controlled or uncontrolled (`useControlledState`-style) and mirrored\n * into an internal `ViewportStore` that powers slice-level subscriptions\n * for layers, world, and overlay children.\n *\n * @example\n * ```tsx\n * <Viewport responsive selectionRect={{ enabled: true }}>\n * <ViewportLayer name=\"grid\" draw={drawGrid} invalidateOn={[gridStep]} />\n * <ViewportLayer name=\"content\" draw={drawNodes} invalidateOn={[nodes]} />\n * <ViewportWorld>\n * <NodeView style={{ position: 'absolute', left: 100, top: 200 }} />\n * </ViewportWorld>\n * <ViewportOverlay>\n * <Toolbar />\n * </ViewportOverlay>\n * </Viewport>\n * ```\n */\nexport const Viewport = ({\n transform: transformProp,\n defaultTransform,\n onTransformChange,\n minZoom = 0.1,\n maxZoom = 8,\n pan,\n zoom,\n selectionRect,\n onSelectionChange,\n onPanStart,\n onPanEnd,\n onZoomStart,\n onZoomEnd,\n responsive = false,\n height = 300,\n disabled = false,\n role = 'application',\n ariaLabel,\n ariaRoledescription,\n className,\n style,\n testId,\n id,\n children,\n ref,\n ...rest\n}: ViewportProps): React.ReactElement => {\n const rootRef = useRef<HTMLDivElement>(null);\n\n // One store per <Viewport> instance, stable for the lifetime of the component.\n const store = useMemo(() => new ViewportStore(), []);\n\n // ── Controlled / uncontrolled transform (React state) ──\n const clampTransform = useCallback(\n (t: ViewportTransform): ViewportTransform => ({\n x: t.x,\n y: t.y,\n zoom: clamp(t.zoom, minZoom, maxZoom),\n }),\n [minZoom, maxZoom]\n );\n\n const [transformRaw, setTransformRaw] = useControlledState<ViewportTransform>(\n {\n value: transformProp,\n defaultValue: defaultTransform,\n onChange: onTransformChange,\n fallback: IDENTITY_TRANSFORM,\n }\n );\n\n const transform = useMemo(\n () => clampTransform(transformRaw),\n [transformRaw, clampTransform]\n );\n const setTransform = useCallback(\n (next: ViewportTransform) => {\n setTransformRaw(clampTransform(next));\n },\n [setTransformRaw, clampTransform]\n );\n\n // Mirror React state → store before paint so layer/world subscribers see the\n // latest transform in the same frame.\n useLayoutEffect(() => {\n store.setTransform(transform);\n }, [store, transform]);\n\n // Wire the store's imperative methods (fitToContent etc.) to React's\n // setTransform and current zoom limits.\n useLayoutEffect(() => {\n store.configureImperative({ setTransform, minZoom, maxZoom });\n }, [store, setTransform, minZoom, maxZoom]);\n\n // ── Size tracking ──\n useResizeObserver(rootRef, entry => {\n store.setSize({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n });\n });\n\n // Seed size on mount in case ResizeObserver fires asynchronously.\n useLayoutEffect(() => {\n const el = rootRef.current;\n if (!el) return;\n const rect = el.getBoundingClientRect();\n store.setSize({ width: rect.width, height: rect.height });\n }, [store]);\n\n // ── Imperative ref ──\n useImperativeHandle(ref, () => store.handle, [store]);\n\n // ── Gestures ──\n const { handlers } = useViewportGestures({\n viewportRef: rootRef,\n store,\n setTransform,\n disabled,\n minZoom,\n maxZoom,\n pan: pan ?? EMPTY_PAN,\n zoom: zoom ?? EMPTY_ZOOM,\n selectionRect: selectionRect ?? EMPTY_SELECTION,\n callbacks: {\n onPanStart,\n onPanEnd,\n onZoomStart,\n onZoomEnd,\n onSelectionChange,\n },\n });\n\n // Subscribe to isPanning only — drives the cursor class on the wrapper.\n const isPanning = useSyncExternalStore(\n store.subscribeIsPanning,\n store.getIsPanning\n );\n\n // ── Children categorization ──\n const { layers, worldChildren, overlayChildren } = useMemo(\n () => categorizeChildren(children),\n [children]\n );\n\n const rootStyle = useMemo(\n () => ({\n ...style,\n ...(!responsive\n ? assignInlineVars({ [viewportHeightVar]: `${height}px` })\n : {}),\n }),\n [style, responsive, height]\n );\n\n return (\n <div\n ref={rootRef}\n id={id}\n data-testid={testId}\n role={role}\n aria-label={ariaLabel}\n aria-roledescription={ariaRoledescription}\n tabIndex={disabled ? -1 : 0}\n className={cx(\n viewportRootRecipe({\n responsive,\n disabled,\n panning: isPanning,\n }),\n className\n )}\n style={rootStyle}\n onPointerDown={handlers.onPointerDown}\n onPointerMove={handlers.onPointerMove}\n onPointerUp={handlers.onPointerUp}\n onPointerCancel={handlers.onPointerCancel}\n onPointerEnter={handlers.onPointerEnter}\n onPointerLeave={handlers.onPointerLeave}\n onContextMenu={handlers.onContextMenu}\n {...rest}\n >\n <ViewportStoreContext.Provider value={store}>\n {layers}\n {worldChildren}\n {overlayChildren}\n <MarqueeRect />\n </ViewportStoreContext.Provider>\n </div>\n );\n};\n\nViewport.displayName = 'Viewport';\n\n/**\n * Internal — renders the marquee selection rectangle. Subscribes only to\n * the marquee slice so it re-renders only when the rectangle changes,\n * never on transform/size/isPanning mutations.\n */\nconst MarqueeRect: React.FC = () => {\n const store = useViewportStore();\n const rect = useSyncExternalStore(\n store.subscribeMarquee,\n store.getMarqueeRect\n );\n if (!rect) return null;\n return (\n <div\n className={marqueeRectStyle}\n style={{\n left: rect.x,\n top: rect.y,\n width: rect.width,\n height: rect.height,\n }}\n data-viewport-marquee=\"\"\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA2BA;AAEA;AACA;AACA;AACA;AACA;AAQA;AAGE;AACE;;AACmC;;AACA;;AACE;;;AAEA;AACvC;AACF;AAEA;;;;;AAMI;;AACA;;AACsB;;AACK;;AACE;AAC/B;AAEA;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AACI;AA4BL;;AAGA;;;;;;AAQG;AAIH;AAEI;AACA;AACA;AACA;AACD;AAGH;AAIA;AAEI;AACF;;;;AAOA;AACF;;;;;;;AASA;;AAEI;AACA;AACD;AACH;;;AAIE;AACA;;AACA;AACA;AACF;;AAGA;;AAGA;AACE;;;;;;;;;AASA;;;;;;AAMC;AACF;;AAGD;;;AAWA;AAEI;;AAEE;;;AAMN;;;AAaQ;AACD;AAqBT;AAEA;AAEA;;;;AAIG;AACH;AACE;AACA;AAIA;AAAW;AACX;;;;;;AAYF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportContext.js","sources":["../../../../../../src/components/primitives/viewport/ViewportContext.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAQE;AAEF;;;AAGG;;AAED;;AAEE;;AAIF;AACF;AAEA;;;;;;;;;;;;;;;;;AAiBG;;AAED;AACA;;;;;;;AAQF;;"}
1
+ {"version":3,"file":"ViewportContext.js","sources":["src/components/primitives/viewport/ViewportContext.ts"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useSyncExternalStore } from 'react';\n\nimport type { ViewportContextValue } from './Viewport.types';\nimport type { ViewportStore } from './ViewportStore';\n\nexport const ViewportStoreContext =\n /*#__PURE__*/ createContext<ViewportStore | null>(null);\n\n/**\n * Internal hook returning the store instance. Throws when called outside\n * a `<Viewport>` subtree.\n */\nexport function useViewportStore(): ViewportStore {\n const store = useContext(ViewportStoreContext);\n if (!store) {\n throw new Error(\n 'useViewportContext must be used inside a <Viewport> subtree.'\n );\n }\n return store;\n}\n\n/**\n * Read viewport state from inside `<Viewport>` children.\n *\n * Returns `transform`, `size`, `isPanning`, and the imperative `handle`.\n * The hook subscribes to every store mutation — if you only need one slice\n * (e.g. just the transform) reach for `useViewportStore()` directly and\n * subscribe to a single slice with `useSyncExternalStore`.\n *\n * @throws If called outside a `<Viewport>` subtree.\n *\n * @example\n * ```tsx\n * function Minimap() {\n * const { transform, size, handle } = useViewportContext();\n * // ...\n * }\n * ```\n */\nexport function useViewportContext(): ViewportContextValue {\n const store = useViewportStore();\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot);\n\n return {\n transform: snapshot.transform,\n size: snapshot.size,\n isPanning: snapshot.isPanning,\n handle: store.handle,\n };\n}\n"],"names":[],"mappings":";;;;AAQE;AAEF;;;AAGG;;AAED;;AAEE;;AAIF;AACF;AAEA;;;;;;;;;;;;;;;;;AAiBG;;AAED;AACA;;;;;;;AAQF;;"}
@@ -6,7 +6,7 @@ import '../../../utils/devWarn.js';
6
6
  import { useLatest } from '../../../hooks/useLatest/useLatest.js';
7
7
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
8
8
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
9
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
9
+ import '@vanilla-extract/css';
10
10
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
11
11
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
12
12
  import '../../../hooks/useNavigationHistory/useNavigationHistory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportLayer.js","sources":["../../../../../../src/components/primitives/viewport/ViewportLayer.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAsBA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAOL;AACA;AAIA;AAEA;AACA;AACA;AACA;AAEA;;;AAEE;AACA;;AACA;;;;AAIA;;AAEA;AAEA;AACA;AACA;AACE;AACA;;AAEF;AACA;AAEA;AACA;AACA;AACE;AACA;;;;;AAKF;;AAGF;AACE;AACA;AACF;;;;;;;AASE;AACA;AACE;AACF;;;AAGF;;;;;AAKE;;AAIE;AACF;AACA;AACA;AACE;AACF;AACF;;AAUF;AAEA;;"}
1
+ {"version":3,"file":"ViewportLayer.js","sources":["src/components/primitives/viewport/ViewportLayer.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n useCallback,\n useEffect,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nimport { resolveCanvasTheme } from '@/components/primitives/canvas/canvasTheme';\nimport { useLatest } from '@/hooks';\nimport { cx } from '@/utils/cx';\n\nimport { layerCanvasStyle } from './Viewport.css';\nimport { useViewportStore } from './ViewportContext';\nimport { worldToScreen, screenToWorld } from './viewportCoords';\n\nimport type {\n ViewportLayerDrawInfo,\n ViewportLayerProps,\n} from './Viewport.types';\n\n/**\n * A perf-isolated canvas layer inside a `<Viewport>`.\n *\n * Each layer owns its own `<canvas>` element and runs an independent draw\n * cycle. Draws are scheduled via `requestAnimationFrame` whenever the\n * viewport transform, viewport size, or any `invalidateOn` dependency\n * changes — or when the imperative `handle.invalidate(name)` is called.\n *\n * @example\n * ```tsx\n * <ViewportLayer\n * name=\"grid\"\n * draw={(ctx, { size, transform, theme }) => {\n * ctx.fillStyle = theme.borderDefault;\n * // ... draw grid\n * }}\n * invalidateOn={[gridStep]}\n * />\n * ```\n */\nexport const ViewportLayer: React.FC<ViewportLayerProps> = ({\n name,\n draw,\n invalidateOn,\n paused = false,\n className,\n}) => {\n const store = useViewportStore();\n const transform = useSyncExternalStore(\n store.subscribeTransform,\n store.getTransform\n );\n const size = useSyncExternalStore(store.subscribeSize, store.getSize);\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const rafRef = useRef<number>(0);\n const drawRef = useLatest(draw);\n const pausedRef = useLatest(paused);\n\n const performDraw = useCallback((): void => {\n if (pausedRef.current) return;\n const canvas = canvasRef.current;\n if (!canvas) return;\n const currentSize = store.getSize();\n if (currentSize.width <= 0 || currentSize.height <= 0) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const dpr =\n typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n const targetW = Math.max(1, Math.round(currentSize.width * dpr));\n const targetH = Math.max(1, Math.round(currentSize.height * dpr));\n if (canvas.width !== targetW || canvas.height !== targetH) {\n canvas.width = targetW;\n canvas.height = targetH;\n }\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, currentSize.width, currentSize.height);\n\n const currentTransform = store.getTransform();\n const theme = resolveCanvasTheme(canvas);\n const info: ViewportLayerDrawInfo = {\n size: currentSize,\n transform: currentTransform,\n theme,\n worldToScreen: p => worldToScreen(p, currentTransform),\n screenToWorld: p => screenToWorld(p, currentTransform),\n };\n drawRef.current(ctx, info);\n }, [store, drawRef, pausedRef]);\n\n const scheduleDraw = useCallback((): void => {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(performDraw);\n }, [performDraw]);\n\n // Subscribe to per-layer invalidation events fired by `handle.invalidate(name)`.\n useEffect(() => {\n return store.subscribeLayer(name, scheduleDraw);\n }, [store, name, scheduleDraw]);\n\n // Schedule a redraw when transform, size, or `invalidateOn` deps change.\n useEffect(() => {\n scheduleDraw();\n return () => {\n cancelAnimationFrame(rafRef.current);\n };\n // `invalidateOn` is intentionally spread into deps so each entry is tracked.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [transform, size, scheduleDraw, ...(invalidateOn ?? [])]);\n\n // Re-render when DPR changes (e.g., dragging the window to a different display).\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const mq = window.matchMedia(\n `(resolution: ${window.devicePixelRatio}dppx)`\n );\n const handler = (): void => {\n scheduleDraw();\n };\n mq.addEventListener('change', handler);\n return () => {\n mq.removeEventListener('change', handler);\n };\n }, [scheduleDraw]);\n\n return (\n <canvas\n ref={canvasRef}\n className={cx(layerCanvasStyle, className)}\n data-viewport-layer={name}\n aria-hidden=\"true\"\n />\n );\n};\n\nViewportLayer.displayName = 'ViewportLayer';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAsBA;;;;;;;;;;;;;;;;;;;AAmBG;AACI;AAOL;AACA;AAIA;AAEA;AACA;AACA;AACA;AAEA;;;AAEE;AACA;;AACA;;;;AAIA;;AAEA;AAEA;AACA;AACA;AACE;AACA;;AAEF;AACA;AAEA;AACA;AACA;AACE;AACA;;;;;AAKF;;AAGF;AACE;AACA;AACF;;;;;;;AASE;AACA;AACE;AACF;;;AAGF;;;;;AAKE;;AAIE;AACF;AACA;AACA;AACE;AACF;AACF;;AAUF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportOverlay.js","sources":["../../../../../../src/components/primitives/viewport/ViewportOverlay.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAUA;;;;;;;;;;;;;;;;;;;;AAoBG;AACI;;;;;AASL;;;;;;AAMA;AACE;;AAGF;AAaF;AAEA;;"}
1
+ {"version":3,"file":"ViewportOverlay.js","sources":["src/components/primitives/viewport/ViewportOverlay.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { overlayLayerStyle } from './Viewport.css';\n\nimport type { ViewportOverlayProps } from './Viewport.types';\n\n/**\n * Container for HTML children positioned in **screen coordinates**, rendered\n * above all canvas layers and world children.\n *\n * Typical use: toolbars, status text, minimap, or any UI that should stay\n * pinned to the viewport regardless of pan/zoom.\n *\n * Pointer events from interactive overlay children (buttons, sliders, …)\n * are stopped at the overlay boundary so a click on the toolbar does not\n * also start a Viewport pan or marquee gesture. The wrapper itself stays\n * `pointer-events: none`; children opt in with `pointerEvents: 'auto'`.\n *\n * @example\n * ```tsx\n * <ViewportOverlay>\n * <div style={{ position: 'absolute', bottom: 8, right: 8 }}>\n * <Minimap />\n * </div>\n * </ViewportOverlay>\n * ```\n */\nexport const ViewportOverlay: React.FC<ViewportOverlayProps> = ({\n children,\n className,\n style,\n}) => {\n // Stop pointer events from interactive overlay children from reaching the\n // Viewport wrapper. Without this, clicking a toolbar button starts a\n // marquee/pan gesture (and the gesture's `setPointerCapture` steals the\n // pointer-up event, so the button's `onClick` never fires).\n const stopPointer = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n e.stopPropagation();\n }, []);\n // Same problem for the native wheel listener: stopImmediatePropagation\n // prevents the Viewport's non-passive wheel zoom from firing when the user\n // scrolls inside an overlay (e.g., a scrollable list in a toolbar).\n const stopWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => {\n e.nativeEvent.stopImmediatePropagation();\n }, []);\n\n return (\n <div\n className={cx(overlayLayerStyle, className)}\n style={style}\n onPointerDown={stopPointer}\n onPointerMove={stopPointer}\n onPointerUp={stopPointer}\n onPointerCancel={stopPointer}\n onWheel={stopWheel}\n >\n {children}\n </div>\n );\n};\n\nViewportOverlay.displayName = 'ViewportOverlay';\n"],"names":[],"mappings":";;;;;;AAUA;;;;;;;;;;;;;;;;;;;;AAoBG;AACI;;;;;AASL;;;;;;AAMA;AACE;;AAGF;AAaF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportStore.js","sources":["../../../../../../src/components/primitives/viewport/ViewportStore.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ViewportStore.js","sources":["src/components/primitives/viewport/ViewportStore.ts"],"sourcesContent":["import { computeCenterTransform, computeFitTransform } from './viewportMath';\n\nimport type {\n ScreenRect,\n ViewportHandle,\n ViewportSize,\n ViewportTransform,\n WorldRect,\n} from './Viewport.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\n\n/** Read-only snapshot of the viewport store state. */\nexport interface ViewportStoreSnapshot {\n transform: ViewportTransform;\n size: ViewportSize;\n isPanning: boolean;\n marqueeRect: ScreenRect | null;\n}\n\ninterface ImperativeConfig {\n /** Pushes the new transform to React state (typically `useControlledState`'s setter). */\n setTransform: (next: ViewportTransform) => void;\n minZoom: number;\n maxZoom: number;\n}\n\nconst IDENTITY_TRANSFORM: ViewportTransform = { x: 0, y: 0, zoom: 1 };\n\n/**\n * Single source of truth for viewport runtime state — `transform`, `size`,\n * `isPanning`, `marqueeRect`, and per-layer invalidation events.\n *\n * Designed for React's `useSyncExternalStore`: each slice has its own\n * subscribe/get pair so subscribers re-render only when their slice\n * changes (not on every store mutation).\n *\n * `Viewport.tsx` configures the imperative methods (`fitToContent`,\n * `centerOn`, …) at mount via `configureImperative()` so the store knows\n * how to push transform updates back to React state. Until configured,\n * those methods are no-ops.\n */\nexport class ViewportStore {\n private transform: ViewportTransform = IDENTITY_TRANSFORM;\n private size: ViewportSize = { width: 0, height: 0 };\n private isPanning = false;\n private marqueeRect: ScreenRect | null = null;\n private snapshot: ViewportStoreSnapshot = this.computeSnapshot();\n\n private allListeners = new Set<() => void>();\n private transformListeners = new Set<() => void>();\n private sizeListeners = new Set<() => void>();\n private isPanningListeners = new Set<() => void>();\n private marqueeListeners = new Set<() => void>();\n private layerListeners = new Map<string, Set<() => void>>();\n\n private imperative: ImperativeConfig | null = null;\n\n // ── Public read API (arrow functions so they can be passed as callbacks) ──\n\n getSnapshot = (): ViewportStoreSnapshot => this.snapshot;\n getTransform = (): ViewportTransform => this.transform;\n getSize = (): ViewportSize => this.size;\n getIsPanning = (): boolean => this.isPanning;\n getMarqueeRect = (): ScreenRect | null => this.marqueeRect;\n\n // ── Subscriptions ──\n\n subscribe = (cb: () => void): (() => void) => {\n this.allListeners.add(cb);\n return () => {\n this.allListeners.delete(cb);\n };\n };\n\n subscribeTransform = (cb: () => void): (() => void) => {\n this.transformListeners.add(cb);\n return () => {\n this.transformListeners.delete(cb);\n };\n };\n\n subscribeSize = (cb: () => void): (() => void) => {\n this.sizeListeners.add(cb);\n return () => {\n this.sizeListeners.delete(cb);\n };\n };\n\n subscribeIsPanning = (cb: () => void): (() => void) => {\n this.isPanningListeners.add(cb);\n return () => {\n this.isPanningListeners.delete(cb);\n };\n };\n\n subscribeMarquee = (cb: () => void): (() => void) => {\n this.marqueeListeners.add(cb);\n return () => {\n this.marqueeListeners.delete(cb);\n };\n };\n\n subscribeLayer(name: string, cb: () => void): () => void {\n let set = this.layerListeners.get(name);\n if (!set) {\n set = new Set();\n this.layerListeners.set(name, set);\n }\n set.add(cb);\n return () => {\n const current = this.layerListeners.get(name);\n if (!current) return;\n current.delete(cb);\n if (current.size === 0) this.layerListeners.delete(name);\n };\n }\n\n // ── Mutators (called by Viewport / gestures) ──\n\n setTransform(next: ViewportTransform): void {\n if (next === this.transform) return;\n this.transform = next;\n this.snapshot = this.computeSnapshot();\n this.transformListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n setSize(next: ViewportSize): void {\n if (next.width === this.size.width && next.height === this.size.height) {\n return;\n }\n this.size = next;\n this.snapshot = this.computeSnapshot();\n this.sizeListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n setIsPanning(next: boolean): void {\n if (next === this.isPanning) return;\n this.isPanning = next;\n this.snapshot = this.computeSnapshot();\n this.isPanningListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n setMarqueeRect(next: ScreenRect | null): void {\n if (next === this.marqueeRect) return;\n this.marqueeRect = next;\n this.snapshot = this.computeSnapshot();\n this.marqueeListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n /**\n * Trigger a redraw of one layer (when `layerName` is provided) or all\n * layers (when omitted). Does not mutate snapshot state — fires only\n * the layer listeners.\n */\n invalidate(layerName?: string): void {\n if (layerName === undefined) {\n this.layerListeners.forEach(set => {\n set.forEach(cb => {\n cb();\n });\n });\n } else {\n this.layerListeners.get(layerName)?.forEach(cb => {\n cb();\n });\n }\n }\n\n // ── Imperative handle wiring ──\n\n /**\n * Wire up the React-side bits the imperative methods need\n * (a `setTransform` that goes through React state + zoom limits).\n * Viewport calls this on mount and on dependency changes.\n */\n configureImperative(config: ImperativeConfig): void {\n this.imperative = config;\n }\n\n /**\n * Returns a stable handle object whose methods proxy to the store.\n * The store keeps its lifecycle, so this handle reference is stable\n * for the lifetime of the store.\n */\n readonly handle: ViewportHandle = {\n fitToContent: (bounds: WorldRect, padding = 0): void => {\n if (!this.imperative) return;\n this.imperative.setTransform(\n computeFitTransform(bounds, this.size, padding, {\n minZoom: this.imperative.minZoom,\n maxZoom: this.imperative.maxZoom,\n })\n );\n },\n zoomToRect: (rect: WorldRect, padding = 0): void => {\n if (!this.imperative) return;\n this.imperative.setTransform(\n computeFitTransform(rect, this.size, padding, {\n minZoom: this.imperative.minZoom,\n maxZoom: this.imperative.maxZoom,\n })\n );\n },\n centerOn: (point: Point2D, zoom?: number): void => {\n if (!this.imperative) return;\n this.imperative.setTransform(\n computeCenterTransform(\n point,\n this.size,\n this.transform,\n {\n minZoom: this.imperative.minZoom,\n maxZoom: this.imperative.maxZoom,\n },\n zoom\n )\n );\n },\n getTransform: (): ViewportTransform => this.transform,\n getSize: (): ViewportSize => this.size,\n invalidate: (layerName?: string): void => {\n this.invalidate(layerName);\n },\n };\n\n private computeSnapshot(): ViewportStoreSnapshot {\n return {\n transform: this.transform,\n size: this.size,\n isPanning: this.isPanning,\n marqueeRect: this.marqueeRect,\n };\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportWorld.js","sources":["../../../../../../src/components/primitives/viewport/ViewportWorld.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;AAWA;;;;;;;;;;;;;;;;;;AAkBG;AACI;AAKL;AACA;AAKA;AAIM;AACA;;AAMR;AAEA;;"}
1
+ {"version":3,"file":"ViewportWorld.js","sources":["src/components/primitives/viewport/ViewportWorld.tsx"],"sourcesContent":["'use client';\n\nimport React, { useSyncExternalStore } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport { worldLayerStyle } from './Viewport.css';\nimport { useViewportStore } from './ViewportContext';\n\nimport type { ViewportWorldProps } from './Viewport.types';\n\n/**\n * Container for HTML children positioned in **world coordinates**.\n *\n * The wrapper applies the viewport's `translate(x, y) scale(zoom)` so that\n * children whose `left`/`top` are expressed in world units render at the\n * correct screen position and follow pan/zoom automatically.\n *\n * Subscribes only to the `transform` slice of the store — re-renders when\n * the transform changes, not when `isPanning` or `marqueeRect` flip.\n *\n * @example\n * ```tsx\n * <ViewportWorld>\n * <div style={{ position: 'absolute', left: 100, top: 200 }}>\n * Node at world (100, 200)\n * </div>\n * </ViewportWorld>\n * ```\n */\nexport const ViewportWorld: React.FC<ViewportWorldProps> = ({\n children,\n className,\n style,\n}) => {\n const store = useViewportStore();\n const transform = useSyncExternalStore(\n store.subscribeTransform,\n store.getTransform\n );\n\n return (\n <div\n className={cx(worldLayerStyle, className)}\n style={{\n ...style,\n transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.zoom})`,\n }}\n >\n {children}\n </div>\n );\n};\n\nViewportWorld.displayName = 'ViewportWorld';\n"],"names":[],"mappings":";;;;;;;AAWA;;;;;;;;;;;;;;;;;;AAkBG;AACI;AAKL;AACA;AAKA;AAIM;AACA;;AAMR;AAEA;;"}
@@ -5,7 +5,7 @@ import { useLatest } from '../../../hooks/useLatest/useLatest.js';
5
5
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
6
6
  import { useDebouncedCallback } from '../../../hooks/useDebounced/useDebouncedCallback.js';
7
7
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
8
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
8
+ import '@vanilla-extract/css';
9
9
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
10
10
  import 'react/jsx-runtime';
11
11
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
@@ -1 +1 @@
1
- {"version":3,"file":"useViewportGestures.js","sources":["../../../../../../src/components/primitives/viewport/useViewportGestures.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;AA2DA;AACE;AACA;AACA;;AAGF;AACE;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACA;AACA;AAaA;;;;;;AAMG;AACG;;;;AAoBE;;AAMA;AACA;;AAQN;AACA;;;AAIA;AACA;AACA;;AAGA;AAEA;AAEA;AACE;AACA;;;;AAKA;AACE;;;;;AAI8B;AAC9B;AACA;AACA;AAAsB;;AAExB;AACA;AACE;;;;AAEA;;AAEF;AACA;AACE;AACE;;AAEJ;;AAEE;AACF;AACA;AACA;AACA;AACA;AACE;AACA;AACA;AACF;;;;AAKA;;;;;AAIA;AACE;AACA;;AACA;;;AAIA;AACE;AACA;;AAEF;AAEA;AACA;AACE;AACA;;AAEF;AACA;AAMA;AACF;AAEA;AACA;AACE;AACF;AACF;;;AAGE;AACA;;;;;;;AAOD;AAED;AAEI;AACA;AAAa;AAEb;AACE;;AAEF;AACE;;;AAGA;;AAEF;AACF;AAIF;AAEI;AACA;;AACA;;AAEF;AAIF;AAOI;;;;;;AAME;AACA;AACD;;;;AAIC;AACA;AACD;AACD;AACA;;;;AAIC;AACH;AAIF;AAEI;;;;;AAIA;;AAEA;;;;AAKE;AACA;;AAEE;AACE;;AAEA;;AAEA;;AAEA;;AAEA;AACE;;AAEN;;AAGF;;;AAKA;AACE;AACA;;;AAEA;;AAEJ;;;;;AAME;;;AAGD;AAGH;AAEI;AACA;;AAEA;AAEA;AACA;AACA;;AAEA;;;;AAII;AACA;AACA;AACD;;;AAED;;;;AAQF;AACA;;AAEA;AAEA;;;AAGE;AACA;AACE;;AAEA;;AAEE;;;;;;AAcJ;;;;AAGA;;;AAEA;;AAGF;AACA;;;;;AASJ;AAEI;AACF;AAIF;AAEI;AACF;AAIF;AACE;;AAGF;AACE;;AAGF;AAEI;;AACF;;AAKA;;;;;;;;AAQC;;AAEL;;"}
1
+ {"version":3,"file":"useViewportGestures.js","sources":["src/components/primitives/viewport/useViewportGestures.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport { useDebouncedCallback, useLatest } from '@/hooks';\nimport { clamp } from '@/utils/mathUtils';\n\nimport { screenToWorld } from './viewportCoords';\nimport { computeZoomTowardPivot, normalizeRect } from './viewportMath';\n\nimport type {\n ScreenRect,\n ViewportMouseButton,\n ViewportPanConfig,\n ViewportPanEndInfo,\n ViewportSelectionConfig,\n ViewportSelectionEvent,\n ViewportTransform,\n ViewportZoomConfig,\n WorldRect,\n} from './Viewport.types';\nimport type { ViewportStore } from './ViewportStore';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type React from 'react';\n\ninterface GestureCallbacks {\n onPanStart?: () => void;\n onPanEnd?: (info: ViewportPanEndInfo) => void;\n onZoomStart?: () => void;\n onZoomEnd?: () => void;\n onSelectionChange?: (info: ViewportSelectionEvent) => void;\n}\n\ninterface UseViewportGesturesOptions {\n viewportRef: React.RefObject<HTMLDivElement | null>;\n store: ViewportStore;\n /** Called to push a new transform through React state. */\n setTransform: (next: ViewportTransform) => void;\n disabled: boolean;\n minZoom: number;\n maxZoom: number;\n pan: ViewportPanConfig | false;\n zoom: ViewportZoomConfig | false;\n selectionRect: ViewportSelectionConfig;\n callbacks: GestureCallbacks;\n}\n\ninterface UseViewportGesturesReturn {\n handlers: {\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void;\n onPointerMove: (e: React.PointerEvent<HTMLDivElement>) => void;\n onPointerUp: (e: React.PointerEvent<HTMLDivElement>) => void;\n onPointerCancel: (e: React.PointerEvent<HTMLDivElement>) => void;\n onPointerEnter: (e: React.PointerEvent<HTMLDivElement>) => void;\n onPointerLeave: (e: React.PointerEvent<HTMLDivElement>) => void;\n onContextMenu: (e: React.MouseEvent<HTMLDivElement>) => void;\n };\n}\n\nconst BUTTON_TO_NAME: Record<number, ViewportMouseButton> = {\n 0: 'left',\n 1: 'middle',\n 2: 'right',\n};\n\nconst DEFAULT_PAN: Required<ViewportPanConfig> = {\n button: 'middle',\n spaceKey: true,\n};\n\nconst DEFAULT_ZOOM: Required<ViewportZoomConfig> = {\n wheel: true,\n pinch: true,\n speed: 0.0015,\n};\n\nconst DEFAULT_SELECTION: Required<ViewportSelectionConfig> = {\n enabled: false,\n button: 'left',\n additiveModifier: 'shift',\n};\n\nconst ZOOM_END_DELAY_MS = 180;\nconst MAX_VELOCITY_PX_PER_MS = 3;\nconst VELOCITY_SAMPLE_COUNT = 5;\n\ntype GestureKind = 'pan' | 'marquee';\n\ninterface ActiveGesture {\n kind: GestureKind;\n pointerId: number;\n startScreen: Point2D;\n startTransform: ViewportTransform;\n /** For marquee — additive modifier observed at gesture start. */\n additive: boolean;\n}\n\n/**\n * Resolves gesture event handlers (pan, zoom, marquee) for the Viewport\n * wrapper. Used internally by `<Viewport>` — every \"live\" value (current\n * transform, current size, latest callbacks) is read through the store\n * or through a `useLatest` ref so the wheel/keyboard listeners never\n * re-attach on prop changes.\n */\nexport function useViewportGestures(\n options: UseViewportGesturesOptions\n): UseViewportGesturesReturn {\n const {\n viewportRef,\n store,\n setTransform,\n disabled,\n minZoom,\n maxZoom,\n pan,\n zoom,\n selectionRect,\n callbacks,\n } = options;\n\n const panCfg = useMemo<Required<ViewportPanConfig>>(\n () =>\n pan === false\n ? { button: false, spaceKey: false }\n : { ...DEFAULT_PAN, ...pan },\n [pan]\n );\n const zoomCfg = useMemo<Required<ViewportZoomConfig>>(\n () =>\n zoom === false\n ? { wheel: false, pinch: false, speed: DEFAULT_ZOOM.speed }\n : { ...DEFAULT_ZOOM, ...zoom },\n [zoom]\n );\n const selCfg = useMemo<Required<ViewportSelectionConfig>>(\n () => ({ ...DEFAULT_SELECTION, ...selectionRect }),\n [selectionRect]\n );\n\n const callbacksRef = useLatest(callbacks);\n const setTransformRef = useLatest(setTransform);\n const limitsRef = useLatest({ minZoom, maxZoom });\n const zoomSpeedRef = useLatest(zoomCfg.speed);\n\n const activeRef = useRef<ActiveGesture | null>(null);\n const spaceHeldRef = useRef(false);\n const pointerInsideRef = useRef(false);\n\n // Ring-buffer of recent pointer-move samples for velocity smoothing.\n const samplesRef = useRef<Array<{ point: Point2D; time: number }>>([]);\n\n const zoomActiveRef = useRef(false);\n\n const fireZoomEnd = useDebouncedCallback(() => {\n zoomActiveRef.current = false;\n callbacksRef.current.onZoomEnd?.();\n }, ZOOM_END_DELAY_MS);\n\n // ── Space-key tracking (window-scoped, gated by pointer/focus state) ──\n useEffect(() => {\n if (!panCfg.spaceKey || disabled) {\n spaceHeldRef.current = false;\n return;\n }\n const isInteractingWithViewport = (): boolean => {\n if (pointerInsideRef.current) return true;\n const root = viewportRef.current;\n const active = document.activeElement;\n if (!root || !active) return false;\n return root === active || root.contains(active);\n };\n const handleDown = (e: KeyboardEvent): void => {\n if (e.code !== 'Space') return;\n if (!isInteractingWithViewport()) return;\n spaceHeldRef.current = true;\n e.preventDefault();\n };\n const handleUp = (e: KeyboardEvent): void => {\n if (e.code === 'Space') {\n spaceHeldRef.current = false;\n }\n };\n const handleBlur = (): void => {\n spaceHeldRef.current = false;\n };\n window.addEventListener('keydown', handleDown);\n window.addEventListener('keyup', handleUp);\n window.addEventListener('blur', handleBlur);\n return () => {\n window.removeEventListener('keydown', handleDown);\n window.removeEventListener('keyup', handleUp);\n window.removeEventListener('blur', handleBlur);\n };\n }, [panCfg.spaceKey, disabled, viewportRef]);\n\n // ── Native wheel listener (non-passive so we can preventDefault page scroll) ──\n useEffect(() => {\n const el = viewportRef.current;\n if (!el || disabled) return;\n if (!zoomCfg.wheel && !zoomCfg.pinch) return;\n\n const handler = (e: WheelEvent): void => {\n const isPinch = e.ctrlKey;\n if (isPinch && !zoomCfg.pinch) return;\n if (!isPinch && !zoomCfg.wheel) return;\n\n e.preventDefault();\n\n if (!zoomActiveRef.current) {\n zoomActiveRef.current = true;\n callbacksRef.current.onZoomStart?.();\n }\n fireZoomEnd();\n\n const rect = el.getBoundingClientRect();\n const pivot: Point2D = {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n const factor = Math.exp(-e.deltaY * zoomSpeedRef.current);\n const next = computeZoomTowardPivot(\n pivot,\n factor,\n store.getTransform(),\n limitsRef.current\n );\n setTransformRef.current(next);\n };\n\n el.addEventListener('wheel', handler, { passive: false });\n return () => {\n el.removeEventListener('wheel', handler);\n };\n }, [\n viewportRef,\n disabled,\n zoomCfg.wheel,\n zoomCfg.pinch,\n store,\n callbacksRef,\n fireZoomEnd,\n limitsRef,\n setTransformRef,\n zoomSpeedRef,\n ]);\n\n const resolveGesture = useCallback(\n (buttonNum: number): GestureKind | null => {\n const button = BUTTON_TO_NAME[buttonNum];\n if (!button) return null;\n\n if (panCfg.spaceKey && spaceHeldRef.current && panCfg.button !== false) {\n return 'pan';\n }\n if (panCfg.button !== false && button === panCfg.button) {\n return 'pan';\n }\n if (selCfg.enabled && button === selCfg.button) {\n return 'marquee';\n }\n return null;\n },\n [panCfg.spaceKey, panCfg.button, selCfg.enabled, selCfg.button]\n );\n\n const getLocalPoint = useCallback(\n (e: { clientX: number; clientY: number }): Point2D => {\n const el = viewportRef.current;\n if (!el) return { x: 0, y: 0 };\n const rect = el.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n },\n [viewportRef]\n );\n\n const emitSelection = useCallback(\n (\n startScreen: Point2D,\n endScreen: Point2D,\n additive: boolean,\n inProgress: boolean\n ): void => {\n const t = store.getTransform();\n const startWorld = screenToWorld(startScreen, t);\n const endWorld = screenToWorld(endScreen, t);\n const rect: WorldRect = normalizeRect({\n x: startWorld.x,\n y: startWorld.y,\n width: endWorld.x - startWorld.x,\n height: endWorld.y - startWorld.y,\n });\n const screenRect: ScreenRect = normalizeRect({\n x: startScreen.x,\n y: startScreen.y,\n width: endScreen.x - startScreen.x,\n height: endScreen.y - startScreen.y,\n });\n store.setMarqueeRect(inProgress ? screenRect : null);\n callbacksRef.current.onSelectionChange?.({\n rect,\n additive,\n inProgress,\n });\n },\n [store, callbacksRef]\n );\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (disabled) return;\n if (activeRef.current) return;\n\n const kind = resolveGesture(e.button);\n if (!kind) return;\n\n const local = getLocalPoint(e);\n\n activeRef.current = {\n kind,\n pointerId: e.pointerId,\n startScreen: local,\n startTransform: store.getTransform(),\n additive: ((): boolean => {\n switch (selCfg.additiveModifier) {\n case 'shift':\n return e.shiftKey;\n case 'meta':\n return e.metaKey;\n case 'ctrl':\n return e.ctrlKey;\n case 'alt':\n return e.altKey;\n default:\n return false;\n }\n })(),\n };\n\n samplesRef.current = [{ point: local, time: performance.now() }];\n\n e.currentTarget.setPointerCapture(e.pointerId);\n e.preventDefault();\n\n if (kind === 'pan') {\n store.setIsPanning(true);\n callbacksRef.current.onPanStart?.();\n } else {\n emitSelection(local, local, activeRef.current.additive, true);\n }\n },\n [\n disabled,\n resolveGesture,\n getLocalPoint,\n store,\n selCfg.additiveModifier,\n emitSelection,\n callbacksRef,\n ]\n );\n\n const onPointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n const g = activeRef.current;\n if (g?.pointerId !== e.pointerId) return;\n\n const local = getLocalPoint(e);\n\n const samples = samplesRef.current;\n samples.push({ point: local, time: performance.now() });\n if (samples.length > VELOCITY_SAMPLE_COUNT) samples.shift();\n\n if (g.kind === 'pan') {\n const dx = local.x - g.startScreen.x;\n const dy = local.y - g.startScreen.y;\n setTransformRef.current({\n x: g.startTransform.x + dx,\n y: g.startTransform.y + dy,\n zoom: g.startTransform.zoom,\n });\n } else {\n emitSelection(g.startScreen, local, g.additive, true);\n }\n },\n [getLocalPoint, emitSelection, setTransformRef]\n );\n\n const endGesture = useCallback(\n (e: React.PointerEvent<HTMLDivElement>, cancelled: boolean): void => {\n const g = activeRef.current;\n if (g?.pointerId !== e.pointerId) return;\n\n const local = getLocalPoint(e);\n\n if (g.kind === 'pan') {\n let vx = 0;\n let vy = 0;\n const samples = samplesRef.current;\n if (samples.length >= 2) {\n const first = samples[0];\n const last = samples[samples.length - 1];\n if (first && last) {\n const dt = last.time - first.time;\n if (dt > 0) {\n vx = clamp(\n (last.point.x - first.point.x) / dt,\n -MAX_VELOCITY_PX_PER_MS,\n MAX_VELOCITY_PX_PER_MS\n );\n vy = clamp(\n (last.point.y - first.point.y) / dt,\n -MAX_VELOCITY_PX_PER_MS,\n MAX_VELOCITY_PX_PER_MS\n );\n }\n }\n }\n store.setIsPanning(false);\n callbacksRef.current.onPanEnd?.({ velocity: { x: vx, y: vy } });\n } else if (!cancelled) {\n emitSelection(g.startScreen, local, g.additive, false);\n } else {\n store.setMarqueeRect(null);\n }\n\n activeRef.current = null;\n samplesRef.current = [];\n\n if (e.currentTarget.hasPointerCapture(e.pointerId)) {\n e.currentTarget.releasePointerCapture(e.pointerId);\n }\n },\n [getLocalPoint, emitSelection, store, callbacksRef]\n );\n\n const onPointerUp = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n endGesture(e, false);\n },\n [endGesture]\n );\n\n const onPointerCancel = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n endGesture(e, true);\n },\n [endGesture]\n );\n\n const onPointerEnter = useCallback(() => {\n pointerInsideRef.current = true;\n }, []);\n\n const onPointerLeave = useCallback(() => {\n pointerInsideRef.current = false;\n }, []);\n\n const onContextMenu = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (panCfg.button === 'right') e.preventDefault();\n },\n [panCfg.button]\n );\n\n return {\n handlers: {\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onPointerEnter,\n onPointerLeave,\n onContextMenu,\n },\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AA2DA;AACE;AACA;AACA;;AAGF;AACE;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACA;AACA;AAaA;;;;;;AAMG;AACG;;;;AAoBE;;AAMA;AACA;;AAQN;AACA;;;AAIA;AACA;AACA;;AAGA;AAEA;AAEA;AACE;AACA;;;;AAKA;AACE;;;;;AAI8B;AAC9B;AACA;AACA;AAAsB;;AAExB;AACA;AACE;;;;AAEA;;AAEF;AACA;AACE;AACE;;AAEJ;;AAEE;AACF;AACA;AACA;AACA;AACA;AACE;AACA;AACA;AACF;;;;AAKA;;;;;AAIA;AACE;AACA;;AACA;;;AAIA;AACE;AACA;;AAEF;AAEA;AACA;AACE;AACA;;AAEF;AACA;AAMA;AACF;AAEA;AACA;AACE;AACF;AACF;;;AAGE;AACA;;;;;;;AAOD;AAED;AAEI;AACA;AAAa;AAEb;AACE;;AAEF;AACE;;;AAGA;;AAEF;AACF;AAIF;AAEI;AACA;;AACA;;AAEF;AAIF;AAOI;;;;;;AAME;AACA;AACD;;;;AAIC;AACA;AACD;AACD;AACA;;;;AAIC;AACH;AAIF;AAEI;;;;;AAIA;;AAEA;;;;AAKE;AACA;;AAEE;AACE;;AAEA;;AAEA;;AAEA;;AAEA;AACE;;AAEN;;AAGF;;;AAKA;AACE;AACA;;;AAEA;;AAEJ;;;;;AAME;;;AAGD;AAGH;AAEI;AACA;;AAEA;AAEA;AACA;AACA;;AAEA;;;;AAII;AACA;AACA;AACD;;;AAED;;;;AAQF;AACA;;AAEA;AAEA;;;AAGE;AACA;AACE;;AAEA;;AAEE;;;;;;AAcJ;;;;AAGA;;;AAEA;;AAGF;AACA;;;;;AASJ;AAEI;AACF;AAIF;AAEI;AACF;AAIF;AACE;;AAGF;AACE;;AAGF;AAEI;;AACF;;AAKA;;;;;;;;AAQC;;AAEL;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"viewportCoords.js","sources":["../../../../../../src/components/primitives/viewport/viewportCoords.ts"],"sourcesContent":[null],"names":[],"mappings":"AAGA;;;;AAIG;AACG,SAAU,aAAa,CAC3B,KAAc,EACd,SAA4B,EAAA;IAE5B,OAAO;QACL,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;QACzC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;KAC1C;AACH;AAEA;;;;AAIG;AACG,SAAU,aAAa,CAC3B,KAAc,EACd,SAA4B,EAAA;AAE5B,IAAA,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,IAAI,CAAC;IAC7B,OAAO;QACL,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC;QAC9B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC;KAC/B;AACH;AAEA;;;AAGG;AACG,SAAU,0BAA0B,CACxC,KAA2C,EAC3C,QAAqB,EAAA;AAErB,IAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAAE;IAC7C,OAAO;AACL,QAAA,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;AAC5B,QAAA,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;KAC5B;AACH;;;;"}
1
+ {"version":3,"file":"viewportCoords.js","sources":["src/components/primitives/viewport/viewportCoords.ts"],"sourcesContent":["import type { ViewportTransform } from './Viewport.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\n\n/**\n * Convert a world-space point to a screen-space (CSS-pixel) point.\n *\n * Uses the canonical transform: `screenPos = worldPos * zoom + (x, y)`.\n */\nexport function worldToScreen(\n point: Point2D,\n transform: ViewportTransform\n): Point2D {\n return {\n x: point.x * transform.zoom + transform.x,\n y: point.y * transform.zoom + transform.y,\n };\n}\n\n/**\n * Convert a screen-space (CSS-pixel) point to a world-space point.\n *\n * Inverse of `worldToScreen`.\n */\nexport function screenToWorld(\n point: Point2D,\n transform: ViewportTransform\n): Point2D {\n const z = transform.zoom || 1;\n return {\n x: (point.x - transform.x) / z,\n y: (point.y - transform.y) / z,\n };\n}\n\n/**\n * Compute the screen-space (CSS-pixel) position of a pointer event relative\n * to a viewport element.\n */\nexport function getViewportPointerPosition(\n event: { clientX: number; clientY: number },\n viewport: HTMLElement\n): Point2D {\n const rect = viewport.getBoundingClientRect();\n return {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n}\n"],"names":[],"mappings":"AAGA;;;;AAIG;AACG,SAAU,aAAa,CAC3B,KAAc,EACd,SAA4B,EAAA;IAE5B,OAAO;QACL,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;QACzC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;KAC1C;AACH;AAEA;;;;AAIG;AACG,SAAU,aAAa,CAC3B,KAAc,EACd,SAA4B,EAAA;AAE5B,IAAA,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,IAAI,CAAC;IAC7B,OAAO;QACL,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC;QAC9B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC;KAC/B;AACH;AAEA;;;AAGG;AACG,SAAU,0BAA0B,CACxC,KAA2C,EAC3C,QAAqB,EAAA;AAErB,IAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAAE;IAC7C,OAAO;AACL,QAAA,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;AAC5B,QAAA,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;KAC5B;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"viewportMath.js","sources":["../../../../../../src/components/primitives/viewport/viewportMath.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"viewportMath.js","sources":["src/components/primitives/viewport/viewportMath.ts"],"sourcesContent":["import { clamp } from '@/utils/mathUtils';\n\nimport type {\n ViewportSize,\n ViewportTransform,\n WorldRect,\n} from './Viewport.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\n\ninterface ZoomLimits {\n minZoom: number;\n maxZoom: number;\n}\n\n/**\n * Compute a transform that fits `bounds` (in world coordinates) into the\n * viewport `size`, with optional uniform inner `padding` in screen pixels.\n *\n * The resulting transform preserves aspect ratio (uniform zoom on both axes)\n * and centers the content within the viewport.\n */\nexport function computeFitTransform(\n bounds: WorldRect,\n size: ViewportSize,\n padding: number,\n limits: ZoomLimits\n): ViewportTransform {\n const innerW = Math.max(1, size.width - padding * 2);\n const innerH = Math.max(1, size.height - padding * 2);\n\n // Degenerate bounds — fall back to identity scale, center on bounds origin\n const w = bounds.width > 0 ? bounds.width : 1;\n const h = bounds.height > 0 ? bounds.height : 1;\n\n const zoomX = innerW / w;\n const zoomY = innerH / h;\n const zoom = clamp(Math.min(zoomX, zoomY), limits.minZoom, limits.maxZoom);\n\n // Center of world bounds maps to center of viewport\n const worldCx = bounds.x + bounds.width / 2;\n const worldCy = bounds.y + bounds.height / 2;\n const screenCx = size.width / 2;\n const screenCy = size.height / 2;\n\n return {\n x: screenCx - worldCx * zoom,\n y: screenCy - worldCy * zoom,\n zoom,\n };\n}\n\n/**\n * Compute a transform that centers `point` (world coordinates) in the\n * viewport, optionally setting a new zoom.\n */\nexport function computeCenterTransform(\n point: Point2D,\n size: ViewportSize,\n current: ViewportTransform,\n limits: ZoomLimits,\n nextZoom?: number\n): ViewportTransform {\n const zoom = clamp(nextZoom ?? current.zoom, limits.minZoom, limits.maxZoom);\n return {\n x: size.width / 2 - point.x * zoom,\n y: size.height / 2 - point.y * zoom,\n zoom,\n };\n}\n\n/**\n * Compute the new transform for a \"zoom toward pivot\" gesture.\n *\n * The world point currently under `pivot` (screen pixels) stays under\n * the pivot after the zoom change.\n */\nexport function computeZoomTowardPivot(\n pivot: Point2D,\n factor: number,\n current: ViewportTransform,\n limits: ZoomLimits\n): ViewportTransform {\n const nextZoom = clamp(current.zoom * factor, limits.minZoom, limits.maxZoom);\n // World position under pivot before zoom\n const worldX = (pivot.x - current.x) / (current.zoom || 1);\n const worldY = (pivot.y - current.y) / (current.zoom || 1);\n // Keep world point under pivot after zoom\n return {\n x: pivot.x - worldX * nextZoom,\n y: pivot.y - worldY * nextZoom,\n zoom: nextZoom,\n };\n}\n\n/**\n * Normalize a rectangle so that width and height are non-negative,\n * adjusting the origin accordingly. Useful for marquee selection\n * where the user may drag in any direction.\n */\nexport function normalizeRect(rect: WorldRect): WorldRect {\n const x = rect.width < 0 ? rect.x + rect.width : rect.x;\n const y = rect.height < 0 ? rect.y + rect.height : rect.y;\n return {\n x,\n y,\n width: Math.abs(rect.width),\n height: Math.abs(rect.height),\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.js","sources":["../../../../../../src/components/shell/AppShell/AppShell.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AA8BA;AAEA;AACE;AACA;AACA;AACA;AACD;AAEM;AAEP;AAEA;AAkBA;AAEA;;AAYE;AAAiC;;AAG/B;AACA;;AAMU;AACA;AACD;AAUT;AACE;;AAeN;AACA;AAEA;AAmBA;AAEA;AAmBA;AAEA;AAEA;AAYE;AAGE;AACA;AACA;AACD;AAED;;AAOI;;AAKJ;;;;;AAMG;;;;;AAMA;;AAiBL;AAEA;AAEA;AAEO;AACL;AACA;AACA;AACA;AACD;;"}
1
+ {"version":3,"file":"AppShell.js","sources":["src/components/shell/AppShell/AppShell.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useMemo,\n} from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n viewportLockClass,\n shellRoot,\n menuBarSlot,\n toolbarTopSlot,\n sideToolbarSlot,\n dockSlot,\n statusBarSlot,\n} from './AppShell.css';\n\nimport type {\n AppShellProps,\n AppShellSlotProps,\n AppShellToolbarSlotProps,\n AppShellContextValue,\n ToolbarPosition,\n} from './AppShell.types';\n\n// --- Context ---\n\nconst AppShellContext = /*#__PURE__*/ createContext<AppShellContextValue>({\n isToolbarVisible: () => true,\n setToolbarVisible: () => {},\n topChromeSeparator: 'border',\n sideChromeSeparator: 'border',\n});\n\nexport const useAppShell = () => useContext(AppShellContext);\n\n// --- Slot Components ---\n\nconst MenuBarSlot: React.FC<AppShellSlotProps> = ({\n children,\n className,\n style,\n testId,\n ref,\n ...rest\n}) => (\n <header\n ref={ref}\n className={cx(menuBarSlot, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </header>\n);\nMenuBarSlot.displayName = 'AppShell.MenuBar';\n\nconst ToolbarSlot: React.FC<AppShellToolbarSlotProps> = ({\n children,\n\n className,\n style,\n testId,\n ref,\n position = 'top',\n ...rest\n}) => {\n const { isToolbarVisible, topChromeSeparator, sideChromeSeparator } =\n useAppShell();\n if (!isToolbarVisible(position)) return null;\n\n switch (position) {\n case 'left':\n case 'right':\n return (\n <aside\n ref={ref}\n className={cx(\n sideToolbarSlot({\n side: position,\n separator: sideChromeSeparator,\n }),\n className\n )}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </aside>\n );\n default:\n return (\n <div\n ref={ref as React.Ref<HTMLDivElement>}\n className={cx(\n toolbarTopSlot({ separator: topChromeSeparator }),\n className\n )}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n );\n }\n};\nToolbarSlot.displayName = 'AppShell.Toolbar';\n\nconst DockSlot: React.FC<AppShellSlotProps> = ({\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => (\n <main\n ref={ref}\n className={cx(dockSlot, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </main>\n);\nDockSlot.displayName = 'AppShell.Dock';\n\nconst StatusBarSlot: React.FC<AppShellSlotProps> = ({\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => (\n <footer\n ref={ref}\n className={cx(statusBarSlot, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </footer>\n);\nStatusBarSlot.displayName = 'AppShell.StatusBar';\n\n// --- Root Component ---\n\nconst AppShellRoot: React.FC<AppShellProps> = ({\n viewportLock = false,\n topChromeSeparator = 'border',\n sideChromeSeparator = 'border',\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const [toolbarVisibility, setToolbarVisibility] = useState<\n Record<ToolbarPosition, boolean>\n >({\n top: true,\n left: true,\n right: true,\n });\n\n const isToolbarVisible = useCallback(\n (position: ToolbarPosition) => toolbarVisibility[position],\n [toolbarVisibility]\n );\n\n const setToolbarVisible = useCallback(\n (position: ToolbarPosition, visible: boolean) => {\n setToolbarVisibility(prev => ({ ...prev, [position]: visible }));\n },\n []\n );\n\n const contextValue = useMemo(\n () => ({\n isToolbarVisible,\n setToolbarVisible,\n topChromeSeparator,\n sideChromeSeparator,\n }),\n [\n isToolbarVisible,\n setToolbarVisible,\n topChromeSeparator,\n sideChromeSeparator,\n ]\n );\n\n return (\n <AppShellContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cx(shellRoot, viewportLock && viewportLockClass, className)}\n style={style}\n data-testid={testId}\n role=\"application\"\n {...rest}\n >\n {children}\n </div>\n </AppShellContext.Provider>\n );\n};\n\nAppShellRoot.displayName = 'AppShell';\n\n// --- Compound Component ---\n\nexport const AppShell = /*#__PURE__*/ Object.assign(AppShellRoot, {\n MenuBar: MenuBarSlot,\n Toolbar: ToolbarSlot,\n Dock: DockSlot,\n StatusBar: StatusBarSlot,\n});\n"],"names":[],"mappings":";;;;;;AA8BA;AAEA;AACE;AACA;AACA;AACA;AACD;AAEM;AAEP;AAEA;AAkBA;AAEA;;AAYE;AAAiC;;AAG/B;AACA;;AAMU;AACA;AACD;AAUT;AACE;;AAeN;AACA;AAEA;AAmBA;AAEA;AAmBA;AAEA;AAEA;AAYE;AAGE;AACA;AACA;AACD;AAED;;AAOI;;AAKJ;;;;;AAMG;;;;;AAMA;;AAiBL;AAEA;AAEA;AAEO;AACL;AACA;AACA;AACA;AACD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingPanel.js","sources":["../../../../../../src/components/shell/FloatingPanel/FloatingPanel.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;AA+CA;AAEA;AACE;AAEF;AAEO;AAIL;;AAGA;;;;;;AAOA;AACE;;;AAIF;AACE;;AACoC;;;;AAKtC;;AAGI;AACF;AAIF;;;;;;AASA;AAKF;AAEA;AAEA;;AA6BE;AACA;AACA;;;AAKA;AACA;AAEI;;AACA;AACF;;;AAOF;AACA;AAEI;;AACA;AACF;;;AAMF;AACA;AACE;;;AAEA;;AAGF;AAEI;;AAEE;;AAEJ;AAIF;AAEI;;;;AAIF;;;;AAOF;;AAGE;;;;;;;;;AASF;AAEA;AACE;AACF;;;AAKA;;AAGA;;AAGI;AACA;;;AAIA;AACA;;;AAIA;AACE;AACA;;;;AAIE;AACA;;AAEA;AACA;AACF;AACE;AACA;AACD;AACH;;AAGE;AACA;AACF;AAEA;AACA;AACF;;AAKF;;;AAII;AACA;AAEA;AACA;AACA;AACA;AAEA;AACE;AACA;AACA;AACA;;AAEF;;AAGE;AACA;AACF;AAEA;AACA;AACF;;AAKA;AACA;AACA;AACA;AACA;AACD;AAED;AAWM;AACA;;AA0DR;AAEA;;"}
1
+ {"version":3,"file":"FloatingPanel.js","sources":["src/components/shell/FloatingPanel/FloatingPanel.tsx"],"sourcesContent":["'use client';\n\nimport { assignInlineVars } from '@vanilla-extract/dynamic';\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useRef,\n useEffect,\n useId,\n useMemo,\n} from 'react';\n\nimport { ChevronDownIcon } from '@/components/Icons/ChevronDownIcon';\nimport { ChevronUpIcon } from '@/components/Icons/ChevronUpIcon';\nimport { CloseIcon } from '@/components/Icons/CloseIcon';\nimport { ScrollArea } from '@/components/layout/ScrollArea';\nimport { useLatest } from '@/hooks/useLatest';\nimport { useMergedRef } from '@/hooks/useMergedRef';\nimport { cx } from '@/utils/cx';\n\nimport {\n posXVar,\n posYVar,\n panelWidthVar,\n panelHeightVar,\n panelZIndexVar,\n managerRoot,\n panel,\n header,\n title,\n headerActions,\n headerButton,\n collapsibleVisible,\n collapsibleHidden,\n resizeHandle,\n} from './FloatingPanel.css';\n\nimport type {\n FloatingPanelProps,\n FloatingManagerProps,\n FloatingManagerContextValue,\n Position,\n FloatingPanelSize,\n} from './FloatingPanel.types';\n\n// --- FloatingManager Context ---\n\nconst FloatingManagerContext =\n /*#__PURE__*/ createContext<FloatingManagerContextValue | null>(null);\n\nconst useFloatingManager = () => useContext(FloatingManagerContext);\n\nexport const FloatingManager: React.FC<FloatingManagerProps> = ({\n baseZIndex = 100,\n children,\n}) => {\n const stackRef = useRef<string[]>([]);\n const [revision, setRevision] = useState(0);\n\n const register = useCallback((id: string) => {\n if (!stackRef.current.includes(id)) {\n stackRef.current = [...stackRef.current, id];\n setRevision(c => c + 1);\n }\n }, []);\n\n const unregister = useCallback((id: string) => {\n stackRef.current = stackRef.current.filter(s => s !== id);\n setRevision(c => c + 1);\n }, []);\n\n const bringToFront = useCallback((id: string) => {\n const stack = stackRef.current;\n if (stack[stack.length - 1] === id) return; // already on top\n stackRef.current = [...stack.filter(s => s !== id), id];\n setRevision(c => c + 1);\n }, []);\n\n const getZIndex = useCallback(\n (id: string) => {\n const index = stackRef.current.indexOf(id);\n return baseZIndex + (index >= 0 ? index : 0);\n },\n [baseZIndex]\n );\n\n const contextValue = useMemo<FloatingManagerContextValue>(\n () => ({ bringToFront, getZIndex, register, unregister }),\n // `revision` is bumped whenever the panel stack changes; it intentionally\n // busts this memo so consumers re-render and re-read z-indices from the\n // (otherwise stable) getZIndex, even though it is not read in the factory.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [revision, bringToFront, getZIndex, register, unregister]\n );\n\n return (\n <FloatingManagerContext.Provider value={contextValue}>\n <div className={managerRoot}>{children}</div>\n </FloatingManagerContext.Provider>\n );\n};\n\nFloatingManager.displayName = 'FloatingManager';\n\n// --- FloatingPanel Component ---\n\nexport const FloatingPanel: React.FC<FloatingPanelProps> = ({\n title: panelTitle,\n position: controlledPosition,\n defaultPosition = { x: 100, y: 100 },\n onPositionChange,\n size: controlledSize,\n defaultSize = { width: 280, height: 200 },\n onSizeChange,\n minWidth = 150,\n minHeight = 100,\n maxWidth = Infinity,\n maxHeight = Infinity,\n collapsed: controlledCollapsed,\n defaultCollapsed = false,\n onCollapsedChange,\n onClose,\n closable = true,\n resizable = true,\n children,\n\n className,\n panelId,\n style,\n testId,\n ref: externalRef,\n ...rest\n}) => {\n const generatedId = useId();\n const id = panelId ?? generatedId;\n const manager = useFloatingManager();\n\n // Position state\n const [internalPosition, setInternalPosition] =\n useState<Position>(defaultPosition);\n const pos = controlledPosition ?? internalPosition;\n const setPos = useCallback(\n (p: Position) => {\n if (!controlledPosition) setInternalPosition(p);\n onPositionChange?.(p);\n },\n [controlledPosition, onPositionChange]\n );\n\n // Size state\n const [internalSize, setInternalSize] =\n useState<FloatingPanelSize>(defaultSize);\n const currentSize = controlledSize ?? internalSize;\n const setSize = useCallback(\n (s: FloatingPanelSize) => {\n if (!controlledSize) setInternalSize(s);\n onSizeChange?.(s);\n },\n [controlledSize, onSizeChange]\n );\n\n // Collapsed state\n const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);\n const isCollapsed = controlledCollapsed ?? internalCollapsed;\n const toggleCollapse = useCallback(() => {\n const next = !isCollapsed;\n if (controlledCollapsed === undefined) setInternalCollapsed(next);\n onCollapsedChange?.(next);\n }, [isCollapsed, controlledCollapsed, onCollapsedChange]);\n\n const handleCollapseKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleCollapse();\n }\n },\n [toggleCollapse]\n );\n\n const handleCloseKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClose?.();\n }\n },\n [onClose]\n );\n\n // FloatingManager registration -- use stable id, run once. Latest manager via\n // useLatest so the register/unregister effect and handlers read it without\n // writing a ref during render.\n const managerRef = useLatest(manager);\n\n useEffect(() => {\n managerRef.current?.register(id);\n // Reading the latest manager from the ref at cleanup is intentional.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return () => managerRef.current?.unregister(id);\n // Register/unregister exactly once per id. managerRef is a stable useLatest\n // ref read at both register and unregister time; the manager is read via\n // the ref because the manager context value changes on every panel\n // registration and must not re-trigger this effect.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [id]);\n\n const handleBringToFront = useCallback(() => {\n managerRef.current?.bringToFront(id);\n }, [id, managerRef]);\n\n const zIndex = manager?.getZIndex(id) ?? 100;\n\n // --- Drag ---\n const panelRef = useRef<HTMLDivElement>(null);\n const setPanelRef = useMergedRef<HTMLDivElement>(panelRef, externalRef);\n\n const handleDragStart = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n const target = e.currentTarget as HTMLElement;\n target.setPointerCapture(e.pointerId);\n\n // Track the pointer delta from the drag start, so positioning is\n // independent of the coordinate space the panel lives in.\n const startPointer = { x: e.clientX, y: e.clientY };\n const startPos = { x: pos.x, y: pos.y };\n const bounds = panelRef.current?.offsetParent?.getBoundingClientRect();\n const panelRect = panelRef.current?.getBoundingClientRect();\n\n const handleDragMove = (me: PointerEvent) => {\n const newX = startPos.x + (me.clientX - startPointer.x);\n const newY = startPos.y + (me.clientY - startPointer.y);\n // Clamp within the positioned container when one is available,\n // keeping a small margin of the panel on-screen.\n const maxX = bounds\n ? Math.max(0, bounds.width - (panelRect?.width ?? 50))\n : Number.POSITIVE_INFINITY;\n const maxY = bounds\n ? Math.max(0, bounds.height - 30)\n : Number.POSITIVE_INFINITY;\n setPos({\n x: Math.max(0, Math.min(newX, maxX)),\n y: Math.max(0, Math.min(newY, maxY)),\n });\n };\n\n const handleDragEnd = () => {\n target.removeEventListener('pointermove', handleDragMove);\n target.removeEventListener('pointerup', handleDragEnd);\n };\n\n target.addEventListener('pointermove', handleDragMove);\n target.addEventListener('pointerup', handleDragEnd);\n },\n [pos, setPos]\n );\n\n // --- Resize (bottom-right corner only) ---\n const handleResizeStart = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const target = e.currentTarget as HTMLElement;\n target.setPointerCapture(e.pointerId);\n\n const startX = e.clientX;\n const startY = e.clientY;\n const startW = currentSize.width;\n const startH = currentSize.height;\n\n const handleResizeMove = (me: PointerEvent) => {\n const dx = me.clientX - startX;\n const dy = me.clientY - startY;\n const newW = Math.min(maxWidth, Math.max(minWidth, startW + dx));\n const newH = Math.min(maxHeight, Math.max(minHeight, startH + dy));\n setSize({ width: newW, height: newH });\n };\n\n const handleResizeEnd = () => {\n target.removeEventListener('pointermove', handleResizeMove);\n target.removeEventListener('pointerup', handleResizeEnd);\n };\n\n target.addEventListener('pointermove', handleResizeMove);\n target.addEventListener('pointerup', handleResizeEnd);\n },\n [currentSize, minWidth, minHeight, maxWidth, maxHeight, setSize]\n );\n\n const inlineVars = assignInlineVars({\n [posXVar]: `${pos.x}px`,\n [posYVar]: `${pos.y}px`,\n [panelWidthVar]: `${currentSize.width}px`,\n [panelHeightVar]: isCollapsed ? 'auto' : `${currentSize.height}px`,\n [panelZIndexVar]: String(zIndex),\n });\n\n return (\n <div\n ref={setPanelRef}\n className={cx(panel, className)}\n data-testid={testId}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={panelTitle}\n tabIndex={-1}\n onPointerDown={handleBringToFront}\n style={{\n ...style,\n ...inlineVars,\n }}\n {...rest}\n >\n <div\n className={header}\n onPointerDown={handleDragStart}\n data-testid=\"panel-header\"\n >\n <span className={title}>{panelTitle}</span>\n <div className={headerActions}>\n <span\n className={headerButton}\n role=\"button\"\n tabIndex={0}\n onClick={toggleCollapse}\n onKeyDown={handleCollapseKeyDown}\n aria-label={isCollapsed ? 'Expand panel' : 'Collapse panel'}\n >\n {isCollapsed ? (\n <ChevronDownIcon size=\"sm\" color=\"secondary\" decorative />\n ) : (\n <ChevronUpIcon size=\"sm\" color=\"secondary\" decorative />\n )}\n </span>\n {closable && onClose && (\n <span\n className={headerButton}\n role=\"button\"\n tabIndex={0}\n onClick={onClose}\n onKeyDown={handleCloseKeyDown}\n aria-label=\"Close panel\"\n >\n <CloseIcon size=\"sm\" color=\"secondary\" decorative />\n </span>\n )}\n </div>\n </div>\n <div className={isCollapsed ? collapsibleHidden : collapsibleVisible}>\n <ScrollArea\n direction=\"both\"\n scrollbarVisibility=\"auto\"\n scrollbarWidth={5}\n autoFill\n >\n {children}\n </ScrollArea>\n </div>\n {resizable && !isCollapsed && (\n <div\n className={resizeHandle}\n onPointerDown={handleResizeStart}\n data-testid=\"resize-handle\"\n />\n )}\n </div>\n );\n};\n\nFloatingPanel.displayName = 'FloatingPanel';\n"],"names":[],"mappings":";;;;;;;;;;;;;AA+CA;AAEA;AACE;AAEF;AAEO;AAIL;;AAGA;;;;;;AAOA;AACE;;;AAIF;AACE;;AACoC;;;;AAKtC;;AAGI;AACF;AAIF;;;;;;AASA;AAKF;AAEA;AAEA;;AA6BE;AACA;AACA;;;AAKA;AACA;AAEI;;AACA;AACF;;;AAOF;AACA;AAEI;;AACA;AACF;;;AAMF;AACA;AACE;;;AAEA;;AAGF;AAEI;;AAEE;;AAEJ;AAIF;AAEI;;;;AAIF;;;;AAOF;;AAGE;;;;;;;;;AASF;AAEA;AACE;AACF;;;AAKA;;AAGA;;AAGI;AACA;;;AAIA;AACA;;;AAIA;AACE;AACA;;;;AAIE;AACA;;AAEA;AACA;AACF;AACE;AACA;AACD;AACH;;AAGE;AACA;AACF;AAEA;AACA;AACF;;AAKF;;;AAII;AACA;AAEA;AACA;AACA;AACA;AAEA;AACE;AACA;AACA;AACA;;AAEF;;AAGE;AACA;AACF;AAEA;AACA;AACF;;AAKA;AACA;AACA;AACA;AACA;AACD;AAED;AAWM;AACA;;AA0DR;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MenuBar.js","sources":["../../../../../../src/components/shell/MenuBar/MenuBar.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAsCA;AAEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACD;AAED;AAEA;AAEA;AAEA;AAGM;AACA;AACD;AAML;AAEA;AAaE;AAEA;;AAEI;;;AAGJ;AAEA;AAkBF;AAEA;AAEA;AAWE;;AAEA;AAEA;AACE;AACE;AACA;;AAEF;;AACF;AAEA;AACE;;;;;AAMA;;AAC0B;AAC1B;;;AAoCJ;AAEA;AAEA;AAOE;AAUF;AAEA;AAEA;AAEA;AAWE;AACA;AAOA;AACA;AACA;;;AAIE;;AAEA;;AAGF;AACE;;;;AAIF;;;;;;AAOA;AAEI;;;;;;;;;AAWA;;;AAGE;;AAEJ;AAIF;AAEI;;AAOA;;AAEE;AACA;;AACK;;;AAIL;;AACK;;;AAGL;;AAEJ;;;AAMA;;AAEA;AACE;;;;;AAOF;AAEA;AACA;AACE;AACF;AACF;AAEA;;;;AAwCF;AAEA;AAEA;AAEA;;;;;;AAgBE;;AAGI;AACA;;;AAEO;AACL;;AAEJ;AAIF;;;AAIA;AACE;;AAGF;;;AAII;;AASA;;AAEE;AACA;;AAEA;AACE;;;AAEG;;;AAIL;AACA;AACE;;;AAGN;AAIF;;AAGI;;;;;;AAMD;;;;;;;;AASA;;AAmBL;AAEA;AAEA;AAEO;AACL;AACA;AACA;AACA;AACD;;"}
1
+ {"version":3,"file":"MenuBar.js","sources":["src/components/shell/MenuBar/MenuBar.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useRef,\n useEffect,\n useId,\n KeyboardEvent,\n useMemo,\n} from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n menuBarRoot,\n menuContainer,\n trigger,\n dropdown,\n menuItem,\n shortcut,\n separator,\n subTrigger,\n subDropdown,\n subContainer,\n} from './MenuBar.css';\n\nimport type {\n MenuBarProps,\n MenuBarMenuProps,\n MenuBarItemProps,\n MenuBarSubProps,\n MenuBarSeparatorProps,\n MenuBarContextValue,\n} from './MenuBar.types';\n\n// --- Context ---\n\nconst MenuBarContext = /*#__PURE__*/ createContext<MenuBarContextValue>({\n size: 'md',\n menuOffset: 2,\n openMenuId: null,\n setOpenMenuId: () => {},\n registerMenu: () => {},\n unregisterMenu: () => {},\n menuIds: [],\n});\n\nconst useMenuBar = () => useContext(MenuBarContext);\n\nconst SUBMENU_CLOSE_DELAY = 150;\n\nconst MENU_ITEM_SELECTOR = '[role=\"menuitem\"]:not(:disabled)';\n\nconst ChevronRight = () => (\n <span\n style={{\n fontSize: '8px',\n lineHeight: 1,\n }}\n >\n &#x25B6;\n </span>\n);\n\n// --- Sub-components ---\n\nconst MenuBarItem: React.FC<MenuBarItemProps> = ({\n onClick,\n shortcut: shortcutText,\n disabled = false,\n icon,\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const { setOpenMenuId } = useMenuBar();\n\n const handleClick = useCallback(() => {\n if (onClick) {\n onClick();\n setOpenMenuId(null);\n }\n }, [onClick, setOpenMenuId]);\n\n return (\n <button\n role=\"menuitem\"\n onClick={handleClick}\n disabled={disabled}\n className={cx(menuItem, className)}\n style={style}\n data-testid={testId}\n ref={ref}\n type=\"button\"\n tabIndex={-1}\n {...rest}\n >\n {icon && <span>{icon}</span>}\n <span>{children}</span>\n {shortcutText && <span className={shortcut}>{shortcutText}</span>}\n </button>\n );\n};\n\nMenuBarItem.displayName = 'MenuBar.Item';\n\nconst MenuBarSub: React.FC<MenuBarSubProps> = ({\n label,\n children,\n disabled = false,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const { menuOffset } = useMenuBar();\n const [open, setOpen] = useState(false);\n const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleEnter = useCallback(() => {\n if (closeTimer.current) {\n clearTimeout(closeTimer.current);\n closeTimer.current = null;\n }\n if (!disabled) setOpen(true);\n }, [disabled]);\n\n const handleLeave = useCallback(() => {\n closeTimer.current = setTimeout(() => {\n setOpen(false);\n }, SUBMENU_CLOSE_DELAY);\n }, []);\n\n useEffect(() => {\n return () => {\n if (closeTimer.current) clearTimeout(closeTimer.current);\n };\n }, []);\n\n return (\n <div\n ref={ref}\n className={cx(subContainer, className)}\n style={style}\n data-testid={testId}\n onMouseEnter={handleEnter}\n onMouseLeave={handleLeave}\n {...rest}\n >\n <button\n className={subTrigger}\n role=\"menuitem\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n disabled={disabled}\n type=\"button\"\n tabIndex={-1}\n >\n <span>{label}</span>\n <ChevronRight />\n </button>\n {open && (\n <div\n className={subDropdown}\n role=\"menu\"\n style={{ left: `calc(100% + ${menuOffset}px)` }}\n >\n {children}\n </div>\n )}\n </div>\n );\n};\n\nMenuBarSub.displayName = 'MenuBar.Sub';\n\nconst MenuBarSeparator: React.FC<MenuBarSeparatorProps> = ({\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n return (\n <div\n role=\"separator\"\n className={cx(separator, className)}\n style={style}\n data-testid={testId}\n ref={ref}\n {...rest}\n />\n );\n};\n\nMenuBarSeparator.displayName = 'MenuBar.Separator';\n\n// --- MenuBarMenu (top-level dropdown trigger) ---\n\nconst MenuBarMenu: React.FC<MenuBarMenuProps> = ({\n label,\n children,\n disabled = false,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const menuId = useId();\n const {\n openMenuId,\n setOpenMenuId,\n registerMenu,\n unregisterMenu,\n menuOffset,\n } = useMenuBar();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const isOpen = openMenuId === menuId;\n\n useEffect(() => {\n registerMenu(menuId);\n return () => {\n unregisterMenu(menuId);\n };\n }, [menuId, registerMenu, unregisterMenu]);\n\n const handleClick = useCallback(() => {\n if (disabled) return;\n setOpenMenuId(isOpen ? null : menuId);\n }, [disabled, isOpen, menuId, setOpenMenuId]);\n\n const handleMouseEnter = useCallback(() => {\n // Open on hover only when another menu is already open\n if (openMenuId !== null && openMenuId !== menuId && !disabled) {\n setOpenMenuId(menuId);\n }\n }, [openMenuId, menuId, disabled, setOpenMenuId]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setOpenMenuId(menuId);\n // Focus first item in dropdown after open\n setTimeout(() => {\n const firstItem = dropdownRef.current?.querySelector(\n MENU_ITEM_SELECTOR\n ) as HTMLElement | null;\n firstItem?.focus();\n }, 0);\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n setOpenMenuId(null);\n triggerRef.current?.focus();\n }\n },\n [menuId, setOpenMenuId]\n );\n\n const handleDropdownKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n const items = Array.from(\n dropdownRef.current?.querySelectorAll<HTMLElement>(\n MENU_ITEM_SELECTOR\n ) ?? []\n );\n const currentIndex = items.indexOf(document.activeElement as HTMLElement);\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n const next = currentIndex + 1 < items.length ? currentIndex + 1 : 0;\n items[next]?.focus();\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n const prev =\n currentIndex - 1 >= 0 ? currentIndex - 1 : items.length - 1;\n items[prev]?.focus();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setOpenMenuId(null);\n triggerRef.current?.focus();\n }\n },\n [setOpenMenuId]\n );\n\n // Close dropdown when clicking outside\n useEffect(() => {\n if (!isOpen) return;\n\n const handleOutsideClick = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n !triggerRef.current?.contains(target) &&\n !dropdownRef.current?.contains(target)\n ) {\n setOpenMenuId(null);\n }\n };\n\n document.addEventListener('mousedown', handleOutsideClick);\n return () => {\n document.removeEventListener('mousedown', handleOutsideClick);\n };\n }, [isOpen, setOpenMenuId]);\n\n return (\n <div\n ref={ref}\n className={cx(menuContainer, className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n <button\n ref={triggerRef}\n className={trigger({ active: isOpen })}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n type=\"button\"\n role=\"menuitem\"\n aria-haspopup=\"true\"\n aria-expanded={isOpen}\n tabIndex={-1}\n >\n {label}\n </button>\n {isOpen && (\n <div\n ref={dropdownRef}\n className={dropdown}\n role=\"menu\"\n aria-label={label}\n // Focusable programmatically so the open menu can receive focus and\n // handle arrow-key navigation across its items.\n tabIndex={-1}\n onKeyDown={handleDropdownKeyDown}\n style={{ top: `calc(100% + ${menuOffset}px)` }}\n >\n {children}\n </div>\n )}\n </div>\n );\n};\n\nMenuBarMenu.displayName = 'MenuBar.Menu';\n\n// --- Root Component ---\n\nconst MenuBarRoot: React.FC<MenuBarProps> = ({\n size = 'md',\n menuOffset = 2,\n children,\n\n className,\n style,\n testId,\n ref: externalRef,\n ...rest\n}) => {\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n // Registered child menu ids, kept in state so the context value stays\n // reactive (previously a ref + forceUpdate, which read the ref during render).\n const [menuIds, setMenuIds] = useState<string[]>([]);\n const safeMenuOffset = Math.max(0, menuOffset);\n const barRef = useRef<HTMLDivElement>(null);\n const setBarRef = useMemo(\n () => (node: HTMLDivElement | null) => {\n barRef.current = node;\n if (typeof externalRef === 'function') {\n externalRef(node);\n } else if (externalRef && typeof externalRef === 'object') {\n externalRef.current = node;\n }\n },\n [externalRef]\n );\n\n const registerMenu = useCallback((id: string) => {\n setMenuIds(prev => (prev.includes(id) ? prev : [...prev, id]));\n }, []);\n\n const unregisterMenu = useCallback((id: string) => {\n setMenuIds(prev => prev.filter(m => m !== id));\n }, []);\n\n const handleBarKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (!barRef.current) return;\n\n const triggers = Array.from(\n barRef.current.querySelectorAll<HTMLElement>(\n ':scope > div > [role=\"menuitem\"]'\n )\n );\n const currentIndex = triggers.indexOf(\n document.activeElement as HTMLElement\n );\n\n if (e.key === 'ArrowRight') {\n e.preventDefault();\n const next = currentIndex + 1 < triggers.length ? currentIndex + 1 : 0;\n triggers[next]?.focus();\n // If menu is open, switch to next menu\n if (openMenuId !== null) {\n triggers[next]?.click();\n }\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n const prev =\n currentIndex - 1 >= 0 ? currentIndex - 1 : triggers.length - 1;\n triggers[prev]?.focus();\n if (openMenuId !== null) {\n triggers[prev]?.click();\n }\n }\n },\n [openMenuId]\n );\n\n const contextValue = useMemo(\n () => ({\n size,\n menuOffset: safeMenuOffset,\n openMenuId,\n setOpenMenuId,\n registerMenu,\n unregisterMenu,\n menuIds,\n }),\n [\n size,\n safeMenuOffset,\n openMenuId,\n setOpenMenuId,\n registerMenu,\n unregisterMenu,\n menuIds,\n ]\n );\n\n return (\n <MenuBarContext.Provider value={contextValue}>\n <div\n ref={setBarRef}\n className={cx(menuBarRoot({ size }), className)}\n style={style}\n data-testid={testId}\n role=\"menubar\"\n onKeyDown={handleBarKeyDown}\n tabIndex={0}\n {...rest}\n >\n {children}\n </div>\n </MenuBarContext.Provider>\n );\n};\n\nMenuBarRoot.displayName = 'MenuBar';\n\n// --- Compound Component ---\n\nexport const MenuBar = /*#__PURE__*/ Object.assign(MenuBarRoot, {\n Menu: MenuBarMenu,\n Item: MenuBarItem,\n Sub: MenuBarSub,\n Separator: MenuBarSeparator,\n});\n"],"names":[],"mappings":";;;;;;AAsCA;AAEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACD;AAED;AAEA;AAEA;AAEA;AAGM;AACA;AACD;AAML;AAEA;AAaE;AAEA;;AAEI;;;AAGJ;AAEA;AAkBF;AAEA;AAEA;AAWE;;AAEA;AAEA;AACE;AACE;AACA;;AAEF;;AACF;AAEA;AACE;;;;;AAMA;;AAC0B;AAC1B;;;AAoCJ;AAEA;AAEA;AAOE;AAUF;AAEA;AAEA;AAEA;AAWE;AACA;AAOA;AACA;AACA;;;AAIE;;AAEA;;AAGF;AACE;;;;AAIF;;;;;;AAOA;AAEI;;;;;;;;;AAWA;;;AAGE;;AAEJ;AAIF;AAEI;;AAOA;;AAEE;AACA;;AACK;;;AAIL;;AACK;;;AAGL;;AAEJ;;;AAMA;;AAEA;AACE;;;;;AAOF;AAEA;AACA;AACE;AACF;AACF;AAEA;;;;AAwCF;AAEA;AAEA;AAEA;;;;;;AAgBE;;AAGI;AACA;;;AAEO;AACL;;AAEJ;AAIF;;;AAIA;AACE;;AAGF;;;AAII;;AASA;;AAEE;AACA;;AAEA;AACE;;;AAEG;;;AAIL;AACA;AACE;;;AAGN;AAIF;;AAGI;;;;;;AAMD;;;;;;;;AASA;;AAmBL;AAEA;AAEA;AAEO;AACL;AACA;AACA;AACA;AACD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBar.js","sources":["../../../../../../src/components/shell/StatusBar/StatusBar.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAqBA;AACE;AACD;AAED;AAEA;AAEA;AAWI;AAWF;AAGF;AAEA;AAeI;;;AAeE;;AAiBF;AAYF;AAGF;AAEA;AAEA;AAWE;;AAiBF;AAEA;AAEA;AAEO;AACL;AACA;AACD;;"}
1
+ {"version":3,"file":"StatusBar.js","sources":["src/components/shell/StatusBar/StatusBar.tsx"],"sourcesContent":["'use client';\n\nimport React, { createContext, useContext, useMemo } from 'react';\n\nimport { cx } from '@/utils/cx';\n\nimport {\n statusBarRoot,\n statusBarSection,\n itemButton,\n itemSpan,\n badge,\n} from './StatusBar.css';\n\nimport type {\n StatusBarProps,\n StatusBarSectionProps,\n StatusBarItemProps,\n StatusBarContextValue,\n} from './StatusBar.types';\n\nconst StatusBarContext = /*#__PURE__*/ createContext<StatusBarContextValue>({\n size: 'sm',\n});\n\nconst useStatusBar = () => useContext(StatusBarContext);\n\n// --- Sub-components ---\n\nconst StatusBarSection = /*#__PURE__*/ React.memo<StatusBarSectionProps>(\n ({\n side = 'left',\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n return (\n <div\n ref={ref}\n className={cx(statusBarSection({ side }), className)}\n style={style}\n data-testid={testId}\n {...rest}\n >\n {children}\n </div>\n );\n }\n);\n\nStatusBarSection.displayName = 'StatusBar.Section';\n\nconst StatusBarItem = /*#__PURE__*/ React.memo<StatusBarItemProps>(\n ({\n onClick,\n icon,\n children,\n title,\n badge: badgeProp,\n disabled = false,\n\n className,\n style,\n testId,\n ref,\n ...rest\n }) => {\n useStatusBar();\n\n const content = (\n <>\n {icon}\n {children && <span>{children}</span>}\n {badgeProp !== undefined && badgeProp !== false && (\n <span className={badge({ dot: badgeProp === true })}>\n {typeof badgeProp === 'number' ? badgeProp : null}\n </span>\n )}\n </>\n );\n\n if (onClick) {\n return (\n <button\n onClick={onClick}\n title={title}\n disabled={disabled}\n className={cx(itemButton, className)}\n style={style}\n data-testid={testId}\n ref={ref as React.Ref<HTMLButtonElement>}\n type=\"button\"\n {...rest}\n >\n {content}\n </button>\n );\n }\n\n return (\n <span\n title={title}\n className={cx(itemSpan, className)}\n style={style}\n data-testid={testId}\n ref={ref}\n {...rest}\n >\n {content}\n </span>\n );\n }\n);\n\nStatusBarItem.displayName = 'StatusBar.Item';\n\n// --- Root Component ---\n\nconst StatusBarRoot: React.FC<StatusBarProps> = ({\n size = 'sm',\n variant = 'default',\n children,\n\n className,\n style,\n testId,\n ref,\n ...rest\n}) => {\n const contextValue = useMemo(() => ({ size }), [size]);\n\n return (\n <StatusBarContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cx(statusBarRoot({ variant, size }), className)}\n style={style}\n data-testid={testId}\n role=\"status\"\n aria-live=\"polite\"\n {...rest}\n >\n {children}\n </div>\n </StatusBarContext.Provider>\n );\n};\n\nStatusBarRoot.displayName = 'StatusBar';\n\n// --- Compound Component ---\n\nexport const StatusBar = /*#__PURE__*/ Object.assign(StatusBarRoot, {\n Section: StatusBarSection,\n Item: StatusBarItem,\n});\n"],"names":[],"mappings":";;;;;;AAqBA;AACE;AACD;AAED;AAEA;AAEA;AAWI;AAWF;AAGF;AAEA;AAeI;;;AAeE;;AAiBF;AAYF;AAGF;AAEA;AAEA;AAWE;;AAiBF;AAEA;AAEA;AAEO;AACL;AACA;AACD;;"}