@likec4/diagram 1.32.0 → 1.32.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 (52) hide show
  1. package/bundle/{chunk-BvTQaUYl.js → chunk-DlHyKoeo.js} +236 -210
  2. package/bundle/custom.js +50 -49
  3. package/bundle/index.js +144 -121
  4. package/dist/LikeC4Diagram.js +1 -1
  5. package/dist/LikeC4Diagram.props.d.ts +14 -3
  6. package/dist/bundle/LikeC4View.js +16 -15
  7. package/dist/bundle/ReactLikeC4.js +7 -6
  8. package/dist/bundle/index.js +1 -1
  9. package/dist/custom/customNodes.d.ts +5 -0
  10. package/dist/custom/hooks.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/likec4diagram/DiagramXYFlow.js +3 -3
  13. package/dist/likec4diagram/custom/nodes/toolbar/_shared.d.ts +5 -5
  14. package/dist/likec4model/index.d.ts +1 -1
  15. package/dist/likec4model/useLikeC4Model.d.ts +2 -1
  16. package/dist/likec4model/useLikeC4Model.js +13 -2
  17. package/dist/overlays/overlay/Overlay.js +24 -4
  18. package/dist/search/Search.d.ts +2 -3
  19. package/dist/search/Search.js +27 -46
  20. package/dist/search/components/ElementsColumn.js +12 -13
  21. package/dist/search/components/PickView.js +6 -6
  22. package/dist/search/components/SearchByTags.js +5 -2
  23. package/dist/search/components/SearchInput.js +16 -14
  24. package/dist/search/components/ViewsColum.js +16 -9
  25. package/dist/search/components/utils.d.ts +3 -2
  26. package/dist/search/components/utils.js +37 -5
  27. package/dist/search/hooks.d.ts +2 -8
  28. package/dist/search/hooks.js +4 -4
  29. package/dist/state/DiagramActorProvider.js +1 -1
  30. package/dist/state/diagram-machine.d.ts +216 -8
  31. package/dist/state/diagram-machine.js +8 -6
  32. package/package.json +9 -8
  33. package/src/LikeC4Diagram.props.ts +14 -3
  34. package/src/LikeC4Diagram.tsx +1 -1
  35. package/src/bundle/LikeC4View.tsx +12 -19
  36. package/src/bundle/ReactLikeC4.tsx +2 -10
  37. package/src/custom/customNodes.tsx +5 -0
  38. package/src/custom/hooks.ts +1 -0
  39. package/src/likec4diagram/DiagramXYFlow.tsx +3 -3
  40. package/src/likec4model/index.ts +2 -0
  41. package/src/likec4model/useLikeC4Model.ts +16 -2
  42. package/src/overlays/overlay/Overlay.tsx +20 -5
  43. package/src/search/Search.tsx +34 -51
  44. package/src/search/components/ElementsColumn.tsx +12 -15
  45. package/src/search/components/PickView.tsx +41 -47
  46. package/src/search/components/SearchByTags.tsx +5 -2
  47. package/src/search/components/SearchInput.tsx +17 -14
  48. package/src/search/components/ViewsColum.tsx +18 -10
  49. package/src/search/components/utils.ts +41 -4
  50. package/src/search/hooks.ts +5 -8
  51. package/src/state/DiagramActorProvider.tsx +2 -1
  52. package/src/state/diagram-machine.ts +8 -6
@@ -3,12 +3,14 @@ import { css } from '@likec4/styles/css';
3
3
  import { HStack } from '@likec4/styles/jsx';
4
4
  import { Button } from '@mantine/core';
5
5
  import { IconX } from '@tabler/icons-react';
6
+ import { useRef } from 'react';
6
7
  import { useLikeC4Model } from '../../likec4model/useLikeC4Model.js';
7
8
  import { useUpdateSearch, useNormalizedSearch } from '../hooks.js';
8
9
  import { focusToFirstFoundElement, moveFocusToSearchInput } from './utils.js';
9
10
  import { ElementTag } from '../../base/primitives/element/ElementTags.js';
10
11
 
11
12
  function SearchByTags() {
13
+ const ref = useRef(null);
12
14
  let tags = useLikeC4Model().tagsSortedByUsage;
13
15
  let setSearch = useUpdateSearch();
14
16
  let search = useNormalizedSearch();
@@ -24,6 +26,7 @@ function SearchByTags() {
24
26
  return /* @__PURE__ */ jsxs(
25
27
  HStack,
26
28
  {
29
+ ref,
27
30
  css: {
28
31
  gap: "md",
29
32
  paddingLeft: 48,
@@ -85,7 +88,7 @@ function SearchByTags() {
85
88
  e.stopPropagation();
86
89
  setSearch(`#${tag}`);
87
90
  setTimeout(() => {
88
- focusToFirstFoundElement();
91
+ focusToFirstFoundElement(ref.current);
89
92
  }, 350);
90
93
  }
91
94
  },
@@ -102,7 +105,7 @@ function SearchByTags() {
102
105
  onClick: (e) => {
103
106
  e.stopPropagation();
104
107
  setSearch("");
105
- moveFocusToSearchInput();
108
+ moveFocusToSearchInput(ref.current);
106
109
  },
107
110
  rightSection: /* @__PURE__ */ jsx(IconX, { size: 14 }),
108
111
  children: "Clear"
@@ -1,10 +1,9 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useCombobox, ComboboxOption, Text, Combobox, ComboboxTarget, Input, rem, ComboboxDropdown, ComboboxOptions, ScrollAreaAutosize, ComboboxEmpty } from '@mantine/core';
3
- import { useFocusWithin, useWindowEvent } from '@mantine/hooks';
4
- import { usePreviousDistinct } from '@react-hookz/web';
3
+ import { useFocusWithin, useWindowEvent, useMergedRef } from '@mantine/hooks';
5
4
  import { IconSearch } from '@tabler/icons-react';
6
- import { memo } from 'react';
7
- import { keys, only } from 'remeda';
5
+ import { memo, useRef } from 'react';
6
+ import { keys } from 'remeda';
8
7
  import { useLikeC4Model } from '../../likec4model/useLikeC4Model.js';
9
8
  import { useSearchActor, useSearch } from '../hooks.js';
10
9
  import { input } from './styles.css.js';
@@ -15,11 +14,11 @@ function startingWithKind(search) {
15
14
  }
16
15
  const SEARCH_PREFIXES = ["#", "kind:"];
17
16
  const LikeC4SearchInput = memo(() => {
18
- const { close, searchActorRef } = useSearchActor();
17
+ const searchActorRef = useSearchActor();
19
18
  const likec4model = useLikeC4Model();
19
+ const inputRef = useRef(null);
20
20
  const { ref, focused } = useFocusWithin();
21
21
  const [search, setSearch] = useSearch();
22
- usePreviousDistinct(search);
23
22
  const combobox = useCombobox({
24
23
  scrollBehavior: "smooth",
25
24
  loop: false
@@ -29,7 +28,7 @@ const LikeC4SearchInput = memo(() => {
29
28
  (event) => {
30
29
  try {
31
30
  if (!focused && (event.key === "Backspace" || event.key.startsWith("Arrow") || event.key.match(/^\p{L}$/u))) {
32
- moveFocusToSearchInput();
31
+ moveFocusToSearchInput(inputRef.current);
33
32
  }
34
33
  } catch (e) {
35
34
  console.warn(e);
@@ -51,12 +50,13 @@ const LikeC4SearchInput = memo(() => {
51
50
  case search.startsWith("#"): {
52
51
  const searchTag = search.toLocaleLowerCase().slice(1);
53
52
  const alloptions = likec4model.tags.filter((tag) => tag.toLocaleLowerCase().includes(searchTag));
54
- isExactMatch = only(alloptions)?.toLocaleLowerCase() === searchTag;
55
53
  if (alloptions.length === 0) {
54
+ isExactMatch = false;
56
55
  options = [
57
56
  /* @__PURE__ */ jsx(ComboboxEmpty, { children: "No tags found" }, "empty-tags")
58
57
  ];
59
58
  } else {
59
+ isExactMatch = likec4model.tags.some((tag) => tag.toLocaleLowerCase() === searchTag);
60
60
  options = alloptions.map((tag) => /* @__PURE__ */ jsxs(ComboboxOption, { value: `#${tag}`, children: [
61
61
  /* @__PURE__ */ jsx(Text, { component: "span", opacity: 0.5, mr: 1, fz: "sm", children: "#" }),
62
62
  tag
@@ -70,13 +70,14 @@ const LikeC4SearchInput = memo(() => {
70
70
  let alloptions = keys(likec4model.specification.elements);
71
71
  if (term) {
72
72
  alloptions = alloptions.filter((kind) => kind.toLocaleLowerCase().includes(term));
73
- isExactMatch = only(alloptions)?.toLocaleLowerCase() === term;
74
73
  }
75
74
  if (alloptions.length === 0) {
75
+ isExactMatch = false;
76
76
  options = [
77
77
  /* @__PURE__ */ jsx(ComboboxEmpty, { children: "No kinds found" }, "empty-kinds")
78
78
  ];
79
79
  } else {
80
+ isExactMatch = alloptions.some((kind) => kind.toLocaleLowerCase() === term);
80
81
  options = alloptions.map((kind) => /* @__PURE__ */ jsxs(ComboboxOption, { value: `kind:${kind}`, children: [
81
82
  /* @__PURE__ */ jsx(Text, { component: "span", opacity: 0.5, mr: 1, fz: "sm", children: "kind:" }),
82
83
  kind
@@ -94,7 +95,7 @@ const LikeC4SearchInput = memo(() => {
94
95
  if (!SEARCH_PREFIXES.includes(optionValue)) {
95
96
  combobox.closeDropdown();
96
97
  setTimeout(() => {
97
- focusToFirstFoundElement();
98
+ focusToFirstFoundElement(inputRef.current);
98
99
  }, 350);
99
100
  }
100
101
  },
@@ -111,10 +112,11 @@ const LikeC4SearchInput = memo(() => {
111
112
  /* @__PURE__ */ jsx(ComboboxTarget, { children: /* @__PURE__ */ jsx(
112
113
  Input,
113
114
  {
114
- ref,
115
- id: "likec4searchinput",
115
+ ref: useMergedRef(inputRef, ref),
116
116
  placeholder: "Search by title, description or start with # or kind:",
117
117
  autoFocus: true,
118
+ "data-autofocus": true,
119
+ "data-likec4-search-input": true,
118
120
  tabIndex: 0,
119
121
  classNames: {
120
122
  input: input
@@ -129,7 +131,7 @@ const LikeC4SearchInput = memo(() => {
129
131
  e.stopPropagation();
130
132
  const openedWithSearch = searchActorRef.getSnapshot().context.openedWithSearch;
131
133
  if (search === "" || search === openedWithSearch) {
132
- close();
134
+ searchActorRef.send({ type: "close" });
133
135
  } else {
134
136
  setSearch("");
135
137
  }
@@ -197,7 +199,7 @@ const LikeC4SearchInput = memo(() => {
197
199
  search === "" && combobox.getSelectedOptionIndex() === options.length - 1)) {
198
200
  combobox.closeDropdown();
199
201
  stopAndPrevent(e);
200
- focusToFirstFoundElement();
202
+ focusToFirstFoundElement(inputRef.current);
201
203
  return;
202
204
  }
203
205
  }
@@ -4,18 +4,19 @@ import { Box } from '@likec4/styles/jsx';
4
4
  import { Stack, VisuallyHidden, UnstyledButton, createScopedKeydownHandler, ThemeIcon, Group, Highlight, Badge } from '@mantine/core';
5
5
  import { IconStack2, IconZoomScan } from '@tabler/icons-react';
6
6
  import * as m from 'motion/react-m';
7
- import { memo } from 'react';
7
+ import { memo, useRef } from 'react';
8
8
  import { first } from 'remeda';
9
9
  import { useCurrentViewId } from '../../hooks/useCurrentViewId.js';
10
10
  import { useDiagram } from '../../hooks/useDiagram.js';
11
11
  import { useLikeC4Model } from '../../likec4model/useLikeC4Model.js';
12
- import { useNormalizedSearch } from '../hooks.js';
12
+ import { useNormalizedSearch, useSearchActor } from '../hooks.js';
13
13
  import { emptyBoX, buttonsva, focusable } from './_shared.css.js';
14
- import { moveFocusToSearchInput, centerY } from './utils.js';
14
+ import { moveFocusToSearchInput, queryAllFocusable, centerY } from './utils.js';
15
15
  import { viewButton } from './ViewsColumn.css.js';
16
16
 
17
17
  const NothingFound = () => /* @__PURE__ */ jsx(Box, { className: emptyBoX, children: "Nothing found" });
18
18
  const ViewsColumn = memo(() => {
19
+ const ref = useRef(null);
19
20
  let views = [...useLikeC4Model().views()];
20
21
  let search = useNormalizedSearch();
21
22
  if (search) {
@@ -33,15 +34,14 @@ const ViewsColumn = memo(() => {
33
34
  return /* @__PURE__ */ jsxs(
34
35
  Stack,
35
36
  {
37
+ ref,
36
38
  renderRoot: (props) => /* @__PURE__ */ jsx(m.div, { layout: true, ...props }),
37
39
  gap: 8,
38
40
  "data-likec4-search-views": true,
39
41
  onKeyDown: (e) => {
40
42
  if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
41
43
  const maxY = e.target.getBoundingClientRect().y;
42
- const elementButtons = [...document.querySelectorAll(
43
- `[data-likec4-search-elements] .likec4-focusable`
44
- )];
44
+ const elementButtons = queryAllFocusable(ref.current, "elements", ".likec4-element-button");
45
45
  let elementButton = elementButtons.length > 1 ? elementButtons.find((el, i, all) => centerY(el) > maxY || i === all.length - 1) : null;
46
46
  elementButton ??= first(elementButtons);
47
47
  if (elementButton) {
@@ -60,7 +60,7 @@ const ViewsColumn = memo(() => {
60
60
  tabIndex: -1,
61
61
  onFocus: (e) => {
62
62
  e.stopPropagation();
63
- moveFocusToSearchInput();
63
+ moveFocusToSearchInput(ref.current);
64
64
  }
65
65
  }
66
66
  ) }),
@@ -78,9 +78,16 @@ const ViewsColumn = memo(() => {
78
78
  });
79
79
  const btn = buttonsva();
80
80
  function ViewButton({ className, view, loop = false, search, ...props }) {
81
+ const searchActorRef = useSearchActor();
81
82
  const diagram = useDiagram();
82
83
  const currentViewId = useCurrentViewId();
83
84
  const isCurrentView = view.id === currentViewId;
85
+ const navigate = () => {
86
+ searchActorRef.send({ type: "close" });
87
+ setTimeout(() => {
88
+ diagram.navigateTo(view.id);
89
+ }, 100);
90
+ };
84
91
  return /* @__PURE__ */ jsxs(
85
92
  UnstyledButton,
86
93
  {
@@ -90,7 +97,7 @@ function ViewButton({ className, view, loop = false, search, ...props }) {
90
97
  ...isCurrentView && { "data-disabled": true },
91
98
  onClick: (e) => {
92
99
  e.stopPropagation();
93
- diagram.navigateTo(view.id);
100
+ navigate();
94
101
  },
95
102
  onKeyDown: createScopedKeydownHandler({
96
103
  siblingSelector: "[data-likec4-view]",
@@ -101,7 +108,7 @@ function ViewButton({ className, view, loop = false, search, ...props }) {
101
108
  onKeyDown: (e) => {
102
109
  if (e.nativeEvent.code === "Space") {
103
110
  e.stopPropagation();
104
- diagram.navigateTo(view.id);
111
+ navigate();
105
112
  }
106
113
  }
107
114
  }),
@@ -1,4 +1,5 @@
1
1
  export declare function stopAndPrevent(e: React.KeyboardEvent | KeyboardEvent): void;
2
2
  export declare function centerY(element: HTMLElement): number;
3
- export declare function moveFocusToSearchInput(): void;
4
- export declare function focusToFirstFoundElement(): void;
3
+ export declare function moveFocusToSearchInput(from: HTMLElement | null | undefined): void;
4
+ export declare function focusToFirstFoundElement(from: HTMLElement | null | undefined): void;
5
+ export declare function queryAllFocusable(from: HTMLElement | null | undefined, where: 'elements' | 'views', selector?: string): HTMLButtonElement[];
@@ -1,3 +1,4 @@
1
+ import { isFunction } from 'remeda';
1
2
  import { focusable } from './_shared.css.js';
2
3
 
3
4
  function stopAndPrevent(e) {
@@ -10,17 +11,48 @@ function centerY(element) {
10
11
  const y = rect.y + Math.floor(rect.height / 2);
11
12
  return y;
12
13
  }
13
- function moveFocusToSearchInput() {
14
- const input = document.getElementById("likec4searchinput");
14
+ function moveFocusToSearchInput(from) {
15
+ if (!from) {
16
+ console.error("moveFocusToSearchInput: from is null or undefined");
17
+ return;
18
+ }
19
+ const root = from.getRootNode();
20
+ if (!isFunction(root.querySelector)) {
21
+ console.error("moveFocusToSearchInput: root.querySelector is not a function");
22
+ return;
23
+ }
24
+ let input = root.querySelector("[data-likec4-search-input]");
15
25
  if (input) {
16
26
  const length = input.value.length;
17
27
  input.focus();
18
28
  input.setSelectionRange(length, length);
19
29
  }
20
30
  }
21
- function focusToFirstFoundElement() {
22
- let firstFoundElement = document.querySelector(`[data-likec4-search] .${focusable}`);
31
+ function focusToFirstFoundElement(from) {
32
+ if (!from) {
33
+ console.error("focusToFirstFoundElement: from is null or undefined");
34
+ return;
35
+ }
36
+ const root = from.getRootNode();
37
+ if (!isFunction(root.querySelector)) {
38
+ console.error("focusToFirstFoundElement: root.querySelector is not a function");
39
+ return;
40
+ }
41
+ let firstFoundElement = root.querySelector(`[data-likec4-search] .${focusable}`);
23
42
  firstFoundElement?.focus();
24
43
  }
44
+ function queryAllFocusable(from, where, selector = `.${focusable}`) {
45
+ if (!from) {
46
+ console.error("queryAllFocusable: from is null or undefined");
47
+ return [];
48
+ }
49
+ const root = from.getRootNode();
50
+ if (!isFunction(root.querySelectorAll)) {
51
+ console.error("queryAllFocusable: root.querySelectorAll is not a function");
52
+ return [];
53
+ }
54
+ const elements = root.querySelectorAll(`[data-likec4-search-${where}] ${selector}`);
55
+ return [...elements];
56
+ }
25
57
 
26
- export { centerY, focusToFirstFoundElement, moveFocusToSearchInput, stopAndPrevent };
58
+ export { centerY, focusToFirstFoundElement, moveFocusToSearchInput, queryAllFocusable, stopAndPrevent };
@@ -1,15 +1,9 @@
1
1
  import { SearchActorRef } from './searchActor';
2
2
  import { Fqn } from '@likec4/core';
3
3
  export declare const SearchActorContext: ({ children, value }: {
4
- value: {
5
- searchActorRef: SearchActorRef;
6
- close: (cb?: () => void) => void;
7
- };
4
+ value: SearchActorRef;
8
5
  children: React.ReactNode;
9
- }) => import("react/jsx-runtime").JSX.Element, useSearchActor: () => {
10
- searchActorRef: SearchActorRef;
11
- close: (cb?: () => void) => void;
12
- };
6
+ }) => import("react/jsx-runtime").JSX.Element, useSearchActor: () => SearchActorRef;
13
7
  export declare function useSearch(): [string, (search: string) => void];
14
8
  export declare function useNormalizedSearch(): string;
15
9
  export declare function useUpdateSearch(): (search: string) => void;
@@ -5,7 +5,7 @@ import { useCallback, useDeferredValue } from 'react';
5
5
  const [SearchActorContext, useSearchActor] = createSafeContext("SearchActorContext");
6
6
  const selectSearchValue = (s) => s.context.searchValue;
7
7
  function useSearch() {
8
- const { searchActorRef } = useSearchActor();
8
+ const searchActorRef = useSearchActor();
9
9
  const searchValue = useSelector(searchActorRef, selectSearchValue);
10
10
  const updateSearch = useCallback((search) => {
11
11
  searchActorRef.send({ type: "change.search", search });
@@ -17,18 +17,18 @@ const selectNormalizedSearchValue = (s) => {
17
17
  return v.length > 1 ? v : "";
18
18
  };
19
19
  function useNormalizedSearch() {
20
- const { searchActorRef } = useSearchActor();
20
+ const searchActorRef = useSearchActor();
21
21
  return useDeferredValue(useSelector(searchActorRef, selectNormalizedSearchValue));
22
22
  }
23
23
  function useUpdateSearch() {
24
- const { searchActorRef } = useSearchActor();
24
+ const searchActorRef = useSearchActor();
25
25
  return useCallback((search) => {
26
26
  searchActorRef.send({ type: "change.search", search });
27
27
  }, [searchActorRef]);
28
28
  }
29
29
  const selectPickViewFor = (s) => s.context.pickViewFor;
30
30
  function usePickViewFor() {
31
- const { searchActorRef } = useSearchActor();
31
+ const searchActorRef = useSearchActor();
32
32
  return useSelector(searchActorRef, selectPickViewFor);
33
33
  }
34
34
 
@@ -29,7 +29,7 @@ function DiagramActorProvider({
29
29
  "trigger:NavigateTo": (_, { viewId }) => {
30
30
  setTimeout(() => {
31
31
  handlersRef.current.onNavigateTo?.(viewId);
32
- }, 30);
32
+ }, 40);
33
33
  },
34
34
  "trigger:OnChange": (_, params) => {
35
35
  handlersRef.current.onChange?.(params);
@@ -2137,15 +2137,223 @@ declare const _diagramMachine: StateMachine<Context, Events, {
2137
2137
  };
2138
2138
  readonly navigating: {
2139
2139
  readonly id: "navigating";
2140
- readonly entry: readonly ["closeAllOverlays", "closeSearch", "stopSyncLayout", {
2141
- readonly type: "trigger:NavigateTo";
2142
- readonly params: ({ context }: {
2143
- context: Context;
2144
- event: Events;
2145
- }) => {
2146
- viewId: ViewId;
2140
+ readonly entry: readonly ["closeAllOverlays", "closeSearch", "stopSyncLayout", ActionFunction<Context, Events, Events, undefined, Values<{
2141
+ syncManualLayoutActorLogic: {
2142
+ src: "syncManualLayoutActorLogic";
2143
+ logic: SyncLayoutActorLogic;
2144
+ id: "syncLayout";
2147
2145
  };
2148
- }];
2146
+ hotkeyActorLogic: {
2147
+ src: "hotkeyActorLogic";
2148
+ logic: HotkeyActorLogic;
2149
+ id: "hotkey";
2150
+ };
2151
+ overlaysActorLogic: {
2152
+ src: "overlaysActorLogic";
2153
+ logic: OverlaysActorLogic;
2154
+ id: "overlays";
2155
+ };
2156
+ searchActorLogic: {
2157
+ src: "searchActorLogic";
2158
+ logic: SearchActorLogic;
2159
+ id: "search";
2160
+ };
2161
+ }>, Values<{
2162
+ onNodeMouseEnter: {
2163
+ type: "onNodeMouseEnter";
2164
+ params: {
2165
+ node: Types.Node;
2166
+ };
2167
+ };
2168
+ onNodeMouseLeave: {
2169
+ type: "onNodeMouseLeave";
2170
+ params: {
2171
+ node: Types.Node;
2172
+ };
2173
+ };
2174
+ onEdgeMouseEnter: {
2175
+ type: "onEdgeMouseEnter";
2176
+ params: {
2177
+ edge: Types.Edge;
2178
+ };
2179
+ };
2180
+ onEdgeMouseLeave: {
2181
+ type: "onEdgeMouseLeave";
2182
+ params: {
2183
+ edge: Types.Edge;
2184
+ };
2185
+ };
2186
+ "trigger:OnChange": {
2187
+ type: "trigger:OnChange";
2188
+ params: {
2189
+ change: ViewChange;
2190
+ };
2191
+ };
2192
+ "layout.align": {
2193
+ type: "layout.align";
2194
+ params: {
2195
+ mode: AlignmentMode;
2196
+ };
2197
+ };
2198
+ "notations.highlight": {
2199
+ type: "notations.highlight";
2200
+ params: {
2201
+ notation: ElementNotation;
2202
+ kind?: string;
2203
+ };
2204
+ };
2205
+ "tag.highlight": {
2206
+ type: "tag.highlight";
2207
+ params: NonReducibleUnknown;
2208
+ };
2209
+ "xyflow:fitDiagram": {
2210
+ type: "xyflow:fitDiagram";
2211
+ params: {
2212
+ duration?: number;
2213
+ bounds?: BBox;
2214
+ } | undefined;
2215
+ };
2216
+ closeAllOverlays: {
2217
+ type: "closeAllOverlays";
2218
+ params: NonReducibleUnknown;
2219
+ };
2220
+ "trigger:NavigateTo": {
2221
+ type: "trigger:NavigateTo";
2222
+ params: {
2223
+ viewId: ViewId;
2224
+ };
2225
+ };
2226
+ "trigger:OpenSource": {
2227
+ type: "trigger:OpenSource";
2228
+ params: OpenSourceParams;
2229
+ };
2230
+ "assign lastClickedNode": {
2231
+ type: "assign lastClickedNode";
2232
+ params: NonReducibleUnknown;
2233
+ };
2234
+ "open source of focused or last clicked node": {
2235
+ type: "open source of focused or last clicked node";
2236
+ params: NonReducibleUnknown;
2237
+ };
2238
+ "xyflow:fitFocusedBounds": {
2239
+ type: "xyflow:fitFocusedBounds";
2240
+ params: unknown;
2241
+ };
2242
+ "xyflow:setViewportCenter": {
2243
+ type: "xyflow:setViewportCenter";
2244
+ params: {
2245
+ x: number;
2246
+ y: number;
2247
+ };
2248
+ };
2249
+ "xyflow:setViewport": {
2250
+ type: "xyflow:setViewport";
2251
+ params: {
2252
+ viewport: Viewport;
2253
+ duration?: number;
2254
+ };
2255
+ };
2256
+ "xyflow:alignNodeFromToAfterNavigate": {
2257
+ type: "xyflow:alignNodeFromToAfterNavigate";
2258
+ params: {
2259
+ fromNode: NodeId;
2260
+ toPosition: XYPoint;
2261
+ };
2262
+ };
2263
+ "ensure overlays actor state": {
2264
+ type: "ensure overlays actor state";
2265
+ params: NonReducibleUnknown;
2266
+ };
2267
+ "ensure search actor state": {
2268
+ type: "ensure search actor state";
2269
+ params: NonReducibleUnknown;
2270
+ };
2271
+ updateFeatures: {
2272
+ type: "updateFeatures";
2273
+ params: NonReducibleUnknown;
2274
+ };
2275
+ closeSearch: {
2276
+ type: "closeSearch";
2277
+ params: NonReducibleUnknown;
2278
+ };
2279
+ startSyncLayout: {
2280
+ type: "startSyncLayout";
2281
+ params: NonReducibleUnknown;
2282
+ };
2283
+ stopSyncLayout: {
2284
+ type: "stopSyncLayout";
2285
+ params: NonReducibleUnknown;
2286
+ };
2287
+ "focus on nodes and edges": {
2288
+ type: "focus on nodes and edges";
2289
+ params: NonReducibleUnknown;
2290
+ };
2291
+ "undim everything": {
2292
+ type: "undim everything";
2293
+ params: NonReducibleUnknown;
2294
+ };
2295
+ "update active walkthrough": {
2296
+ type: "update active walkthrough";
2297
+ params: NonReducibleUnknown;
2298
+ };
2299
+ }>, Values<{
2300
+ isReady: {
2301
+ type: "isReady";
2302
+ params: unknown;
2303
+ };
2304
+ "enabled: FitView": {
2305
+ type: "enabled: FitView";
2306
+ params: unknown;
2307
+ };
2308
+ "enabled: FocusMode": {
2309
+ type: "enabled: FocusMode";
2310
+ params: unknown;
2311
+ };
2312
+ "enabled: Readonly": {
2313
+ type: "enabled: Readonly";
2314
+ params: unknown;
2315
+ };
2316
+ "enabled: RelationshipDetails": {
2317
+ type: "enabled: RelationshipDetails";
2318
+ params: unknown;
2319
+ };
2320
+ "enabled: Search": {
2321
+ type: "enabled: Search";
2322
+ params: unknown;
2323
+ };
2324
+ "not readonly": {
2325
+ type: "not readonly";
2326
+ params: unknown;
2327
+ };
2328
+ "is dynamic view": {
2329
+ type: "is dynamic view";
2330
+ params: unknown;
2331
+ };
2332
+ "is another view": {
2333
+ type: "is another view";
2334
+ params: unknown;
2335
+ };
2336
+ "click: selected node": {
2337
+ type: "click: selected node";
2338
+ params: unknown;
2339
+ };
2340
+ "click: same node": {
2341
+ type: "click: same node";
2342
+ params: unknown;
2343
+ };
2344
+ "click: focused node": {
2345
+ type: "click: focused node";
2346
+ params: unknown;
2347
+ };
2348
+ "click: node has connections": {
2349
+ type: "click: node has connections";
2350
+ params: unknown;
2351
+ };
2352
+ "click: selected edge": {
2353
+ type: "click: selected edge";
2354
+ params: unknown;
2355
+ };
2356
+ }>, never, EventObject>];
2149
2357
  readonly on: {
2150
2358
  readonly 'update.view': {
2151
2359
  readonly actions: ActionFunction<Context, {
@@ -819,12 +819,14 @@ const _diagramMachine = setup({
819
819
  "closeAllOverlays",
820
820
  "closeSearch",
821
821
  "stopSyncLayout",
822
- {
823
- type: "trigger:NavigateTo",
824
- params: ({ context }) => ({
825
- viewId: nonNullable(context.lastOnNavigate, "Invalid state, lastOnNavigate is null").toView
826
- })
827
- }
822
+ enqueueActions(({ enqueue, context }) => {
823
+ enqueue({
824
+ type: "trigger:NavigateTo",
825
+ params: {
826
+ viewId: nonNullable(context.lastOnNavigate, "Invalid state, lastOnNavigate is null").toView
827
+ }
828
+ });
829
+ })
828
830
  ],
829
831
  on: {
830
832
  "update.view": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.32.0",
3
+ "version": "1.32.1",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -85,9 +85,9 @@
85
85
  "remeda": "^2.23.0",
86
86
  "type-fest": "^4.41.0",
87
87
  "xstate": "^5.19.3",
88
- "@likec4/core": "1.32.0",
89
- "@likec4/styles": "1.32.0",
90
- "@likec4/style-preset": "1.32.0"
88
+ "@likec4/styles": "1.32.1",
89
+ "@likec4/core": "1.32.1",
90
+ "@likec4/style-preset": "1.32.1"
91
91
  },
92
92
  "peerDependencies": {
93
93
  "react": "^18.x || ^19.x",
@@ -100,7 +100,7 @@
100
100
  "@types/d3-shape": "^3.1.7",
101
101
  "@types/react": "^19.1.5",
102
102
  "@types/react-dom": "^19.1.5",
103
- "@types/node": "^20.19.0",
103
+ "@types/node": "~20.19.0",
104
104
  "@vitejs/plugin-react": "^4.5.0",
105
105
  "postcss": "^8.5.4",
106
106
  "react": "^19.1.0",
@@ -108,9 +108,9 @@
108
108
  "typescript": "^5.8.3",
109
109
  "vite": "^6.3.5",
110
110
  "vite-plugin-dts": "^4.5.4",
111
- "vitest": "^3.2.3",
111
+ "vitest": "3.2.3",
112
112
  "wireit": "^0.14.12",
113
- "@likec4/tsconfig": "1.32.0"
113
+ "@likec4/tsconfig": "1.32.1"
114
114
  },
115
115
  "scripts": {
116
116
  "typecheck": "tsc --build --verbose",
@@ -118,6 +118,7 @@
118
118
  "build:bundle": "vite build -m bundle",
119
119
  "build": "echo \"use pnpm turbo run build\" || true",
120
120
  "pack": "pnpm pack",
121
- "test": "vitest run --no-isolate"
121
+ "test": "vitest run --no-isolate",
122
+ "clean": "pnpm rimraf dist lib bundle"
122
123
  }
123
124
  }