@r2digisolutions/components 0.1.6 → 0.2.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 (389) hide show
  1. package/README.md +1 -1
  2. package/dist/components/atoms/Checkbox/Checkbox.svelte +10 -3
  3. package/dist/components/atoms/Checkbox/Checkbox.svelte.d.ts +3 -0
  4. package/dist/components/atoms/IconButton/IconButton.svelte +1 -1
  5. package/dist/components/atoms/Input/Input.svelte +17 -2
  6. package/dist/components/atoms/Input/Input.svelte.d.ts +6 -1
  7. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte +21 -0
  8. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte.d.ts +8 -0
  9. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.stories.js +8 -0
  10. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte +122 -0
  11. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte.d.ts +11 -0
  12. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte +12 -0
  13. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte.d.ts +18 -0
  14. package/dist/components/atoms/PanKnob/PanKnob.stories.d.ts +9 -0
  15. package/dist/components/atoms/PanKnob/PanKnob.stories.js +8 -0
  16. package/dist/components/atoms/PanKnob/PanKnob.svelte +218 -0
  17. package/dist/components/atoms/PanKnob/PanKnob.svelte.d.ts +19 -0
  18. package/dist/components/atoms/PanKnob/PanKnobStory.svelte +15 -0
  19. package/dist/components/atoms/PanKnob/PanKnobStory.svelte.d.ts +3 -0
  20. package/dist/components/atoms/Playhead/Playhead.stories.js +8 -0
  21. package/dist/components/atoms/Playhead/Playhead.svelte +59 -0
  22. package/dist/components/atoms/Playhead/Playhead.svelte.d.ts +13 -0
  23. package/dist/components/atoms/Playhead/PlayheadStory.svelte +9 -0
  24. package/dist/components/atoms/Playhead/PlayheadStory.svelte.d.ts +18 -0
  25. package/dist/components/atoms/Textarea/Textarea.svelte +4 -1
  26. package/dist/components/atoms/Textarea/Textarea.svelte.d.ts +1 -0
  27. package/dist/components/atoms/TimeRuler/TimeRuler.stories.js +8 -0
  28. package/dist/components/atoms/TimeRuler/TimeRuler.svelte +58 -0
  29. package/dist/components/atoms/TimeRuler/TimeRuler.svelte.d.ts +10 -0
  30. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte +7 -0
  31. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte.d.ts +18 -0
  32. package/dist/components/atoms/Toggle/Toggle.svelte +1 -1
  33. package/dist/components/atoms/Tooltip/Tooltip.svelte +1 -1
  34. package/dist/components/atoms/TrimHandle/TrimHandle.stories.js +8 -0
  35. package/dist/components/atoms/TrimHandle/TrimHandle.svelte +63 -0
  36. package/dist/components/atoms/TrimHandle/TrimHandle.svelte.d.ts +12 -0
  37. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte +11 -0
  38. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte.d.ts +18 -0
  39. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.d.ts +9 -0
  40. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.js +8 -0
  41. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte +102 -0
  42. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte.d.ts +20 -0
  43. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte +34 -0
  44. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte.d.ts +3 -0
  45. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +112 -62
  46. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte.d.ts +2 -0
  47. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.stories.js +8 -0
  48. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte +117 -0
  49. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte.d.ts +23 -0
  50. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte +18 -0
  51. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte.d.ts +18 -0
  52. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.stories.js +8 -0
  53. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte +858 -0
  54. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte.d.ts +43 -0
  55. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte +7 -0
  56. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte.d.ts +18 -0
  57. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.d.ts +9 -0
  58. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.js +8 -0
  59. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte +1140 -0
  60. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte.d.ts +28 -0
  61. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte +20 -0
  62. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte.d.ts +3 -0
  63. package/dist/components/molecules/CodeEditor/CodeEditor.svelte +13 -10
  64. package/dist/components/molecules/ColorPicker/ColorPicker.svelte +167 -97
  65. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.d.ts +9 -0
  66. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.js +8 -0
  67. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte +108 -0
  68. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte.d.ts +18 -0
  69. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte +15 -0
  70. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte.d.ts +3 -0
  71. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.d.ts +9 -0
  72. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.js +8 -0
  73. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte +412 -0
  74. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte.d.ts +14 -0
  75. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte +27 -0
  76. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte.d.ts +3 -0
  77. package/dist/components/molecules/ConflictResolver/ConflictResolver.stories.js +8 -0
  78. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte +73 -0
  79. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte.d.ts +16 -0
  80. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte +11 -0
  81. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte.d.ts +18 -0
  82. package/dist/components/molecules/ContextMenu/ContextMenu.svelte +237 -41
  83. package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +17 -1
  84. package/dist/components/molecules/DateTimePicker/DateTimePicker.svelte.d.ts +1 -1
  85. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.d.ts +9 -0
  86. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.js +8 -0
  87. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte +56 -0
  88. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte.d.ts +12 -0
  89. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte +12 -0
  90. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte.d.ts +3 -0
  91. package/dist/components/molecules/FilterList/FilterList.stories.d.ts +9 -0
  92. package/dist/components/molecules/FilterList/FilterList.stories.js +8 -0
  93. package/dist/components/molecules/FilterList/FilterList.svelte +101 -0
  94. package/dist/components/molecules/FilterList/FilterList.svelte.d.ts +18 -0
  95. package/dist/components/molecules/FilterList/FilterListStory.svelte +31 -0
  96. package/dist/components/molecules/FilterList/FilterListStory.svelte.d.ts +3 -0
  97. package/dist/components/molecules/FormDateTimePicker/FormDateTimePicker.svelte.d.ts +1 -1
  98. package/dist/components/molecules/Gauge/Gauge.stories.d.ts +1 -1
  99. package/dist/components/molecules/InfiniteScroll/InfiniteScroll.stories.d.ts +1 -1
  100. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.d.ts +9 -0
  101. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.js +8 -0
  102. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte +94 -0
  103. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte.d.ts +15 -0
  104. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte +18 -0
  105. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte.d.ts +3 -0
  106. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.stories.js +8 -0
  107. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte +50 -0
  108. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte.d.ts +11 -0
  109. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte +13 -0
  110. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte.d.ts +18 -0
  111. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.stories.js +8 -0
  112. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte +380 -0
  113. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte.d.ts +33 -0
  114. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte +14 -0
  115. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte.d.ts +18 -0
  116. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.d.ts +9 -0
  117. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.js +8 -0
  118. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte +399 -0
  119. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte.d.ts +37 -0
  120. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte +24 -0
  121. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte.d.ts +3 -0
  122. package/dist/components/molecules/MediaStage/MediaStage.stories.d.ts +9 -0
  123. package/dist/components/molecules/MediaStage/MediaStage.stories.js +8 -0
  124. package/dist/components/molecules/MediaStage/MediaStage.svelte +1498 -0
  125. package/dist/components/molecules/MediaStage/MediaStage.svelte.d.ts +45 -0
  126. package/dist/components/molecules/MediaStage/MediaStageStory.svelte +35 -0
  127. package/dist/components/molecules/MediaStage/MediaStageStory.svelte.d.ts +3 -0
  128. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.d.ts +9 -0
  129. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.js +8 -0
  130. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte +131 -0
  131. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte.d.ts +19 -0
  132. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte +20 -0
  133. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte.d.ts +3 -0
  134. package/dist/components/molecules/MixerChannel/MixerChannel.stories.d.ts +9 -0
  135. package/dist/components/molecules/MixerChannel/MixerChannel.stories.js +8 -0
  136. package/dist/components/molecules/MixerChannel/MixerChannel.svelte +92 -0
  137. package/dist/components/molecules/MixerChannel/MixerChannel.svelte.d.ts +11 -0
  138. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte +13 -0
  139. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte.d.ts +3 -0
  140. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte +454 -0
  141. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte.d.ts +8 -0
  142. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte +26 -0
  143. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte.d.ts +22 -0
  144. package/dist/components/molecules/NodeGraph/NodeGraph.stories.d.ts +12 -0
  145. package/dist/components/molecules/NodeGraph/NodeGraph.stories.js +9 -0
  146. package/dist/components/molecules/NodeGraph/NodeGraph.svelte +1409 -0
  147. package/dist/components/molecules/NodeGraph/NodeGraph.svelte.d.ts +33 -0
  148. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte +90 -0
  149. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte.d.ts +3 -0
  150. package/dist/components/molecules/NodePalette/NodePalette.stories.js +8 -0
  151. package/dist/components/molecules/NodePalette/NodePalette.svelte +86 -0
  152. package/dist/components/molecules/NodePalette/NodePalette.svelte.d.ts +11 -0
  153. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte +11 -0
  154. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte.d.ts +18 -0
  155. package/dist/components/molecules/Poll/Poll.stories.d.ts +1 -1
  156. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.stories.js +8 -0
  157. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte +72 -0
  158. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte.d.ts +12 -0
  159. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte +16 -0
  160. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte.d.ts +18 -0
  161. package/dist/components/molecules/PropertyField/PropertyField.svelte +57 -3
  162. package/dist/components/molecules/PropertyField/PropertyField.svelte.d.ts +10 -0
  163. package/dist/components/molecules/PropertyField/PropertyFieldStory.svelte +21 -0
  164. package/dist/components/molecules/PropertyGroup/PropertyGroup.svelte +1 -1
  165. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.d.ts +9 -0
  166. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.js +8 -0
  167. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte +52 -0
  168. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte.d.ts +18 -0
  169. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte +62 -0
  170. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte.d.ts +3 -0
  171. package/dist/components/molecules/RelationPicker/RelationPicker.stories.d.ts +9 -0
  172. package/dist/components/molecules/RelationPicker/RelationPicker.stories.js +8 -0
  173. package/dist/components/molecules/RelationPicker/RelationPicker.svelte +180 -0
  174. package/dist/components/molecules/RelationPicker/RelationPicker.svelte.d.ts +24 -0
  175. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte +16 -0
  176. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte.d.ts +3 -0
  177. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.d.ts +9 -0
  178. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.js +8 -0
  179. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte +154 -0
  180. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte.d.ts +12 -0
  181. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte +16 -0
  182. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte.d.ts +3 -0
  183. package/dist/components/molecules/SecretField/SecretField.stories.d.ts +9 -0
  184. package/dist/components/molecules/SecretField/SecretField.stories.js +8 -0
  185. package/dist/components/molecules/SecretField/SecretField.svelte +58 -0
  186. package/dist/components/molecules/SecretField/SecretField.svelte.d.ts +15 -0
  187. package/dist/components/molecules/SecretField/SecretFieldStory.svelte +8 -0
  188. package/dist/components/molecules/SecretField/SecretFieldStory.svelte.d.ts +3 -0
  189. package/dist/components/molecules/SplitPane/SplitPane.svelte +96 -37
  190. package/dist/components/molecules/SplitPane/SplitPane.svelte.d.ts +10 -2
  191. package/dist/components/molecules/TableToolbar/TableToolbar.svelte.d.ts +1 -1
  192. package/dist/components/molecules/Terminal/Terminal.stories.js +20 -0
  193. package/dist/components/molecules/Terminal/Terminal.svelte +238 -0
  194. package/dist/components/molecules/Terminal/Terminal.svelte.d.ts +19 -0
  195. package/dist/components/molecules/Terminal/TerminalStory.svelte +47 -0
  196. package/dist/components/molecules/Terminal/TerminalStory.svelte.d.ts +6 -0
  197. package/dist/components/molecules/TimelineClip/TimelineClip.stories.js +8 -0
  198. package/dist/components/molecules/TimelineClip/TimelineClip.svelte +116 -0
  199. package/dist/components/molecules/TimelineClip/TimelineClip.svelte.d.ts +15 -0
  200. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte +18 -0
  201. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte.d.ts +18 -0
  202. package/dist/components/molecules/TimelineTrack/TimelineTrack.stories.js +8 -0
  203. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte +56 -0
  204. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte.d.ts +16 -0
  205. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte +35 -0
  206. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte.d.ts +18 -0
  207. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.stories.js +8 -0
  208. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte +158 -0
  209. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte.d.ts +18 -0
  210. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte +55 -0
  211. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte.d.ts +18 -0
  212. package/dist/components/molecules/TrackHeader/TrackHeader.stories.d.ts +9 -0
  213. package/dist/components/molecules/TrackHeader/TrackHeader.stories.js +8 -0
  214. package/dist/components/molecules/TrackHeader/TrackHeader.svelte +54 -0
  215. package/dist/components/molecules/TrackHeader/TrackHeader.svelte.d.ts +9 -0
  216. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte +10 -0
  217. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte.d.ts +3 -0
  218. package/dist/components/molecules/TransportControls/TransportControls.stories.d.ts +9 -0
  219. package/dist/components/molecules/TransportControls/TransportControls.stories.js +8 -0
  220. package/dist/components/molecules/TransportControls/TransportControls.svelte +53 -0
  221. package/dist/components/molecules/TransportControls/TransportControls.svelte.d.ts +12 -0
  222. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte +18 -0
  223. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte.d.ts +3 -0
  224. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.stories.js +8 -0
  225. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte +117 -0
  226. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte.d.ts +20 -0
  227. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte +36 -0
  228. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte.d.ts +18 -0
  229. package/dist/components/molecules/VideoPlayer/VideoPlayer.stories.d.ts +1 -1
  230. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.d.ts +9 -0
  231. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.js +8 -0
  232. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte +59 -0
  233. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte.d.ts +9 -0
  234. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte +10 -0
  235. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte.d.ts +3 -0
  236. package/dist/components/molecules/WaveformRegion/WaveformRegion.stories.js +8 -0
  237. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte +82 -0
  238. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte.d.ts +13 -0
  239. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte +17 -0
  240. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte.d.ts +18 -0
  241. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte +13 -4
  242. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte.d.ts +3 -1
  243. package/dist/components/molecules/WidgetCanvas/widgetCanvasContext.d.ts +2 -0
  244. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte +206 -37
  245. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte.d.ts +31 -0
  246. package/dist/components/organisms/AssetPickerPage/AssetPickerPage.svelte.d.ts +1 -1
  247. package/dist/components/organisms/AudioEditor/AudioEditor.stories.d.ts +12 -0
  248. package/dist/components/organisms/AudioEditor/AudioEditor.stories.js +9 -0
  249. package/dist/components/organisms/AudioEditor/AudioEditor.svelte +273 -0
  250. package/dist/components/organisms/AudioEditor/AudioEditor.svelte.d.ts +13 -0
  251. package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte +10 -0
  252. package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte.d.ts +3 -0
  253. package/dist/components/organisms/BacklogPage/BacklogPage.svelte.d.ts +1 -1
  254. package/dist/components/organisms/BlogEditor/BlogEditor.stories.d.ts +12 -0
  255. package/dist/components/organisms/BlogEditor/BlogEditor.stories.js +9 -0
  256. package/dist/components/organisms/BlogEditor/BlogEditor.svelte +1208 -0
  257. package/dist/components/organisms/BlogEditor/BlogEditor.svelte.d.ts +16 -0
  258. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte +144 -0
  259. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte.d.ts +3 -0
  260. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte +28 -0
  261. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte.d.ts +10 -0
  262. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte +34 -0
  263. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte.d.ts +11 -0
  264. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte +13 -0
  265. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte.d.ts +8 -0
  266. package/dist/components/organisms/BlogRenderer/BlogRenderer.stories.js +8 -0
  267. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte +469 -0
  268. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte.d.ts +14 -0
  269. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte +20 -0
  270. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte.d.ts +18 -0
  271. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.d.ts +12 -0
  272. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.js +9 -0
  273. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte +1012 -0
  274. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte.d.ts +16 -0
  275. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte +76 -0
  276. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte.d.ts +3 -0
  277. package/dist/components/organisms/CalendarApp/CalendarApp.svelte.d.ts +1 -1
  278. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.d.ts +12 -0
  279. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.js +9 -0
  280. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte +1680 -0
  281. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte.d.ts +18 -0
  282. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte +329 -0
  283. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte.d.ts +3 -0
  284. package/dist/components/organisms/DashboardBuilderPage/DashboardBuilderPage.svelte.d.ts +1 -1
  285. package/dist/components/organisms/DataGrid/DataGrid.stories.d.ts +65 -0
  286. package/dist/components/organisms/DataGrid/DataGrid.stories.js +95 -0
  287. package/dist/components/organisms/DataGrid/DataGrid.svelte +2264 -0
  288. package/dist/components/organisms/DataGrid/DataGrid.svelte.d.ts +99 -0
  289. package/dist/components/organisms/DataGrid/DataGridStory.svelte +659 -0
  290. package/dist/components/organisms/DataGrid/DataGridStory.svelte.d.ts +11 -0
  291. package/dist/components/organisms/DataGrid/breakpoints.d.ts +10 -0
  292. package/dist/components/organisms/DataGrid/breakpoints.js +20 -0
  293. package/dist/components/organisms/DataGrid/cellEditors.d.ts +8 -0
  294. package/dist/components/organisms/DataGrid/cellEditors.js +59 -0
  295. package/dist/components/organisms/DataGrid/conditionalFormat.d.ts +11 -0
  296. package/dist/components/organisms/DataGrid/conditionalFormat.js +98 -0
  297. package/dist/components/organisms/DataGrid/filterRows.d.ts +5 -0
  298. package/dist/components/organisms/DataGrid/filterRows.js +60 -0
  299. package/dist/components/organisms/DataGrid/marks.d.ts +9 -0
  300. package/dist/components/organisms/DataGrid/marks.js +91 -0
  301. package/dist/components/organisms/DataGrid/types.d.ts +126 -0
  302. package/dist/components/organisms/DataGrid/types.js +21 -0
  303. package/dist/components/organisms/DesktopShell/DesktopShell.svelte.d.ts +1 -1
  304. package/dist/components/organisms/EditorShell/EditorShell.svelte +123 -28
  305. package/dist/components/organisms/EditorShell/EditorShell.svelte.d.ts +21 -1
  306. package/dist/components/organisms/FileUploader/FileUploader.svelte +77 -15
  307. package/dist/components/organisms/FileUploader/FileUploader.svelte.d.ts +11 -0
  308. package/dist/components/organisms/ImportWizard/ImportWizard.stories.js +8 -0
  309. package/dist/components/organisms/ImportWizard/ImportWizard.svelte +209 -0
  310. package/dist/components/organisms/ImportWizard/ImportWizard.svelte.d.ts +22 -0
  311. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte +16 -0
  312. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte.d.ts +18 -0
  313. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.d.ts +33 -0
  314. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.js +56 -0
  315. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte +830 -0
  316. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte.d.ts +68 -0
  317. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte +600 -0
  318. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte.d.ts +7 -0
  319. package/dist/components/organisms/ResourceStudio/fieldsToColumns.d.ts +4 -0
  320. package/dist/components/organisms/ResourceStudio/fieldsToColumns.js +20 -0
  321. package/dist/components/organisms/ResourceStudio/fieldsToSchema.d.ts +6 -0
  322. package/dist/components/organisms/ResourceStudio/fieldsToSchema.js +53 -0
  323. package/dist/components/organisms/ResourceStudio/types.d.ts +69 -0
  324. package/dist/components/organisms/ResourceStudio/types.js +15 -0
  325. package/dist/components/organisms/Scheduler/Scheduler.svelte.d.ts +1 -1
  326. package/dist/components/organisms/SchemaForm/SchemaForm.svelte +10 -3
  327. package/dist/components/organisms/SchemaForm/SchemaForm.svelte.d.ts +1 -0
  328. package/dist/components/organisms/VideoEditor/VideoEditor.stories.d.ts +12 -0
  329. package/dist/components/organisms/VideoEditor/VideoEditor.stories.js +9 -0
  330. package/dist/components/organisms/VideoEditor/VideoEditor.svelte +308 -0
  331. package/dist/components/organisms/VideoEditor/VideoEditor.svelte.d.ts +13 -0
  332. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte +10 -0
  333. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte.d.ts +3 -0
  334. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.d.ts +12 -0
  335. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.js +9 -0
  336. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte +22 -0
  337. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte.d.ts +13 -0
  338. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte +8 -0
  339. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte.d.ts +3 -0
  340. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.d.ts +12 -0
  341. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.js +9 -0
  342. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte +32 -0
  343. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte.d.ts +17 -0
  344. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte +21 -0
  345. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte.d.ts +3 -0
  346. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.d.ts +25 -0
  347. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.js +18 -0
  348. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte +192 -0
  349. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte.d.ts +62 -0
  350. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte +129 -0
  351. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte.d.ts +7 -0
  352. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.d.ts +12 -0
  353. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.js +9 -0
  354. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte +22 -0
  355. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte.d.ts +13 -0
  356. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte +8 -0
  357. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte.d.ts +3 -0
  358. package/dist/index.d.ts +94 -1
  359. package/dist/index.js +68 -0
  360. package/dist/types/xyflow-svelte.d.ts +62 -0
  361. package/dist/utils/audioProject.d.ts +19 -0
  362. package/dist/utils/audioProject.js +70 -0
  363. package/dist/utils/blogDocument.d.ts +175 -0
  364. package/dist/utils/blogDocument.js +220 -0
  365. package/dist/utils/blueprintRuntime.d.ts +34 -0
  366. package/dist/utils/blueprintRuntime.js +289 -0
  367. package/dist/utils/canvasDocument.d.ts +239 -0
  368. package/dist/utils/canvasDocument.js +443 -0
  369. package/dist/utils/canvasExport.d.ts +10 -0
  370. package/dist/utils/canvasExport.js +469 -0
  371. package/dist/utils/canvasHierarchy.d.ts +189 -0
  372. package/dist/utils/canvasHierarchy.js +674 -0
  373. package/dist/utils/canvasHistory.d.ts +19 -0
  374. package/dist/utils/canvasHistory.js +48 -0
  375. package/dist/utils/canvasWidget.d.ts +81 -0
  376. package/dist/utils/canvasWidget.js +597 -0
  377. package/dist/utils/marqueeSelect.d.ts +48 -0
  378. package/dist/utils/marqueeSelect.js +189 -0
  379. package/dist/utils/mediaTime.d.ts +16 -0
  380. package/dist/utils/mediaTime.js +57 -0
  381. package/dist/utils/mediaTracks.d.ts +61 -0
  382. package/dist/utils/mediaTracks.js +102 -0
  383. package/dist/utils/nodeGraph.d.ts +354 -0
  384. package/dist/utils/nodeGraph.js +1453 -0
  385. package/dist/utils/queryBridge.d.ts +18 -0
  386. package/dist/utils/queryBridge.js +118 -0
  387. package/dist/utils/videoSequence.d.ts +13 -0
  388. package/dist/utils/videoSequence.js +63 -0
  389. package/package.json +5 -2
@@ -0,0 +1,1453 @@
1
+ /**
2
+ * Node graph helpers — Blueprint-style typed pins, edges, validation.
3
+ */
4
+ export const DEFAULT_NODE_WIDTH = 220;
5
+ export const DEFAULT_NODE_HEIGHT = 80;
6
+ export const PORT_SIZE = 12;
7
+ /** Half of the pin glyph — wire starts/ends at the rim of the circle/play icon. */
8
+ export const EDGE_PORT_PAD = PORT_SIZE / 2;
9
+ /** SVG marker tip length (viewBox units ≈ user units with markerWidth 8). */
10
+ export const EDGE_ARROW_LENGTH = 8;
11
+ export const PIN_TYPE_COLORS = {
12
+ exec: '#e2e8f0',
13
+ bool: '#ef4444',
14
+ int: '#22c55e',
15
+ float: '#86efac',
16
+ string: '#a855f7',
17
+ object: '#38bdf8',
18
+ any: '#94a3b8'
19
+ };
20
+ export function pinColor(port) {
21
+ const dt = port.dataType ?? (port.kind === 'exec' ? 'exec' : 'any');
22
+ return PIN_TYPE_COLORS[dt] ?? PIN_TYPE_COLORS.any;
23
+ }
24
+ function execPort(id, label, side, offset) {
25
+ return { id, label, side, offset, kind: 'exec', dataType: 'exec' };
26
+ }
27
+ function dataPort(id, label, dataType, side, offset) {
28
+ return { id, label, side, offset, kind: 'data', dataType };
29
+ }
30
+ export const DEFAULT_NODE_TYPES = [
31
+ {
32
+ type: 'trigger',
33
+ label: 'Trigger',
34
+ category: 'Events',
35
+ description: 'Starts the flow',
36
+ color: '#10b981',
37
+ inputs: [],
38
+ outputs: [execPort('exec', 'Then', 'right')]
39
+ },
40
+ {
41
+ type: 'action',
42
+ label: 'Action',
43
+ category: 'Actions',
44
+ description: 'Do something',
45
+ color: '#3b82f6',
46
+ inputs: [execPort('exec_in', 'Exec', 'left')],
47
+ outputs: [execPort('exec', 'Then', 'right')]
48
+ },
49
+ {
50
+ type: 'condition',
51
+ label: 'Branch',
52
+ category: 'Flow',
53
+ description: 'Branch on a boolean',
54
+ color: '#f59e0b',
55
+ height: 96,
56
+ inputs: [
57
+ execPort('exec_in', 'Exec', 'left', 0.28),
58
+ dataPort('condition', 'Condition', 'bool', 'left', 0.72)
59
+ ],
60
+ outputs: [
61
+ execPort('true', 'True', 'right', 0.32),
62
+ execPort('false', 'False', 'right', 0.68)
63
+ ]
64
+ },
65
+ {
66
+ type: 'transform',
67
+ label: 'Transform',
68
+ category: 'Actions',
69
+ description: 'Map data then continue',
70
+ color: '#8b5cf6',
71
+ height: 96,
72
+ inputs: [
73
+ execPort('exec_in', 'Exec', 'left', 0.28),
74
+ dataPort('in', 'In', 'any', 'left', 0.72)
75
+ ],
76
+ outputs: [
77
+ execPort('exec', 'Then', 'right', 0.28),
78
+ dataPort('out', 'Out', 'any', 'right', 0.72)
79
+ ]
80
+ },
81
+ {
82
+ type: 'delay',
83
+ label: 'Delay',
84
+ category: 'Flow',
85
+ description: 'Wait before continuing',
86
+ color: '#64748b',
87
+ inputs: [
88
+ execPort('exec_in', 'Exec', 'left', 0.3),
89
+ dataPort('seconds', 'Seconds', 'float', 'left', 0.7)
90
+ ],
91
+ outputs: [execPort('exec', 'Then', 'right')]
92
+ },
93
+ {
94
+ type: 'end',
95
+ label: 'End',
96
+ category: 'Flow',
97
+ description: 'Terminal step',
98
+ color: '#ef4444',
99
+ inputs: [execPort('exec_in', 'Exec', 'left')],
100
+ outputs: []
101
+ },
102
+ {
103
+ type: 'get_string',
104
+ label: 'Get String',
105
+ category: 'Functions',
106
+ description: 'Pure data — no exec pins',
107
+ color: '#a855f7',
108
+ width: 168,
109
+ height: 56,
110
+ inputs: [],
111
+ outputs: [dataPort('value', 'Return', 'string', 'right')],
112
+ defaultData: { label: '"Hello"' }
113
+ },
114
+ {
115
+ type: 'format_string',
116
+ label: 'Format String',
117
+ category: 'Functions',
118
+ description: 'Pure function — data in/out only',
119
+ color: '#a855f7',
120
+ height: 88,
121
+ inputs: [
122
+ dataPort('template', 'Template', 'string', 'left', 0.35),
123
+ dataPort('value', 'Value', 'any', 'left', 0.7)
124
+ ],
125
+ outputs: [dataPort('out', 'Result', 'string', 'right')]
126
+ },
127
+ {
128
+ type: 'to_bool',
129
+ label: 'To Bool',
130
+ category: 'Functions',
131
+ description: 'Cast / coerce to boolean',
132
+ color: '#ef4444',
133
+ width: 160,
134
+ height: 56,
135
+ inputs: [dataPort('in', 'In', 'any', 'left')],
136
+ outputs: [dataPort('out', 'Out', 'bool', 'right')]
137
+ },
138
+ {
139
+ type: 'comment',
140
+ label: 'Comment',
141
+ category: 'Utility',
142
+ description: 'Annotation box',
143
+ color: '#fbbf24',
144
+ width: 220,
145
+ height: 100,
146
+ inputs: [],
147
+ outputs: [],
148
+ defaultData: { label: 'Comment', commentColor: 'rgba(251, 191, 36, 0.25)' }
149
+ },
150
+ {
151
+ type: 'reroute',
152
+ label: 'Reroute',
153
+ category: 'Utility',
154
+ description: 'Wire knot / pass-through',
155
+ color: '#94a3b8',
156
+ width: 16,
157
+ height: 16,
158
+ hidden: true,
159
+ inputs: [dataPort('in', '', 'any', 'left')],
160
+ outputs: [dataPort('out', '', 'any', 'right')]
161
+ },
162
+ {
163
+ type: 'collapsed_graph',
164
+ label: 'Collapsed Graph',
165
+ category: 'Utility',
166
+ description: 'Collapsed selection (expand with E)',
167
+ color: '#7c3aed',
168
+ width: 220,
169
+ height: 72,
170
+ hidden: true,
171
+ inputs: [execPort('exec_in', 'Exec', 'left')],
172
+ outputs: [execPort('exec', 'Then', 'right')],
173
+ defaultData: { label: 'Collapsed Graph' }
174
+ }
175
+ ];
176
+ /** Unreal-inspired blueprint catalog */
177
+ export const DEFAULT_BLUEPRINT_NODE_TYPES = [
178
+ {
179
+ type: 'event_begin',
180
+ label: 'Event BeginPlay',
181
+ category: 'Events',
182
+ color: '#dc2626',
183
+ contexts: ['event_graph'],
184
+ inputs: [],
185
+ outputs: [execPort('exec', 'Then', 'right')],
186
+ defaultData: { label: 'Event BeginPlay' }
187
+ },
188
+ {
189
+ type: 'event_tick',
190
+ label: 'Event Tick',
191
+ category: 'Events',
192
+ color: '#dc2626',
193
+ contexts: ['event_graph'],
194
+ height: 88,
195
+ inputs: [],
196
+ outputs: [
197
+ execPort('exec', 'Then', 'right'),
198
+ dataPort('delta', 'Delta Seconds', 'float', 'right')
199
+ ],
200
+ defaultData: { label: 'Event Tick' }
201
+ },
202
+ {
203
+ type: 'branch',
204
+ label: 'Branch',
205
+ category: 'Flow Control',
206
+ color: '#64748b',
207
+ contexts: ['event_graph', 'function_graph', 'macro_graph'],
208
+ width: 240,
209
+ height: 88,
210
+ inputs: [
211
+ execPort('exec_in', 'Exec', 'left'),
212
+ dataPort('condition', 'Condition', 'bool', 'left')
213
+ ],
214
+ outputs: [execPort('true', 'True', 'right'), execPort('false', 'False', 'right')]
215
+ },
216
+ {
217
+ type: 'delay_bp',
218
+ label: 'Delay',
219
+ category: 'Flow Control',
220
+ color: '#64748b',
221
+ contexts: ['event_graph', 'function_graph'],
222
+ width: 240,
223
+ height: 88,
224
+ inputs: [
225
+ execPort('exec_in', 'Exec', 'left'),
226
+ dataPort('duration', 'Duration', 'float', 'left')
227
+ ],
228
+ outputs: [
229
+ execPort('completed', 'Completed', 'right'),
230
+ execPort('aborted', 'Aborted', 'right')
231
+ ]
232
+ },
233
+ {
234
+ type: 'print_string',
235
+ label: 'Print String',
236
+ category: 'Utilities',
237
+ color: '#0ea5e9',
238
+ contexts: ['event_graph', 'function_graph', 'macro_graph'],
239
+ width: 250,
240
+ height: 110,
241
+ inputs: [
242
+ execPort('exec_in', 'Exec', 'left'),
243
+ dataPort('in_string', 'In String', 'string', 'left'),
244
+ dataPort('duration', 'Duration', 'float', 'left')
245
+ ],
246
+ outputs: [execPort('exec', 'Then', 'right')]
247
+ },
248
+ {
249
+ type: 'make_string',
250
+ label: 'Make Literal String',
251
+ category: 'Utilities',
252
+ color: '#a855f7',
253
+ contexts: ['event_graph', 'function_graph', 'macro_graph', 'construction_script'],
254
+ width: 180,
255
+ height: 56,
256
+ inputs: [],
257
+ outputs: [dataPort('value', 'Return', 'string', 'right')],
258
+ defaultData: { label: '"Hello"' }
259
+ },
260
+ {
261
+ type: 'return_node',
262
+ label: 'Return Node',
263
+ category: 'Flow Control',
264
+ color: '#dc2626',
265
+ contexts: ['function_graph'],
266
+ description: 'Only available inside function graphs',
267
+ inputs: [execPort('exec_in', 'Exec', 'left')],
268
+ outputs: []
269
+ },
270
+ {
271
+ type: 'construction_add',
272
+ label: 'Add Component',
273
+ category: 'Components',
274
+ color: '#f97316',
275
+ contexts: ['construction_script'],
276
+ description: 'Only available in Construction Script',
277
+ inputs: [execPort('exec_in', 'Exec', 'left')],
278
+ outputs: [execPort('exec', 'Then', 'right'), dataPort('component', 'Component', 'object', 'right')]
279
+ },
280
+ {
281
+ type: 'comment',
282
+ label: 'Comment',
283
+ category: 'Utility',
284
+ color: '#fbbf24',
285
+ width: 240,
286
+ height: 110,
287
+ inputs: [],
288
+ outputs: [],
289
+ defaultData: { label: 'Comment', commentColor: 'rgba(251, 191, 36, 0.28)' }
290
+ },
291
+ {
292
+ type: 'reroute',
293
+ label: 'Reroute',
294
+ category: 'Utility',
295
+ description: 'Wire knot / pass-through',
296
+ color: '#94a3b8',
297
+ width: 16,
298
+ height: 16,
299
+ hidden: true,
300
+ inputs: [dataPort('in', '', 'any', 'left')],
301
+ outputs: [dataPort('out', '', 'any', 'right')]
302
+ },
303
+ {
304
+ type: 'collapsed_graph',
305
+ label: 'Collapsed Graph',
306
+ category: 'Utility',
307
+ description: 'Collapsed selection (expand with E)',
308
+ color: '#7c3aed',
309
+ width: 220,
310
+ height: 72,
311
+ hidden: true,
312
+ inputs: [execPort('exec_in', 'Exec', 'left')],
313
+ outputs: [execPort('exec', 'Then', 'right')],
314
+ defaultData: { label: 'Collapsed Graph' }
315
+ },
316
+ /** Templates for dynamic variable nodes (hidden from palette). */
317
+ {
318
+ type: 'var_get',
319
+ label: 'Get',
320
+ category: 'Variables',
321
+ hidden: true,
322
+ width: 160,
323
+ height: 52,
324
+ inputs: [],
325
+ outputs: [dataPort('value', '', 'any', 'right')]
326
+ },
327
+ {
328
+ type: 'var_set',
329
+ label: 'Set',
330
+ category: 'Variables',
331
+ hidden: true,
332
+ height: 72,
333
+ inputs: [execPort('exec_in', 'Exec', 'left'), dataPort('value', '', 'any', 'left')],
334
+ outputs: [execPort('exec', 'Then', 'right'), dataPort('out', '', 'any', 'right')]
335
+ }
336
+ ];
337
+ export function emptyGraphDocument() {
338
+ return { version: 1, nodes: [], edges: [] };
339
+ }
340
+ function uid(prefix) {
341
+ return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
342
+ }
343
+ export function resolveNodeType(type, catalog = DEFAULT_NODE_TYPES) {
344
+ return catalog.find((t) => t.type === type);
345
+ }
346
+ export function defaultPortsForType(type, catalog = DEFAULT_NODE_TYPES) {
347
+ const def = resolveNodeType(type, catalog);
348
+ if (def) {
349
+ return {
350
+ inputs: (def.inputs ?? []).map((p) => ({ ...p })),
351
+ outputs: (def.outputs ?? []).map((p) => ({ ...p }))
352
+ };
353
+ }
354
+ return {
355
+ inputs: [execPort('exec_in', 'Exec', 'left')],
356
+ outputs: [execPort('exec', 'Then', 'right')]
357
+ };
358
+ }
359
+ export function createGraphNode(partial, catalog = DEFAULT_NODE_TYPES) {
360
+ const def = resolveNodeType(partial.type, catalog);
361
+ const ports = defaultPortsForType(partial.type, catalog);
362
+ return {
363
+ id: partial.id ?? uid('n'),
364
+ type: partial.type,
365
+ x: partial.x,
366
+ y: partial.y,
367
+ width: partial.width ?? def?.width ?? DEFAULT_NODE_WIDTH,
368
+ height: partial.height ?? def?.height ?? DEFAULT_NODE_HEIGHT,
369
+ data: {
370
+ label: def?.label ?? partial.type,
371
+ color: def?.color,
372
+ ...(def?.defaultData ?? {}),
373
+ ...(partial.data ?? {})
374
+ },
375
+ inputs: partial.inputs ?? ports.inputs,
376
+ outputs: partial.outputs ?? ports.outputs
377
+ };
378
+ }
379
+ /** Duplicate nodes (+ internal edges), like UE Blueprint Ctrl+W / duplicate. */
380
+ export function duplicateGraphSelection(doc, nodeIds, opts) {
381
+ const idSet = new Set(nodeIds);
382
+ const sources = doc.nodes.filter((n) => idSet.has(n.id));
383
+ if (!sources.length)
384
+ return { doc, newNodeIds: [] };
385
+ const dx = opts?.offsetX ?? 32;
386
+ const dy = opts?.offsetY ?? 32;
387
+ const idMap = new Map();
388
+ const clones = sources.map((n) => {
389
+ const id = uid('n');
390
+ idMap.set(n.id, id);
391
+ return {
392
+ ...n,
393
+ id,
394
+ x: n.x + dx,
395
+ y: n.y + dy,
396
+ inputs: n.inputs?.map((p) => ({ ...p })),
397
+ outputs: n.outputs?.map((p) => ({ ...p })),
398
+ data: n.data ? { ...n.data } : undefined
399
+ };
400
+ });
401
+ const edgeClones = doc.edges
402
+ .filter((e) => idSet.has(e.source) && idSet.has(e.target))
403
+ .map((e) => ({
404
+ ...e,
405
+ id: uid('e'),
406
+ source: idMap.get(e.source),
407
+ target: idMap.get(e.target)
408
+ }));
409
+ return {
410
+ doc: {
411
+ ...doc,
412
+ nodes: [...doc.nodes, ...clones],
413
+ edges: [...doc.edges, ...edgeClones]
414
+ },
415
+ newNodeIds: clones.map((n) => n.id)
416
+ };
417
+ }
418
+ export function cloneGraphDocument(doc) {
419
+ return JSON.parse(JSON.stringify(doc));
420
+ }
421
+ export const GRAPH_CLIPBOARD_MIME = 'application/x-r2-graph-fragment';
422
+ export function extractGraphSelection(doc, nodeIds) {
423
+ const idSet = new Set(nodeIds);
424
+ const nodes = doc.nodes
425
+ .filter((n) => idSet.has(n.id))
426
+ .map((n) => ({
427
+ ...n,
428
+ inputs: n.inputs?.map((p) => ({ ...p })),
429
+ outputs: n.outputs?.map((p) => ({ ...p })),
430
+ data: n.data ? { ...n.data } : undefined
431
+ }));
432
+ const edges = doc.edges
433
+ .filter((e) => idSet.has(e.source) && idSet.has(e.target))
434
+ .map((e) => ({ ...e }));
435
+ return { version: 1, nodes, edges };
436
+ }
437
+ export function encodeGraphClipboard(fragment) {
438
+ const payload = {
439
+ mime: GRAPH_CLIPBOARD_MIME,
440
+ version: 1,
441
+ fragment: cloneGraphDocument(fragment)
442
+ };
443
+ return JSON.stringify(payload);
444
+ }
445
+ export function decodeGraphClipboard(raw) {
446
+ try {
447
+ const parsed = JSON.parse(raw);
448
+ if (parsed &&
449
+ typeof parsed === 'object' &&
450
+ 'mime' in parsed &&
451
+ parsed.mime === GRAPH_CLIPBOARD_MIME &&
452
+ parsed.fragment) {
453
+ return cloneGraphDocument(parsed.fragment);
454
+ }
455
+ if (parsed && typeof parsed === 'object' && 'nodes' in parsed && Array.isArray(parsed.nodes)) {
456
+ return cloneGraphDocument(parsed);
457
+ }
458
+ }
459
+ catch {
460
+ /* ignore */
461
+ }
462
+ return null;
463
+ }
464
+ export function pasteGraphSelection(doc, fragment, opts) {
465
+ if (!fragment.nodes.length)
466
+ return { doc, newNodeIds: [] };
467
+ const dx = opts?.offsetX ?? 40;
468
+ const dy = opts?.offsetY ?? 40;
469
+ let ox = 0;
470
+ let oy = 0;
471
+ if (opts?.origin) {
472
+ const minX = Math.min(...fragment.nodes.map((n) => n.x));
473
+ const minY = Math.min(...fragment.nodes.map((n) => n.y));
474
+ ox = opts.origin.x - minX;
475
+ oy = opts.origin.y - minY;
476
+ }
477
+ else {
478
+ ox = dx;
479
+ oy = dy;
480
+ }
481
+ const idMap = new Map();
482
+ const clones = fragment.nodes.map((n) => {
483
+ const id = uid('n');
484
+ idMap.set(n.id, id);
485
+ return {
486
+ ...n,
487
+ id,
488
+ x: n.x + ox,
489
+ y: n.y + oy,
490
+ inputs: n.inputs?.map((p) => ({ ...p })),
491
+ outputs: n.outputs?.map((p) => ({ ...p })),
492
+ data: n.data ? { ...n.data } : undefined
493
+ };
494
+ });
495
+ const edgeClones = fragment.edges
496
+ .filter((e) => idMap.has(e.source) && idMap.has(e.target))
497
+ .map((e) => ({
498
+ ...e,
499
+ id: uid('e'),
500
+ source: idMap.get(e.source),
501
+ target: idMap.get(e.target)
502
+ }));
503
+ return {
504
+ doc: {
505
+ ...doc,
506
+ nodes: [...doc.nodes, ...clones],
507
+ edges: [...doc.edges, ...edgeClones]
508
+ },
509
+ newNodeIds: clones.map((n) => n.id)
510
+ };
511
+ }
512
+ export function alignGraphNodes(doc, nodeIds, align) {
513
+ const idSet = new Set(nodeIds);
514
+ const targets = doc.nodes.filter((n) => idSet.has(n.id) && n.type !== 'comment');
515
+ if (targets.length < 2)
516
+ return doc;
517
+ const boxes = targets.map((n) => {
518
+ const { w, h } = nodeSize(n);
519
+ return { n, w, h, cx: n.x + w / 2, cy: n.y + h / 2, r: n.x + w, b: n.y + h };
520
+ });
521
+ let anchor = 0;
522
+ switch (align) {
523
+ case 'left':
524
+ anchor = Math.min(...boxes.map((b) => b.n.x));
525
+ break;
526
+ case 'right':
527
+ anchor = Math.max(...boxes.map((b) => b.r));
528
+ break;
529
+ case 'top':
530
+ anchor = Math.min(...boxes.map((b) => b.n.y));
531
+ break;
532
+ case 'bottom':
533
+ anchor = Math.max(...boxes.map((b) => b.b));
534
+ break;
535
+ case 'centerX':
536
+ anchor = boxes.reduce((s, b) => s + b.cx, 0) / boxes.length;
537
+ break;
538
+ case 'centerY':
539
+ anchor = boxes.reduce((s, b) => s + b.cy, 0) / boxes.length;
540
+ break;
541
+ }
542
+ const nextPos = new Map();
543
+ for (const b of boxes) {
544
+ let x = b.n.x;
545
+ let y = b.n.y;
546
+ if (align === 'left')
547
+ x = anchor;
548
+ else if (align === 'right')
549
+ x = anchor - b.w;
550
+ else if (align === 'centerX')
551
+ x = anchor - b.w / 2;
552
+ else if (align === 'top')
553
+ y = anchor;
554
+ else if (align === 'bottom')
555
+ y = anchor - b.h;
556
+ else if (align === 'centerY')
557
+ y = anchor - b.h / 2;
558
+ nextPos.set(b.n.id, { x, y });
559
+ }
560
+ return {
561
+ ...doc,
562
+ nodes: doc.nodes.map((n) => {
563
+ const p = nextPos.get(n.id);
564
+ return p ? { ...n, x: p.x, y: p.y } : n;
565
+ })
566
+ };
567
+ }
568
+ export function distributeGraphNodes(doc, nodeIds, axis) {
569
+ const idSet = new Set(nodeIds);
570
+ const targets = doc.nodes.filter((n) => idSet.has(n.id) && n.type !== 'comment');
571
+ if (targets.length < 3)
572
+ return doc;
573
+ const sorted = [...targets].sort((a, b) => (axis === 'horizontal' ? a.x - b.x : a.y - b.y));
574
+ const first = sorted[0];
575
+ const last = sorted[sorted.length - 1];
576
+ const { w: lw, h: lh } = nodeSize(last);
577
+ const start = axis === 'horizontal' ? first.x : first.y;
578
+ const end = axis === 'horizontal' ? last.x + lw : last.y + lh;
579
+ const totalSize = sorted.reduce((s, n) => {
580
+ const { w, h } = nodeSize(n);
581
+ return s + (axis === 'horizontal' ? w : h);
582
+ }, 0);
583
+ const gap = (end - start - totalSize) / (sorted.length - 1);
584
+ const nextPos = new Map();
585
+ let cursor = start;
586
+ for (const n of sorted) {
587
+ const { w, h } = nodeSize(n);
588
+ if (axis === 'horizontal')
589
+ nextPos.set(n.id, { x: cursor, y: n.y });
590
+ else
591
+ nextPos.set(n.id, { x: n.x, y: cursor });
592
+ cursor += (axis === 'horizontal' ? w : h) + gap;
593
+ }
594
+ return {
595
+ ...doc,
596
+ nodes: doc.nodes.map((n) => {
597
+ const p = nextPos.get(n.id);
598
+ return p ? { ...n, x: p.x, y: p.y } : n;
599
+ })
600
+ };
601
+ }
602
+ export function selectionBounds(doc, nodeIds, padding = 24) {
603
+ const idSet = new Set(nodeIds);
604
+ const nodes = doc.nodes.filter((n) => idSet.has(n.id));
605
+ if (!nodes.length)
606
+ return null;
607
+ let minX = Infinity;
608
+ let minY = Infinity;
609
+ let maxX = -Infinity;
610
+ let maxY = -Infinity;
611
+ for (const n of nodes) {
612
+ const { w, h } = nodeSize(n);
613
+ minX = Math.min(minX, n.x);
614
+ minY = Math.min(minY, n.y);
615
+ maxX = Math.max(maxX, n.x + w);
616
+ maxY = Math.max(maxY, n.y + h);
617
+ }
618
+ return {
619
+ x: minX - padding,
620
+ y: minY - padding,
621
+ width: maxX - minX + padding * 2,
622
+ height: maxY - minY + padding * 2
623
+ };
624
+ }
625
+ export function createCommentFromSelection(doc, nodeIds, opts) {
626
+ const bounds = selectionBounds(doc, nodeIds, 28);
627
+ if (!bounds)
628
+ return null;
629
+ const comment = {
630
+ id: uid('n'),
631
+ type: 'comment',
632
+ x: bounds.x,
633
+ y: bounds.y,
634
+ width: Math.max(180, bounds.width),
635
+ height: Math.max(80, bounds.height),
636
+ data: {
637
+ label: opts?.label ?? 'Comment',
638
+ commentColor: 'rgba(251, 191, 36, 0.18)',
639
+ memberIds: [...nodeIds]
640
+ },
641
+ inputs: [],
642
+ outputs: []
643
+ };
644
+ return {
645
+ doc: { ...doc, nodes: [comment, ...doc.nodes] },
646
+ commentId: comment.id
647
+ };
648
+ }
649
+ export function createRerouteNode(pos, port) {
650
+ const kind = port.kind ?? (port.dataType === 'exec' ? 'exec' : 'data');
651
+ const dataType = (port.dataType ?? (kind === 'exec' ? 'exec' : 'any'));
652
+ return {
653
+ id: uid('n'),
654
+ type: 'reroute',
655
+ x: pos.x - 8,
656
+ y: pos.y - 8,
657
+ width: 16,
658
+ height: 16,
659
+ data: {
660
+ label: 'Reroute',
661
+ pinKind: kind,
662
+ pinDataType: dataType,
663
+ color: kind === 'exec' ? '#94a3b8' : pinColor({ id: 'p', kind, dataType })
664
+ },
665
+ inputs: [{ id: 'in', label: '', side: 'left', kind, dataType }],
666
+ outputs: [{ id: 'out', label: '', side: 'right', kind, dataType }]
667
+ };
668
+ }
669
+ export function insertRerouteOnEdge(doc, edgeId, pos) {
670
+ const edge = doc.edges.find((e) => e.id === edgeId);
671
+ if (!edge)
672
+ return null;
673
+ const source = doc.nodes.find((n) => n.id === edge.source);
674
+ const out = source?.outputs?.find((p) => p.id === (edge.sourceHandle ?? p.id)) ??
675
+ source?.outputs?.[0];
676
+ const port = out ?? { kind: 'data', dataType: 'any' };
677
+ const reroute = createRerouteNode(pos, port);
678
+ const left = {
679
+ id: uid('e'),
680
+ source: edge.source,
681
+ target: reroute.id,
682
+ sourceHandle: edge.sourceHandle,
683
+ targetHandle: 'in',
684
+ label: edge.label
685
+ };
686
+ const right = {
687
+ id: uid('e'),
688
+ source: reroute.id,
689
+ target: edge.target,
690
+ sourceHandle: 'out',
691
+ targetHandle: edge.targetHandle
692
+ };
693
+ return {
694
+ doc: {
695
+ ...doc,
696
+ nodes: [...doc.nodes, reroute],
697
+ edges: [...doc.edges.filter((e) => e.id !== edgeId), left, right]
698
+ },
699
+ rerouteId: reroute.id
700
+ };
701
+ }
702
+ export function breakLinksAtHandle(doc, nodeId, handleId, handleType) {
703
+ if (!handleId) {
704
+ return {
705
+ ...doc,
706
+ edges: doc.edges.filter((e) => handleType === 'source'
707
+ ? e.source !== nodeId
708
+ : handleType === 'target'
709
+ ? e.target !== nodeId
710
+ : e.source !== nodeId && e.target !== nodeId)
711
+ };
712
+ }
713
+ return {
714
+ ...doc,
715
+ edges: doc.edges.filter((e) => {
716
+ if (handleType === 'source' || handleType == null) {
717
+ if (e.source === nodeId && (e.sourceHandle ?? '') === handleId)
718
+ return false;
719
+ }
720
+ if (handleType === 'target' || handleType == null) {
721
+ if (e.target === nodeId && (e.targetHandle ?? '') === handleId)
722
+ return false;
723
+ }
724
+ return true;
725
+ })
726
+ };
727
+ }
728
+ export function collapseSelectionToFunction(doc, nodeIds, opts) {
729
+ const idSet = new Set(nodeIds.filter((id) => doc.nodes.some((n) => n.id === id)));
730
+ const members = doc.nodes.filter((n) => idSet.has(n.id) && n.type !== 'comment' && n.type !== 'collapsed_graph');
731
+ if (members.length < 1)
732
+ return null;
733
+ const memberIds = new Set(members.map((n) => n.id));
734
+ const internalEdges = doc.edges.filter((e) => memberIds.has(e.source) && memberIds.has(e.target));
735
+ const incoming = doc.edges.filter((e) => memberIds.has(e.target) && !memberIds.has(e.source));
736
+ const outgoing = doc.edges.filter((e) => memberIds.has(e.source) && !memberIds.has(e.target));
737
+ const inputs = [];
738
+ const outputs = [];
739
+ const inMap = [];
740
+ const outMap = [];
741
+ incoming.forEach((edge, i) => {
742
+ const target = members.find((n) => n.id === edge.target);
743
+ const port = target?.inputs?.find((p) => p.id === (edge.targetHandle ?? p.id)) ??
744
+ target?.inputs?.[0];
745
+ const pinId = `in_${i}`;
746
+ inputs.push({
747
+ id: pinId,
748
+ label: port?.label ?? `In ${i + 1}`,
749
+ side: 'left',
750
+ kind: port?.kind ?? 'data',
751
+ dataType: port?.dataType ?? 'any'
752
+ });
753
+ inMap.push({ edge, pinId });
754
+ });
755
+ outgoing.forEach((edge, i) => {
756
+ const source = members.find((n) => n.id === edge.source);
757
+ const port = source?.outputs?.find((p) => p.id === (edge.sourceHandle ?? p.id)) ??
758
+ source?.outputs?.[0];
759
+ const pinId = `out_${i}`;
760
+ outputs.push({
761
+ id: pinId,
762
+ label: port?.label ?? `Out ${i + 1}`,
763
+ side: 'right',
764
+ kind: port?.kind ?? 'data',
765
+ dataType: port?.dataType ?? 'any'
766
+ });
767
+ outMap.push({ edge, pinId });
768
+ });
769
+ if (!inputs.length)
770
+ inputs.push(execPort('exec_in', 'Exec', 'left'));
771
+ if (!outputs.length)
772
+ outputs.push(execPort('exec', 'Then', 'right'));
773
+ const bounds = selectionBounds(doc, [...memberIds], 0);
774
+ const collapsed = {
775
+ id: uid('n'),
776
+ type: 'collapsed_graph',
777
+ x: bounds ? bounds.x + bounds.width / 2 - 110 : members[0].x,
778
+ y: bounds ? bounds.y + bounds.height / 2 - 36 : members[0].y,
779
+ width: 220,
780
+ height: Math.max(72, 40 + Math.max(inputs.length, outputs.length) * 22),
781
+ data: {
782
+ label: opts?.label ?? `Collapsed (${members.length})`,
783
+ color: '#7c3aed',
784
+ collapsedGraph: {
785
+ version: 1,
786
+ nodes: members.map((n) => ({
787
+ ...n,
788
+ inputs: n.inputs?.map((p) => ({ ...p })),
789
+ outputs: n.outputs?.map((p) => ({ ...p })),
790
+ data: n.data ? { ...n.data } : undefined
791
+ })),
792
+ edges: internalEdges.map((e) => ({ ...e }))
793
+ },
794
+ boundaryIn: inMap.map(({ edge, pinId }) => ({
795
+ pinId,
796
+ innerNodeId: edge.target,
797
+ innerHandle: edge.targetHandle
798
+ })),
799
+ boundaryOut: outMap.map(({ edge, pinId }) => ({
800
+ pinId,
801
+ innerNodeId: edge.source,
802
+ innerHandle: edge.sourceHandle
803
+ }))
804
+ },
805
+ inputs,
806
+ outputs
807
+ };
808
+ const rewired = [
809
+ ...inMap.map(({ edge, pinId }) => ({
810
+ id: uid('e'),
811
+ source: edge.source,
812
+ target: collapsed.id,
813
+ sourceHandle: edge.sourceHandle,
814
+ targetHandle: pinId
815
+ })),
816
+ ...outMap.map(({ edge, pinId }) => ({
817
+ id: uid('e'),
818
+ source: collapsed.id,
819
+ target: edge.target,
820
+ sourceHandle: pinId,
821
+ targetHandle: edge.targetHandle
822
+ }))
823
+ ];
824
+ const keepEdges = doc.edges.filter((e) => !memberIds.has(e.source) && !memberIds.has(e.target));
825
+ return {
826
+ doc: {
827
+ ...doc,
828
+ nodes: [...doc.nodes.filter((n) => !memberIds.has(n.id)), collapsed],
829
+ edges: [...keepEdges, ...rewired]
830
+ },
831
+ collapsedId: collapsed.id
832
+ };
833
+ }
834
+ export function expandCollapsedGraph(doc, nodeId) {
835
+ const node = doc.nodes.find((n) => n.id === nodeId && n.type === 'collapsed_graph');
836
+ if (!node)
837
+ return null;
838
+ const subgraph = node.data?.collapsedGraph;
839
+ if (!subgraph?.nodes?.length)
840
+ return null;
841
+ const idMap = new Map();
842
+ const clones = subgraph.nodes.map((n) => {
843
+ const id = uid('n');
844
+ idMap.set(n.id, id);
845
+ return {
846
+ ...n,
847
+ id,
848
+ x: n.x,
849
+ y: n.y,
850
+ inputs: n.inputs?.map((p) => ({ ...p })),
851
+ outputs: n.outputs?.map((p) => ({ ...p })),
852
+ data: n.data ? { ...n.data } : undefined
853
+ };
854
+ });
855
+ const internal = (subgraph.edges ?? []).map((e) => ({
856
+ ...e,
857
+ id: uid('e'),
858
+ source: idMap.get(e.source),
859
+ target: idMap.get(e.target)
860
+ }));
861
+ const boundaryIn = node.data?.boundaryIn ?? [];
862
+ const boundaryOut = node.data?.boundaryOut ?? [];
863
+ const external = doc.edges.filter((e) => e.source !== nodeId && e.target !== nodeId);
864
+ const restoredIn = doc.edges
865
+ .filter((e) => e.target === nodeId)
866
+ .map((e) => {
867
+ const b = boundaryIn.find((x) => x.pinId === (e.targetHandle ?? x.pinId));
868
+ const inner = b ? idMap.get(b.innerNodeId) : clones[0]?.id;
869
+ if (!inner)
870
+ return null;
871
+ return {
872
+ id: uid('e'),
873
+ source: e.source,
874
+ target: inner,
875
+ sourceHandle: e.sourceHandle,
876
+ targetHandle: b?.innerHandle
877
+ };
878
+ })
879
+ .filter(Boolean);
880
+ const restoredOut = doc.edges
881
+ .filter((e) => e.source === nodeId)
882
+ .map((e) => {
883
+ const b = boundaryOut.find((x) => x.pinId === (e.sourceHandle ?? x.pinId));
884
+ const inner = b ? idMap.get(b.innerNodeId) : clones[clones.length - 1]?.id;
885
+ if (!inner)
886
+ return null;
887
+ return {
888
+ id: uid('e'),
889
+ source: inner,
890
+ target: e.target,
891
+ sourceHandle: b?.innerHandle,
892
+ targetHandle: e.targetHandle
893
+ };
894
+ })
895
+ .filter(Boolean);
896
+ return {
897
+ doc: {
898
+ ...doc,
899
+ nodes: [...doc.nodes.filter((n) => n.id !== nodeId), ...clones],
900
+ edges: [...external, ...internal, ...restoredIn, ...restoredOut]
901
+ },
902
+ newNodeIds: clones.map((n) => n.id)
903
+ };
904
+ }
905
+ export function createGraphEdge(source, target, opts) {
906
+ return {
907
+ id: opts?.id ?? uid('e'),
908
+ source,
909
+ target,
910
+ label: opts?.label,
911
+ sourceHandle: opts?.sourceHandle ?? 'exec',
912
+ targetHandle: opts?.targetHandle ?? 'exec_in'
913
+ };
914
+ }
915
+ export function serializeGraphDocument(doc) {
916
+ return JSON.stringify(doc, null, 2);
917
+ }
918
+ export function parseGraphDocument(raw) {
919
+ if (typeof raw !== 'string')
920
+ return normalizeGraph(raw);
921
+ try {
922
+ return normalizeGraph(JSON.parse(raw));
923
+ }
924
+ catch {
925
+ return emptyGraphDocument();
926
+ }
927
+ }
928
+ function normalizeGraph(input) {
929
+ if (!input || typeof input !== 'object')
930
+ return emptyGraphDocument();
931
+ const obj = input;
932
+ const nodes = Array.isArray(obj.nodes)
933
+ ? obj.nodes.filter((n) => !!n &&
934
+ typeof n === 'object' &&
935
+ typeof n.id === 'string' &&
936
+ typeof n.type === 'string')
937
+ : [];
938
+ const edges = Array.isArray(obj.edges)
939
+ ? obj.edges.filter((e) => !!e &&
940
+ typeof e === 'object' &&
941
+ typeof e.id === 'string' &&
942
+ typeof e.source === 'string' &&
943
+ typeof e.target === 'string')
944
+ : [];
945
+ return { version: 1, nodes, edges };
946
+ }
947
+ export function removeNode(doc, nodeId) {
948
+ return {
949
+ ...doc,
950
+ nodes: doc.nodes.filter((n) => n.id !== nodeId),
951
+ edges: doc.edges.filter((e) => e.source !== nodeId && e.target !== nodeId)
952
+ };
953
+ }
954
+ export function removeEdge(doc, edgeId) {
955
+ return { ...doc, edges: doc.edges.filter((e) => e.id !== edgeId) };
956
+ }
957
+ export function updateNodePosition(doc, nodeId, x, y) {
958
+ return {
959
+ ...doc,
960
+ nodes: doc.nodes.map((n) => (n.id === nodeId ? { ...n, x, y } : n))
961
+ };
962
+ }
963
+ export function nodeSize(node, fallbackW = DEFAULT_NODE_WIDTH, fallbackH = DEFAULT_NODE_HEIGHT) {
964
+ return { w: node.width ?? fallbackW, h: node.height ?? fallbackH };
965
+ }
966
+ export function nodeCenter(node, width, height) {
967
+ const { w, h } = nodeSize(node, width, height);
968
+ return { x: node.x + w / 2, y: node.y + h / 2 };
969
+ }
970
+ function portOffset(port, index, total) {
971
+ if (typeof port.offset === 'number')
972
+ return Math.min(1, Math.max(0, port.offset));
973
+ if (total <= 1)
974
+ return 0.5;
975
+ return (index + 1) / (total + 1);
976
+ }
977
+ export function portPosition(node, port, kind, index = 0, total = 1, fallbackW = DEFAULT_NODE_WIDTH, fallbackH = DEFAULT_NODE_HEIGHT) {
978
+ const { w, h } = nodeSize(node, fallbackW, fallbackH);
979
+ const side = port.side ?? (kind === 'input' ? 'left' : 'right');
980
+ const t = portOffset(port, index, total);
981
+ switch (side) {
982
+ case 'left':
983
+ return { x: node.x, y: node.y + h * t };
984
+ case 'right':
985
+ return { x: node.x + w, y: node.y + h * t };
986
+ case 'top':
987
+ return { x: node.x + w * t, y: node.y };
988
+ case 'bottom':
989
+ return { x: node.x + w * t, y: node.y + h };
990
+ default:
991
+ return { x: node.x + w, y: node.y + h / 2 };
992
+ }
993
+ }
994
+ export function findPort(node, handleId, kind) {
995
+ const list = kind === 'input' ? (node.inputs ?? []) : (node.outputs ?? []);
996
+ if (!list.length)
997
+ return null;
998
+ const index = handleId ? list.findIndex((p) => p.id === handleId) : 0;
999
+ const i = index >= 0 ? index : 0;
1000
+ return { port: list[i], index: i, total: list.length };
1001
+ }
1002
+ export function edgeEndpoints(doc, edge, fallbackW = DEFAULT_NODE_WIDTH, fallbackH = DEFAULT_NODE_HEIGHT) {
1003
+ const source = doc.nodes.find((n) => n.id === edge.source);
1004
+ const target = doc.nodes.find((n) => n.id === edge.target);
1005
+ if (!source || !target)
1006
+ return null;
1007
+ const out = findPort(source, edge.sourceHandle, 'output');
1008
+ const inn = findPort(target, edge.targetHandle, 'input');
1009
+ const from = out
1010
+ ? portPosition(source, out.port, 'output', out.index, out.total, fallbackW, fallbackH)
1011
+ : {
1012
+ x: source.x + nodeSize(source, fallbackW, fallbackH).w,
1013
+ y: source.y + nodeSize(source, fallbackW, fallbackH).h / 2
1014
+ };
1015
+ const to = inn
1016
+ ? portPosition(target, inn.port, 'input', inn.index, inn.total, fallbackW, fallbackH)
1017
+ : { x: target.x, y: target.y + nodeSize(target, fallbackW, fallbackH).h / 2 };
1018
+ return { from, to };
1019
+ }
1020
+ /** Offset a port-center point along its side normal (away from the node). */
1021
+ export function offsetPortPoint(point, side, distance) {
1022
+ switch (side) {
1023
+ case 'left':
1024
+ return { x: point.x - distance, y: point.y };
1025
+ case 'right':
1026
+ return { x: point.x + distance, y: point.y };
1027
+ case 'top':
1028
+ return { x: point.x, y: point.y - distance };
1029
+ case 'bottom':
1030
+ return { x: point.x, y: point.y + distance };
1031
+ default:
1032
+ return { x: point.x + distance, y: point.y };
1033
+ }
1034
+ }
1035
+ export function isExecPort(port) {
1036
+ return (port.kind ?? port.dataType) === 'exec' || port.dataType === 'exec';
1037
+ }
1038
+ export function isDataPort(port) {
1039
+ return !isExecPort(port);
1040
+ }
1041
+ export function formatPortLiteral(port) {
1042
+ if (port.value == null)
1043
+ return '';
1044
+ if (typeof port.value === 'boolean')
1045
+ return port.value ? 'true' : 'false';
1046
+ return String(port.value);
1047
+ }
1048
+ export function parsePortLiteral(port, raw) {
1049
+ const dt = port.dataType ?? 'any';
1050
+ if (dt === 'bool') {
1051
+ const v = raw.trim().toLowerCase();
1052
+ if (v === 'true' || v === '1' || v === 'yes')
1053
+ return true;
1054
+ if (v === 'false' || v === '0' || v === 'no' || v === '')
1055
+ return false;
1056
+ return Boolean(raw);
1057
+ }
1058
+ if (dt === 'int') {
1059
+ const n = parseInt(raw, 10);
1060
+ return Number.isFinite(n) ? n : 0;
1061
+ }
1062
+ if (dt === 'float') {
1063
+ const n = parseFloat(raw);
1064
+ return Number.isFinite(n) ? n : 0;
1065
+ }
1066
+ if (dt === 'object') {
1067
+ const t = raw.trim();
1068
+ if (!t || t === 'null')
1069
+ return null;
1070
+ try {
1071
+ return JSON.parse(t);
1072
+ }
1073
+ catch {
1074
+ return t;
1075
+ }
1076
+ }
1077
+ return raw;
1078
+ }
1079
+ export function defaultPortLiteral(port) {
1080
+ if (port.value !== undefined)
1081
+ return port.value;
1082
+ const dt = port.dataType ?? 'any';
1083
+ switch (dt) {
1084
+ case 'bool':
1085
+ return false;
1086
+ case 'int':
1087
+ return 0;
1088
+ case 'float':
1089
+ return 0;
1090
+ case 'string':
1091
+ return '';
1092
+ case 'object':
1093
+ return null;
1094
+ default:
1095
+ return '';
1096
+ }
1097
+ }
1098
+ /** Map nodeId → input handle ids that have an incoming edge. */
1099
+ export function wiredInputIdsByNode(edges) {
1100
+ const map = new Map();
1101
+ for (const e of edges) {
1102
+ const handle = e.targetHandle ?? 'exec_in';
1103
+ if (!map.has(e.target))
1104
+ map.set(e.target, new Set());
1105
+ map.get(e.target).add(handle);
1106
+ }
1107
+ return map;
1108
+ }
1109
+ /** Bezier with endpoints on the pin rim along the side normal (not the chord). */
1110
+ export function edgePathForPorts(from, to, opts) {
1111
+ const fromSide = opts?.fromSide ?? 'right';
1112
+ const toSide = opts?.toSide ?? 'left';
1113
+ const padStart = opts?.padStart ?? EDGE_PORT_PAD;
1114
+ /** Tip of the marker sits on the path end — stop at pin rim. */
1115
+ const padEnd = opts?.padEnd ?? EDGE_PORT_PAD;
1116
+ const curvature = opts?.curvature ?? 0.45;
1117
+ const a = offsetPortPoint(from, fromSide, padStart);
1118
+ const b = offsetPortPoint(to, toSide, padEnd);
1119
+ return edgePathFromPoints(a, b, curvature);
1120
+ }
1121
+ /** True if the type exposes at least one input pin compatible with `source`. */
1122
+ export function nodeTypeAcceptsPort(typeDef, source) {
1123
+ return (typeDef.inputs ?? []).some((p) => pinsCompatible(source, p));
1124
+ }
1125
+ export function firstCompatibleInput(node, source) {
1126
+ return (node.inputs ?? []).find((p) => pinsCompatible(source, p)) ?? null;
1127
+ }
1128
+ export function edgePathFromPoints(from, to, curvature = 0.45) {
1129
+ const dx = Math.abs(to.x - from.x);
1130
+ const dy = Math.abs(to.y - from.y);
1131
+ const offset = Math.max(40, Math.min(dx * curvature, 180));
1132
+ if (dx >= dy * 0.4) {
1133
+ const c1x = from.x + offset;
1134
+ const c2x = to.x - offset;
1135
+ return `M ${from.x} ${from.y} C ${c1x} ${from.y}, ${c2x} ${to.y}, ${to.x} ${to.y}`;
1136
+ }
1137
+ const c1y = from.y + offset;
1138
+ const c2y = to.y - offset;
1139
+ return `M ${from.x} ${from.y} C ${from.x} ${c1y}, ${to.x} ${c2y}, ${to.x} ${to.y}`;
1140
+ }
1141
+ export function pinsCompatible(source, target) {
1142
+ const sk = source.kind ?? (source.dataType === 'exec' ? 'exec' : 'data');
1143
+ const tk = target.kind ?? (target.dataType === 'exec' ? 'exec' : 'data');
1144
+ if (sk !== tk)
1145
+ return false;
1146
+ if (sk === 'exec')
1147
+ return true;
1148
+ const st = source.dataType ?? 'any';
1149
+ const tt = target.dataType ?? 'any';
1150
+ if (st === 'any' || tt === 'any')
1151
+ return true;
1152
+ return st === tt;
1153
+ }
1154
+ export function validateGraph(doc) {
1155
+ const issues = [];
1156
+ for (const edge of doc.edges) {
1157
+ const source = doc.nodes.find((n) => n.id === edge.source);
1158
+ const target = doc.nodes.find((n) => n.id === edge.target);
1159
+ if (!source || !target) {
1160
+ issues.push({
1161
+ id: `missing-${edge.id}`,
1162
+ level: 'error',
1163
+ message: `Edge ${edge.id} references missing node`,
1164
+ edgeId: edge.id
1165
+ });
1166
+ continue;
1167
+ }
1168
+ const out = findPort(source, edge.sourceHandle, 'output');
1169
+ const inn = findPort(target, edge.targetHandle, 'input');
1170
+ if (!out || !inn) {
1171
+ issues.push({
1172
+ id: `port-${edge.id}`,
1173
+ level: 'error',
1174
+ message: `Edge ${edge.id} has invalid handles`,
1175
+ edgeId: edge.id
1176
+ });
1177
+ continue;
1178
+ }
1179
+ if (!pinsCompatible(out.port, inn.port)) {
1180
+ issues.push({
1181
+ id: `type-${edge.id}`,
1182
+ level: 'error',
1183
+ message: `Incompatible pins: ${out.port.dataType ?? out.port.kind} → ${inn.port.dataType ?? inn.port.kind}`,
1184
+ edgeId: edge.id
1185
+ });
1186
+ }
1187
+ }
1188
+ for (const node of doc.nodes) {
1189
+ if (node.type === 'comment' || node.type === 'reroute' || node.type === 'collapsed_graph')
1190
+ continue;
1191
+ const hasExecOut = (node.outputs ?? []).some((p) => (p.kind ?? p.dataType) === 'exec' || p.dataType === 'exec');
1192
+ const hasExecIn = (node.inputs ?? []).some((p) => (p.kind ?? p.dataType) === 'exec' || p.dataType === 'exec');
1193
+ // Entry/event nodes with no continuation — not sinks like Print/Delay (Then unused is fine).
1194
+ if (hasExecOut && !hasExecIn && !doc.edges.some((e) => e.source === node.id)) {
1195
+ issues.push({
1196
+ id: `orphan-out-${node.id}`,
1197
+ level: 'warning',
1198
+ message: `Node "${node.data?.label ?? node.type}" has no outgoing exec wire`,
1199
+ nodeId: node.id
1200
+ });
1201
+ }
1202
+ if (hasExecIn && !doc.edges.some((e) => e.target === node.id)) {
1203
+ issues.push({
1204
+ id: `orphan-in-${node.id}`,
1205
+ level: 'warning',
1206
+ message: `Node "${node.data?.label ?? node.type}" has no incoming wire`,
1207
+ nodeId: node.id
1208
+ });
1209
+ }
1210
+ }
1211
+ return issues;
1212
+ }
1213
+ export function snap(value, grid) {
1214
+ if (grid <= 1)
1215
+ return value;
1216
+ return Math.round(value / grid) * grid;
1217
+ }
1218
+ export function fitView(nodes, viewport, padding = 48, fallbackW = DEFAULT_NODE_WIDTH, fallbackH = DEFAULT_NODE_HEIGHT) {
1219
+ if (!nodes.length)
1220
+ return { pan: { x: 0, y: 0 }, scale: 1 };
1221
+ let minX = Infinity;
1222
+ let minY = Infinity;
1223
+ let maxX = -Infinity;
1224
+ let maxY = -Infinity;
1225
+ for (const n of nodes) {
1226
+ const { w, h } = nodeSize(n, fallbackW, fallbackH);
1227
+ minX = Math.min(minX, n.x);
1228
+ minY = Math.min(minY, n.y);
1229
+ maxX = Math.max(maxX, n.x + w);
1230
+ maxY = Math.max(maxY, n.y + h);
1231
+ }
1232
+ const bw = maxX - minX || 1;
1233
+ const bh = maxY - minY || 1;
1234
+ const scale = Math.min(2, Math.max(0.35, Math.min((viewport.width - padding * 2) / bw, (viewport.height - padding * 2) / bh)));
1235
+ return {
1236
+ pan: {
1237
+ x: (viewport.width - bw * scale) / 2 - minX * scale,
1238
+ y: (viewport.height - bh * scale) / 2 - minY * scale
1239
+ },
1240
+ scale
1241
+ };
1242
+ }
1243
+ export function groupNodeTypesByCategory(types) {
1244
+ const map = new Map();
1245
+ for (const t of types) {
1246
+ const cat = t.category ?? 'Other';
1247
+ if (!map.has(cat))
1248
+ map.set(cat, []);
1249
+ map.get(cat).push(t);
1250
+ }
1251
+ return [...map.entries()].map(([category, list]) => ({ category, types: list }));
1252
+ }
1253
+ export function nodeTypeAllowedInContext(type, context) {
1254
+ if (!context)
1255
+ return true;
1256
+ if (!type.contexts?.length)
1257
+ return true;
1258
+ return type.contexts.includes(context);
1259
+ }
1260
+ /** Palette / place-menu catalog: context + hide templates. */
1261
+ export function filterNodeTypesForGraph(types, opts) {
1262
+ return types.filter((t) => {
1263
+ if (!opts?.includeHidden && t.hidden)
1264
+ return false;
1265
+ return nodeTypeAllowedInContext(t, opts?.context);
1266
+ });
1267
+ }
1268
+ export function variablePinColor(dataType) {
1269
+ return PIN_TYPE_COLORS[dataType] ?? PIN_TYPE_COLORS.any;
1270
+ }
1271
+ export function defaultValueForPinType(dataType) {
1272
+ switch (dataType) {
1273
+ case 'bool':
1274
+ return false;
1275
+ case 'int':
1276
+ return 0;
1277
+ case 'float':
1278
+ return 0;
1279
+ case 'string':
1280
+ return '';
1281
+ case 'object':
1282
+ return null;
1283
+ default:
1284
+ return undefined;
1285
+ }
1286
+ }
1287
+ export function createVarGetNode(variable, pos) {
1288
+ const color = variablePinColor(variable.dataType);
1289
+ const w = Math.max(148, variable.name.length * 8 + 56);
1290
+ return {
1291
+ id: uid('n'),
1292
+ type: 'var_get',
1293
+ x: pos.x,
1294
+ y: pos.y,
1295
+ width: w,
1296
+ height: 52,
1297
+ data: {
1298
+ label: variable.name,
1299
+ color,
1300
+ variableId: variable.id,
1301
+ variableName: variable.name,
1302
+ access: 'get'
1303
+ },
1304
+ inputs: [],
1305
+ outputs: [dataPort('value', '', variable.dataType, 'right')]
1306
+ };
1307
+ }
1308
+ export function createVarSetNode(variable, pos) {
1309
+ const color = variablePinColor(variable.dataType);
1310
+ const w = Math.max(168, variable.name.length * 8 + 72);
1311
+ return {
1312
+ id: uid('n'),
1313
+ type: 'var_set',
1314
+ x: pos.x,
1315
+ y: pos.y,
1316
+ width: w,
1317
+ height: 72,
1318
+ data: {
1319
+ label: `Set ${variable.name}`,
1320
+ color,
1321
+ variableId: variable.id,
1322
+ variableName: variable.name,
1323
+ access: 'set'
1324
+ },
1325
+ inputs: [
1326
+ execPort('exec_in', 'Exec', 'left'),
1327
+ dataPort('value', variable.name, variable.dataType, 'left')
1328
+ ],
1329
+ outputs: [
1330
+ execPort('exec', 'Then', 'right'),
1331
+ dataPort('out', '', variable.dataType, 'right')
1332
+ ]
1333
+ };
1334
+ }
1335
+ /** Place-menu entries for Get/Set of each blueprint variable. */
1336
+ export function variablePlaceItems(variables) {
1337
+ const items = [];
1338
+ for (const v of variables) {
1339
+ const color = variablePinColor(v.dataType);
1340
+ items.push({
1341
+ id: `get:${v.id}`,
1342
+ kind: 'get',
1343
+ variable: v,
1344
+ label: `Get ${v.name}`,
1345
+ color
1346
+ });
1347
+ items.push({
1348
+ id: `set:${v.id}`,
1349
+ kind: 'set',
1350
+ variable: v,
1351
+ label: `Set ${v.name}`,
1352
+ color
1353
+ });
1354
+ }
1355
+ return items;
1356
+ }
1357
+ export function emptyBlueprintDocument(name = 'New Blueprint') {
1358
+ return { version: 1, name, graph: emptyGraphDocument(), variables: [] };
1359
+ }
1360
+ export function toFlowNodes(doc, catalog = DEFAULT_NODE_TYPES, selectedIds = []) {
1361
+ const selected = new Set(selectedIds);
1362
+ // Comments first so they paint under other nodes when z-index ties.
1363
+ const ordered = [
1364
+ ...doc.nodes.filter((n) => n.type === 'comment'),
1365
+ ...doc.nodes.filter((n) => n.type !== 'comment')
1366
+ ];
1367
+ return ordered.map((n) => {
1368
+ const def = resolveNodeType(n.type, catalog);
1369
+ const { w, h } = nodeSize(n);
1370
+ const isComment = n.type === 'comment';
1371
+ return {
1372
+ id: n.id,
1373
+ type: 'blueprint',
1374
+ position: { x: n.x, y: n.y },
1375
+ selected: selected.has(n.id),
1376
+ width: w,
1377
+ height: h,
1378
+ zIndex: isComment ? -1 : 1,
1379
+ class: isComment ? 'bp-flow-comment' : undefined,
1380
+ data: {
1381
+ ...(n.data ?? {}),
1382
+ graphType: n.type,
1383
+ label: n.data?.label ?? def?.label ?? n.type,
1384
+ description: n.data?.description,
1385
+ color: n.data?.color ?? def?.color,
1386
+ commentColor: n.data?.commentColor,
1387
+ memberIds: Array.isArray(n.data?.memberIds)
1388
+ ? [...n.data.memberIds]
1389
+ : undefined,
1390
+ inputs: (n.inputs ?? []).map((p) => ({ ...p })),
1391
+ outputs: (n.outputs ?? []).map((p) => ({ ...p })),
1392
+ width: n.width ?? def?.width,
1393
+ height: n.height ?? def?.height
1394
+ }
1395
+ };
1396
+ });
1397
+ }
1398
+ export function toFlowEdges(doc, selectedIds = []) {
1399
+ const selected = new Set(selectedIds);
1400
+ return doc.edges.map((e) => ({
1401
+ id: e.id,
1402
+ source: e.source,
1403
+ target: e.target,
1404
+ sourceHandle: e.sourceHandle ?? null,
1405
+ targetHandle: e.targetHandle ?? null,
1406
+ label: e.label,
1407
+ selected: selected.has(e.id)
1408
+ }));
1409
+ }
1410
+ export function fromFlowNodes(nodes) {
1411
+ return nodes.map((n) => {
1412
+ const { graphType, inputs, outputs, width, height, _alert: _a, _wiredInputs: _w, _onLiteral: _o, ...rest } = n.data;
1413
+ return {
1414
+ id: n.id,
1415
+ type: graphType,
1416
+ x: n.position.x,
1417
+ y: n.position.y,
1418
+ width: width ?? n.width,
1419
+ height: height ?? n.height,
1420
+ data: { ...rest },
1421
+ inputs: (inputs ?? []).map((p) => ({ ...p })),
1422
+ outputs: (outputs ?? []).map((p) => ({ ...p }))
1423
+ };
1424
+ });
1425
+ }
1426
+ export function fromFlowEdges(edges) {
1427
+ return edges.map((e) => ({
1428
+ id: e.id,
1429
+ source: e.source,
1430
+ target: e.target,
1431
+ sourceHandle: e.sourceHandle ?? undefined,
1432
+ targetHandle: e.targetHandle ?? undefined,
1433
+ label: typeof e.label === 'string' ? e.label : undefined
1434
+ }));
1435
+ }
1436
+ export function flowDocumentFromFlow(nodes, edges) {
1437
+ return {
1438
+ version: 1,
1439
+ nodes: fromFlowNodes(nodes),
1440
+ edges: fromFlowEdges(edges)
1441
+ };
1442
+ }
1443
+ /** Resolve a port on a flow node by handle id + direction. */
1444
+ export function flowPortOnNode(node, handleId, kind) {
1445
+ if (!node)
1446
+ return null;
1447
+ const list = kind === 'input' ? node.data.inputs : node.data.outputs;
1448
+ if (!list?.length)
1449
+ return null;
1450
+ if (!handleId)
1451
+ return list[0] ?? null;
1452
+ return list.find((p) => p.id === handleId) ?? null;
1453
+ }