@likec4/diagram 1.56.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/LikeC4Diagram.js +3 -1
  2. package/dist/LikeC4View.js +47 -55
  3. package/dist/adhoc-editor/ElementsTree.js +2 -6
  4. package/dist/components/RootContainer.js +19 -18
  5. package/dist/context/DiagramFeatures.d.ts +1 -1
  6. package/dist/context/DiagramFeatures.js +5 -0
  7. package/dist/context/RootContainerContext.d.ts +10 -17
  8. package/dist/context/RootContainerContext.js +1 -13
  9. package/dist/custom/index.d.ts +1 -1
  10. package/dist/custom/index.js +1 -2
  11. package/dist/editor/LikeC4EditorCallbacks.d.ts +5 -0
  12. package/dist/editor/actor/actions.d.ts +115 -0
  13. package/dist/editor/actor/actions.js +122 -0
  14. package/dist/editor/{hotkeyActor.d.ts → actor/hotkey.d.ts} +1 -1
  15. package/dist/editor/{hotkeyActor.js → actor/hotkey.js} +4 -4
  16. package/dist/editor/actor/machine.d.ts +11 -0
  17. package/dist/editor/actor/machine.js +22 -0
  18. package/dist/editor/{editorActor.setup.d.ts → actor/setup.d.ts} +13 -49
  19. package/dist/editor/{editorActor.setup.js → actor/setup.js} +13 -10
  20. package/dist/editor/actor/state.editor.d.ts +97 -0
  21. package/dist/editor/actor/state.editor.js +55 -0
  22. package/dist/editor/actor/state.sync-queue.d.ts +420 -0
  23. package/dist/editor/actor/state.sync-queue.js +235 -0
  24. package/dist/editor/actor/types.d.ts +59 -0
  25. package/dist/editor/actor/types.js +5 -0
  26. package/dist/editor/applyChangesToManualLayout.js +1 -1
  27. package/dist/editor/index.d.ts +2 -1
  28. package/dist/editor/useEditorActorLogic.d.ts +8 -2
  29. package/dist/editor/useEditorActorLogic.js +26 -6
  30. package/dist/hooks/useDiagram.js +6 -1
  31. package/dist/hooks/useDiagramCompareLayout.js +1 -1
  32. package/dist/hooks/useEditorActor.d.ts +4 -0
  33. package/dist/hooks/useEditorActor.js +26 -0
  34. package/dist/hooks/useLikeC4ElementsTree.d.ts +3 -2
  35. package/dist/hooks/useLikeC4ElementsTree.js +3 -1
  36. package/dist/likec4diagram/DiagramUI.js +8 -4
  37. package/dist/likec4diagram/DiagramXYFlow.js +12 -12
  38. package/dist/likec4diagram/state/aligners.js +3 -0
  39. package/dist/likec4diagram/state/assign.js +1 -1
  40. package/dist/likec4diagram/state/diagram-api.d.ts +16 -0
  41. package/dist/likec4diagram/state/diagram-api.js +13 -7
  42. package/dist/likec4diagram/state/machine.actions.js +7 -8
  43. package/dist/likec4diagram/state/machine.d.ts +1 -1
  44. package/dist/likec4diagram/state/machine.setup.js +1 -1
  45. package/dist/likec4diagram/state/types.d.ts +1 -1
  46. package/dist/likec4diagram/state/utils.d.ts +1 -1
  47. package/dist/likec4diagram/useLayoutConstraints.js +2 -0
  48. package/dist/navigationpanel/controls/ToggleReadonly.js +4 -2
  49. package/dist/navigationpanel/editorpanel/ApplySemanticLayout.d.ts +4 -0
  50. package/dist/navigationpanel/editorpanel/ApplySemanticLayout.js +36 -0
  51. package/dist/navigationpanel/editorpanel/EditorPanel.js +45 -33
  52. package/dist/navigationpanel/walkthrough/DynamicViewControls.d.ts +61 -61
  53. package/dist/overlays/overlay/Overlay.d.ts +16 -0
  54. package/dist/overlays/overlay/Overlay.js +50 -52
  55. package/dist/overlays/overlaysActor.js +28 -27
  56. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +4 -5
  57. package/dist/overlays/relationship-details/custom/nodeTypes.js +25 -24
  58. package/dist/overlays/relationships-browser/SelectElement.js +2 -2
  59. package/dist/search/Search.d.ts +6 -3
  60. package/dist/search/Search.js +60 -71
  61. package/dist/search/components/ElementsColumn.js +12 -8
  62. package/dist/search/searchActor.js +30 -26
  63. package/dist/shadowroot/ShadowRoot.d.ts +7 -6
  64. package/dist/shadowroot/ShadowRoot.js +59 -20
  65. package/dist/shadowroot/styles.css.d.ts +10 -2
  66. package/dist/shadowroot/styles.css.js +33 -36
  67. package/dist/styles2.js +1 -1
  68. package/package.json +17 -23
  69. package/panda.buildinfo.json +15 -15
  70. package/src/styles-font.css +114 -0
  71. package/src/styles-min.css +2 -0
  72. package/src/styles-xyflow.css +1 -0
  73. package/src/styles.css +3 -0
  74. package/styles-min.css +1 -1
  75. package/styles.css +1 -1
  76. package/dist/bundle/index.d.ts +0 -1
  77. package/dist/editor/editorActor.actions.d.ts +0 -153
  78. package/dist/editor/editorActor.actions.js +0 -133
  79. package/dist/editor/editorActor.states.d.ts +0 -9
  80. package/dist/editor/editorActor.states.js +0 -219
  81. package/dist/hooks/useOverlaysActor.js +0 -11
  82. package/dist/hooks/useSearchActor.js +0 -11
@@ -0,0 +1,59 @@
1
+ import { Types } from '../../likec4diagram/types';
2
+ import { HotKeyEvent } from './hotkey';
3
+ import type * as t from '@likec4/core/types';
4
+ export type EditorActorEvent = {
5
+ type: 'change.view';
6
+ change: t.ViewChange;
7
+ } | {
8
+ type: 'change.semantic-layout';
9
+ } | {
10
+ type: 'change.latest-to-manual';
11
+ } | {
12
+ type: 'change.sync-snapshot';
13
+ } | {
14
+ type: 'view.synched';
15
+ } | {
16
+ type: 'cancel';
17
+ } | {
18
+ type: 'edit.move.start';
19
+ subject: 'node' | 'edge';
20
+ } | {
21
+ type: 'edit.move.end';
22
+ } | {
23
+ type: 'edit.move.cancel';
24
+ } | HotKeyEvent;
25
+ export type Snapshot = {
26
+ view: t.LayoutedView;
27
+ change: t.ViewChange.SaveViewSnapshot;
28
+ xynodes: Types.Node[];
29
+ xyedges: Types.Edge[];
30
+ };
31
+ export type LinkedSnapshot = {
32
+ head: Snapshot;
33
+ tail: LinkedSnapshot | null;
34
+ };
35
+ export interface EditorActorInput {
36
+ viewId: t.ViewId;
37
+ }
38
+ export type SyncOp = t.ViewChange | 'sync-snapshot' | 'apply-semantic-layout' | 'apply-latest-to-manual';
39
+ export declare const isViewChange: (change: SyncOp) => change is t.ViewChange;
40
+ export interface EditorActorContext {
41
+ viewId: t.ViewId;
42
+ history: LinkedSnapshot | null;
43
+ editing: null | {
44
+ /**
45
+ * The subject of the edit
46
+ */
47
+ subject: 'node' | 'edge';
48
+ /**
49
+ * The state before editing started
50
+ */
51
+ before: Snapshot;
52
+ };
53
+ syncQueue: Array<SyncOp>;
54
+ processing: Exclude<SyncOp, 'sync-snapshot'> | null;
55
+ }
56
+ export type EditorActorEmitedEvent = {
57
+ type: 'idle';
58
+ };
59
+ export type EditorActorStateTag = 'pending' | 'busy' | 'ai-semantic-layout';
@@ -0,0 +1,5 @@
1
+ import "../../_virtual/_rolldown/runtime.js";
2
+ //#region src/editor/actor/types.ts
3
+ var isViewChange = (change) => typeof change !== "string";
4
+ //#endregion
5
+ export { isViewChange };
@@ -153,7 +153,7 @@ function edgeControlPoints(source, target) {
153
153
  if (source === target) {
154
154
  const loopSize = 80;
155
155
  const centerOfTopBoundary = vector(0, source.height || 0).multiply(-.5).add(sourceCenter);
156
- return [centerOfTopBoundary.add(vector(-loopSize / 2.5, -loopSize)).trunc().toObject(), centerOfTopBoundary.add(vector(loopSize / 2.5, -loopSize)).trunc().toObject()];
156
+ return [centerOfTopBoundary.add(vector(-80 / 2.5, -80)).trunc().toObject(), centerOfTopBoundary.add(vector(loopSize / 2.5, -80)).trunc().toObject()];
157
157
  }
158
158
  const sourceToTargetVector = targetCenter.subtract(sourceCenter);
159
159
  const sourceBorderPoint = getBorderPointOnVector(source, sourceCenter, sourceToTargetVector);
@@ -1,4 +1,5 @@
1
- export type * from './editorActor.states';
1
+ export type * from './actor/machine';
2
+ export type * from './actor/types';
2
3
  export { createLikeC4Editor } from './LikeC4EditorCallbacks';
3
4
  export type { LikeC4EditorCallbacks } from './LikeC4EditorCallbacks';
4
5
  export { EnsureEditorContext, LikeC4EditorProvider, useOptionalLikeC4Editor, } from './LikeC4EditorProvider';
@@ -1,2 +1,8 @@
1
- import { EditorActorLogic } from './editorActor.states';
2
- export declare function useEditorActorLogic(): EditorActorLogic;
1
+ import { EditorActorLogic } from './actor/machine';
2
+ export declare function useEditorActorLogic(): EditorActorLogic & {
3
+ /**
4
+ * True if the editor is running in stub mode (no actual editor port available)
5
+ * This happens when the diagram is rendered outside of vscode extension / vite- plugin
6
+ */
7
+ readonly isStub: boolean;
8
+ };
@@ -1,9 +1,10 @@
1
1
  import "../_virtual/_rolldown/runtime.js";
2
2
  import { useCallbackRef } from "../hooks/useCallbackRef.js";
3
3
  import { useOptionalLikeC4Editor } from "./LikeC4EditorProvider.js";
4
- import { editorActorLogic } from "./editorActor.states.js";
4
+ import { editorActorLogic } from "./actor/machine.js";
5
5
  import { applyChangesToManualLayout } from "./applyChangesToManualLayout.js";
6
6
  import { useMemo } from "react";
7
+ import { isNullish } from "remeda";
7
8
  import { fromPromise } from "xstate";
8
9
  //#region src/editor/useEditorActorLogic.ts
9
10
  var promisify = (fn) => {
@@ -11,25 +12,44 @@ var promisify = (fn) => {
11
12
  };
12
13
  function useEditorActorLogic() {
13
14
  const port = useOptionalLikeC4Editor();
15
+ const isStub = isNullish(port);
14
16
  const applyLatest = useCallbackRef(async ({ input: { viewId, current } }) => {
15
17
  if (!port) {
16
18
  console.error("No editor port available for applying latest to manual layout");
17
- return Promise.reject(/* @__PURE__ */ new Error("No editor port"));
19
+ throw new Error("No editor port");
18
20
  }
19
21
  return { updated: applyChangesToManualLayout(await promisify(() => current ?? port.fetchView(viewId, "manual")), await promisify(() => port.fetchView(viewId, "auto"))) };
20
22
  });
21
23
  const executeChange = useCallbackRef(async ({ input }) => {
22
24
  if (!port) {
23
25
  console.error("No editor port available for executing change");
24
- return Promise.reject(/* @__PURE__ */ new Error("No editor port"));
26
+ throw new Error("No editor port");
25
27
  }
26
28
  for (const change of input.changes) await promisify(() => port.handleChange(input.viewId, change));
27
29
  return {};
28
30
  });
29
- return useMemo(() => editorActorLogic.provide({ actors: {
31
+ const applySemanticLayout = useCallbackRef(async ({ input }) => {
32
+ if (!port) {
33
+ console.error("No editor port available for applying semantic layout");
34
+ throw new Error("No editor port");
35
+ }
36
+ if (!port.applySemanticLayout) {
37
+ console.error("No applySemanticLayout method available on editor port");
38
+ throw new Error("No applySemanticLayout method");
39
+ }
40
+ await port.applySemanticLayout(input.viewId);
41
+ return {};
42
+ });
43
+ return useMemo(() => Object.assign(editorActorLogic.provide({ actors: {
30
44
  applyLatest: fromPromise(applyLatest),
31
- executeChange: fromPromise(executeChange)
32
- } }), [applyLatest, executeChange]);
45
+ executeChange: fromPromise(executeChange),
46
+ applySemanticLayout: fromPromise(applySemanticLayout)
47
+ } }), { isStub }), [
48
+ applyLatest,
49
+ executeChange,
50
+ applySemanticLayout,
51
+ isStub
52
+ ]);
33
53
  }
34
54
  //#endregion
35
55
  export { useEditorActorLogic };
@@ -45,7 +45,11 @@ function useOnDiagramEvent(event, callback, options) {
45
45
  useEffect(() => {
46
46
  if (once && wasCalled.current) return;
47
47
  let subscription = actorRef.on(event, (payload) => {
48
- callbackRef(payload);
48
+ if (!once || !wasCalled.current) try {
49
+ callbackRef(payload);
50
+ } catch (error) {
51
+ console.error(error);
52
+ }
49
53
  wasCalled.current = true;
50
54
  if (once) {
51
55
  subscription?.unsubscribe();
@@ -56,6 +60,7 @@ function useOnDiagramEvent(event, callback, options) {
56
60
  subscription?.unsubscribe();
57
61
  };
58
62
  }, [
63
+ callbackRef,
59
64
  actorRef,
60
65
  event,
61
66
  once
@@ -68,7 +68,7 @@ function useDiagramCompareLayout() {
68
68
  console.warn("Compare with latest feature is not enabled");
69
69
  return;
70
70
  }
71
- nonNullable(actorRef.system?.get("editor"), "editor actor not found").send({ type: "applyLatestToManual" });
71
+ nonNullable(actorRef.system?.get("editor"), "editor actor not found").send({ type: "change.latest-to-manual" });
72
72
  if (state.isActive) actorRef.send({
73
73
  type: "toggle.feature",
74
74
  feature: "CompareWithLatest",
@@ -0,0 +1,4 @@
1
+ import { EditorActorRef } from '../editor/actor/machine';
2
+ import { EditorActorStateTag } from '../editor/actor/types';
3
+ export declare function useEditorActorRef(): EditorActorRef | null;
4
+ export declare function useEditorActorStateHasTag(tag: EditorActorStateTag): boolean;
@@ -0,0 +1,26 @@
1
+ import "../_virtual/_rolldown/runtime.js";
2
+ import { selectDiagramActor, useDiagramSnapshot } from "./useDiagram.js";
3
+ import { useEffect, useState } from "react";
4
+ //#region src/hooks/useEditorActor.ts
5
+ var select = selectDiagramActor((s) => {
6
+ return s.children.editor ?? null;
7
+ });
8
+ function useEditorActorRef() {
9
+ return useDiagramSnapshot(select, Object.is);
10
+ }
11
+ function useEditorActorStateHasTag(tag) {
12
+ const editorActor = useEditorActorRef();
13
+ const [hasTag, setHasTag] = useState(() => editorActor?.getSnapshot().hasTag(tag) ?? false);
14
+ useEffect(() => {
15
+ const subscription = editorActor?.subscribe((snapshot) => {
16
+ setHasTag(snapshot.hasTag(tag));
17
+ });
18
+ return () => {
19
+ subscription?.unsubscribe();
20
+ setHasTag(false);
21
+ };
22
+ }, [editorActor, tag]);
23
+ return hasTag;
24
+ }
25
+ //#endregion
26
+ export { useEditorActorStateHasTag };
@@ -1,8 +1,10 @@
1
1
  import { Fqn, ViewId } from '@likec4/core/types';
2
- interface LikeC4ModelTreeNodeData {
2
+ import { TreeNodeData } from '@mantine/core';
3
+ export interface LikeC4ModelTreeNodeData extends TreeNodeData {
3
4
  label: string;
4
5
  value: Fqn;
5
6
  children: LikeC4ModelTreeNodeData[];
7
+ hasChildren: boolean;
6
8
  }
7
9
  export declare const sortByLabel: (a: LikeC4ModelTreeNodeData, b: LikeC4ModelTreeNodeData) => number;
8
10
  /**
@@ -10,4 +12,3 @@ export declare const sortByLabel: (a: LikeC4ModelTreeNodeData, b: LikeC4ModelTre
10
12
  * If `viewId` is provided, returns the tree of elements in the view.
11
13
  */
12
14
  export declare function useLikeC4ElementsTree(viewId?: ViewId): LikeC4ModelTreeNodeData[];
13
- export {};
@@ -5,10 +5,12 @@ import { compareNatural } from "@likec4/core/utils";
5
5
  //#region src/hooks/useLikeC4ElementsTree.ts
6
6
  var sortByLabel = (a, b) => compareNatural(a.label, b.label);
7
7
  function buildNode(element) {
8
+ const children = [...element.children()].map(buildNode).sort(sortByLabel);
8
9
  return {
9
10
  label: element.title || element.id,
10
11
  value: element.id,
11
- children: [...element.children()].map(buildNode).sort(sortByLabel)
12
+ children,
13
+ hasChildren: children.length > 0
12
14
  };
13
15
  }
14
16
  /**
@@ -1,7 +1,7 @@
1
1
  import "../_virtual/_rolldown/runtime.js";
2
2
  import { useEnabledFeatures } from "../context/DiagramFeatures.js";
3
+ import { selectDiagramActor, useDiagramSnapshot } from "../hooks/useDiagram.js";
3
4
  import { ErrorBoundary } from "../components/ErrorFallback.js";
4
- import { useOverlaysActorRef } from "../hooks/useOverlaysActor.js";
5
5
  import { NavigationPanel } from "../navigationpanel/NavigationPanel.js";
6
6
  import { Overlays } from "../overlays/Overlays.js";
7
7
  import { Search } from "../search/Search.js";
@@ -12,10 +12,14 @@ import { memo, useCallback } from "react";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
13
  import { useRerender } from "@react-hookz/web";
14
14
  //#region src/likec4diagram/DiagramUI.tsx
15
+ var selectChildren = selectDiagramActor((s) => ({
16
+ overlays: s.children.overlays ?? null,
17
+ search: s.children.search ?? null
18
+ }));
15
19
  var LikeC4DiagramUI = memo(() => {
16
20
  const { enableControls, enableNotations, enableSearch, enableRelationshipDetails, enableReadOnly, enableCompareWithLatest } = useEnabledFeatures();
17
21
  const rerender = useRerender();
18
- const overlaysActorRef = useOverlaysActorRef();
22
+ const actors = useDiagramSnapshot(selectChildren);
19
23
  return /* @__PURE__ */ jsxs(ErrorBoundary, {
20
24
  onReset: useCallback(() => {
21
25
  console.warn("DiagramUI: resetting error boundary and rerendering...");
@@ -23,9 +27,9 @@ var LikeC4DiagramUI = memo(() => {
23
27
  }, []),
24
28
  children: [
25
29
  enableControls && /* @__PURE__ */ jsx(NavigationPanel, {}),
26
- overlaysActorRef && /* @__PURE__ */ jsx(Overlays, { overlaysActorRef }),
30
+ actors.overlays && /* @__PURE__ */ jsx(Overlays, { overlaysActorRef: actors.overlays }),
27
31
  enableNotations && /* @__PURE__ */ jsx(NotationPanel, {}),
28
- enableSearch && /* @__PURE__ */ jsx(Search, {}),
32
+ enableSearch && actors.search && /* @__PURE__ */ jsx(Search, { searchActorRef: actors.search }),
29
33
  enableRelationshipDetails && enableReadOnly && /* @__PURE__ */ jsx(RelationshipPopover, {}),
30
34
  enableCompareWithLatest && /* @__PURE__ */ jsx(LayoutDriftFrame, {})
31
35
  ]
@@ -2,13 +2,12 @@ import "../_virtual/_rolldown/runtime.js";
2
2
  import { useCallbackRef as useCallbackRef$1 } from "../hooks/useCallbackRef.js";
3
3
  import { depsShallowEqual, useUpdateEffect as useUpdateEffect$1 } from "../hooks/useUpdateEffect.js";
4
4
  import { BaseXYFlow } from "../base/BaseXYFlow.js";
5
- import { useIsReducedGraphics, usePanningAtom } from "../context/RootContainerContext.js";
5
+ import { useRootContainer } from "../context/RootContainerContext.js";
6
6
  import { useDiagramEventHandlers } from "../context/DiagramEventHandlers.js";
7
7
  import { useDiagram } from "../hooks/safeContext.js";
8
8
  import { selectDiagramActor, useDiagramSnapshot } from "../hooks/useDiagram.js";
9
9
  import { viewBounds } from "./state/utils.js";
10
10
  import { deriveToggledFeatures } from "./state/machine.setup.js";
11
- import { memoNode } from "../base-primitives/memoNode.js";
12
11
  import { BuiltinEdges, BuiltinNodes } from "./custom/index.js";
13
12
  import { useLayoutConstraints } from "./useLayoutConstraints.js";
14
13
  import { cx } from "@likec4/styles/css";
@@ -23,13 +22,13 @@ var edgeTypes = {
23
22
  "seq-step": BuiltinEdges.SequenceStepEdge
24
23
  };
25
24
  var builtinNodes = {
26
- element: memoNode(BuiltinNodes.ElementNode),
27
- deployment: memoNode(BuiltinNodes.DeploymentNode),
28
- "compound-element": memoNode(BuiltinNodes.CompoundElementNode),
29
- "compound-deployment": memoNode(BuiltinNodes.CompoundDeploymentNode),
30
- "view-group": memoNode(BuiltinNodes.ViewGroupNode),
31
- "seq-actor": memoNode(BuiltinNodes.SequenceActorNode),
32
- "seq-parallel": memoNode(BuiltinNodes.SequenceParallelArea)
25
+ element: BuiltinNodes.ElementNode,
26
+ deployment: BuiltinNodes.DeploymentNode,
27
+ "compound-element": BuiltinNodes.CompoundElementNode,
28
+ "compound-deployment": BuiltinNodes.CompoundDeploymentNode,
29
+ "view-group": BuiltinNodes.ViewGroupNode,
30
+ "seq-actor": BuiltinNodes.SequenceActorNode,
31
+ "seq-parallel": BuiltinNodes.SequenceParallelArea
33
32
  };
34
33
  function prepareNodeTypes(nodeTypes) {
35
34
  if (!nodeTypes || isEmpty(nodeTypes)) return builtinNodes;
@@ -53,7 +52,7 @@ var viewportToTopLeft = (ctx) => {
53
52
  };
54
53
  var selectXYProps = selectDiagramActor(({ context: ctx, children }) => {
55
54
  const { enableReadOnly } = deriveToggledFeatures(ctx);
56
- const isNotEditingEdge = enableReadOnly || children.editor?.getSnapshot().context.editing !== "edge";
55
+ const isNotEditingEdge = enableReadOnly || children.editor?.getSnapshot().context.editing?.subject !== "edge";
57
56
  let nodesDraggable = !enableReadOnly && ctx.nodesDraggable;
58
57
  if (ctx.dynamicViewVariant === "sequence" && ctx.view._type === "dynamic") nodesDraggable = false;
59
58
  return {
@@ -74,9 +73,10 @@ function LikeC4DiagramXYFlow({ background = "dots", reactFlowProps = {}, childre
74
73
  const diagram = useDiagram();
75
74
  let { enableReadOnly, initialized, nodes, edges, enableFitView, nodesDraggable, nodesSelectable, ...props } = useDiagramSnapshot(selectXYProps);
76
75
  const { onNodeContextMenu, onCanvasContextMenu, onEdgeContextMenu, onNodeClick, onEdgeClick, onCanvasClick, onCanvasDblClick } = useDiagramEventHandlers();
77
- const isReducedGraphics = useIsReducedGraphics();
76
+ const { reducedGraphics, $panning } = useRootContainer();
77
+ const isReducedGraphics = reducedGraphics;
78
78
  const layoutConstraints = useLayoutConstraints();
79
- const $isPanning = usePanningAtom();
79
+ const $isPanning = $panning;
80
80
  const isPanning = useTimeout(() => {
81
81
  $isPanning.set(true);
82
82
  }, isReducedGraphics ? 200 : 800);
@@ -5,6 +5,9 @@ import { getNodeDimensions } from "@xyflow/system";
5
5
  //#region src/likec4diagram/state/aligners.ts
6
6
  var Aligner = class {};
7
7
  var LinearAligner = class extends Aligner {
8
+ getEdgePosition;
9
+ computePosition;
10
+ propertyToEdit;
8
11
  alignTo;
9
12
  constructor(getEdgePosition, computePosition, propertyToEdit) {
10
13
  super();
@@ -86,7 +86,7 @@ function resetEdgeControlPoints(nodeLookup, edge) {
86
86
  if (source === target) {
87
87
  const loopSize = 80;
88
88
  const centerOfTopBoundary = vector(0, source.height || 0).multiply(-.5).add(sourceCenter);
89
- return [centerOfTopBoundary.add(vector(-loopSize / 2.5, -loopSize)).round().toObject(), centerOfTopBoundary.add(vector(loopSize / 2.5, -loopSize)).round().toObject()];
89
+ return [centerOfTopBoundary.add(vector(-80 / 2.5, -80)).round().toObject(), centerOfTopBoundary.add(vector(loopSize / 2.5, -80)).round().toObject()];
90
90
  }
91
91
  const sourceToTargetVector = targetCenter.subtract(sourceCenter);
92
92
  const sourceBorderPoint = getBorderPointOnVector(source, sourceCenter, sourceToTargetVector);
@@ -2,8 +2,10 @@ import { DynamicViewDisplayVariant, NodeNotation as ElementNotation, ViewChange
2
2
  import { RefObject } from 'react';
3
3
  import { PartialDeep } from 'type-fest';
4
4
  import { FeatureName } from '../../context/DiagramFeatures';
5
+ import { EditorActorRef } from '../../editor/actor/machine';
5
6
  import { OpenSourceParams } from '../../LikeC4Diagram.props';
6
7
  import { OverlaysActorRef } from '../../overlays/overlaysActor';
8
+ import { SearchActorRef } from '../../search/searchActor';
7
9
  import { Types } from '../types';
8
10
  import { AlignmentMode } from './aligners';
9
11
  import { DiagramActorRef, DiagramContext, DiagramEvents } from './types';
@@ -27,7 +29,21 @@ export interface DiagramApi<A extends Any = Unknown> {
27
29
  * @warning Do not use in render phase
28
30
  */
29
31
  readonly currentView: t.DiagramView<A>;
32
+ /**
33
+ * Editor actor reference
34
+ * @warning Do not use in render phase
35
+ */
36
+ editorActor(): EditorActorRef;
37
+ /**
38
+ * Overlays actor reference
39
+ * @warning Do not use in render phase
40
+ */
30
41
  overlays(): OverlaysActorRef;
42
+ /**
43
+ * Search actor reference
44
+ * @warning Do not use in render phase
45
+ */
46
+ searchActor(): SearchActorRef;
31
47
  /**
32
48
  * Send event to diagram actor
33
49
  */
@@ -8,8 +8,17 @@ function makeDiagramApi(actorRef) {
8
8
  get actor() {
9
9
  return actorRef.current;
10
10
  },
11
+ editorActor() {
12
+ const editorActor = typedSystem(actorRef.current.system).editorActorRef;
13
+ return nonNullable(editorActor, "Editor actor not found in actor system");
14
+ },
11
15
  overlays() {
12
- return nonNullable(actorRef.current.getSnapshot().children.overlays, "Overlays actor not found");
16
+ const overlaysActor = typedSystem(actorRef.current.system).overlaysActorRef;
17
+ return nonNullable(overlaysActor, "Overlays actor not found in actor system");
18
+ },
19
+ searchActor() {
20
+ const searchActor = typedSystem(actorRef.current.system).searchActorRef;
21
+ return nonNullable(searchActor, "Search actor not found in actor system");
13
22
  },
14
23
  send: (event) => actorRef.current.send(event),
15
24
  navigateTo: (viewId, fromNode, focusOnElement) => {
@@ -79,22 +88,19 @@ function makeDiagramApi(actorRef) {
79
88
  const editorActor = typedSystem(actorRef.current.system).editorActorRef;
80
89
  invariant(editorActor, "No editor actor found in diagram actor system");
81
90
  editorActor.send({
82
- type: "edit.start",
91
+ type: "edit.move.start",
83
92
  subject
84
93
  });
85
94
  },
86
95
  stopEditing: (wasChanged = false) => {
87
96
  const editorActor = typedSystem(actorRef.current.system).editorActorRef;
88
97
  invariant(editorActor, "No editor actor found in diagram actor system");
89
- editorActor.send({
90
- type: "edit.finish",
91
- wasChanged
92
- });
98
+ editorActor.send({ type: wasChanged ? "edit.move.end" : "edit.move.cancel" });
93
99
  },
94
100
  undoEditing: () => {
95
101
  const editorActor = typedSystem(actorRef.current.system).editorActorRef;
96
102
  invariant(editorActor, "No editor actor found in diagram actor system");
97
- const hasUndo = editorActor.getSnapshot().context.history.length > 0;
103
+ const hasUndo = editorActor.getSnapshot().context.history !== null;
98
104
  if (hasUndo) editorActor.send({ type: "undo" });
99
105
  return hasUndo;
100
106
  },
@@ -214,7 +214,7 @@ var triggerChange = (viewChange) => machine.enqueueActions(({ event, enqueue })
214
214
  }
215
215
  enqueue.assign({ viewportChangedManually: true });
216
216
  enqueue.sendTo(typedSystem.editorActor, {
217
- type: "change",
217
+ type: "change.view",
218
218
  change
219
219
  });
220
220
  });
@@ -388,14 +388,13 @@ var ensureEditorActor = () => machine.enqueueActions(({ enqueue, context, system
388
388
  });
389
389
  });
390
390
  var startEditing = (subject = "node") => machine.sendTo(typedSystem.editorActor, {
391
- type: "edit.start",
391
+ type: "edit.move.start",
392
392
  subject
393
393
  });
394
- var sendSynced = () => machine.sendTo(typedSystem.editorActor, { type: "synced" });
395
- var stopEditing = (wasChanged = false) => machine.sendTo(typedSystem.editorActor, {
396
- type: "edit.finish",
397
- wasChanged
398
- });
394
+ var sendSynced = () => {
395
+ return machine.sendTo(typedSystem.editorActor, { type: "view.synched" });
396
+ };
397
+ var stopEditing = (wasChanged = false) => machine.sendTo(typedSystem.editorActor, { type: wasChanged ? "edit.move.end" : "edit.move.cancel" });
399
398
  var cancelEditing = () => machine.sendTo(typedSystem.editorActor, { type: "cancel" });
400
399
  var hasModelFqn = (node) => "modelFqn" in node.data && isTruthy(node.data.modelFqn);
401
400
  var openElementDetails = (params) => machine.enqueueActions(({ context, event, enqueue }) => {
@@ -591,7 +590,7 @@ var stopHotKeyActor = () => machine.stopChild("hotkey");
591
590
  */
592
591
  var AUTO_UNFOCUS_DELAY = 3e3;
593
592
  var startAutoUnfocusTimer = () => machine.enqueueActions(({ context, enqueue }) => {
594
- if (context.autoUnfocusTimer && AUTO_UNFOCUS_DELAY > 0) enqueue.raise({ type: "focus.autoUnfocus" }, {
593
+ if (context.autoUnfocusTimer && true) enqueue.raise({ type: "focus.autoUnfocus" }, {
595
594
  delay: AUTO_UNFOCUS_DELAY,
596
595
  id: "autoUnfocusTimer"
597
596
  });
@@ -1,5 +1,5 @@
1
1
  import { ActorRef, MachineSnapshot, StateMachine } from 'xstate';
2
- import { EditorActorRef } from '../../editor/editorActor.states';
2
+ import { EditorActorRef } from '../../editor/actor/machine';
3
3
  import { OverlaysActorRef } from '../../overlays/overlaysActor';
4
4
  import { SearchActorRef } from '../../search/searchActor';
5
5
  import { Context as DiagramContext, EmittedEvents as DiagramEmittedEvents, Events as DiagramEvents, Input } from './machine.setup';
@@ -1,5 +1,5 @@
1
1
  import "../../_virtual/_rolldown/runtime.js";
2
- import { editorActorLogic } from "../../editor/editorActor.states.js";
2
+ import { editorActorLogic } from "../../editor/actor/machine.js";
3
3
  import { overlaysActorLogic } from "../../overlays/overlaysActor.js";
4
4
  import { searchActorLogic } from "../../search/searchActor.js";
5
5
  import { hotkeyActorLogic } from "./hotkeyActor.js";
@@ -1,5 +1,5 @@
1
1
  import { ActorSystem } from 'xstate';
2
- import { EditorActorRef } from '../../editor/editorActor.states';
2
+ import { EditorActorRef } from '../../editor/actor/machine';
3
3
  import { OverlaysActorRef } from '../../overlays/overlaysActor';
4
4
  import { SearchActorRef } from '../../search/searchActor';
5
5
  import { DiagramMachineRef } from './machine';
@@ -2,7 +2,7 @@ import { BBox } from '@likec4/core/geometry';
2
2
  import { DeploymentFqn, DiagramEdge, DiagramNode, DiagramView, Fqn } from '@likec4/core/types';
3
3
  import { Viewport } from '@xyflow/system';
4
4
  import { ActorSystem } from 'xstate';
5
- import { EditorActorRef } from '../../editor/editorActor.states';
5
+ import { EditorActorRef } from '../../editor/actor/machine';
6
6
  import { OverlaysActorRef } from '../../overlays/overlaysActor';
7
7
  import { SearchActorRef } from '../../search/searchActor';
8
8
  import { Types } from '../types';
@@ -85,6 +85,7 @@ var Rect = class {
85
85
  }
86
86
  };
87
87
  var CompoundRect = class extends Rect {
88
+ parent;
88
89
  children = [];
89
90
  constructor(xynode, parent = null) {
90
91
  super(xynode, parent);
@@ -92,6 +93,7 @@ var CompoundRect = class extends Rect {
92
93
  }
93
94
  };
94
95
  var Leaf = class extends Rect {
96
+ parent;
95
97
  constructor(xynode, parent = null) {
96
98
  super(xynode, parent);
97
99
  this.parent = parent;
@@ -14,10 +14,12 @@ import * as m$1 from "motion/react-m";
14
14
  var selector = (ctx) => {
15
15
  const comparingLatest = deriveToggledFeatures(ctx).enableCompareWithLatest && !!ctx.view.drifts && ctx.view._layout === "auto";
16
16
  const noActiveWalkthrough = !isTruthy(ctx.activeWalkthrough);
17
+ const hasEditor = ctx.features.enableEditor;
18
+ const isReadOnly = ctx.toggledFeatures.enableReadOnly ?? false;
17
19
  return {
18
- visible: ctx.features.enableEditor && noActiveWalkthrough,
20
+ visible: hasEditor && noActiveWalkthrough,
19
21
  disabled: comparingLatest,
20
- isReadOnly: ctx.toggledFeatures.enableReadOnly ?? false
22
+ isReadOnly
21
23
  };
22
24
  };
23
25
  var ToggleReadonly = () => {
@@ -0,0 +1,4 @@
1
+ import { NamedExoticComponent } from 'react';
2
+ export declare const ApplySemanticLayout: NamedExoticComponent<{
3
+ visible?: boolean;
4
+ }>;
@@ -0,0 +1,36 @@
1
+ import "../../_virtual/_rolldown/runtime.js";
2
+ import { useDiagram } from "../../hooks/safeContext.js";
3
+ import { PanelActionIcon } from "../_common.js";
4
+ import { useEditorActorStateHasTag } from "../../hooks/useEditorActor.js";
5
+ import { Tooltip } from "./_common.js";
6
+ import { IconSparkles } from "@tabler/icons-react";
7
+ import { memo } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/navigationpanel/editorpanel/ApplySemanticLayout.tsx
10
+ var ApplySemanticLayout = memo(({ visible = true }) => {
11
+ const diagram = useDiagram();
12
+ return /* @__PURE__ */ jsx(Tooltip, {
13
+ label: "Semantic Layout with AI",
14
+ children: /* @__PURE__ */ jsx(PanelActionIcon, {
15
+ loading: useEditorActorStateHasTag("ai-semantic-layout"),
16
+ initial: { display: visible ? "block" : "none" },
17
+ animate: {
18
+ display: visible ? "block" : "none",
19
+ opacity: visible ? 1 : .2,
20
+ x: visible ? 0 : -5,
21
+ y: visible ? 0 : -8
22
+ },
23
+ onClick: (e) => {
24
+ e.stopPropagation();
25
+ diagram.editorActor().send({ type: "change.semantic-layout" });
26
+ },
27
+ children: /* @__PURE__ */ jsx(IconSparkles, {
28
+ size: 14,
29
+ stroke: 2
30
+ })
31
+ })
32
+ });
33
+ });
34
+ ApplySemanticLayout.displayName = "ApplySemanticLayout";
35
+ //#endregion
36
+ export { ApplySemanticLayout };