entangle-ui 0.10.0 → 0.12.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 (589) hide show
  1. package/CHANGELOG.md +145 -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/controls/Slider/{Slider.css.ts.vanilla-Cqm3fQ0S.css → Slider.css.ts.vanilla-CLf_RC0A.css} +50 -47
  5. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyPanel.css.ts.vanilla-RYv_XgOu.css → PropertyPanel.css.ts.vanilla-Dpr_k5I3.css} +4 -1
  6. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertyRow.css.ts.vanilla-C3YZnnHb.css → PropertyRow.css.ts.vanilla-pq1Uhd2a.css} +15 -8
  7. package/dist/esm/assets/src/components/editor/PropertyInspector/{PropertySection.css.ts.vanilla-DK12opZc.css → PropertySection.css.ts.vanilla-6MWWAqyd.css} +50 -32
  8. package/dist/esm/assets/src/components/navigation/Menu/{Menu.css.ts.vanilla-B5iVe5S2.css → Menu.css.ts.vanilla-Bhh1L5yl.css} +14 -11
  9. package/dist/esm/assets/src/components/primitives/Tooltip/{Tooltip.css.ts.vanilla-CrEFoLBX.css → Tooltip.css.ts.vanilla-BqaiGrFQ.css} +12 -9
  10. package/dist/esm/assets/src/components/shell/AppShell/{AppShell.css.ts.vanilla-BYmtU0O_.css → AppShell.css.ts.vanilla-BLK2-DRL.css} +1 -0
  11. package/dist/esm/assets/src/components/shell/MenuBar/{MenuBar.css.ts.vanilla-TgPcl4yA.css → MenuBar.css.ts.vanilla-Dt3w4f-q.css} +18 -6
  12. package/dist/esm/components/Icons/AddIcon.js.map +1 -1
  13. package/dist/esm/components/Icons/AiChatIcon.js.map +1 -1
  14. package/dist/esm/components/Icons/AiSparklesIcon.js.map +1 -1
  15. package/dist/esm/components/Icons/ArchiveIcon.js.map +1 -1
  16. package/dist/esm/components/Icons/ArrowDownIcon.js.map +1 -1
  17. package/dist/esm/components/Icons/ArrowLeftIcon.js.map +1 -1
  18. package/dist/esm/components/Icons/ArrowRightIcon.js.map +1 -1
  19. package/dist/esm/components/Icons/ArrowUpIcon.js.map +1 -1
  20. package/dist/esm/components/Icons/BookmarkIcon.js.map +1 -1
  21. package/dist/esm/components/Icons/BugIcon.js.map +1 -1
  22. package/dist/esm/components/Icons/BuildingIcon.js.map +1 -1
  23. package/dist/esm/components/Icons/CalendarIcon.js.map +1 -1
  24. package/dist/esm/components/Icons/CameraIcon.js +31 -0
  25. package/dist/esm/components/Icons/CameraIcon.js.map +1 -0
  26. package/dist/esm/components/Icons/CheckIcon.js.map +1 -1
  27. package/dist/esm/components/Icons/ChevronDownIcon.js.map +1 -1
  28. package/dist/esm/components/Icons/ChevronLeftIcon.js.map +1 -1
  29. package/dist/esm/components/Icons/ChevronRightIcon.js.map +1 -1
  30. package/dist/esm/components/Icons/ChevronUpIcon.js.map +1 -1
  31. package/dist/esm/components/Icons/CircleIcon.js.map +1 -1
  32. package/dist/esm/components/Icons/ClockIcon.js.map +1 -1
  33. package/dist/esm/components/Icons/CloseIcon.js.map +1 -1
  34. package/dist/esm/components/Icons/CloudUploadIcon.js.map +1 -1
  35. package/dist/esm/components/Icons/CodeIcon.js.map +1 -1
  36. package/dist/esm/components/Icons/CopyIcon.js.map +1 -1
  37. package/dist/esm/components/Icons/CubeIcon.js +31 -0
  38. package/dist/esm/components/Icons/CubeIcon.js.map +1 -0
  39. package/dist/esm/components/Icons/CutIcon.js.map +1 -1
  40. package/dist/esm/components/Icons/DotsHorizontalIcon.js.map +1 -1
  41. package/dist/esm/components/Icons/DotsVerticalIcon.js.map +1 -1
  42. package/dist/esm/components/Icons/DownloadIcon.js.map +1 -1
  43. package/dist/esm/components/Icons/EditIcon.js.map +1 -1
  44. package/dist/esm/components/Icons/ErrorIcon.js.map +1 -1
  45. package/dist/esm/components/Icons/ExternalLinkIcon.js.map +1 -1
  46. package/dist/esm/components/Icons/EyeDropperIcon.js.map +1 -1
  47. package/dist/esm/components/Icons/EyeIcon.js.map +1 -1
  48. package/dist/esm/components/Icons/FileTextIcon.js.map +1 -1
  49. package/dist/esm/components/Icons/FilterIcon.js.map +1 -1
  50. package/dist/esm/components/Icons/FirstIcon.js.map +1 -1
  51. package/dist/esm/components/Icons/FolderCogIcon.js.map +1 -1
  52. package/dist/esm/components/Icons/FolderIcon.js.map +1 -1
  53. package/dist/esm/components/Icons/FolderOpenIcon.js.map +1 -1
  54. package/dist/esm/components/Icons/FullscreenIcon.js.map +1 -1
  55. package/dist/esm/components/Icons/GitBranchIcon.js.map +1 -1
  56. package/dist/esm/components/Icons/GridIcon.js.map +1 -1
  57. package/dist/esm/components/Icons/HeartIcon.js.map +1 -1
  58. package/dist/esm/components/Icons/HelpIcon.js.map +1 -1
  59. package/dist/esm/components/Icons/HomeIcon.js.map +1 -1
  60. package/dist/esm/components/Icons/ImageIcon.js.map +1 -1
  61. package/dist/esm/components/Icons/InfoIcon.js.map +1 -1
  62. package/dist/esm/components/Icons/LastIcon.js.map +1 -1
  63. package/dist/esm/components/Icons/LinkIcon.js.map +1 -1
  64. package/dist/esm/components/Icons/ListIcon.js.map +1 -1
  65. package/dist/esm/components/Icons/LockIcon.js.map +1 -1
  66. package/dist/esm/components/Icons/MaximizeIcon.js.map +1 -1
  67. package/dist/esm/components/Icons/MenuIcon.js.map +1 -1
  68. package/dist/esm/components/Icons/MinimizeIcon.js.map +1 -1
  69. package/dist/esm/components/Icons/MinusIcon.js.map +1 -1
  70. package/dist/esm/components/Icons/OrbitIcon.js +31 -0
  71. package/dist/esm/components/Icons/OrbitIcon.js.map +1 -0
  72. package/dist/esm/components/Icons/PasteIcon.js.map +1 -1
  73. package/dist/esm/components/Icons/PauseIcon.js.map +1 -1
  74. package/dist/esm/components/Icons/PinIcon.js.map +1 -1
  75. package/dist/esm/components/Icons/PlayIcon.js.map +1 -1
  76. package/dist/esm/components/Icons/RedoIcon.js.map +1 -1
  77. package/dist/esm/components/Icons/RefreshIcon.js.map +1 -1
  78. package/dist/esm/components/Icons/RobotIcon.js.map +1 -1
  79. package/dist/esm/components/Icons/RotateIcon.js +32 -0
  80. package/dist/esm/components/Icons/RotateIcon.js.map +1 -0
  81. package/dist/esm/components/Icons/SaveIcon.js.map +1 -1
  82. package/dist/esm/components/Icons/SearchIcon.js.map +1 -1
  83. package/dist/esm/components/Icons/SendIcon.js.map +1 -1
  84. package/dist/esm/components/Icons/SettingsIcon.js.map +1 -1
  85. package/dist/esm/components/Icons/SortIcon.js.map +1 -1
  86. package/dist/esm/components/Icons/SpinIcon.js +32 -0
  87. package/dist/esm/components/Icons/SpinIcon.js.map +1 -0
  88. package/dist/esm/components/Icons/StarIcon.js.map +1 -1
  89. package/dist/esm/components/Icons/StopIcon.js.map +1 -1
  90. package/dist/esm/components/Icons/SuccessIcon.js.map +1 -1
  91. package/dist/esm/components/Icons/TagIcon.js.map +1 -1
  92. package/dist/esm/components/Icons/TangentAlignedIcon.js.map +1 -1
  93. package/dist/esm/components/Icons/TangentAutoIcon.js.map +1 -1
  94. package/dist/esm/components/Icons/TangentFreeIcon.js.map +1 -1
  95. package/dist/esm/components/Icons/TangentLinearIcon.js.map +1 -1
  96. package/dist/esm/components/Icons/TangentMirroredIcon.js.map +1 -1
  97. package/dist/esm/components/Icons/TangentStepIcon.js.map +1 -1
  98. package/dist/esm/components/Icons/TerminalIcon.js.map +1 -1
  99. package/dist/esm/components/Icons/TrashIcon.js.map +1 -1
  100. package/dist/esm/components/Icons/UndoIcon.js.map +1 -1
  101. package/dist/esm/components/Icons/UnlinkIcon.js.map +1 -1
  102. package/dist/esm/components/Icons/UnlockIcon.js.map +1 -1
  103. package/dist/esm/components/Icons/UploadIcon.js.map +1 -1
  104. package/dist/esm/components/Icons/UserIcon.js.map +1 -1
  105. package/dist/esm/components/Icons/UsersIcon.js.map +1 -1
  106. package/dist/esm/components/Icons/WarningIcon.js.map +1 -1
  107. package/dist/esm/components/Icons/ZoomFitIcon.js +32 -0
  108. package/dist/esm/components/Icons/ZoomFitIcon.js.map +1 -0
  109. package/dist/esm/components/Icons/ZoomInIcon.js.map +1 -1
  110. package/dist/esm/components/Icons/ZoomOutIcon.js.map +1 -1
  111. package/dist/esm/components/controls/CartesianPicker/CartesianPicker.js.map +1 -1
  112. package/dist/esm/components/controls/CartesianPicker/useCartesianInteraction.js.map +1 -1
  113. package/dist/esm/components/controls/CartesianPicker/useCartesianRenderer.js.map +1 -1
  114. package/dist/esm/components/controls/ColorPicker/AlphaSlider.js.map +1 -1
  115. package/dist/esm/components/controls/ColorPicker/ColorArea.js.map +1 -1
  116. package/dist/esm/components/controls/ColorPicker/ColorInputs.js.map +1 -1
  117. package/dist/esm/components/controls/ColorPicker/ColorPalette.js.map +1 -1
  118. package/dist/esm/components/controls/ColorPicker/ColorPicker.js.map +1 -1
  119. package/dist/esm/components/controls/ColorPicker/ColorPresets.js.map +1 -1
  120. package/dist/esm/components/controls/ColorPicker/ColorSwatch.js.map +1 -1
  121. package/dist/esm/components/controls/ColorPicker/EyeDropper.js.map +1 -1
  122. package/dist/esm/components/controls/ColorPicker/HueSlider.js.map +1 -1
  123. package/dist/esm/components/controls/ColorPicker/colorUtils.js.map +1 -1
  124. package/dist/esm/components/controls/ColorPicker/palettes/material.js.map +1 -1
  125. package/dist/esm/components/controls/ColorPicker/palettes/professional.js.map +1 -1
  126. package/dist/esm/components/controls/ColorPicker/palettes/tailwind.js.map +1 -1
  127. package/dist/esm/components/controls/ColorPicker/useColor.js.map +1 -1
  128. package/dist/esm/components/controls/Combobox/Combobox.js.map +1 -1
  129. package/dist/esm/components/controls/CurveEditor/CurveCanvas.js.map +1 -1
  130. package/dist/esm/components/controls/CurveEditor/CurveEditor.js.map +1 -1
  131. package/dist/esm/components/controls/CurveEditor/CurveToolbar.js.map +1 -1
  132. package/dist/esm/components/controls/CurveEditor/curvePresets.js.map +1 -1
  133. package/dist/esm/components/controls/CurveEditor/curveUtils.js.map +1 -1
  134. package/dist/esm/components/controls/CurveEditor/useCurveInteraction.js.map +1 -1
  135. package/dist/esm/components/controls/CurveEditor/useCurveRenderer.js.map +1 -1
  136. package/dist/esm/components/controls/FileTree/FileTree.js +7 -1
  137. package/dist/esm/components/controls/FileTree/FileTree.js.map +1 -1
  138. package/dist/esm/components/controls/FileTree/fileTreeIcons.js.map +1 -1
  139. package/dist/esm/components/controls/FileTree/fileTreeLabels.js.map +1 -1
  140. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js +1 -1
  141. package/dist/esm/components/controls/FileTree/useFileTreeDrop.js.map +1 -1
  142. package/dist/esm/components/controls/FileUploader/FileUploader.js.map +1 -1
  143. package/dist/esm/components/controls/MultiSelect/MultiSelect.js.map +1 -1
  144. package/dist/esm/components/controls/NumberInput/NumberInput.js.map +1 -1
  145. package/dist/esm/components/controls/NumberInput/useNumberInput.js.map +1 -1
  146. package/dist/esm/components/controls/Select/Select.css.js +1 -1
  147. package/dist/esm/components/controls/Select/Select.js +15 -7
  148. package/dist/esm/components/controls/Select/Select.js.map +1 -1
  149. package/dist/esm/components/controls/Slider/Slider.css.js +10 -11
  150. package/dist/esm/components/controls/Slider/Slider.css.js.map +1 -1
  151. package/dist/esm/components/controls/Slider/Slider.js +40 -7
  152. package/dist/esm/components/controls/Slider/Slider.js.map +1 -1
  153. package/dist/esm/components/controls/TagInput/TagInput.js.map +1 -1
  154. package/dist/esm/components/controls/TreeView/TreeNode.js +6 -0
  155. package/dist/esm/components/controls/TreeView/TreeNode.js.map +1 -1
  156. package/dist/esm/components/controls/TreeView/TreeView.js.map +1 -1
  157. package/dist/esm/components/controls/TreeView/useTreeState.js.map +1 -1
  158. package/dist/esm/components/controls/VectorInput/VectorInput.js +6 -0
  159. package/dist/esm/components/controls/VectorInput/VectorInput.js.map +1 -1
  160. package/dist/esm/components/data/DataTable/DataTable.js.map +1 -1
  161. package/dist/esm/components/editor/AssetBrowser/AssetBrowser.js.map +1 -1
  162. package/dist/esm/components/editor/AssetBrowser/AssetBrowserAnnouncementLive.js.map +1 -1
  163. package/dist/esm/components/editor/AssetBrowser/AssetBrowserBreadcrumbs.js.map +1 -1
  164. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js +6 -0
  165. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContent.js.map +1 -1
  166. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContext.js.map +1 -1
  167. package/dist/esm/components/editor/AssetBrowser/AssetBrowserContextMenu.js.map +1 -1
  168. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js +6 -0
  169. package/dist/esm/components/editor/AssetBrowser/AssetBrowserDefaultMenus.js.map +1 -1
  170. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js +1 -1
  171. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGrid.js.map +1 -1
  172. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js +6 -0
  173. package/dist/esm/components/editor/AssetBrowser/AssetBrowserGridItem.js.map +1 -1
  174. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js +6 -0
  175. package/dist/esm/components/editor/AssetBrowser/AssetBrowserList.js.map +1 -1
  176. package/dist/esm/components/editor/AssetBrowser/AssetBrowserRenameField.js.map +1 -1
  177. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSidebar.js.map +1 -1
  178. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStatusBar.js.map +1 -1
  179. package/dist/esm/components/editor/AssetBrowser/AssetBrowserStore.js.map +1 -1
  180. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js +6 -0
  181. package/dist/esm/components/editor/AssetBrowser/AssetBrowserSurface.js.map +1 -1
  182. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js +6 -0
  183. package/dist/esm/components/editor/AssetBrowser/AssetBrowserToolbar.js.map +1 -1
  184. package/dist/esm/components/editor/AssetBrowser/assetBrowserFilter.js.map +1 -1
  185. package/dist/esm/components/editor/AssetBrowser/assetBrowserFormat.js.map +1 -1
  186. package/dist/esm/components/editor/AssetBrowser/assetBrowserGeometry.js.map +1 -1
  187. package/dist/esm/components/editor/AssetBrowser/assetBrowserKeyboard.js.map +1 -1
  188. package/dist/esm/components/editor/AssetBrowser/assetBrowserLabels.js.map +1 -1
  189. package/dist/esm/components/editor/AssetBrowser/slots.js.map +1 -1
  190. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserAnnouncement.js.map +1 -1
  191. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js +1 -1
  192. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserHandle.js.map +1 -1
  193. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js +1 -1
  194. package/dist/esm/components/editor/AssetBrowser/useAssetBrowserViewState.js.map +1 -1
  195. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js +1 -1
  196. package/dist/esm/components/editor/AssetBrowser/useAssetDnd.js.map +1 -1
  197. package/dist/esm/components/editor/AssetBrowser/useAssetGridKeyboardNav.js.map +1 -1
  198. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js +1 -1
  199. package/dist/esm/components/editor/AssetBrowser/useAssetGridVirtualizer.js.map +1 -1
  200. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js +1 -1
  201. package/dist/esm/components/editor/AssetBrowser/useAssetMarqueeGesture.js.map +1 -1
  202. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js +1 -1
  203. package/dist/esm/components/editor/AssetBrowser/useAssetMutationKeyboard.js.map +1 -1
  204. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js +1 -1
  205. package/dist/esm/components/editor/AssetBrowser/useAssetMutations.js.map +1 -1
  206. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js +1 -1
  207. package/dist/esm/components/editor/AssetBrowser/useAssetNavigation.js.map +1 -1
  208. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js +1 -1
  209. package/dist/esm/components/editor/AssetBrowser/useAssetSelectionController.js.map +1 -1
  210. package/dist/esm/components/editor/ChatPanel/ChatActionBar.js.map +1 -1
  211. package/dist/esm/components/editor/ChatPanel/ChatAttachment.js.map +1 -1
  212. package/dist/esm/components/editor/ChatPanel/ChatBubble.js.map +1 -1
  213. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js +6 -0
  214. package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js.map +1 -1
  215. package/dist/esm/components/editor/ChatPanel/ChatContextChip.js.map +1 -1
  216. package/dist/esm/components/editor/ChatPanel/ChatEmptyState.js.map +1 -1
  217. package/dist/esm/components/editor/ChatPanel/ChatIcons.js.map +1 -1
  218. package/dist/esm/components/editor/ChatPanel/ChatInput.js +6 -0
  219. package/dist/esm/components/editor/ChatPanel/ChatInput.js.map +1 -1
  220. package/dist/esm/components/editor/ChatPanel/ChatInputToolbar.js.map +1 -1
  221. package/dist/esm/components/editor/ChatPanel/ChatMarkdownRenderer.js.map +1 -1
  222. package/dist/esm/components/editor/ChatPanel/ChatMessage.js +6 -0
  223. package/dist/esm/components/editor/ChatPanel/ChatMessage.js.map +1 -1
  224. package/dist/esm/components/editor/ChatPanel/ChatMessageList.js.map +1 -1
  225. package/dist/esm/components/editor/ChatPanel/ChatPanel.js.map +1 -1
  226. package/dist/esm/components/editor/ChatPanel/ChatToolCall.js.map +1 -1
  227. package/dist/esm/components/editor/ChatPanel/ChatTypingIndicator.js.map +1 -1
  228. package/dist/esm/components/editor/ChatPanel/useChatInput.js.map +1 -1
  229. package/dist/esm/components/editor/ChatPanel/useChatMessages.js.map +1 -1
  230. package/dist/esm/components/editor/ChatPanel/useChatScroll.js.map +1 -1
  231. package/dist/esm/components/editor/Minimap/Minimap.js +1 -1
  232. package/dist/esm/components/editor/Minimap/Minimap.js.map +1 -1
  233. package/dist/esm/components/editor/Minimap/Minimap.types.js.map +1 -1
  234. package/dist/esm/components/editor/Minimap/MinimapContext.js.map +1 -1
  235. package/dist/esm/components/editor/Minimap/MinimapCorner.js.map +1 -1
  236. package/dist/esm/components/editor/Minimap/MinimapFooter.js.map +1 -1
  237. package/dist/esm/components/editor/Minimap/MinimapStore.js.map +1 -1
  238. package/dist/esm/components/editor/Minimap/MinimapTitle.js.map +1 -1
  239. package/dist/esm/components/editor/Minimap/ViewportMinimap.js +1 -1
  240. package/dist/esm/components/editor/Minimap/ViewportMinimap.js.map +1 -1
  241. package/dist/esm/components/editor/Minimap/computeBoundsFromItems.js.map +1 -1
  242. package/dist/esm/components/editor/Minimap/index.js.map +1 -1
  243. package/dist/esm/components/editor/Minimap/minimapCoords.js.map +1 -1
  244. package/dist/esm/components/editor/Minimap/minimapDrawing.js.map +1 -1
  245. package/dist/esm/components/editor/Minimap/minimapHitTest.js.map +1 -1
  246. package/dist/esm/components/editor/Minimap/useMinimapGestures.js +1 -1
  247. package/dist/esm/components/editor/Minimap/useMinimapGestures.js.map +1 -1
  248. package/dist/esm/components/editor/NodeGraph/NodeGraph.js +1 -1
  249. package/dist/esm/components/editor/NodeGraph/NodeGraph.js.map +1 -1
  250. package/dist/esm/components/editor/NodeGraph/NodeGraph.types.js.map +1 -1
  251. package/dist/esm/components/editor/NodeGraph/NodeGraphContext.js.map +1 -1
  252. package/dist/esm/components/editor/NodeGraph/NodeGraphEdgeLabels.js.map +1 -1
  253. package/dist/esm/components/editor/NodeGraph/NodeGraphGroup.js.map +1 -1
  254. package/dist/esm/components/editor/NodeGraph/NodeGraphMinimap.js.map +1 -1
  255. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js +1 -1
  256. package/dist/esm/components/editor/NodeGraph/NodeGraphNode.js.map +1 -1
  257. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeContext.js.map +1 -1
  258. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeParts.js.map +1 -1
  259. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js +1 -1
  260. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSection.js.map +1 -1
  261. package/dist/esm/components/editor/NodeGraph/NodeGraphNodeSectionContext.js.map +1 -1
  262. package/dist/esm/components/editor/NodeGraph/NodeGraphPin.js.map +1 -1
  263. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js +1 -1
  264. package/dist/esm/components/editor/NodeGraph/NodeGraphPort.js.map +1 -1
  265. package/dist/esm/components/editor/NodeGraph/NodeGraphPortVisual.js.map +1 -1
  266. package/dist/esm/components/editor/NodeGraph/NodeGraphSlots.js.map +1 -1
  267. package/dist/esm/components/editor/NodeGraph/NodeGraphSpawnPalette.js.map +1 -1
  268. package/dist/esm/components/editor/NodeGraph/NodeGraphStore.js.map +1 -1
  269. package/dist/esm/components/editor/NodeGraph/NodeGraphToolbar.js.map +1 -1
  270. package/dist/esm/components/editor/NodeGraph/createTypeMatchValidator.js.map +1 -1
  271. package/dist/esm/components/editor/NodeGraph/nodeGraphActions.js.map +1 -1
  272. package/dist/esm/components/editor/NodeGraph/nodeGraphDrawing.js.map +1 -1
  273. package/dist/esm/components/editor/NodeGraph/nodeGraphIds.js.map +1 -1
  274. package/dist/esm/components/editor/NodeGraph/nodeGraphMath.js.map +1 -1
  275. package/dist/esm/components/editor/NodeGraph/sortSlots.js.map +1 -1
  276. package/dist/esm/components/editor/NodeGraph/useDragGesture.js.map +1 -1
  277. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js +1 -1
  278. package/dist/esm/components/editor/NodeGraph/useNodeGraph.js.map +1 -1
  279. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js +1 -1
  280. package/dist/esm/components/editor/NodeGraph/useNodeGraphConnection.js.map +1 -1
  281. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js +1 -1
  282. package/dist/esm/components/editor/NodeGraph/useNodeGraphEdgeInteraction.js.map +1 -1
  283. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js +1 -1
  284. package/dist/esm/components/editor/NodeGraph/useNodeGraphGroupDrag.js.map +1 -1
  285. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js +1 -1
  286. package/dist/esm/components/editor/NodeGraph/useNodeGraphKeyboard.js.map +1 -1
  287. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js +1 -1
  288. package/dist/esm/components/editor/NodeGraph/useNodeGraphNodeDrag.js.map +1 -1
  289. package/dist/esm/components/editor/NodeGraph/useStoreSlice.js.map +1 -1
  290. package/dist/esm/components/editor/PropertyInspector/PropertyGroup.js.map +1 -1
  291. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js +4 -3
  292. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.css.js.map +1 -1
  293. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js +5 -4
  294. package/dist/esm/components/editor/PropertyInspector/PropertyPanel.js.map +1 -1
  295. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js +7 -6
  296. package/dist/esm/components/editor/PropertyInspector/PropertyRow.css.js.map +1 -1
  297. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js +18 -3
  298. package/dist/esm/components/editor/PropertyInspector/PropertyRow.js.map +1 -1
  299. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js +11 -10
  300. package/dist/esm/components/editor/PropertyInspector/PropertySection.css.js.map +1 -1
  301. package/dist/esm/components/editor/PropertyInspector/PropertySection.js +29 -21
  302. package/dist/esm/components/editor/PropertyInspector/PropertySection.js.map +1 -1
  303. package/dist/esm/components/editor/PropertyInspector/usePropertyUndo.js.map +1 -1
  304. package/dist/esm/components/editor/Timeline/Timeline.js +1 -1
  305. package/dist/esm/components/editor/Timeline/Timeline.js.map +1 -1
  306. package/dist/esm/components/editor/Timeline/Timeline.types.js.map +1 -1
  307. package/dist/esm/components/editor/Timeline/TimelineContext.js.map +1 -1
  308. package/dist/esm/components/editor/Timeline/TimelineFooter.js.map +1 -1
  309. package/dist/esm/components/editor/Timeline/TimelineMinimap.js +1 -1
  310. package/dist/esm/components/editor/Timeline/TimelineMinimap.js.map +1 -1
  311. package/dist/esm/components/editor/Timeline/TimelineStore.js.map +1 -1
  312. package/dist/esm/components/editor/Timeline/TimelineToolbar.js.map +1 -1
  313. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js +1 -1
  314. package/dist/esm/components/editor/Timeline/TimelineTrackHeaders.js.map +1 -1
  315. package/dist/esm/components/editor/Timeline/TimelineTrackScale.js.map +1 -1
  316. package/dist/esm/components/editor/Timeline/index.js.map +1 -1
  317. package/dist/esm/components/editor/Timeline/timelineCoords.js.map +1 -1
  318. package/dist/esm/components/editor/Timeline/timelineDrawing.js.map +1 -1
  319. package/dist/esm/components/editor/Timeline/timelineEdits.js.map +1 -1
  320. package/dist/esm/components/editor/Timeline/timelineHitTest.js.map +1 -1
  321. package/dist/esm/components/editor/Timeline/timelineLayout.js.map +1 -1
  322. package/dist/esm/components/editor/Timeline/timelineSelection.js.map +1 -1
  323. package/dist/esm/components/editor/Timeline/useTimelineDraw.js +1 -1
  324. package/dist/esm/components/editor/Timeline/useTimelineDraw.js.map +1 -1
  325. package/dist/esm/components/editor/Timeline/useTimelineGestures.js +1 -1
  326. package/dist/esm/components/editor/Timeline/useTimelineGestures.js.map +1 -1
  327. package/dist/esm/components/editor/Timeline/useTimelinePlayback.js.map +1 -1
  328. package/dist/esm/components/editor/TransformControl/TransformControl.js.map +1 -1
  329. package/dist/esm/components/editor/ViewportGizmo/ViewportGizmo.js.map +1 -1
  330. package/dist/esm/components/editor/ViewportGizmo/gizmoMath.js.map +1 -1
  331. package/dist/esm/components/editor/ViewportGizmo/useGizmoInteraction.js.map +1 -1
  332. package/dist/esm/components/editor/ViewportGizmo/useGizmoRenderer.js.map +1 -1
  333. package/dist/esm/components/feedback/Alert/Alert.js.map +1 -1
  334. package/dist/esm/components/feedback/Alert/AlertActions.js.map +1 -1
  335. package/dist/esm/components/feedback/Alert/AlertDescription.js.map +1 -1
  336. package/dist/esm/components/feedback/Alert/AlertTitle.js.map +1 -1
  337. package/dist/esm/components/feedback/CommandPalette/CommandPalette.js.map +1 -1
  338. package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js.map +1 -1
  339. package/dist/esm/components/feedback/CommandPalette/useRecentItems.js.map +1 -1
  340. package/dist/esm/components/feedback/Dialog/Dialog.js.map +1 -1
  341. package/dist/esm/components/feedback/Dialog/DialogBody.js.map +1 -1
  342. package/dist/esm/components/feedback/Dialog/DialogClose.js.map +1 -1
  343. package/dist/esm/components/feedback/Dialog/DialogFooter.js.map +1 -1
  344. package/dist/esm/components/feedback/Dialog/DialogHeader.js.map +1 -1
  345. package/dist/esm/components/feedback/Dialog/useDialogAnimation.js.map +1 -1
  346. package/dist/esm/components/feedback/Drawer/Drawer.js.map +1 -1
  347. package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js.map +1 -1
  348. package/dist/esm/components/feedback/EmptyState/EmptyState.js.map +1 -1
  349. package/dist/esm/components/feedback/LogView/LogView.js.map +1 -1
  350. package/dist/esm/components/feedback/LogView/LogViewBody.js.map +1 -1
  351. package/dist/esm/components/feedback/LogView/LogViewContext.js.map +1 -1
  352. package/dist/esm/components/feedback/LogView/LogViewParts.js.map +1 -1
  353. package/dist/esm/components/feedback/LogView/LogViewStore.js.map +1 -1
  354. package/dist/esm/components/feedback/LogView/logViewLabels.js.map +1 -1
  355. package/dist/esm/components/feedback/LogView/logViewLevels.js.map +1 -1
  356. package/dist/esm/components/feedback/LogView/logViewUtils.js.map +1 -1
  357. package/dist/esm/components/feedback/LogView/useFollowTail.js.map +1 -1
  358. package/dist/esm/components/feedback/LogView/useLogSelection.js.map +1 -1
  359. package/dist/esm/components/feedback/ProgressBar/CircularProgress.js.map +1 -1
  360. package/dist/esm/components/feedback/ProgressBar/ProgressBar.js.map +1 -1
  361. package/dist/esm/components/feedback/Skeleton/Skeleton.js.map +1 -1
  362. package/dist/esm/components/feedback/Skeleton/SkeletonGroup.js.map +1 -1
  363. package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js.map +1 -1
  364. package/dist/esm/components/feedback/Spinner/Spinner.js +12 -3
  365. package/dist/esm/components/feedback/Spinner/Spinner.js.map +1 -1
  366. package/dist/esm/components/feedback/Stat/Stat.js.map +1 -1
  367. package/dist/esm/components/feedback/Toast/ToastContainer.js.map +1 -1
  368. package/dist/esm/components/feedback/Toast/ToastItem.js.map +1 -1
  369. package/dist/esm/components/feedback/Toast/ToastProvider.js.map +1 -1
  370. package/dist/esm/components/feedback/Toast/useToast.js.map +1 -1
  371. package/dist/esm/components/form/FormHelperText.js.map +1 -1
  372. package/dist/esm/components/form/FormLabel.js.map +1 -1
  373. package/dist/esm/components/form/InputWrapper.js.map +1 -1
  374. package/dist/esm/components/layout/Accordion/Accordion.js.map +1 -1
  375. package/dist/esm/components/layout/Accordion/AccordionContent.js.map +1 -1
  376. package/dist/esm/components/layout/Accordion/AccordionItem.js.map +1 -1
  377. package/dist/esm/components/layout/Accordion/AccordionTrigger.js.map +1 -1
  378. package/dist/esm/components/layout/Card/Card.js.map +1 -1
  379. package/dist/esm/components/layout/Divider/Divider.js.map +1 -1
  380. package/dist/esm/components/layout/Flex/Flex.js.map +1 -1
  381. package/dist/esm/components/layout/Grid/Grid.js.map +1 -1
  382. package/dist/esm/components/layout/ListItem/ListItem.js.map +1 -1
  383. package/dist/esm/components/layout/PageHeader/PageHeader.js.map +1 -1
  384. package/dist/esm/components/layout/PanelSurface/PanelSurface.js.map +1 -1
  385. package/dist/esm/components/layout/ScrollArea/ScrollArea.js.map +1 -1
  386. package/dist/esm/components/layout/Spacer/Spacer.js.map +1 -1
  387. package/dist/esm/components/layout/SplitPane/SplitPane.js.map +1 -1
  388. package/dist/esm/components/layout/SplitPane/SplitPanePanel.js.map +1 -1
  389. package/dist/esm/components/layout/Stack/Stack.js.map +1 -1
  390. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js.map +1 -1
  391. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js.map +1 -1
  392. package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbSeparator.js.map +1 -1
  393. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js +6 -0
  394. package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js.map +1 -1
  395. package/dist/esm/components/navigation/ContextMenu/ContextMenu.js +2 -2
  396. package/dist/esm/components/navigation/ContextMenu/ContextMenu.js.map +1 -1
  397. package/dist/esm/components/navigation/Menu/Menu.css.js +11 -10
  398. package/dist/esm/components/navigation/Menu/Menu.css.js.map +1 -1
  399. package/dist/esm/components/navigation/Menu/Menu.js +2 -2
  400. package/dist/esm/components/navigation/Menu/Menu.js.map +1 -1
  401. package/dist/esm/components/navigation/Menu/MenuGapContext.js.map +1 -1
  402. package/dist/esm/components/navigation/Pagination/Pagination.js.map +1 -1
  403. package/dist/esm/components/navigation/Pagination/usePagination.js.map +1 -1
  404. package/dist/esm/components/navigation/PathBar/PathBar.js +7 -1
  405. package/dist/esm/components/navigation/PathBar/PathBar.js.map +1 -1
  406. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js +6 -0
  407. package/dist/esm/components/navigation/PathBar/PathBarSiblingMenu.js.map +1 -1
  408. package/dist/esm/components/navigation/PathBar/pathUtils.js.map +1 -1
  409. package/dist/esm/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -1
  410. package/dist/esm/components/navigation/SegmentedControl/SegmentedControlItem.js.map +1 -1
  411. package/dist/esm/components/navigation/Tabs/Tab.js.map +1 -1
  412. package/dist/esm/components/navigation/Tabs/TabList.js.map +1 -1
  413. package/dist/esm/components/navigation/Tabs/TabPanel.js.map +1 -1
  414. package/dist/esm/components/navigation/Tabs/Tabs.js.map +1 -1
  415. package/dist/esm/components/primitives/Avatar/Avatar.js +6 -0
  416. package/dist/esm/components/primitives/Avatar/Avatar.js.map +1 -1
  417. package/dist/esm/components/primitives/Avatar/AvatarGroup.js.map +1 -1
  418. package/dist/esm/components/primitives/Badge/Badge.js +6 -0
  419. package/dist/esm/components/primitives/Badge/Badge.js.map +1 -1
  420. package/dist/esm/components/primitives/Button/Button.js.map +1 -1
  421. package/dist/esm/components/primitives/Checkbox/Checkbox.js.map +1 -1
  422. package/dist/esm/components/primitives/Checkbox/CheckboxGroup.js.map +1 -1
  423. package/dist/esm/components/primitives/Code/Code.js.map +1 -1
  424. package/dist/esm/components/primitives/Collapsible/Collapsible.js.map +1 -1
  425. package/dist/esm/components/primitives/HoverCard/HoverCard.js.map +1 -1
  426. package/dist/esm/components/primitives/Icon/Icon.js.map +1 -1
  427. package/dist/esm/components/primitives/IconButton/IconButton.js +4 -2
  428. package/dist/esm/components/primitives/IconButton/IconButton.js.map +1 -1
  429. package/dist/esm/components/primitives/Input/Input.js.map +1 -1
  430. package/dist/esm/components/primitives/Kbd/Kbd.js.map +1 -1
  431. package/dist/esm/components/primitives/Link/Link.js.map +1 -1
  432. package/dist/esm/components/primitives/Paper/Paper.js.map +1 -1
  433. package/dist/esm/components/primitives/Popover/Popover.js.map +1 -1
  434. package/dist/esm/components/primitives/Popover/PopoverClose.js.map +1 -1
  435. package/dist/esm/components/primitives/Popover/PopoverContent.js.map +1 -1
  436. package/dist/esm/components/primitives/Popover/PopoverTrigger.js.map +1 -1
  437. package/dist/esm/components/primitives/Radio/Radio.js.map +1 -1
  438. package/dist/esm/components/primitives/Radio/RadioGroup.js.map +1 -1
  439. package/dist/esm/components/primitives/Switch/Switch.js.map +1 -1
  440. package/dist/esm/components/primitives/Text/Text.js.map +1 -1
  441. package/dist/esm/components/primitives/TextArea/TextArea.js.map +1 -1
  442. package/dist/esm/components/primitives/Tooltip/Arrow.js.map +1 -1
  443. package/dist/esm/components/primitives/Tooltip/Tooltip.css.js +6 -5
  444. package/dist/esm/components/primitives/Tooltip/Tooltip.css.js.map +1 -1
  445. package/dist/esm/components/primitives/Tooltip/Tooltip.js +12 -2
  446. package/dist/esm/components/primitives/Tooltip/Tooltip.js.map +1 -1
  447. package/dist/esm/components/primitives/Tooltip/utils.js.map +1 -1
  448. package/dist/esm/components/primitives/VisuallyHidden/VisuallyHidden.js.map +1 -1
  449. package/dist/esm/components/primitives/canvas/CanvasContainer.js.map +1 -1
  450. package/dist/esm/components/primitives/canvas/canvasCoords.js.map +1 -1
  451. package/dist/esm/components/primitives/canvas/canvasDrawing.js.map +1 -1
  452. package/dist/esm/components/primitives/canvas/canvasTheme.js.map +1 -1
  453. package/dist/esm/components/primitives/canvas/useCanvasRenderer.js.map +1 -1
  454. package/dist/esm/components/primitives/viewport/Viewport.js +6 -3
  455. package/dist/esm/components/primitives/viewport/Viewport.js.map +1 -1
  456. package/dist/esm/components/primitives/viewport/ViewportContext.js.map +1 -1
  457. package/dist/esm/components/primitives/viewport/ViewportLayer.js +1 -1
  458. package/dist/esm/components/primitives/viewport/ViewportLayer.js.map +1 -1
  459. package/dist/esm/components/primitives/viewport/ViewportOverlay.js.map +1 -1
  460. package/dist/esm/components/primitives/viewport/ViewportStore.js.map +1 -1
  461. package/dist/esm/components/primitives/viewport/ViewportWorld.js.map +1 -1
  462. package/dist/esm/components/primitives/viewport/useViewportGestures.js +1 -1
  463. package/dist/esm/components/primitives/viewport/useViewportGestures.js.map +1 -1
  464. package/dist/esm/components/primitives/viewport/viewportCoords.js.map +1 -1
  465. package/dist/esm/components/primitives/viewport/viewportMath.js.map +1 -1
  466. package/dist/esm/components/shell/AppShell/AppShell.css.js +1 -1
  467. package/dist/esm/components/shell/AppShell/AppShell.js.map +1 -1
  468. package/dist/esm/components/shell/FloatingPanel/FloatingPanel.js.map +1 -1
  469. package/dist/esm/components/shell/MenuBar/MenuBar.css.js +7 -6
  470. package/dist/esm/components/shell/MenuBar/MenuBar.css.js.map +1 -1
  471. package/dist/esm/components/shell/MenuBar/MenuBar.js +52 -3
  472. package/dist/esm/components/shell/MenuBar/MenuBar.js.map +1 -1
  473. package/dist/esm/components/shell/StatusBar/StatusBar.js.map +1 -1
  474. package/dist/esm/components/shell/Toolbar/Toolbar.js.map +1 -1
  475. package/dist/esm/context/KeyboardContext.js.map +1 -1
  476. package/dist/esm/hooks/useBreakpoint/useBreakpoint.js.map +1 -1
  477. package/dist/esm/hooks/useClickOutside/useClickOutside.js.map +1 -1
  478. package/dist/esm/hooks/useClipboard/useClipboard.js.map +1 -1
  479. package/dist/esm/hooks/useControlledState/useControlledState.js.map +1 -1
  480. package/dist/esm/hooks/useDebounced/useDebouncedCallback.js.map +1 -1
  481. package/dist/esm/hooks/useDebounced/useDebouncedValue.js.map +1 -1
  482. package/dist/esm/hooks/useDisclosure/useDisclosure.js.map +1 -1
  483. package/dist/esm/hooks/useEventCallback/useEventCallback.js.map +1 -1
  484. package/dist/esm/hooks/useFocusTrap/useFocusTrap.js.map +1 -1
  485. package/dist/esm/hooks/useHotkey/useHotkey.js.map +1 -1
  486. package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js.map +1 -1
  487. package/dist/esm/hooks/useIsMounted/useIsMounted.js.map +1 -1
  488. package/dist/esm/hooks/useKeyboard/useKeyboard.js.map +1 -1
  489. package/dist/esm/hooks/useKeyboard/utils.js.map +1 -1
  490. package/dist/esm/hooks/useLatest/useLatest.js.map +1 -1
  491. package/dist/esm/hooks/useListboxNav/useListboxNav.js.map +1 -1
  492. package/dist/esm/hooks/useMediaQuery/useMediaQuery.js.map +1 -1
  493. package/dist/esm/hooks/useMergedRef/useMergedRef.js.map +1 -1
  494. package/dist/esm/hooks/useNavigationHistory/useNavigationHistory.js.map +1 -1
  495. package/dist/esm/hooks/useResizeObserver/useResizeObserver.js.map +1 -1
  496. package/dist/esm/hooks/useTheme/useTheme.js +1 -1
  497. package/dist/esm/hooks/useTheme/useTheme.js.map +1 -1
  498. package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js.map +1 -1
  499. package/dist/esm/index.js +6 -0
  500. package/dist/esm/index.js.map +1 -1
  501. package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
  502. package/dist/esm/styles.css.js +3 -0
  503. package/dist/esm/styles.css.js.map +1 -0
  504. package/dist/esm/theme/ThemeProvider.js +5 -3
  505. package/dist/esm/theme/ThemeProvider.js.map +1 -1
  506. package/dist/esm/theme/VanillaThemeProvider.js.map +1 -1
  507. package/dist/esm/theme/breakpoints.js.map +1 -1
  508. package/dist/esm/theme/createCustomTheme.js +1 -1
  509. package/dist/esm/theme/createCustomTheme.js.map +1 -1
  510. package/dist/esm/theme/createLightTheme.js.map +1 -1
  511. package/dist/esm/theme/darkThemeValues.js.map +1 -1
  512. package/dist/esm/theme/lightThemeValues.js.map +1 -1
  513. package/dist/esm/theme/themeContractData.js.map +1 -1
  514. package/dist/esm/utils/cx.js.map +1 -1
  515. package/dist/esm/utils/devWarn.js.map +1 -1
  516. package/dist/esm/utils/mathExpression.js.map +1 -1
  517. package/dist/esm/utils/mathUtils.js.map +1 -1
  518. package/dist/esm/utils/objects.js.map +1 -1
  519. package/dist/esm/utils/platform.js.map +1 -1
  520. package/dist/tokens/tokens.dark.css +1 -1
  521. package/dist/tokens/tokens.json +1 -1
  522. package/dist/tokens/tokens.light.css +1 -1
  523. package/dist/types/components/Icons/CameraIcon.d.ts +34 -0
  524. package/dist/types/components/Icons/CubeIcon.d.ts +34 -0
  525. package/dist/types/components/Icons/OrbitIcon.d.ts +34 -0
  526. package/dist/types/components/Icons/RotateIcon.d.ts +35 -0
  527. package/dist/types/components/Icons/SpinIcon.d.ts +35 -0
  528. package/dist/types/components/Icons/ZoomFitIcon.d.ts +35 -0
  529. package/dist/types/components/controls/Select/Select.d.ts +1 -1
  530. package/dist/types/components/controls/Select/Select.types.d.ts +43 -9
  531. package/dist/types/components/controls/Slider/Slider.d.ts +7 -0
  532. package/dist/types/components/editor/PropertyInspector/PropertyInspector.types.d.ts +49 -3
  533. package/dist/types/components/feedback/Spinner/Spinner.d.ts +6 -1
  534. package/dist/types/components/feedback/Spinner/Spinner.types.d.ts +8 -0
  535. package/dist/types/components/primitives/Button/Button.d.ts +1 -1
  536. package/dist/types/components/primitives/IconButton/IconButton.d.ts +3 -2
  537. package/dist/types/components/primitives/viewport/Viewport.d.ts +5 -2
  538. package/dist/types/components/shell/MenuBar/MenuBar.d.ts +862 -0
  539. package/dist/types/index.d.ts +6 -0
  540. package/dist/types/theme/ThemeProvider.d.ts +5 -3
  541. package/package.json +6 -2
  542. package/dist/esm/_virtual/_commonjsHelpers.js +0 -6
  543. package/dist/esm/_virtual/_commonjsHelpers.js.map +0 -1
  544. package/dist/esm/_virtual/cjs.js +0 -4
  545. package/dist/esm/_virtual/cjs.js.map +0 -1
  546. package/dist/esm/_virtual/cssesc.js +0 -8
  547. package/dist/esm/_virtual/cssesc.js.map +0 -1
  548. package/dist/esm/_virtual/picocolors.js +0 -8
  549. package/dist/esm/_virtual/picocolors.js.map +0 -1
  550. package/dist/esm/_virtual/picocolors2.js +0 -4
  551. package/dist/esm/_virtual/picocolors2.js.map +0 -1
  552. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js +0 -56
  553. package/dist/esm/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +0 -1
  554. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js +0 -46
  555. package/dist/esm/node_modules/@vanilla-extract/css/adapter/dist/vanilla-extract-css-adapter.esm.js.map +0 -1
  556. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js +0 -13
  557. package/dist/esm/node_modules/@vanilla-extract/css/dist/taggedTemplateLiteral-10998315.esm.js.map +0 -1
  558. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js +0 -962
  559. package/dist/esm/node_modules/@vanilla-extract/css/dist/transformCss-fd0786e1.esm.js.map +0 -1
  560. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js +0 -309
  561. package/dist/esm/node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js.map +0 -1
  562. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js +0 -18
  563. package/dist/esm/node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.esm.js.map +0 -1
  564. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js +0 -23
  565. package/dist/esm/node_modules/@vanilla-extract/css/injectStyles/dist/vanilla-extract-css-injectStyles.esm.js.map +0 -1
  566. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js +0 -1543
  567. package/dist/esm/node_modules/@vanilla-extract/css/node_modules/lru-cache/dist/esm/index.js.map +0 -1
  568. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js +0 -38
  569. package/dist/esm/node_modules/@vanilla-extract/private/dist/vanilla-extract-private.esm.js.map +0 -1
  570. package/dist/esm/node_modules/css-what/lib/es/parse.js +0 -424
  571. package/dist/esm/node_modules/css-what/lib/es/parse.js.map +0 -1
  572. package/dist/esm/node_modules/css-what/lib/es/types.js +0 -29
  573. package/dist/esm/node_modules/css-what/lib/es/types.js.map +0 -1
  574. package/dist/esm/node_modules/cssesc/cssesc.js +0 -120
  575. package/dist/esm/node_modules/cssesc/cssesc.js.map +0 -1
  576. package/dist/esm/node_modules/dedent/dist/dedent.js +0 -100
  577. package/dist/esm/node_modules/dedent/dist/dedent.js.map +0 -1
  578. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js +0 -40
  579. package/dist/esm/node_modules/deep-object-diff/mjs/diff.js.map +0 -1
  580. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js +0 -9
  581. package/dist/esm/node_modules/deep-object-diff/mjs/utils.js.map +0 -1
  582. package/dist/esm/node_modules/deepmerge/dist/cjs.js +0 -143
  583. package/dist/esm/node_modules/deepmerge/dist/cjs.js.map +0 -1
  584. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js +0 -1386
  585. package/dist/esm/node_modules/media-query-parser/dist/media-query-parser.esm.js.map +0 -1
  586. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js +0 -102
  587. package/dist/esm/node_modules/modern-ahocorasick/dist/index.js.map +0 -1
  588. package/dist/esm/node_modules/picocolors/picocolors.js +0 -87
  589. package/dist/esm/node_modules/picocolors/picocolors.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useChatMessages.js","sources":["../../../../../../src/components/editor/ChatPanel/useChatMessages.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYM;;;;AAMJ;AAEA;;;;AAKI;AACF;AAIF;AAEI;AACF;;;AAaM;AAAmB;AACnB;AACA;;;AAOR;;;AAIA;;;AAIA;AAEI;;;;;;;;;;;;;AAeN;;"}
1
+ {"version":3,"file":"useChatMessages.js","sources":["src/components/editor/ChatPanel/useChatMessages.ts"],"sourcesContent":["'use client';\n\nimport { useState, useCallback } from 'react';\n\nimport { useLatest } from '@/hooks/useLatest';\n\nimport type {\n ChatMessageData,\n UseChatMessagesOptions,\n UseChatMessagesReturn,\n} from './ChatPanel.types';\n\nexport function useChatMessages(\n options: UseChatMessagesOptions = {}\n): UseChatMessagesReturn {\n const { initialMessages = [], maxMessages } = options;\n const [messages, setMessages] = useState<ChatMessageData[]>(initialMessages);\n // Latest messages for synchronous reads in getMessage() without stale closures.\n const messagesRef = useLatest(messages);\n\n const trimToMax = useCallback(\n (msgs: ChatMessageData[]): ChatMessageData[] => {\n if (maxMessages !== undefined && msgs.length > maxMessages) {\n return msgs.slice(msgs.length - maxMessages);\n }\n return msgs;\n },\n [maxMessages]\n );\n\n const appendMessage = useCallback(\n (message: ChatMessageData) => {\n setMessages(prev => trimToMax([...prev, message]));\n },\n [trimToMax]\n );\n\n const updateMessage = useCallback(\n (\n id: string,\n update:\n | Partial<ChatMessageData>\n | ((prev: ChatMessageData) => Partial<ChatMessageData>)\n ) => {\n setMessages(prev =>\n prev.map(msg => {\n if (msg.id !== id) return msg;\n const partial = typeof update === 'function' ? update(msg) : update;\n return { ...msg, ...partial };\n })\n );\n },\n []\n );\n\n const removeMessage = useCallback((id: string) => {\n setMessages(prev => prev.filter(msg => msg.id !== id));\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n }, []);\n\n const getMessage = useCallback(\n (id: string): ChatMessageData | undefined => {\n return messagesRef.current.find(msg => msg.id === id);\n },\n // messagesRef is a stable useLatest ref; listed to satisfy the rule.\n [messagesRef]\n );\n\n return {\n messages,\n setMessages,\n appendMessage,\n updateMessage,\n removeMessage,\n clearMessages,\n getMessage,\n };\n}\n"],"names":[],"mappings":";;;;AAYM;;;;AAMJ;AAEA;;;;AAKI;AACF;AAIF;AAEI;AACF;;;AAaM;AAAmB;AACnB;AACA;;;AAOR;;;AAIA;;;AAIA;AAEI;;;;;;;;;;;;;AAeN;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useChatScroll.js","sources":["../../../../../../src/components/editor/ChatPanel/useChatScroll.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAWM;AAGJ;AAEA;AACA;;;;AAIA;AACA;AACA;;;AAIE;AACF;;AAEE;AACF;AAEA;AACE;AACA;AAAgB;;AAGhB;AACF;;AAGE;AACA;;;;;AAKC;;;;AAKH;AACE;AACA;;AACA;;;AAKE;;;;AAOF;AACA;;;AAGE;;;;;AAKF;AAEA;AACA;AACE;AACF;AACF;;;;AAKE;AACA;;;;;;AAMF;AACE;AACA;AACA;;;;;;AAMA;;;;;;AAKF;;;;AAKE;AACA;AACA;;;AAIA;;;;;AAKI;AACF;;;;;;;;AAOJ;;;;;;;;;;AAWF;;"}
1
+ {"version":3,"file":"useChatScroll.js","sources":["src/components/editor/ChatPanel/useChatScroll.ts"],"sourcesContent":["'use client';\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\n\nimport { useResizeObserver } from '@/hooks/useResizeObserver';\n\nimport type {\n UseChatScrollOptions,\n UseChatScrollReturn,\n} from './ChatPanel.types';\n\nexport function useChatScroll(\n options: UseChatScrollOptions\n): UseChatScrollReturn {\n const { messages, enabled = true, threshold = 100 } = options;\n\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const scrollContentRef = useRef<HTMLDivElement>(null);\n const [isAtBottom, setIsAtBottom] = useState(true);\n const [hasNewMessages, setHasNewMessages] = useState(false);\n const prevMessageCountRef = useRef(messages.length);\n const isAtBottomRef = useRef(isAtBottom);\n const enabledRef = useRef(enabled);\n const lastContentHeightRef = useRef(0);\n\n // Keep refs in sync for use inside observer callbacks.\n useEffect(() => {\n isAtBottomRef.current = isAtBottom;\n }, [isAtBottom]);\n useEffect(() => {\n enabledRef.current = enabled;\n }, [enabled]);\n\n const checkIfAtBottom = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container) return true;\n\n const { scrollTop, scrollHeight, clientHeight } = container;\n return scrollHeight - scrollTop - clientHeight <= threshold;\n }, [threshold]);\n\n const scrollToBottom = useCallback((behavior: ScrollBehavior = 'auto') => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior,\n });\n setIsAtBottom(true);\n setHasNewMessages(false);\n }, []);\n\n const scrollTo = useCallback((opts: ScrollToOptions) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n container.scrollTo(opts);\n }, []);\n\n const scrollToElement = useCallback(\n (el: HTMLElement, opts?: ScrollIntoViewOptions) => {\n el.scrollIntoView(opts);\n },\n []\n );\n\n // Listen for scroll events to track position\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n const atBottom = checkIfAtBottom();\n setIsAtBottom(atBottom);\n if (atBottom) {\n setHasNewMessages(false);\n }\n };\n\n container.addEventListener('scroll', handleScroll, { passive: true });\n return () => {\n container.removeEventListener('scroll', handleScroll);\n };\n }, [checkIfAtBottom]);\n\n // Seed the last-height baseline once the content node mounts so growth is\n // measured against the initial height, not zero.\n useEffect(() => {\n const content = scrollContentRef.current;\n if (!content) return;\n lastContentHeightRef.current = content.getBoundingClientRect().height;\n }, []);\n\n // Observe content growth — keeps the list pinned to the bottom during streaming\n // (when message text grows but `messages.length` stays constant).\n useResizeObserver(scrollContentRef, entry => {\n const nextHeight = entry.contentRect.height;\n const prevHeight = lastContentHeightRef.current;\n lastContentHeightRef.current = nextHeight;\n\n // Only react to growth — shrinks shouldn't force a scroll jump.\n if (nextHeight <= prevHeight) return;\n if (!enabledRef.current) return;\n\n if (isAtBottomRef.current) {\n scrollToBottom('auto');\n } else {\n setHasNewMessages(true);\n }\n });\n\n // Auto-scroll or show indicator on new messages. Fallback for mounts and\n // cleared lists where content height may not grow monotonically.\n useEffect(() => {\n const currentCount = messages.length;\n const prevCount = prevMessageCountRef.current;\n prevMessageCountRef.current = currentCount;\n\n if (currentCount <= prevCount) return;\n\n if (!enabled) return;\n\n if (isAtBottom) {\n // Use requestAnimationFrame for DOM to update first\n requestAnimationFrame(() => {\n scrollToBottom();\n });\n } else {\n // Reacts to an incoming-message event (count grew while scrolled away) —\n // event-driven, not derivable during render.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setHasNewMessages(true);\n }\n }, [messages.length, enabled, isAtBottom, scrollToBottom]);\n\n return {\n scrollContainerRef,\n scrollContentRef,\n isAtBottom,\n hasNewMessages,\n scrollToBottom,\n scrollTo,\n scrollToElement,\n };\n}\n"],"names":[],"mappings":";;;;AAWM;AAGJ;AAEA;AACA;;;;AAIA;AACA;AACA;;;AAIE;AACF;;AAEE;AACF;AAEA;AACE;AACA;AAAgB;;AAGhB;AACF;;AAGE;AACA;;;;;AAKC;;;;AAKH;AACE;AACA;;AACA;;;AAKE;;;;AAOF;AACA;;;AAGE;;;;;AAKF;AAEA;AACA;AACE;AACF;AACF;;;;AAKE;AACA;;;;;;AAMF;AACE;AACA;AACA;;;;;;AAMA;;;;;;AAKF;;;;AAKE;AACA;AACA;;;AAIA;;;;;AAKI;AACF;;;;;;;;AAOJ;;;;;;;;;;AAWF;;"}
@@ -7,7 +7,7 @@ import { useLatest } from '../../../hooks/useLatest/useLatest.js';
7
7
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
8
8
  import { vars } from '../../../theme/contract.css.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":"Minimap.js","sources":["../../../../../../src/components/editor/Minimap/Minimap.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAiDA;AAEA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAYF;;;AAGA;AAEA;AACE;AACE;AACA;AACA;AACA;AACA;AACA;;;;AAKE;AACE;;;;AAIJ;AACA;;;;AAII;AACE;AACF;AACE;;;AAII;;;AAIR;;;AAIF;AAQA;AACE;AAEA;;AAWgC;;AAC3B;;AACA;AACL;AAEI;;;AAMI;AACA;;AAQ2B;;AAC9B;;;;AAGL;AACA;AAEI;;AAEE;;AAEE;;AAER;;AAMJ;AAEA;AACF;AAEA;;;;;AAKG;AACH;AAqBE;;;;;AAKE;AA2BJ;AAEA;;;;;;;;;;;;;;;;AAgBG;AACI;AA0BL;AACA;AAEA;;;AASM;AACA;AACI;AACA;AACA;AACD;;AAMT;;AAGE;AACF;;;;AAKI;AACD;AACH;AAEA;;AAIA;AACE;;;;;;;AAOA;;;;AAID;;AAID;AACA;AACA;AAEA;AACE;AACA;AACE;AACA;;;AAEA;;AAEA;AAEA;AACA;AACA;AACE;AACA;;AAEF;AAEA;AACE;;AAGA;;AAGA;;;;AAMF;;AAEE;;;;;;;AAOD;AACH;AACF;;;;;;;;;;;;AAYC;;AAGC;AACA;AACE;AACF;AACF;;;;;AAKE;;AAIE;AACF;AACA;AACA;AACE;AACF;AACF;;AAIA;;AAcA;AAyBF;AAEA;;"}
1
+ {"version":3,"file":"Minimap.js","sources":["src/components/editor/Minimap/Minimap.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { resolveVarValue } from '@/components/primitives/canvas/canvasTheme';\nimport { useLatest } from '@/hooks';\nimport { vars } from '@/theme/contract.css';\nimport { cx } from '@/utils/cx';\n\nimport {\n minimapShellStyle,\n minimapBodyStyle,\n minimapCanvasStyle,\n minimapOverlayLayerStyle,\n titleOutsideStyle,\n titleInsideStyle,\n footerOutsideStyle,\n footerInsideStyle,\n cornerTopLeftStyle,\n cornerTopRightStyle,\n cornerBottomLeftStyle,\n cornerBottomRightStyle,\n ariaLiveRegionStyle,\n} from './Minimap.css';\nimport { MINIMAP_SLOT } from './Minimap.types';\nimport { MinimapStoreContext, useMinimapDragState } from './MinimapContext';\nimport { computeMinimapHeight } from './minimapCoords';\nimport { drawMinimap } from './minimapDrawing';\nimport { MinimapStore } from './MinimapStore';\nimport { useMinimapGestures } from './useMinimapGestures';\n\nimport type {\n MinimapCornerSide,\n MinimapFooterPlacement,\n MinimapInteractionConfig,\n MinimapProps,\n MinimapSlotKind,\n MinimapSlotMarker,\n MinimapTitlePlacement,\n} from './Minimap.types';\nimport type { MinimapDrawColors } from './minimapDrawing';\n\nconst DEFAULT_OUTSIDE_OVERLAY = 'rgba(0, 0, 0, 0.4)';\n\nconst DEFAULT_INTERACTIONS: Required<MinimapInteractionConfig> = {\n click: true,\n dragViewportRect: true,\n dragFromEmpty: true,\n};\n\nconst DISABLED_INTERACTIONS: Required<MinimapInteractionConfig> = {\n click: false,\n dragViewportRect: false,\n dragFromEmpty: false,\n};\n\ninterface CategorizedSlots {\n titleAbove: React.ReactNode;\n titleInside: React.ReactNode;\n footerBelow: React.ReactNode;\n footerInside: React.ReactNode;\n corners: Partial<Record<MinimapCornerSide, React.ReactNode>>;\n other: React.ReactNode[];\n}\n\nfunction getSlotKind(el: React.ReactElement): MinimapSlotKind | null {\n const marker = (el.type as Partial<MinimapSlotMarker>)[MINIMAP_SLOT];\n return marker ?? null;\n}\n\nfunction categorizeChildren(children: React.ReactNode): CategorizedSlots {\n const slots: CategorizedSlots = {\n titleAbove: null,\n titleInside: null,\n footerBelow: null,\n footerInside: null,\n corners: {},\n other: [],\n };\n\n React.Children.forEach(children, child => {\n if (!React.isValidElement(child)) {\n if (child !== null && child !== undefined && child !== false) {\n slots.other.push(child);\n }\n return;\n }\n const kind = getSlotKind(child);\n if (kind === null) {\n // Dev warning: a child whose displayName looks like a Minimap slot\n // (e.g. wrapped in React.memo) but lost the symbol marker.\n if (process.env['NODE_ENV'] !== 'production') {\n const displayName = (child.type as { displayName?: string } | undefined)\n ?.displayName;\n if (displayName?.startsWith('Minimap.')) {\n console.warn(\n `[Minimap] child \"${displayName}\" looks like a slot subcomponent ` +\n `but is missing the MINIMAP_SLOT symbol marker. It will render ` +\n `as a free-form overlay. If you wrapped a slot subcomponent ` +\n `(e.g. with React.memo), copy the symbol onto the wrapper.`\n );\n }\n }\n slots.other.push(child);\n return;\n }\n\n const props = child.props as {\n children?: React.ReactNode;\n placement?: MinimapTitlePlacement | MinimapFooterPlacement;\n side?: MinimapCornerSide;\n className?: string;\n style?: React.CSSProperties;\n };\n\n if (kind === 'title') {\n const placement: MinimapTitlePlacement =\n props.placement === 'top-inside' ? 'top-inside' : 'top-outside';\n const node = (\n <div\n className={cx(\n placement === 'top-inside' ? titleInsideStyle : titleOutsideStyle,\n props.className\n )}\n style={props.style}\n >\n {props.children}\n </div>\n );\n if (placement === 'top-inside') slots.titleInside = node;\n else slots.titleAbove = node;\n } else if (kind === 'footer') {\n const placement: MinimapFooterPlacement =\n props.placement === 'bottom-inside'\n ? 'bottom-inside'\n : 'bottom-outside';\n const node = (\n <div\n className={cx(\n placement === 'bottom-inside'\n ? footerInsideStyle\n : footerOutsideStyle,\n props.className\n )}\n style={props.style}\n >\n {props.children}\n </div>\n );\n if (placement === 'bottom-inside') slots.footerInside = node;\n else slots.footerBelow = node;\n } else {\n // kind is narrowed to 'corner' here (only remaining slot kind).\n const side: MinimapCornerSide = props.side ?? 'top-right';\n const cornerStyle =\n side === 'top-left'\n ? cornerTopLeftStyle\n : side === 'top-right'\n ? cornerTopRightStyle\n : side === 'bottom-left'\n ? cornerBottomLeftStyle\n : cornerBottomRightStyle;\n slots.corners[side] = (\n <div className={cx(cornerStyle, props.className)} style={props.style}>\n {props.children}\n </div>\n );\n }\n });\n\n return slots;\n}\n\n/**\n * The interactive body that hosts canvas + overlay layer + pointer/keyboard\n * handlers. Subscribes to the drag slice for its `data-dragging` attribute\n * + aria-live announcement so neither lives in React state on the outer\n * shell.\n */\nfunction MinimapBody({\n bodyRef,\n canvasRef,\n width,\n height,\n ariaLabel,\n disabled,\n handlers,\n overlayChildren,\n ariaLiveActive,\n}: {\n bodyRef: React.RefObject<HTMLDivElement | null>;\n canvasRef: React.RefObject<HTMLCanvasElement | null>;\n width: number;\n height: number;\n ariaLabel: string;\n disabled: boolean;\n handlers: ReturnType<typeof useMinimapGestures>['handlers'];\n overlayChildren: React.ReactNode;\n ariaLiveActive: boolean;\n}): React.ReactElement {\n const isDragging = useMinimapDragState();\n return (\n // The minimap body is a labelled landmark region that doubles as an\n // interactive pan/zoom surface (focusable, with pointer + key handlers).\n // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions\n <div\n ref={bodyRef}\n className={minimapBodyStyle}\n data-dragging={isDragging || undefined}\n data-disabled={disabled || undefined}\n role=\"region\"\n aria-label={ariaLabel}\n tabIndex={disabled ? -1 : 0}\n style={{ width, height }}\n onPointerDown={handlers.onPointerDown}\n onPointerMove={handlers.onPointerMove}\n onPointerUp={handlers.onPointerUp}\n onPointerCancel={handlers.onPointerCancel}\n onPointerLeave={handlers.onPointerLeave}\n onKeyDown={handlers.onKeyDown}\n >\n <canvas\n ref={canvasRef}\n className={minimapCanvasStyle}\n style={{ width, height }}\n />\n <div className={minimapOverlayLayerStyle}>{overlayChildren}</div>\n <div className={ariaLiveRegionStyle} aria-live=\"polite\" role=\"status\">\n {ariaLiveActive && isDragging ? 'Panning viewport' : ''}\n </div>\n </div>\n );\n}\n\n/**\n * Compact navigation widget for editor viewports. Renders a miniature of\n * the world content alongside a draggable rectangle that mirrors the main\n * viewport's visible region. Intended to be shared by NodeGraph, Timeline,\n * and any custom 2D editor surface.\n *\n * Designed as a controlled primitive — pass the current `transform` /\n * `viewportSize` from your `<Viewport>` and translate `onNavigate.worldPoint`\n * into a `viewport.centerOn(...)` call.\n *\n * Children may include `<Minimap.Title>`, `<Minimap.Footer>`,\n * `<Minimap.Corner>` slot subcomponents — any other nodes render as a\n * free-form overlay layer above the canvas body. Children can read live\n * state (hover position, hovered item id, transform) via\n * `useMinimapContext()` / `useMinimapHover()` / `useMinimapGeometry()` /\n * `useMinimapDragState()`.\n */\nexport const Minimap = ({\n items,\n worldBounds,\n transform,\n viewportSize,\n onNavigate,\n width = 200,\n minHeight = 60,\n maxHeight = 200,\n interactions = DEFAULT_INTERACTIONS,\n keyboardPanStep = 0.1,\n backgroundColor,\n defaultItemColor,\n viewportRectStroke,\n outsideOverlay = DEFAULT_OUTSIDE_OVERLAY,\n renderOverlay,\n disabled = false,\n ariaLabel = 'Minimap',\n className,\n style,\n testId,\n id,\n children,\n ref,\n ...rest\n}: MinimapProps): React.ReactElement => {\n const bodyRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const height = useMemo(\n () => computeMinimapHeight(width, worldBounds, minHeight, maxHeight),\n [width, worldBounds, minHeight, maxHeight]\n );\n const minimapSize = useMemo(() => ({ width, height }), [width, height]);\n\n const interactionsConfig = useMemo<Required<MinimapInteractionConfig>>(\n () =>\n interactions === false\n ? DISABLED_INTERACTIONS\n : {\n click: interactions.click ?? true,\n dragViewportRect: interactions.dragViewportRect ?? true,\n dragFromEmpty: interactions.dragFromEmpty ?? true,\n },\n [interactions]\n );\n\n // ── Store ──\n\n const store = useMemo(() => new MinimapStore(), []);\n\n useLayoutEffect(() => {\n store.setGeometry({ transform, viewportSize, worldBounds, minimapSize });\n }, [store, transform, viewportSize, worldBounds, minimapSize]);\n\n useLayoutEffect(() => {\n store.configureHandle({\n focus: () => bodyRef.current?.focus(),\n getElement: () => bodyRef.current,\n });\n }, [store]);\n\n useImperativeHandle(ref, () => store.handle, [store]);\n\n // ── Gestures ──\n\n const { handlers } = useMinimapGestures({\n containerRef: bodyRef,\n store,\n worldBounds,\n transform,\n viewportSize,\n minimapSize,\n items,\n interactions: interactionsConfig,\n keyboardPanStep,\n disabled,\n onNavigate,\n });\n\n // ── Draw — useLayoutEffect + scheduleDraw, theme resolved per-frame ──\n\n const renderOverlayRef = useLatest(renderOverlay);\n const itemsRef = useLatest(items);\n const rafRef = useRef<number>(0);\n\n const scheduleDraw = useCallback((): void => {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\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(width * dpr));\n const targetH = Math.max(1, Math.round(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\n const colors: MinimapDrawColors = {\n background:\n backgroundColor ??\n resolveVarValue(canvas, vars.colors.background.secondary),\n defaultItem:\n defaultItemColor ??\n resolveVarValue(canvas, vars.colors.accent.primary),\n viewportRectStroke:\n viewportRectStroke ??\n resolveVarValue(canvas, vars.colors.accent.primary),\n outsideOverlay,\n };\n\n drawMinimap({\n ctx,\n size: { width, height },\n worldBounds,\n transform,\n viewportSize,\n items: itemsRef.current,\n colors,\n renderOverlay: renderOverlayRef.current,\n });\n });\n }, [\n width,\n height,\n worldBounds,\n transform,\n viewportSize,\n backgroundColor,\n defaultItemColor,\n viewportRectStroke,\n outsideOverlay,\n itemsRef,\n renderOverlayRef,\n ]);\n\n useLayoutEffect(() => {\n scheduleDraw();\n return () => {\n cancelAnimationFrame(rafRef.current);\n };\n }, [scheduleDraw]);\n\n // Redraw when DPR changes (e.g. dragging 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 // ── Slots ──\n\n const slots = useMemo(() => categorizeChildren(children), [children]);\n\n const overlayChildren = (\n <>\n {slots.titleInside}\n {slots.footerInside}\n {slots.corners['top-left']}\n {slots.corners['top-right']}\n {slots.corners['bottom-left']}\n {slots.corners['bottom-right']}\n {slots.other}\n </>\n );\n\n return (\n <MinimapStoreContext.Provider value={store}>\n <div\n className={cx(minimapShellStyle, className)}\n data-testid={testId}\n id={id}\n style={style}\n {...rest}\n >\n {slots.titleAbove}\n <MinimapBody\n bodyRef={bodyRef}\n canvasRef={canvasRef}\n width={width}\n height={height}\n ariaLabel={ariaLabel}\n disabled={disabled}\n handlers={handlers}\n overlayChildren={overlayChildren}\n ariaLiveActive={!disabled}\n />\n {slots.footerBelow}\n </div>\n </MinimapStoreContext.Provider>\n );\n};\n\nMinimap.displayName = 'Minimap';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAiDA;AAEA;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAYF;;;AAGA;AAEA;AACE;AACE;AACA;AACA;AACA;AACA;AACA;;;;AAKE;AACE;;;;AAIJ;AACA;;;;AAII;AACE;AACF;AACE;;;AAII;;;AAIR;;;AAIF;AAQA;AACE;AAEA;;AAWgC;;AAC3B;;AACA;AACL;AAEI;;;AAMI;AACA;;AAQ2B;;AAC9B;;;;AAGL;AACA;AAEI;;AAEE;;AAEE;;AAER;;AAMJ;AAEA;AACF;AAEA;;;;;AAKG;AACH;AAqBE;;;;;AAKE;AA2BJ;AAEA;;;;;;;;;;;;;;;;AAgBG;AACI;AA0BL;AACA;AAEA;;;AASM;AACA;AACI;AACA;AACA;AACD;;AAMT;;AAGE;AACF;;;;AAKI;AACD;AACH;AAEA;;AAIA;AACE;;;;;;;AAOA;;;;AAID;;AAID;AACA;AACA;AAEA;AACE;AACA;AACE;AACA;;;AAEA;;AAEA;AAEA;AACA;AACA;AACE;AACA;;AAEF;AAEA;AACE;;AAGA;;AAGA;;;;AAMF;;AAEE;;;;;;;AAOD;AACH;AACF;;;;;;;;;;;;AAYC;;AAGC;AACA;AACE;AACF;AACF;;;;;AAKE;;AAIE;AACF;AACA;AACA;AACE;AACF;AACF;;AAIA;;AAcA;AAyBF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Minimap.types.js","sources":["../../../../../../src/components/editor/Minimap/Minimap.types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAyHA;AAEA;;;;;AAKG;AACI,MAAM,YAAY,GAAkB,MAAM,CAAC,GAAG,CAAC,mBAAmB;;;;"}
1
+ {"version":3,"file":"Minimap.types.js","sources":["src/components/editor/Minimap/Minimap.types.ts"],"sourcesContent":["import type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportTransform,\n ViewportSize,\n WorldRect,\n} from '@/components/primitives/viewport';\nimport type { BaseComponent } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\nimport type React from 'react';\n\n// ─── Drawing info ───\n\n/**\n * Helpers and current state passed to `renderOverlay` and to custom item\n * `draw` callbacks. Exposes the same world ↔ minimap math the built-in\n * shapes use, so consumer drawing stays aligned with everything else.\n */\nexport interface MinimapDrawInfo {\n /** Minimap size in CSS pixels (canvas already DPR-scaled). */\n minimapSize: ViewportSize;\n /** World rectangle this minimap maps from. */\n worldBounds: WorldRect;\n /** Current main-viewport transform (mirrored). */\n transform: ViewportTransform;\n /** Current main-viewport size in CSS pixels (mirrored). */\n viewportSize: ViewportSize;\n /** Uniform world → minimap scale (px per world unit). */\n scale: number;\n /** Letterbox offset applied when minimap aspect ≠ worldBounds aspect. */\n offset: Point2D;\n /** Map a world point to a minimap CSS-pixel point. */\n worldToMinimap: (point: Point2D) => Point2D;\n /** Inverse of `worldToMinimap`. */\n minimapToWorld: (point: Point2D) => Point2D;\n}\n\n// ─── Items ───\n\ninterface MinimapItemBase {\n /** Stable identity. Used for hover hit-testing and future selection support. */\n id: string;\n /** Override draw color for this item. Falls back to `defaultItemColor`. */\n color?: string;\n}\n\nexport interface MinimapRectItem extends MinimapItemBase {\n type: 'rect';\n /** Top-left X in world units. */\n x: number;\n /** Top-left Y in world units. */\n y: number;\n /** Width in world units. */\n width: number;\n /** Height in world units. */\n height: number;\n}\n\nexport interface MinimapCircleItem extends MinimapItemBase {\n type: 'circle';\n /** Center X in world units. */\n cx: number;\n /** Center Y in world units. */\n cy: number;\n /** Radius in world units. */\n r: number;\n}\n\nexport interface MinimapLineItem extends MinimapItemBase {\n type: 'line';\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n /** Stroke width in minimap CSS pixels (does not scale with content). @default 1 */\n lineWidth?: number;\n}\n\n/**\n * Caller-defined item. `draw` is invoked with the minimap canvas context\n * and a `MinimapDrawInfo` object containing world ↔ minimap helpers.\n * `bounds` (world coords) is used for hover hit-testing.\n */\nexport interface MinimapCustomItem extends MinimapItemBase {\n type: 'custom';\n bounds: WorldRect;\n draw: (ctx: CanvasRenderingContext2D, info: MinimapDrawInfo) => void;\n}\n\n/** Discriminated union of all minimap item shapes. */\nexport type MinimapItem =\n | MinimapRectItem\n | MinimapCircleItem\n | MinimapLineItem\n | MinimapCustomItem;\n\n// ─── Interactions ───\n\nexport type MinimapNavigatePhase = 'click' | 'drag-start' | 'drag' | 'drag-end';\n\n/**\n * Info passed to `onNavigate` for every navigation event.\n *\n * `worldPoint` is the world-space point the user wants at the center\n * of the main viewport — call `viewport.centerOn(info.worldPoint)`\n * (or update your transform accordingly) to satisfy the request.\n */\nexport interface MinimapNavigateInfo {\n worldPoint: Point2D;\n phase: MinimapNavigatePhase;\n}\n\n/** Fine-grained gesture toggles. Pass `false` to `interactions` to disable everything. */\nexport interface MinimapInteractionConfig {\n /** Tap outside the viewport rect → `phase: 'click'`. @default true */\n click?: boolean;\n /** Drag the viewport rect itself → `phase: 'drag-*'`. @default true */\n dragViewportRect?: boolean;\n /** Drag starting outside the rect → immediately jumps + pans. @default true */\n dragFromEmpty?: boolean;\n}\n\n// ─── Slot markers ───\n\n/**\n * Symbol attached to `Minimap.Title` / `.Footer` / `.Corner` so the parent\n * `<Minimap>` can identify slot children without relying on `displayName`\n * (which gets clobbered by wrappers like `React.memo`, `React.forwardRef`,\n * or Vanilla Extract recipes).\n */\nexport const MINIMAP_SLOT: unique symbol = Symbol.for('etui.minimap.slot');\n\nexport type MinimapSlotKind = 'title' | 'footer' | 'corner';\n\nexport interface MinimapSlotMarker {\n [MINIMAP_SLOT]: MinimapSlotKind;\n}\n\nexport type MinimapTitlePlacement = 'top-outside' | 'top-inside';\nexport type MinimapFooterPlacement = 'bottom-outside' | 'bottom-inside';\nexport type MinimapCornerSide =\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right';\n\n// ─── Imperative handle ───\n\n/**\n * Imperative handle exposed via `ref` on `<Minimap>` and `<ViewportMinimap>`.\n * Stable for the lifetime of the component.\n */\nexport interface MinimapHandle {\n /** Focus the minimap body so arrow keys start working. */\n focus(): void;\n /** Access the underlying body DOM element (the `role=\"region\"` div). */\n getElement(): HTMLDivElement | null;\n /** Convert a world-space point to minimap CSS-pixel coordinates. */\n worldToMinimap(point: Point2D): Point2D;\n /** Inverse of `worldToMinimap`. */\n minimapToWorld(point: Point2D): Point2D;\n}\n\n// ─── Props ───\n\nexport interface MinimapBaseProps extends Omit<\n BaseComponent,\n 'onChange' | 'ref'\n> {\n /** Items rendered as the content miniature. */\n items: ReadonlyArray<MinimapItem>;\n /**\n * World-space rectangle the minimap maps to. Use the exported\n * `computeBoundsFromItems(items, padding?)` helper if you don't already\n * track one yourself.\n */\n worldBounds: WorldRect;\n /** Current main-viewport transform — drives the viewport rect overlay. */\n transform: ViewportTransform;\n /** Current main-viewport size in CSS pixels — drives the viewport rect overlay. */\n viewportSize: ViewportSize;\n\n /**\n * Called when the user navigates via click, drag, or arrow keys.\n * `info.worldPoint` is the world-space point that should sit at the\n * center of the main viewport — pass it to `viewport.centerOn(...)`.\n */\n onNavigate?: (info: MinimapNavigateInfo) => void;\n\n /**\n * Minimap width in CSS pixels. Height is derived from `worldBounds`\n * aspect ratio and clamped to `[minHeight, maxHeight]`.\n * @default 200\n */\n width?: number;\n /** @default 60 */\n minHeight?: number;\n /** @default 200 */\n maxHeight?: number;\n\n /**\n * Gesture configuration. Pass `false` to disable all interactions.\n * @default { click: true, dragViewportRect: true, dragFromEmpty: true }\n */\n interactions?: MinimapInteractionConfig | false;\n\n /**\n * Keyboard pan step, as a fraction of the current main-viewport's\n * world-space extent per arrow-key press. Shift × 5.\n * @default 0.1\n */\n keyboardPanStep?: number;\n\n /** Override background color. Defaults to theme `--etui-color-bg-secondary`. */\n backgroundColor?: string;\n /** Default item color. Defaults to theme accent. */\n defaultItemColor?: string;\n /** Viewport-rect outline color. Defaults to theme accent. */\n viewportRectStroke?: string;\n /**\n * Dimmed overlay color covering the area outside the viewport rect.\n * @default 'rgba(0, 0, 0, 0.4)'\n */\n outsideOverlay?: string;\n\n /**\n * Custom canvas drawing pass executed after items and before the\n * viewport-rect shroud + outline. Use for backdrops, playheads, grid\n * overlays, selection regions — anything that should sit between items\n * and the viewport-rect chrome.\n */\n renderOverlay?: (\n ctx: CanvasRenderingContext2D,\n info: MinimapDrawInfo\n ) => void;\n\n /** Disable interactions and dim the minimap. @default false */\n disabled?: boolean;\n\n /** @default 'Minimap' */\n ariaLabel?: string;\n\n /**\n * Slot children. Pass `<Minimap.Title>`, `<Minimap.Footer>`,\n * `<Minimap.Corner>` subcomponents for chrome, or arbitrary nodes for\n * absolute overlays inside the canvas body. Children that aren't\n * recognised slot markers render as a free-form overlay layer.\n */\n children?: React.ReactNode;\n\n /** Imperative handle. */\n ref?: React.Ref<MinimapHandle>;\n}\n\nexport type MinimapProps = Prettify<MinimapBaseProps>;\n\n// ─── Subcomponent props ───\n\nexport interface MinimapTitleProps {\n children?: React.ReactNode;\n /** @default 'top-outside' */\n placement?: MinimapTitlePlacement;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport interface MinimapFooterProps {\n children?: React.ReactNode;\n /** @default 'bottom-outside' */\n placement?: MinimapFooterPlacement;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport interface MinimapCornerProps {\n children?: React.ReactNode;\n /** Which corner of the canvas body to anchor in. @default 'top-right' */\n side?: MinimapCornerSide;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// ─── MinimapContext value ───\n\n/**\n * Live state available to children of a `<Minimap>` via `useMinimapContext()`.\n *\n * For perf-conscious consumers, prefer the per-slice hooks\n * (`useMinimapHover`, `useMinimapGeometry`, `useMinimapDragState`) — each\n * subscribes to a single slice and re-renders only when that slice\n * changes. `useMinimapContext()` re-renders on every store mutation.\n */\nexport interface MinimapContextValue {\n worldBounds: WorldRect;\n minimapSize: ViewportSize;\n transform: ViewportTransform;\n viewportSize: ViewportSize;\n /** Current pointer position in world coordinates, or null when not hovering. */\n hoverWorldPoint: Point2D | null;\n /** Id of the item currently under the pointer (hit-test), or null. */\n hoveredItemId: string | null;\n /** True during an active drag (rect or pan). */\n isDragging: boolean;\n /** Uniform world → minimap scale. */\n scale: number;\n /** Letterbox offset. */\n offset: Point2D;\n /** Same helpers exposed in `MinimapDrawInfo`, for symmetry. */\n worldToMinimap: (point: Point2D) => Point2D;\n minimapToWorld: (point: Point2D) => Point2D;\n}\n"],"names":[],"mappings":"AAyHA;AAEA;;;;;AAKG;AACI,MAAM,YAAY,GAAkB,MAAM,CAAC,GAAG,CAAC,mBAAmB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapContext.js","sources":["../../../../../../src/components/editor/Minimap/MinimapContext.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAaA;AACE;;AAEE;;AAIF;AACF;AAEA;;;;;AAKG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;;"}
1
+ {"version":3,"file":"MinimapContext.js","sources":["src/components/editor/Minimap/MinimapContext.ts"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useSyncExternalStore } from 'react';\n\nimport type { MinimapContextValue } from './Minimap.types';\nimport type {\n MinimapGeometryState,\n MinimapHoverState,\n MinimapStore,\n} from './MinimapStore';\n\nexport const MinimapStoreContext = createContext<MinimapStore | null>(null);\n\nfunction useMinimapStoreInternal(): MinimapStore {\n const store = useContext(MinimapStoreContext);\n if (!store) {\n throw new Error(\n 'useMinimap* hooks must be called inside a <Minimap> component'\n );\n }\n return store;\n}\n\n/**\n * Subscribe to **all** Minimap state. Convenient catch-all but re-renders\n * on every store mutation. For perf-sensitive consumers, prefer the\n * slice-specific hooks (`useMinimapHover`, `useMinimapGeometry`,\n * `useMinimapDragState`).\n */\nexport function useMinimapContext(): MinimapContextValue {\n const store = useMinimapStoreInternal();\n return useSyncExternalStore(store.subscribe, store.getSnapshot);\n}\n\n/**\n * Subscribe to the hover slice. Re-renders only when the pointer position\n * or hovered item id changes.\n */\nexport function useMinimapHover(): MinimapHoverState {\n const store = useMinimapStoreInternal();\n return useSyncExternalStore(store.subscribeHover, store.getHover);\n}\n\n/**\n * Subscribe to the geometry slice (transform / sizes / bounds). Re-renders\n * only on geometry mutations.\n */\nexport function useMinimapGeometry(): MinimapGeometryState {\n const store = useMinimapStoreInternal();\n return useSyncExternalStore(store.subscribeGeometry, store.getGeometry);\n}\n\n/**\n * Subscribe to the drag slice — `true` while a pan/rect-drag gesture is\n * in flight. Re-renders only on drag-state transitions.\n */\nexport function useMinimapDragState(): boolean {\n const store = useMinimapStoreInternal();\n return useSyncExternalStore(store.subscribeDrag, store.getIsDragging);\n}\n"],"names":[],"mappings":";;;;AAaA;AACE;;AAEE;;AAIF;AACF;AAEA;;;;;AAKG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapCorner.js","sources":["../../../../../../src/components/editor/Minimap/MinimapCorner.tsx"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,iBAAiB,GAAwC,MAAM,IAAI;MAE5D,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE;AAC5D,IAAA,WAAW,EAAE,gBAAgB;IAC7B,CAAC,YAAY,GAAG,QAAiB;AAClC,CAAA;;;;"}
1
+ {"version":3,"file":"MinimapCorner.js","sources":["src/components/editor/Minimap/MinimapCorner.tsx"],"sourcesContent":["import { MINIMAP_SLOT } from './Minimap.types';\n\nimport type { MinimapCornerProps } from './Minimap.types';\n\n/**\n * Small chrome block anchored in one of the four corners of the Minimap\n * canvas body. Typical use cases: coordinate readouts, zoom-level chips,\n * status badges. Picked out of `<Minimap>` children by the `MINIMAP_SLOT`\n * symbol — does not render itself in place.\n */\nconst MinimapCornerImpl: (props: MinimapCornerProps) => null = () => null;\n\nexport const MinimapCorner = Object.assign(MinimapCornerImpl, {\n displayName: 'Minimap.Corner',\n [MINIMAP_SLOT]: 'corner' as const,\n});\n"],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,iBAAiB,GAAwC,MAAM,IAAI;MAE5D,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE;AAC5D,IAAA,WAAW,EAAE,gBAAgB;IAC7B,CAAC,YAAY,GAAG,QAAiB;AAClC,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapFooter.js","sources":["../../../../../../src/components/editor/Minimap/MinimapFooter.tsx"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,iBAAiB,GAAwC,MAAM,IAAI;MAE5D,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE;AAC5D,IAAA,WAAW,EAAE,gBAAgB;IAC7B,CAAC,YAAY,GAAG,QAAiB;AAClC,CAAA;;;;"}
1
+ {"version":3,"file":"MinimapFooter.js","sources":["src/components/editor/Minimap/MinimapFooter.tsx"],"sourcesContent":["import { MINIMAP_SLOT } from './Minimap.types';\n\nimport type { MinimapFooterProps } from './Minimap.types';\n\n/**\n * Footer strip rendered below (or inside the bottom of) the Minimap\n * canvas body. Picked out of `<Minimap>` children by the `MINIMAP_SLOT`\n * symbol — does not render itself in place, so its tree position has no\n * effect on its placement.\n */\nconst MinimapFooterImpl: (props: MinimapFooterProps) => null = () => null;\n\nexport const MinimapFooter = Object.assign(MinimapFooterImpl, {\n displayName: 'Minimap.Footer',\n [MINIMAP_SLOT]: 'footer' as const,\n});\n"],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,iBAAiB,GAAwC,MAAM,IAAI;MAE5D,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE;AAC5D,IAAA,WAAW,EAAE,gBAAgB;IAC7B,CAAC,YAAY,GAAG,QAAiB;AAClC,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapStore.js","sources":["../../../../../../src/components/editor/Minimap/MinimapStore.ts"],"sourcesContent":[null],"names":["worldToMinimapFn","minimapToWorldFn"],"mappings":"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"}
1
+ {"version":3,"file":"MinimapStore.js","sources":["src/components/editor/Minimap/MinimapStore.ts"],"sourcesContent":["import {\n computeMinimapOffset,\n computeMinimapScale,\n minimapToWorld as minimapToWorldFn,\n worldToMinimap as worldToMinimapFn,\n} from './minimapCoords';\n\nimport type { MinimapContextValue, MinimapHandle } from './Minimap.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportSize,\n ViewportTransform,\n WorldRect,\n} from '@/components/primitives/viewport';\n\nconst IDENTITY_TRANSFORM: ViewportTransform = { x: 0, y: 0, zoom: 1 };\nconst ZERO_SIZE: ViewportSize = { width: 0, height: 0 };\nconst ZERO_RECT: WorldRect = { x: 0, y: 0, width: 0, height: 0 };\n\n/** Snapshot of the geometry slice — the data needed to position anything. */\nexport interface MinimapGeometryState {\n transform: ViewportTransform;\n viewportSize: ViewportSize;\n worldBounds: WorldRect;\n minimapSize: ViewportSize;\n}\n\n/** Snapshot of the hover slice. */\nexport interface MinimapHoverState {\n hoverWorldPoint: Point2D | null;\n hoveredItemId: string | null;\n}\n\n/**\n * Single source of truth for Minimap runtime state — geometry, hover,\n * drag. Designed for React's `useSyncExternalStore`: each slice has its\n * own subscribe/get pair so subscribers re-render only when their slice\n * changes (not on every store mutation).\n *\n * Wzorowane 1:1 na `primitives/viewport/ViewportStore.ts`.\n */\nexport class MinimapStore {\n private geometry: MinimapGeometryState = {\n transform: IDENTITY_TRANSFORM,\n viewportSize: ZERO_SIZE,\n worldBounds: ZERO_RECT,\n minimapSize: ZERO_SIZE,\n };\n private hover: MinimapHoverState = {\n hoverWorldPoint: null,\n hoveredItemId: null,\n };\n private isDragging = false;\n private snapshot: MinimapContextValue = this.computeSnapshot();\n\n private allListeners = new Set<() => void>();\n private geometryListeners = new Set<() => void>();\n private hoverListeners = new Set<() => void>();\n private dragListeners = new Set<() => void>();\n\n // ── Public read API (arrow functions so they can be passed as callbacks) ──\n\n getSnapshot = (): MinimapContextValue => this.snapshot;\n getGeometry = (): MinimapGeometryState => this.geometry;\n getHover = (): MinimapHoverState => this.hover;\n getIsDragging = (): boolean => this.isDragging;\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 subscribeGeometry = (cb: () => void): (() => void) => {\n this.geometryListeners.add(cb);\n return () => {\n this.geometryListeners.delete(cb);\n };\n };\n\n subscribeHover = (cb: () => void): (() => void) => {\n this.hoverListeners.add(cb);\n return () => {\n this.hoverListeners.delete(cb);\n };\n };\n\n subscribeDrag = (cb: () => void): (() => void) => {\n this.dragListeners.add(cb);\n return () => {\n this.dragListeners.delete(cb);\n };\n };\n\n // ── Mutators ──\n\n setGeometry(partial: Partial<MinimapGeometryState>): void {\n const next: MinimapGeometryState = {\n transform: partial.transform ?? this.geometry.transform,\n viewportSize: partial.viewportSize ?? this.geometry.viewportSize,\n worldBounds: partial.worldBounds ?? this.geometry.worldBounds,\n minimapSize: partial.minimapSize ?? this.geometry.minimapSize,\n };\n if (\n next.transform === this.geometry.transform &&\n sizeEqual(next.viewportSize, this.geometry.viewportSize) &&\n rectEqual(next.worldBounds, this.geometry.worldBounds) &&\n sizeEqual(next.minimapSize, this.geometry.minimapSize)\n ) {\n return;\n }\n this.geometry = next;\n this.snapshot = this.computeSnapshot();\n this.geometryListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n setHover(next: MinimapHoverState): void {\n if (\n hoverPointEqual(next.hoverWorldPoint, this.hover.hoverWorldPoint) &&\n next.hoveredItemId === this.hover.hoveredItemId\n ) {\n return;\n }\n this.hover = next;\n this.snapshot = this.computeSnapshot();\n this.hoverListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n setIsDragging(next: boolean): void {\n if (next === this.isDragging) return;\n this.isDragging = next;\n this.snapshot = this.computeSnapshot();\n this.dragListeners.forEach(cb => {\n cb();\n });\n this.allListeners.forEach(cb => {\n cb();\n });\n }\n\n // ── Imperative handle ──\n\n /**\n * Stable handle whose methods proxy to the current store state. The\n * handle reference is stable for the lifetime of the store.\n */\n readonly handle: MinimapHandle = {\n focus: (): void => {\n this.focusElement?.();\n },\n getElement: (): HTMLDivElement | null => this.elementGetter?.() ?? null,\n worldToMinimap: (p: Point2D): Point2D =>\n worldToMinimapFn(p, this.geometry.worldBounds, this.geometry.minimapSize),\n minimapToWorld: (p: Point2D): Point2D =>\n minimapToWorldFn(p, this.geometry.worldBounds, this.geometry.minimapSize),\n };\n\n /** Wired up by `Minimap.tsx` so the handle knows which element to act on. */\n configureHandle(config: {\n focus: () => void;\n getElement: () => HTMLDivElement | null;\n }): void {\n this.focusElement = config.focus;\n this.elementGetter = config.getElement;\n }\n\n private focusElement: (() => void) | null = null;\n private elementGetter: (() => HTMLDivElement | null) | null = null;\n\n private computeSnapshot(): MinimapContextValue {\n const { worldBounds, minimapSize, transform, viewportSize } = this.geometry;\n const scale = computeMinimapScale(worldBounds, minimapSize);\n const offset = computeMinimapOffset(worldBounds, minimapSize, scale);\n return {\n worldBounds,\n minimapSize,\n transform,\n viewportSize,\n hoverWorldPoint: this.hover.hoverWorldPoint,\n hoveredItemId: this.hover.hoveredItemId,\n isDragging: this.isDragging,\n scale,\n offset,\n worldToMinimap: (p: Point2D): Point2D =>\n worldToMinimapFn(p, worldBounds, minimapSize),\n minimapToWorld: (p: Point2D): Point2D =>\n minimapToWorldFn(p, worldBounds, minimapSize),\n };\n }\n}\n\nfunction sizeEqual(a: ViewportSize, b: ViewportSize): boolean {\n return a.width === b.width && a.height === b.height;\n}\n\nfunction rectEqual(a: WorldRect, b: WorldRect): boolean {\n return (\n a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height\n );\n}\n\nfunction hoverPointEqual(a: Point2D | null, b: Point2D | null): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n return a.x === b.x && a.y === b.y;\n}\n"],"names":["worldToMinimapFn","minimapToWorldFn"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapTitle.js","sources":["../../../../../../src/components/editor/Minimap/MinimapTitle.tsx"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,gBAAgB,GAAuC,MAAM,IAAI;MAE1D,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC1D,IAAA,WAAW,EAAE,eAAe;IAC5B,CAAC,YAAY,GAAG,OAAgB;AACjC,CAAA;;;;"}
1
+ {"version":3,"file":"MinimapTitle.js","sources":["src/components/editor/Minimap/MinimapTitle.tsx"],"sourcesContent":["import { MINIMAP_SLOT } from './Minimap.types';\n\nimport type { MinimapTitleProps } from './Minimap.types';\n\n/**\n * Title strip rendered above (or inside the top of) the Minimap canvas\n * body. Picked out of `<Minimap>` children by the `MINIMAP_SLOT` symbol —\n * does not render itself in place, so its tree position has no effect on\n * its placement.\n */\nconst MinimapTitleImpl: (props: MinimapTitleProps) => null = () => null;\n\nexport const MinimapTitle = Object.assign(MinimapTitleImpl, {\n displayName: 'Minimap.Title',\n [MINIMAP_SLOT]: 'title' as const,\n});\n"],"names":[],"mappings":";;AAIA;;;;;AAKG;AACH,MAAM,gBAAgB,GAAuC,MAAM,IAAI;MAE1D,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC1D,IAAA,WAAW,EAAE,eAAe;IAC5B,CAAC,YAAY,GAAG,OAAgB;AACjC,CAAA;;;;"}
@@ -11,7 +11,7 @@ import { useLatest } from '../../../hooks/useLatest/useLatest.js';
11
11
  import { useResizeObserver } from '../../../hooks/useResizeObserver/useResizeObserver.js';
12
12
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
13
13
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
14
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
14
+ import '@vanilla-extract/css';
15
15
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
16
16
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
17
17
  import '../../../hooks/useNavigationHistory/useNavigationHistory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"ViewportMinimap.js","sources":["../../../../../../src/components/editor/Minimap/ViewportMinimap.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAyDA;AAIE;AACE;;AAEF;AACE;AACA;;AAEF;AAAiC;;AAC5B;AACL;AAAgC;;AAC3B;AACL;AACF;AAEA;;;;;;;;;AASG;AACI;;AAUL;;AAGA;AAGI;AACF;;;AAUA;;AAGF;AACA;AAEI;AACA;AACF;AAIF;AAYF;AAEA;;"}
1
+ {"version":3,"file":"ViewportMinimap.js","sources":["src/components/editor/Minimap/ViewportMinimap.tsx"],"sourcesContent":["'use client';\n\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { useViewportContext } from '@/components/primitives/viewport';\nimport { useLatest, useResizeObserver } from '@/hooks';\n\nimport { Minimap } from './Minimap';\n\nimport type {\n MinimapHandle,\n MinimapNavigateInfo,\n MinimapProps,\n} from './Minimap.types';\n\nexport type ViewportMinimapPlacement =\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right'\n | {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n width?: number | string;\n height?: number | string;\n };\n\nexport interface ViewportMinimapProps extends Omit<\n MinimapProps,\n 'transform' | 'viewportSize' | 'ref'\n> {\n /**\n * Anchored position inside the parent `<Viewport>`. Use a preset for\n * the four corners, or an object for custom anchoring.\n * @default 'bottom-right'\n */\n placement?: ViewportMinimapPlacement;\n /**\n * Distance (CSS px) from the viewport edge when using a preset placement.\n * Ignored when `placement` is an object.\n * @default 12\n */\n margin?: number;\n /**\n * When true, the minimap width tracks the wrapper's measured width via\n * ResizeObserver. The wrapper size must be controlled externally (e.g.\n * via custom `placement` or a parent container). The `width` prop, if\n * provided, becomes a fallback used until the first measurement lands.\n * @default false\n */\n responsive?: boolean;\n /** Imperative handle (same shape as `<Minimap>`'s). */\n ref?: React.Ref<MinimapHandle>;\n}\n\nfunction placementToStyle(\n placement: ViewportMinimapPlacement,\n margin: number\n): React.CSSProperties {\n if (typeof placement === 'object') {\n return { position: 'absolute', pointerEvents: 'auto', ...placement };\n }\n const style: React.CSSProperties = {\n position: 'absolute',\n pointerEvents: 'auto',\n };\n if (placement.startsWith('top')) style.top = margin;\n else style.bottom = margin;\n if (placement.endsWith('left')) style.left = margin;\n else style.right = margin;\n return style;\n}\n\n/**\n * Auto-bound minimap for use inside a `<Viewport>`. Reads live `transform`\n * and `size` from `useViewportContext()`, positions itself in a corner\n * (or custom anchor), and wires `onNavigate` to the viewport handle's\n * `centerOn`. Falls back to the manual `<Minimap>` if you need the\n * minimap outside the Viewport tree.\n *\n * Recognized by `<Viewport>` as an overlay child — drop it among layers\n * and world/overlay siblings without an explicit `<ViewportOverlay>` wrapper.\n */\nexport const ViewportMinimap = ({\n placement = 'bottom-right',\n margin = 12,\n responsive = false,\n width: widthProp,\n onNavigate: userOnNavigate,\n ref,\n ...minimapProps\n}: ViewportMinimapProps): React.ReactElement => {\n const { transform, size, handle } = useViewportContext();\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [measuredWidth, setMeasuredWidth] = useState<number | null>(null);\n\n useResizeObserver(\n wrapperRef,\n entry => {\n setMeasuredWidth(entry.contentRect.width);\n },\n { enabled: responsive }\n );\n\n const wrapperStyle = useMemo(\n () => placementToStyle(placement, margin),\n [placement, margin]\n );\n\n const effectiveWidth = responsive\n ? (measuredWidth ?? widthProp ?? 200)\n : widthProp;\n\n const userOnNavigateRef = useLatest(userOnNavigate);\n const handleNavigate = useCallback(\n (info: MinimapNavigateInfo): void => {\n handle.centerOn(info.worldPoint);\n userOnNavigateRef.current?.(info);\n },\n [handle, userOnNavigateRef]\n );\n\n return (\n <div ref={wrapperRef} style={wrapperStyle}>\n <Minimap\n {...minimapProps}\n ref={ref}\n transform={transform}\n viewportSize={size}\n width={effectiveWidth}\n onNavigate={handleNavigate}\n />\n </div>\n );\n};\n\nViewportMinimap.displayName = 'ViewportMinimap';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAyDA;AAIE;AACE;;AAEF;AACE;AACA;;AAEF;AAAiC;;AAC5B;AACL;AAAgC;;AAC3B;AACL;AACF;AAEA;;;;;;;;;AASG;AACI;;AAUL;;AAGA;AAGI;AACF;;;AAUA;;AAGF;AACA;AAEI;AACA;AACF;AAIF;AAYF;AAEA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"computeBoundsFromItems.js","sources":["../../../../../../src/components/editor/Minimap/computeBoundsFromItems.ts"],"sourcesContent":[null],"names":[],"mappings":"AAGA;;;;;;AAMG;SACa,sBAAsB,CACpC,KAAiC,EACjC,UAAkB,CAAC,EAAA;AAEnB,IAAA,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AACtB,QAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;IAC5C;IAEA,IAAI,IAAI,GAAG,QAAQ;IACnB,IAAI,IAAI,GAAG,QAAQ;AACnB,IAAA,IAAI,IAAI,GAAG,CAAC,QAAQ;AACpB,IAAA,IAAI,IAAI,GAAG,CAAC,QAAQ;AAEpB,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,QAAQ,IAAI,CAAC,IAAI;AACf,YAAA,KAAK,MAAM;AACT,gBAAA,CAAC,GAAG,IAAI,CAAC,CAAC;AACV,gBAAA,CAAC,GAAG,IAAI,CAAC,CAAC;gBACV,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK;gBACvB,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM;gBACxB;AACF,YAAA,KAAK,QAAQ;gBACX,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB;AACF,YAAA,KAAK,MAAM;AACT,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC9B;AACF,YAAA,KAAK,QAAQ;AACX,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;AACrC,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM;gBACtC;;QAEJ,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;IACxB;IAEA,OAAO;QACL,CAAC,EAAE,IAAI,GAAG,OAAO;QACjB,CAAC,EAAE,IAAI,GAAG,OAAO;AACjB,QAAA,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO;AAChC,QAAA,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO;KAClC;AACH;;;;"}
1
+ {"version":3,"file":"computeBoundsFromItems.js","sources":["src/components/editor/Minimap/computeBoundsFromItems.ts"],"sourcesContent":["import type { MinimapItem } from './Minimap.types';\nimport type { WorldRect } from '@/components/primitives/viewport';\n\n/**\n * Compute the tight axis-aligned bounding box of a set of minimap items,\n * with optional uniform padding (in world units) on every side.\n *\n * An empty input returns a zero-area rect at the origin so the minimap\n * can still render a meaningful surface.\n */\nexport function computeBoundsFromItems(\n items: ReadonlyArray<MinimapItem>,\n padding: number = 0\n): WorldRect {\n if (items.length === 0) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const item of items) {\n let l = 0;\n let t = 0;\n let r = 0;\n let b = 0;\n switch (item.type) {\n case 'rect':\n l = item.x;\n t = item.y;\n r = item.x + item.width;\n b = item.y + item.height;\n break;\n case 'circle':\n l = item.cx - item.r;\n t = item.cy - item.r;\n r = item.cx + item.r;\n b = item.cy + item.r;\n break;\n case 'line':\n l = Math.min(item.x1, item.x2);\n t = Math.min(item.y1, item.y2);\n r = Math.max(item.x1, item.x2);\n b = Math.max(item.y1, item.y2);\n break;\n case 'custom':\n l = item.bounds.x;\n t = item.bounds.y;\n r = item.bounds.x + item.bounds.width;\n b = item.bounds.y + item.bounds.height;\n break;\n }\n if (l < minX) minX = l;\n if (t < minY) minY = t;\n if (r > maxX) maxX = r;\n if (b > maxY) maxY = b;\n }\n\n return {\n x: minX - padding,\n y: minY - padding,\n width: maxX - minX + 2 * padding,\n height: maxY - minY + 2 * padding,\n };\n}\n"],"names":[],"mappings":"AAGA;;;;;;AAMG;SACa,sBAAsB,CACpC,KAAiC,EACjC,UAAkB,CAAC,EAAA;AAEnB,IAAA,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AACtB,QAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;IAC5C;IAEA,IAAI,IAAI,GAAG,QAAQ;IACnB,IAAI,IAAI,GAAG,QAAQ;AACnB,IAAA,IAAI,IAAI,GAAG,CAAC,QAAQ;AACpB,IAAA,IAAI,IAAI,GAAG,CAAC,QAAQ;AAEpB,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;QACT,IAAI,CAAC,GAAG,CAAC;AACT,QAAA,QAAQ,IAAI,CAAC,IAAI;AACf,YAAA,KAAK,MAAM;AACT,gBAAA,CAAC,GAAG,IAAI,CAAC,CAAC;AACV,gBAAA,CAAC,GAAG,IAAI,CAAC,CAAC;gBACV,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK;gBACvB,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM;gBACxB;AACF,YAAA,KAAK,QAAQ;gBACX,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACpB;AACF,YAAA,KAAK,MAAM;AACT,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9B,gBAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC9B;AACF,YAAA,KAAK,QAAQ;AACX,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;AACrC,gBAAA,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM;gBACtC;;QAEJ,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC;IACxB;IAEA,OAAO;QACL,CAAC,EAAE,IAAI,GAAG,OAAO;QACjB,CAAC,EAAE,IAAI,GAAG,OAAO;AACjB,QAAA,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO;AAChC,QAAA,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO;KAClC;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../../src/components/editor/Minimap/index.ts"],"sourcesContent":[null],"names":["MinimapBase"],"mappings":";;;;;;;AAWA,MAAM,gBAAgB,GAAGA,SAA8B;AACvD,gBAAgB,CAAC,KAAK,GAAG,YAAY;AACrC,gBAAgB,CAAC,MAAM,GAAG,aAAa;AACvC,gBAAgB,CAAC,MAAM,GAAG,aAAa;AAEhC,MAAM,OAAO,GAAG;;;;"}
1
+ {"version":3,"file":"index.js","sources":["src/components/editor/Minimap/index.ts"],"sourcesContent":["import { Minimap as MinimapBase } from './Minimap';\nimport { MinimapCorner } from './MinimapCorner';\nimport { MinimapFooter } from './MinimapFooter';\nimport { MinimapTitle } from './MinimapTitle';\n\ntype MinimapCompound = typeof MinimapBase & {\n Title: typeof MinimapTitle;\n Footer: typeof MinimapFooter;\n Corner: typeof MinimapCorner;\n};\n\nconst MinimapWithSlots = MinimapBase as MinimapCompound;\nMinimapWithSlots.Title = MinimapTitle;\nMinimapWithSlots.Footer = MinimapFooter;\nMinimapWithSlots.Corner = MinimapCorner;\n\nexport const Minimap = MinimapWithSlots;\nexport { MinimapTitle, MinimapFooter, MinimapCorner };\nexport { ViewportMinimap } from './ViewportMinimap';\nexport { computeBoundsFromItems } from './computeBoundsFromItems';\nexport {\n useMinimapContext,\n useMinimapHover,\n useMinimapGeometry,\n useMinimapDragState,\n} from './MinimapContext';\nexport { MINIMAP_SLOT } from './Minimap.types';\n\nexport type {\n MinimapProps,\n MinimapItem,\n MinimapRectItem,\n MinimapCircleItem,\n MinimapLineItem,\n MinimapCustomItem,\n MinimapNavigateInfo,\n MinimapNavigatePhase,\n MinimapInteractionConfig,\n MinimapDrawInfo,\n MinimapContextValue,\n MinimapHandle,\n MinimapSlotKind,\n MinimapSlotMarker,\n MinimapTitleProps,\n MinimapFooterProps,\n MinimapCornerProps,\n MinimapTitlePlacement,\n MinimapFooterPlacement,\n MinimapCornerSide,\n} from './Minimap.types';\nexport type { MinimapGeometryState, MinimapHoverState } from './MinimapStore';\nexport type {\n ViewportMinimapProps,\n ViewportMinimapPlacement,\n} from './ViewportMinimap';\n"],"names":["MinimapBase"],"mappings":";;;;;;;AAWA,MAAM,gBAAgB,GAAGA,SAA8B;AACvD,gBAAgB,CAAC,KAAK,GAAG,YAAY;AACrC,gBAAgB,CAAC,MAAM,GAAG,aAAa;AACvC,gBAAgB,CAAC,MAAM,GAAG,aAAa;AAEhC,MAAM,OAAO,GAAG;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"minimapCoords.js","sources":["../../../../../../src/components/editor/Minimap/minimapCoords.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minimapCoords.js","sources":["src/components/editor/Minimap/minimapCoords.ts"],"sourcesContent":["import type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportTransform,\n ViewportSize,\n WorldRect,\n} from '@/components/primitives/viewport';\n\n/** Axis-aligned rectangle in minimap (CSS-pixel) coordinates. */\nexport interface MinimapScreenRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Derive minimap height from a width + `worldBounds` aspect ratio,\n * clamped to `[minHeight, maxHeight]`.\n *\n * When `worldBounds` is zero-area, falls back to `minHeight` (the minimap\n * still renders a usable surface so users see the viewport rect).\n */\nexport function computeMinimapHeight(\n width: number,\n worldBounds: WorldRect,\n minHeight: number,\n maxHeight: number\n): number {\n if (worldBounds.width <= 0 || worldBounds.height <= 0) {\n return minHeight;\n }\n const ratio = worldBounds.height / worldBounds.width;\n const raw = width * ratio;\n return Math.min(maxHeight, Math.max(minHeight, raw));\n}\n\n/**\n * Uniform scale that fits `worldBounds` inside `minimapSize`, preserving\n * the world aspect ratio. If the minimap was clamped (e.g. height hit\n * `maxHeight`), the resulting content is letterboxed.\n */\nexport function computeMinimapScale(\n worldBounds: WorldRect,\n minimapSize: ViewportSize\n): number {\n if (worldBounds.width <= 0 || worldBounds.height <= 0) {\n return 1;\n }\n return Math.min(\n minimapSize.width / worldBounds.width,\n minimapSize.height / worldBounds.height\n );\n}\n\n/** Letterbox offset (each side) when world and minimap aspect ratios differ. */\nexport function computeMinimapOffset(\n worldBounds: WorldRect,\n minimapSize: ViewportSize,\n scale: number\n): Point2D {\n const usedW = worldBounds.width * scale;\n const usedH = worldBounds.height * scale;\n return {\n x: (minimapSize.width - usedW) / 2,\n y: (minimapSize.height - usedH) / 2,\n };\n}\n\n/** Map a world point to minimap CSS pixel coordinates. */\nexport function worldToMinimap(\n point: Point2D,\n worldBounds: WorldRect,\n minimapSize: ViewportSize\n): Point2D {\n const scale = computeMinimapScale(worldBounds, minimapSize);\n const offset = computeMinimapOffset(worldBounds, minimapSize, scale);\n return {\n x: offset.x + (point.x - worldBounds.x) * scale,\n y: offset.y + (point.y - worldBounds.y) * scale,\n };\n}\n\n/** Inverse of `worldToMinimap`: minimap CSS point → world point. */\nexport function minimapToWorld(\n point: Point2D,\n worldBounds: WorldRect,\n minimapSize: ViewportSize\n): Point2D {\n // Zero-area bounds have no meaningful inverse mapping — collapse everything\n // to the bounds origin so navigation still emits a stable point.\n if (worldBounds.width <= 0 || worldBounds.height <= 0) {\n return { x: worldBounds.x, y: worldBounds.y };\n }\n const scale = computeMinimapScale(worldBounds, minimapSize);\n const offset = computeMinimapOffset(worldBounds, minimapSize, scale);\n return {\n x: worldBounds.x + (point.x - offset.x) / scale,\n y: worldBounds.y + (point.y - offset.y) / scale,\n };\n}\n\n/**\n * Viewport rect (in minimap CSS px) for a given main-viewport transform\n * and size. The world-space region visible in the main viewport is at\n * `(-tx / zoom, -ty / zoom)` with size `viewportSize / zoom`.\n */\nexport function getViewportRectOnMinimap(\n transform: ViewportTransform,\n viewportSize: ViewportSize,\n worldBounds: WorldRect,\n minimapSize: ViewportSize\n): MinimapScreenRect {\n const scale = computeMinimapScale(worldBounds, minimapSize);\n const offset = computeMinimapOffset(worldBounds, minimapSize, scale);\n const zoom = transform.zoom === 0 ? 1 : transform.zoom;\n\n const worldX = -transform.x / zoom;\n const worldY = -transform.y / zoom;\n const worldW = viewportSize.width / zoom;\n const worldH = viewportSize.height / zoom;\n\n return {\n x: offset.x + (worldX - worldBounds.x) * scale,\n y: offset.y + (worldY - worldBounds.y) * scale,\n width: worldW * scale,\n height: worldH * scale,\n };\n}\n\n/** Current world-space center of the main viewport. */\nexport function getViewportCenterWorld(\n transform: ViewportTransform,\n viewportSize: ViewportSize\n): Point2D {\n const zoom = transform.zoom === 0 ? 1 : transform.zoom;\n return {\n x: (-transform.x + viewportSize.width / 2) / zoom,\n y: (-transform.y + viewportSize.height / 2) / zoom,\n };\n}\n\n/**\n * Build the shared coordinate helpers used by built-in drawing,\n * `renderOverlay`, and custom items. `transform`/`viewportSize` are not\n * needed by the helpers themselves but are passed downstream alongside\n * this bundle to form the public `MinimapDrawInfo`.\n */\nexport function buildDrawInfo(\n worldBounds: WorldRect,\n minimapSize: ViewportSize\n): {\n scale: number;\n offset: Point2D;\n worldToMinimap: (point: Point2D) => Point2D;\n minimapToWorld: (point: Point2D) => Point2D;\n} {\n const scale = computeMinimapScale(worldBounds, minimapSize);\n const offset = computeMinimapOffset(worldBounds, minimapSize, scale);\n return {\n scale,\n offset,\n worldToMinimap: (p: Point2D) => worldToMinimap(p, worldBounds, minimapSize),\n minimapToWorld: (p: Point2D) => minimapToWorld(p, worldBounds, minimapSize),\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"minimapDrawing.js","sources":["../../../../../../src/components/editor/Minimap/minimapDrawing.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minimapDrawing.js","sources":["src/components/editor/Minimap/minimapDrawing.ts"],"sourcesContent":["import { buildDrawInfo, getViewportRectOnMinimap } from './minimapCoords';\n\nimport type { MinimapDrawInfo, MinimapItem } from './Minimap.types';\nimport type { MinimapScreenRect } from './minimapCoords';\nimport type {\n ViewportTransform,\n ViewportSize,\n WorldRect,\n} from '@/components/primitives/viewport';\n\nexport interface MinimapDrawColors {\n background: string;\n defaultItem: string;\n viewportRectStroke: string;\n outsideOverlay: string;\n}\n\nexport interface MinimapDrawInput {\n ctx: CanvasRenderingContext2D;\n size: ViewportSize;\n worldBounds: WorldRect;\n transform: ViewportTransform;\n viewportSize: ViewportSize;\n items: ReadonlyArray<MinimapItem>;\n colors: MinimapDrawColors;\n renderOverlay?: (\n ctx: CanvasRenderingContext2D,\n info: MinimapDrawInfo\n ) => void;\n}\n\n/**\n * Render a full minimap frame: background → items → caller `renderOverlay`\n * → dimmed shroud around the viewport rect → viewport rect outline. The\n * caller is responsible for DPR scaling on `ctx` before invoking.\n */\nexport function drawMinimap(input: MinimapDrawInput): void {\n const {\n ctx,\n size,\n worldBounds,\n transform,\n viewportSize,\n items,\n colors,\n renderOverlay,\n } = input;\n\n ctx.clearRect(0, 0, size.width, size.height);\n ctx.fillStyle = colors.background;\n ctx.fillRect(0, 0, size.width, size.height);\n\n const helpers = buildDrawInfo(worldBounds, size);\n const info: MinimapDrawInfo = {\n minimapSize: size,\n worldBounds,\n transform,\n viewportSize,\n ...helpers,\n };\n\n ctx.save();\n ctx.beginPath();\n ctx.rect(0, 0, size.width, size.height);\n ctx.clip();\n\n for (const item of items) {\n const color = item.color ?? colors.defaultItem;\n ctx.fillStyle = color;\n ctx.strokeStyle = color;\n\n switch (item.type) {\n case 'rect': {\n const topLeft = info.worldToMinimap({ x: item.x, y: item.y });\n ctx.fillRect(\n topLeft.x,\n topLeft.y,\n Math.max(1, item.width * info.scale),\n Math.max(1, item.height * info.scale)\n );\n break;\n }\n case 'circle': {\n const center = info.worldToMinimap({ x: item.cx, y: item.cy });\n const r = Math.max(0.5, item.r * info.scale);\n ctx.beginPath();\n ctx.arc(center.x, center.y, r, 0, Math.PI * 2);\n ctx.fill();\n break;\n }\n case 'line': {\n const a = info.worldToMinimap({ x: item.x1, y: item.y1 });\n const b = info.worldToMinimap({ x: item.x2, y: item.y2 });\n ctx.lineWidth = item.lineWidth ?? 1;\n ctx.beginPath();\n ctx.moveTo(a.x, a.y);\n ctx.lineTo(b.x, b.y);\n ctx.stroke();\n break;\n }\n case 'custom': {\n ctx.save();\n item.draw(ctx, info);\n ctx.restore();\n break;\n }\n }\n }\n\n if (renderOverlay) {\n ctx.save();\n renderOverlay(ctx, info);\n ctx.restore();\n }\n\n ctx.restore();\n\n const vr = getViewportRectOnMinimap(\n transform,\n viewportSize,\n worldBounds,\n size\n );\n drawOutsideOverlay(ctx, size, vr, colors.outsideOverlay);\n\n ctx.strokeStyle = colors.viewportRectStroke;\n ctx.lineWidth = 1;\n const strokeW = Math.max(0, vr.width - 1);\n const strokeH = Math.max(0, vr.height - 1);\n ctx.strokeRect(vr.x + 0.5, vr.y + 0.5, strokeW, strokeH);\n}\n\nfunction drawOutsideOverlay(\n ctx: CanvasRenderingContext2D,\n size: ViewportSize,\n rect: MinimapScreenRect,\n color: string\n): void {\n const rl = Math.max(0, Math.min(size.width, rect.x));\n const rt = Math.max(0, Math.min(size.height, rect.y));\n const rr = Math.max(0, Math.min(size.width, rect.x + rect.width));\n const rb = Math.max(0, Math.min(size.height, rect.y + rect.height));\n\n ctx.fillStyle = color;\n if (rt > 0) ctx.fillRect(0, 0, size.width, rt);\n if (rb < size.height) ctx.fillRect(0, rb, size.width, size.height - rb);\n if (rl > 0 && rt < rb) ctx.fillRect(0, rt, rl, rb - rt);\n if (rr < size.width && rt < rb) {\n ctx.fillRect(rr, rt, size.width - rr, rb - rt);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"minimapHitTest.js","sources":["../../../../../../src/components/editor/Minimap/minimapHitTest.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minimapHitTest.js","sources":["src/components/editor/Minimap/minimapHitTest.ts"],"sourcesContent":["import type { MinimapItem } from './Minimap.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type { WorldRect } from '@/components/primitives/viewport';\n\n/** Distance from point P to line segment A-B (in world units). */\nfunction distancePointToSegment(p: Point2D, a: Point2D, b: Point2D): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lenSq = dx * dx + dy * dy;\n if (lenSq === 0) {\n const ex = p.x - a.x;\n const ey = p.y - a.y;\n return Math.hypot(ex, ey);\n }\n let t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n const cx = a.x + t * dx;\n const cy = a.y + t * dy;\n return Math.hypot(p.x - cx, p.y - cy);\n}\n\n/**\n * Hit-test a world point against the item list, returning the topmost\n * (last-drawn) match. `lineToleranceWorld` is the picking radius (world\n * units) used for line items.\n */\nexport function hitTestItems(\n worldPoint: Point2D,\n items: ReadonlyArray<MinimapItem>,\n lineToleranceWorld: number\n): string | null {\n for (let i = items.length - 1; i >= 0; i -= 1) {\n const item = items[i];\n if (!item) continue;\n if (pointHitsItem(worldPoint, item, lineToleranceWorld)) {\n return item.id;\n }\n }\n return null;\n}\n\nfunction pointHitsItem(\n p: Point2D,\n item: MinimapItem,\n lineToleranceWorld: number\n): boolean {\n switch (item.type) {\n case 'rect':\n return (\n p.x >= item.x &&\n p.x <= item.x + item.width &&\n p.y >= item.y &&\n p.y <= item.y + item.height\n );\n case 'circle': {\n const dx = p.x - item.cx;\n const dy = p.y - item.cy;\n return dx * dx + dy * dy <= item.r * item.r;\n }\n case 'line':\n return (\n distancePointToSegment(\n p,\n { x: item.x1, y: item.y1 },\n { x: item.x2, y: item.y2 }\n ) <= lineToleranceWorld\n );\n case 'custom':\n return inWorldRect(p, item.bounds);\n }\n}\n\nfunction inWorldRect(p: Point2D, rect: WorldRect): boolean {\n return (\n p.x >= rect.x &&\n p.x <= rect.x + rect.width &&\n p.y >= rect.y &&\n p.y <= rect.y + rect.height\n );\n}\n"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ import '../../../utils/devWarn.js';
4
4
  import { useLatest } from '../../../hooks/useLatest/useLatest.js';
5
5
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
6
6
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
7
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
7
+ import '@vanilla-extract/css';
8
8
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
9
9
  import 'react/jsx-runtime';
10
10
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
@@ -1 +1 @@
1
- {"version":3,"file":"useMinimapGestures.js","sources":["../../../../../../src/components/editor/Minimap/useMinimapGestures.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;AA2BA;AACA;AACA;AAqCA;AAIE;;AACA;;AAEF;AAEA;AAIE;AAGF;AAEA;;;;;;;;;;AAUG;AACG;AAGJ;;;;;;;;;;;AAaA;AAEA;AAEI;AACF;AAIF;;AAGM;;;AAGF;AACA;AACA;;;;AAMA;AACA;;AAEE;;AAED;;AAKL;;;AAGI;AACA;;;AAGA;AACA;AACA;AACA;AACA;AAEA;;;AASA;AAEA;;;;AAIE;AACE;AACA;;;AAEG;;;;;AAIA;;;;;;;AAOP;;;;AAKE;;;AAIF;;AAEE;;;AAEK;AACL;;;;AAIJ;;;;;;;;;;AAWC;AAGH;AAEI;AACA;;;;;AAKA;AACA;;AAEA;AACA;AACA;;;AAIA;AAEA;AACE;;AACA;AACE;AACA;;;;;;AAKA;;;;AAKJ;;AAEA;;;;;;;AAQA;AACA;AACE;AACE;AACA;AACD;AACD;AACD;AACH;;;;;;;;AASC;AAGH;;AACwB;;AAExB;;AAII;AACA;;AACA;;AAEE;;;AAIA;AACA;;AAEA;AACE;;;AAMK;;;;AAGA;;AAEL;AACA;AACE;AACE;AACA;AACD;AACD;AACD;;;AAIL;AACA;AACF;AAIF;AAEI;AACF;AAIF;AAEI;AACF;AAIF;;;;;AAKI;AACE;;;AAGA;;;AAGA;;;AAGA;;;AAGA;;;;AAKF;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACE;AACE;AACA;AACD;AACD;AACD;AACH;AAIF;AAEI;AACA;AACA;AACA;AACA;AACA;AACD;;;;;;;AAQA;;AAIL;;"}
1
+ {"version":3,"file":"useMinimapGestures.js","sources":["src/components/editor/Minimap/useMinimapGestures.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useRef } from 'react';\n\nimport { useLatest } from '@/hooks';\n\nimport {\n getViewportCenterWorld,\n getViewportRectOnMinimap,\n minimapToWorld,\n} from './minimapCoords';\nimport { hitTestItems } from './minimapHitTest';\n\nimport type {\n MinimapInteractionConfig,\n MinimapItem,\n MinimapNavigateInfo,\n} from './Minimap.types';\nimport type { MinimapStore } from './MinimapStore';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportSize,\n ViewportTransform,\n WorldRect,\n} from '@/components/primitives/viewport';\nimport type React from 'react';\n\nconst CLICK_THRESHOLD_PX = 3;\n/** Hover line-picking tolerance, in minimap CSS px. Translated to world units per gesture. */\nconst LINE_HIT_TOLERANCE_MINIMAP_PX = 4;\n\ninterface UseMinimapGesturesOptions {\n containerRef: React.RefObject<HTMLDivElement | null>;\n store: MinimapStore;\n worldBounds: WorldRect;\n transform: ViewportTransform;\n viewportSize: ViewportSize;\n minimapSize: ViewportSize;\n items: ReadonlyArray<MinimapItem>;\n interactions: Required<MinimapInteractionConfig>;\n keyboardPanStep: number;\n disabled: boolean;\n onNavigate: ((info: MinimapNavigateInfo) => void) | undefined;\n}\n\ntype GestureMode = 'pending-click' | 'drag-rect' | 'drag-pan' | 'cancelled';\n\ninterface PointerState {\n pointerId: number;\n mode: GestureMode;\n startScreen: Point2D;\n /** Drag-rect only: world-space offset from viewport center at drag-start. */\n grabOffsetWorld?: Point2D;\n}\n\ninterface UseMinimapGesturesReturn {\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 onPointerLeave: (e: React.PointerEvent<HTMLDivElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;\n };\n}\n\nfunction getLocalPointerPosition(\n e: React.PointerEvent<HTMLDivElement>,\n container: HTMLDivElement | null\n): Point2D {\n if (!container) return { x: 0, y: 0 };\n const rect = container.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n}\n\nfunction pointInRect(\n p: Point2D,\n r: { x: number; y: number; width: number; height: number }\n): boolean {\n return (\n p.x >= r.x && p.x <= r.x + r.width && p.y >= r.y && p.y <= r.y + r.height\n );\n}\n\n/**\n * Pointer + keyboard gesture machine for `<Minimap>`. All live props and\n * the `onNavigate` callback are read through `useLatest` refs so the\n * returned handlers are stable for the lifetime of the component —\n * pointer event listeners never re-attach on prop changes.\n *\n * Hover state and drag state are written directly to the `MinimapStore`,\n * not local React state, so slice subscribers (`useMinimapHover`,\n * `useMinimapDragState`) re-render independently and don't see the rest\n * of the world thrash.\n */\nexport function useMinimapGestures(\n opts: UseMinimapGesturesOptions\n): UseMinimapGesturesReturn {\n const { containerRef, store } = opts;\n\n // Live refs — handlers always see the latest values without re-binding.\n const worldBoundsRef = useLatest(opts.worldBounds);\n const transformRef = useLatest(opts.transform);\n const viewportSizeRef = useLatest(opts.viewportSize);\n const minimapSizeRef = useLatest(opts.minimapSize);\n const itemsRef = useLatest(opts.items);\n const interactionsRef = useLatest(opts.interactions);\n const keyboardPanStepRef = useLatest(opts.keyboardPanStep);\n const disabledRef = useLatest(opts.disabled);\n const onNavigateRef = useLatest(opts.onNavigate);\n\n const stateRef = useRef<PointerState | null>(null);\n\n const emit = useCallback(\n (info: MinimapNavigateInfo): void => {\n onNavigateRef.current?.(info);\n },\n [onNavigateRef]\n );\n\n const updateHover = useCallback(\n (screen: Point2D | null): void => {\n if (!screen) {\n store.setHover({ hoverWorldPoint: null, hoveredItemId: null });\n return;\n }\n const worldBounds = worldBoundsRef.current;\n const minimapSize = minimapSizeRef.current;\n const items = itemsRef.current;\n const worldPoint = minimapToWorld(screen, worldBounds, minimapSize);\n const scaleX =\n worldBounds.width > 0 ? minimapSize.width / worldBounds.width : 1;\n const scaleY =\n worldBounds.height > 0 ? minimapSize.height / worldBounds.height : 1;\n const scale = Math.min(scaleX, scaleY) || 1;\n const tolerance = LINE_HIT_TOLERANCE_MINIMAP_PX / scale;\n store.setHover({\n hoverWorldPoint: worldPoint,\n hoveredItemId: hitTestItems(worldPoint, items, tolerance),\n });\n },\n [store, worldBoundsRef, minimapSizeRef, itemsRef]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent<HTMLDivElement>): void => {\n if (disabledRef.current || e.button !== 0) return;\n const container = containerRef.current;\n if (!container) return;\n\n const screen = getLocalPointerPosition(e, container);\n const worldBounds = worldBoundsRef.current;\n const minimapSize = minimapSizeRef.current;\n const transform = transformRef.current;\n const viewportSize = viewportSizeRef.current;\n const interactions = interactionsRef.current;\n\n const viewportRect = getViewportRectOnMinimap(\n transform,\n viewportSize,\n worldBounds,\n minimapSize\n );\n const inside = pointInRect(screen, viewportRect);\n\n let mode: GestureMode | null = null;\n let grabOffsetWorld: Point2D | undefined;\n\n if (inside && interactions.dragViewportRect) {\n mode = 'drag-rect';\n const pointerWorld = minimapToWorld(screen, worldBounds, minimapSize);\n const center = getViewportCenterWorld(transform, viewportSize);\n grabOffsetWorld = {\n x: pointerWorld.x - center.x,\n y: pointerWorld.y - center.y,\n };\n } else if (!inside && interactions.click) {\n // Tap-vs-drag is resolved on pointermove / pointerup.\n // dragFromEmpty (if enabled) takes over after the click threshold.\n mode = 'pending-click';\n } else if (!inside && interactions.dragFromEmpty) {\n mode = 'drag-pan';\n } else {\n return;\n }\n\n e.preventDefault();\n container.setPointerCapture(e.pointerId);\n\n stateRef.current = {\n pointerId: e.pointerId,\n mode,\n startScreen: screen,\n grabOffsetWorld,\n };\n\n if (mode === 'drag-pan') {\n const worldPoint = minimapToWorld(screen, worldBounds, minimapSize);\n store.setIsDragging(true);\n emit({ worldPoint, phase: 'drag-start' });\n } else if (mode === 'drag-rect') {\n store.setIsDragging(true);\n const center = getViewportCenterWorld(transform, viewportSize);\n emit({ worldPoint: center, phase: 'drag-start' });\n }\n },\n [\n containerRef,\n disabledRef,\n interactionsRef,\n transformRef,\n viewportSizeRef,\n worldBoundsRef,\n minimapSizeRef,\n store,\n emit,\n ]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>): void => {\n const container = containerRef.current;\n if (!container) return;\n const screen = getLocalPointerPosition(e, container);\n // Always update hover state — independent of gesture capture.\n updateHover(screen);\n\n const state = stateRef.current;\n if (state?.pointerId !== e.pointerId) return;\n\n const worldBounds = worldBoundsRef.current;\n const minimapSize = minimapSizeRef.current;\n const interactions = interactionsRef.current;\n\n const dx = screen.x - state.startScreen.x;\n const dy = screen.y - state.startScreen.y;\n const moved = Math.hypot(dx, dy) >= CLICK_THRESHOLD_PX;\n\n if (state.mode === 'pending-click') {\n if (!moved) return;\n if (interactions.dragFromEmpty) {\n state.mode = 'drag-pan';\n store.setIsDragging(true);\n const worldPoint = minimapToWorld(screen, worldBounds, minimapSize);\n emit({ worldPoint, phase: 'drag-start' });\n } else {\n // Threshold exceeded but drag-from-empty is disabled — cancel the click.\n state.mode = 'cancelled';\n }\n return;\n }\n\n if (state.mode === 'cancelled') return;\n\n if (state.mode === 'drag-pan') {\n const worldPoint = minimapToWorld(screen, worldBounds, minimapSize);\n emit({ worldPoint, phase: 'drag' });\n return;\n }\n\n // Only 'drag-rect' remains after the early returns above.\n const pointerWorld = minimapToWorld(screen, worldBounds, minimapSize);\n const offset = state.grabOffsetWorld ?? { x: 0, y: 0 };\n emit({\n worldPoint: {\n x: pointerWorld.x - offset.x,\n y: pointerWorld.y - offset.y,\n },\n phase: 'drag',\n });\n },\n [\n containerRef,\n worldBoundsRef,\n minimapSizeRef,\n interactionsRef,\n store,\n emit,\n updateHover,\n ]\n );\n\n const handlePointerLeave = useCallback((): void => {\n if (stateRef.current) return; // keep hover during drag (pointer capture)\n updateHover(null);\n }, [updateHover]);\n\n const endGesture = useCallback(\n (e: React.PointerEvent<HTMLDivElement>, cancelled: boolean): void => {\n const state = stateRef.current;\n if (state?.pointerId !== e.pointerId) return;\n const container = containerRef.current;\n if (container?.hasPointerCapture(e.pointerId)) {\n container.releasePointerCapture(e.pointerId);\n }\n\n if (!cancelled) {\n const worldBounds = worldBoundsRef.current;\n const minimapSize = minimapSizeRef.current;\n const screen = getLocalPointerPosition(e, container);\n if (state.mode === 'pending-click') {\n const worldPoint = minimapToWorld(\n state.startScreen,\n worldBounds,\n minimapSize\n );\n emit({ worldPoint, phase: 'click' });\n } else if (state.mode === 'drag-pan') {\n const worldPoint = minimapToWorld(screen, worldBounds, minimapSize);\n emit({ worldPoint, phase: 'drag-end' });\n } else if (state.mode === 'drag-rect') {\n const pointerWorld = minimapToWorld(screen, worldBounds, minimapSize);\n const offset = state.grabOffsetWorld ?? { x: 0, y: 0 };\n emit({\n worldPoint: {\n x: pointerWorld.x - offset.x,\n y: pointerWorld.y - offset.y,\n },\n phase: 'drag-end',\n });\n }\n }\n\n stateRef.current = null;\n store.setIsDragging(false);\n },\n [containerRef, worldBoundsRef, minimapSizeRef, store, emit]\n );\n\n const handlePointerUp = useCallback(\n (e: React.PointerEvent<HTMLDivElement>): void => {\n endGesture(e, false);\n },\n [endGesture]\n );\n\n const handlePointerCancel = useCallback(\n (e: React.PointerEvent<HTMLDivElement>): void => {\n endGesture(e, true);\n },\n [endGesture]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>): void => {\n if (disabledRef.current) return;\n let dx = 0;\n let dy = 0;\n switch (e.key) {\n case 'ArrowLeft':\n dx = -1;\n break;\n case 'ArrowRight':\n dx = 1;\n break;\n case 'ArrowUp':\n dy = -1;\n break;\n case 'ArrowDown':\n dy = 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n\n const transform = transformRef.current;\n const viewportSize = viewportSizeRef.current;\n const keyboardPanStep = keyboardPanStepRef.current;\n\n const zoom = transform.zoom === 0 ? 1 : transform.zoom;\n const worldViewW = viewportSize.width / zoom;\n const worldViewH = viewportSize.height / zoom;\n const stepMul = e.shiftKey ? 5 : 1;\n const stepW = worldViewW * keyboardPanStep * stepMul;\n const stepH = worldViewH * keyboardPanStep * stepMul;\n\n const currentCenter = getViewportCenterWorld(transform, viewportSize);\n emit({\n worldPoint: {\n x: currentCenter.x + dx * stepW,\n y: currentCenter.y + dy * stepH,\n },\n phase: 'click',\n });\n },\n [disabledRef, transformRef, viewportSizeRef, keyboardPanStepRef, emit]\n );\n\n const handlers = useMemo(\n () => ({\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: handlePointerUp,\n onPointerCancel: handlePointerCancel,\n onPointerLeave: handlePointerLeave,\n onKeyDown: handleKeyDown,\n }),\n [\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handlePointerCancel,\n handlePointerLeave,\n handleKeyDown,\n ]\n );\n\n return { handlers };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA2BA;AACA;AACA;AAqCA;AAIE;;AACA;;AAEF;AAEA;AAIE;AAGF;AAEA;;;;;;;;;;AAUG;AACG;AAGJ;;;;;;;;;;;AAaA;AAEA;AAEI;AACF;AAIF;;AAGM;;;AAGF;AACA;AACA;;;;AAMA;AACA;;AAEE;;AAED;;AAKL;;;AAGI;AACA;;;AAGA;AACA;AACA;AACA;AACA;AAEA;;;AASA;AAEA;;;;AAIE;AACE;AACA;;;AAEG;;;;;AAIA;;;;;;;AAOP;;;;AAKE;;;AAIF;;AAEE;;;AAEK;AACL;;;;AAIJ;;;;;;;;;;AAWC;AAGH;AAEI;AACA;;;;;AAKA;AACA;;AAEA;AACA;AACA;;;AAIA;AAEA;AACE;;AACA;AACE;AACA;;;;;;AAKA;;;;AAKJ;;AAEA;;;;;;;AAQA;AACA;AACE;AACE;AACA;AACD;AACD;AACD;AACH;;;;;;;;AASC;AAGH;;AACwB;;AAExB;;AAII;AACA;;AACA;;AAEE;;;AAIA;AACA;;AAEA;AACE;;;AAMK;;;;AAGA;;AAEL;AACA;AACE;AACE;AACA;AACD;AACD;AACD;;;AAIL;AACA;AACF;AAIF;AAEI;AACF;AAIF;AAEI;AACF;AAIF;;;;;AAKI;AACE;;;AAGA;;;AAGA;;;AAGA;;;AAGA;;;;AAKF;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACE;AACE;AACA;AACD;AACD;AACD;AACH;AAIF;AAEI;AACA;AACA;AACA;AACA;AACA;AACD;;;;;;;AAQA;;AAIL;;"}
@@ -11,7 +11,7 @@ import { useControlledState } from '../../../hooks/useControlledState/useControl
11
11
  import { useLatest } from '../../../hooks/useLatest/useLatest.js';
12
12
  import '../../../hooks/useBreakpoint/useBreakpoint.js';
13
13
  import './../../../assets/src/theme/lightTheme.css.ts.vanilla-Ct6f9Iym.css';
14
- import '../../../node_modules/@vanilla-extract/css/dist/vanilla-extract-css.esm.js';
14
+ import '@vanilla-extract/css';
15
15
  import './../../../assets/src/theme/darkTheme.css.ts.vanilla-BHZ3ecRn.css';
16
16
  import './../../../assets/src/theme/globalScrollbars.css.ts.vanilla-BAJwnUEJ.css';
17
17
  import '../../../hooks/useNavigationHistory/useNavigationHistory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"NodeGraph.js","sources":["../../../../../../src/components/editor/NodeGraph/NodeGraph.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsGA;AACA;AACA;AACA;AACE;AACA;AACA;;AAEF;AAEA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACH;;AAyCE;AACA;AACA;;;;AAKA;;;;;AASA;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;;;;;;;;AASE;AACH;;AAGE;AACF;;AAGA;AACA;AACE;;;AAIF;;AAGA;;;;AAMI;AACA;;AACA;AACA;;;;AAQA;AACF;;AAKF;AACA;AACA;AACA;AACA;AACA;;;AAKI;AACA;;;AAGA;AACE;AACA;AAEE;;;;;;AAYJ;;AAQA;;AACA;AACE;;;;;AAKF;AACF;;;;;;;AAQC;;AAIH;AACE;;;;;;AAMA;AACA;AACD;;AAGD;;;;;;AAME;AACA;AACD;;AAGD;;;;;;;;AAYE;AACA;AACA;AACD;;;;;;;;AAUG;;AAEE;AAAuB;;AACU;AACjC;;;;AAKE;;;AAGJ;AACA;AACF;;AAME;;AACA;AAGA;AACF;;AAKF;AACA;;;AAGI;;;;AAII;AACA;AACA;;;AAGC;;AAEF;;;;;AAMH;;;;;;AAOA;;AAGE;;AAQE;;AAEE;AACA;AACA;AACD;;;;;AAML;AACE;AAKA;AAME;;;AAGJ;AACA;AACE;;;;;;;AAOE;AACA;AACA;AACD;AACH;AACF;;;;;;;;AASC;;AAIH;AACA;;;;;;;AAOI;;;;;;;AAOE;;;;AAIA;;;AAGA;;AAEF;;AAEA;;AAEE;AACE;;;;;;;;;;;AASJ;AACE;;;;;;AAMF;;;AAGA;;;AAGF;;;;;;;AAQC;;;;;;;;;AAYA;;;;;;;;;;;;;;AAeH;;;;;AAMI;;AAEA;;;;AAIA;;AAGE;;;AAIF;;;AAKA;;;;;;AASA;;;AAKA;AACF;;;;;;;;;AAUC;;AAIH;;AAEE;AACA;AACA;;;;AAID;;AAGD;AACA;AACA;AACA;AACA;;;AAQI;AACE;AACA;AACA;AACA;AACD;;;AAUD;AACA;AACA;;AAEA;AACF;AAIF;;AAMI;AACA;AACA;AACA;;AAEA;AAYF;;AASE;AACA;;;;AAOI;AAKA;AAAe;AACf;;AAIN;;;;;;AASA;AACE;AACF;AACA;AACE;;;AAGA;AACA;;;AAGA;AACA;;AAEA;;;;;AAKA;;;;AAIA;;;AAGA;;AAEA;;;;AAIA;;AAEF;;AAC8B;AAC9B;AACF;;AAGA;;AAIM;AACA;;AACA;;;;;;AASA;AACA;;AACA;AACA;;AACA;;AAIA;;;;;;AASA;AACA;;;AAEA;;AACA;;;;AAQC;;AAEH;;;AAGA;;;AAGA;AACA;;;AAIA;AACD;;;;AAOH;AAEA;;;;AAmFoB;AAetB;AAyBA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO;;"}
1
+ {"version":3,"file":"NodeGraph.js","sources":["src/components/editor/NodeGraph/NodeGraph.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n useCallback,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useTransition,\n} from 'react';\n\nimport {\n Viewport,\n ViewportLayer,\n ViewportWorld,\n ViewportOverlay,\n screenToWorld as worldFromScreen,\n worldToScreen as screenFromWorld,\n} from '@/components/primitives/viewport';\nimport { useControlledState, useLatest } from '@/hooks';\nimport { cx } from '@/utils/cx';\n\nimport { nodeGraphRootStyle } from './NodeGraph.css';\nimport { NodeGraphStoreContext } from './NodeGraphContext';\nimport {\n buildDrawTheme,\n drawBackground,\n drawConnectionPreview,\n drawEdges,\n drawGroups,\n} from './nodeGraphDrawing';\nimport { EdgeLabelsLayer } from './NodeGraphEdgeLabels';\nimport { NodeGraphGroupView } from './NodeGraphGroup';\nimport {\n computeNodesBounds,\n findEdgeAtPoint,\n getNodeBox,\n isPointInNode,\n isPointInRect,\n rectsIntersect,\n resolvePortRef,\n toggleSelected,\n} from './nodeGraphMath';\nimport { NodeGraphMinimapInner } from './NodeGraphMinimap';\nimport { NodeGraphNodeView } from './NodeGraphNode';\nimport {\n NodeGraphNodeBody,\n NodeGraphNodeHeader,\n NodeGraphPinList,\n NodeGraphPinRow,\n} from './NodeGraphNodeParts';\nimport { NodeGraphNodeSection } from './NodeGraphNodeSection';\nimport { NodeGraphPin } from './NodeGraphPin';\nimport { NodeGraphPort } from './NodeGraphPort';\nimport { NodeGraphPortVisual } from './NodeGraphPortVisual';\nimport {\n NodeGraphBackground,\n NodeGraphMinimap,\n NodeGraphSpawnPalette,\n NodeGraphToolbar,\n} from './NodeGraphSlots';\nimport { NodeGraphSpawnPaletteInner } from './NodeGraphSpawnPalette';\nimport { NodeGraphStore } from './NodeGraphStore';\nimport {\n NodeGraphToolbarInner,\n NodeGraphFitContentButton,\n NodeGraphFitSelectionButton,\n NodeGraphZoomInButton,\n NodeGraphZoomOutButton,\n NodeGraphResetZoomButton,\n NodeGraphToolbarSeparator,\n} from './NodeGraphToolbar';\nimport { sortSlots } from './sortSlots';\nimport { useNodeGraphConnection } from './useNodeGraphConnection';\nimport {\n useNodeGraphEdgeInteraction,\n EDGE_HIT_PX,\n} from './useNodeGraphEdgeInteraction';\nimport { useNodeGraphGroupDrag } from './useNodeGraphGroupDrag';\nimport { useNodeGraphKeyboard } from './useNodeGraphKeyboard';\nimport { useNodeGraphNodeDrag } from './useNodeGraphNodeDrag';\n\nimport type {\n NodeGraphContextMenuInfo,\n NodeGraphEdge,\n NodeGraphGroup,\n NodeGraphHandle,\n NodeGraphLayerName,\n NodeGraphNode,\n NodeGraphPortRef,\n NodeGraphProps,\n NodeGraphSelection,\n NodeGraphTarget,\n} from './NodeGraph.types';\nimport type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportHandle,\n ViewportSelectionEvent,\n ViewportTransform,\n WorldRect,\n} from '@/components/primitives/viewport';\n\nconst EMPTY_NODES: NodeGraphNode[] = [];\nconst EMPTY_EDGES: NodeGraphEdge[] = [];\nconst EMPTY_GROUPS: NodeGraphGroup[] = [];\nconst EMPTY_SELECTION: NodeGraphSelection = {\n nodes: [],\n edges: [],\n groups: [],\n};\nconst DEFAULT_NODE_SIZE = { width: 180, height: 80 };\n\n// ─── Main component ───\n\n/**\n * `NodeGraph` — interactive, data-driven node editor surface built on\n * `Viewport`. Renders nodes as HTML in world space (`renderNode`) and\n * edges as Béziers on a perf-isolated canvas layer.\n *\n * The component is fully controlled-or-uncontrolled across four data\n * dimensions (nodes / edges / groups / selection) — each emits a full\n * array on change. Connection drags, marquee selection, drag-to-move,\n * snap-to-grid, and keyboard nav are all wired in.\n *\n * @example\n * ```tsx\n * <NodeGraph\n * nodes={nodes}\n * edges={edges}\n * onNodesChange={setNodes}\n * onEdgesChange={setEdges}\n * renderNode={node => <MyNode data={node.data} />}\n * isValidConnection={(src, tgt) => src.node !== tgt.node}\n * responsive\n * >\n * <NodeGraph.Background variant=\"dots\" gap={24} />\n * <NodeGraph.Minimap placement=\"bottom-right\" />\n * </NodeGraph>\n * ```\n */\nconst NodeGraphImpl = ({\n nodes: nodesProp,\n defaultNodes,\n onNodesChange,\n edges: edgesProp,\n defaultEdges,\n onEdgesChange,\n groups: groupsProp,\n defaultGroups,\n onGroupsChange,\n selection: selectionProp,\n defaultSelection,\n onSelectionChange,\n renderNode,\n renderEdgeLabel,\n edgeStyle,\n isValidConnection,\n snapToGrid = false,\n onConnectStart,\n onConnectEnd,\n onContextMenu,\n onDelete,\n onActivate,\n pan,\n zoom,\n minZoom = 0.1,\n maxZoom = 4,\n selectionRect = true,\n responsive = false,\n height = 480,\n defaultNodeSize: defaultNodeSizeProp = DEFAULT_NODE_SIZE,\n disabled = false,\n ariaLabel = 'Node graph',\n className,\n style,\n testId,\n id,\n children,\n ref,\n}: NodeGraphProps): React.ReactElement => {\n // ── Refs ──\n const rootRef = useRef<HTMLDivElement>(null);\n const viewportHandleRef = useRef<ViewportHandle>(null);\n const store = useMemo(() => new NodeGraphStore(), []);\n\n // Stabilize defaultNodeSize identity across renders when the consumer\n // passes an inline literal — downstream effects/memos depend on its\n // reference and would otherwise re-fire every render.\n const defaultNodeSize = useMemo(\n () => ({\n width: defaultNodeSizeProp.width,\n height: defaultNodeSizeProp.height,\n }),\n [defaultNodeSizeProp.width, defaultNodeSizeProp.height]\n );\n\n // ── Controlled / uncontrolled data ──\n const [nodes, setNodes] = useControlledState<NodeGraphNode[]>({\n value: nodesProp,\n defaultValue: defaultNodes,\n onChange: onNodesChange,\n fallback: EMPTY_NODES,\n });\n const [edges, setEdges] = useControlledState<NodeGraphEdge[]>({\n value: edgesProp,\n defaultValue: defaultEdges,\n onChange: onEdgesChange,\n fallback: EMPTY_EDGES,\n });\n const [groups, setGroups] = useControlledState<NodeGraphGroup[]>({\n value: groupsProp,\n defaultValue: defaultGroups,\n onChange: onGroupsChange,\n fallback: EMPTY_GROUPS,\n });\n const [selection, setSelection] = useControlledState<NodeGraphSelection>({\n value: selectionProp,\n defaultValue: defaultSelection,\n onChange: onSelectionChange,\n fallback: EMPTY_SELECTION,\n });\n\n // ── Mirror React state into the store ──\n useLayoutEffect(() => {\n store.setData({\n nodes,\n edges,\n groups,\n defaultNodeSize,\n });\n }, [store, nodes, edges, groups, defaultNodeSize]);\n\n useLayoutEffect(() => {\n store.setSelection(selection);\n }, [store, selection]);\n\n // ── Transform tracking (mirror Viewport transform into a ref for math) ──\n const transformRef = useRef<ViewportTransform>({ x: 0, y: 0, zoom: 1 });\n const handleTransformChange = useCallback((next: ViewportTransform) => {\n transformRef.current = next;\n }, []);\n\n // ── Slot sorting ──\n const slots = useMemo(() => sortSlots(children), [children]);\n\n // ── Helpers ──\n const getTransform = useCallback((): ViewportTransform => {\n return viewportHandleRef.current?.getTransform() ?? transformRef.current;\n }, []);\n\n const localScreenPoint = useCallback(\n (clientX: number, clientY: number): Point2D => {\n const el = rootRef.current;\n if (!el) return { x: 0, y: 0 };\n const rect = el.getBoundingClientRect();\n return { x: clientX - rect.left, y: clientY - rect.top };\n },\n []\n );\n\n const screenToWorldLocal = useCallback(\n (clientX: number, clientY: number): Point2D => {\n const local = localScreenPoint(clientX, clientY);\n return worldFromScreen(local, getTransform());\n },\n [localScreenPoint, getTransform]\n );\n\n // ── Targets / hit testing ──\n const nodesRef = useLatest(nodes);\n const groupsRef = useLatest(groups);\n const selectionRef = useLatest(selection);\n const setSelectionRef = useLatest(setSelection);\n const setNodesRef = useLatest(setNodes);\n const disabledRef = useLatest(disabled);\n\n const findHitTarget = useCallback(\n (clientX: number, clientY: number): NodeGraphTarget => {\n const worldPoint = screenToWorldLocal(clientX, clientY);\n const currentNodes = nodesRef.current;\n const currentGroups = groupsRef.current;\n // Iterate top-to-bottom so the last-rendered node \"wins\" — matches what\n // the user sees on top.\n for (let i = currentNodes.length - 1; i >= 0; i--) {\n const node = currentNodes[i];\n if (\n node &&\n isPointInNode(\n worldPoint,\n node,\n store.getMeasuredSize(node.id),\n defaultNodeSize\n )\n ) {\n return { kind: 'node', id: node.id };\n }\n }\n // Edges sit above groups / background but below nodes, so hit-test them\n // after nodes and before groups. Drawn on a canvas → no DOM to walk.\n const edgeThreshold = EDGE_HIT_PX / (getTransform().zoom || 1);\n const edgeId = findEdgeAtPoint(\n worldPoint,\n store.getData().edges,\n store.getNodeById,\n store.getPortPosition,\n edgeThreshold\n );\n if (edgeId) return { kind: 'edge', id: edgeId };\n for (let i = currentGroups.length - 1; i >= 0; i--) {\n const group = currentGroups[i];\n if (group && isPointInRect(worldPoint, group.bounds)) {\n return { kind: 'group', id: group.id };\n }\n }\n return { kind: 'empty', worldPoint };\n },\n [\n defaultNodeSize,\n screenToWorldLocal,\n nodesRef,\n groupsRef,\n store,\n getTransform,\n ]\n );\n\n // ── Connection drag (ports) ──\n const { onPortPointerDown, onEdgeReconnectStart } = useNodeGraphConnection({\n viewportRef: rootRef,\n store,\n getTransform,\n isValidConnection,\n onConnectStart,\n onConnectEnd,\n emitEdgesChange: setEdges,\n emitSelectionChange: setSelection,\n });\n\n // ── Node body pointerdown — drag (single/multi) + select on release ──\n const { onNodeBodyPointerDown, onNodeBodyPointerUp } = useNodeGraphNodeDrag({\n store,\n getTransform,\n localScreenPoint,\n snapToGrid,\n disabled,\n emitNodesChange: setNodes,\n emitSelectionChange: setSelection,\n });\n\n // ── Group interaction (drag + resize + click-select) ──\n const setGroupsRef = useLatest(setGroups);\n const {\n onGroupBodyPointerDown,\n onGroupHandlePointerDown,\n onGroupBodyPointerUp,\n } = useNodeGraphGroupDrag({\n store,\n getTransform,\n localScreenPoint,\n snapToGrid,\n disabled,\n defaultNodeSize,\n emitGroupsChange: setGroups,\n emitNodesChange: setNodes,\n emitSelectionChange: setSelection,\n });\n\n // ── Group label / colour edits ──\n //\n // The library's group overlay owns the inline label editor and the\n // colour swatch — these handlers translate UI commits into a controlled\n // `onGroupsChange` emission so the consumer receives the full next\n // groups array, same as every other group mutation.\n const handleGroupLabelChange = useCallback(\n (group: NodeGraphGroup, nextLabel: string): void => {\n const trimmed = nextLabel.trim();\n const nextGroups = groupsRef.current.map(g => {\n if (g.id !== group.id) return g;\n if ((g.label ?? '') === trimmed) return g;\n if (trimmed === '') {\n // Empty label collapses back to `undefined` so the default\n // \"Group\" placeholder shows up cleanly on next render.\n const { label: _omit, ...rest } = g;\n void _omit;\n return rest;\n }\n return { ...g, label: trimmed };\n });\n setGroupsRef.current(nextGroups);\n },\n [groupsRef, setGroupsRef]\n );\n\n const handleGroupColorChange = useCallback(\n (group: NodeGraphGroup, nextColor: string): void => {\n if (group.color === nextColor) return;\n const nextGroups = groupsRef.current.map(g =>\n g.id === group.id ? { ...g, color: nextColor } : g\n );\n setGroupsRef.current(nextGroups);\n },\n [groupsRef, setGroupsRef]\n );\n\n // ── Marquee selection from the Viewport ──\n const [, startMarqueeTransition] = useTransition();\n const handleViewportSelection = useCallback(\n (info: ViewportSelectionEvent): void => {\n if (disabledRef.current) return;\n if (info.inProgress) {\n // Live preview: drive the marquee overlay via the store so canvas\n // hit-test for hover/edge can also respond if needed.\n store.setInteraction({\n kind: 'marquee',\n startWorld: { x: info.rect.x, y: info.rect.y },\n currentWorld: {\n x: info.rect.x + info.rect.width,\n y: info.rect.y + info.rect.height,\n },\n additive: info.additive,\n });\n return;\n }\n\n // Final marquee — compute selection from rect intersection.\n store.setInteraction({ kind: 'idle' });\n const rect: WorldRect = info.rect;\n\n // A near-zero-area rect is a plain click, not a drag. Use it to select\n // an edge — edges are drawn on a canvas and never receive the pointer\n // event directly, so this is where edge clicks are resolved. Falls\n // through to the normal node-marquee / clear path when no edge is hit.\n const zoom = getTransform().zoom || 1;\n const isClick =\n rect.width * zoom <= EDGE_HIT_PX && rect.height * zoom <= EDGE_HIT_PX;\n if (isClick) {\n const edgeId = findEdgeAtPoint(\n { x: rect.x, y: rect.y },\n store.getData().edges,\n store.getNodeById,\n store.getPortPosition,\n EDGE_HIT_PX / zoom\n );\n if (edgeId) {\n const current = selectionRef.current;\n setSelectionRef.current({\n nodes: info.additive ? current.nodes : [],\n edges: toggleSelected(current.edges, edgeId, info.additive),\n groups: info.additive ? current.groups : [],\n });\n return;\n }\n }\n\n const hits: string[] = [];\n for (const node of nodesRef.current) {\n const box = getNodeBox(\n node,\n store.getMeasuredSize(node.id),\n defaultNodeSize\n );\n if (\n rectsIntersect(\n { x: box.x, y: box.y, width: box.width, height: box.height },\n rect\n )\n ) {\n hits.push(node.id);\n }\n }\n const current = selectionRef.current;\n const nextNodes = info.additive\n ? Array.from(new Set([...current.nodes, ...hits]))\n : hits;\n // Selection commits can cascade into expensive renderNode bodies for\n // a large hit set — let React schedule it as non-urgent so the\n // gesture release doesn't hitch.\n startMarqueeTransition(() => {\n setSelectionRef.current({\n nodes: nextNodes,\n edges: info.additive ? current.edges : [],\n groups: info.additive ? current.groups : [],\n });\n });\n },\n [\n store,\n nodesRef,\n selectionRef,\n setSelectionRef,\n defaultNodeSize,\n disabledRef,\n getTransform,\n ]\n );\n\n // ── Context menu ──\n const onContextMenuRef = useLatest(onContextMenu);\n const handleContextMenu = useCallback(\n (event: React.MouseEvent<HTMLDivElement>): void => {\n if (disabledRef.current) return;\n event.preventDefault();\n // Walk up the DOM from the event target to find data attributes\n // identifying a port or a node. Ports take priority because they're\n // descendants of nodes — the loop bails on the first match.\n const targetEl = event.target as Element | null;\n let portRef: NodeGraphPortRef | null = null;\n let nodeId: string | null = null;\n let cursor: Element | null = targetEl;\n while (cursor && cursor !== rootRef.current) {\n const portId = cursor.getAttribute('data-port-id');\n const dataNodeId = cursor.getAttribute('data-node-id');\n if (portId && dataNodeId) {\n portRef = { node: dataNodeId, port: portId };\n break;\n }\n if (dataNodeId && !nodeId) {\n nodeId = dataNodeId;\n }\n cursor = cursor.parentElement;\n }\n const screenPoint = localScreenPoint(event.clientX, event.clientY);\n const worldPoint = worldFromScreen(screenPoint, getTransform());\n let resolvedTarget: NodeGraphTarget;\n if (portRef) {\n resolvedTarget = {\n kind: 'port',\n node: portRef.node,\n port: portRef.port,\n };\n } else if (nodeId) {\n resolvedTarget = { kind: 'node', id: nodeId };\n } else {\n resolvedTarget = findHitTarget(event.clientX, event.clientY);\n }\n const info: NodeGraphContextMenuInfo = {\n target: resolvedTarget,\n screenPoint,\n worldPoint,\n };\n // Consumer callback fires first — they may render their own menu,\n // log telemetry, etc.\n onContextMenuRef.current?.(info);\n // SpawnPalette subscribers (if mounted) get pinged for empty /\n // group targets: those are the \"drop a new node here\" spots.\n if (resolvedTarget.kind === 'empty' || resolvedTarget.kind === 'group') {\n store.requestSpawn({ worldPoint, screenPoint });\n }\n },\n [\n findHitTarget,\n localScreenPoint,\n getTransform,\n onContextMenuRef,\n disabledRef,\n store,\n ]\n );\n\n // ── Edge hover + endpoint grab (canvas edges → pointer hit-test) ──\n const { onRootPointerMove, onRootPointerLeave, onRootPointerDownCapture } =\n useNodeGraphEdgeInteraction({\n store,\n getTransform,\n screenToWorldLocal,\n localScreenPoint,\n onEdgeReconnectStart,\n disabled,\n });\n\n // ── Delete ──\n //\n // Without a consumer-supplied `onDelete`, the library cascades the\n // selection through nodes / edges / groups automatically: nodes get\n // removed, edges are filtered out when either endpoint is gone (or\n // when the edge itself is selected), groups in the selection drop.\n // Saves every consumer the same 8-line filter and avoids the classic\n // \"I forgot to clean up orphan edges\" bug.\n //\n // If the consumer provides `onDelete`, they take over completely —\n // they can still call the exported `applyCascadeDelete` helper to do\n // the same filtering plus their own snapshot / undo / confirmation\n // logic on top.\n const handleDeleteInternal = useCallback(\n (sel: NodeGraphSelection): void => {\n if (onDelete) {\n onDelete(sel);\n return;\n }\n const currentNodes = nodesRef.current;\n const currentEdges = store.getData().edges;\n const currentGroups = groupsRef.current;\n const removedNodeIds = new Set(sel.nodes);\n const removedEdgeIds = new Set(sel.edges);\n const removedGroupIds = new Set(sel.groups);\n if (\n removedNodeIds.size === 0 &&\n removedEdgeIds.size === 0 &&\n removedGroupIds.size === 0\n ) {\n return;\n }\n if (removedNodeIds.size > 0) {\n setNodesRef.current(\n currentNodes.filter(n => !removedNodeIds.has(n.id))\n );\n }\n const nextEdges = currentEdges.filter(\n e =>\n !removedEdgeIds.has(e.id) &&\n !removedNodeIds.has(e.source.node) &&\n !removedNodeIds.has(e.target.node)\n );\n if (nextEdges.length !== currentEdges.length) {\n setEdges(nextEdges);\n }\n if (removedGroupIds.size > 0) {\n setGroupsRef.current(\n currentGroups.filter(g => !removedGroupIds.has(g.id))\n );\n }\n setSelectionRef.current({ nodes: [], edges: [], groups: [] });\n },\n [\n onDelete,\n store,\n nodesRef,\n groupsRef,\n setNodesRef,\n setGroupsRef,\n setSelectionRef,\n setEdges,\n ]\n );\n\n // ── Keyboard ──\n const { onKeyDown } = useNodeGraphKeyboard({\n store,\n emitNodesChange: setNodes,\n emitSelectionChange: setSelection,\n onDelete: handleDeleteInternal,\n onActivate,\n snapToGrid,\n disabled,\n });\n\n // ── Canvas draw callbacks (stable identities via useLatest) ──\n const backgroundProps = slots.backgroundProps;\n const backgroundVariant = backgroundProps?.variant ?? 'dots';\n const backgroundGap = backgroundProps?.gap ?? 24;\n const backgroundColor = backgroundProps?.color;\n const backgroundFill = backgroundProps?.background;\n\n const drawBackgroundLayer = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n info: Parameters<React.ComponentProps<typeof ViewportLayer>['draw']>[1]\n ): void => {\n const theme = buildDrawTheme(info.theme);\n drawBackground(ctx, info, theme, {\n variant: backgroundVariant,\n gap: backgroundGap,\n color: backgroundColor,\n background: backgroundFill,\n });\n },\n [backgroundVariant, backgroundGap, backgroundColor, backgroundFill]\n );\n\n const drawGroupsLayer = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n info: Parameters<React.ComponentProps<typeof ViewportLayer>['draw']>[1]\n ): void => {\n const data = store.getData();\n const sel = store.getSelection();\n const interaction = store.getInteraction();\n const theme = buildDrawTheme(info.theme);\n drawGroups(ctx, info, data, sel, interaction, theme);\n },\n [store]\n );\n\n const edgeStyleRef = useLatest(edgeStyle);\n const drawEdgesLayer = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n info: Parameters<React.ComponentProps<typeof ViewportLayer>['draw']>[1]\n ): void => {\n const data = store.getData();\n const sel = store.getSelection();\n const hover = store.getHover();\n const interaction = store.getInteraction();\n const theme = buildDrawTheme(info.theme);\n drawEdges(\n ctx,\n info,\n data,\n sel,\n hover.hoveredEdgeId,\n interaction,\n store.getNodeById,\n store.getPortPosition,\n edgeStyleRef.current,\n theme\n );\n },\n [store, edgeStyleRef]\n );\n\n const drawPreviewLayer = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n info: Parameters<React.ComponentProps<typeof ViewportLayer>['draw']>[1]\n ): void => {\n const interaction = store.getInteraction();\n if (interaction.kind !== 'connect') return;\n const theme = buildDrawTheme(info.theme);\n drawConnectionPreview(\n ctx,\n info,\n interaction,\n portRef => {\n const resolved = resolvePortRef(\n portRef,\n store.getNodeById,\n store.getPortPosition\n );\n if (!resolved) return null;\n return { position: resolved.position, side: resolved.side };\n },\n theme\n );\n },\n [store]\n );\n\n // Force invalidation of canvas layers when the relevant store slices change.\n // `invalidate` reads `viewportHandleRef.current` at call time so a viewport\n // remount (which would re-bind the imperative handle) doesn't leave us\n // pointing at a stale handle reference.\n useLayoutEffect(() => {\n const invalidate = (layer: NodeGraphLayerName): void => {\n viewportHandleRef.current?.invalidate(layer);\n };\n const unsubs: Array<() => void> = [\n store.subscribeData(() => {\n invalidate('groups');\n invalidate('edges');\n }),\n store.subscribeSelection(() => {\n invalidate('groups');\n invalidate('edges');\n }),\n store.subscribeHover(() => {\n invalidate('edges');\n }),\n // Interaction drives the in-flight drag delta — every canvas layer\n // that visualises something positional needs to redraw on each tick:\n // edges (connectors follow dragged nodes live, not snap on release),\n // groups (drag-groups / resize-group), and the connection preview.\n store.subscribeInteraction(() => {\n invalidate('edges');\n invalidate('groups');\n invalidate('preview');\n }),\n // Port positions (re)registered by `<NodeGraph.Port>` slots — edges\n // anchor at the registered point, so any change must redraw.\n store.subscribePortPositions(() => {\n invalidate('edges');\n }),\n // Measured node sizes feed the marquee / hit-test bounds — no canvas\n // redraw needed, but subscribe so React-side reads in renderers see\n // the updates if they depend on it.\n store.subscribeMeasuredSizes(() => undefined),\n ];\n return () => {\n for (const unsub of unsubs) unsub();\n };\n }, [store]);\n\n // ── Imperative handle ──\n useImperativeHandle(\n ref,\n (): NodeGraphHandle => ({\n fitToContent: padding => {\n const vp = viewportHandleRef.current;\n if (!vp) return;\n const bounds = computeNodesBounds(\n nodesRef.current,\n store.getMeasuredSize,\n defaultNodeSize\n );\n if (bounds.width === 0 && bounds.height === 0) return;\n vp.fitToContent(bounds, padding ?? 32);\n },\n fitToSelection: padding => {\n const vp = viewportHandleRef.current;\n if (!vp) return;\n const sel = selectionRef.current.nodes;\n if (sel.length === 0) return;\n const selectedIds = new Set(sel);\n const selectedNodes = nodesRef.current.filter(n =>\n selectedIds.has(n.id)\n );\n const bounds = computeNodesBounds(\n selectedNodes,\n store.getMeasuredSize,\n defaultNodeSize\n );\n if (bounds.width === 0 && bounds.height === 0) return;\n vp.fitToContent(bounds, padding ?? 64);\n },\n focusNode: idStr => {\n const vp = viewportHandleRef.current;\n if (!vp) return;\n const node = store.getNodeById(idStr);\n if (!node) return;\n const box = getNodeBox(\n node,\n store.getMeasuredSize(node.id),\n defaultNodeSize\n );\n vp.centerOn({\n x: box.x + box.width / 2,\n y: box.y + box.height / 2,\n });\n },\n centerOn: (point, z) => {\n viewportHandleRef.current?.centerOn(point, z);\n },\n zoomToRect: (rect, padding) => {\n viewportHandleRef.current?.zoomToRect(rect, padding);\n },\n getTransform: () => getTransform(),\n getSize: () =>\n viewportHandleRef.current?.getSize() ?? { width: 0, height: 0 },\n worldToScreen: point => screenFromWorld(point, getTransform()),\n screenToWorld: point => worldFromScreen(point, getTransform()),\n invalidate: layerName => viewportHandleRef.current?.invalidate(layerName),\n }),\n [nodesRef, selectionRef, defaultNodeSize, getTransform, store]\n );\n\n // Edge labels rendered as world-space children at the midpoint of each\n // edge. Mounted as its own subscriber component so the labels follow\n // dragged nodes live without re-rendering the whole NodeGraph.\n const renderEdgeLabelRef = useLatest(renderEdgeLabel);\n\n return (\n <NodeGraphStoreContext.Provider value={store}>\n {/*\n The root is an event-delegation wrapper for graph-wide keyboard\n shortcuts and pointer capture; it is not itself focusable. The\n focusable, labelled interactive surface is the inner <Viewport>\n (ariaLabel + ariaRoledescription=\"node graph\"), which jsx-a11y\n cannot see through this wrapper.\n */}\n {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}\n <div\n ref={rootRef}\n id={id}\n data-testid={testId}\n onKeyDown={onKeyDown}\n onContextMenu={handleContextMenu}\n onPointerDownCapture={onRootPointerDownCapture}\n onPointerMove={onRootPointerMove}\n onPointerLeave={onRootPointerLeave}\n className={cx(nodeGraphRootStyle, className)}\n style={style}\n >\n <Viewport\n ref={viewportHandleRef}\n responsive={responsive}\n height={height}\n pan={pan}\n zoom={zoom}\n minZoom={minZoom}\n maxZoom={maxZoom}\n selectionRect={{ enabled: selectionRect, button: 'left' }}\n onSelectionChange={handleViewportSelection}\n onTransformChange={handleTransformChange}\n disabled={disabled}\n ariaLabel={ariaLabel}\n ariaRoledescription=\"node graph\"\n >\n {slots.hasBackground ? (\n <ViewportLayer name=\"background\" draw={drawBackgroundLayer} />\n ) : null}\n <ViewportLayer name=\"groups\" draw={drawGroupsLayer} />\n <ViewportLayer name=\"edges\" draw={drawEdgesLayer} />\n <ViewportWorld>\n {groups.map(group => (\n <NodeGraphGroupView\n key={group.id}\n group={group}\n onBodyPointerDown={onGroupBodyPointerDown}\n onBodyPointerUp={onGroupBodyPointerUp}\n onHandlePointerDown={onGroupHandlePointerDown}\n onBodyContextMenu={handleContextMenu}\n onLabelChange={handleGroupLabelChange}\n onColorChange={handleGroupColorChange}\n />\n ))}\n {nodes.map(node => (\n <NodeGraphNodeView\n key={node.id}\n node={node}\n renderNode={renderNode}\n onBodyPointerDown={onNodeBodyPointerDown}\n onBodyPointerUp={onNodeBodyPointerUp}\n onPortPointerDown={onPortPointerDown}\n onBodyContextMenu={handleContextMenu}\n />\n ))}\n <EdgeLabelsLayer\n renderEdgeLabelRef={renderEdgeLabelRef}\n hasRenderEdgeLabel={renderEdgeLabel !== undefined}\n />\n </ViewportWorld>\n <ViewportLayer name=\"preview\" draw={drawPreviewLayer} />\n {slots.hasMinimap || slots.toolbars.length > 0 ? (\n <ViewportOverlay>\n {slots.hasMinimap ? (\n <NodeGraphMinimapInner {...(slots.minimapProps ?? {})} />\n ) : null}\n {slots.toolbars.map((toolbarProps, i) => (\n <NodeGraphToolbarInner\n // Placement is part of the identity — multiple toolbars\n // in the same NodeGraph use different placements as\n // their natural key.\n key={toolbarProps.placement ?? `toolbar-${i}`}\n {...toolbarProps}\n />\n ))}\n </ViewportOverlay>\n ) : null}\n </Viewport>\n {/* SpawnPalette renders in a portal (via CommandPalette) so it\n sits at the React tree root, outside the Viewport. Subscribes\n to the store's spawn-request channel for right-click triggers. */}\n {slots.spawnPaletteProps ? (\n <NodeGraphSpawnPaletteInner {...slots.spawnPaletteProps} />\n ) : null}\n </div>\n </NodeGraphStoreContext.Provider>\n );\n};\n\n// ─── Compound exports ───\n\ntype NodeGraphCompound = typeof NodeGraphImpl & {\n Minimap: typeof NodeGraphMinimap;\n Background: typeof NodeGraphBackground;\n Port: typeof NodeGraphPort;\n PortVisual: typeof NodeGraphPortVisual;\n Pin: typeof NodeGraphPin;\n NodeBody: typeof NodeGraphNodeBody;\n NodeHeader: typeof NodeGraphNodeHeader;\n NodeSection: typeof NodeGraphNodeSection;\n PinList: typeof NodeGraphPinList;\n PinRow: typeof NodeGraphPinRow;\n Toolbar: typeof NodeGraphToolbar;\n ToolbarSeparator: typeof NodeGraphToolbarSeparator;\n FitContentButton: typeof NodeGraphFitContentButton;\n FitSelectionButton: typeof NodeGraphFitSelectionButton;\n ZoomInButton: typeof NodeGraphZoomInButton;\n ZoomOutButton: typeof NodeGraphZoomOutButton;\n ResetZoomButton: typeof NodeGraphResetZoomButton;\n SpawnPalette: typeof NodeGraphSpawnPalette;\n};\n\nNodeGraphImpl.displayName = 'NodeGraph';\n\nconst NodeGraphWithSlots = NodeGraphImpl as NodeGraphCompound;\nNodeGraphWithSlots.Minimap = NodeGraphMinimap;\nNodeGraphWithSlots.Background = NodeGraphBackground;\nNodeGraphWithSlots.Port = NodeGraphPort;\nNodeGraphWithSlots.PortVisual = NodeGraphPortVisual;\nNodeGraphWithSlots.Pin = NodeGraphPin;\nNodeGraphWithSlots.NodeBody = NodeGraphNodeBody;\nNodeGraphWithSlots.NodeHeader = NodeGraphNodeHeader;\nNodeGraphWithSlots.NodeSection = NodeGraphNodeSection;\nNodeGraphWithSlots.PinList = NodeGraphPinList;\nNodeGraphWithSlots.PinRow = NodeGraphPinRow;\nNodeGraphWithSlots.Toolbar = NodeGraphToolbar;\nNodeGraphWithSlots.ToolbarSeparator = NodeGraphToolbarSeparator;\nNodeGraphWithSlots.FitContentButton = NodeGraphFitContentButton;\nNodeGraphWithSlots.FitSelectionButton = NodeGraphFitSelectionButton;\nNodeGraphWithSlots.ZoomInButton = NodeGraphZoomInButton;\nNodeGraphWithSlots.ZoomOutButton = NodeGraphZoomOutButton;\nNodeGraphWithSlots.ResetZoomButton = NodeGraphResetZoomButton;\nNodeGraphWithSlots.SpawnPalette = NodeGraphSpawnPalette;\n\nexport const NodeGraph = NodeGraphWithSlots;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsGA;AACA;AACA;AACA;AACE;AACA;AACA;;AAEF;AAEA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACH;;AAyCE;AACA;AACA;;;;AAKA;;;;;AASA;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;;;;;;;;AASE;AACH;;AAGE;AACF;;AAGA;AACA;AACE;;;AAIF;;AAGA;;;;AAMI;AACA;;AACA;AACA;;;;AAQA;AACF;;AAKF;AACA;AACA;AACA;AACA;AACA;;;AAKI;AACA;;;AAGA;AACE;AACA;AAEE;;;;;;AAYJ;;AAQA;;AACA;AACE;;;;;AAKF;AACF;;;;;;;AAQC;;AAIH;AACE;;;;;;AAMA;AACA;AACD;;AAGD;;;;;;AAME;AACA;AACD;;AAGD;;;;;;;;AAYE;AACA;AACA;AACD;;;;;;;;AAUG;;AAEE;AAAuB;;AACU;AACjC;;;;AAKE;;;AAGJ;AACA;AACF;;AAME;;AACA;AAGA;AACF;;AAKF;AACA;;;AAGI;;;;AAII;AACA;AACA;;;AAGC;;AAEF;;;;;AAMH;;;;;;AAOA;;AAGE;;AAQE;;AAEE;AACA;AACA;AACD;;;;;AAML;AACE;AAKA;AAME;;;AAGJ;AACA;AACE;;;;;;;AAOE;AACA;AACA;AACD;AACH;AACF;;;;;;;;AASC;;AAIH;AACA;;;;;;;AAOI;;;;;;;AAOE;;;;AAIA;;;AAGA;;AAEF;;AAEA;;AAEE;AACE;;;;;;;;;;;AASJ;AACE;;;;;;AAMF;;;AAGA;;;AAGF;;;;;;;AAQC;;;;;;;;;AAYA;;;;;;;;;;;;;;AAeH;;;;;AAMI;;AAEA;;;;AAIA;;AAGE;;;AAIF;;;AAKA;;;;;;AASA;;;AAKA;AACF;;;;;;;;;AAUC;;AAIH;;AAEE;AACA;AACA;;;;AAID;;AAGD;AACA;AACA;AACA;AACA;;;AAQI;AACE;AACA;AACA;AACA;AACD;;;AAUD;AACA;AACA;;AAEA;AACF;AAIF;;AAMI;AACA;AACA;AACA;;AAEA;AAYF;;AASE;AACA;;;;AAOI;AAKA;AAAe;AACf;;AAIN;;;;;;AASA;AACE;AACF;AACA;AACE;;;AAGA;AACA;;;AAGA;AACA;;AAEA;;;;;AAKA;;;;AAIA;;;AAGA;;AAEA;;;;AAIA;;AAEF;;AAC8B;AAC9B;AACF;;AAGA;;AAIM;AACA;;AACA;;;;;;AASA;AACA;;AACA;AACA;;AACA;;AAIA;;;;;;AASA;AACA;;;AAEA;;AACA;;;;AAQC;;AAEH;;;AAGA;;;AAGA;AACA;;;AAIA;AACD;;;;AAOH;AAEA;;;;AAmFoB;AAetB;AAyBA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"NodeGraph.types.js","sources":["../../../../../../src/components/editor/NodeGraph/NodeGraph.types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAwUA;AAEA;;;;AAIG;AACI,MAAM,eAAe,GAAkB,MAAM,CAAC,GAAG,CAAC,qBAAqB;;;;"}
1
+ {"version":3,"file":"NodeGraph.types.js","sources":["src/components/editor/NodeGraph/NodeGraph.types.ts"],"sourcesContent":["import type { Point2D } from '@/components/primitives/canvas/canvas.types';\nimport type {\n ViewportPanConfig,\n ViewportSize,\n ViewportTransform,\n ViewportZoomConfig,\n WorldRect,\n} from '@/components/primitives/viewport';\nimport type { BaseComponent } from '@/types/common';\nimport type { Prettify } from '@/types/utilities';\nimport type React from 'react';\n\n// ─── Geometry primitives ───\n\n/** Side of a node a port is anchored to. */\nexport type NodeGraphPortSide = 'left' | 'right' | 'top' | 'bottom';\n\n/** Reference to a single port on a node. */\nexport interface NodeGraphPortRef {\n /** Owning node id. */\n node: string;\n /** Port id within that node. */\n port: string;\n}\n\n// ─── Data model ───\n\nexport interface NodeGraphNode {\n /** Stable identity. */\n id: string;\n /** Position in world coordinates (top-left corner of the node body). */\n position: Point2D;\n /**\n * Override the auto-measured width of the node body. Use this when you\n * need fixed-size nodes. When omitted, the library measures the rendered\n * node DOM and uses that size for hit-testing, marquee selection, and\n * minimap geometry.\n */\n width?: number;\n /** Override the auto-measured height of the node body. See {@link width}. */\n height?: number;\n /** Arbitrary consumer payload passed to `renderNode`. */\n data?: unknown;\n /**\n * When false, the node cannot be moved by drag. Selection still works.\n * @default true\n */\n draggable?: boolean;\n /**\n * When false, the node cannot be selected (clicks pass through to the\n * background). Drag is also disabled.\n * @default true\n */\n selectable?: boolean;\n}\n\nexport interface NodeGraphEdge {\n /** Stable identity. */\n id: string;\n /** Edge source endpoint. */\n source: NodeGraphPortRef;\n /** Edge target endpoint. */\n target: NodeGraphPortRef;\n /** Arbitrary consumer payload (e.g. animation flags, weights). */\n data?: unknown;\n /**\n * Optional HTML label rendered absolutely above the edge midpoint.\n * Use `renderEdgeLabel` for full control, or pass a node here for the\n * default centred placement.\n */\n label?: React.ReactNode;\n /**\n * Override the stroke colour of this edge in its default state.\n * Selected / hovered edges still pick up the theme accents (so the\n * interaction state stays visible), this colour is used only when\n * neither state is active. Useful for type-coloured wires — assign\n * the colour at edge-creation time based on the source pin's data\n * type, the way UE5 paints exec / float / bool wires differently.\n */\n color?: string;\n}\n\n/**\n * A visual backdrop rectangle drawn under nodes. Groups in v1 are purely\n * decorative — nodes are not children of a group, they simply happen to\n * overlap with it. Selection of a group through marquee/click can be\n * wired up by the consumer via `onContextMenu` / future selection API.\n */\nexport interface NodeGraphGroup {\n /** Stable identity. */\n id: string;\n /** Group rectangle in world coordinates. */\n bounds: WorldRect;\n /** Optional title shown above the group's top edge. */\n label?: string;\n /** Optional CSS colour string used for the group tint and label. */\n color?: string;\n}\n\nexport interface NodeGraphSelection {\n /** Selected node ids. */\n nodes: string[];\n /** Selected edge ids. */\n edges: string[];\n /** Selected group ids. */\n groups: string[];\n}\n\n// ─── Targets / events ───\n\n/** Discriminated union describing what was hit by a pointer event. */\nexport type NodeGraphTarget =\n | { kind: 'node'; id: string }\n | { kind: 'edge'; id: string }\n | { kind: 'port'; node: string; port: string }\n | { kind: 'group'; id: string }\n | { kind: 'empty'; worldPoint: Point2D };\n\nexport interface NodeGraphContextMenuInfo {\n target: NodeGraphTarget;\n /** Screen-space (CSS-pixel) position of the pointer relative to viewport. */\n screenPoint: Point2D;\n /** World-space position of the pointer. */\n worldPoint: Point2D;\n}\n\nexport interface NodeGraphConnectStartInfo {\n source: NodeGraphPortRef;\n /** World-space position the drag started at (the source port). */\n worldPoint: Point2D;\n}\n\nexport interface NodeGraphConnectEndInfo {\n source: NodeGraphPortRef;\n /** Resolved drop target, or null when the drag ended on empty space. */\n target: NodeGraphPortRef | null;\n /** True when the drop was rejected (target invalid or empty). */\n cancelled: boolean;\n /**\n * World-space position the drag was released at. With `cancelled` + a null\n * `target` this is an empty-space drop — the hook for a \"drag a wire onto\n * the canvas → open a create-node menu here → connect the new node to\n * `source`\" flow. Place the spawned node at this point.\n */\n worldPoint: Point2D;\n /**\n * Screen-space (CSS-pixel, relative to the viewport top-left) release\n * position — position your create-node menu / popover here.\n */\n screenPoint: Point2D;\n}\n\nexport interface NodeGraphConnectionValidationInfo {\n /** True when source and target reference the same node. */\n sameNode: boolean;\n /** Side combination shorthand, e.g. `'right->left'`. */\n sideCombo: string;\n /** `dataType` declared on the source `<NodeGraph.Port>`, if any. */\n sourceDataType?: string;\n /** `dataType` declared on the target `<NodeGraph.Port>`, if any. */\n targetDataType?: string;\n}\n\n// ─── Rendering ───\n\n/** Context passed to `renderNode`. */\nexport interface NodeGraphRenderCtx {\n /** True when the node is part of the current selection. */\n selected: boolean;\n /** True when the node is being dragged (single or multi). */\n dragging: boolean;\n /** True when the pointer is hovering over the node body. */\n hovered: boolean;\n /** Current viewport zoom — useful for LOD rendering. */\n zoom: number;\n}\n\n/** Resolved port metadata passed to the `edgeStyle` callback. */\nexport interface NodeGraphEdgeStyleCtx {\n /** True when the edge is in the current selection. */\n selected: boolean;\n /** True when the pointer is currently hovering over the edge. */\n hovered: boolean;\n /**\n * The `side` and `dataType` declared on the source `<NodeGraph.Port>`,\n * resolved from the store. `null` when the port hasn't been measured\n * yet (e.g. first paint before `useLayoutEffect` has run).\n */\n sourcePort: { side: NodeGraphPortSide; dataType?: string } | null;\n /** Same for the target endpoint. */\n targetPort: { side: NodeGraphPortSide; dataType?: string } | null;\n}\n\n/**\n * Style overrides for a single edge, returned by `edgeStyle`. Any field\n * left undefined falls back to the default (theme + `edge.color`).\n */\nexport interface NodeGraphEdgeStyle {\n /** Stroke colour. Overrides `edge.color`. */\n color?: string;\n /** Stroke width in screen pixels. */\n width?: number;\n /**\n * Marching-ant dash pattern, in screen pixels.\n * Example: `[8, 6]` draws 8 px dash + 6 px gap repeating.\n * Pass `null` (or omit) for a solid stroke.\n */\n dash?: ReadonlyArray<number> | null;\n}\n\n/**\n * Per-edge style hook. Called on every frame for every edge — keep it\n * cheap (map lookup, ternary). The library memoizes nothing here; if\n * the result is expensive, hoist into a `useMemo` keyed by inputs.\n */\nexport type NodeGraphEdgeStyleFn = (\n edge: NodeGraphEdge,\n ctx: NodeGraphEdgeStyleCtx\n) => NodeGraphEdgeStyle | undefined;\n\n// ─── Port slot ───\n\n/**\n * Built-in port handle shapes. `circle` is the default data-pin look,\n * `triangle` is the UE-style exec/flow arrow, `diamond` / `square` cover\n * the other common node-editor conventions. Render any other visual by\n * passing `children` to `<NodeGraph.Port>`.\n */\nexport type NodeGraphPortShape = 'circle' | 'triangle' | 'diamond' | 'square';\n\n/**\n * Props for `<NodeGraph.Port>` — the compound child rendered inside\n * `renderNode` to declare a connection endpoint.\n *\n * The library tracks the slot's DOM position and registers it as the\n * anchor for any edge that references this port. Pointer events on the\n * slot start a connection drag automatically — no manual wiring from the\n * consumer.\n *\n * @example\n * ```tsx\n * <NodeGraph\n * renderNode={(node, ctx) => (\n * <MyNodeBody>\n * <Row>\n * <NodeGraph.Port id=\"exec-in\" side=\"left\" dataType=\"exec\" />\n * Execute\n * </Row>\n * </MyNodeBody>\n * )}\n * />\n * ```\n */\nexport interface NodeGraphPortSlotProps {\n /** Stable identity within the owning node — referenced by `NodeGraphEdge`. */\n id: string;\n /** Which side of the node the port anchors to. Determines Bézier tangent. */\n side: NodeGraphPortSide;\n /**\n * Opaque type token forwarded to `isValidConnection` and exposed on\n * `data-port-data-type` for CSS theming. Not interpreted by the library.\n */\n dataType?: string;\n /**\n * Built-in handle shape used when no `children` are supplied.\n * @default 'circle'\n */\n shape?: NodeGraphPortShape;\n /**\n * Handle colour for the built-in visual (any CSS colour). When omitted,\n * the port inherits the theme focus colour; the connection-drag states\n * (source / candidate / invalid) still override it so interaction stays\n * visible. Ignored when `children` are supplied.\n */\n color?: string;\n /**\n * Force the built-in visual filled (`true`) or hollow (`false`). When\n * omitted, the port fills automatically while it is connected to at\n * least one edge and stays hollow otherwise — the standard \"wired vs\n * unwired pin\" convention. Ignored when `children` are supplied.\n */\n filled?: boolean;\n /**\n * Replace the built-in port visual entirely. When provided, no built-in\n * chrome is rendered — the children fill the slot wrapper. State for\n * theming (source / candidate / hover / invalid / connected) is exposed\n * via `data-port-*` attributes on the wrapper.\n */\n children?: React.ReactNode;\n /** Accessible label. Falls back to `${side} port ${id}`. */\n label?: string;\n /** Extra class applied to the slot wrapper. */\n className?: string;\n /** Inline style override on the slot wrapper. */\n style?: React.CSSProperties;\n}\n\n// ─── Imperative handle ───\n\nexport interface NodeGraphHandle {\n /** Pan/zoom so all nodes fit inside the viewport with optional padding. */\n fitToContent(padding?: number): void;\n /** Pan/zoom so all *selected* nodes fit. No-op when selection is empty. */\n fitToSelection(padding?: number): void;\n /** Center the viewport on a specific node. */\n focusNode(id: string): void;\n /** Center on a world point, optionally setting zoom. */\n centerOn(point: Point2D, zoom?: number): void;\n /** Pan/zoom to fit a world rectangle. */\n zoomToRect(rect: WorldRect, padding?: number): void;\n /** Read the current transform. */\n getTransform(): ViewportTransform;\n /** Read the current viewport size in CSS pixels. */\n getSize(): ViewportSize;\n /** Convert a world point to a screen (CSS-pixel) point. */\n worldToScreen(point: Point2D): Point2D;\n /** Convert a screen (CSS-pixel) point to a world point. */\n screenToWorld(point: Point2D): Point2D;\n /**\n * Force a redraw. With no `layerName`, all canvas layers redraw on the\n * next frame; with a name (`'edges' | 'groups' | 'preview'`), only that\n * layer redraws.\n */\n invalidate(layerName?: NodeGraphLayerName): void;\n}\n\nexport type NodeGraphLayerName = 'groups' | 'edges' | 'preview';\n\n// ─── Slot markers ───\n\n/**\n * Symbol attached to `<NodeGraph.Minimap>` and other slot subcomponents so\n * the parent `<NodeGraph>` can identify them without relying on\n * `displayName` (which gets clobbered by `React.memo` / minifiers).\n */\nexport const NODE_GRAPH_SLOT: unique symbol = Symbol.for('etui.nodegraph.slot');\n\nexport type NodeGraphSlotKind =\n | 'minimap'\n | 'background'\n | 'toolbar'\n | 'spawn-palette';\n\n/**\n * Template registered with `<NodeGraph.SpawnPalette>` — describes a\n * spawn-able node + how to build it at a given world point. The\n * library handles search / filtering / focus / selection of templates\n * in the popover; this is the data slice consumer cares about.\n */\nexport interface NodeGraphTemplate {\n /** Stable identifier (used for keys + the palette's recent list). */\n id: string;\n /** Human-readable title shown in the palette. */\n title: string;\n /** Optional secondary line. */\n subtitle?: string;\n /** Group label used to section the palette list. */\n group?: string;\n /** Extra strings the fuzzy matcher considers (synonyms, tags). */\n keywords?: ReadonlyArray<string>;\n /** Optional leading icon. */\n icon?: React.ReactNode;\n /**\n * Build the node body from a world position. The library assigns\n * the final `id` (so consumer doesn't have to roll their own\n * uniqueness scheme) — return everything except `id`.\n */\n build: (worldPoint: Point2D) => Omit<NodeGraphNode, 'id'>;\n}\n\nexport interface NodeGraphSpawnContext {\n /** World point where the user invoked the palette. */\n worldPoint: Point2D;\n /** Screen-space point (CSS pixels relative to viewport top-left). */\n screenPoint: Point2D;\n}\n\nexport interface NodeGraphSpawnPaletteSlotProps {\n /** All spawn-able templates. Filtering happens inside the library. */\n templates: ReadonlyArray<NodeGraphTemplate>;\n /**\n * Called when the user picks a template. Library has already\n * assigned an `id`; consumer typically appends to their nodes state.\n */\n onSpawn: (node: NodeGraphNode, ctx: NodeGraphSpawnContext) => void;\n /** Placeholder for the search input. */\n placeholder?: string;\n /** localStorage key for the palette's recent list. */\n recentKey?: string;\n /** Popover width. @default 400 */\n width?: number | string;\n /** Popover max height. @default 360 */\n maxHeight?: number;\n}\n\nexport interface NodeGraphToolbarSlotProps {\n /**\n * Anchored corner inside the graph. Defaults to top-left.\n */\n placement?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n /** Distance from the edge, CSS px. @default 12 */\n margin?: number;\n /** Gap between toolbar buttons / children, CSS px. @default 4 */\n gap?: number;\n /** Optional className applied to the toolbar wrapper. */\n className?: string;\n /** Inline style override. */\n style?: React.CSSProperties;\n /** Toolbar contents — typically `<NodeGraph.FitContentButton>` etc. */\n children?: React.ReactNode;\n}\n\nexport interface NodeGraphSlotMarker {\n [NODE_GRAPH_SLOT]: NodeGraphSlotKind;\n}\n\n// ─── Props ───\n\nexport interface NodeGraphBaseProps extends Omit<\n BaseComponent,\n 'onChange' | 'onContextMenu' | 'ref'\n> {\n // ── Nodes (controlled / uncontrolled) ──\n nodes?: NodeGraphNode[];\n defaultNodes?: NodeGraphNode[];\n onNodesChange?: (nodes: NodeGraphNode[]) => void;\n\n // ── Edges (controlled / uncontrolled) ──\n edges?: NodeGraphEdge[];\n defaultEdges?: NodeGraphEdge[];\n onEdgesChange?: (edges: NodeGraphEdge[]) => void;\n\n // ── Groups (controlled / uncontrolled) ──\n groups?: NodeGraphGroup[];\n defaultGroups?: NodeGraphGroup[];\n onGroupsChange?: (groups: NodeGraphGroup[]) => void;\n\n // ── Selection (controlled / uncontrolled) ──\n selection?: NodeGraphSelection;\n defaultSelection?: NodeGraphSelection;\n onSelectionChange?: (selection: NodeGraphSelection) => void;\n\n // ── Rendering ──\n /**\n * Render the body of a node. The returned content sits inside a wrapper\n * `<div>` positioned in world space — do not set position/transform\n * yourself. Declare connection endpoints by placing `<NodeGraph.Port>`\n * children anywhere inside the returned tree; the library tracks their\n * DOM positions automatically and routes edges through them.\n */\n renderNode?: (\n node: NodeGraphNode,\n ctx: NodeGraphRenderCtx\n ) => React.ReactNode;\n /**\n * Render a label above the midpoint of an edge. Receives the edge data.\n * When omitted, `edge.label` is used as-is (if defined).\n */\n renderEdgeLabel?: (edge: NodeGraphEdge) => React.ReactNode;\n /**\n * Per-edge style hook called on every draw frame. The returned shape\n * is shallow-merged into the default edge style; any field left\n * undefined falls back to `edge.color` / theme defaults.\n *\n * The second argument carries resolved port metadata from the store\n * so consumers don't need to maintain a parallel index just to colour\n * wires by their source pin's `dataType`.\n *\n * @example\n * ```tsx\n * <NodeGraph\n * edgeStyle={(edge, ctx) => ({\n * color: TYPE_COLOR[ctx.sourcePort?.dataType ?? 'any'],\n * width: ctx.selected ? 3 : 1.5,\n * })}\n * />\n * ```\n */\n edgeStyle?: NodeGraphEdgeStyleFn;\n\n // ── Interaction ──\n /**\n * Validate a connection between two ports. Return `false` to reject the\n * drop; the preview edge is still drawn while the user is hovering, but\n * styled as invalid.\n */\n isValidConnection?: (\n source: NodeGraphPortRef,\n target: NodeGraphPortRef,\n info: NodeGraphConnectionValidationInfo\n ) => boolean;\n /**\n * Snap node positions to a grid of `snapToGrid` world units. Pass `false`\n * to disable snapping. Affects drag (mouse), not programmatic position\n * updates.\n * @default false\n */\n snapToGrid?: number | false;\n /** Fired when a connection drag starts (pointer-down on a port). */\n onConnectStart?: (info: NodeGraphConnectStartInfo) => void;\n /** Fired when a connection drag ends (drop on a port or cancellation). */\n onConnectEnd?: (info: NodeGraphConnectEndInfo) => void;\n /**\n * Fired on a context menu (right-click) over any part of the graph.\n * Includes a discriminated target so the consumer can render contextual\n * menus for nodes / edges / ports / groups / empty background.\n */\n onContextMenu?: (info: NodeGraphContextMenuInfo) => void;\n /** Fired when Delete/Backspace is pressed with a non-empty selection. */\n onDelete?: (selection: NodeGraphSelection) => void;\n /** Fired when Enter is pressed with a single focused node. */\n onActivate?: (node: NodeGraphNode) => void;\n\n // ── Viewport pass-through ──\n /**\n * Pan gesture configuration, or `false` to disable. Defaults match\n * `<Viewport>`: middle-mouse drag + space-key + left-drag.\n */\n pan?: ViewportPanConfig | false;\n /** Zoom gesture configuration, or `false` to disable. */\n zoom?: ViewportZoomConfig | false;\n /** @default 0.1 */\n minZoom?: number;\n /** @default 4 */\n maxZoom?: number;\n /**\n * Enable marquee selection rectangle. When true, dragging on empty\n * background draws a marquee that selects intersecting nodes.\n * @default true\n */\n selectionRect?: boolean;\n /**\n * Track parent size via `ResizeObserver`. Identical to `<Viewport>`'s\n * `responsive`. @default false\n */\n responsive?: boolean;\n /** Fixed height when not responsive. @default 480 */\n height?: number;\n /**\n * Fallback size used when neither `node.width`/`height` nor the measured\n * DOM size is yet available — for the brief window between mount and\n * first ResizeObserver tick, and for the imperative `fitToContent` /\n * minimap reads at first paint.\n * @default { width: 180, height: 80 }\n */\n defaultNodeSize?: { width: number; height: number };\n /**\n * Disable all interaction and dim the surface.\n * @default false\n */\n disabled?: boolean;\n\n // ── Accessibility ──\n /** @default 'Node graph' */\n ariaLabel?: string;\n\n /** Slot children: `<NodeGraph.Minimap>`, `<NodeGraph.Background>`. */\n children?: React.ReactNode;\n\n /** Imperative handle. */\n ref?: React.Ref<NodeGraphHandle>;\n}\n\nexport type NodeGraphProps = Prettify<NodeGraphBaseProps>;\n\n// ─── Subcomponent props ───\n\n/**\n * Per-node colouring for the minimap. Return `{ color }` for a flat tinted\n * rect, or add `headerColor` for a two-tone \"header strip + body\" mini-node\n * that echoes the real node's look at a glance.\n */\nexport interface NodeGraphMinimapNodeStyle {\n /** Body fill colour. Falls back to the minimap's default item colour. */\n color?: string;\n /** When set, a header strip is drawn on top in this colour (two-tone). */\n headerColor?: string;\n}\n\nexport interface NodeGraphMinimapSlotProps {\n /**\n * Anchored position inside the graph. Matches `ViewportMinimap`'s\n * `placement` (string preset or custom anchor object).\n * @default 'bottom-right'\n */\n placement?:\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right'\n | {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n width?: number | string;\n height?: number | string;\n };\n /** Distance from the edge for preset placements (CSS px). @default 12 */\n margin?: number;\n /** Minimap width in CSS pixels. @default 200 */\n width?: number;\n /** Optional title (rendered as `<Minimap.Title>`). */\n title?: React.ReactNode;\n /** Optional className applied to the minimap wrapper. */\n className?: string;\n /**\n * CSS colour used to highlight selected nodes inside the minimap. When\n * omitted, selected nodes use the same colour as unselected ones.\n */\n selectedColor?: string;\n /**\n * Per-node colouring. Return `{ color }` to tint the rect, or\n * `{ color, headerColor }` to draw a two-tone header/body mini-node that\n * mirrors the real node. When omitted, every node uses the default colour\n * (or `selectedColor` while selected).\n */\n nodeStyle?: (node: NodeGraphNode) => NodeGraphMinimapNodeStyle | undefined;\n}\n\nexport interface NodeGraphBackgroundSlotProps {\n /**\n * Background style. `'dots'` and `'grid'` are built in; pass `'none'`\n * for an opaque background only.\n * @default 'dots'\n */\n variant?: 'dots' | 'grid' | 'none';\n /**\n * Grid spacing in world units. The pattern repeats at this interval\n * regardless of zoom.\n * @default 24\n */\n gap?: number;\n /** Optional dot/line colour. Defaults to theme `border.default`. */\n color?: string;\n /** Optional background colour. Defaults to theme `background.primary`. */\n background?: string;\n}\n"],"names":[],"mappings":"AAwUA;AAEA;;;;AAIG;AACI,MAAM,eAAe,GAAkB,MAAM,CAAC,GAAG,CAAC,qBAAqB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"NodeGraphContext.js","sources":["../../../../../../src/components/editor/NodeGraph/NodeGraphContext.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAaE;AAEF;AACE;;AAEE;;AAIF;AACF;AAEA;;;;AAIG;;;AAGH;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;AAEG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;;"}
1
+ {"version":3,"file":"NodeGraphContext.js","sources":["src/components/editor/NodeGraph/NodeGraphContext.ts"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useSyncExternalStore } from 'react';\n\nimport type { NodeGraphSelection } from './NodeGraph.types';\nimport type {\n NodeGraphDataState,\n NodeGraphHoverState,\n NodeGraphInteractionState,\n NodeGraphStore,\n} from './NodeGraphStore';\n\nexport const NodeGraphStoreContext =\n /*#__PURE__*/ createContext<NodeGraphStore | null>(null);\n\nfunction useStoreInternal(): NodeGraphStore {\n const store = useContext(NodeGraphStoreContext);\n if (!store) {\n throw new Error(\n 'useNodeGraph* hooks must be called inside a <NodeGraph> component'\n );\n }\n return store;\n}\n\n/**\n * Access the underlying `NodeGraphStore` instance — escape hatch for\n * subscribing to custom slice combinations or for imperative reads from\n * non-React code paths (gesture handlers, canvas draw frames).\n */\nexport function useNodeGraphStore(): NodeGraphStore {\n return useStoreInternal();\n}\n\n/**\n * Subscribe to the data slice — re-renders when the graph contents\n * (`nodes`, `edges`, `groups`, default size) change.\n */\nexport function useNodeGraphData(): NodeGraphDataState {\n const store = useStoreInternal();\n return useSyncExternalStore(store.subscribeData, store.getData);\n}\n\n/**\n * Subscribe to the selection slice — re-renders when the selection changes.\n */\nexport function useNodeGraphSelection(): NodeGraphSelection {\n const store = useStoreInternal();\n return useSyncExternalStore(store.subscribeSelection, store.getSelection);\n}\n\n/**\n * Subscribe to the interaction slice — re-renders on gesture lifecycle\n * (drag, connect, marquee) and on per-frame deltas during a drag.\n */\nexport function useNodeGraphInteraction(): NodeGraphInteractionState {\n const store = useStoreInternal();\n return useSyncExternalStore(store.subscribeInteraction, store.getInteraction);\n}\n\n/**\n * Subscribe to the hover slice — re-renders when the hovered node / edge /\n * port changes.\n */\nexport function useNodeGraphHover(): NodeGraphHoverState {\n const store = useStoreInternal();\n return useSyncExternalStore(store.subscribeHover, store.getHover);\n}\n"],"names":[],"mappings":";;;;AAaE;AAEF;AACE;;AAEE;;AAIF;AACF;AAEA;;;;AAIG;;;AAGH;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;AAEG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;AAEA;;;AAGG;;AAED;;AAEF;;"}