@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
@@ -0,0 +1,566 @@
1
+ import "../../_virtual/_rolldown/runtime.js";
2
+ import { normalizeSpacing, rectFromSteps } from "./utils.js";
3
+ import { filter, first, flatMap, hasAtLeast, last, map, only, pipe } from "remeda";
4
+ import { invariant, nonNullable, nonexhaustive } from "@likec4/core/utils";
5
+ import { flowGuards } from "@likec4/core/types";
6
+ import * as kiwi from "@lume/kiwi";
7
+ import defu from "defu";
8
+ //#region src/likec4diagram/xyflow-sequence/layouter.ts
9
+ var Strength = {
10
+ required: kiwi.Strength.required,
11
+ strong: kiwi.Strength.strong,
12
+ medium: kiwi.Strength.medium,
13
+ soft: kiwi.Strength.create(0, .8, 1),
14
+ weak: kiwi.Strength.weak
15
+ };
16
+ var SequenceViewLayouter = class {
17
+ #flow;
18
+ #solver = new kiwi.Solver();
19
+ #actors;
20
+ #compounds = [];
21
+ #viewportRight;
22
+ #viewportBottom;
23
+ #rowsTop;
24
+ /**
25
+ * Each row has inner and outer bounds
26
+ * For adjacent rows, outer-bottom equals outer-top of the next row
27
+ *
28
+ * Inner bounds (top and bottom) are updated during layouting (when wrapped with subflow)
29
+ *
30
+ * ------ outer-top -------
31
+ * [ subflow stack begins ]
32
+ * ------ inner-top -------
33
+ * [ A ---> B ]
34
+ * ---- inner-bottom ------
35
+ * [ subflow stack ends ]
36
+ * ---- outer-bottom ------
37
+ */
38
+ #rows = [];
39
+ #subflows = /* @__PURE__ */ new Map();
40
+ constructor({ actors, steps, compounds, flow, collapsedFlows }) {
41
+ this.#solver.maxIterations = 2e3;
42
+ this.#flow = flow;
43
+ const firstRowOffset = Math.max(...actors.map((actor) => actor.height)) + 30;
44
+ this.#rowsTop = this.newVar(firstRowOffset);
45
+ this.constraint(this.#rowsTop, "==", firstRowOffset, Strength.soft);
46
+ this.constraint(this.#rowsTop, ">=", firstRowOffset, Strength.weak);
47
+ this.#viewportRight = this.newVar(0);
48
+ this.#viewportBottom = this.newVar(0);
49
+ this.#actors = this.addActors(actors);
50
+ for (const compound of compounds) {
51
+ const result = this.addCompound(compound);
52
+ const toplevel = result[0];
53
+ this.constraint(toplevel.y1, "==", 0, Strength.strong);
54
+ this.put(this.#rowsTop, Strength.strong).after(toplevel.y2);
55
+ this.#compounds.push(...result);
56
+ }
57
+ const [firstActor, ...restActors] = this.#actors;
58
+ this.constraint(firstActor.offset.left, "==", 0, Strength.strong);
59
+ const lastActor = restActors.reduce((prev, actor) => {
60
+ this.put(actor.x).after(prev.right, 80);
61
+ this.put(prev.offset.right, Strength.strong).before(actor.offset.left, 50);
62
+ this.constraint(actor.centerY, "==", prev.centerY, Strength.strong);
63
+ return actor;
64
+ }, firstActor);
65
+ for (const step of steps) this.addStep(step);
66
+ this.createSubflowAreas(steps, new Set(collapsedFlows));
67
+ this.constraint(this.#viewportRight, "==", lastActor.offset.right);
68
+ const mostBottom = last(this.#rows)?.inner.bottom ?? this.#rowsTop;
69
+ this.put(this.#viewportBottom, Strength.strong).after(mostBottom, 16);
70
+ if (compounds.length > 0) for (const compound of this.#compounds) {
71
+ const from = compound.from.column;
72
+ const to = compound.to.column;
73
+ let maxRow = Math.max(compound.from.maxRow, compound.to.maxRow);
74
+ for (let i = from + 1; i < to; i++) {
75
+ const actorBox = this.actorBox(i);
76
+ maxRow = Math.max(maxRow, actorBox.maxRow);
77
+ }
78
+ const lastRow = nonNullable(this.#rows[maxRow], `row ${maxRow} not found`);
79
+ this.put(compound.bottom, Strength.strong).after(lastRow.inner.bottom, 10);
80
+ }
81
+ this.#solver.updateVariables();
82
+ }
83
+ getSubflowAreas() {
84
+ return [...this.#subflows.entries()].map(([id, { x1, y1, x2, y2 }]) => ({
85
+ id,
86
+ x: x1.value(),
87
+ y: y1.value(),
88
+ width: x2.value() - x1.value(),
89
+ height: y2.value() - y1.value()
90
+ }));
91
+ }
92
+ getActorBox(actor) {
93
+ const actorBox = this.actorBox(actor);
94
+ return {
95
+ x: actorBox.x.value(),
96
+ y: actorBox.y.value(),
97
+ width: actorBox.width,
98
+ height: actorBox.height
99
+ };
100
+ }
101
+ getCompoundBoxes() {
102
+ return this.#compounds.map(({ node, depth, x1, y1, x2, bottom }) => ({
103
+ node,
104
+ depth,
105
+ x: x1.value(),
106
+ y: y1.value(),
107
+ width: x2.value() - x1.value(),
108
+ height: bottom.value() - y1.value()
109
+ }));
110
+ }
111
+ getPortCenter(step, type) {
112
+ const { column, row } = type === "source" ? step.from : step.to;
113
+ const x = this.actorBox(column).centerX;
114
+ const { rowTop } = nonNullable(this.#rows[row]);
115
+ if (step.isSelfLoop && type === "target") return {
116
+ cx: x.value(),
117
+ cy: rowTop.value(),
118
+ height: 24
119
+ };
120
+ return {
121
+ cx: x.value(),
122
+ cy: rowTop.value() + 40 + step.offset,
123
+ height: type === "source" ? 40 : 24
124
+ };
125
+ }
126
+ isStepCollapsed(step) {
127
+ if (step.from.row === step.to.row) return this.#rows[step.from.row]?.collapsed ?? false;
128
+ const minRow = Math.min(step.from.row, step.to.row);
129
+ const maxRow = Math.min(step.from.row, step.to.row);
130
+ let collapsed = true;
131
+ for (let i = minRow; i <= maxRow; i++) {
132
+ collapsed = collapsed && (this.#rows[i]?.collapsed ?? false);
133
+ if (!collapsed) break;
134
+ }
135
+ return collapsed;
136
+ }
137
+ getViewBounds() {
138
+ return {
139
+ x: 0,
140
+ y: 0,
141
+ width: this.#viewportRight.value(),
142
+ height: this.#viewportBottom.value()
143
+ };
144
+ }
145
+ actorBox(actor) {
146
+ if (typeof actor !== "number") {
147
+ const id = typeof actor === "string" ? actor : actor.id;
148
+ actor = this.#actors.findIndex((a) => a.actor.id === id);
149
+ invariant(actor >= 0, `actor ${id} not found`);
150
+ }
151
+ return nonNullable(this.#actors[actor], `actor at index ${actor} not found`);
152
+ }
153
+ addActors(actors) {
154
+ let accX = 0;
155
+ return map(actors, (actor, column) => {
156
+ const x = this.newVar(accX);
157
+ accX += actor.width + 80;
158
+ const y = this.newVar(0);
159
+ const actorBox = {
160
+ column,
161
+ actor,
162
+ x,
163
+ y,
164
+ centerX: x.plus(Math.round(actor.width / 2)),
165
+ centerY: y.plus(Math.round(actor.height / 2)),
166
+ width: actor.width,
167
+ height: actor.height,
168
+ right: x.plus(actor.width),
169
+ bottom: y.plus(actor.height),
170
+ minRow: Infinity,
171
+ maxRow: -Infinity
172
+ };
173
+ const top = this.newVar(0);
174
+ const left = this.newVar(0);
175
+ const right = this.newVar(0);
176
+ const bottom = this.newVar(0);
177
+ this.put(y, Strength.strong).after(top);
178
+ this.put(x, Strength.strong).after(left);
179
+ this.put(actorBox.right, Strength.strong).before(right);
180
+ this.put(actorBox.bottom, Strength.strong).before(bottom);
181
+ return {
182
+ ...actorBox,
183
+ offset: {
184
+ top,
185
+ left,
186
+ right,
187
+ bottom
188
+ }
189
+ };
190
+ });
191
+ }
192
+ addStep(step) {
193
+ const source = this.actorBox(step.source);
194
+ const target = this.actorBox(step.target);
195
+ source.minRow = Math.min(source.minRow, step.from.row);
196
+ source.maxRow = Math.max(source.maxRow, step.from.row);
197
+ target.minRow = Math.min(target.minRow, step.to.row);
198
+ target.maxRow = Math.max(target.maxRow, step.to.row);
199
+ const [left, right] = source.column <= target.column ? [source, target] : [target, source];
200
+ const width = (step.label?.width ?? 100) + 50;
201
+ if (Math.abs(target.column - source.column) <= 1) if (left !== right) this.constraint(left.centerX.plus(width), "<=", right.centerX);
202
+ else this.constraint(left.centerX.plus(width), "<=", left.offset.right);
203
+ let height = step.label?.height ? step.label.height + 50 + 24 : 100;
204
+ height = Math.max(height, 100) + step.offset;
205
+ this.ensureRow(step.from.row, height);
206
+ if (step.to.row !== step.from.row) this.ensureRow(step.to.row, 24);
207
+ return this;
208
+ }
209
+ /**
210
+ * Recursively adds a compound and its nested compounds to the layout.
211
+ * Also updates offsets of the actor boxes to accommodate the compound.
212
+ */
213
+ addCompound(compound) {
214
+ const PADDING = 32;
215
+ const PADDING_TOP = 40;
216
+ const PADDING_TOP_FROM_ACTOR = 52;
217
+ const children = [];
218
+ const nested = compound.nested.flatMap((c) => {
219
+ const result = this.addCompound(c);
220
+ children.push(result[0]);
221
+ return result;
222
+ });
223
+ const depth = Math.max(...nested.map((c) => c.depth + 1), 0);
224
+ const from = this.actorBox(compound.from);
225
+ const to = this.actorBox(compound.to);
226
+ const x1 = from.offset.left.minus(PADDING);
227
+ from.offset.left = x1;
228
+ const x2 = to.offset.right.plus(PADDING);
229
+ to.offset.right = x2;
230
+ const bottom = this.newVar(0);
231
+ const onlyChild = only(children);
232
+ let y1;
233
+ let y2;
234
+ switch (true) {
235
+ case !!onlyChild:
236
+ y1 = onlyChild.y1.minus(PADDING_TOP);
237
+ y2 = onlyChild.y2.plus(PADDING);
238
+ this.put(onlyChild.bottom).before(bottom, PADDING);
239
+ break;
240
+ case to === from:
241
+ y1 = this.newVar(0);
242
+ y2 = this.newVar(0);
243
+ this.put(y1).before(from.offset.top, PADDING_TOP_FROM_ACTOR);
244
+ this.put(from.offset.bottom).before(y2, PADDING);
245
+ this.put(y2).before(bottom);
246
+ break;
247
+ case children.length > 0:
248
+ y1 = this.newVar(0);
249
+ y2 = this.newVar(0);
250
+ for (const child of children) {
251
+ this.put(y1).before(child.y1, PADDING);
252
+ this.put(child.y2).before(y2, PADDING);
253
+ this.put(child.bottom).before(bottom, PADDING);
254
+ }
255
+ break;
256
+ default:
257
+ y1 = this.newVar(0);
258
+ y2 = this.newVar(0);
259
+ for (var col = from.column; col <= to.column; col++) {
260
+ const offset = this.actorBox(col).offset;
261
+ this.put(y1).before(offset.top, PADDING_TOP_FROM_ACTOR);
262
+ this.put(offset.bottom).before(y2, PADDING);
263
+ }
264
+ this.put(y2).before(bottom);
265
+ break;
266
+ }
267
+ for (var col = from.column; col <= to.column; col++) {
268
+ const offset = this.actorBox(col).offset;
269
+ offset.top = y1;
270
+ offset.bottom = y2;
271
+ }
272
+ return [{
273
+ node: compound.node,
274
+ depth,
275
+ from,
276
+ to,
277
+ x1,
278
+ y1,
279
+ x2,
280
+ y2,
281
+ bottom
282
+ }, ...nested];
283
+ }
284
+ ensureRow(row, rowHeight) {
285
+ while (row >= this.#rows.length) {
286
+ const outerTop = last(this.#rows)?.outer.bottom || this.#rowsTop;
287
+ const innerTop = this.newVar(outerTop.value());
288
+ this.put(innerTop).after(outerTop);
289
+ let heightValue = rowHeight;
290
+ if (row !== this.#rows.length) heightValue = 100;
291
+ const height = new kiwi.Variable();
292
+ height.setValue(heightValue);
293
+ this.#solver.addEditVariable(height, Strength.strong);
294
+ this.#solver.suggestValue(height, heightValue);
295
+ const innerBottom = this.newVar(innerTop.value() + heightValue);
296
+ this.require(innerBottom).after(innerTop);
297
+ this.constraint(innerBottom.minus(innerTop), "==", height, Strength.strong);
298
+ const outerBottom = this.newVar(innerBottom.value());
299
+ this.put(outerBottom).after(innerBottom);
300
+ this.#rows.push({
301
+ inner: {
302
+ top: innerTop,
303
+ bottom: innerBottom
304
+ },
305
+ rowTop: innerTop,
306
+ outer: {
307
+ top: outerTop,
308
+ bottom: outerBottom
309
+ },
310
+ height
311
+ });
312
+ }
313
+ const rowVar = nonNullable(this.#rows[row]);
314
+ if (rowHeight > rowVar.height.value()) {
315
+ rowVar.height.setValue(rowHeight);
316
+ this.#solver.suggestValue(rowVar.height, rowHeight);
317
+ }
318
+ return rowVar;
319
+ }
320
+ collapseRect({ min, max }) {
321
+ const h = 0;
322
+ for (let row = min.row; row <= max.row; row++) {
323
+ const r = nonNullable(this.#rows[row], `Row ${row} not found`);
324
+ r.collapsed = true;
325
+ r.height.setValue(h);
326
+ this.#solver.suggestValue(r.height, h);
327
+ }
328
+ }
329
+ getRectBounds({ min, max }) {
330
+ const firstRow = this.#rows[min.row];
331
+ const lastRow = this.#rows[max.row];
332
+ invariant(firstRow && lastRow, `Subflow box invalid minRow=${min.row} maxRow=${max.row}`);
333
+ return {
334
+ x1: this.actorBox(min.column).centerX,
335
+ x2: this.actorBox(max.column).centerX,
336
+ get top() {
337
+ return firstRow.inner.top;
338
+ },
339
+ set top(value) {
340
+ firstRow.inner.top = value;
341
+ },
342
+ get bottom() {
343
+ return lastRow.inner.bottom;
344
+ },
345
+ set bottom(value) {
346
+ lastRow.inner.bottom = value;
347
+ },
348
+ minY: firstRow.outer.top,
349
+ maxY: lastRow.outer.bottom
350
+ };
351
+ }
352
+ wrapAroundRect(rect, spacing) {
353
+ const p = normalizeSpacing(spacing ?? 16);
354
+ const bounds = this.getRectBounds(rect);
355
+ const x1 = this.newVar(0);
356
+ this.put(x1).before(bounds.x1, p.left);
357
+ const x2 = this.newVar(0);
358
+ this.put(x2).after(bounds.x2, p.right);
359
+ const y1 = this.newVar(bounds.minY.value());
360
+ this.require(y1).after(bounds.minY);
361
+ this.put(y1).before(bounds.top, p.top);
362
+ const y2 = this.newVar(bounds.maxY.value());
363
+ this.put(y2).after(bounds.bottom, p.bottom);
364
+ this.require(y2).before(bounds.maxY);
365
+ bounds.top = y1;
366
+ bounds.bottom = y2;
367
+ return {
368
+ x1,
369
+ y1,
370
+ x2,
371
+ y2
372
+ };
373
+ }
374
+ createSubflowAreas(steps, collapsed) {
375
+ const selectSteps = (id) => filter(steps, (s) => s.id.startsWith(id));
376
+ const spacing = {
377
+ top: 30,
378
+ right: 40,
379
+ bottom: 10,
380
+ left: 90
381
+ };
382
+ /**
383
+ * Expands the parent bounding box to fit all subflows and their nested steps.
384
+ */
385
+ const fitSubflows = ({ area, visited, stretch = false, padding }) => {
386
+ const areas = pipe(visited, filter(flowGuards.isSubFlow), flatMap((b) => this.#subflows.get(b.id) ?? []));
387
+ if (!hasAtLeast(areas, 1)) return;
388
+ const p = defu(padding, spacing);
389
+ const firstArea = first(areas);
390
+ const lastArea = last(areas);
391
+ if (firstArea.min.row == area.min.row) this.require(area.y1).before(firstArea.y1, p.top);
392
+ if (lastArea.max.row == area.max.row) this.require(lastArea.y2).before(area.y2, p.bottom);
393
+ for (const subarea of areas) {
394
+ this.require(subarea.x1).after(area.x1, p.left);
395
+ this.require(subarea.x2).before(area.x2, p.right);
396
+ if (stretch) {
397
+ subarea.x1 = p.left > 0 ? area.x1.plus(p.left) : area.x1;
398
+ subarea.x2 = p.right > 0 ? area.x2.minus(p.right) : area.x2;
399
+ }
400
+ }
401
+ };
402
+ const createSubflowArea = (subflow) => {
403
+ const rect = rectFromSteps(selectSteps(subflow.id));
404
+ let space;
405
+ switch (true) {
406
+ case flowGuards.isAltOrTry(subflow):
407
+ space = 0;
408
+ break;
409
+ case collapsed.has(subflow.id) && flowGuards.isAltOrTryBranch(subflow):
410
+ space = {
411
+ ...spacing,
412
+ top: 36,
413
+ bottom: 0
414
+ };
415
+ break;
416
+ case collapsed.has(subflow.id):
417
+ space = {
418
+ ...spacing,
419
+ top: 24,
420
+ bottom: 0
421
+ };
422
+ break;
423
+ default:
424
+ space = spacing;
425
+ break;
426
+ }
427
+ const area = {
428
+ ...this.wrapAroundRect(rect, space),
429
+ ...rect
430
+ };
431
+ this.#subflows.set(subflow.id, area);
432
+ return area;
433
+ };
434
+ this.#flow.walk({ subflow: ({ subflow, previous, parent }) => ({
435
+ next: collapsed.has(subflow.id) ? [] : subflow.flow,
436
+ onLeave: ({ visited }) => {
437
+ const area = createSubflowArea(subflow);
438
+ const previousSubflow = flowGuards.isSubFlow(previous) && this.#subflows.get(previous.id);
439
+ if (!flowGuards.isAltOrTryBranch(subflow) && previousSubflow) this.put(previousSubflow.y2).before(area.y1, 32);
440
+ if (!parent && area.min.column > 0) this.require(this.actorBox(area.min.column - 1).centerX).before(area.x1, 100);
441
+ switch (true) {
442
+ case collapsed.has(subflow.id):
443
+ this.collapseRect(area);
444
+ return;
445
+ case flowGuards.isAltOrTry(subflow): return fitSubflows({
446
+ area,
447
+ visited,
448
+ padding: {
449
+ top: 30,
450
+ left: 0,
451
+ right: 0
452
+ },
453
+ stretch: true
454
+ });
455
+ case flowGuards.isAltOrTryBranch(subflow): return fitSubflows({
456
+ area,
457
+ visited,
458
+ padding: {
459
+ top: 50,
460
+ left: 32,
461
+ bottom: 32,
462
+ right: 32
463
+ }
464
+ });
465
+ default: return fitSubflows({
466
+ area,
467
+ visited,
468
+ padding: {
469
+ top: 40,
470
+ bottom: 12,
471
+ left: 32,
472
+ right: 16
473
+ }
474
+ });
475
+ }
476
+ }
477
+ }) });
478
+ }
479
+ newVar(initialValue) {
480
+ const v = new kiwi.Variable();
481
+ this.#solver.addEditVariable(v, Strength.weak);
482
+ if (typeof initialValue === "number") {
483
+ v.setValue(initialValue);
484
+ this.#solver.suggestValue(v, initialValue);
485
+ }
486
+ return v;
487
+ }
488
+ require(...args) {
489
+ if (args.length == 1) {
490
+ const [left] = args;
491
+ return {
492
+ before: (right, gap = 0) => {
493
+ let other = gap ? right.minus(gap) : right;
494
+ return this.constraint(left, "<=", other, Strength.required);
495
+ },
496
+ after: (right, gap = 0) => {
497
+ let other = gap ? right.plus(gap) : right;
498
+ return this.constraint(left, ">=", other, Strength.required);
499
+ }
500
+ };
501
+ }
502
+ const [left, op, right] = args;
503
+ const constraint = this.constraint(left, op, right, Strength.required);
504
+ switch (op) {
505
+ case "<=":
506
+ case ">=":
507
+ this.constraint(left, "==", right, Strength.weak);
508
+ break;
509
+ case "<= 0":
510
+ case ">= 0":
511
+ this.constraint(left, "== 0", void 0, Strength.weak);
512
+ break;
513
+ }
514
+ return constraint;
515
+ }
516
+ /**
517
+ * Adds a constraint with medium strength by default
518
+ */
519
+ constraint(left, op, right = void 0, strength = Strength.medium) {
520
+ let operator;
521
+ switch (op) {
522
+ case "==":
523
+ operator = kiwi.Operator.Eq;
524
+ break;
525
+ case ">=":
526
+ operator = kiwi.Operator.Ge;
527
+ break;
528
+ case "<=":
529
+ operator = kiwi.Operator.Le;
530
+ break;
531
+ case "== 0":
532
+ operator = kiwi.Operator.Eq;
533
+ right = 0;
534
+ break;
535
+ case ">= 0":
536
+ operator = kiwi.Operator.Ge;
537
+ right = 0;
538
+ break;
539
+ case "<= 0":
540
+ operator = kiwi.Operator.Le;
541
+ right = 0;
542
+ break;
543
+ default: nonexhaustive(op);
544
+ }
545
+ const constraint = new kiwi.Constraint(left, operator, right ?? 0, strength);
546
+ this.#solver.addConstraint(constraint);
547
+ return constraint;
548
+ }
549
+ put(variable, strength = Strength.required) {
550
+ const eqStrength = strength === Strength.required ? Strength.soft : Strength.weak;
551
+ return {
552
+ before: (other, gap) => {
553
+ if (gap) other = other.minus(gap);
554
+ this.constraint(variable, "<=", other, strength);
555
+ this.constraint(variable, "==", other, eqStrength);
556
+ },
557
+ after: (other, gap) => {
558
+ if (gap) other = other.plus(gap);
559
+ this.constraint(variable, ">=", other, strength);
560
+ this.constraint(variable, "==", other, eqStrength);
561
+ }
562
+ };
563
+ }
564
+ };
565
+ //#endregion
566
+ export { SequenceViewLayouter, Strength };
@@ -1,11 +1,17 @@
1
1
  import { LayoutedDynamicView, ViewId } from '@likec4/core/types';
2
+ import { DiagramContext } from '../state/types';
2
3
  import { Types } from '../types';
3
4
  /**
4
5
  * Converts a sequence layout to XY flow nodes and edges.
5
6
  * @param view The next dynamic view which contains the sequence layout.
6
7
  * @param currentViewId The ID of the current view (optional, used to exclude navigation to the current view)
7
8
  */
8
- export declare function sequenceLayoutToXY(view: LayoutedDynamicView, currentViewId: ViewId | undefined): {
9
- xynodes: Array<Types.SequenceActorNode | Types.SequenceParallelArea | Types.ViewGroupNode>;
9
+ export declare function sequenceLayoutToXY({ view, currentViewId, collapsedFlows }: {
10
+ view: LayoutedDynamicView;
11
+ currentViewId: ViewId | undefined;
12
+ collapsedFlows: DiagramContext['collapsedSequenceFlows'];
13
+ }): {
14
+ xynodes: Array<Types.SequenceActorNode | Types.SequenceParallelArea | Types.SequenceSubflowArea | Types.ViewGroupNode>;
10
15
  xyedges: Array<Types.SequenceStepEdge>;
16
+ layout: LayoutedDynamicView.Sequence.Layout;
11
17
  };