@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
@@ -36,7 +36,8 @@ function LikeC4Diagram({ onCanvasClick, onCanvasContextMenu, onCanvasDblClick, o
36
36
  const optionalLikeC4Model = useOptionalLikeC4Model();
37
37
  enableCompareWithLatest = enableCompareWithLatest && !!onLayoutTypeChange && !!optionalLikeC4Model && !isEmptyish(optionalLikeC4Model.$data.manualLayouts);
38
38
  const hasLikeC4Model = !!optionalLikeC4Model;
39
- const hasEditor = !!useOptionalLikeC4Editor();
39
+ const editor = useOptionalLikeC4Editor();
40
+ const hasEditor = !!editor;
40
41
  const readonly = !hasEditor;
41
42
  nodesSelectable ??= hasEditor || enableFocusMode || !!onNavigateTo || !!onNodeClick;
42
43
  const bounds = pickViewBounds(view, dynamicViewVariant);
@@ -66,6 +67,7 @@ function LikeC4Diagram({ onCanvasClick, onCanvasContextMenu, onCanvasDblClick, o
66
67
  features: {
67
68
  enableFitView: fitView,
68
69
  enableEditor: hasEditor,
70
+ enableAISemanticLayout: hasEditor && !!editor.applySemanticLayout,
69
71
  enableReadOnly: readonly,
70
72
  enableFocusMode,
71
73
  enableNavigateTo: !!onNavigateTo,
@@ -1,5 +1,4 @@
1
1
  import "./_virtual/_rolldown/runtime.js";
2
- import { useCallbackRef } from "./hooks/useCallbackRef.js";
3
2
  import { stopPropagation } from "./utils/xyflow.js";
4
3
  import { FitViewPaddings } from "./base/const.js";
5
4
  import { useOptionalLikeC4Model } from "./context/LikeC4ModelContext.js";
@@ -10,11 +9,10 @@ import { ErrorMessage } from "./components/ViewNotFound.js";
10
9
  import { ShadowRoot } from "./shadowroot/ShadowRoot.js";
11
10
  import { css, cx } from "@likec4/styles/css";
12
11
  import { IconX } from "@tabler/icons-react";
13
- import { useRef, useState } from "react";
12
+ import { useState } from "react";
14
13
  import { jsx, jsxs } from "react/jsx-runtime";
15
14
  import { isBoolean } from "remeda";
16
15
  import { ActionIcon } from "@mantine/core";
17
- import { AnimatePresence } from "motion/react";
18
16
  import { Box as Box$1 } from "@likec4/styles/jsx";
19
17
  //#region src/LikeC4View.tsx
20
18
  var cssInteractive = css({
@@ -31,20 +29,19 @@ var cssInteractive = css({
31
29
  * Component is wrapped in ShadowRoot to isolate styles.
32
30
  */
33
31
  function LikeC4View({ viewId, className, pannable = false, zoomable = false, keepAspectRatio = true, colorScheme, injectFontCss = true, controls = false, layoutType: initialLayoutType = "manual", background = "transparent", browser = true, showNavigationButtons = false, enableNotations, enableFocusMode = false, enableDynamicViewWalkthrough = false, enableElementDetails = false, enableRelationshipDetails = false, enableRelationshipBrowser = enableRelationshipDetails, enableNotes = false, reduceGraphics = "auto", mantineTheme, styleNonce, style, reactFlowProps, renderNodes, children, ...props }) {
34
- const rootRef = useRef(null);
35
32
  const likec4model = useOptionalLikeC4Model();
36
33
  const [layoutType, setLayoutType] = useState(initialLayoutType);
37
34
  const [browserViewId, _onNavigateTo] = useState(null);
38
- const onNavigateTo = useCallbackRef((viewId) => {
35
+ const onNavigateTo = (viewId) => {
39
36
  if (viewId && viewId !== browserViewId) setLayoutType(initialLayoutType);
40
37
  _onNavigateTo(viewId);
41
- });
42
- const onNavigateToThisView = useCallbackRef(() => {
38
+ };
39
+ const onNavigateToThisView = () => {
43
40
  onNavigateTo(viewId);
44
- });
45
- const closeBrowser = useCallbackRef(() => {
41
+ };
42
+ const closeBrowser = () => {
46
43
  onNavigateTo(null);
47
- });
44
+ };
48
45
  if (!likec4model) return /* @__PURE__ */ jsx(ErrorMessage, { children: "LikeC4Model not found. Make sure you have LikeC4ModelProvider in the component tree." });
49
46
  const viewModel = likec4model.findView(viewId);
50
47
  if (!viewModel) return /* @__PURE__ */ jsxs(ErrorMessage, { children: [
@@ -70,9 +67,7 @@ function LikeC4View({ viewId, className, pannable = false, zoomable = false, kee
70
67
  const isBrowserEnabled = browser !== false;
71
68
  const browserProps = isBoolean(browser) ? {} : browser;
72
69
  const bounds = pickViewBounds(view, props.dynamicViewVariant);
73
- const root = rootRef.current ? { root: rootRef.current } : void 0;
74
70
  return /* @__PURE__ */ jsxs(ShadowRoot, {
75
- ref: rootRef,
76
71
  injectFontCss,
77
72
  theme: mantineTheme,
78
73
  colorScheme,
@@ -109,49 +104,46 @@ function LikeC4View({ viewId, className, pannable = false, zoomable = false, kee
109
104
  renderNodes,
110
105
  ...props,
111
106
  children
112
- }), /* @__PURE__ */ jsx(AnimatePresence, {
113
- ...root,
114
- children: browserView && /* @__PURE__ */ jsxs(Overlay, {
115
- openDelay: 0,
116
- onClose: closeBrowser,
117
- children: [/* @__PURE__ */ jsx(LikeC4Diagram, {
118
- view: browserView,
119
- pannable: true,
120
- zoomable: true,
121
- background: "dots",
122
- onNavigateTo,
123
- showNavigationButtons: true,
124
- enableDynamicViewWalkthrough: true,
125
- enableFocusMode: true,
126
- enableRelationshipBrowser: true,
127
- enableElementDetails: true,
128
- enableRelationshipDetails: true,
129
- enableSearch: true,
130
- enableElementTags: true,
131
- enableNotes: true,
132
- enableCompareWithLatest: true,
133
- controls: true,
134
- fitView: true,
135
- ...props,
136
- fitViewPadding: FitViewPaddings.withControls,
137
- ...browserProps,
138
- enableNotations: browserViewHasNotations && (browserProps.enableNotations ?? true),
139
- renderNodes,
140
- onLayoutTypeChange: setLayoutType
141
- }), /* @__PURE__ */ jsx(Box$1, {
142
- pos: "absolute",
143
- top: "4",
144
- right: "4",
145
- zIndex: "999",
146
- onClick: stopPropagation,
147
- children: /* @__PURE__ */ jsx(ActionIcon, {
148
- variant: "default",
149
- color: "gray",
150
- onClick: closeBrowser,
151
- children: /* @__PURE__ */ jsx(IconX, {})
152
- })
153
- })]
154
- })
107
+ }), browserView && /* @__PURE__ */ jsxs(Overlay, {
108
+ openDelay: 0,
109
+ onClose: closeBrowser,
110
+ children: [/* @__PURE__ */ jsx(LikeC4Diagram, {
111
+ view: browserView,
112
+ pannable: true,
113
+ zoomable: true,
114
+ background: "dots",
115
+ onNavigateTo,
116
+ showNavigationButtons: true,
117
+ enableDynamicViewWalkthrough: true,
118
+ enableFocusMode: true,
119
+ enableRelationshipBrowser: true,
120
+ enableElementDetails: true,
121
+ enableRelationshipDetails: true,
122
+ enableSearch: true,
123
+ enableElementTags: true,
124
+ enableNotes: true,
125
+ enableCompareWithLatest: true,
126
+ controls: true,
127
+ fitView: true,
128
+ ...props,
129
+ fitViewPadding: FitViewPaddings.withControls,
130
+ ...browserProps,
131
+ enableNotations: browserViewHasNotations && (browserProps.enableNotations ?? true),
132
+ renderNodes,
133
+ onLayoutTypeChange: setLayoutType
134
+ }), /* @__PURE__ */ jsx(Box$1, {
135
+ pos: "absolute",
136
+ top: "4",
137
+ right: "4",
138
+ zIndex: "999",
139
+ onClick: stopPropagation,
140
+ children: /* @__PURE__ */ jsx(ActionIcon, {
141
+ variant: "default",
142
+ color: "gray",
143
+ onClick: closeBrowser,
144
+ children: /* @__PURE__ */ jsx(IconX, {})
145
+ })
146
+ })]
155
147
  })]
156
148
  });
157
149
  }
@@ -39,12 +39,8 @@ var ElementsTree = memo(() => {
39
39
  }
40
40
  break;
41
41
  }
42
- case "ArrowUp":
43
- console.log("ArrowUp", { selected: api.selectedValue });
44
- break;
45
- default:
46
- console.log(e.key);
47
- return;
42
+ case "ArrowUp": break;
43
+ default: return;
48
44
  }
49
45
  } }),
50
46
  children: /* @__PURE__ */ jsxs(Tree$1.Root, {
@@ -1,5 +1,5 @@
1
1
  import "../_virtual/_rolldown/runtime.js";
2
- import { PanningAtomSafeCtx, ReduceGraphicsModeProvider, RootContainerContextProvider } from "../context/RootContainerContext.js";
2
+ import { RootContainerContextProvider } from "../context/RootContainerContext.js";
3
3
  import { cx } from "@likec4/styles/css";
4
4
  import { useMemo, useRef, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -13,23 +13,24 @@ function RootContainer({ id, className, reduceGraphics = false, children }) {
13
13
  const ctx = useMemo(() => ({
14
14
  id,
15
15
  ref,
16
- selector: `#${id}`
17
- }), [id, ref]);
18
- return /* @__PURE__ */ jsx(ReduceGraphicsModeProvider, {
19
- value: reduceGraphics,
20
- children: /* @__PURE__ */ jsx(PanningAtomSafeCtx, {
21
- value: $isPanning,
22
- children: /* @__PURE__ */ jsx("div", {
23
- id,
24
- className: cx("likec4-root", className),
25
- ref,
26
- "data-likec4-diagram-panning": isPanning,
27
- ...reduceGraphics && { ["data-likec4-reduced-graphics"]: true },
28
- children: /* @__PURE__ */ jsx(RootContainerContextProvider, {
29
- value: ctx,
30
- children
31
- })
32
- })
16
+ selector: `#${id}`,
17
+ reducedGraphics: reduceGraphics,
18
+ $panning: $isPanning
19
+ }), [
20
+ id,
21
+ ref,
22
+ reduceGraphics,
23
+ $isPanning
24
+ ]);
25
+ return /* @__PURE__ */ jsx("div", {
26
+ id,
27
+ className: cx("likec4-root", className),
28
+ ref,
29
+ "data-likec4-diagram-panning": isPanning,
30
+ ...reduceGraphics && { ["data-likec4-reduced-graphics"]: true },
31
+ children: /* @__PURE__ */ jsx(RootContainerContextProvider, {
32
+ value: ctx,
33
+ children
33
34
  })
34
35
  });
35
36
  }
@@ -1,7 +1,7 @@
1
1
  import { ExclusiveUnion } from '@likec4/core/types';
2
2
  import { PropsWithChildren } from 'react';
3
3
  import { JSX } from 'react/jsx-runtime';
4
- declare const FeatureNames: readonly ["Controls", "Editor", "ReadOnly", "FocusMode", "NavigateTo", "ElementDetails", "RelationshipDetails", "RelationshipBrowser", "Search", "NavigationButtons", "Notations", "DynamicViewWalkthrough", "FitView", "CompareWithLatest", "Notes", "Vscode", "ElementTags"];
4
+ declare const FeatureNames: readonly ["Controls", "Editor", "AISemanticLayout", "ReadOnly", "FocusMode", "NavigateTo", "ElementDetails", "RelationshipDetails", "RelationshipBrowser", "Search", "NavigationButtons", "Notations", "DynamicViewWalkthrough", "FitView", "CompareWithLatest", "Notes", "Vscode", "ElementTags"];
5
5
  export type FeatureName = typeof FeatureNames[number];
6
6
  export type TogglableFeature = ('ReadOnly' | 'CompareWithLatest') & FeatureName;
7
7
  export type EnabledFeatures = {
@@ -6,6 +6,10 @@ import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
6
6
  //#region src/context/DiagramFeatures.tsx
7
7
  var DefaultFeatures = {
8
8
  enableEditor: false,
9
+ /**
10
+ * Enabled if editor has `applySemanticLayout` method
11
+ */
12
+ enableAISemanticLayout: false,
9
13
  enableReadOnly: true,
10
14
  enableCompareWithLatest: false,
11
15
  enableControls: false,
@@ -51,6 +55,7 @@ function DiagramFeatures({ children, features, overrides }) {
51
55
  var overridesForOverlays = {
52
56
  enableControls: false,
53
57
  enableReadOnly: true,
58
+ enableAISemanticLayout: false,
54
59
  enableCompareWithLatest: false
55
60
  };
56
61
  DiagramFeatures.Overlays = ({ children }) => {
@@ -1,26 +1,19 @@
1
1
  import { WritableAtom } from 'nanostores';
2
- import { RefObject, Provider, Context } from 'react';
3
- export declare const RootContainerContextProvider: Provider<{
4
- id: string;
5
- selector: string;
6
- ref: RefObject<HTMLDivElement | null>;
7
- } | null>;
8
- export declare function useRootContainerContext(): {
9
- id: string;
10
- selector: string;
11
- ref: RefObject<HTMLDivElement | null>;
12
- } | null;
13
- export declare function useRootContainer(): {
14
- id: string;
15
- selector: string;
16
- ref: RefObject<HTMLDivElement | null>;
2
+ import { RefObject, Provider } from 'react';
3
+ export type RootContainerContextType = {
4
+ readonly id: string;
5
+ readonly selector: string;
6
+ readonly ref: RefObject<HTMLDivElement | null>;
7
+ readonly $panning: WritableAtom<boolean>;
8
+ readonly reducedGraphics: boolean;
17
9
  };
10
+ export declare const RootContainerContextProvider: Provider<RootContainerContextType | null>;
11
+ export declare function useRootContainerContext(): RootContainerContextType | null;
12
+ export declare function useRootContainer(): RootContainerContextType;
18
13
  export declare function useRootContainerRef(): RefObject<HTMLDivElement | null>;
19
14
  export declare function useRootContainerElement(): HTMLDivElement | null;
20
- export declare const ReduceGraphicsModeProvider: Provider<boolean | null>;
21
15
  /**
22
16
  * Hook to determine if reduced graphics mode is enabled.
23
17
  */
24
18
  export declare function useIsReducedGraphics(): boolean;
25
- export declare const PanningAtomSafeCtx: Context<WritableAtom<boolean> | null>, usePanningAtom: () => WritableAtom<boolean>;
26
19
  export declare function useIsPanning(): boolean;
@@ -1,6 +1,5 @@
1
1
  import "../_virtual/_rolldown/runtime.js";
2
2
  import { createContext, useContext } from "react";
3
- import { createSafeContext } from "@mantine/core";
4
3
  import "@nanostores/react";
5
4
  //#region src/context/RootContainerContext.tsx
6
5
  var RootContainerContext = createContext(null);
@@ -19,16 +18,5 @@ function useRootContainerRef() {
19
18
  function useRootContainerElement() {
20
19
  return useRootContainer().ref.current;
21
20
  }
22
- var ReduceGraphicsModeCtx = createContext(null);
23
- var ReduceGraphicsModeProvider = ReduceGraphicsModeCtx.Provider;
24
- /**
25
- * Hook to determine if reduced graphics mode is enabled.
26
- */
27
- function useIsReducedGraphics() {
28
- const isReduced = useContext(ReduceGraphicsModeCtx);
29
- if (isReduced === null) console.warn("ReduceGraphicsMode is not provided");
30
- return isReduced ?? false;
31
- }
32
- var [PanningAtomSafeCtx, usePanningAtom] = createSafeContext("PanningAtomSafeCtx is not provided");
33
21
  //#endregion
34
- export { PanningAtomSafeCtx, ReduceGraphicsModeProvider, RootContainerContextProvider, useIsReducedGraphics, usePanningAtom, useRootContainerContext, useRootContainerElement, useRootContainerRef };
22
+ export { RootContainerContextProvider, useRootContainer, useRootContainerContext, useRootContainerElement, useRootContainerRef };
@@ -5,11 +5,11 @@ export * from './primitives';
5
5
  export type { BaseEdge, BaseEdgeData, BaseEdgeProps, BaseEdgePropsWithData, BaseNode, BaseNodeData, BaseNodeProps, BaseNodePropsWithData, } from '../base/types';
6
6
  export type { DiagramNodeWithNavigate, ElementIconRenderer, ElementIconRendererProps, LikeC4ColorScheme, LikeC4DiagramEventHandlers, LikeC4DiagramProperties, NodeRenderers, OnCanvasClick, OnEdgeClick, OnNavigateTo, OnNodeClick, OpenSourceParams, PaddingUnit, PaddingWithUnit, ViewPadding, WhereOperator, } from '../LikeC4Diagram.props';
7
7
  export { Base } from '../base/Base';
8
+ export type { XYStoreState } from '../hooks/useXYFlow';
8
9
  export type { Types } from '../likec4diagram/types';
9
10
  export { type EnabledFeatures, IfEnabled, IfNotEnabled, IfNotReadOnly, IfReadOnly, useEnabledFeatures, } from '../context/DiagramFeatures';
10
11
  export { Overlay } from '../overlays/overlay/Overlay';
11
12
  export type { OverlayProps } from '../overlays/overlay/Overlay';
12
13
  export { PortalToContainer } from '../components/PortalToContainer';
13
- export { ShadowRoot } from '../shadowroot/ShadowRoot';
14
14
  export { FramerMotionConfig } from '../context/FramerMotionConfig';
15
15
  export { NavigationPanel } from '../components/NavigationPanel';
@@ -35,7 +35,6 @@ import { CompoundDeploymentToolbar, CompoundElementToolbar } from "../likec4diag
35
35
  import { DeploymentElementToolbar, ElementToolbar } from "../likec4diagram/custom/nodes/toolbar/ElementToolbar.js";
36
36
  import { CompoundDeploymentNode, CompoundDetailsButtonWithHandler, CompoundElementNode, DeploymentNode, ElementDetailsButtonWithHandler, ElementNode, ViewGroupNode } from "../likec4diagram/custom/nodes/nodes.js";
37
37
  import { SequenceActorNode, SequenceParallelArea } from "../likec4diagram/custom/nodes/SequenceActorNode.js";
38
- import { ShadowRoot } from "../shadowroot/ShadowRoot.js";
39
38
  import { NavigationPanel } from "../components/NavigationPanel.js";
40
39
  import { compoundDeploymentNode, compoundElementNode, deploymentNode, elementNode, sequenceActorNode, viewGroupNode } from "./customNodes.js";
41
- export { Base, CompoundActionButton, CompoundActions, CompoundDeploymentNode, CompoundDeploymentToolbar, CompoundDetailsButton, CompoundDetailsButtonWithHandler, CompoundElementNode, CompoundElementToolbar, CompoundNodeContainer, CompoundTitle, DefaultHandles, DeploymentElementActions, DeploymentElementToolbar, DeploymentNode, ElementActionButtons, ElementActions, ElementData, ElementDetailsButton, ElementDetailsButtonWithHandler, ElementNode, ElementNodeContainer, ElementShape, ElementTag, ElementTags, ElementToolbar, FramerMotionConfig, IfEnabled, IfNotEnabled, IfNotReadOnly, IfReadOnly, Markdown, NavigationPanel, Overlay, PortalToContainer, SequenceActorNode, SequenceParallelArea, ShadowRoot, Toolbar, ViewGroupNode, compoundDeploymentNode, compoundElementNode, deploymentNode, elementNode, memoEdge, memoNode, sequenceActorNode, useCurrentView, useCurrentViewId, useCurrentViewModel, useDiagram, useDiagramActorRef, useDiagramContext, useDiagramEventHandlers, useEnabledFeatures, useHasProjects, useLikeC4Model, useLikeC4Project, useLikeC4ProjectId, useLikeC4Projects, useLikeC4ProjectsContext, useLikeC4Specification, useLikeC4Styles, useLikeC4ViewModel, useOnDiagramEvent, useOptionalCurrentViewModel, useOptionalLikeC4Model, useSetState, useUpdateEffect, viewGroupNode };
40
+ export { Base, CompoundActionButton, CompoundActions, CompoundDeploymentNode, CompoundDeploymentToolbar, CompoundDetailsButton, CompoundDetailsButtonWithHandler, CompoundElementNode, CompoundElementToolbar, CompoundNodeContainer, CompoundTitle, DefaultHandles, DeploymentElementActions, DeploymentElementToolbar, DeploymentNode, ElementActionButtons, ElementActions, ElementData, ElementDetailsButton, ElementDetailsButtonWithHandler, ElementNode, ElementNodeContainer, ElementShape, ElementTag, ElementTags, ElementToolbar, FramerMotionConfig, IfEnabled, IfNotEnabled, IfNotReadOnly, IfReadOnly, Markdown, NavigationPanel, Overlay, PortalToContainer, SequenceActorNode, SequenceParallelArea, Toolbar, ViewGroupNode, compoundDeploymentNode, compoundElementNode, deploymentNode, elementNode, memoEdge, memoNode, sequenceActorNode, useCurrentView, useCurrentViewId, useCurrentViewModel, useDiagram, useDiagramActorRef, useDiagramContext, useDiagramEventHandlers, useEnabledFeatures, useHasProjects, useLikeC4Model, useLikeC4Project, useLikeC4ProjectId, useLikeC4Projects, useLikeC4ProjectsContext, useLikeC4Specification, useLikeC4Styles, useLikeC4ViewModel, useOnDiagramEvent, useOptionalCurrentViewModel, useOptionalLikeC4Model, useSetState, useUpdateEffect, viewGroupNode };
@@ -3,6 +3,11 @@ import type * as t from '@likec4/core/types';
3
3
  * Callbacks from LikeC4 Editor.
4
4
  */
5
5
  export interface LikeC4EditorCallbacks {
6
+ /**
7
+ * Apply semantic layout to a view (if AI is available)
8
+ * See vite-plugin settings for more details
9
+ */
10
+ applySemanticLayout?: undefined | ((viewId: t.ViewId) => Promise<void>);
6
11
  /**
7
12
  * Fetch a view by its ID and layout type.
8
13
  *
@@ -0,0 +1,115 @@
1
+ import { ActorSystem, ActionFunction, CancelAction, PromiseActorLogic, EventObject, NonReducibleUnknown } from 'xstate';
2
+ import { DiagramMachineRef } from '../../likec4diagram/state/machine';
3
+ import { Snapshot, EditorActorContext, EditorActorEvent, EditorActorEmitedEvent } from './types';
4
+ import { HotkeyActorLogic } from './hotkey';
5
+ import type * as t from '@likec4/core/types';
6
+ /**
7
+ * Actually this is DiagramActorRef
8
+ * But we can't use it here due to circular type inference
9
+ */
10
+ export declare const diagramActorRef: (system: ActorSystem<any>) => DiagramMachineRef;
11
+ export declare function makeSnapshot(system: ActorSystem<any>): Snapshot;
12
+ type LayoutChanges = t.ViewChange.ResetManualLayout | t.ViewChange.SaveViewSnapshot;
13
+ export declare const isLayoutChange: (change: t.ViewChange) => change is LayoutChanges;
14
+ export declare const withoutSnapshotChanges: (data: t.ViewChange[]) => (t.ViewChange.ChangeElementStyle | t.ViewChange.ChangeAutoLayout | t.ViewChange.ChangeProperty)[];
15
+ export declare const scheduleSync: (delay?: number) => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, never, never, never, "500ms" | "wait-after-edit", never>;
16
+ export declare const cancelSync: () => CancelAction<EditorActorContext, EditorActorEvent, undefined, EditorActorEvent>;
17
+ /**
18
+ * Save the state before editing starts
19
+ */
20
+ export declare const saveBeforeEditing: ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, {
21
+ src: "hotkey";
22
+ logic: HotkeyActorLogic;
23
+ id: "hotkey";
24
+ } | {
25
+ src: "applyLatest";
26
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplyLatestToManual.Output, import("./setup").EditorCalls.ApplyLatestToManual.Input, EventObject>;
27
+ id: string | undefined;
28
+ } | {
29
+ src: "executeChange";
30
+ logic: PromiseActorLogic<NonReducibleUnknown, import("./setup").EditorCalls.ExecuteChange.Input, EventObject>;
31
+ id: string | undefined;
32
+ } | {
33
+ src: "applySemanticLayout";
34
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplySemanticLayout.Output, import("./setup").EditorCalls.ApplySemanticLayout.Input, EventObject>;
35
+ id: string | undefined;
36
+ }, never, never, never, never>;
37
+ /**
38
+ * When editing finishes, push the "beforeEditing" state to the history stack
39
+ */
40
+ export declare const pushHistory: () => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, {
41
+ src: "hotkey";
42
+ logic: HotkeyActorLogic;
43
+ id: "hotkey";
44
+ } | {
45
+ src: "applyLatest";
46
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplyLatestToManual.Output, import("./setup").EditorCalls.ApplyLatestToManual.Input, EventObject>;
47
+ id: string | undefined;
48
+ } | {
49
+ src: "executeChange";
50
+ logic: PromiseActorLogic<NonReducibleUnknown, import("./setup").EditorCalls.ExecuteChange.Input, EventObject>;
51
+ id: string | undefined;
52
+ } | {
53
+ src: "applySemanticLayout";
54
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplySemanticLayout.Output, import("./setup").EditorCalls.ApplySemanticLayout.Input, EventObject>;
55
+ id: string | undefined;
56
+ }, never, never, never, never>;
57
+ export declare const reschedule: (delay?: number) => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, never, never, never, "500ms" | "wait-after-edit", never>;
58
+ export declare const undo: () => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, {
59
+ src: "hotkey";
60
+ logic: HotkeyActorLogic;
61
+ id: "hotkey";
62
+ } | {
63
+ src: "applyLatest";
64
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplyLatestToManual.Output, import("./setup").EditorCalls.ApplyLatestToManual.Input, EventObject>;
65
+ id: string | undefined;
66
+ } | {
67
+ src: "executeChange";
68
+ logic: PromiseActorLogic<NonReducibleUnknown, import("./setup").EditorCalls.ExecuteChange.Input, EventObject>;
69
+ id: string | undefined;
70
+ } | {
71
+ src: "applySemanticLayout";
72
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplySemanticLayout.Output, import("./setup").EditorCalls.ApplySemanticLayout.Input, EventObject>;
73
+ id: string | undefined;
74
+ }, never, {
75
+ type: "has pending";
76
+ params: unknown;
77
+ } | {
78
+ type: "can undo";
79
+ params: unknown;
80
+ }, "500ms" | "wait-after-edit", EditorActorEmitedEvent>;
81
+ export declare const pushToSyncQueue: () => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, {
82
+ src: "hotkey";
83
+ logic: HotkeyActorLogic;
84
+ id: "hotkey";
85
+ } | {
86
+ src: "applyLatest";
87
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplyLatestToManual.Output, import("./setup").EditorCalls.ApplyLatestToManual.Input, EventObject>;
88
+ id: string | undefined;
89
+ } | {
90
+ src: "executeChange";
91
+ logic: PromiseActorLogic<NonReducibleUnknown, import("./setup").EditorCalls.ExecuteChange.Input, EventObject>;
92
+ id: string | undefined;
93
+ } | {
94
+ src: "applySemanticLayout";
95
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplySemanticLayout.Output, import("./setup").EditorCalls.ApplySemanticLayout.Input, EventObject>;
96
+ id: string | undefined;
97
+ }, never, never, never, never>;
98
+ export declare const clearQueue: () => ActionFunction<EditorActorContext, EditorActorEvent, EditorActorEvent, undefined, {
99
+ src: "hotkey";
100
+ logic: HotkeyActorLogic;
101
+ id: "hotkey";
102
+ } | {
103
+ src: "applyLatest";
104
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplyLatestToManual.Output, import("./setup").EditorCalls.ApplyLatestToManual.Input, EventObject>;
105
+ id: string | undefined;
106
+ } | {
107
+ src: "executeChange";
108
+ logic: PromiseActorLogic<NonReducibleUnknown, import("./setup").EditorCalls.ExecuteChange.Input, EventObject>;
109
+ id: string | undefined;
110
+ } | {
111
+ src: "applySemanticLayout";
112
+ logic: PromiseActorLogic<import("./setup").EditorCalls.ApplySemanticLayout.Output, import("./setup").EditorCalls.ApplySemanticLayout.Input, EventObject>;
113
+ id: string | undefined;
114
+ }, never, never, never, never>;
115
+ export {};
@@ -0,0 +1,122 @@
1
+ import "../../_virtual/_rolldown/runtime.js";
2
+ import { machine } from "./setup.js";
3
+ import { createViewChange } from "../../likec4diagram/state/createViewChange.js";
4
+ import { typedSystem } from "../../likec4diagram/state/utils.js";
5
+ import { isViewChange } from "./types.js";
6
+ import { filter, isNot, omit } from "remeda";
7
+ import { assertEvent } from "xstate";
8
+ //#region src/editor/actor/actions.ts
9
+ /**
10
+ * Actually this is DiagramActorRef
11
+ * But we can't use it here due to circular type inference
12
+ */
13
+ var getDiagramContext = function(system) {
14
+ return system.get("diagram").getSnapshot().context;
15
+ };
16
+ function makeSnapshot(system) {
17
+ const parentContext = getDiagramContext(system);
18
+ return {
19
+ xynodes: parentContext.xynodes.map(({ measured, data, ...n }) => ({
20
+ ...omit(n, [
21
+ "selected",
22
+ "dragging",
23
+ "resizing"
24
+ ]),
25
+ data: omit(data, ["dimmed", "hovered"]),
26
+ measured,
27
+ initialWidth: measured?.width ?? n.width ?? n.initialWidth,
28
+ initialHeight: measured?.height ?? n.height ?? n.initialHeight
29
+ })),
30
+ xyedges: parentContext.xyedges.map(({ data, ...e }) => ({
31
+ ...omit(e, ["selected"]),
32
+ data: omit(data, [
33
+ "active",
34
+ "dimmed",
35
+ "hovered"
36
+ ])
37
+ })),
38
+ change: createViewChange(parentContext),
39
+ view: parentContext.view
40
+ };
41
+ }
42
+ var isLayoutChange = (change) => change.op === "reset-manual-layout" || change.op === "save-view-snapshot";
43
+ filter(isNot(isLayoutChange));
44
+ var scheduleSync = (delay = 50) => {
45
+ return machine.raise({ type: "change.sync-snapshot" }, delay ? {
46
+ delay,
47
+ id: "sync-snapshot"
48
+ } : void 0);
49
+ };
50
+ /**
51
+ * Save the state before editing starts
52
+ */
53
+ var saveBeforeEditing = machine.assign(({ system, event }) => {
54
+ assertEvent(event, "edit.move.start");
55
+ return { editing: {
56
+ subject: event.subject,
57
+ before: makeSnapshot(system)
58
+ } };
59
+ });
60
+ /**
61
+ * When editing finishes, push the "beforeEditing" state to the history stack
62
+ */
63
+ var pushHistory = () => machine.assign(({ context }) => {
64
+ const editing = context.editing;
65
+ if (editing) return {
66
+ editing: null,
67
+ history: {
68
+ head: editing.before,
69
+ tail: context.history
70
+ }
71
+ };
72
+ return {};
73
+ });
74
+ var reschedule = (delay = 300) => machine.raise(({ event }) => ({ ...event }), { delay });
75
+ var undo = () => machine.enqueueActions(({ context: { history }, enqueue }) => {
76
+ if (!history) return;
77
+ const last = history.head;
78
+ enqueue.assign({ history: history.tail });
79
+ enqueue.sendTo(typedSystem.diagramActor, {
80
+ type: "update.view",
81
+ view: last.view,
82
+ xyedges: last.xyedges,
83
+ xynodes: last.xynodes,
84
+ source: "editor"
85
+ });
86
+ enqueue.cancel("undo-view");
87
+ enqueue.raise({
88
+ type: "change.view",
89
+ change: last.change
90
+ }, {
91
+ delay: 200,
92
+ id: "undo-view"
93
+ });
94
+ });
95
+ var pushToSyncQueue = () => machine.assign(({ context: { syncQueue }, event }) => {
96
+ let nextOp;
97
+ switch (event.type) {
98
+ case "change.view":
99
+ nextOp = event.change;
100
+ break;
101
+ case "change.semantic-layout":
102
+ nextOp = "apply-semantic-layout";
103
+ break;
104
+ case "change.latest-to-manual":
105
+ nextOp = "apply-semantic-layout";
106
+ break;
107
+ case "change.sync-snapshot":
108
+ nextOp = "sync-snapshot";
109
+ break;
110
+ default: throw new Error(`Invalid event type: ${event.type}`);
111
+ }
112
+ if (syncQueue.length === 0) return { syncQueue: [nextOp] };
113
+ const isNextLayoutChange = isViewChange(nextOp) && isLayoutChange(nextOp);
114
+ let pending = syncQueue.filter((existingOp) => {
115
+ if (existingOp === nextOp) return false;
116
+ if (isNextLayoutChange && isViewChange(existingOp) && isLayoutChange(existingOp)) return false;
117
+ return true;
118
+ });
119
+ return { syncQueue: pending.length > 0 ? [...pending, nextOp] : [nextOp] };
120
+ });
121
+ //#endregion
122
+ export { makeSnapshot, pushHistory, pushToSyncQueue, reschedule, saveBeforeEditing, scheduleSync, undo };
@@ -4,4 +4,4 @@ export type HotKeyEvent = {
4
4
  };
5
5
  export interface HotkeyActorLogic extends CallbackActorLogic<AnyEventObject, NonReducibleUnknown, HotKeyEvent> {
6
6
  }
7
- export declare const hotkeyActorLogic: HotkeyActorLogic;
7
+ export declare const hotkey: HotkeyActorLogic;
@@ -1,8 +1,8 @@
1
- import "../_virtual/_rolldown/runtime.js";
1
+ import "../../_virtual/_rolldown/runtime.js";
2
2
  import { getHotkeyHandler } from "@mantine/hooks";
3
3
  import { fromCallback } from "xstate";
4
- //#region src/editor/hotkeyActor.ts
5
- var hotkeyActorLogic = fromCallback(({ sendBack }) => {
4
+ //#region src/editor/actor/hotkey.ts
5
+ var hotkey = fromCallback(({ sendBack }) => {
6
6
  const ctrlZHandler = getHotkeyHandler([[
7
7
  "mod + z",
8
8
  (event) => {
@@ -17,4 +17,4 @@ var hotkeyActorLogic = fromCallback(({ sendBack }) => {
17
17
  };
18
18
  });
19
19
  //#endregion
20
- export { hotkeyActorLogic };
20
+ export { hotkey };
@@ -0,0 +1,11 @@
1
+ import { ActorRef, SnapshotFrom, StateMachine } from 'xstate';
2
+ import { EditorActorEvent, EditorActorContext, EditorActorEmitedEvent, EditorActorInput, EditorActorStateTag } from './types';
3
+ export interface EditorActorLogic extends StateMachine<EditorActorContext, EditorActorEvent, any, any, any, any, any, {
4
+ editor: 'idle' | 'moving';
5
+ syncQueue: 'idle' | 'pending' | 'suspended' | 'process';
6
+ }, EditorActorStateTag, EditorActorInput, any, EditorActorEmitedEvent, any, any> {
7
+ }
8
+ export declare const editorActorLogic: EditorActorLogic;
9
+ export type EditorActorSnapshot = SnapshotFrom<EditorActorLogic>;
10
+ export interface EditorActorRef extends ActorRef<EditorActorSnapshot, EditorActorEvent, EditorActorEmitedEvent> {
11
+ }