@multiplatform.one/node-graph 7.7.6 → 7.8.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 (119) hide show
  1. package/dist/cjs/model/history.cjs +8 -4
  2. package/dist/cjs/model/history.native.js +8 -4
  3. package/dist/cjs/model/history.native.js.map +1 -1
  4. package/dist/cjs/native/GraphToolbar.cjs +21 -7
  5. package/dist/cjs/native/GraphToolbar.native.js +21 -7
  6. package/dist/cjs/native/GraphToolbar.native.js.map +1 -1
  7. package/dist/cjs/react-flow/useGraphController.cjs +9 -17
  8. package/dist/cjs/react-flow/useGraphController.native.js +10 -18
  9. package/dist/cjs/react-flow/useGraphController.native.js.map +1 -1
  10. package/dist/esm/NodeGraph.native.js.map +1 -1
  11. package/dist/esm/bench/frameSampler.native.js.map +1 -1
  12. package/dist/esm/bench/generateGraph.native.js.map +1 -1
  13. package/dist/esm/diagnostics/GraphDiagnostics.native.js.map +1 -1
  14. package/dist/esm/diagnostics/LiveGraphDiagnostics.native.js.map +1 -1
  15. package/dist/esm/diagnostics/fromWire.native.js.map +1 -1
  16. package/dist/esm/diagnostics/lastError.native.js.map +1 -1
  17. package/dist/esm/diagnostics/types.native.js.map +1 -1
  18. package/dist/esm/diagnostics/useGraphDiagnostics.native.js.map +1 -1
  19. package/dist/esm/dom/GraphDomLayout.native.js.map +1 -1
  20. package/dist/esm/dom/boot.native.js.map +1 -1
  21. package/dist/esm/dom/wire.native.js.map +1 -1
  22. package/dist/esm/edges/GraphEdge.native.js.map +1 -1
  23. package/dist/esm/edges/edgeKinds.native.js.map +1 -1
  24. package/dist/esm/edges/edgeStyle.native.js.map +1 -1
  25. package/dist/esm/index.native.js.map +1 -1
  26. package/dist/esm/interaction/lassoIntercept.native.js.map +1 -1
  27. package/dist/esm/interaction/legalTargets.native.js.map +1 -1
  28. package/dist/esm/interaction/snapAlignment.native.js.map +1 -1
  29. package/dist/esm/interaction/snapChanges.native.js.map +1 -1
  30. package/dist/esm/interaction/spatialHash.native.js.map +1 -1
  31. package/dist/esm/interaction/useLassoSelect.native.js.map +1 -1
  32. package/dist/esm/knobs/KnobEnvelopeProvider.native.js.map +1 -1
  33. package/dist/esm/knobs/envelope.native.js.map +1 -1
  34. package/dist/esm/knobs/graphKnobs.native.js.map +1 -1
  35. package/dist/esm/knobs/useKnobEnvelope.native.js.map +1 -1
  36. package/dist/esm/layout/dagre.native.js.map +1 -1
  37. package/dist/esm/layout/layout.native.js.map +1 -1
  38. package/dist/esm/layout/runner.native.js.map +1 -1
  39. package/dist/esm/layout/structuredCloneShim.native.js.map +1 -1
  40. package/dist/esm/layout/types.native.js.map +1 -1
  41. package/dist/esm/layout/worker.entry.native.js.map +1 -1
  42. package/dist/esm/layout/worker.generated.native.js.map +1 -1
  43. package/dist/esm/model/commands.native.js.map +1 -1
  44. package/dist/esm/model/connect.native.js.map +1 -1
  45. package/dist/esm/model/document.native.js.map +1 -1
  46. package/dist/esm/model/history.mjs +8 -4
  47. package/dist/esm/model/history.mjs.map +1 -1
  48. package/dist/esm/model/history.native.js +8 -4
  49. package/dist/esm/model/history.native.js.map +1 -1
  50. package/dist/esm/model/index.native.js.map +1 -1
  51. package/dist/esm/model/schema.native.js.map +1 -1
  52. package/dist/esm/model/select.native.js.map +1 -1
  53. package/dist/esm/model/serialize.native.js.map +1 -1
  54. package/dist/esm/native/DomOnlyStory.native.js.map +1 -1
  55. package/dist/esm/native/GraphToolbar.mjs +18 -4
  56. package/dist/esm/native/GraphToolbar.mjs.map +1 -1
  57. package/dist/esm/native/GraphToolbar.native.js +18 -4
  58. package/dist/esm/native/GraphToolbar.native.js.map +1 -1
  59. package/dist/esm/native/domEntryRegistry.native.js.map +1 -1
  60. package/dist/esm/native/graphChildren.native.js.map +1 -1
  61. package/dist/esm/nodes/GraphNode.native.js.map +1 -1
  62. package/dist/esm/nodes/GraphPort.native.js.map +1 -1
  63. package/dist/esm/nodes/handleGeometry.native.js.map +1 -1
  64. package/dist/esm/nodes/lod.native.js.map +1 -1
  65. package/dist/esm/nodes/nodeMeasure.native.js.map +1 -1
  66. package/dist/esm/nodes/overviewNode.native.js.map +1 -1
  67. package/dist/esm/react-flow/ConnectionPuck.native.js.map +1 -1
  68. package/dist/esm/react-flow/GraphActions.native.js.map +1 -1
  69. package/dist/esm/react-flow/GraphCommandBridge.native.js.map +1 -1
  70. package/dist/esm/react-flow/GraphNodeHost.native.js.map +1 -1
  71. package/dist/esm/react-flow/GraphPaintProbe.native.js.map +1 -1
  72. package/dist/esm/react-flow/GraphZoomVar.native.js.map +1 -1
  73. package/dist/esm/react-flow/LassoOverlay.native.js.map +1 -1
  74. package/dist/esm/react-flow/NodeGraphWeb.native.js.map +1 -1
  75. package/dist/esm/react-flow/SnapGuides.native.js.map +1 -1
  76. package/dist/esm/react-flow/demoControlBody.native.js.map +1 -1
  77. package/dist/esm/react-flow/demoNodeBody.native.js.map +1 -1
  78. package/dist/esm/react-flow/fixtures.native.js.map +1 -1
  79. package/dist/esm/react-flow/flowAdapter.native.js.map +1 -1
  80. package/dist/esm/react-flow/graphHandle.native.js.map +1 -1
  81. package/dist/esm/react-flow/nodeCensus.native.js.map +1 -1
  82. package/dist/esm/react-flow/useGraphController.mjs +9 -17
  83. package/dist/esm/react-flow/useGraphController.mjs.map +1 -1
  84. package/dist/esm/react-flow/useGraphController.native.js +10 -18
  85. package/dist/esm/react-flow/useGraphController.native.js.map +1 -1
  86. package/dist/esm/react-flow/xy.native.js.map +1 -1
  87. package/dist/esm/theme/GraphFaces.native.js.map +1 -1
  88. package/dist/esm/theme/GraphVarsStyle.native.js.map +1 -1
  89. package/dist/esm/theme/faces.generated.native.js.map +1 -1
  90. package/dist/esm/theme/faces.native.js.map +1 -1
  91. package/dist/esm/theme/graphVars.native.js.map +1 -1
  92. package/dist/jsx/model/history.mjs +8 -4
  93. package/dist/jsx/model/history.mjs.map +1 -1
  94. package/dist/jsx/model/history.native.js +8 -4
  95. package/dist/jsx/model/history.native.js.map +1 -1
  96. package/dist/jsx/native/GraphToolbar.mjs +18 -4
  97. package/dist/jsx/native/GraphToolbar.mjs.map +1 -1
  98. package/dist/jsx/native/GraphToolbar.native.js +21 -7
  99. package/dist/jsx/native/GraphToolbar.native.js.map +1 -1
  100. package/dist/jsx/react-flow/useGraphController.mjs +9 -17
  101. package/dist/jsx/react-flow/useGraphController.mjs.map +1 -1
  102. package/dist/jsx/react-flow/useGraphController.native.js +10 -18
  103. package/dist/jsx/react-flow/useGraphController.native.js.map +1 -1
  104. package/package.json +7 -6
  105. package/src/NodeGraph.historyBridge.spec.tsx +87 -0
  106. package/src/bench/Perf200.stories.tsx +43 -11
  107. package/src/interaction/Lasso.stories.tsx +22 -7
  108. package/src/layout/AutoLayout.stories.spec.tsx +26 -0
  109. package/src/layout/AutoLayout.stories.tsx +22 -12
  110. package/src/model/history.spec.ts +19 -0
  111. package/src/model/history.ts +17 -6
  112. package/src/native/GraphToolbar.spec.tsx +53 -0
  113. package/src/native/GraphToolbar.tsx +18 -14
  114. package/src/react-flow/useGraphController.ts +14 -12
  115. package/types/model/history.d.ts +3 -2
  116. package/types/model/history.d.ts.map +1 -1
  117. package/types/native/GraphToolbar.d.ts +4 -10
  118. package/types/native/GraphToolbar.d.ts.map +1 -1
  119. package/types/react-flow/useGraphController.d.ts.map +1 -1
@@ -48,6 +48,7 @@
48
48
 
49
49
  import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
50
50
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
51
+ import { pressTargetStyle } from "@multiplatform.one/theme";
51
52
  import { Button, SizableText, XStack, YStack } from "tamagui";
52
53
  import type { FrameStats } from "../bench/frameSampler";
53
54
  import { gestureEndMark, gestureStartMark } from "../bench/frameSampler";
@@ -73,6 +74,7 @@ const meta: Meta<typeof NodeGraph> = {
73
74
  parameters: {
74
75
  status: { type: "beta" },
75
76
  layout: "fullscreen",
77
+ nativeGallery: { scroll: false },
76
78
  docs: {
77
79
  description: {
78
80
  component:
@@ -253,20 +255,36 @@ function Bench({ variant }: { readonly variant: "tamagui" | "control" }) {
253
255
  }, [culling, layoutRunner, start, stop, variant]);
254
256
 
255
257
  return (
256
- <YStack width="100%" height={700} padding="$3" gap="$2">
258
+ <YStack
259
+ width="100%"
260
+ height={hasDomRealm ? 700 : undefined}
261
+ flex={hasDomRealm ? undefined : 1}
262
+ minHeight={0}
263
+ padding="$3"
264
+ gap="$2"
265
+ >
257
266
  <SizableText size="$2" opacity={0.7}>
258
- 200 nodes, ~400 edges, one seed. Start, then bracket each pan with Gesture start / Gesture
259
- end, then Stop. The readout's p95 and mean are over the BRACKETED frames only; the idle
260
- frames between pans are counted, not mixed in. A run where nothing moved is DISCARDED by the
261
- reporter and says so, rather than printing plausible numbers.
267
+ {hasDomRealm
268
+ ? "200 nodes, ~400 edges, one seed. Start, then bracket each pan with Gesture start / Gesture end, then Stop. The readout's p95 and mean are over the BRACKETED frames only; the idle frames between pans are counted, not mixed in. A run where nothing moved is DISCARDED by the reporter and says so, rather than printing plausible numbers."
269
+ : "Start, mark each pan with Gesture start / end, then Stop to read the result."}
262
270
  </SizableText>
263
271
  {/* OUTSIDE the canvas. These were children until milestone 6, which is why
264
272
  no device ever had a Start button. */}
265
273
  <XStack gap="$2" alignItems="center" flexWrap="wrap">
266
- <Button size="$2" disabled={sampling} onPress={() => start("run")}>
274
+ <Button
275
+ size="$2"
276
+ {...(hasDomRealm ? {} : pressTargetStyle())}
277
+ disabled={sampling}
278
+ onPress={() => start("run")}
279
+ >
267
280
  Start
268
281
  </Button>
269
- <Button size="$2" disabled={!sampling} onPress={() => stop("run")}>
282
+ <Button
283
+ size="$2"
284
+ {...(hasDomRealm ? {} : pressTargetStyle())}
285
+ disabled={!sampling}
286
+ onPress={() => stop("run")}
287
+ >
270
288
  Stop
271
289
  </Button>
272
290
  {/*
@@ -275,10 +293,19 @@ function Bench({ variant }: { readonly variant: "tamagui" | "control" }) {
275
293
  scripted pan and the next — which is exactly the caveat the m6 iOS
276
294
  number shipped with.
277
295
  */}
278
- <Button size="$2" disabled={!sampling} onPress={markGesture}>
296
+ <Button
297
+ size="$2"
298
+ {...(hasDomRealm ? {} : pressTargetStyle())}
299
+ disabled={!sampling}
300
+ onPress={markGesture}
301
+ >
279
302
  {inGesture ? "Gesture end" : "Gesture start"}
280
303
  </Button>
281
- <Button size="$2" onPress={() => graph.current?.relayout()}>
304
+ <Button
305
+ size="$2"
306
+ {...(hasDomRealm ? {} : pressTargetStyle())}
307
+ onPress={() => graph.current?.relayout()}
308
+ >
282
309
  Tidy
283
310
  </Button>
284
311
  {/*
@@ -286,7 +313,12 @@ function Bench({ variant }: { readonly variant: "tamagui" | "control" }) {
286
313
  now — but because a culling change inside a sampled window silently
287
314
  changes what the window measured.
288
315
  */}
289
- <Button size="$2" disabled={sampling} onPress={() => setCulling((on) => !on)}>
316
+ <Button
317
+ size="$2"
318
+ {...(hasDomRealm ? {} : pressTargetStyle())}
319
+ disabled={sampling}
320
+ onPress={() => setCulling((on) => !on)}
321
+ >
290
322
  {culling ? "Culling ON" : "Culling OFF"}
291
323
  </Button>
292
324
  </XStack>
@@ -306,7 +338,7 @@ function Bench({ variant }: { readonly variant: "tamagui" | "control" }) {
306
338
  <SizableText size="$2" fontFamily="$mono">
307
339
  {sampling ? "sampling…" : summarize(report)}
308
340
  </SizableText>
309
- <YStack flex={1}>
341
+ <YStack flex={1} minHeight={0}>
310
342
  {/*
311
343
  NO `key`. `onlyRenderVisibleElements` is an ordinary React Flow prop
312
344
  and flips in place; keying the canvas on it threw the canvas away and
@@ -63,6 +63,7 @@ const meta: Meta<typeof NodeGraph> = {
63
63
  parameters: {
64
64
  status: { type: "beta" },
65
65
  layout: "fullscreen",
66
+ nativeGallery: { scroll: false },
66
67
  docs: {
67
68
  description: {
68
69
  component:
@@ -95,7 +96,14 @@ function ToolbarModeStory() {
95
96
  }, []);
96
97
 
97
98
  return (
98
- <YStack width="100%" height={560} padding="$3" gap="$3">
99
+ <YStack
100
+ width="100%"
101
+ height={hasDomRealm ? 560 : undefined}
102
+ flex={hasDomRealm ? undefined : 1}
103
+ minHeight={0}
104
+ padding="$3"
105
+ gap="$3"
106
+ >
99
107
  <XStack alignItems="center" gap="$3" flexWrap="wrap">
100
108
  <GraphToolbar mode={mode} onModeChange={setMode} />
101
109
  <SizableText fontFamily="$mono" size="$2">
@@ -104,7 +112,7 @@ function ToolbarModeStory() {
104
112
  }`}
105
113
  </SizableText>
106
114
  </XStack>
107
- <YStack flex={1}>
115
+ <YStack flex={1} minHeight={0}>
108
116
  <NodeGraph
109
117
  schema={schema}
110
118
  defaultDocument={demoDocumentLarge(12)}
@@ -156,7 +164,14 @@ function LongPressStory() {
156
164
  }, []);
157
165
 
158
166
  return (
159
- <YStack width="100%" height={560} padding="$3" gap="$3">
167
+ <YStack
168
+ width="100%"
169
+ height={hasDomRealm ? 560 : undefined}
170
+ flex={hasDomRealm ? undefined : 1}
171
+ minHeight={0}
172
+ padding="$3"
173
+ gap="$3"
174
+ >
160
175
  <XStack alignItems="center" gap="$3" flexWrap="wrap">
161
176
  <GraphToolbar mode={mode} onModeChange={setMode} />
162
177
  <SizableText fontFamily="$mono" size="$2">
@@ -167,11 +182,11 @@ function LongPressStory() {
167
182
  {`selected: ${selected.length ? selected.join(", ") : "none"}`}
168
183
  </SizableText>
169
184
  <SizableText size="$2" opacity={0.7}>
170
- Hold for 350 ms without moving more than 10 px, then drag. The interceptor takes the move
171
- stream away from d3-zoom inside the canvas's own realm, so the marquee draws and the graph
172
- underneath does not pan. A second finger cancels: a pinch is not a lasso.
185
+ {hasDomRealm
186
+ ? "Hold for 350 ms without moving more than 10 px, then drag. The interceptor takes the move stream away from d3-zoom inside the canvas's own realm, so the marquee draws and the graph underneath does not pan. A second finger cancels: a pinch is not a lasso."
187
+ : "Hold briefly, then drag to select. A second finger cancels the selection gesture."}
173
188
  </SizableText>
174
- <YStack flex={1}>
189
+ <YStack flex={1} minHeight={0}>
175
190
  <NodeGraph
176
191
  schema={schema}
177
192
  defaultDocument={demoDocumentLarge(12)}
@@ -0,0 +1,26 @@
1
+ import type { ComponentType } from "react";
2
+ import { cleanup, fireEvent, screen } from "@testing-library/react";
3
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
4
+ import { afterEach, expect, it, vi } from "vitest";
5
+ import { Undo } from "./AutoLayout.stories";
6
+
7
+ vi.mock("../native/DomOnlyStory", () => ({ hasDomRealm: false }));
8
+ vi.mock("../NodeGraph", () => ({
9
+ NodeGraph: ({ interactionMode }: { interactionMode: string }) => (
10
+ <div data-testid="canvas" data-mode={interactionMode} />
11
+ ),
12
+ }));
13
+
14
+ afterEach(cleanup);
15
+
16
+ it("keeps useful native actions, omits the DOM-only stamp, and wires mode to the canvas", () => {
17
+ const Story = Undo.render as ComponentType;
18
+ renderWithProviders(<Story />);
19
+ expect(screen.queryByRole("button", { name: "Stamp positions" })).toBeNull();
20
+ expect(screen.queryByText("no stamp yet")).toBeNull();
21
+ for (const name of ["Tidy the graph", "Undo", "Redo"])
22
+ expect(screen.getByRole("button", { name })).toBeTruthy();
23
+ expect(screen.getByTestId("canvas").getAttribute("data-mode")).toBe("pan");
24
+ fireEvent.click(screen.getByRole("button", { name: "Select mode" }));
25
+ expect(screen.getByTestId("canvas").getAttribute("data-mode")).toBe("select");
26
+ });
@@ -37,8 +37,10 @@
37
37
 
38
38
  import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
39
39
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
40
- import { Button, SizableText, XStack, YStack } from "tamagui";
40
+ import { Button } from "@multiplatform.one/forms";
41
+ import { SizableText, XStack, YStack } from "tamagui";
41
42
  import type { GraphEventWire } from "../dom/wire";
43
+ import type { GraphInteractionMode } from "../interaction/useLassoSelect";
42
44
  import type { BuiltinEdgeData } from "../edges/edgeKinds";
43
45
  import type { GraphDocument } from "../model/index";
44
46
  import { GraphToolbar } from "../native/GraphToolbar";
@@ -59,6 +61,7 @@ const meta: Meta<typeof NodeGraph> = {
59
61
  parameters: {
60
62
  status: { type: "beta" },
61
63
  layout: "fullscreen",
64
+ nativeGallery: { scroll: false },
62
65
  docs: {
63
66
  description: {
64
67
  component:
@@ -154,6 +157,7 @@ function AutoLayoutPage({
154
157
  readonly fitView?: boolean;
155
158
  }) {
156
159
  const graph = useRef<NodeGraphHandle>(null);
160
+ const [mode, setMode] = useState<GraphInteractionMode>("pan");
157
161
  const [reading, setReading] = useState<LayoutReading | null>(null);
158
162
  const [pending, setPending] = useState(false);
159
163
  const [checksum, setChecksum] = useState<string | null>(null);
@@ -237,29 +241,34 @@ function AutoLayoutPage({
237
241
  const wrongRunner = reading?.runner === "inline" && typeof globalThis.Worker === "function";
238
242
 
239
243
  return (
240
- <YStack width="100%" height={640} padding="$3" gap="$2">
244
+ <YStack
245
+ width="100%"
246
+ height={hasDomRealm ? 640 : undefined}
247
+ flex={hasDomRealm ? undefined : 1}
248
+ minHeight={0}
249
+ padding="$3"
250
+ gap="$2"
251
+ >
241
252
  <SizableText size="$2" opacity={0.7}>
242
- Press Tidy. The readout is the assertion: `worker-blob` on web AND on device — the relayout
243
- runs inside the canvas, and on native the canvas is a WebView, which has a real Worker.
244
- `inline` on a platform that has Worker is a failed run, not a slow one.
253
+ {hasDomRealm
254
+ ? "Press Tidy. The readout is the assertion: `worker-blob` on web AND on device — the relayout runs inside the canvas, and on native the canvas is a WebView, which has a real Worker. `inline` on a platform that has Worker is a failed run, not a slow one."
255
+ : "Tidy rearranges the graph. Undo restores its previous layout."}
245
256
  </SizableText>
246
257
  {/* OUTSIDE the canvas. On native a child of <NodeGraph> is dropped, which
247
258
  is why this page had no Tidy button on any device until milestone 6. */}
248
259
  <XStack gap="$3" alignItems="center" flexWrap="wrap">
249
260
  <GraphToolbar
250
- mode="pan"
251
- onModeChange={() => undefined}
261
+ mode={mode}
262
+ onModeChange={setMode}
252
263
  onFitView={() => graph.current?.fitView()}
253
264
  onTidy={tidy}
254
265
  onUndo={() => graph.current?.undo()}
255
266
  onRedo={() => graph.current?.redo()}
256
267
  busy={pending}
257
268
  />
258
- {showChecksum ? (
269
+ {showChecksum && hasDomRealm ? (
259
270
  <>
260
- <Button size="$2" onPress={stamp}>
261
- Stamp positions
262
- </Button>
271
+ <Button onPress={stamp}>Stamp positions</Button>
263
272
  <SizableText size="$2" opacity={0.7}>
264
273
  {checksum === null ? "no stamp yet" : `checksum ${checksum}`}
265
274
  </SizableText>
@@ -297,11 +306,12 @@ function AutoLayoutPage({
297
306
  </SizableText>
298
307
  ) : null}
299
308
  </XStack>
300
- <YStack flex={1}>
309
+ <YStack flex={1} minHeight={0}>
301
310
  <NodeGraph
302
311
  schema={schema}
303
312
  defaultDocument={document}
304
313
  fitView={fitView}
314
+ interactionMode={mode}
305
315
  graphRef={graph}
306
316
  onGraphEvent={onGraphEvent}
307
317
  >
@@ -47,6 +47,25 @@ const relayout: GraphCommand<Nodes, Edges> = {
47
47
  positions: { a: { x: 0, y: 0 }, b: { x: 0, y: 60 } },
48
48
  };
49
49
 
50
+ it("reports the applied history command without notifying for an empty stack", () => {
51
+ const history = createHistory<Nodes, Edges>();
52
+ const applied: Array<[Doc, GraphCommand<Nodes, Edges>]> = [];
53
+ const observe = (next: Doc, command: GraphCommand<Nodes, Edges>) => applied.push([next, command]);
54
+ expect(history.undo(doc, observe)).toBe(doc);
55
+ expect(history.redo(doc, observe)).toBe(doc);
56
+ expect(applied).toEqual([]);
57
+ const changed = history.commit(doc, drag(6));
58
+ const undone = history.undo(changed, observe);
59
+ expect(undone).toEqual(doc);
60
+ expect(history.redo(undone, observe)).toEqual(changed);
61
+ expect(applied).toEqual([
62
+ [doc, drag(-6)],
63
+ [changed, drag(6)],
64
+ ]);
65
+ history.redo(changed, observe);
66
+ expect(applied).toHaveLength(2);
67
+ });
68
+
50
69
  describe("a 30-step drag", () => {
51
70
  // 20 ms a step, so the gesture runs 580 ms — LONGER than the 400 ms default.
52
71
  // That is deliberate: the window measures the gap since the last movement,
@@ -33,8 +33,15 @@ export interface HistoryOptions {
33
33
  export interface GraphHistory<N extends NodeKindDefs, E extends EdgeKindDefs> {
34
34
  /** Apply the command, record it, return the new document. */
35
35
  readonly commit: (doc: GraphDocument<N, E>, command: GraphCommand<N, E>) => GraphDocument<N, E>;
36
- readonly undo: (doc: GraphDocument<N, E>) => GraphDocument<N, E>;
37
- readonly redo: (doc: GraphDocument<N, E>) => GraphDocument<N, E>;
36
+ /** Notify command transports with the journal entry that produced the document. */
37
+ readonly undo: (
38
+ doc: GraphDocument<N, E>,
39
+ onApplied?: (next: GraphDocument<N, E>, command: GraphCommand<N, E>) => void,
40
+ ) => GraphDocument<N, E>;
41
+ readonly redo: (
42
+ doc: GraphDocument<N, E>,
43
+ onApplied?: (next: GraphDocument<N, E>, command: GraphCommand<N, E>) => void,
44
+ ) => GraphDocument<N, E>;
38
45
  readonly canUndo: () => boolean;
39
46
  readonly canRedo: () => boolean;
40
47
  readonly depth: () => number;
@@ -127,18 +134,22 @@ export function createHistory<N extends NodeKindDefs, E extends EdgeKindDefs>(
127
134
  return next;
128
135
  },
129
136
 
130
- undo(doc) {
137
+ undo(doc, onApplied) {
131
138
  const entry = past.pop();
132
139
  if (!entry) return doc;
133
140
  future.push(entry);
134
- return applyCommand(doc, entry.undo);
141
+ const next = applyCommand(doc, entry.undo);
142
+ onApplied?.(next, entry.undo);
143
+ return next;
135
144
  },
136
145
 
137
- redo(doc) {
146
+ redo(doc, onApplied) {
138
147
  const entry = future.pop();
139
148
  if (!entry) return doc;
140
149
  past.push(entry);
141
- return applyCommand(doc, entry.redo);
150
+ const next = applyCommand(doc, entry.redo);
151
+ onApplied?.(next, entry.redo);
152
+ return next;
142
153
  },
143
154
 
144
155
  canUndo: () => past.length > 0,
@@ -0,0 +1,53 @@
1
+ import { cleanup, fireEvent, screen } from "@testing-library/react";
2
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
3
+ import { afterEach, describe, expect, it, vi } from "vitest";
4
+ import { GraphToolbar } from "./GraphToolbar";
5
+
6
+ afterEach(cleanup);
7
+
8
+ describe("GraphToolbar actions", () => {
9
+ it("keeps every action independently reachable with the selected mode exposed", () => {
10
+ const onModeChange = vi.fn();
11
+ const callbacks = { onFitView: vi.fn(), onTidy: vi.fn(), onUndo: vi.fn(), onRedo: vi.fn() };
12
+ renderWithProviders(<GraphToolbar mode="pan" onModeChange={onModeChange} {...callbacks} />);
13
+ expect(screen.getByRole("button", { name: "Pan mode" }).getAttribute("aria-pressed")).toBe(
14
+ "true",
15
+ );
16
+ fireEvent.click(screen.getByRole("button", { name: "Select mode" }));
17
+ expect(onModeChange).toHaveBeenCalledExactlyOnceWith("select");
18
+ for (const [name, callback] of [
19
+ ["Fit the graph to the view", callbacks.onFitView],
20
+ ["Tidy the graph", callbacks.onTidy],
21
+ ["Undo", callbacks.onUndo],
22
+ ["Redo", callbacks.onRedo],
23
+ ] as const) {
24
+ fireEvent.click(screen.getByRole("button", { name }));
25
+ expect(callback).toHaveBeenCalledOnce();
26
+ }
27
+ });
28
+
29
+ it("keeps busy/history-disabled actions inert and optional actions absent", () => {
30
+ const onModeChange = vi.fn();
31
+ const onTidy = vi.fn();
32
+ const onUndo = vi.fn();
33
+ renderWithProviders(
34
+ <GraphToolbar
35
+ mode="select"
36
+ onModeChange={onModeChange}
37
+ onTidy={onTidy}
38
+ onUndo={onUndo}
39
+ busy
40
+ canUndo={false}
41
+ />,
42
+ );
43
+ for (const name of ["Tidy the graph", "Undo"]) {
44
+ const button = screen.getByRole("button", { name });
45
+ expect(button.getAttribute("aria-disabled")).toBe("true");
46
+ fireEvent.click(button);
47
+ }
48
+ expect(onTidy).not.toHaveBeenCalled();
49
+ expect(onUndo).not.toHaveBeenCalled();
50
+ expect(screen.queryByRole("button", { name: "Redo" })).toBeNull();
51
+ expect(screen.queryByRole("button", { name: "Fit the graph to the view" })).toBeNull();
52
+ });
53
+ });
@@ -23,17 +23,11 @@
23
23
  * that fights the platform's own double-tap zoom is worse than a visible
24
24
  * control. It renders only when a handler is given, so a read-only canvas
25
25
  * does not grow a dead button.
26
- * - selection is shown by DROPPING `chromeless` on the active button and
27
- * spreading the `textWeight` fragment onto it, never by a colour. Both are
28
- * Tamagui's own, so the active stop follows whatever theme the envelope
29
- * resolved and there is no literal here to drift from it. (`themeInverse`
30
- * would have been the obvious choice and is not a prop in Tamagui 2.7.6;
31
- * `ThemeProps` carries no `inverse` either, so the pressed state is
32
- * fill-and-weight rather than a theme flip.)
26
+ * - selection is exposed explicitly to the shared house Button, which owns
27
+ * selected paint and the control recipes on both platforms.
33
28
  *
34
- * Every style comes from a whole `knobProps.*` fragment spread (AGENTS.md).
35
- * Built from `tamagui` rather than `@multiplatform.one/components`, which is an
36
- * optional peer of this package.
29
+ * The toolbar surface resolves its own layout fragments. Its controls use the
30
+ * canonical forms Button so radius, type and interaction states keep one owner.
37
31
  *
38
32
  * A11y is expressed with `role` / `aria-*` and not with the React Native
39
33
  * `accessibility*` names, matching the house count (113 `aria-label` against 15
@@ -45,8 +39,9 @@
45
39
  * correct on both platforms rather than a web-only concession.
46
40
  */
47
41
 
48
- import { useResolvedKnobs } from "@multiplatform.one/theme";
49
- import { Button, XStack } from "tamagui";
42
+ import { pressTargetStyle, useResolvedKnobs } from "@multiplatform.one/theme";
43
+ import { Button } from "@multiplatform.one/forms";
44
+ import { XStack, isWeb } from "tamagui";
50
45
  import type { GraphInteractionMode } from "../interaction/useLassoSelect";
51
46
 
52
47
  export interface GraphToolbarProps {
@@ -104,6 +99,10 @@ export function GraphToolbar({
104
99
  {...knobProps.gap}
105
100
  {...knobProps.panelPadding}
106
101
  {...knobProps.elevatedSurface}
102
+ flexWrap="wrap"
103
+ maxWidth="100%"
104
+ minWidth={0}
105
+ flexShrink={1}
107
106
  >
108
107
  {modes.map((candidate) => {
109
108
  const active = candidate === mode;
@@ -111,12 +110,13 @@ export function GraphToolbar({
111
110
  <Button
112
111
  key={candidate}
113
112
  aria-label={`${modeLabels[candidate]} mode`}
114
- aria-pressed={active}
113
+ {...(isWeb ? { "aria-pressed": active } : { "aria-selected": active })}
114
+ selected={active}
115
115
  chromeless={!active}
116
116
  disabled={disabled}
117
117
  onPress={() => onModeChange(candidate)}
118
118
  size={knobProps.sizeToken}
119
- {...(active ? knobProps.textWeight : {})}
119
+ {...pressTargetStyle()}
120
120
  >
121
121
  {modeLabels[candidate]}
122
122
  </Button>
@@ -129,6 +129,7 @@ export function GraphToolbar({
129
129
  disabled={disabled}
130
130
  onPress={onFitView}
131
131
  size={knobProps.sizeToken}
132
+ {...pressTargetStyle()}
132
133
  >
133
134
  Fit
134
135
  </Button>
@@ -140,6 +141,7 @@ export function GraphToolbar({
140
141
  disabled={disabled || busy}
141
142
  onPress={onTidy}
142
143
  size={knobProps.sizeToken}
144
+ {...pressTargetStyle()}
143
145
  >
144
146
  {busy ? "Tidying…" : "Tidy"}
145
147
  </Button>
@@ -151,6 +153,7 @@ export function GraphToolbar({
151
153
  disabled={disabled || !canUndo}
152
154
  onPress={onUndo}
153
155
  size={knobProps.sizeToken}
156
+ {...pressTargetStyle()}
154
157
  >
155
158
  Undo
156
159
  </Button>
@@ -162,6 +165,7 @@ export function GraphToolbar({
162
165
  disabled={disabled || !canRedo}
163
166
  onPress={onRedo}
164
167
  size={knobProps.sizeToken}
168
+ {...pressTargetStyle()}
165
169
  >
166
170
  Redo
167
171
  </Button>
@@ -410,23 +410,25 @@ export function useGraphController<N extends NodeKindDefs, E extends EdgeKindDef
410
410
  [coarsePointer, commit, readOnly, size],
411
411
  );
412
412
 
413
+ const publishHistoryChange = useCallback(
414
+ (next: GraphDocument<N, E>, command: GraphCommand<N, E>) => {
415
+ if (next === documentRef.current) return;
416
+ if (!controlled) setOwnDocument(next);
417
+ documentRef.current = next;
418
+ onDocumentChange?.(next, command);
419
+ },
420
+ [controlled, onDocumentChange],
421
+ );
422
+
413
423
  const undo = useCallback(() => {
414
- const next = history.undo(documentRef.current);
424
+ history.undo(documentRef.current, publishHistoryChange);
415
425
  setHistoryVersion((version) => version + 1);
416
- if (next === documentRef.current) return;
417
- if (!controlled) setOwnDocument(next);
418
- documentRef.current = next;
419
- onDocumentChange?.(next, { t: "batch", commands: [] });
420
- }, [controlled, history, onDocumentChange]);
426
+ }, [history, publishHistoryChange]);
421
427
 
422
428
  const redo = useCallback(() => {
423
- const next = history.redo(documentRef.current);
429
+ history.redo(documentRef.current, publishHistoryChange);
424
430
  setHistoryVersion((version) => version + 1);
425
- if (next === documentRef.current) return;
426
- if (!controlled) setOwnDocument(next);
427
- documentRef.current = next;
428
- onDocumentChange?.(next, { t: "batch", commands: [] });
429
- }, [controlled, history, onDocumentChange]);
431
+ }, [history, publishHistoryChange]);
430
432
 
431
433
  return {
432
434
  document,
@@ -28,8 +28,9 @@ export interface HistoryOptions {
28
28
  export interface GraphHistory<N extends NodeKindDefs, E extends EdgeKindDefs> {
29
29
  /** Apply the command, record it, return the new document. */
30
30
  readonly commit: (doc: GraphDocument<N, E>, command: GraphCommand<N, E>) => GraphDocument<N, E>;
31
- readonly undo: (doc: GraphDocument<N, E>) => GraphDocument<N, E>;
32
- readonly redo: (doc: GraphDocument<N, E>) => GraphDocument<N, E>;
31
+ /** Notify command transports with the journal entry that produced the document. */
32
+ readonly undo: (doc: GraphDocument<N, E>, onApplied?: (next: GraphDocument<N, E>, command: GraphCommand<N, E>) => void) => GraphDocument<N, E>;
33
+ readonly redo: (doc: GraphDocument<N, E>, onApplied?: (next: GraphDocument<N, E>, command: GraphCommand<N, E>) => void) => GraphDocument<N, E>;
33
34
  readonly canUndo: () => boolean;
34
35
  readonly canRedo: () => boolean;
35
36
  readonly depth: () => number;
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/model/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY;IAC1E,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY;IAC1E,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAuBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY,EAC1E,OAAO,GAAE,cAAmB,GAC3B,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAqFpB"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/model/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY;IAC1E,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY;IAC1E,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,CACb,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,KACzE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CACb,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,KACzE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAuBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,YAAY,EAC1E,OAAO,GAAE,cAAmB,GAC3B,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAyFpB"}
@@ -23,17 +23,11 @@
23
23
  * that fights the platform's own double-tap zoom is worse than a visible
24
24
  * control. It renders only when a handler is given, so a read-only canvas
25
25
  * does not grow a dead button.
26
- * - selection is shown by DROPPING `chromeless` on the active button and
27
- * spreading the `textWeight` fragment onto it, never by a colour. Both are
28
- * Tamagui's own, so the active stop follows whatever theme the envelope
29
- * resolved and there is no literal here to drift from it. (`themeInverse`
30
- * would have been the obvious choice and is not a prop in Tamagui 2.7.6;
31
- * `ThemeProps` carries no `inverse` either, so the pressed state is
32
- * fill-and-weight rather than a theme flip.)
26
+ * - selection is exposed explicitly to the shared house Button, which owns
27
+ * selected paint and the control recipes on both platforms.
33
28
  *
34
- * Every style comes from a whole `knobProps.*` fragment spread (AGENTS.md).
35
- * Built from `tamagui` rather than `@multiplatform.one/components`, which is an
36
- * optional peer of this package.
29
+ * The toolbar surface resolves its own layout fragments. Its controls use the
30
+ * canonical forms Button so radius, type and interaction states keep one owner.
37
31
  *
38
32
  * A11y is expressed with `role` / `aria-*` and not with the React Native
39
33
  * `accessibility*` names, matching the house count (113 `aria-label` against 15
@@ -1 +1 @@
1
- {"version":3,"file":"GraphToolbar.d.ts","sourceRoot":"","sources":["../../src/native/GraphToolbar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5D,wDAAwD;IACxD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AASD,wBAAgB,YAAY,CAAC,EAC3B,IAAY,EACZ,OAAc,EACd,OAAc,EACd,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,iBAAiB,2CA0EnB"}
1
+ {"version":3,"file":"GraphToolbar.d.ts","sourceRoot":"","sources":["../../src/native/GraphToolbar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5D,wDAAwD;IACxD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AASD,wBAAgB,YAAY,CAAC,EAC3B,IAAY,EACZ,OAAc,EACd,OAAc,EACd,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,iBAAiB,2CAmFnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useGraphController.d.ts","sourceRoot":"","sources":["../../src/react-flow/useGraphController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useGraphController.d.ts","sourceRoot":"","sources":["../../src/react-flow/useGraphController.ts"],"names":[],"mappings":"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"}