likec4 1.8.2-next.1 → 1.10.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.
package/README.md CHANGED
@@ -156,9 +156,69 @@ likec4 codegen ts ...
156
156
 
157
157
  ## API Usage
158
158
 
159
- LikeC4 model can be accessed
159
+ You can access and traverse your architecture model programmatically using the LikeC4 Model API.
160
160
 
161
+ ### From workspace
161
162
 
163
+ Recursively searches and parses source files from the wokrkspace directory:
164
+
165
+ ```ts
166
+ import { LikeC4 } from 'likec4'
167
+
168
+ const likec4 = await LikeC4.fromWorkspace('path to workspace', opts)
169
+ ```
170
+
171
+ ### From source
172
+
173
+ Parses the model from the string:
174
+
175
+ ```ts
176
+ import { LikeC4 } from "likec4"
177
+
178
+ const likec4 = await LikeC4.fromSource(`
179
+ specification {
180
+ element system
181
+ element user
182
+ }
183
+ model {
184
+ customer = user 'Customer'
185
+ cloud = system 'System'
186
+ }
187
+ views {
188
+ view index {
189
+ include *
190
+ }
191
+ }
192
+ `, opts)
193
+ ```
194
+
195
+ ### Example
196
+
197
+ When the model is initialized, you can use the following methods to query and traverse it.
198
+
199
+ ```ts
200
+ import { LikeC4 } from "likec4"
201
+
202
+ const likec4 = await LikeC4.fromSource(`....`)
203
+
204
+ // Validation errors
205
+ console.log(likec4.getErrors())
206
+
207
+ // Traverse the model
208
+ const model = likec4.model()
209
+ model
210
+ .element('cloud.backend.api')
211
+ .incoming() // relationships incoming to the element
212
+ .filter(r => r.tags.includes('http')) // filter by tags
213
+ .map(r => r.source) // get source elements
214
+
215
+ // Layouted views
216
+ const diagrams = await likec4.diagrams()
217
+
218
+
219
+ ```
220
+
221
+ Check Typescript definitions for available methods.
162
222
 
163
223
  ## Development
164
224
 
@@ -1,5 +1,11 @@
1
- import type { LikeC4ViewBaseProps } from 'likec4/react'
2
- import { LikeC4Browser, LikeC4ViewElement, useColorScheme } from 'likec4/react'
1
+ import {
2
+ LikeC4Browser,
3
+ LikeC4ViewEmbedded,
4
+ type LikeC4ViewProps as BaseLikeC4ViewProps,
5
+ ReactLikeC4 as GenericReactLikeC4,
6
+ type ReactLikeC4Props as GenericReactLikeC4Props,
7
+ useColorScheme
8
+ } from 'likec4/react'
3
9
  import { memo, useCallback, useState } from 'react'
4
10
  import { Icons } from 'virtual:likec4/icons'
5
11
  import {
@@ -18,16 +24,34 @@ type IconRendererProps = {
18
24
  }
19
25
  }
20
26
 
21
- const RenderIcon = ({ node }: IconRendererProps) => {
27
+ function RenderIcon({ node }: IconRendererProps) {
22
28
  const IconComponent = Icons[node.icon ?? '']
23
29
  return IconComponent ? <IconComponent /> : null
24
30
  }
25
31
 
26
- export { isLikeC4ViewId }
32
+ export { isLikeC4ViewId, LikeC4Views, RenderIcon }
33
+
34
+ export type LikeC4ViewProps = BaseLikeC4ViewProps<LikeC4ViewId, LikeC4Tag, LikeC4ElementKind>
27
35
 
28
- export type LikeC4ViewProps = LikeC4ViewBaseProps<LikeC4ViewId, LikeC4Tag, LikeC4ElementKind>
36
+ const NotFound = ({ viewId }: { viewId: string }) => (
37
+ <div
38
+ style={{
39
+ margin: '1rem 0'
40
+ }}>
41
+ <div
42
+ style={{
43
+ margin: '0 auto',
44
+ display: 'inline-block',
45
+ padding: '2rem',
46
+ background: 'rgba(250,82,82,.15)',
47
+ color: '#ffa8a8'
48
+ }}>
49
+ View <code>{viewId}</code> not found
50
+ </div>
51
+ </div>
52
+ )
29
53
 
30
- export const LikeC4View = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4ViewComponent({
54
+ const LikeC4ViewMemo = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4View({
31
55
  viewId,
32
56
  interactive = true,
33
57
  colorScheme: explicitColorScheme,
@@ -40,6 +64,9 @@ export const LikeC4View = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4V
40
64
  showNavigationButtons = false,
41
65
  showNotations = false,
42
66
  enableFocusMode = false,
67
+ browserClassName,
68
+ browserStyle,
69
+ mantineTheme,
43
70
  ...props
44
71
  }) {
45
72
  const view = LikeC4Views[viewId]
@@ -52,23 +79,23 @@ export const LikeC4View = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4V
52
79
  onNavigateTo(null)
53
80
  }, [onNavigateTo])
54
81
 
82
+ const colorScheme = useColorScheme(explicitColorScheme)
83
+
55
84
  if (!view) {
56
- throw new Error(`View with id ${viewId} not found`)
85
+ return <NotFound viewId={viewId} />
57
86
  }
58
87
 
59
88
  if (browserViewId && !browserView) {
60
- throw new Error(`View with id ${browserViewId} not found`)
89
+ return <NotFound viewId={browserViewId} />
61
90
  }
62
91
 
63
92
  if (interactive && enableFocusMode) {
64
93
  console.warn('Focus mode is not supported in interactive mode')
65
94
  }
66
95
 
67
- const colorScheme = useColorScheme(explicitColorScheme)
68
-
69
96
  return (
70
97
  <>
71
- <LikeC4ViewElement<LikeC4ViewId, LikeC4Tag, LikeC4ElementKind>
98
+ <LikeC4ViewEmbedded<LikeC4ViewId, LikeC4Tag, LikeC4ElementKind>
72
99
  view={view}
73
100
  colorScheme={colorScheme}
74
101
  injectFontCss={injectFontCss}
@@ -81,6 +108,7 @@ export const LikeC4View = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4V
81
108
  showNotations={showNotations}
82
109
  enableFocusMode={enableFocusMode}
83
110
  where={where}
111
+ mantineTheme={mantineTheme}
84
112
  {...props}
85
113
  />
86
114
  {browserView && (
@@ -93,9 +121,33 @@ export const LikeC4View = /* @__PURE__ */ memo<LikeC4ViewProps>(function LikeC4V
93
121
  onClose={closeBrowser}
94
122
  renderIcon={RenderIcon}
95
123
  where={where}
124
+ className={browserClassName}
125
+ style={browserStyle}
126
+ mantineTheme={mantineTheme}
96
127
  />
97
128
  )}
98
129
  </>
99
130
  )
100
131
  })
101
- LikeC4View.displayName = 'LikeC4View'
132
+ LikeC4ViewMemo.displayName = 'LikeC4ViewMemo'
133
+ export { LikeC4ViewMemo as LikeC4View }
134
+
135
+ export type ReactLikeC4Props =
136
+ & Omit<GenericReactLikeC4Props<LikeC4ViewId, LikeC4Tag, LikeC4ElementKind>, 'view' | 'renderIcon'>
137
+ & {
138
+ viewId: LikeC4ViewId
139
+ }
140
+
141
+ export function ReactLikeC4({ viewId, ...props }: ReactLikeC4Props) {
142
+ const view = LikeC4Views[viewId]
143
+ if (!view) {
144
+ return <NotFound viewId={viewId} />
145
+ }
146
+ return (
147
+ <GenericReactLikeC4
148
+ view={view}
149
+ renderIcon={RenderIcon}
150
+ {...props}
151
+ />
152
+ )
153
+ }
@@ -0,0 +1,317 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useOverviewGraph } from "virtual:likec4/overview-graph";
3
+ import { u, c as createReactComponent, I as IconFolderFilled, e, a as useUpdateEffect, n as nonexhaustive } from "./main-KEhBGhZ8.js";
4
+ import { u as useRouter } from "./tanstack-router-Bc_WYOzY.js";
5
+ import { B as BaseEdge, H as Handle, P as Position, u as useNodesState, a as useEdgesState, i as index, b as Background, c as BackgroundVariant } from "./likec4-BqIZe8Y0.js";
6
+ import { memo, useRef, useMemo } from "react";
7
+ import { P as Paper, c as clsx, G as Group, T as ThemeIcon, a as Text, C as Card, b as CardSection, d as Center, I as Image, B as Box, u as useMantineColorScheme } from "./mantine-BnwtT_Nz.js";
8
+ import { usePreviewUrl } from "virtual:likec4/previews";
9
+ function a(...n) {
10
+ return u(c, n);
11
+ }
12
+ function c(n, r) {
13
+ let o = {};
14
+ for (let e2 of r) e2 in n && (o[e2] = n[e2]);
15
+ return o;
16
+ }
17
+ /**
18
+ * @license @tabler/icons-react v3.14.0 - MIT
19
+ *
20
+ * This source code is licensed under the MIT license.
21
+ * See the LICENSE file in the root directory of this source tree.
22
+ */
23
+ var IconLoader = createReactComponent("outline", "loader", "IconLoader", [["path", { d: "M12 6l0 -3", key: "svg-0" }], ["path", { d: "M16.25 7.75l2.15 -2.15", key: "svg-1" }], ["path", { d: "M18 12l3 0", key: "svg-2" }], ["path", { d: "M16.25 16.25l2.15 2.15", key: "svg-3" }], ["path", { d: "M12 18l0 3", key: "svg-4" }], ["path", { d: "M7.75 16.25l-2.15 2.15", key: "svg-5" }], ["path", { d: "M6 12l-3 0", key: "svg-6" }], ["path", { d: "M7.75 7.75l-2.15 -2.15", key: "svg-7" }]]);
24
+ /**
25
+ * @license @tabler/icons-react v3.14.0 - MIT
26
+ *
27
+ * This source code is licensed under the MIT license.
28
+ * See the LICENSE file in the root directory of this source tree.
29
+ */
30
+ var IconFileFilled = createReactComponent("filled", "file-filled", "IconFileFilled", [["path", { d: "M12 2l.117 .007a1 1 0 0 1 .876 .876l.007 .117v4l.005 .15a2 2 0 0 0 1.838 1.844l.157 .006h4l.117 .007a1 1 0 0 1 .876 .876l.007 .117v9a3 3 0 0 1 -2.824 2.995l-.176 .005h-10a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-14a3 3 0 0 1 2.824 -2.995l.176 -.005h5z", key: "svg-0" }], ["path", { d: "M19 7h-4l-.001 -4.001z", key: "svg-1" }]]), root = "mxt2a80";
31
+ function edgePath(points) {
32
+ return points.reduce((acc, [x, y], i) => acc + `${i === 0 ? "M" : " L"} ${x},${y}`, "");
33
+ }
34
+ function LinkEdge({
35
+ id,
36
+ data,
37
+ ...props
38
+ }) {
39
+ if (!data)
40
+ return null;
41
+ const path = edgePath(data.points);
42
+ return /* @__PURE__ */ jsx(
43
+ BaseEdge,
44
+ {
45
+ id,
46
+ path,
47
+ ...props
48
+ }
49
+ );
50
+ }
51
+ var handleCenter = "_1n8mzjc0", toplevelNode = "_1n8mzjc1", nestedNode = "_1n8mzjc2", dimmed = "_1n8mzjc3", folderNode = "_1n8mzjc4", fileNode = "_1n8mzjc5", viewNode = "_1n8mzjc6", viewNodeImageSection = "_1n8mzjc7", viewTitle = "_1n8mzjc8";
52
+ const FolderNode = /* @__PURE__ */ memo(function({
53
+ data,
54
+ parentId,
55
+ id
56
+ }) {
57
+ const isTopLevel = e(parentId);
58
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
59
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, className: handleCenter }),
60
+ /* @__PURE__ */ jsx(
61
+ Paper,
62
+ {
63
+ p: "sm",
64
+ pt: "xs",
65
+ radius: "md",
66
+ withBorder: !0,
67
+ shadow: isTopLevel ? "lg" : "xs",
68
+ className: clsx(
69
+ folderNode,
70
+ isTopLevel ? toplevelNode : nestedNode,
71
+ data.dimmed && dimmed
72
+ ),
73
+ children: /* @__PURE__ */ jsxs(Group, { gap: 8, children: [
74
+ /* @__PURE__ */ jsx(ThemeIcon, { size: 24, variant: "transparent", color: "dark.4", children: /* @__PURE__ */ jsx(IconFolderFilled, { size: "100%" }) }),
75
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, children: data.label })
76
+ ] })
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, className: handleCenter })
80
+ ] });
81
+ }), FileNode = /* @__PURE__ */ memo(function({
82
+ data,
83
+ parentId,
84
+ id
85
+ }) {
86
+ const isTopLevel = e(parentId);
87
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
88
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, className: handleCenter }),
89
+ /* @__PURE__ */ jsx(
90
+ Paper,
91
+ {
92
+ p: "sm",
93
+ pt: "xs",
94
+ radius: "md",
95
+ withBorder: !0,
96
+ shadow: isTopLevel ? "lg" : "xs",
97
+ className: clsx(
98
+ fileNode,
99
+ isTopLevel ? toplevelNode : nestedNode,
100
+ data.dimmed && dimmed
101
+ ),
102
+ children: /* @__PURE__ */ jsxs(Group, { gap: 8, children: [
103
+ /* @__PURE__ */ jsx(ThemeIcon, { size: 24, variant: "transparent", color: "dark.3", children: /* @__PURE__ */ jsx(IconFileFilled, { size: "100%" }) }),
104
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, children: data.label })
105
+ ] })
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, className: handleCenter })
109
+ ] });
110
+ }), ViewNode = /* @__PURE__ */ memo(function({
111
+ data,
112
+ height = 320
113
+ }) {
114
+ const imageUrl = usePreviewUrl(data.viewId);
115
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
116
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, className: handleCenter }),
117
+ /* @__PURE__ */ jsxs(
118
+ Card,
119
+ {
120
+ className: clsx(
121
+ viewNode,
122
+ data.dimmed && dimmed
123
+ ),
124
+ withBorder: !0,
125
+ shadow: "xs",
126
+ padding: 0,
127
+ children: [
128
+ /* @__PURE__ */ jsx(CardSection, { className: viewNodeImageSection, children: imageUrl ? /* @__PURE__ */ jsx(
129
+ Image,
130
+ {
131
+ src: imageUrl,
132
+ fit: "contain",
133
+ h: height - 60
134
+ }
135
+ ) : /* @__PURE__ */ jsx(Center, { h: height - 60, children: /* @__PURE__ */ jsxs(Group, { children: [
136
+ /* @__PURE__ */ jsx(ThemeIcon, { size: 60, variant: "transparent", color: "dark", children: /* @__PURE__ */ jsx(IconLoader, { stroke: 1.5, size: "100%" }) }),
137
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 500, c: "dimmed", children: "Preview not available" })
138
+ ] }) }) }),
139
+ /* @__PURE__ */ jsx(Box, { className: viewTitle, h: 60, p: "sm", pl: "md", children: /* @__PURE__ */ jsx(Text, { component: "div", size: "lg", fw: 500, children: data.label }) })
140
+ ]
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, className: handleCenter })
144
+ ] });
145
+ }), nodeTypes = {
146
+ folder: FolderNode,
147
+ file: FileNode,
148
+ view: ViewNode
149
+ }, edgeTypes = {
150
+ link: LinkEdge
151
+ }, overviewGraphToXYFlowData = (graph) => ({
152
+ nodes: graph.nodes.map(({ id, parentId, position, width, height, ...node }) => {
153
+ const parent = parentId ? graph.nodes.find((n) => n.id === parentId) : null, rect = {
154
+ ...position,
155
+ width,
156
+ height
157
+ };
158
+ parent && (position = {
159
+ x: position.x - parent.position.x,
160
+ y: position.y - parent.position.y
161
+ });
162
+ const xyparent = parent ? { parentId: parent.id } : {};
163
+ switch (node.type) {
164
+ case "file":
165
+ case "folder":
166
+ return {
167
+ id,
168
+ type: node.type,
169
+ data: {
170
+ dimmed: !1,
171
+ label: node.label,
172
+ path: node.path,
173
+ rect
174
+ },
175
+ deletable: !1,
176
+ position,
177
+ width,
178
+ height,
179
+ zIndex: 1,
180
+ ...xyparent
181
+ };
182
+ case "view":
183
+ return {
184
+ id,
185
+ type: "view",
186
+ data: {
187
+ dimmed: !1,
188
+ label: node.label,
189
+ viewId: node.viewId,
190
+ rect
191
+ },
192
+ selectable: !1,
193
+ deletable: !1,
194
+ position,
195
+ width,
196
+ height,
197
+ zIndex: 3,
198
+ ...xyparent
199
+ };
200
+ default:
201
+ nonexhaustive(node);
202
+ }
203
+ }),
204
+ edges: graph.edges.map((edge) => ({
205
+ id: edge.id,
206
+ source: edge.source,
207
+ target: edge.target,
208
+ type: "link",
209
+ zIndex: 2,
210
+ hidden: !0,
211
+ data: {
212
+ points: edge.points
213
+ }
214
+ }))
215
+ });
216
+ function OverviewDiagrams({
217
+ graph,
218
+ fitViewPadding = 0.1,
219
+ zoomable = !0,
220
+ pannable = !0
221
+ }) {
222
+ const router = useRouter(), xyflowRef = useRef(), { colorScheme } = useMantineColorScheme(), xyflowdata = useMemo(() => overviewGraphToXYFlowData(graph), [graph]), [nodes, setNodes, onNodesChange] = useNodesState(xyflowdata.nodes), [edges, setEdges, onEdgeChanges] = useEdgesState(xyflowdata.edges);
223
+ useUpdateEffect(() => {
224
+ setNodes(
225
+ (nodes2) => xyflowdata.nodes.map((n) => {
226
+ const current = nodes2.find((node) => node.id === n.id);
227
+ return current ? { ...a(current, ["selected", "hidden"]), ...n } : n;
228
+ })
229
+ ), setEdges(xyflowdata.edges);
230
+ }, [xyflowdata.nodes, xyflowdata.edges]);
231
+ const focusedNode = nodes.find((node) => node.selected);
232
+ return useUpdateEffect(() => {
233
+ const xyflow = xyflowRef.current;
234
+ xyflow && (focusedNode ? xyflow.fitView({
235
+ maxZoom: 1,
236
+ padding: fitViewPadding,
237
+ nodes: [focusedNode],
238
+ duration: 450
239
+ }) : xyflow.fitView({
240
+ maxZoom: 1,
241
+ padding: fitViewPadding,
242
+ duration: 800
243
+ }));
244
+ }, [focusedNode?.id ?? null]), /* @__PURE__ */ jsx(
245
+ index,
246
+ {
247
+ colorMode: colorScheme === "auto" ? "system" : colorScheme,
248
+ className: root,
249
+ nodeTypes,
250
+ edgeTypes,
251
+ nodes,
252
+ onNodesChange,
253
+ edges,
254
+ onEdgesChange: onEdgeChanges,
255
+ fitView: !0,
256
+ fitViewOptions: useMemo(() => ({
257
+ minZoom: 0.05,
258
+ maxZoom: 1,
259
+ padding: fitViewPadding,
260
+ includeHiddenNodes: !0
261
+ }), [fitViewPadding]),
262
+ nodesDraggable: !1,
263
+ nodesConnectable: !1,
264
+ nodesFocusable: !0,
265
+ edgesReconnectable: !1,
266
+ edgesFocusable: !1,
267
+ multiSelectionKeyCode: null,
268
+ zoomOnPinch: zoomable,
269
+ zoomOnScroll: !pannable && zoomable,
270
+ zoomOnDoubleClick: !1,
271
+ ...!zoomable && {
272
+ zoomActivationKeyCode: null
273
+ },
274
+ maxZoom: zoomable ? 2 : 1,
275
+ minZoom: zoomable ? 0.01 : 1,
276
+ preventScrolling: zoomable || pannable,
277
+ noDragClassName: "nodrag",
278
+ noPanClassName: "nopan",
279
+ panOnScroll: pannable,
280
+ panOnDrag: pannable,
281
+ ...!pannable && {
282
+ selectionKeyCode: null
283
+ },
284
+ onInit: (instance) => xyflowRef.current = instance,
285
+ onNodeClick: (event, node) => {
286
+ if (node.type === "view") {
287
+ event.stopPropagation(), setNodes((nodes2) => nodes2.map(({ data, ...n }) => ({ ...n, data: { ...data, dimmed: n.id !== node.id } }))), xyflowRef.current?.fitView({
288
+ maxZoom: 10,
289
+ padding: 0,
290
+ nodes: [node],
291
+ duration: 1200
292
+ }), setTimeout(() => {
293
+ xyflowRef.current?.updateNodeData(node.id, { dimmed: !0 });
294
+ }, 400), setTimeout(() => {
295
+ router.navigate({
296
+ to: "/view/$viewId/",
297
+ params: {
298
+ viewId: node.data.viewId
299
+ },
300
+ search: !0
301
+ });
302
+ }, 800);
303
+ return;
304
+ }
305
+ node.selected && (event.stopPropagation(), setNodes((nodes2) => nodes2.map((n) => n.id === node.id ? { ...n, selected: !1 } : n)));
306
+ },
307
+ children: /* @__PURE__ */ jsx(Background, { variant: BackgroundVariant.Dots, size: 4, gap: 50 })
308
+ }
309
+ );
310
+ }
311
+ function OverviewPage() {
312
+ const graph = useOverviewGraph();
313
+ return /* @__PURE__ */ jsx(Box, { pos: "fixed", inset: 0, children: /* @__PURE__ */ jsx(OverviewDiagrams, { graph }) });
314
+ }
315
+ export {
316
+ OverviewPage as default
317
+ };
@@ -5947,31 +5947,31 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
5947
5947
  }
5948
5948
  memo(ResizeControl);
5949
5949
  export {
5950
- Background as B,
5950
+ BaseEdge as B,
5951
5951
  Controls as C,
5952
5952
  EdgeLabelRenderer as E,
5953
5953
  Handle as H,
5954
5954
  Position as P,
5955
5955
  ReactFlowProvider as R,
5956
- useStoreApi as a,
5957
- useNodesData as b,
5958
- useStore as c,
5959
- createWithEqualityFn as d,
5960
- applyNodeChanges as e,
5961
- applyEdgeChanges as f,
5962
- getViewportForBounds as g,
5963
- getNodeDimensions as h,
5964
- getBoundsOfRects as i,
5965
- boxToRect as j,
5966
- useStoreWithEqualityFn as k,
5967
- useOnViewportChange as l,
5968
- index as m,
5969
- useOnSelectionChange as n,
5970
- BackgroundVariant as o,
5971
- BaseEdge as p,
5972
- useNodesState as q,
5973
- useEdgesState as r,
5956
+ useEdgesState as a,
5957
+ Background as b,
5958
+ BackgroundVariant as c,
5959
+ useReactFlow as d,
5960
+ useStoreApi as e,
5961
+ useNodesData as f,
5962
+ useStore as g,
5963
+ createWithEqualityFn as h,
5964
+ index as i,
5965
+ applyNodeChanges as j,
5966
+ applyEdgeChanges as k,
5967
+ getViewportForBounds as l,
5968
+ getNodeDimensions as m,
5969
+ getBoundsOfRects as n,
5970
+ boxToRect as o,
5971
+ useStoreWithEqualityFn as p,
5972
+ useOnViewportChange as q,
5973
+ useOnSelectionChange as r,
5974
5974
  shallow$1 as s,
5975
- useReactFlow as u,
5975
+ useNodesState as u,
5976
5976
  withSelectorExports as w
5977
5977
  };