@likec4/diagram 1.45.0 → 1.46.2

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 (206) hide show
  1. package/bundle/index.js +2488 -1959
  2. package/dist/LikeC4Diagram.d.ts +1 -1
  3. package/dist/LikeC4Diagram.js +8 -7
  4. package/dist/LikeC4Diagram.props.d.ts +4 -12
  5. package/dist/LikeC4ProjectsProvider.js +8 -4
  6. package/dist/LikeC4View.js +1 -5
  7. package/dist/ReactLikeC4.d.ts +1 -4
  8. package/dist/StaticLikeC4Diagram.js +0 -2
  9. package/dist/base-primitives/NodeHandles.d.ts +2 -1
  10. package/dist/base-primitives/NodeHandles.js +22 -18
  11. package/dist/base-primitives/compound/CompoundActionButton.js +1 -1
  12. package/dist/base-primitives/compound/CompoundDetailsButton.js +1 -1
  13. package/dist/base-primitives/edge/EdgeActionButton.js +1 -1
  14. package/dist/base-primitives/edge/EdgeContainer.d.ts +1 -1
  15. package/dist/base-primitives/edge/EdgeContainer.js +2 -3
  16. package/dist/base-primitives/edge/EdgeLabel.js +16 -16
  17. package/dist/base-primitives/edge/EdgeLabelContainer.d.ts +1 -1
  18. package/dist/base-primitives/edge/EdgeLabelContainer.js +5 -4
  19. package/dist/base-primitives/edge/EdgePath.js +13 -18
  20. package/dist/base-primitives/element/ElementActionButtons.js +1 -1
  21. package/dist/base-primitives/element/ElementDetailsButton.js +1 -1
  22. package/dist/base-primitives/memoNode.js +1 -1
  23. package/dist/components/ErrorFallback.js +1 -1
  24. package/dist/components/Link.js +2 -2
  25. package/dist/context/DiagramEventHandlers.js +0 -1
  26. package/dist/context/DiagramFeatures.d.ts +1 -1
  27. package/dist/context/DiagramFeatures.js +1 -0
  28. package/dist/context/EnsureMantine.js +2 -1
  29. package/dist/context/IconRenderer.js +6 -6
  30. package/dist/editor/LikeC4EditorProvider.d.ts +22 -0
  31. package/dist/editor/LikeC4EditorProvider.js +12 -0
  32. package/dist/editor/__tests__/fixture.d.ts +205 -0
  33. package/dist/editor/applyChangesToManualLayout.d.ts +8 -0
  34. package/dist/editor/applyChangesToManualLayout.js +182 -0
  35. package/dist/editor/editorActor.actions.d.ts +201 -0
  36. package/dist/editor/editorActor.actions.js +149 -0
  37. package/dist/editor/editorActor.d.ts +653 -0
  38. package/dist/editor/editorActor.js +324 -0
  39. package/dist/editor/hotkeyActor.d.ts +7 -0
  40. package/dist/editor/hotkeyActor.js +19 -0
  41. package/dist/editor/index.d.ts +3 -2
  42. package/dist/editor/useEditorActorLogic.d.ts +565 -0
  43. package/dist/editor/useEditorActorLogic.js +54 -0
  44. package/dist/hooks/safeContext.d.ts +3 -2
  45. package/dist/hooks/safeContext.js +7 -4
  46. package/dist/hooks/useDiagram.d.ts +4 -2
  47. package/dist/hooks/useDiagram.js +19 -8
  48. package/dist/hooks/useDiagramCompareLayout.d.ts +8 -0
  49. package/dist/hooks/useDiagramCompareLayout.js +22 -2
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +1 -0
  52. package/dist/likec4diagram/DiagramXYFlow.js +1 -2
  53. package/dist/likec4diagram/custom/edges/EdgeDrifts.js +1 -5
  54. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +74 -48
  55. package/dist/likec4diagram/custom/edges/edges.css.d.ts +0 -1
  56. package/dist/likec4diagram/custom/edges/edges.css.js +30 -24
  57. package/dist/likec4diagram/custom/edges/useControlPoints.js +2 -2
  58. package/dist/likec4diagram/custom/nodes/ElementActions.js +2 -2
  59. package/dist/likec4diagram/custom/nodes/NodeDrifts.js +4 -9
  60. package/dist/likec4diagram/custom/nodes/nodes.js +3 -6
  61. package/dist/likec4diagram/custom/nodes/toolbar/ElementToolbar.js +2 -2
  62. package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +2 -2
  63. package/dist/likec4diagram/relationship-popover/RelationshipPopover.js +127 -14
  64. package/dist/likec4diagram/state/DiagramActorProvider.js +63 -71
  65. package/dist/likec4diagram/state/assign.d.ts +4 -1
  66. package/dist/likec4diagram/state/assign.js +11 -8
  67. package/dist/likec4diagram/state/createViewChange.js +13 -9
  68. package/dist/likec4diagram/state/diagram-api.d.ts +20 -2
  69. package/dist/likec4diagram/state/diagram-api.js +58 -44
  70. package/dist/likec4diagram/state/hotkeyActor.d.ts +1 -1
  71. package/dist/likec4diagram/state/hotkeyActor.js +12 -0
  72. package/dist/likec4diagram/state/machine.actions.d.ts +774 -195
  73. package/dist/likec4diagram/state/machine.actions.js +185 -74
  74. package/dist/likec4diagram/state/machine.actions.layout.d.ts +93 -31
  75. package/dist/likec4diagram/state/machine.actions.layout.js +16 -4
  76. package/dist/likec4diagram/state/machine.d.ts +5 -4
  77. package/dist/likec4diagram/state/machine.js +11 -6
  78. package/dist/likec4diagram/state/machine.setup.d.ts +20 -9
  79. package/dist/likec4diagram/state/machine.setup.js +18 -3
  80. package/dist/likec4diagram/state/machine.state.initializing.d.ts +34 -18
  81. package/dist/likec4diagram/state/machine.state.initializing.js +10 -10
  82. package/dist/likec4diagram/state/machine.state.navigating.js +28 -9
  83. package/dist/likec4diagram/state/machine.state.ready.d.ts +1368 -434
  84. package/dist/likec4diagram/state/machine.state.ready.focused.d.ts +363 -39
  85. package/dist/likec4diagram/state/machine.state.ready.focused.js +17 -4
  86. package/dist/likec4diagram/state/machine.state.ready.idle.d.ts +104 -38
  87. package/dist/likec4diagram/state/machine.state.ready.idle.js +14 -5
  88. package/dist/likec4diagram/state/machine.state.ready.js +13 -90
  89. package/dist/likec4diagram/state/machine.state.ready.printing.d.ts +18 -6
  90. package/dist/likec4diagram/state/machine.state.ready.walkthrough.d.ts +204 -31
  91. package/dist/likec4diagram/state/machine.state.ready.walkthrough.js +14 -1
  92. package/dist/likec4diagram/state/types.d.ts +6 -2
  93. package/dist/likec4diagram/state/utils.d.ts +33 -7
  94. package/dist/likec4diagram/state/utils.js +23 -7
  95. package/dist/likec4diagram/ui/notation/NotationPanel.js +3 -3
  96. package/dist/likec4diagram/useLayoutConstraints.js +5 -9
  97. package/dist/navigationpanel/NavigationPanel.js +6 -9
  98. package/dist/navigationpanel/NavigationPanelDropdown.js +7 -7
  99. package/dist/navigationpanel/_common.js +1 -1
  100. package/dist/navigationpanel/comparepanel/CompareActionsMenu.d.ts +3 -1
  101. package/dist/navigationpanel/comparepanel/CompareActionsMenu.js +40 -14
  102. package/dist/navigationpanel/comparepanel/ComparePanelControls.js +6 -4
  103. package/dist/navigationpanel/comparepanel/LayoutTypeSwitcher.js +2 -2
  104. package/dist/navigationpanel/controls/DetailsControls.js +2 -2
  105. package/dist/navigationpanel/controls/LayoutWarning.js +2 -1
  106. package/dist/navigationpanel/controls/NavigationButtons.js +2 -2
  107. package/dist/navigationpanel/controls/OpenSource.js +1 -1
  108. package/dist/navigationpanel/controls/SearchControl.js +2 -2
  109. package/dist/navigationpanel/controls/ToggleReadonly.js +25 -17
  110. package/dist/navigationpanel/dropdown/ProjectsMenu.js +1 -1
  111. package/dist/navigationpanel/editorpanel/CenterCamera.js +1 -1
  112. package/dist/navigationpanel/editorpanel/ChangeAutoLayoutButton.js +1 -1
  113. package/dist/navigationpanel/editorpanel/ManualLayoutToolsButton.js +9 -9
  114. package/dist/navigationpanel/editorpanel/ToggleReadonly.js +1 -1
  115. package/dist/navigationpanel/walkthrough/ActiveWalkthroughControls.js +3 -3
  116. package/dist/navigationpanel/walkthrough/DynamicViewControls.d.ts +66 -66
  117. package/dist/navigationpanel/walkthrough/DynamicViewControls.js +1 -1
  118. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/createReactComponent.js +1 -1
  119. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.js +1 -1
  120. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertTriangle.js +1 -1
  121. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowDownRight.js +1 -1
  122. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowLeft.js +1 -1
  123. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js +1 -1
  124. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconBolt.js +1 -1
  125. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconBrowser.js +1 -1
  126. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.js +1 -1
  127. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.js +1 -1
  128. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.js +1 -1
  129. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronRight.js +1 -1
  130. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.js +1 -1
  131. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconCylinder.js +1 -1
  132. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconDeviceMobile.js +1 -1
  133. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconDirectionSignFilled.js +1 -1
  134. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconExternalLink.js +1 -1
  135. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconFileSymlink.js +1 -1
  136. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconFocusCentered.js +1 -1
  137. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconFolderFilled.js +1 -1
  138. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconHelpCircle.js +1 -1
  139. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconId.js +1 -1
  140. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconInfoCircle.js +1 -1
  141. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignBottom.js +1 -1
  142. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignCenter.js +1 -1
  143. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignLeft.js +1 -1
  144. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignMiddle.js +1 -1
  145. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignRight.js +1 -1
  146. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutAlignTop.js +1 -1
  147. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutBoardSplit.js +1 -1
  148. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutCollage.js +1 -1
  149. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLayoutDashboard.js +1 -1
  150. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLink.js +1 -1
  151. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLock.js +1 -1
  152. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconLockOpen2.js +1 -1
  153. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerPlayFilled.js +1 -1
  154. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerSkipBackFilled.js +1 -1
  155. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerSkipForwardFilled.js +1 -1
  156. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerStopFilled.js +1 -1
  157. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconRectangularPrism.js +1 -1
  158. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconReorder.js +1 -1
  159. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconRouteOff.js +1 -1
  160. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.js +1 -1
  161. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconSelector.js +1 -1
  162. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconStack2.js +1 -1
  163. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconStarFilled.js +1 -1
  164. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconTarget.js +1 -1
  165. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconTransform.js +1 -1
  166. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconUser.js +1 -1
  167. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconX.js +1 -1
  168. package/dist/node_modules/.pnpm/{@tabler_icons-react@3.35.0_react@19.2.0 → @tabler_icons-react@3.36.0_react@19.2.3}/node_modules/@tabler/icons-react/dist/esm/icons/IconZoomScan.js +1 -1
  169. package/dist/overlays/Overlays.js +23 -11
  170. package/dist/overlays/element-details/ElementDetailsCard.css.js +8 -11
  171. package/dist/overlays/element-details/ElementDetailsCard.js +4 -4
  172. package/dist/overlays/element-details/MetadataValue.js +4 -6
  173. package/dist/overlays/element-details/TabPanelDeployments.js +3 -3
  174. package/dist/overlays/element-details/TabPanelRelationships.js +12 -7
  175. package/dist/overlays/element-details/TabPanelStructure.js +1 -1
  176. package/dist/overlays/overlaysActor.js +6 -5
  177. package/dist/overlays/relationship-details/RelationshipDetails.js +3 -3
  178. package/dist/overlays/relationship-details/SelectEdge.js +2 -2
  179. package/dist/overlays/relationship-details/custom/ElementActions.js +3 -3
  180. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +3 -3
  181. package/dist/overlays/relationships-browser/SelectElement.js +2 -2
  182. package/dist/overlays/relationships-browser/custom/ElementActions.js +3 -3
  183. package/dist/search/components/ElementsColumn.js +16 -11
  184. package/dist/search/components/PickView.js +3 -1
  185. package/dist/search/components/SearchByTags.js +1 -1
  186. package/dist/search/components/SearchInput.js +1 -1
  187. package/dist/search/components/ViewsColum.d.ts +3 -1
  188. package/dist/search/components/ViewsColum.js +14 -9
  189. package/dist/search/components/utils.d.ts +6 -0
  190. package/dist/search/components/utils.js +4 -1
  191. package/dist/shadowroot/styles.css.js +6 -1
  192. package/dist/styles.css2.js +1 -1
  193. package/dist/utils/index.d.ts +2 -2
  194. package/dist/utils/xyflow.d.ts +2 -3
  195. package/dist/utils/xyflow.js +9 -8
  196. package/package.json +22 -22
  197. package/panda.buildinfo.json +61 -80
  198. package/styles-min.css +1 -1
  199. package/styles.css +1 -1
  200. package/dist/base-primitives/edge/edge.css.d.ts +0 -4
  201. package/dist/base-primitives/edge/edge.css.js +0 -71
  202. package/dist/editor/LikeC4EditorContext.d.ts +0 -21
  203. package/dist/likec4diagram/state/syncManualLayoutActor.d.ts +0 -46
  204. package/dist/likec4diagram/state/syncManualLayoutActor.js +0 -309
  205. package/dist/utils/vector.d.ts +0 -86
  206. package/dist/utils/vector.js +0 -127
@@ -4,11 +4,11 @@ import { nameFromFqn } from '@likec4/core';
4
4
  import { cx, css } from '@likec4/styles/css';
5
5
  import { VStack, styled, HStack, Box } from '@likec4/styles/jsx';
6
6
  import { bleed } from '@likec4/styles/patterns';
7
- import { Divider, ScrollAreaAutosize, Button, TooltipGroup, Tooltip as Tooltip$1, Text, ActionIcon } from '@mantine/core';
7
+ import { Divider, ScrollAreaAutosize, Button, TooltipGroup, Tooltip as Tooltip$1, Text, ActionIcon, Notification } from '@mantine/core';
8
8
  import { useActorRef, useSelector } from '@xstate/react';
9
9
  import { shallowEqual } from 'fast-equals';
10
10
  import { memo, useEffect, useCallback, useRef, useState, useLayoutEffect, Fragment, forwardRef } from 'react';
11
- import { isEmpty, pipe, map, filter, isTruthy, partition, clamp } from 'remeda';
11
+ import { isEmpty, pipe, map, filter, isTruthy, partition, clamp, entries } from 'remeda';
12
12
  import { Link } from '../../components/Link.js';
13
13
  import { PortalToContainer } from '../../components/PortalToContainer.js';
14
14
  import { useDiagramEventHandlers } from '../../context/DiagramEventHandlers.js';
@@ -21,9 +21,10 @@ import { endpoint, title } from './styles.css.js';
21
21
  import { useDiagram } from '../../hooks/safeContext.js';
22
22
  import { useRootContainerRef } from '../../context/RootContainerContext.js';
23
23
  import { roundDpr } from '../../utils/roundDpr.js';
24
- import IconArrowRight from '../../node_modules/.pnpm/@tabler_icons-react@3.35.0_react@19.2.0/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js';
25
- import IconZoomScan from '../../node_modules/.pnpm/@tabler_icons-react@3.35.0_react@19.2.0/node_modules/@tabler/icons-react/dist/esm/icons/IconZoomScan.js';
26
- import IconFileSymlink from '../../node_modules/.pnpm/@tabler_icons-react@3.35.0_react@19.2.0/node_modules/@tabler/icons-react/dist/esm/icons/IconFileSymlink.js';
24
+ import IconArrowRight from '../../node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js';
25
+ import IconZoomScan from '../../node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconZoomScan.js';
26
+ import IconFileSymlink from '../../node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconFileSymlink.js';
27
+ import IconInfoCircle from '../../node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconInfoCircle.js';
27
28
  import { Markdown } from '../../base-primitives/Markdown.js';
28
29
 
29
30
  function selectDiagramContext(c) {
@@ -143,7 +144,7 @@ const RelationshipPopover = memo(() => {
143
144
  ) });
144
145
  });
145
146
  const getEdgeLabelElement = (edgeId, container) => {
146
- return container?.querySelector(`.likec4-edge-label[data-edge-id="${edgeId}"]`) ?? container?.querySelector(`.react-flow__edge[data-id="${edgeId}"] .edge-center-point`) ?? null;
147
+ return container?.querySelector(`.likec4-edge-label[data-edge-id="${edgeId}"]`) ?? container?.querySelector(`.likec4-edge-middle-point[data-edge-id="${edgeId}"]`) ?? null;
147
148
  };
148
149
  const POPOVER_PADDING = 8;
149
150
  const RelationshipPopoverInternal = ({
@@ -157,7 +158,7 @@ const RelationshipPopoverInternal = ({
157
158
  onMouseLeave
158
159
  }) => {
159
160
  const ref = useRef(null);
160
- const { enableNavigateTo, enableVscode } = useEnabledFeatures();
161
+ const { enableNavigateTo, enableVscode, enableCompareWithLatest } = useEnabledFeatures();
161
162
  const { onOpenSource } = useDiagramEventHandlers();
162
163
  const containerRef = useRootContainerRef();
163
164
  const [referenceEl, setReferenceEl] = useState(null);
@@ -178,24 +179,26 @@ const RelationshipPopoverInternal = ({
178
179
  offset(4),
179
180
  autoPlacement({
180
181
  crossAxis: true,
181
- padding: POPOVER_PADDING,
182
+ // padding: POPOVER_PADDING,
182
183
  allowedPlacements: [
183
184
  "bottom-start",
185
+ "bottom-end",
186
+ "left-start",
184
187
  "top-start",
188
+ "top-end",
185
189
  "right-start",
186
190
  "right-end",
187
191
  "left-end"
188
192
  ]
189
193
  }),
190
194
  size({
191
- padding: POPOVER_PADDING,
192
195
  apply({ availableHeight, availableWidth, elements }) {
193
196
  if (wasCanceled) {
194
197
  return;
195
198
  }
196
199
  Object.assign(elements.floating.style, {
197
- maxWidth: `${clamp(roundDpr(availableWidth), { min: 200, max: 400 })}px`,
198
- maxHeight: `${clamp(roundDpr(availableHeight), { min: 0, max: 500 })}px`
200
+ maxWidth: `${clamp(roundDpr(availableWidth), { min: 220, max: 400 })}px`,
201
+ maxHeight: `${clamp(roundDpr(availableHeight), { min: 100, max: 500 })}px`
199
202
  });
200
203
  }
201
204
  }),
@@ -254,7 +257,8 @@ const RelationshipPopoverInternal = ({
254
257
  styles: {
255
258
  viewport: {
256
259
  overscrollBehavior: "contain",
257
- minWidth: 180
260
+ minWidth: 200,
261
+ minHeight: 40
258
262
  }
259
263
  },
260
264
  className: cx(
@@ -281,6 +285,7 @@ const RelationshipPopoverInternal = ({
281
285
  paddingTop: "2"
282
286
  },
283
287
  children: [
288
+ enableCompareWithLatest && /* @__PURE__ */ jsx(EdgeDrifts, { diagramEdge }),
284
289
  /* @__PURE__ */ jsx(
285
290
  Button,
286
291
  {
@@ -321,6 +326,25 @@ const RelationshipPopoverInternal = ({
321
326
  }
322
327
  );
323
328
  };
329
+ const EdgeDrifts = ({ diagramEdge }) => {
330
+ const drifts = diagramEdge.drifts;
331
+ if (!drifts || drifts.length === 0) {
332
+ return null;
333
+ }
334
+ return /* @__PURE__ */ jsx(
335
+ Notification,
336
+ {
337
+ color: "orange",
338
+ withBorder: false,
339
+ withCloseButton: false,
340
+ title: "Changes:",
341
+ children: drifts.map((drift) => /* @__PURE__ */ jsxs(Text, { mt: 2, size: "sm", lh: "xs", children: [
342
+ "- ",
343
+ drift
344
+ ] }, drift))
345
+ }
346
+ );
347
+ };
324
348
  const Relationship = forwardRef(({
325
349
  viewId,
326
350
  relationship: r,
@@ -333,6 +357,65 @@ const Relationship = forwardRef(({
333
357
  const targetId = getEndpointId(r, "target", targetNode);
334
358
  const navigateTo = onNavigateTo && r.navigateTo?.id !== viewId ? r.navigateTo?.id : void 0;
335
359
  const links = r.links;
360
+ const metadataEntries = r.hasMetadata() ? entries(r.getMetadata()).sort(([a], [b]) => a.localeCompare(b)) : null;
361
+ const metadataTooltipLabel = metadataEntries && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
362
+ /* @__PURE__ */ jsx(
363
+ "div",
364
+ {
365
+ style: {
366
+ fontWeight: 600,
367
+ fontSize: "10px",
368
+ color: "#868e96",
369
+ marginBottom: "2px",
370
+ letterSpacing: "0.5px",
371
+ textTransform: "uppercase"
372
+ },
373
+ children: "Metadata"
374
+ }
375
+ ),
376
+ /* @__PURE__ */ jsx(
377
+ "div",
378
+ {
379
+ style: {
380
+ borderTop: "1px solid rgba(0, 0, 0, 0.1)",
381
+ paddingTop: "6px",
382
+ display: "flex",
383
+ flexDirection: "column",
384
+ gap: "6px"
385
+ },
386
+ children: metadataEntries.map(([key, value]) => {
387
+ const displayValue = Array.isArray(value) ? value.join(", ") : value;
388
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px", fontSize: "12px", lineHeight: "1.4" }, children: [
389
+ /* @__PURE__ */ jsxs(
390
+ "span",
391
+ {
392
+ style: {
393
+ fontWeight: 600,
394
+ minWidth: "110px",
395
+ color: "#495057"
396
+ },
397
+ children: [
398
+ key,
399
+ ":"
400
+ ]
401
+ }
402
+ ),
403
+ /* @__PURE__ */ jsx(
404
+ "span",
405
+ {
406
+ style: {
407
+ color: "#212529",
408
+ wordBreak: "break-word",
409
+ flex: 1
410
+ },
411
+ children: displayValue
412
+ }
413
+ )
414
+ ] }, key);
415
+ })
416
+ }
417
+ )
418
+ ] });
336
419
  return /* @__PURE__ */ jsxs(
337
420
  VStack,
338
421
  {
@@ -388,7 +471,37 @@ const Relationship = forwardRef(({
388
471
  }
389
472
  ) })
390
473
  ] }) }),
391
- /* @__PURE__ */ jsx(Box, { className: title, children: r.title || "untitled" }),
474
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", alignItems: "center", children: [
475
+ /* @__PURE__ */ jsx(Box, { className: title, children: r.title || "untitled" }),
476
+ metadataTooltipLabel && /* @__PURE__ */ jsx(
477
+ Tooltip,
478
+ {
479
+ label: metadataTooltipLabel,
480
+ w: 350,
481
+ position: "right",
482
+ offset: 10,
483
+ openDelay: 300,
484
+ withArrow: true,
485
+ bg: "white",
486
+ c: "dark",
487
+ withinPortal: true,
488
+ styles: {
489
+ tooltip: {
490
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
491
+ border: "1px solid #dee2e6"
492
+ }
493
+ },
494
+ children: /* @__PURE__ */ jsx(Box, { display: "inline-flex", children: /* @__PURE__ */ jsx(
495
+ IconInfoCircle,
496
+ {
497
+ size: 14,
498
+ opacity: 0.5,
499
+ style: { flexShrink: 0, cursor: "help" }
500
+ }
501
+ ) })
502
+ }
503
+ )
504
+ ] }),
392
505
  r.kind && /* @__PURE__ */ jsxs(HStack, { gap: "2", children: [
393
506
  /* @__PURE__ */ jsx(Label, { children: "kind" }),
394
507
  /* @__PURE__ */ jsx(Text, { size: "xs", className: css({ userSelect: "all" }), children: r.kind })
@@ -411,7 +524,7 @@ const Relationship = forwardRef(({
411
524
  _dark: "mantine.colors.dark[4]"
412
525
  }
413
526
  },
414
- children: /* @__PURE__ */ jsx(Markdown, { value: r.summary, fontSize: "sm" })
527
+ children: /* @__PURE__ */ jsx(Markdown, { value: r.summary, fontSize: "sm", textScale: 0.875 })
415
528
  }
416
529
  )
417
530
  ] }),
@@ -1,19 +1,19 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useRafEffect } from '@react-hookz/web';
3
3
  import { useActorRef, useSelector } from '@xstate/react';
4
4
  import { useStoreApi } from '@xyflow/react';
5
5
  import { shallowEqual } from 'fast-equals';
6
- import { useState, useEffect, memo, useRef } from 'react';
7
- import { isNullish } from 'remeda';
6
+ import { useRef, useState, useEffect, memo } from 'react';
7
+ import { omitBy, isNullish } from 'remeda';
8
8
  import { ErrorBoundary } from '../../components/ErrorFallback.js';
9
9
  import { useDiagramEventHandlers } from '../../context/DiagramEventHandlers.js';
10
10
  import { useEnabledFeatures, DiagramFeatures } from '../../context/DiagramFeatures.js';
11
11
  import { CurrentViewModelContext } from '../../context/LikeC4ModelContext.js';
12
- import { DiagramActorContextProvider, useDiagram } from '../../hooks/safeContext.js';
13
- import { useOnDiagramEvent } from '../../hooks/useDiagram.js';
12
+ import { useEditorActorLogic } from '../../editor/useEditorActorLogic.js';
13
+ import { DiagramActorContextProvider, DiagramApiContextProvider, useDiagram } from '../../hooks/safeContext.js';
14
+ import { useOnDiagramEvent, useDiagramContext } from '../../hooks/useDiagram.js';
14
15
  import { useLikeC4Model } from '../../hooks/useLikeC4Model.js';
15
16
  import { useUpdateEffect } from '../../hooks/useUpdateEffect.js';
16
- import { convertToXYFlow } from '../convert-to-xyflow.js';
17
17
  import { makeDiagramApi } from './diagram-api.js';
18
18
  import { diagramMachine } from './machine.js';
19
19
  import { DiagramToggledFeaturesPersistence } from './persistence.js';
@@ -30,8 +30,13 @@ function DiagramActorProvider({
30
30
  dynamicViewVariant: _defaultVariant
31
31
  }) {
32
32
  const xystore = useStoreApi();
33
- const actorRef = useActorRef(
34
- diagramMachine,
33
+ const editorActor = useEditorActorLogic(view.id);
34
+ const actor = useActorRef(
35
+ diagramMachine.provide({
36
+ actors: {
37
+ editorActor
38
+ }
39
+ }),
35
40
  {
36
41
  id: `diagram`,
37
42
  systemId: "diagram",
@@ -44,54 +49,61 @@ function DiagramActorProvider({
44
49
  fitViewPadding,
45
50
  nodesDraggable,
46
51
  nodesSelectable,
52
+ where,
47
53
  dynamicViewVariant: _defaultVariant
48
54
  }
49
55
  }
50
56
  );
57
+ const actorRef = useRef(actor);
58
+ if (actorRef.current !== actor) {
59
+ console.warn("DiagramMachine actor instance changed", {
60
+ context: {
61
+ previous: actorRef.current.getSnapshot().context,
62
+ current: actor.getSnapshot().context
63
+ }
64
+ });
65
+ actorRef.current = actor;
66
+ }
51
67
  const [api, setApi] = useState(() => makeDiagramApi(actorRef));
52
68
  useEffect(() => {
53
69
  setApi((api2) => {
54
- if (api2.actor === actorRef) return api2;
70
+ if (api2.ref === actorRef) {
71
+ return api2;
72
+ }
73
+ console.warn(
74
+ "DiagramMachine actorRef changed, creating new DiagramApi instance, this should not happen during the lifetime of the actor"
75
+ );
55
76
  return makeDiagramApi(actorRef);
56
77
  });
57
78
  }, [actorRef]);
58
- if (api.actor !== actorRef) {
59
- console.warn("DiagramApi instance changed, this should not happen during the lifetime of the actor");
60
- }
61
79
  const features = useEnabledFeatures();
62
80
  useEffect(
63
- () => actorRef.send({ type: "update.features", features }),
64
- [features, actorRef]
81
+ () => actor.send({ type: "update.features", features }),
82
+ [features, actor]
65
83
  );
66
84
  useEffect(
67
- () => actorRef.send({
85
+ () => actor.send({
68
86
  type: "update.inputs",
69
- inputs: { zoomable, pannable, fitViewPadding, nodesDraggable, nodesSelectable }
87
+ inputs: { zoomable, where, pannable, fitViewPadding, nodesDraggable, nodesSelectable }
70
88
  }),
71
- [zoomable, pannable, fitViewPadding, actorRef, nodesDraggable, nodesSelectable]
89
+ [zoomable, where, pannable, fitViewPadding, actor, nodesDraggable, nodesSelectable]
72
90
  );
73
91
  useUpdateEffect(() => {
74
92
  if (!_defaultVariant) return;
75
- actorRef.send({ type: "switch.dynamicViewVariant", variant: _defaultVariant });
76
- }, [_defaultVariant, actorRef]);
77
- return /* @__PURE__ */ jsxs(DiagramActorContextProvider, { value: api, children: [
78
- /* @__PURE__ */ jsxs(ErrorBoundary, { children: [
79
- /* @__PURE__ */ jsx(
80
- DiagramXYFlowSyncProvider,
81
- {
82
- view,
83
- where,
84
- actorRef
85
- }
86
- ),
87
- /* @__PURE__ */ jsx(CurrentViewModelProvider, { actorRef, children })
88
- ] }),
93
+ actor.send({ type: "switch.dynamicViewVariant", variant: _defaultVariant });
94
+ }, [_defaultVariant, actor]);
95
+ useRafEffect(
96
+ () => actor.send({ type: "update.view", view, source: "external" }),
97
+ [actor, view]
98
+ );
99
+ return /* @__PURE__ */ jsx(DiagramActorContextProvider, { value: actor, children: /* @__PURE__ */ jsxs(DiagramApiContextProvider, { value: api, children: [
100
+ /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(CurrentViewModelProvider, { actorRef: actor, children }) }),
89
101
  /* @__PURE__ */ jsx(DiagramActorEventListener, {})
90
- ] });
102
+ ] }) });
91
103
  }
92
104
  const selectFromActor = ({ context }) => {
93
105
  let toggledFeatures = context.toggledFeatures;
94
- const hasDrifts = context.view.drifts != null;
106
+ const hasDrifts = context.view.drifts != null && context.view.drifts.length > 0;
95
107
  const enableCompareWithLatest = context.features.enableCompareWithLatest && (toggledFeatures.enableCompareWithLatest ?? false) && isNullish(context.activeWalkthrough) && hasDrifts;
96
108
  const enableReadOnly = context.features.enableReadOnly || toggledFeatures.enableReadOnly || !!context.activeWalkthrough || context.dynamicViewVariant === "sequence" && context.view._type === "dynamic" || enableCompareWithLatest && context.view._layout === "auto";
97
109
  if (toggledFeatures.enableReadOnly !== enableReadOnly || toggledFeatures.enableCompareWithLatest !== enableCompareWithLatest) {
@@ -115,62 +127,42 @@ function CurrentViewModelProvider({ children, actorRef }) {
115
127
  selectFromActor,
116
128
  compareSelected
117
129
  );
118
- useUpdateEffect(() => {
119
- DiagramToggledFeaturesPersistence.write(toggledFeatures);
120
- }, [toggledFeatures]);
121
130
  const likec4model = useLikeC4Model();
122
131
  const viewmodel = likec4model.findView(viewId);
123
132
  return /* @__PURE__ */ jsx(CurrentViewModelContext.Provider, { value: viewmodel, children: /* @__PURE__ */ jsx(DiagramFeatures, { overrides: toggledFeatures, children }) });
124
133
  }
125
- const selectFromActor2 = (state) => {
126
- return state.context.dynamicViewVariant;
127
- };
128
- function DiagramXYFlowSyncProvider({ view, where, actorRef }) {
129
- const dynamicViewVariant = useSelector(actorRef, selectFromActor2);
130
- useRafEffect(() => {
131
- actorRef.send({
132
- type: "update.view",
133
- ...convertToXYFlow({ view, where, dynamicViewVariant })
134
- });
135
- }, [view, where, dynamicViewVariant, actorRef]);
136
- return null;
137
- }
138
134
  const DiagramActorEventListener = memo(() => {
139
135
  const diagram = useDiagram();
140
136
  const {
141
137
  onNavigateTo,
142
138
  onOpenSource,
143
- onChange,
139
+ // onChange,
144
140
  onLayoutTypeChange,
145
141
  handlersRef
146
142
  } = useDiagramEventHandlers();
147
143
  useOnDiagramEvent("openSource", ({ params }) => onOpenSource?.(params));
148
144
  useOnDiagramEvent("navigateTo", ({ viewId }) => onNavigateTo?.(viewId));
149
- useOnDiagramEvent("onChange", ({ change }) => onChange?.({ change }));
150
145
  useOnDiagramEvent("onLayoutTypeChange", ({ layoutType }) => {
151
146
  onLayoutTypeChange?.(layoutType);
152
147
  });
153
- const wasEmitted = useRef(false);
154
- useEffect(() => {
155
- if (wasEmitted.current) return;
156
- let subscription = diagram.actor.on(
157
- "initialized",
158
- ({ instance: xyflow }) => {
159
- try {
160
- handlersRef.current.onInitialized?.({ diagram, xyflow });
161
- } catch (error) {
162
- console.error(error);
163
- } finally {
164
- wasEmitted.current = true;
165
- subscription?.unsubscribe();
166
- subscription = null;
167
- }
148
+ useOnDiagramEvent(
149
+ "initialized",
150
+ ({ instance: xyflow }) => {
151
+ try {
152
+ handlersRef.current.onInitialized?.({ diagram, xyflow });
153
+ } catch (error) {
154
+ console.error(error);
168
155
  }
169
- );
170
- return () => {
171
- subscription?.unsubscribe();
172
- };
173
- }, [diagram]);
156
+ },
157
+ { once: true }
158
+ );
159
+ const toggledFeatures = useDiagramContext(
160
+ (ctx) => ctx.toggledFeatures,
161
+ shallowEqual
162
+ );
163
+ useUpdateEffect(() => {
164
+ DiagramToggledFeaturesPersistence.write(omitBy(toggledFeatures, isNullish));
165
+ }, [toggledFeatures]);
174
166
  return null;
175
167
  });
176
168
 
@@ -17,7 +17,10 @@ export declare function mergeXYNodesEdges(context: Pick<DiagramContext, 'xynodes
17
17
  xyedges: Types.Edge[];
18
18
  view: LayoutedView;
19
19
  };
20
- export declare function focusNodesEdges(params: ActionArg): Partial<DiagramContext>;
20
+ export declare function focusNodesEdges(context: DiagramContext): {
21
+ xynodes: Types.Node<"element" | "deployment" | "compound-element" | "compound-deployment" | "view-group" | "seq-actor" | "seq-parallel">[];
22
+ xyedges: Types.Edge<"relationship" | "seq-step">[];
23
+ } | null;
21
24
  export declare function updateNodeData({ context, event }: ActionArg): Partial<DiagramContext>;
22
25
  export declare function updateEdgeData({ context, event }: ActionArg): Partial<DiagramContext>;
23
26
  export declare function resetEdgeControlPoints(nodeLookup: NodeLookup, edge: Types.Edge): [XYPoint] | [XYPoint, XYPoint];
@@ -1,9 +1,9 @@
1
1
  import { nonNullable } from '@likec4/core';
2
+ import { vector } from '@likec4/core/geometry';
2
3
  import { getNodeDimensions } from '@xyflow/system';
3
4
  import { deepEqual } from 'fast-equals';
4
5
  import { mergeDeep } from 'remeda';
5
6
  import { assertEvent } from 'xstate';
6
- import { vector } from '../../utils/vector.js';
7
7
  import { getNodeCenter } from '../../utils/xyflow.js';
8
8
  import { updateNodes } from '../../base/updateNodes.js';
9
9
  import { updateEdges } from '../../base/updateEdges.js';
@@ -29,10 +29,10 @@ function mergeXYNodesEdges(context, event) {
29
29
  view: nextView
30
30
  };
31
31
  }
32
- function focusNodesEdges(params) {
33
- const { xynodes: _xynodes, xyedges: _xyedges, focusedNode } = params.context;
32
+ function focusNodesEdges(context) {
33
+ const { xynodes: _xynodes, xyedges: _xyedges, focusedNode } = context;
34
34
  if (!focusedNode) {
35
- return {};
35
+ return null;
36
36
  }
37
37
  const focused = /* @__PURE__ */ new Set([focusedNode]);
38
38
  const xyedges = _xyedges.map((edge) => {
@@ -55,7 +55,6 @@ function focusNodesEdges(params) {
55
55
  };
56
56
  }
57
57
  function updateNodeData({ context, event }) {
58
- console.log("updateNodeData called", event);
59
58
  assertEvent(event, "update.nodeData");
60
59
  const xynodes = context.xynodes.map((node) => {
61
60
  if (node.id !== event.nodeId) {
@@ -105,14 +104,18 @@ function resetEdgeControlPoints(nodeLookup, edge) {
105
104
  const loopSize = 80;
106
105
  const centerOfTopBoundary = vector(0, source.height || 0).multiply(-0.5).add(sourceCenter);
107
106
  return [
108
- centerOfTopBoundary.add(vector(-loopSize / 2.5, -loopSize)),
109
- centerOfTopBoundary.add(vector(loopSize / 2.5, -loopSize))
107
+ centerOfTopBoundary.add(vector(-loopSize / 2.5, -loopSize)).round().toObject(),
108
+ centerOfTopBoundary.add(vector(loopSize / 2.5, -loopSize)).round().toObject()
110
109
  ];
111
110
  }
112
111
  const sourceToTargetVector = targetCenter.subtract(sourceCenter);
113
112
  const sourceBorderPoint = getBorderPointOnVector(source, sourceCenter, sourceToTargetVector);
114
113
  const targetBorderPoint = getBorderPointOnVector(target, targetCenter, sourceToTargetVector.multiply(-1));
115
- return [sourceBorderPoint.add(targetBorderPoint.subtract(sourceBorderPoint).multiply(0.4))];
114
+ const sourceToTarget = targetBorderPoint.subtract(sourceBorderPoint);
115
+ return [
116
+ sourceBorderPoint.add(sourceToTarget.multiply(0.4)).round().toObject(),
117
+ sourceBorderPoint.add(sourceToTarget.multiply(0.6)).round().toObject()
118
+ ];
116
119
  }
117
120
 
118
121
  export { focusNodesEdges, mergeXYNodesEdges, resetEdgeControlPoints, updateEdgeData, updateNodeData };
@@ -12,6 +12,7 @@ function createViewChange(parentContext) {
12
12
  // Ignore layout type from view
13
13
  ...view
14
14
  },
15
+ xynodes,
15
16
  xystore
16
17
  } = parentContext;
17
18
  const { nodeLookup, edgeLookup } = xystore.getState();
@@ -22,22 +23,24 @@ function createViewChange(parentContext) {
22
23
  console.error(`Internal node not found for ${node.id}`);
23
24
  return node;
24
25
  }
25
- const dimensions = getNodeDimensions(internal);
26
- const isChanged = !isSamePoint(internal.internals.positionAbsolute, node) || node.width !== dimensions.width || node.height !== dimensions.height;
26
+ const xynodedata = xynodes.find((n) => n.id === node.id)?.data ?? internal.data;
27
+ const position = internal.internals.positionAbsolute;
28
+ const { width, height } = getNodeDimensions(internal);
29
+ const isChanged = !isSamePoint(position, node) || node.width !== width || node.height !== height;
27
30
  if (isChanged) {
28
31
  movedNodes.add(node.id);
29
32
  }
30
33
  return {
31
34
  ...node,
32
- shape: internal.data.shape,
33
- color: internal.data.color,
35
+ shape: xynodedata.shape,
36
+ color: xynodedata.color,
34
37
  style: {
35
- ...internal.data.style
38
+ ...xynodedata.style
36
39
  },
37
- x: Math.floor(internal.internals.positionAbsolute.x),
38
- y: Math.floor(internal.internals.positionAbsolute.y),
39
- width: Math.ceil(dimensions.width),
40
- height: Math.ceil(dimensions.height)
40
+ x: Math.floor(position.x),
41
+ y: Math.floor(position.y),
42
+ width: Math.ceil(width),
43
+ height: Math.ceil(height)
41
44
  };
42
45
  });
43
46
  const edges = map(view.edges, (edge) => {
@@ -66,6 +69,7 @@ function createViewChange(parentContext) {
66
69
  });
67
70
  const snapshot = {
68
71
  ...view,
72
+ _layout: "manual",
69
73
  bounds: calcViewBounds({ nodes, edges }),
70
74
  nodes,
71
75
  edges
@@ -1,7 +1,9 @@
1
1
  import { DynamicViewDisplayVariant, NodeNotation as ElementNotation, ViewChange } from '@likec4/core/types';
2
+ import { RefObject } from 'react';
2
3
  import { PartialDeep } from 'type-fest';
3
4
  import { FeatureName } from '../../context/DiagramFeatures';
4
5
  import { OpenSourceParams } from '../../LikeC4Diagram.props';
6
+ import { OverlaysActorRef } from '../../overlays/overlaysActor';
5
7
  import { Types } from '../types';
6
8
  import { AlignmentMode } from './aligners';
7
9
  import { DiagramActorRef, DiagramContext, DiagramEvents } from './types';
@@ -13,19 +15,30 @@ type Fqn<A> = t.aux.Fqn<A>;
13
15
  type NodeId = t.aux.NodeId;
14
16
  type EdgeId = t.aux.EdgeId;
15
17
  export interface DiagramApi<A extends Any = Unknown> {
18
+ /**
19
+ * React ref to the diagram actor
20
+ */
21
+ readonly ref: RefObject<DiagramActorRef>;
22
+ /**
23
+ * @warning Do not use in render phase
24
+ */
16
25
  readonly actor: DiagramActorRef;
17
26
  /**
18
27
  * @warning Do not use in render phase
19
28
  */
20
29
  readonly currentView: t.DiagramView<A>;
30
+ overlays(): OverlaysActorRef;
21
31
  /**
22
32
  * Send event to diagram actor
23
33
  */
24
34
  send(event: DiagramEvents): void;
25
35
  /**
26
36
  * Navigate to view
37
+ * @param viewId - Target view ID
38
+ * @param fromNode - Node from which navigation was triggered
39
+ * @param focusOnElement - Element FQN to focus after navigation (from search)
27
40
  */
28
- navigateTo(viewId: ViewId<A>, fromNode?: NodeId): void;
41
+ navigateTo(viewId: ViewId<A>, fromNode?: NodeId, focusOnElement?: Fqn<A>): void;
29
42
  /**
30
43
  * Navigate back or forward in history
31
44
  */
@@ -76,6 +89,11 @@ export interface DiagramApi<A extends Any = Unknown> {
76
89
  * Focus node
77
90
  */
78
91
  focusNode(nodeId: NodeId): void;
92
+ /**
93
+ * Focus on element by FQN (finds the node and focuses on it).
94
+ * Used by search to highlight an element on the current view.
95
+ */
96
+ focusOnElement(elementFqn: Fqn<A>): void;
79
97
  /**
80
98
  * @warning Do not use in render phase
81
99
  */
@@ -105,5 +123,5 @@ export interface DiagramApi<A extends Any = Unknown> {
105
123
  */
106
124
  switchDynamicViewVariant(variant: DynamicViewDisplayVariant): void;
107
125
  }
108
- export declare function makeDiagramApi<A extends Any = Unknown>(actor: DiagramActorRef): DiagramApi<A>;
126
+ export declare function makeDiagramApi<A extends Any = Unknown>(actorRef: RefObject<DiagramActorRef>): DiagramApi<A>;
109
127
  export {};