@likec4/diagram 1.58.0 → 1.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/LikeC4Diagram.js +1 -1
  2. package/dist/LikeC4Diagram.props.d.ts +1 -1
  3. package/dist/LikeC4Styles.js +1 -1
  4. package/dist/LikeC4View.js +2 -2
  5. package/dist/ReactLikeC4.d.ts +1 -1
  6. package/dist/base/Base.d.ts +3 -2
  7. package/dist/base/Base.js +14 -26
  8. package/dist/base/BaseXYFlow.d.ts +2 -1
  9. package/dist/base/BaseXYFlow.js +63 -4
  10. package/dist/base/keyboardZoom.d.ts +3 -0
  11. package/dist/base/keyboardZoom.js +20 -0
  12. package/dist/base/updateEdges.js +7 -16
  13. package/dist/base/updateNodes.js +3 -9
  14. package/dist/base-primitives/compound/CompoundActionButton.d.ts +2 -1
  15. package/dist/base-primitives/compound/CompoundActionButton.js +5 -2
  16. package/dist/base-primitives/compound/CompoundDetailsButton.d.ts +2 -1
  17. package/dist/base-primitives/compound/CompoundDetailsButton.js +5 -2
  18. package/dist/base-primitives/compound/CompoundTitle.d.ts +7 -1
  19. package/dist/base-primitives/compound/CompoundTitle.js +2 -1
  20. package/dist/base-primitives/compound/actionbtns.css.d.ts +1 -1
  21. package/dist/base-primitives/edge/EdgeActionButton.d.ts +2 -1
  22. package/dist/base-primitives/edge/EdgeActionButton.js +2 -1
  23. package/dist/base-primitives/edge/EdgeContainer.d.ts +1 -1
  24. package/dist/base-primitives/edge/EdgeContainer.js +4 -2
  25. package/dist/base-primitives/edge/EdgeLabel.d.ts +2 -0
  26. package/dist/base-primitives/edge/EdgeLabel.js +2 -5
  27. package/dist/base-primitives/element/ElementActionButtons.d.ts +1 -0
  28. package/dist/base-primitives/element/ElementActionButtons.js +4 -1
  29. package/dist/base-primitives/element/ElementData.d.ts +3 -1
  30. package/dist/base-primitives/element/ElementData.js +2 -1
  31. package/dist/base-primitives/element/ElementDetailsButton.d.ts +2 -1
  32. package/dist/base-primitives/element/ElementDetailsButton.js +5 -2
  33. package/dist/base-primitives/element/ElementNodeContainer.js +1 -1
  34. package/dist/base-primitives/element/ElementShape.js +3 -0
  35. package/dist/components/ErrorFallback.js +3 -5
  36. package/dist/components/Link.js +6 -6
  37. package/dist/components/NavigationPanel.js +1 -1
  38. package/dist/components/SearchControl.css.js +11 -11
  39. package/dist/context/TagStylesContext.d.ts +3 -3
  40. package/dist/context/TagStylesContext.js +16 -16
  41. package/dist/custom/index.d.ts +1 -0
  42. package/dist/custom/index.js +3 -2
  43. package/dist/editor/actor/actions.js +1 -1
  44. package/dist/editor/actor/machine.d.ts +4 -6
  45. package/dist/editor/actor/setup.d.ts +16 -2
  46. package/dist/editor/actor/setup.js +5 -4
  47. package/dist/hooks/index.d.ts +1 -1
  48. package/dist/hooks/safeContext.d.ts +156 -3
  49. package/dist/hooks/safeContext.js +60 -12
  50. package/dist/hooks/useCurrentViewModel.js +1 -1
  51. package/dist/hooks/useDiagram.d.ts +8 -0
  52. package/dist/hooks/useDiagram.js +9 -2
  53. package/dist/hooks/useEditorActor.js +1 -1
  54. package/dist/hooks/useLikeC4ElementsTree.js +1 -1
  55. package/dist/hooks/useLikeC4Model.js +1 -1
  56. package/dist/hooks/useXYFlow.d.ts +1 -0
  57. package/dist/hooks/useXYFlow.js +5 -3
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +2 -2
  60. package/dist/likec4diagram/DiagramUI.js +19 -6
  61. package/dist/likec4diagram/DiagramXYFlow.js +39 -14
  62. package/dist/likec4diagram/convert-to-xyflow.d.ts +3 -5
  63. package/dist/likec4diagram/convert-to-xyflow.js +29 -10
  64. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +13 -4
  65. package/dist/likec4diagram/custom/edges/SequenceStepEdge.js +11 -4
  66. package/dist/likec4diagram/custom/edges/edges.css.js +1 -1
  67. package/dist/likec4diagram/custom/index.d.ts +2 -1
  68. package/dist/likec4diagram/custom/index.js +5 -3
  69. package/dist/likec4diagram/custom/nodes/CompoundActions.js +1 -0
  70. package/dist/likec4diagram/custom/nodes/ElementActions.d.ts +2 -2
  71. package/dist/likec4diagram/custom/nodes/ElementActions.js +13 -3
  72. package/dist/likec4diagram/custom/nodes/NodeNotes.js +0 -4
  73. package/dist/likec4diagram/custom/nodes/SequenceActorNode.js +32 -19
  74. package/dist/likec4diagram/custom/nodes/SequenceSubFlow.d.ts +2 -0
  75. package/dist/likec4diagram/custom/nodes/SequenceSubFlow.js +234 -0
  76. package/dist/likec4diagram/custom/nodes/index.d.ts +1 -0
  77. package/dist/likec4diagram/custom/nodes/nodes.js +20 -5
  78. package/dist/likec4diagram/custom/nodes/toolbar/ColorButton.js +1 -1
  79. package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +1 -1
  80. package/dist/likec4diagram/relationship-popover/RelationshipPopover.js +15 -14
  81. package/dist/likec4diagram/relationship-popover/components.d.ts +1 -1
  82. package/dist/likec4diagram/state/DiagramActorProvider.js +11 -20
  83. package/dist/likec4diagram/state/aligners.js +1 -1
  84. package/dist/likec4diagram/state/assign.d.ts +1 -1
  85. package/dist/likec4diagram/state/assign.js +1 -1
  86. package/dist/likec4diagram/state/createViewChange.js +1 -1
  87. package/dist/likec4diagram/state/diagram-api.d.ts +18 -10
  88. package/dist/likec4diagram/state/diagram-api.js +333 -229
  89. package/dist/likec4diagram/state/machine.actions.d.ts +1026 -332
  90. package/dist/likec4diagram/state/machine.actions.js +115 -44
  91. package/dist/likec4diagram/state/machine.actions.layout.d.ts +123 -51
  92. package/dist/likec4diagram/state/machine.actions.layout.js +40 -33
  93. package/dist/likec4diagram/state/machine.d.ts +154 -16
  94. package/dist/likec4diagram/state/machine.js +5 -41
  95. package/dist/likec4diagram/state/machine.setup.d.ts +84 -19
  96. package/dist/likec4diagram/state/machine.setup.js +65 -12
  97. package/dist/likec4diagram/state/machine.state.initializing.d.ts +59 -33
  98. package/dist/likec4diagram/state/machine.state.navigating.js +7 -3
  99. package/dist/likec4diagram/state/machine.state.ready.d.ts +1540 -476
  100. package/dist/likec4diagram/state/machine.state.ready.focused.d.ts +294 -53
  101. package/dist/likec4diagram/state/machine.state.ready.focused.js +3 -3
  102. package/dist/likec4diagram/state/machine.state.ready.idle.d.ts +264 -73
  103. package/dist/likec4diagram/state/machine.state.ready.idle.js +31 -6
  104. package/dist/likec4diagram/state/machine.state.ready.js +22 -16
  105. package/dist/likec4diagram/state/machine.state.ready.printing.d.ts +23 -9
  106. package/dist/likec4diagram/state/machine.state.ready.walkthrough.d.ts +288 -84
  107. package/dist/likec4diagram/state/machine.state.ready.walkthrough.js +135 -66
  108. package/dist/likec4diagram/state/types.d.ts +4 -2
  109. package/dist/likec4diagram/state/utils.d.ts +7 -0
  110. package/dist/likec4diagram/state/utils.js +36 -34
  111. package/dist/likec4diagram/types.d.ts +47 -3
  112. package/dist/likec4diagram/ui/FloatingSequenceActors.d.ts +6 -0
  113. package/dist/likec4diagram/ui/FloatingSequenceActors.js +155 -0
  114. package/dist/likec4diagram/ui/LayoutDriftFrame.js +2 -2
  115. package/dist/likec4diagram/ui/index.d.ts +2 -0
  116. package/dist/likec4diagram/ui/notation/NotationPanel.css.js +5 -5
  117. package/dist/likec4diagram/ui/sequence-outline/SequenceOutlinePanel.d.ts +2 -0
  118. package/dist/likec4diagram/ui/sequence-outline/SequenceOutlinePanel.js +540 -0
  119. package/dist/likec4diagram/ui/sequence-outline/state.d.ts +36 -0
  120. package/dist/likec4diagram/ui/sequence-outline/state.js +55 -0
  121. package/dist/likec4diagram/xyflow-diagram/diagram-view.d.ts +1 -1
  122. package/dist/likec4diagram/xyflow-diagram/diagram-view.js +112 -60
  123. package/dist/likec4diagram/xyflow-sequence/_types.d.ts +55 -5
  124. package/dist/likec4diagram/xyflow-sequence/const.d.ts +5 -5
  125. package/dist/likec4diagram/xyflow-sequence/const.js +4 -4
  126. package/dist/likec4diagram/xyflow-sequence/layouter.d.ts +30 -6
  127. package/dist/likec4diagram/xyflow-sequence/layouter.js +566 -0
  128. package/dist/likec4diagram/xyflow-sequence/{sequence-layout.d.ts → sequence-view-to-xy.d.ts} +8 -2
  129. package/dist/likec4diagram/xyflow-sequence/{sequence-layout.js → sequence-view-to-xy.js} +111 -14
  130. package/dist/likec4diagram/xyflow-sequence/sequence-view.d.ts +2 -7
  131. package/dist/likec4diagram/xyflow-sequence/sequence-view.js +144 -0
  132. package/dist/likec4diagram/xyflow-sequence/utils.d.ts +9 -1
  133. package/dist/likec4diagram/xyflow-sequence/utils.js +96 -0
  134. package/dist/navigationpanel/NavigationPanel.d.ts +5 -2
  135. package/dist/navigationpanel/NavigationPanel.js +58 -59
  136. package/dist/navigationpanel/NavigationPanelDropdown.js +45 -38
  137. package/dist/navigationpanel/_common.js +2 -2
  138. package/dist/navigationpanel/actor.actions.d.ts +19 -0
  139. package/dist/navigationpanel/actor.actions.js +45 -0
  140. package/dist/navigationpanel/actor.d.ts +34 -96
  141. package/dist/navigationpanel/actor.js +21 -84
  142. package/dist/navigationpanel/actor.setup.d.ts +98 -0
  143. package/dist/navigationpanel/actor.setup.js +31 -0
  144. package/dist/navigationpanel/comparepanel/DriftsSummary.js +4 -5
  145. package/dist/navigationpanel/controls/DetailsControls.js +7 -8
  146. package/dist/navigationpanel/dropdown/ProjectsMenu.js +1 -1
  147. package/dist/navigationpanel/editorpanel/styles.js +8 -8
  148. package/dist/navigationpanel/hooks.d.ts +20 -5
  149. package/dist/navigationpanel/hooks.js +4 -18
  150. package/dist/navigationpanel/styles.css.d.ts +1 -1
  151. package/dist/navigationpanel/walkthrough/ActiveWalkthroughControls.js +2 -2
  152. package/dist/navigationpanel/walkthrough/DynamicViewControls.d.ts +4 -4
  153. package/dist/navigationpanel/walkthrough/DynamicViewControls.js +23 -25
  154. package/dist/navigationpanel/walkthrough/WalkthroughPanel.js +5 -5
  155. package/dist/overlays/Overlays.d.ts +4 -2
  156. package/dist/overlays/Overlays.js +10 -10
  157. package/dist/overlays/element-details/ElementDetailsCard.css.js +17 -17
  158. package/dist/overlays/element-details/MetadataValue.js +15 -15
  159. package/dist/overlays/element-details/TabPanelDeployments.css.js +5 -5
  160. package/dist/overlays/element-details/TabPanelRelationships.css.js +11 -11
  161. package/dist/overlays/element-details/TabPanelRelationships.js +1 -1
  162. package/dist/overlays/element-details/TabPanelStructure.css.js +2 -2
  163. package/dist/overlays/element-details/TabPanelStructure.js +1 -1
  164. package/dist/overlays/element-details/actor.d.ts +2 -3
  165. package/dist/overlays/hooks.d.ts +28 -0
  166. package/dist/overlays/hooks.js +5 -0
  167. package/dist/overlays/overlay/Overlay.js +34 -25
  168. package/dist/overlays/overlaysActor.js +0 -1
  169. package/dist/overlays/relationship-details/custom/nodeTypes.js +1 -1
  170. package/dist/overlays/relationship-details/layout.js +1 -1
  171. package/dist/overlays/relationships-browser/SelectElement.css.js +2 -2
  172. package/dist/overlays/relationships-browser/actor.js +79 -78
  173. package/dist/overlays/relationships-browser/custom/nodeTypes.js +1 -1
  174. package/dist/overlays/relationships-browser/hooks.js +1 -1
  175. package/dist/overlays/relationships-browser/layout.js +2 -2
  176. package/dist/projects-overview/actor.js +4 -4
  177. package/dist/search/Search.js +1 -1
  178. package/dist/search/components/ElementsColumn.css.js +2 -2
  179. package/dist/search/components/ViewsColum.js +1 -1
  180. package/dist/search/components/_shared.css.d.ts +1 -1
  181. package/dist/search/components/_shared.css.js +23 -23
  182. package/dist/search/components/styles.css.js +4 -4
  183. package/dist/shadowroot/ShadowRoot.d.ts +1 -1
  184. package/dist/shadowroot/ShadowRoot.js +76 -28
  185. package/dist/styles2.js +1 -1
  186. package/dist/utils/defineActors.d.ts +21 -0
  187. package/dist/utils/defineActors.js +13 -0
  188. package/dist/utils/index.d.ts +1 -0
  189. package/dist/utils/index.js +5 -4
  190. package/dist/utils/readableText.d.ts +11 -0
  191. package/dist/utils/readableText.js +18 -0
  192. package/package.json +18 -30
  193. package/panda.buildinfo.json +270 -288
  194. package/styles-min.css +1 -1
  195. package/styles.css +1 -1
  196. package/adhoc-editor/package.json +0 -4
  197. package/dist/adhoc-editor/EditorPanel.d.ts +0 -1
  198. package/dist/adhoc-editor/EditorPanel.js +0 -106
  199. package/dist/adhoc-editor/ElementsTree.d.ts +0 -2
  200. package/dist/adhoc-editor/ElementsTree.js +0 -112
  201. package/dist/adhoc-editor/LikeC4AdHocViewEditor.d.ts +0 -4
  202. package/dist/adhoc-editor/LikeC4AdHocViewEditor.js +0 -83
  203. package/dist/adhoc-editor/components/Tree.d.ts +0 -48
  204. package/dist/adhoc-editor/components/Tree.js +0 -213
  205. package/dist/adhoc-editor/hooks.d.ts +0 -14
  206. package/dist/adhoc-editor/hooks.js +0 -34
  207. package/dist/adhoc-editor/index.d.ts +0 -2
  208. package/dist/adhoc-editor/index.js +0 -2
  209. package/dist/adhoc-editor/state/ActorProvider.d.ts +0 -5
  210. package/dist/adhoc-editor/state/ActorProvider.js +0 -37
  211. package/dist/adhoc-editor/state/actor.d.ts +0 -13
  212. package/dist/adhoc-editor/state/actor.editor.d.ts +0 -56
  213. package/dist/adhoc-editor/state/actor.editor.js +0 -167
  214. package/dist/adhoc-editor/state/actor.js +0 -14
  215. package/dist/adhoc-editor/state/actor.layouter.d.ts +0 -51
  216. package/dist/adhoc-editor/state/actor.layouter.js +0 -54
  217. package/dist/adhoc-editor/state/actor.types.d.ts +0 -63
  218. package/dist/adhoc-editor/state/actor.types.js +0 -25
  219. package/dist/adhoc-editor/state/panel.d.ts +0 -95
  220. package/dist/adhoc-editor/state/panel.js +0 -124
  221. package/dist/adhoc-editor/state/utils.d.ts +0 -17
  222. package/dist/adhoc-editor/state/utils.js +0 -25
  223. package/dist/adhoc-editor/useElementsTree.d.ts +0 -18
  224. package/dist/adhoc-editor/useElementsTree.js +0 -98
  225. package/dist/adhoc-editor/viewrules/ViewRulesPanel.d.ts +0 -6
  226. package/dist/context/ShadowRootContext.d.ts +0 -3
  227. package/dist/context/ShadowRootContext.js +0 -5
  228. package/dist/shadowroot/styles.d.ts +0 -13
  229. package/dist/shadowroot/styles.js +0 -60
@@ -100,7 +100,7 @@ function LikeC4Diagram({ onCanvasClick, onCanvasContextMenu, onCanvasDblClick, o
100
100
  onLayoutTypeChange
101
101
  },
102
102
  children: [/* @__PURE__ */ jsx(LikeC4Styles, { id }), /* @__PURE__ */ jsx(TagStylesProvider, {
103
- rootSelector: `#${id}`,
103
+ id,
104
104
  children: /* @__PURE__ */ jsx(RootContainer, {
105
105
  id,
106
106
  className,
@@ -26,7 +26,7 @@ export type ElementIconRendererProps = {
26
26
  };
27
27
  export type ElementIconRenderer = (props: ElementIconRendererProps) => ReactNode;
28
28
  export type LikeC4ColorScheme = 'light' | 'dark';
29
- export type OverrideReactFlowProps = Pick<ReactFlowProps<Types.AnyNode, Types.AnyEdge>, 'paneClickDistance' | 'nodeClickDistance' | 'selectionKeyCode' | 'panActivationKeyCode' | 'multiSelectionKeyCode' | 'zoomActivationKeyCode' | 'snapToGrid' | 'snapGrid' | 'onlyRenderVisibleElements' | 'nodesDraggable' | 'nodesFocusable' | 'elementsSelectable' | 'selectNodesOnDrag' | 'panOnDrag' | 'preventScrolling' | 'zoomOnScroll' | 'zoomOnPinch' | 'panOnScroll' | 'panOnScrollSpeed' | 'panOnScrollMode' | 'zoomOnDoubleClick' | 'nodeDragThreshold'>;
29
+ export type OverrideReactFlowProps = Pick<ReactFlowProps<Types.AnyNode, Types.AnyEdge>, 'paneClickDistance' | 'nodeClickDistance' | 'selectionKeyCode' | 'panActivationKeyCode' | 'multiSelectionKeyCode' | 'zoomActivationKeyCode' | 'snapToGrid' | 'snapGrid' | 'onlyRenderVisibleElements' | 'nodesDraggable' | 'nodesFocusable' | 'elementsSelectable' | 'selectNodesOnDrag' | 'panOnDrag' | 'preventScrolling' | 'zoomOnScroll' | 'zoomOnPinch' | 'panOnScroll' | 'panOnScrollSpeed' | 'panOnScrollMode' | 'zoomOnDoubleClick' | 'nodeDragThreshold' | 'edgesFocusable'>;
30
30
  export type PaddingUnit = 'px' | '%';
31
31
  export type PaddingWithUnit = `${number}${PaddingUnit}` | number;
32
32
  export type ViewPaddings = {
@@ -50,7 +50,7 @@ function LikeC4Styles({ id }) {
50
50
  return /* @__PURE__ */ jsx(MemoizedStyle, {
51
51
  id,
52
52
  nonce,
53
- colorsStyles: useMemo(() => generateBuiltInColorStyles($styles, rootSelector), [rootSelector, $styles])
53
+ colorsStyles: useMemo(() => generateBuiltInColorStyles($styles, rootSelector), [rootSelector, $styles.fingerprint])
54
54
  });
55
55
  }
56
56
  /**
@@ -98,14 +98,14 @@ function LikeC4View({ viewId, className, pannable = false, zoomable = false, kee
98
98
  enableSearch: false,
99
99
  ...isBrowserEnabled && {
100
100
  onCanvasClick: onNavigateToThisView,
101
- onNodeClick: onNavigateToThisView
101
+ onNodeClick: onNavigateToThisView,
102
+ onEdgeClick: onNavigateToThisView
102
103
  },
103
104
  reactFlowProps,
104
105
  renderNodes,
105
106
  ...props,
106
107
  children
107
108
  }), browserView && /* @__PURE__ */ jsxs(Overlay, {
108
- openDelay: 0,
109
109
  onClose: closeBrowser,
110
110
  children: [/* @__PURE__ */ jsx(LikeC4Diagram, {
111
111
  view: browserView,
@@ -35,7 +35,7 @@ export type ReactLikeC4Props<A extends t.aux.Any = t.aux.UnknownLayouted> = {
35
35
  style?: CSSProperties | undefined;
36
36
  mantineTheme?: any;
37
37
  /** Function to generate nonce attribute added to all generated `<style />` tags */
38
- styleNonce?: string | (() => string) | undefined;
38
+ styleNonce?: string | (() => string | undefined) | undefined;
39
39
  children?: ReactNode | undefined;
40
40
  } & Omit<LikeC4DiagramProperties<A>, 'view'> & LikeC4DiagramEventHandlers<A>;
41
41
  /**
@@ -12,11 +12,12 @@ declare function setDimmed<T extends WithDimmed>(value: T, dimmed: 'immediate' |
12
12
  declare function setDimmed(dimmed: 'immediate' | boolean): <T extends WithDimmed>(value: T) => T;
13
13
  declare function setHovered<T extends WithHovered>(value: T, hovered: boolean): T;
14
14
  declare function setHovered(hovered: boolean): <T extends WithHovered>(value: T) => T;
15
+ export declare function hasSubObject<E>(value: E, subobl: Partial<E>): boolean;
15
16
  type WithData<D> = {
16
17
  data: D;
17
18
  };
18
- declare function setData<E extends WithData<any>>(value: E, state: Partial<E['data']>): E;
19
- declare function setData<E extends WithData<any>>(state: Partial<NoInfer<E['data']>>): (value: E) => E;
19
+ declare function setData<E extends WithData<any>>(value: E, data: Partial<E['data']>): E;
20
+ declare function setData<E extends WithData<any>>(state: Partial<NoInfer<E>['data']>): (value: E) => E;
20
21
  export declare const Base: {
21
22
  setDimmed: typeof setDimmed;
22
23
  setHovered: typeof setHovered;
package/dist/base/Base.js CHANGED
@@ -1,37 +1,25 @@
1
- import "../_virtual/_rolldown/runtime.js";
2
- import { hasSubObject } from "remeda";
1
+ import { __name } from "../_virtual/_rolldown/runtime.js";
2
+ import { deepEqual } from "fast-equals";
3
+ import { entries } from "remeda";
3
4
  //#region src/base/Base.ts
4
- var _setDimmed = (v, dimmed) => (v.data.dimmed ?? false) === dimmed ? v : {
5
- ...v,
6
- data: {
7
- ...v.data,
8
- dimmed
9
- }
10
- };
5
+ var mergeData = (v, data) => Object.assign({}, v, { data: Object.assign({}, v.data, data) });
6
+ var _setDimmed = (v, dimmed) => (v.data.dimmed ?? false) === dimmed ? v : mergeData(v, { dimmed });
11
7
  function setDimmed(arg1, arg2) {
12
8
  if (arg2 !== void 0) return _setDimmed(arg1, arg2);
13
9
  return (v) => _setDimmed(v, arg1);
14
10
  }
15
- var _setHovered = (v, hovered) => (v.data.hovered ?? false) === hovered ? v : {
16
- ...v,
17
- data: {
18
- ...v.data,
19
- hovered
20
- }
21
- };
11
+ var _setHovered = (v, hovered) => (v.data.hovered ?? false) === hovered ? v : mergeData(v, { hovered });
22
12
  function setHovered(arg1, arg2) {
23
13
  if (arg2 !== void 0) return _setHovered(arg1, arg2);
24
14
  return (v) => _setHovered(v, arg1);
25
15
  }
26
- function _setData(value, state) {
27
- if (hasSubObject(value.data, state)) return value;
28
- return {
29
- ...value,
30
- data: {
31
- ...value.data,
32
- ...state
33
- }
34
- };
16
+ function hasSubObject$1(value, subobl) {
17
+ return value === subobl || entries(subobl).every(([key, v]) => deepEqual(value[key] ?? void 0, v));
18
+ }
19
+ __name(hasSubObject$1, "hasSubObject");
20
+ function _setData(value, data) {
21
+ if (hasSubObject$1(value.data, data)) return value;
22
+ return mergeData(value, data);
35
23
  }
36
24
  function setData(arg1, arg2) {
37
25
  if (arg2 !== void 0) return _setData(arg1, arg2);
@@ -43,4 +31,4 @@ var Base = {
43
31
  setData
44
32
  };
45
33
  //#endregion
46
- export { Base };
34
+ export { Base, hasSubObject$1 as hasSubObject };
@@ -8,8 +8,9 @@ export type BaseXYFlowProps<NodeType extends BaseNode, EdgeType extends BaseEdge
8
8
  zoomable: boolean;
9
9
  nodesSelectable: boolean;
10
10
  nodesDraggable: boolean;
11
+ showControls?: boolean;
11
12
  background?: 'transparent' | 'solid' | XYBackground;
12
13
  fitViewPadding?: ViewPadding | undefined;
13
14
  onViewportResize?: undefined | (() => void);
14
15
  } & SetRequired<Omit<ReactFlowProps<NodeType, EdgeType>, 'defaultNodes' | 'defaultEdges' | 'fitViewOptions' | 'nodesSelectable' | 'nodesDraggable'>, 'nodes' | 'edges' | 'onNodesChange' | 'onEdgesChange'>>;
15
- export declare function BaseXYFlow<NodeType extends BaseNode, EdgeType extends BaseEdge>({ nodes, edges, onEdgesChange, onNodesChange, className, pannable, zoomable, nodesSelectable, nodesDraggable, background, children, colorMode, fitViewPadding, fitView, zoomOnDoubleClick, onViewportResize, onMoveEnd, onNodeMouseEnter, onNodeMouseLeave, onEdgeMouseEnter, onEdgeMouseLeave, ...props }: BaseXYFlowProps<NodeType, EdgeType>): import("react").JSX.Element;
16
+ export declare function BaseXYFlow<NodeType extends BaseNode, EdgeType extends BaseEdge>({ nodes, edges, onEdgesChange, onNodesChange, className, pannable, zoomable, nodesSelectable, nodesDraggable, background, children, colorMode, fitViewPadding, fitView, zoomOnDoubleClick, onViewportResize, onMoveEnd, onNodeMouseEnter, onNodeMouseLeave, onEdgeMouseEnter, onEdgeMouseLeave, onKeyDownCapture, ariaLabelConfig, nodesFocusable, edgesFocusable, showControls, ...props }: BaseXYFlowProps<NodeType, EdgeType>): import("react").JSX.Element;
@@ -2,18 +2,45 @@ import "../_virtual/_rolldown/runtime.js";
2
2
  import { Background as Background$1 } from "./Background.js";
3
3
  import { useCallbackRef } from "../hooks/useCallbackRef.js";
4
4
  import { useUpdateEffect } from "../hooks/useUpdateEffect.js";
5
- import { useIsZoomTooSmall, useXYStoreApi } from "../hooks/useXYFlow.js";
5
+ import { useIsZoomTooSmall, useXYFlow, useXYStoreApi } from "../hooks/useXYFlow.js";
6
6
  import { roundDpr } from "../utils/roundDpr.js";
7
7
  import { stopPropagation } from "../utils/xyflow.js";
8
8
  import { Base } from "./Base.js";
9
9
  import { MinZoom } from "./const.js";
10
+ import { getKeyboardZoomAction } from "./keyboardZoom.js";
10
11
  import { cx } from "@likec4/styles/css";
11
12
  import { useMemo } from "react";
12
13
  import { jsx, jsxs } from "react/jsx-runtime";
13
14
  import { ReactFlow, useStore } from "@xyflow/react";
14
15
  import { useMantineColorScheme } from "@mantine/core";
15
16
  //#region src/base/BaseXYFlow.tsx
16
- function BaseXYFlow({ nodes, edges, onEdgesChange, onNodesChange, className, pannable = true, zoomable = true, nodesSelectable = true, nodesDraggable = false, background = "dots", children, colorMode, fitViewPadding = 0, fitView = true, zoomOnDoubleClick = false, onViewportResize, onMoveEnd, onNodeMouseEnter, onNodeMouseLeave, onEdgeMouseEnter, onEdgeMouseLeave, ...props }) {
17
+ var likec4AriaLabelConfig = {
18
+ "node.a11yDescription.default": "Press Enter or Space to select this node and reveal its actions.",
19
+ "node.a11yDescription.keyboardDisabled": "Keyboard activation is disabled.",
20
+ "edge.a11yDescription.default": "Press Enter or Space to select this relationship and reveal its actions."
21
+ };
22
+ function activateFocusedElement(event) {
23
+ if (event.repeat || event.key !== "Enter" && event.key !== " ") return;
24
+ const target = event.target;
25
+ if (!(target instanceof Element)) return;
26
+ const interactive = target.closest("a,button,input,textarea,select,[role=\"button\"],[role=\"link\"],[contenteditable=\"true\"]");
27
+ if (interactive && !interactive.classList.contains("react-flow__node") && !interactive.classList.contains("react-flow__edge")) return;
28
+ const flowElement = target.closest(".react-flow__node[data-id], .react-flow__edge[data-id]");
29
+ const view = flowElement?.ownerDocument.defaultView;
30
+ if (!flowElement || !view) return;
31
+ event.preventDefault();
32
+ const rect = flowElement.getBoundingClientRect();
33
+ flowElement.dispatchEvent(new view.MouseEvent("click", {
34
+ bubbles: true,
35
+ cancelable: true,
36
+ button: 0,
37
+ clientX: rect.left + rect.width / 2,
38
+ clientY: rect.top + rect.height / 2,
39
+ detail: 1,
40
+ view
41
+ }));
42
+ }
43
+ function BaseXYFlow({ nodes, edges, onEdgesChange, onNodesChange, className, pannable = true, zoomable = true, nodesSelectable = true, nodesDraggable = false, background = "dots", children, colorMode, fitViewPadding = 0, fitView = true, zoomOnDoubleClick = false, onViewportResize, onMoveEnd, onNodeMouseEnter, onNodeMouseLeave, onEdgeMouseEnter, onEdgeMouseLeave, onKeyDownCapture, ariaLabelConfig, nodesFocusable = nodesDraggable || nodesSelectable, edgesFocusable = false, showControls = false, ...props }) {
17
44
  const fitViewOptions = useMemo(() => ({
18
45
  minZoom: MinZoom,
19
46
  maxZoom: 1,
@@ -22,9 +49,30 @@ function BaseXYFlow({ nodes, edges, onEdgesChange, onNodesChange, className, pan
22
49
  }), [fitViewPadding]);
23
50
  const isBgWithPattern = background !== "transparent" && background !== "solid";
24
51
  const isZoomTooSmall = useIsZoomTooSmall();
52
+ const xyflow = useXYFlow();
25
53
  const xystore = useXYStoreApi();
26
54
  const { colorScheme } = useMantineColorScheme();
27
55
  if (!colorMode) colorMode = colorScheme === "auto" ? "system" : colorScheme;
56
+ const tabIndex = props.tabIndex ?? (zoomable ? 0 : void 0);
57
+ const ariaLabel = props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0 || tabIndex === void 0 ? props["aria-label"] : "Interactive diagram";
58
+ const onKeyDown = useCallbackRef((event) => {
59
+ props.onKeyDown?.(event);
60
+ if (event.defaultPrevented || !zoomable) return;
61
+ const action = getKeyboardZoomAction(event.nativeEvent);
62
+ if (!action) return;
63
+ event.preventDefault();
64
+ switch (action) {
65
+ case "zoom-in":
66
+ xyflow.zoomIn();
67
+ return;
68
+ case "zoom-out":
69
+ xyflow.zoomOut();
70
+ return;
71
+ case "reset":
72
+ xyflow.fitView(fitViewOptions);
73
+ return;
74
+ }
75
+ });
28
76
  return /* @__PURE__ */ jsxs(ReactFlow, {
29
77
  colorMode,
30
78
  nodes,
@@ -51,9 +99,13 @@ function BaseXYFlow({ nodes, edges, onEdgesChange, onNodesChange, className, pan
51
99
  selectionKeyCode: null
52
100
  },
53
101
  elementsSelectable: nodesSelectable,
54
- nodesFocusable: nodesDraggable || nodesSelectable,
55
- edgesFocusable: false,
102
+ nodesFocusable,
103
+ edgesFocusable,
56
104
  nodesDraggable,
105
+ ariaLabelConfig: {
106
+ ...likec4AriaLabelConfig,
107
+ ...ariaLabelConfig
108
+ },
57
109
  nodeDragThreshold: 4,
58
110
  nodeClickDistance: 3,
59
111
  paneClickDistance: 3,
@@ -121,7 +173,14 @@ function BaseXYFlow({ nodes, edges, onEdgesChange, onNodesChange, className, pan
121
173
  }),
122
174
  onNodeDoubleClick: stopPropagation,
123
175
  onEdgeDoubleClick: stopPropagation,
176
+ onKeyDownCapture: useCallbackRef((event) => {
177
+ onKeyDownCapture?.(event);
178
+ if (!event.defaultPrevented) activateFocusedElement(event);
179
+ }),
124
180
  ...props,
181
+ "aria-label": ariaLabel,
182
+ tabIndex,
183
+ onKeyDown,
125
184
  children: [
126
185
  isBgWithPattern && /* @__PURE__ */ jsx(Background$1, { background }),
127
186
  onViewportResize && /* @__PURE__ */ jsx(ViewportResizeHanlder, { onViewportResize }),
@@ -0,0 +1,3 @@
1
+ export type KeyboardZoomAction = 'zoom-in' | 'zoom-out' | 'reset';
2
+ export declare function isEditableKeyboardTarget(target: EventTarget | null): boolean;
3
+ export declare function getKeyboardZoomAction(event: Pick<KeyboardEvent, 'key' | 'ctrlKey' | 'metaKey' | 'target'>): KeyboardZoomAction | null;
@@ -0,0 +1,20 @@
1
+ import "../_virtual/_rolldown/runtime.js";
2
+ //#region src/base/keyboardZoom.ts
3
+ function isEditableKeyboardTarget(target) {
4
+ if (!(target instanceof HTMLElement)) return false;
5
+ const tagName = target.tagName.toLowerCase();
6
+ return tagName === "input" || tagName === "textarea" || tagName === "select" || target.isContentEditable;
7
+ }
8
+ function getKeyboardZoomAction(event) {
9
+ if (!event.ctrlKey && !event.metaKey || isEditableKeyboardTarget(event.target)) return null;
10
+ switch (event.key) {
11
+ case "+":
12
+ case "=": return "zoom-in";
13
+ case "-":
14
+ case "_": return "zoom-out";
15
+ case "0": return "reset";
16
+ default: return null;
17
+ }
18
+ }
19
+ //#endregion
20
+ export { getKeyboardZoomAction, isEditableKeyboardTarget };
@@ -1,6 +1,7 @@
1
1
  import "../_virtual/_rolldown/runtime.js";
2
+ import { hasSubObject as hasSubObject$1 } from "./Base.js";
2
3
  import { deepEqual } from "fast-equals";
3
- import { hasSubObject, isDefined, isShallowEqual, pickBy } from "remeda";
4
+ import { isDefined, isShallowEqual, pickBy } from "remeda";
4
5
  //#region src/base/updateEdges.ts
5
6
  var EMPTY_OBJ = {};
6
7
  function _update(current, updated) {
@@ -9,23 +10,13 @@ function _update(current, updated) {
9
10
  const existing = current.find((n) => n.id === update.id && n.type === update.type && n.source === update.source && n.target === update.target);
10
11
  if (!existing) return update;
11
12
  if (existing === update) return existing;
12
- const isSameData = hasSubObject(existing.data, update.data);
13
+ const isSameData = hasSubObject$1(existing.data, update.data);
13
14
  let data = isSameData ? existing.data : update.data;
14
15
  if (!isSameData) {
15
- if (isDefined(existing.data.hovered) && !isDefined(update.data.hovered)) data = {
16
- ...data,
17
- hovered: existing.data.hovered
18
- };
19
- if (isDefined(existing.data.dimmed) && !isDefined(update.data.dimmed)) data = {
20
- ...data,
21
- dimmed: existing.data.dimmed
22
- };
23
- if (isDefined(existing.data.active) && !isDefined(update.data.active)) data = {
24
- ...data,
25
- active: existing.data.active
26
- };
27
- }
28
- if (isSameData && deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.focusable, update.focusable ?? existing.focusable) && deepEqual(existing.animated, update.animated ?? existing.animated) && deepEqual(existing.className, update.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.label, update.label) && deepEqual(existing.sourceHandle, update.sourceHandle) && deepEqual(existing.targetHandle, update.targetHandle) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) return existing;
16
+ if (isDefined(existing.data.hovered) && !isDefined(data.hovered)) data = Object.assign({ hovered: existing.data.hovered }, data);
17
+ if (isDefined(existing.data.dimmed) && !isDefined(data.dimmed)) data = Object.assign({ dimmed: existing.data.dimmed }, data);
18
+ if (isDefined(existing.data.active) && !isDefined(data.active)) data = Object.assign({ active: existing.data.active }, data);
19
+ } else if (deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.animated, update.animated ?? existing.animated) && deepEqual(existing.ariaLabel, update.ariaLabel ?? existing.ariaLabel) && deepEqual(existing.ariaRole, update.ariaRole ?? existing.ariaRole) && deepEqual(existing.className, update.className ?? existing.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.label, update.label) && deepEqual(existing.sourceHandle, update.sourceHandle ?? existing.sourceHandle) && deepEqual(existing.targetHandle, update.targetHandle ?? existing.targetHandle) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) return existing;
29
20
  return {
30
21
  ...pickBy(existing, isDefined),
31
22
  ...pickBy(update, isDefined),
@@ -13,19 +13,13 @@ function _update(current, updated) {
13
13
  const isSameData = hasSubObject(existing.data, update.data);
14
14
  let data = isSameData ? existing.data : update.data;
15
15
  if (!isSameData) {
16
- if (isDefined(existing.data.hovered) && !isDefined(update.data.hovered)) data = {
17
- ...data,
18
- hovered: existing.data.hovered
19
- };
20
- if (isDefined(existing.data.dimmed) && !isDefined(update.data.dimmed)) data = {
21
- ...data,
22
- dimmed: existing.data.dimmed
23
- };
16
+ if (isDefined(existing.data.hovered) && !isDefined(data.hovered)) data = Object.assign({ hovered: existing.data.hovered }, data);
17
+ if (isDefined(existing.data.dimmed) && !isDefined(data.dimmed)) data = Object.assign({ dimmed: existing.data.dimmed }, data);
24
18
  }
25
19
  const { width: existingWidth, height: existingHeight } = getNodeDimensions(existing);
26
20
  const haveHandles = Object.hasOwn(existing, "handles") || Object.hasOwn(update, "handles");
27
21
  const isSameHandles = !haveHandles || deepEqual(existing.handles ?? [], update.handles ?? []);
28
- if (isSameData && isSameHandles && deepEqual(existingWidth, update.width ?? update.initialWidth) && deepEqual(existingHeight, update.height ?? update.initialHeight) && deepEqual(existing.parentId ?? null, update.parentId ?? null) && deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.focusable, update.focusable ?? existing.focusable) && deepEqual(existing.draggable, update.draggable ?? existing.draggable) && deepEqual(existing.dragHandle, update.dragHandle) && deepEqual(existing.className, update.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.position, update.position) && deepEqual(existing.domAttributes ?? EMPTY_OBJ, update.domAttributes ?? EMPTY_OBJ) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) return existing;
22
+ if (isSameData && isSameHandles && deepEqual(existingWidth, update.width ?? update.initialWidth) && deepEqual(existingHeight, update.height ?? update.initialHeight) && deepEqual(existing.parentId ?? null, update.parentId ?? null) && deepEqual(existing.hidden, update.hidden ?? existing.hidden) && deepEqual(existing.selected, update.selected ?? existing.selected) && deepEqual(existing.selectable, update.selectable ?? existing.selectable) && deepEqual(existing.focusable, update.focusable ?? existing.focusable) && deepEqual(existing.draggable, update.draggable ?? existing.draggable) && deepEqual(existing.ariaLabel, update.ariaLabel ?? existing.ariaLabel) && deepEqual(existing.ariaRole, update.ariaRole ?? existing.ariaRole) && deepEqual(existing.dragHandle, update.dragHandle) && deepEqual(existing.className, update.className) && deepEqual(existing.zIndex, update.zIndex ?? existing.zIndex) && deepEqual(existing.position, update.position) && deepEqual(existing.domAttributes ?? EMPTY_OBJ, update.domAttributes ?? EMPTY_OBJ) && deepEqual(existing.style ?? EMPTY_OBJ, update.style ?? EMPTY_OBJ)) return existing;
29
23
  const handles = haveHandles && isSameHandles ? existing.handles : update.handles;
30
24
  return {
31
25
  ...pickBy(existing, (v, k) => isDefined(v) && k !== "parentId" && k !== "handles"),
@@ -3,7 +3,8 @@ import { Simplify } from 'type-fest';
3
3
  import { BaseNodeProps } from '../../base/types';
4
4
  type CompoundActionButtonProps = Simplify<BaseNodeProps & {
5
5
  icon?: ReactNode;
6
+ ariaLabel?: string;
6
7
  onClick: (e: ReactMouseEvent) => void;
7
8
  }>;
8
- export declare function CompoundActionButton({ data: { hovered: isHovered, }, icon, onClick, }: CompoundActionButtonProps): import("react").JSX.Element;
9
+ export declare function CompoundActionButton({ selected, data: { hovered: isHovered, }, icon, ariaLabel, onClick, }: CompoundActionButtonProps): import("react").JSX.Element;
9
10
  export {};
@@ -27,8 +27,9 @@ var variants = {
27
27
  },
28
28
  whileTap: { scale: 1 }
29
29
  };
30
- function CompoundActionButton({ data: { hovered: isHovered = false }, icon, onClick }) {
30
+ function CompoundActionButton({ selected = false, data: { hovered: isHovered = false }, icon, ariaLabel = "Navigate to view", onClick }) {
31
31
  const isHoverDebounced = useDebouncedValue(isHovered, isHovered ? 130 : 0)[0] && isHovered;
32
+ const isActionVisible = selected || isHoverDebounced;
32
33
  let variant = isHoverDebounced ? "hovered" : "normal";
33
34
  return /* @__PURE__ */ jsx(m.div, {
34
35
  initial: false,
@@ -41,7 +42,9 @@ function CompoundActionButton({ data: { hovered: isHovered = false }, icon, onCl
41
42
  tabIndex: -1,
42
43
  children: /* @__PURE__ */ jsx(ActionIcon, {
43
44
  className: cx("nodrag nopan", compoundActionBtn({ delay: isHovered && !isHoverDebounced }), actionBtn({ variant: "transparent" })),
44
- tabIndex: -1,
45
+ tabIndex: isActionVisible ? 0 : -1,
46
+ inert: isActionVisible ? void 0 : true,
47
+ "aria-label": ariaLabel,
45
48
  onClick,
46
49
  onDoubleClick: stopPropagation,
47
50
  children: icon ?? /* @__PURE__ */ jsx(IconZoomScan, { stroke: 2 })
@@ -3,7 +3,8 @@ import { Simplify } from 'type-fest';
3
3
  import { BaseNodeProps } from '../../base/types';
4
4
  type CompoundDetailsButtonProps = Simplify<BaseNodeProps & {
5
5
  icon?: ReactNode;
6
+ ariaLabel?: string;
6
7
  onClick: (e: ReactMouseEvent) => void;
7
8
  }>;
8
- export declare function CompoundDetailsButton({ data: { hovered: isHovered, }, icon, onClick, }: CompoundDetailsButtonProps): import("react").JSX.Element;
9
+ export declare function CompoundDetailsButton({ selected, data: { hovered: isHovered, }, icon, ariaLabel, onClick, }: CompoundDetailsButtonProps): import("react").JSX.Element;
9
10
  export {};
@@ -15,8 +15,9 @@ var variants = {
15
15
  whileHover: { scale: 1.4 },
16
16
  whileTap: { scale: 1 }
17
17
  };
18
- function CompoundDetailsButton({ data: { hovered: isHovered = false }, icon, onClick }) {
18
+ function CompoundDetailsButton({ selected = false, data: { hovered: isHovered = false }, icon, ariaLabel = "Open details", onClick }) {
19
19
  const isHoverDebounced = useDebouncedValue(isHovered, isHovered ? 130 : 0)[0] && isHovered;
20
+ const isActionVisible = selected || isHoverDebounced;
20
21
  const variant = isHoverDebounced ? "hovered" : "normal";
21
22
  return /* @__PURE__ */ jsx(m.div, {
22
23
  initial: false,
@@ -28,7 +29,9 @@ function CompoundDetailsButton({ data: { hovered: isHovered = false }, icon, onC
28
29
  tabIndex: -1,
29
30
  children: /* @__PURE__ */ jsx(ActionIcon, {
30
31
  className: cx("nodrag nopan", compoundActionBtn({ delay: isHovered && !isHoverDebounced }), actionBtn({ variant: "transparent" })),
31
- tabIndex: -1,
32
+ tabIndex: isActionVisible ? 0 : -1,
33
+ inert: isActionVisible ? void 0 : true,
34
+ "aria-label": ariaLabel,
32
35
  onClick,
33
36
  onDoubleClick: stopPropagation,
34
37
  children: icon ?? /* @__PURE__ */ jsx(IconId, {
@@ -8,6 +8,12 @@ type RequiredData = {
8
8
  };
9
9
  type CompoundTitleProps = {
10
10
  data: RequiredData;
11
+ /**
12
+ * Opt-in: hide the title from assistive technologies. The main diagram sets
13
+ * this because the compound node's accessible label already conveys the
14
+ * title, so re-exposing it here would cause a duplicate announcement.
15
+ */
16
+ 'aria-hidden'?: boolean | undefined;
11
17
  };
12
- export declare function CompoundTitle({ data }: CompoundTitleProps): import("react").JSX.Element;
18
+ export declare function CompoundTitle({ data, 'aria-hidden': ariaHidden }: CompoundTitleProps): import("react").JSX.Element;
13
19
  export {};
@@ -2,9 +2,10 @@ import "../../_virtual/_rolldown/runtime.js";
2
2
  import { IconRenderer } from "../../context/IconRenderer.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/base-primitives/compound/CompoundTitle.tsx
5
- function CompoundTitle({ data }) {
5
+ function CompoundTitle({ data, "aria-hidden": ariaHidden }) {
6
6
  return /* @__PURE__ */ jsxs("div", {
7
7
  className: "likec4-compound-title-container",
8
+ "aria-hidden": ariaHidden,
8
9
  children: [IconRenderer({
9
10
  element: data,
10
11
  className: "likec4-compound-icon"
@@ -1,4 +1,4 @@
1
- import { RecipeRuntimeFn } from '../../../styled-system';
1
+ import { RecipeRuntimeFn } from '../../../styled-system/types';
2
2
  export declare const compoundActionBtn: RecipeRuntimeFn<{
3
3
  delay: {
4
4
  true: {
@@ -1,7 +1,8 @@
1
1
  import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
2
2
  type EdgeActionBtnProps = {
3
3
  icon?: ReactNode;
4
+ ariaLabel?: string;
4
5
  onClick: (e: ReactMouseEvent) => void;
5
6
  };
6
- export declare function EdgeActionButton({ icon, onClick }: EdgeActionBtnProps): import("react").JSX.Element;
7
+ export declare function EdgeActionButton({ icon, ariaLabel, onClick }: EdgeActionBtnProps): import("react").JSX.Element;
7
8
  export {};
@@ -6,12 +6,13 @@ import { jsx } from "react/jsx-runtime";
6
6
  import { ActionIcon } from "@mantine/core";
7
7
  import { edgeActionBtn } from "@likec4/styles/recipes";
8
8
  //#region src/base-primitives/edge/EdgeActionButton.tsx
9
- function EdgeActionButton({ icon, onClick }) {
9
+ function EdgeActionButton({ icon, ariaLabel = "Navigate to view", onClick }) {
10
10
  return /* @__PURE__ */ jsx(ActionIcon, {
11
11
  className: cx("nodrag nopan", edgeActionBtn()),
12
12
  onPointerDownCapture: stopPropagation,
13
13
  onClick,
14
14
  role: "button",
15
+ "aria-label": ariaLabel,
15
16
  onDoubleClick: stopPropagation,
16
17
  children: icon ?? /* @__PURE__ */ jsx(IconZoomScan, {})
17
18
  });
@@ -7,5 +7,5 @@ type EdgeContainerProps = PropsWithChildren<BaseEdgePropsWithData<Data> & {
7
7
  component?: 'g' | 'svg' | undefined;
8
8
  className?: string | undefined;
9
9
  }>;
10
- export declare function EdgeContainer({ className, component, selectable, selected, data: { color, hovered: isHovered, active: isActive, dimmed: isDimmed, ...data }, animated, children, style, }: EdgeContainerProps): import("react").JSX.Element;
10
+ export declare function EdgeContainer({ className, component, selectable, selected, data: { color, hovered: isHovered, active: isActive, dimmed: isDimmed, ...data }, animated, children, style, ...rest }: EdgeContainerProps): import("react").JSX.Element;
11
11
  export {};
@@ -1,9 +1,10 @@
1
1
  import "../../_virtual/_rolldown/runtime.js";
2
2
  import { cx } from "@likec4/styles/css";
3
3
  import { jsx } from "react/jsx-runtime";
4
+ import { pickBy } from "remeda";
4
5
  import { invariant } from "@likec4/core";
5
6
  //#region src/base-primitives/edge/EdgeContainer.tsx
6
- function EdgeContainer({ className, component = "g", selectable = false, selected = false, data: { color = "gray", hovered: isHovered = false, active: isActive = false, dimmed: isDimmed = false, ...data }, animated = false, children, style }) {
7
+ function EdgeContainer({ className, component = "g", selectable = false, selected = false, data: { color = "gray", hovered: isHovered = false, active: isActive = false, dimmed: isDimmed = false, ...data }, animated = false, children, style, ...rest }) {
7
8
  animated = animated || isActive;
8
9
  const props = {
9
10
  className: cx(className, "likec4-edge-container", selected && "selected", selectable && "selectable"),
@@ -13,7 +14,8 @@ function EdgeContainer({ className, component = "g", selectable = false, selecte
13
14
  "data-likec4-hovered": isHovered,
14
15
  ...animated && { "data-likec4-animated": animated },
15
16
  ...selected && { "data-likec4-selected": selected },
16
- ...isDimmed !== false && { "data-likec4-dimmed": isDimmed }
17
+ ...isDimmed !== false && { "data-likec4-dimmed": isDimmed },
18
+ ...pickBy(rest, (value, key) => value !== void 0 && key.startsWith("data-"))
17
19
  };
18
20
  if (component === "svg") return /* @__PURE__ */ jsx("svg", {
19
21
  style,
@@ -7,6 +7,8 @@ type Data = UndefinedOnPartialDeep<Pick<DiagramEdge, 'label' | 'technology'>>;
7
7
  type EdgeLabelProps = HTMLMotionProps<'div'> & {
8
8
  children?: ReactNode;
9
9
  edgeProps: BaseEdgePropsWithData<Data>;
10
+ isSequenceStep?: boolean;
11
+ stepNum?: number;
10
12
  pointerEvents?: 'all' | 'none';
11
13
  };
12
14
  export declare const EdgeLabel: ForwardRefExoticComponent<Omit<EdgeLabelProps, "ref"> & RefAttributes<HTMLDivElement>>;
@@ -3,14 +3,11 @@ import { cx } from "@likec4/styles/css";
3
3
  import { forwardRef } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { isTruthy } from "remeda";
6
- import { extractStep, isStepEdgeId } from "@likec4/core";
7
6
  import { Box } from "@likec4/styles/jsx";
8
7
  import * as m from "motion/react-m";
9
8
  import { edgeLabel } from "@likec4/styles/recipes";
10
9
  //#region src/base-primitives/edge/EdgeLabel.tsx
11
- var EdgeLabel = forwardRef(({ edgeProps: { id, data: { label, technology, hovered: isHovered = false }, selected = false, selectable = false }, pointerEvents = "all", className, children, ...rest }, ref) => {
12
- const stepNum = isStepEdgeId(id) ? extractStep(id) : null;
13
- const isStepEdge = stepNum !== null;
10
+ var EdgeLabel = forwardRef(({ edgeProps: { id, data: { label, technology, hovered: isHovered = false }, selected = false, selectable = false }, isSequenceStep: isStepEdge = false, stepNum, pointerEvents = "all", className, children, ...rest }, ref) => {
14
11
  const hasLabel = isTruthy(label) || isTruthy(technology);
15
12
  return /* @__PURE__ */ jsxs(m.div, {
16
13
  ref,
@@ -22,7 +19,7 @@ var EdgeLabel = forwardRef(({ edgeProps: { id, data: { label, technology, hovere
22
19
  "data-edge-id": id,
23
20
  animate: { scale: isHovered && !selected ? 1.06 : 1 },
24
21
  ...rest,
25
- children: [stepNum !== null && /* @__PURE__ */ jsx(Box, {
22
+ children: [isStepEdge && stepNum && /* @__PURE__ */ jsx(Box, {
26
23
  className: "likec4-edge-label__step-number",
27
24
  children: stepNum
28
25
  }), hasLabel && /* @__PURE__ */ jsxs(Box, {
@@ -35,6 +35,7 @@ export declare function ElementActionButtons({ selected, data: { hovered: isHove
35
35
  export declare namespace ElementActionButtons {
36
36
  type Item = {
37
37
  key?: string;
38
+ ariaLabel?: string;
38
39
  icon?: ReactNode;
39
40
  onClick: (e: ReactMouseEvent) => void;
40
41
  };
@@ -66,6 +66,7 @@ function ElementActionButtons({ selected = false, data: { hovered: isHovered = f
66
66
  break;
67
67
  default: variant = "normal";
68
68
  }
69
+ const isActionVisible = isHovered || selected;
69
70
  return /* @__PURE__ */ jsx("div", {
70
71
  className: actionButtons(),
71
72
  children: /* @__PURE__ */ jsx(m.div, {
@@ -83,7 +84,9 @@ function ElementActionButtons({ selected = false, data: { hovered: isHovered = f
83
84
  initial: false,
84
85
  whileTap: { scale: 1 },
85
86
  whileHover: { scale: 1.3 },
86
- tabIndex: -1,
87
+ tabIndex: isActionVisible ? 0 : -1,
88
+ inert: isActionVisible ? void 0 : true,
89
+ "aria-label": button.ariaLabel ?? button.key ?? "Element action",
87
90
  onClick: button.onClick,
88
91
  onDoubleClick: stopPropagation,
89
92
  children: button.icon || /* @__PURE__ */ jsx(IconBolt, {})
@@ -47,7 +47,9 @@ type SlotProps = {
47
47
  * </ElementData.Root>
48
48
  * ```
49
49
  */
50
- export declare function ElementData({ data }: ElementDataProps): import("react").JSX.Element;
50
+ export declare function ElementData({ data, 'aria-hidden': ariaHidden }: ElementDataProps & {
51
+ 'aria-hidden'?: boolean | undefined;
52
+ }): import("react").JSX.Element;
51
53
  export declare namespace ElementData {
52
54
  var Root: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & ElementDataProps & import("react").RefAttributes<HTMLDivElement>>;
53
55
  var Icon: ({ data, ...props }: IconProps) => import("react").JSX.Element;
@@ -101,9 +101,10 @@ var Description = forwardRef(({ data: { description }, className, ...props }, re
101
101
  * </ElementData.Root>
102
102
  * ```
103
103
  */
104
- function ElementData({ data }) {
104
+ function ElementData({ data, "aria-hidden": ariaHidden }) {
105
105
  return /* @__PURE__ */ jsxs(Root, {
106
106
  data,
107
+ "aria-hidden": ariaHidden,
107
108
  children: [/* @__PURE__ */ jsx(Icon, { data }), /* @__PURE__ */ jsxs(Content, { children: [
108
109
  /* @__PURE__ */ jsx(Title, { data }),
109
110
  /* @__PURE__ */ jsx(Technology, { data }),
@@ -4,7 +4,8 @@ type ElementDetailsButtonProps = {
4
4
  selected?: boolean;
5
5
  data: BaseNodeData;
6
6
  icon?: ReactNode;
7
+ ariaLabel?: string;
7
8
  onClick: (e: ReactMouseEvent) => void;
8
9
  };
9
- export declare function ElementDetailsButton({ selected, data: { hovered: isHovered, }, icon, onClick, }: ElementDetailsButtonProps): import("react").JSX.Element;
10
+ export declare function ElementDetailsButton({ selected, data: { hovered: isHovered, }, icon, ariaLabel, onClick, }: ElementDetailsButtonProps): import("react").JSX.Element;
10
11
  export {};