diff --git a/packages/serverless-workflow-diagram-editor/package.json b/packages/serverless-workflow-diagram-editor/package.json index de855e0..20484ec 100644 --- a/packages/serverless-workflow-diagram-editor/package.json +++ b/packages/serverless-workflow-diagram-editor/package.json @@ -37,6 +37,9 @@ "start": "storybook dev -p 6006 --no-open", "build:storybook": "pnpm clean:storybook && storybook build --output-dir ./dist-storybook" }, + "dependencies": { + "@xyflow/react": "catalog:" + }, "devDependencies": { "@chromatic-com/storybook": "catalog:", "@storybook/addon-a11y": "catalog:", diff --git a/packages/serverless-workflow-diagram-editor/src/diagram-editor/DiagramEditor.tsx b/packages/serverless-workflow-diagram-editor/src/diagram-editor/DiagramEditor.tsx index a896f45..8373227 100644 --- a/packages/serverless-workflow-diagram-editor/src/diagram-editor/DiagramEditor.tsx +++ b/packages/serverless-workflow-diagram-editor/src/diagram-editor/DiagramEditor.tsx @@ -14,33 +14,45 @@ * limitations under the License. */ -import type { CSSProperties } from "react"; +import * as React from "react"; +import { Diagram, DiagramRef } from "../react-flow/diagram/Diagram"; -const clickmeBtnStyle: CSSProperties = { - border: "2px solid blue", - borderRadius: "10px", - fontSize: "large", - fontWeight: "500", - background: "blue", - color: "white", +/** + * DiagramEditor component API + */ +export type DiagramEditorRef = { + doSomething: () => void; // TODO: to be implemented, it is just a placeholder }; export type DiagramEditorProps = { - content: string; isReadOnly: boolean; + locale: string; + ref?: React.Ref; }; -export const DiagramEditor = (props: DiagramEditorProps) => { - //TODO: Implement the actual component this is just a placeholder +export const DiagramEditor = ({ ref }: DiagramEditorProps) => { + // TODO: i18n + // TODO: store, context + // TODO: ErrorBoundary / fallback + + // Refs + const diagramDivRef = React.useRef(null); + const diagramRef = React.useRef(null); + + // Allow imperatively controlling the Editor + React.useImperativeHandle( + ref, + () => ({ + doSomething: () => { + // TODO: to be implemented, it is just a placeholder + }, + }), + [], + ); return ( <> -

Hello from DiagramEditor component!

-

Read-only: {props.isReadOnly ? "true" : "false"}

-

Content: {props.content}

- + ); }; diff --git a/packages/serverless-workflow-diagram-editor/tests/react-flow/Sample.test.tsx b/packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.css similarity index 79% rename from packages/serverless-workflow-diagram-editor/tests/react-flow/Sample.test.tsx rename to packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.css index 1198dbf..15dfc99 100644 --- a/packages/serverless-workflow-diagram-editor/tests/react-flow/Sample.test.tsx +++ b/packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.css @@ -14,10 +14,12 @@ * limitations under the License. */ -import { expect, describe, it } from "vitest"; +.diagram-container { + height: 100%; + position: relative; +} -describe("MyComponent", () => { - it("Just a sample test", () => { - expect(true).toBeTruthy(); - }); -}); +.diagram-background { + --xy-background-pattern-color: #ccc; + background-color: #E5E4E2; +} diff --git a/packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.tsx b/packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.tsx new file mode 100644 index 0000000..068a5f6 --- /dev/null +++ b/packages/serverless-workflow-diagram-editor/src/react-flow/diagram/Diagram.tsx @@ -0,0 +1,107 @@ +/* + * Copyright 2021-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as React from "react"; +import * as RF from "@xyflow/react"; +import "@xyflow/react/dist/style.css"; +import "./Diagram.css"; + +const FIT_VIEW_OPTIONS: RF.FitViewOptions = { maxZoom: 1, minZoom: 0.1, duration: 400 }; + +// TODO: Nodes and Edges are hardcoded for now to generate a renderable basic workflow +// It shall be replaced by the actual implementation based on graph structure +const initialNodes: RF.Node[] = [ + { id: "n1", position: { x: 100, y: 0 }, data: { label: "Node 1" } }, + { id: "n2", position: { x: 100, y: 100 }, data: { label: "Node 2" } }, + { id: "n3", position: { x: 0, y: 200 }, data: { label: "Node 3" } }, + { id: "n4", position: { x: 200, y: 200 }, data: { label: "Node 4" } }, + { id: "n5", position: { x: 100, y: 300 }, data: { label: "Node 5" } }, +]; +const initialEdges: RF.Edge[] = [ + { id: "n1-n2", source: "n1", target: "n2" }, + { id: "n2-n3", source: "n2", target: "n3" }, + { id: "n2-n4", source: "n2", target: "n4" }, + { id: "n3-n5", source: "n3", target: "n5" }, + { id: "n4-n5", source: "n4", target: "n5" }, +]; + +/** + * Diagram component API + */ +export type DiagramRef = { + doSomething: () => void; // TODO: to be implemented, it is just a placeholder +}; + +export type DiagramProps = { + divRef?: React.RefObject; + ref?: React.Ref; +}; + +export const Diagram = ({ divRef, ref }: DiagramProps) => { + const [minimapVisible, setMinimapVisible] = React.useState(false); + + const [nodes, setNodes] = React.useState(initialNodes); + const [edges, setEdges] = React.useState(initialEdges); + + const onNodesChange = React.useCallback( + (changes) => setNodes((nodesSnapshot) => RF.applyNodeChanges(changes, nodesSnapshot)), + [], + ); + const onEdgesChange = React.useCallback( + (changes) => setEdges((edgesSnapshot) => RF.applyEdgeChanges(changes, edgesSnapshot)), + [], + ); + + React.useImperativeHandle( + ref, + () => ({ + doSomething: () => { + // TODO: to be implemented, it is just a placeholder + }, + }), + [], + ); + + return ( +
+ + {minimapVisible && } + + + setMinimapVisible(!minimapVisible)}>M + + + +
+ ); +}; diff --git a/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.stories.ts b/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.stories.ts index 6d7be1b..5576dcc 100644 --- a/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.stories.ts +++ b/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.stories.ts @@ -36,6 +36,6 @@ type Story = StoryObj; export const Component: Story = { args: { isReadOnly: true, - content: "Sample Content", + locale: "en", }, }; diff --git a/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.tsx b/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.tsx index 9e1f3ba..d20084c 100644 --- a/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.tsx +++ b/packages/serverless-workflow-diagram-editor/stories/DiagramEditor.tsx @@ -15,15 +15,15 @@ */ import { - DiagramEditor as SWDiagramEditor, + DiagramEditor as Component, DiagramEditorProps, } from "../src/diagram-editor/DiagramEditor"; /** Primary UI component for user interaction */ export const DiagramEditor = ({ ...props }: DiagramEditorProps) => { return ( - <> - - +
+ +
); }; diff --git a/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.story.test.tsx b/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.story.test.tsx index 2762f20..32bdee7 100644 --- a/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.story.test.tsx +++ b/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.story.test.tsx @@ -17,29 +17,24 @@ import { render, screen } from "@testing-library/react"; import { composeStories } from "@storybook/react-vite"; import * as stories from "../../stories/DiagramEditor.stories"; -import userEvent from "@testing-library/user-event"; import { vi, test, expect, afterEach, describe } from "vitest"; // Composes all stories in the file const { Component } = composeStories(stories); -describe("DiagramEditor component story", () => { +describe("Story - DiagramEditor component", () => { afterEach(() => { vi.restoreAllMocks(); }); - test("Render DiagramEditor Component from story", async () => { - const content = "Sample Content"; + test("Renders react flow Diagram component", async () => { + const locale = "en"; const isReadOnly = true; - const alertMock = vi.spyOn(window, "alert").mockImplementation(() => {}); - render(); + render(); - const user = userEvent.setup(); - const button = screen.getByRole("button", { name: /Click me!/i }); + const reactFlowContainer = screen.getByTestId("diagram-container"); - await user.click(button); - - expect(alertMock).toHaveBeenCalledWith("Hello from Diagram!"); + expect(reactFlowContainer).toBeInTheDocument(); }); }); diff --git a/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.test.tsx b/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.test.tsx index 2319495..5d3c757 100644 --- a/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.test.tsx +++ b/packages/serverless-workflow-diagram-editor/tests/diagram-editor/DiagramEditor.test.tsx @@ -16,7 +16,6 @@ import { render, screen } from "@testing-library/react"; import { DiagramEditor } from "../../src/diagram-editor"; -import userEvent from "@testing-library/user-event"; import { vi, test, expect, afterEach, describe } from "vitest"; describe("DiagramEditor Component", () => { @@ -24,18 +23,14 @@ describe("DiagramEditor Component", () => { vi.restoreAllMocks(); }); - test("Render DiagramEditor Component", async () => { - const content = "Sample Content"; + test("Renders react flow Diagram component", async () => { + const locale = "en"; const isReadOnly = true; - const alertMock = vi.spyOn(window, "alert").mockImplementation(() => {}); - render(); + render(); - const user = userEvent.setup(); - const button = screen.getByRole("button", { name: /Click me!/i }); + const reactFlowContainer = screen.getByTestId("diagram-container"); - await user.click(button); - - expect(alertMock).toHaveBeenCalledWith("Hello from Diagram!"); + expect(reactFlowContainer).toBeInTheDocument(); }); }); diff --git a/packages/serverless-workflow-diagram-editor/tests/react-flow/diagram/Diagram.test.tsx b/packages/serverless-workflow-diagram-editor/tests/react-flow/diagram/Diagram.test.tsx new file mode 100644 index 0000000..9502958 --- /dev/null +++ b/packages/serverless-workflow-diagram-editor/tests/react-flow/diagram/Diagram.test.tsx @@ -0,0 +1,41 @@ +/* + * Copyright 2021-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { render, screen } from "@testing-library/react"; +import { Diagram } from "../../../src/react-flow/diagram/Diagram"; +import { vi, test, expect, afterEach, describe } from "vitest"; + +describe("Diagram Component", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + test("Renders react flow nodes", async () => { + render(); + + const node1 = screen.getByText("Node 1"); + const node2 = screen.getByText("Node 2"); + const node3 = screen.getByText("Node 3"); + const node4 = screen.getByText("Node 4"); + const node5 = screen.getByText("Node 5"); + + expect(node1).toBeInTheDocument(); + expect(node2).toBeInTheDocument(); + expect(node3).toBeInTheDocument(); + expect(node4).toBeInTheDocument(); + expect(node5).toBeInTheDocument(); + }); +}); diff --git a/packages/serverless-workflow-diagram-editor/tests/setupTests.ts b/packages/serverless-workflow-diagram-editor/tests/setupTests.ts index e3fbb04..729d8fb 100644 --- a/packages/serverless-workflow-diagram-editor/tests/setupTests.ts +++ b/packages/serverless-workflow-diagram-editor/tests/setupTests.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { afterEach } from "vitest"; +import { afterEach, vi } from "vitest"; import { cleanup } from "@testing-library/react"; import "@testing-library/jest-dom/vitest"; // This extends vitest's expect with jest-dom matchers @@ -22,3 +22,13 @@ import "@testing-library/jest-dom/vitest"; // This extends vitest's expect with afterEach(() => { cleanup(); }); + +// Mock ResizeObserver +vi.stubGlobal( + "ResizeObserver", + class { + observe() {} + unobserve() {} + disconnect() {} + }, +); diff --git a/packages/serverless-workflow-diagram-editor/tsconfig.json b/packages/serverless-workflow-diagram-editor/tsconfig.json index f74da5e..80b08ef 100644 --- a/packages/serverless-workflow-diagram-editor/tsconfig.json +++ b/packages/serverless-workflow-diagram-editor/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { + "types": ["node", "vite/client"], "baseUrl": ".", "declaration": true, "declarationMap": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5eefd81..7e49358 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ catalogs: default: '@chromatic-com/storybook': specifier: ^5.0.1 - version: 5.0.2 + version: 5.1.1 '@storybook/addon-a11y': specifier: ^10.2.19 version: 10.3.3 @@ -44,10 +44,13 @@ catalogs: version: 19.2.3 '@vitest/coverage-v8': specifier: ^4.1.0 - version: 4.1.1 + version: 4.1.2 '@vitest/ui': specifier: ^4.1.0 - version: 4.1.1 + version: 4.1.2 + '@xyflow/react': + specifier: ^12.10.1 + version: 12.10.1 husky: specifier: ^9.1.7 version: 9.1.7 @@ -62,7 +65,7 @@ catalogs: version: 0.41.0 oxlint: specifier: ^1.56.0 - version: 1.56.0 + version: 1.57.0 react: specifier: ^19.2.4 version: 19.2.4 @@ -89,7 +92,7 @@ catalogs: version: 6.1.1 vitest: specifier: ^4.1.0 - version: 4.1.1 + version: 4.1.2 importers: @@ -112,10 +115,14 @@ importers: version: 5.9.3 packages/serverless-workflow-diagram-editor: + dependencies: + '@xyflow/react': + specifier: 'catalog:' + version: 12.10.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) devDependencies: '@chromatic-com/storybook': specifier: 'catalog:' - version: 5.0.2(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + version: 5.1.1(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) '@storybook/addon-a11y': specifier: 'catalog:' version: 10.3.3(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) @@ -124,7 +131,7 @@ importers: version: 10.3.3(@types/react@19.2.14)(esbuild@0.27.4)(rollup@4.60.0)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.3.3(@vitest/runner@4.1.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vitest@4.1.1) + version: 10.3.3(@vitest/runner@4.1.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vitest@4.1.2) '@storybook/react-vite': specifier: 'catalog:' version: 10.3.3(esbuild@0.27.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) @@ -151,10 +158,10 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.1(vitest@4.1.1) + version: 4.1.2(vitest@4.1.2) '@vitest/ui': specifier: 'catalog:' - version: 4.1.1(vitest@4.1.1) + version: 4.1.2(vitest@4.1.2) jsdom: specifier: 'catalog:' version: 25.0.1 @@ -163,7 +170,7 @@ importers: version: 0.41.0 oxlint: specifier: 'catalog:' - version: 1.56.0 + version: 1.57.0 react: specifier: 'catalog:' version: 19.2.4 @@ -184,7 +191,7 @@ importers: version: 6.1.1(typescript@5.9.3)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) vitest: specifier: 'catalog:' - version: 4.1.1(@types/node@25.5.0)(@vitest/ui@4.1.1)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(@vitest/ui@4.1.2)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) packages: @@ -269,8 +276,8 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@chromatic-com/storybook@5.0.2': - resolution: {integrity: sha512-uLd5gyvcz8q83GI0rYWjml45ryO3ZJwZLretLEZvWFJ3UlFk5C5Km9cwRcKZgZp0F3zYwbb8nEe6PJdgA1eKxg==} + '@chromatic-com/storybook@5.1.1': + resolution: {integrity: sha512-BPoAXHM71XgeCK2u0jKr9i8apeQMm/Z9IWGyndA2FMijfQG9m8ox45DdWh/pxFkK5ClhGgirv5QwMhFIeHmThg==} engines: {node: '>=20.0.0', yarn: '>=1.22.18'} peerDependencies: storybook: ^0.0.0-0 || ^10.1.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 @@ -771,124 +778,124 @@ packages: cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.56.0': - resolution: {integrity: sha512-IyfYPthZyiSKwAv/dLjeO18SaK8MxLI9Yss2JrRDyweQAkuL3LhEy7pwIwI7uA3KQc1Vdn20kdmj3q0oUIQL6A==} + '@oxlint/binding-android-arm-eabi@1.57.0': + resolution: {integrity: sha512-C7EiyfAJG4B70496eV543nKiq5cH0o/xIh/ufbjQz3SIvHhlDDsyn+mRFh+aW8KskTyUpyH2LGWL8p2oN6bl1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.56.0': - resolution: {integrity: sha512-Ga5zYrzH6vc/VFxhn6MmyUnYEfy9vRpwTIks99mY3j6Nz30yYpIkWryI0QKPCgvGUtDSXVLEaMum5nA+WrNOSg==} + '@oxlint/binding-android-arm64@1.57.0': + resolution: {integrity: sha512-9i80AresjZ/FZf5xK8tKFbhQnijD4s1eOZw6/FHUwD59HEZbVLRc2C88ADYJfLZrF5XofWDiRX/Ja9KefCLy7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.56.0': - resolution: {integrity: sha512-ogmbdJysnw/D4bDcpf1sPLpFThZ48lYp4aKYm10Z/6Nh1SON6NtnNhTNOlhEY296tDFItsZUz+2tgcSYqh8Eyw==} + '@oxlint/binding-darwin-arm64@1.57.0': + resolution: {integrity: sha512-0eUfhRz5L2yKa9I8k3qpyl37XK3oBS5BvrgdVIx599WZK63P8sMbg+0s4IuxmIiZuBK68Ek+Z+gcKgeYf0otsg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.56.0': - resolution: {integrity: sha512-x8QE1h+RAtQ2g+3KPsP6Fk/tdz6zJQUv5c7fTrJxXV3GHOo+Ry5p/PsogU4U+iUZg0rj6hS+E4xi+mnwwlDCWQ==} + '@oxlint/binding-darwin-x64@1.57.0': + resolution: {integrity: sha512-UvrSuzBaYOue+QMAcuDITe0k/Vhj6KZGjfnI6x+NkxBTke/VoM7ZisaxgNY0LWuBkTnd1OmeQfEQdQ48fRjkQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.56.0': - resolution: {integrity: sha512-6G+WMZvwJpMvY7my+/SHEjb7BTk/PFbePqLpmVmUJRIsJMy/UlyYqjpuh0RCgYYkPLcnXm1rUM04kbTk8yS1Yg==} + '@oxlint/binding-freebsd-x64@1.57.0': + resolution: {integrity: sha512-wtQq0dCoiw4bUwlsNVDJJ3pxJA218fOezpgtLKrbQqUtQJcM9yP8z+I9fu14aHg0uyAxIY+99toL6uBa2r7nxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.56.0': - resolution: {integrity: sha512-YYHBsk/sl7fYwQOok+6W5lBPeUEvisznV/HZD2IfZmF3Bns6cPC3Z0vCtSEOaAWTjYWN3jVsdu55jMxKlsdlhg==} + '@oxlint/binding-linux-arm-gnueabihf@1.57.0': + resolution: {integrity: sha512-qxFWl2BBBFcT4djKa+OtMdnLgoHEJXpqjyGwz8OhW35ImoCwR5qtAGqApNYce5260FQqoAHW8S8eZTjiX67Tsg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.56.0': - resolution: {integrity: sha512-+AZK8rOUr78y8WT6XkDb04IbMRqauNV+vgT6f8ZLOH8wnpQ9i7Nol0XLxAu+Cq7Sb+J9wC0j6Km5hG8rj47/yQ==} + '@oxlint/binding-linux-arm-musleabihf@1.57.0': + resolution: {integrity: sha512-SQoIsBU7J0bDW15/f0/RvxHfY3Y0+eB/caKBQtNFbuerTiA6JCYx9P1MrrFTwY2dTm/lMgTSgskvCEYk2AtG/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.56.0': - resolution: {integrity: sha512-urse2SnugwJRojUkGSSeH2LPMaje5Q50yQtvtL9HFckiyeqXzoFwOAZqD5TR29R2lq7UHidfFDM9EGcchcbb8A==} + '@oxlint/binding-linux-arm64-gnu@1.57.0': + resolution: {integrity: sha512-jqxYd1W6WMeozsCmqe9Rzbu3SRrGTyGDAipRlRggetyYbUksJqJKvUNTQtZR/KFoJPb+grnSm5SHhdWrywv3RQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.56.0': - resolution: {integrity: sha512-rkTZkBfJ4TYLjansjSzL6mgZOdN5IvUnSq3oNJSLwBcNvy3dlgQtpHPrRxrCEbbcp7oQ6If0tkNaqfOsphYZ9g==} + '@oxlint/binding-linux-arm64-musl@1.57.0': + resolution: {integrity: sha512-i66WyEPVEvq9bxRUCJ/MP5EBfnTDN3nhwEdFZFTO5MmLLvzngfWEG3NSdXQzTT3vk5B9i6C2XSIYBh+aG6uqyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.56.0': - resolution: {integrity: sha512-uqL1kMH3u69/e1CH2EJhP3CP28jw2ExLsku4o8RVAZ7fySo9zOyI2fy9pVlTAp4voBLVgzndXi3SgtdyCTa2aA==} + '@oxlint/binding-linux-ppc64-gnu@1.57.0': + resolution: {integrity: sha512-oMZDCwz4NobclZU3pH+V1/upVlJZiZvne4jQP+zhJwt+lmio4XXr4qG47CehvrW1Lx2YZiIHuxM2D4YpkG3KVA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.56.0': - resolution: {integrity: sha512-j0CcMBOgV6KsRaBdsebIeiy7hCjEvq2KdEsiULf2LZqAq0v1M1lWjelhCV57LxsqaIGChXFuFJ0RiFrSRHPhSg==} + '@oxlint/binding-linux-riscv64-gnu@1.57.0': + resolution: {integrity: sha512-uoBnjJ3MMEBbfnWC1jSFr7/nSCkcQYa72NYoNtLl1imshDnWSolYCjzb8LVCwYCCfLJXD+0gBLD7fyC14c0+0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.56.0': - resolution: {integrity: sha512-7VDOiL8cDG3DQ/CY3yKjbV1c4YPvc4vH8qW09Vv+5ukq3l/Kcyr6XGCd5NvxUmxqDb2vjMpM+eW/4JrEEsUetA==} + '@oxlint/binding-linux-riscv64-musl@1.57.0': + resolution: {integrity: sha512-BdrwD7haPZ8a9KrZhKJRSj6jwCor+Z8tHFZ3PT89Y3Jq5v3LfMfEePeAmD0LOTWpiTmzSzdmyw9ijneapiVHKQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.56.0': - resolution: {integrity: sha512-JGRpX0M+ikD3WpwJ7vKcHKV6Kg0dT52BW2Eu2BupXotYeqGXBrbY+QPkAyKO6MNgKozyTNaRh3r7g+VWgyAQYQ==} + '@oxlint/binding-linux-s390x-gnu@1.57.0': + resolution: {integrity: sha512-BNs+7ZNsRstVg2tpNxAXfMX/Iv5oZh204dVyb8Z37+/gCh+yZqNTlg6YwCLIMPSk5wLWIGOaQjT0GUOahKYImw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.56.0': - resolution: {integrity: sha512-dNaICPvtmuxFP/VbqdofrLqdS3bM/AKJN3LMJD52si44ea7Be1cBk6NpfIahaysG9Uo+L98QKddU9CD5L8UHnQ==} + '@oxlint/binding-linux-x64-gnu@1.57.0': + resolution: {integrity: sha512-AghS18w+XcENcAX0+BQGLiqjpqpaxKJa4cWWP0OWNLacs27vHBxu7TYkv9LUSGe5w8lOJHeMxcYfZNOAPqw2bg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.56.0': - resolution: {integrity: sha512-pF1vOtM+GuXmbklM1hV8WMsn6tCNPvkUzklj/Ej98JhlanbmA2RB1BILgOpwSuCTRTIYx2MXssmEyQQ90QF5aA==} + '@oxlint/binding-linux-x64-musl@1.57.0': + resolution: {integrity: sha512-E/FV3GB8phu/Rpkhz5T96hAiJlGzn91qX5yj5gU754P5cmVGXY1Jw/VSjDSlZBCY3VHjsVLdzgdkJaomEmcNOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.56.0': - resolution: {integrity: sha512-bp8NQ4RE6fDIFLa4bdBiOA+TAvkNkg+rslR+AvvjlLTYXLy9/uKAYLQudaQouWihLD/hgkrXIKKzXi5IXOewwg==} + '@oxlint/binding-openharmony-arm64@1.57.0': + resolution: {integrity: sha512-xvZ2yZt0nUVfU14iuGv3V25jpr9pov5N0Wr28RXnHFxHCRxNDMtYPHV61gGLhN9IlXM96gI4pyYpLSJC5ClLCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.56.0': - resolution: {integrity: sha512-PxT4OJDfMOQBzo3OlzFb9gkoSD+n8qSBxyVq2wQSZIHFQYGEqIRTo9M0ZStvZm5fdhMqaVYpOnJvH2hUMEDk/g==} + '@oxlint/binding-win32-arm64-msvc@1.57.0': + resolution: {integrity: sha512-Z4D8Pd0AyHBKeazhdIXeUUy5sIS3Mo0veOlzlDECg6PhRRKgEsBJCCV1n+keUZtQ04OP+i7+itS3kOykUyNhDg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.56.0': - resolution: {integrity: sha512-PTRy6sIEPqy2x8PTP1baBNReN/BNEFmde0L+mYeHmjXE1Vlcc9+I5nsqENsB2yAm5wLkzPoTNCMY/7AnabT4/A==} + '@oxlint/binding-win32-ia32-msvc@1.57.0': + resolution: {integrity: sha512-StOZ9nFMVKvevicbQfql6Pouu9pgbeQnu60Fvhz2S6yfMaii+wnueLnqQ5I1JPgNF0Syew4voBlAaHD13wH6tw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.56.0': - resolution: {integrity: sha512-ZHa0clocjLmIDr+1LwoWtxRcoYniAvERotvwKUYKhH41NVfl0Y4LNbyQkwMZzwDvKklKGvGZ5+DAG58/Ik47tQ==} + '@oxlint/binding-win32-x64-msvc@1.57.0': + resolution: {integrity: sha512-6PuxhYgth8TuW0+ABPOIkGdBYw+qYGxgIdXPHSVpiCDm+hqTTWCmC739St1Xni0DJBt8HnSHTG67i1y6gr8qrA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1180,6 +1187,24 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -1206,11 +1231,11 @@ packages: '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - '@vitest/coverage-v8@4.1.1': - resolution: {integrity: sha512-nZ4RWwGCoGOQRMmU/Q9wlUY540RVRxJZ9lxFsFfy0QV7Zmo5VVBhB6Sl9Xa0KIp2iIs3zWfPlo9LcY1iqbpzCw==} + '@vitest/coverage-v8@4.1.2': + resolution: {integrity: sha512-sPK//PHO+kAkScb8XITeB1bf7fsk85Km7+rt4eeuRR3VS1/crD47cmV5wicisJmjNdfeokTZwjMk4Mj2d58Mgg==} peerDependencies: - '@vitest/browser': 4.1.1 - vitest: 4.1.1 + '@vitest/browser': 4.1.2 + vitest: 4.1.2 peerDependenciesMeta: '@vitest/browser': optional: true @@ -1218,11 +1243,11 @@ packages: '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - '@vitest/expect@4.1.1': - resolution: {integrity: sha512-xAV0fqBTk44Rn6SjJReEQkHP3RrqbJo6JQ4zZ7/uVOiJZRarBtblzrOfFIZeYUrukp2YD6snZG6IBqhOoHTm+A==} + '@vitest/expect@4.1.2': + resolution: {integrity: sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==} - '@vitest/mocker@4.1.1': - resolution: {integrity: sha512-h3BOylsfsCLPeceuCPAAJ+BvNwSENgJa4hXoXu4im0bs9Lyp4URc4JYK4pWLZ4pG/UQn7AT92K6IByi6rE6g3A==} + '@vitest/mocker@4.1.2': + resolution: {integrity: sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1235,31 +1260,40 @@ packages: '@vitest/pretty-format@3.2.4': resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/pretty-format@4.1.1': - resolution: {integrity: sha512-GM+TEQN5WhOygr1lp7skeVjdLPqqWMHsfzXrcHAqZJi/lIVh63H0kaRCY8MDhNWikx19zBUK8ceaLB7X5AH9NQ==} + '@vitest/pretty-format@4.1.2': + resolution: {integrity: sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==} - '@vitest/runner@4.1.1': - resolution: {integrity: sha512-f7+FPy75vN91QGWsITueq0gedwUZy1fLtHOCMeQpjs8jTekAHeKP80zfDEnhrleviLHzVSDXIWuCIOFn3D3f8A==} + '@vitest/runner@4.1.2': + resolution: {integrity: sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==} - '@vitest/snapshot@4.1.1': - resolution: {integrity: sha512-kMVSgcegWV2FibXEx9p9WIKgje58lcTbXgnJixfcg15iK8nzCXhmalL0ZLtTWLW9PH1+1NEDShiFFedB3tEgWg==} + '@vitest/snapshot@4.1.2': + resolution: {integrity: sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==} '@vitest/spy@3.2.4': resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - '@vitest/spy@4.1.1': - resolution: {integrity: sha512-6Ti/KT5OVaiupdIZEuZN7l3CZcR0cxnxt70Z0//3CtwgObwA6jZhmVBA3yrXSVN3gmwjgd7oDNLlsXz526gpRA==} + '@vitest/spy@4.1.2': + resolution: {integrity: sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==} - '@vitest/ui@4.1.1': - resolution: {integrity: sha512-k0qNVLmCISxoGWvdhOeynlZVrfjx7Xjp95kIptN0fZYyONCgVcKIPn53MpFZ7S+fO6YdKNhgIfl0nu92Q0CCOg==} + '@vitest/ui@4.1.2': + resolution: {integrity: sha512-/irhyeAcKS2u6Zokagf9tqZJ0t8S6kMZq4ZG9BHZv7I+fkRrYfQX4w7geYeC2r6obThz39PDxvXQzZX+qXqGeg==} peerDependencies: - vitest: 4.1.1 + vitest: 4.1.2 '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@vitest/utils@4.1.1': - resolution: {integrity: sha512-cNxAlaB3sHoCdL6pj6yyUXv9Gry1NHNg0kFTXdvSIZXLHsqKH7chiWOkwJ5s5+d/oMwcoG9T0bKU38JZWKusrQ==} + '@vitest/utils@4.1.2': + resolution: {integrity: sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==} + + '@xyflow/react@12.10.1': + resolution: {integrity: sha512-5eSWtIK/+rkldOuFbOOz44CRgQRjtS9v5nufk77DV+XBnfCGL9HAQ8PG00o2ZYKqkEU/Ak6wrKC95Tu+2zuK3Q==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@xyflow/system@0.0.75': + resolution: {integrity: sha512-iXs+AGFLi8w/VlAoc/iSxk+CxfT6o64Uw/k0CKASOPqjqz6E0rb5jFZgJtXGZCpfQI6OQpu5EnumP5fGxQheaQ==} acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} @@ -1324,8 +1358,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - brace-expansion@5.0.4: - resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} engines: {node: 18 || 20 || >=22} browserslist@4.28.1: @@ -1368,6 +1402,9 @@ packages: '@chromatic-com/playwright': optional: true + classcat@5.0.5: + resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -1400,6 +1437,44 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -1454,8 +1529,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.321: - resolution: {integrity: sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==} + electron-to-chromium@1.5.325: + resolution: {integrity: sha512-PwfIw7WQSt3xX7yOf5OE/unLzsK9CaN2f/FvV3WjPR1Knoc1T9vePRVV4W1EM301JzzysK51K7FNKcusCr0zYA==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -1543,8 +1618,8 @@ packages: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} - flatted@3.4.0: - resolution: {integrity: sha512-kC6Bb+ooptOIvWj5B63EQWkF0FEnNjV2ZNkLMLZRDDduIiWeFF4iKnslwhiWxjAdbg4NzTNo6h0qLuvFrcx+Sw==} + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} @@ -1802,8 +1877,8 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - oxlint@1.56.0: - resolution: {integrity: sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g==} + oxlint@1.57.0: + resolution: {integrity: sha512-DGFsuBX5MFZX9yiDdtKjTrYPq45CZ8Fft6qCltJITYZxfwYjVdGf/6wycGYTACloauwIPxUnYhBVeZbHvleGhw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2199,18 +2274,18 @@ packages: yaml: optional: true - vitest@4.1.1: - resolution: {integrity: sha512-yF+o4POL41rpAzj5KVILUxm1GCjKnELvaqmU9TLLUbMfDzuN0UpUR9uaDs+mCtjPe+uYPksXDRLQGGPvj1cTmA==} + vitest@4.1.2: + resolution: {integrity: sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.1 - '@vitest/browser-preview': 4.1.1 - '@vitest/browser-webdriverio': 4.1.1 - '@vitest/ui': 4.1.1 + '@vitest/browser-playwright': 4.1.2 + '@vitest/browser-preview': 4.1.2 + '@vitest/browser-webdriverio': 4.1.2 + '@vitest/ui': 4.1.2 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2298,6 +2373,21 @@ packages: engines: {node: '>= 14.6'} hasBin: true + zustand@4.5.7: + resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + snapshots: '@adobe/css-tools@4.4.4': {} @@ -2414,7 +2504,7 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@chromatic-com/storybook@5.0.2(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))': + '@chromatic-com/storybook@5.1.1(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))': dependencies: '@neoconfetti/react': 1.0.0 chromatic: 13.3.5 @@ -2694,61 +2784,61 @@ snapshots: '@oxfmt/binding-win32-x64-msvc@0.41.0': optional: true - '@oxlint/binding-android-arm-eabi@1.56.0': + '@oxlint/binding-android-arm-eabi@1.57.0': optional: true - '@oxlint/binding-android-arm64@1.56.0': + '@oxlint/binding-android-arm64@1.57.0': optional: true - '@oxlint/binding-darwin-arm64@1.56.0': + '@oxlint/binding-darwin-arm64@1.57.0': optional: true - '@oxlint/binding-darwin-x64@1.56.0': + '@oxlint/binding-darwin-x64@1.57.0': optional: true - '@oxlint/binding-freebsd-x64@1.56.0': + '@oxlint/binding-freebsd-x64@1.57.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.56.0': + '@oxlint/binding-linux-arm-gnueabihf@1.57.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.56.0': + '@oxlint/binding-linux-arm-musleabihf@1.57.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.56.0': + '@oxlint/binding-linux-arm64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.56.0': + '@oxlint/binding-linux-arm64-musl@1.57.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.56.0': + '@oxlint/binding-linux-ppc64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.56.0': + '@oxlint/binding-linux-riscv64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.56.0': + '@oxlint/binding-linux-riscv64-musl@1.57.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.56.0': + '@oxlint/binding-linux-s390x-gnu@1.57.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.56.0': + '@oxlint/binding-linux-x64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-x64-musl@1.56.0': + '@oxlint/binding-linux-x64-musl@1.57.0': optional: true - '@oxlint/binding-openharmony-arm64@1.56.0': + '@oxlint/binding-openharmony-arm64@1.57.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.56.0': + '@oxlint/binding-win32-arm64-msvc@1.57.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.56.0': + '@oxlint/binding-win32-ia32-msvc@1.57.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.56.0': + '@oxlint/binding-win32-x64-msvc@1.57.0': optional: true '@polka/url@1.0.0-next.29': {} @@ -2861,14 +2951,14 @@ snapshots: - vite - webpack - '@storybook/addon-vitest@10.3.3(@vitest/runner@4.1.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vitest@4.1.1)': + '@storybook/addon-vitest@10.3.3(@vitest/runner@4.1.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vitest@4.1.2)': dependencies: '@storybook/global': 5.0.0 '@storybook/icons': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) storybook: 10.3.3(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) optionalDependencies: - '@vitest/runner': 4.1.1 - vitest: 4.1.1(@types/node@25.5.0)(@vitest/ui@4.1.1)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) + '@vitest/runner': 4.1.2 + vitest: 4.1.2(@types/node@25.5.0)(@vitest/ui@4.1.2)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) transitivePeerDependencies: - react - react-dom @@ -3004,6 +3094,27 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/d3-color@3.1.3': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + '@types/deep-eql@4.0.2': {} '@types/doctrine@0.0.9': {} @@ -3026,10 +3137,10 @@ snapshots: '@types/resolve@1.20.6': {} - '@vitest/coverage-v8@4.1.1(vitest@4.1.1)': + '@vitest/coverage-v8@4.1.2(vitest@4.1.2)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.1 + '@vitest/utils': 4.1.2 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -3038,7 +3149,7 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.1(@types/node@25.5.0)(@vitest/ui@4.1.1)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) + vitest: 4.1.2(@types/node@25.5.0)(@vitest/ui@4.1.2)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) '@vitest/expect@3.2.4': dependencies: @@ -3048,18 +3159,18 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/expect@4.1.1': + '@vitest/expect@4.1.2': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.1 - '@vitest/utils': 4.1.1 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.1(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.2(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.1 + '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: @@ -3069,19 +3180,19 @@ snapshots: dependencies: tinyrainbow: 2.0.0 - '@vitest/pretty-format@4.1.1': + '@vitest/pretty-format@4.1.2': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.1': + '@vitest/runner@4.1.2': dependencies: - '@vitest/utils': 4.1.1 + '@vitest/utils': 4.1.2 pathe: 2.0.3 - '@vitest/snapshot@4.1.1': + '@vitest/snapshot@4.1.2': dependencies: - '@vitest/pretty-format': 4.1.1 - '@vitest/utils': 4.1.1 + '@vitest/pretty-format': 4.1.2 + '@vitest/utils': 4.1.2 magic-string: 0.30.21 pathe: 2.0.3 @@ -3089,18 +3200,18 @@ snapshots: dependencies: tinyspy: 4.0.4 - '@vitest/spy@4.1.1': {} + '@vitest/spy@4.1.2': {} - '@vitest/ui@4.1.1(vitest@4.1.1)': + '@vitest/ui@4.1.2(vitest@4.1.2)': dependencies: - '@vitest/utils': 4.1.1 + '@vitest/utils': 4.1.2 fflate: 0.8.2 - flatted: 3.4.0 + flatted: 3.4.2 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vitest: 4.1.1(@types/node@25.5.0)(@vitest/ui@4.1.1)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) + vitest: 4.1.2(@types/node@25.5.0)(@vitest/ui@4.1.2)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) '@vitest/utils@3.2.4': dependencies: @@ -3108,12 +3219,35 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - '@vitest/utils@4.1.1': + '@vitest/utils@4.1.2': dependencies: - '@vitest/pretty-format': 4.1.1 + '@vitest/pretty-format': 4.1.2 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@xyflow/react@12.10.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@xyflow/system': 0.0.75 + classcat: 5.0.5 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + zustand: 4.5.7(@types/react@19.2.14)(react@19.2.4) + transitivePeerDependencies: + - '@types/react' + - immer + + '@xyflow/system@0.0.75': + dependencies: + '@types/d3-drag': 3.0.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + acorn@8.16.0: {} agent-base@7.1.4: {} @@ -3156,7 +3290,7 @@ snapshots: baseline-browser-mapping@2.10.10: {} - brace-expansion@5.0.4: + brace-expansion@5.0.5: dependencies: balanced-match: 4.0.4 @@ -3164,7 +3298,7 @@ snapshots: dependencies: baseline-browser-mapping: 2.10.10 caniuse-lite: 1.0.30001781 - electron-to-chromium: 1.5.321 + electron-to-chromium: 1.5.325 node-releases: 2.0.36 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -3193,6 +3327,8 @@ snapshots: chromatic@13.3.5: {} + classcat@5.0.5: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -3221,6 +3357,42 @@ snapshots: csstype@3.2.3: {} + d3-color@3.1.0: {} + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-ease@3.0.1: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-selection@3.0.0: {} + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -3261,7 +3433,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.321: {} + electron-to-chromium@1.5.325: {} emoji-regex@10.6.0: {} @@ -3370,7 +3542,7 @@ snapshots: filesize@10.1.6: {} - flatted@3.4.0: {} + flatted@3.4.2: {} form-data@4.0.5: dependencies: @@ -3601,7 +3773,7 @@ snapshots: minimatch@10.2.4: dependencies: - brace-expansion: 5.0.4 + brace-expansion: 5.0.5 minimist@1.2.8: {} @@ -3654,27 +3826,27 @@ snapshots: '@oxfmt/binding-win32-ia32-msvc': 0.41.0 '@oxfmt/binding-win32-x64-msvc': 0.41.0 - oxlint@1.56.0: + oxlint@1.57.0: optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.56.0 - '@oxlint/binding-android-arm64': 1.56.0 - '@oxlint/binding-darwin-arm64': 1.56.0 - '@oxlint/binding-darwin-x64': 1.56.0 - '@oxlint/binding-freebsd-x64': 1.56.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.56.0 - '@oxlint/binding-linux-arm-musleabihf': 1.56.0 - '@oxlint/binding-linux-arm64-gnu': 1.56.0 - '@oxlint/binding-linux-arm64-musl': 1.56.0 - '@oxlint/binding-linux-ppc64-gnu': 1.56.0 - '@oxlint/binding-linux-riscv64-gnu': 1.56.0 - '@oxlint/binding-linux-riscv64-musl': 1.56.0 - '@oxlint/binding-linux-s390x-gnu': 1.56.0 - '@oxlint/binding-linux-x64-gnu': 1.56.0 - '@oxlint/binding-linux-x64-musl': 1.56.0 - '@oxlint/binding-openharmony-arm64': 1.56.0 - '@oxlint/binding-win32-arm64-msvc': 1.56.0 - '@oxlint/binding-win32-ia32-msvc': 1.56.0 - '@oxlint/binding-win32-x64-msvc': 1.56.0 + '@oxlint/binding-android-arm-eabi': 1.57.0 + '@oxlint/binding-android-arm64': 1.57.0 + '@oxlint/binding-darwin-arm64': 1.57.0 + '@oxlint/binding-darwin-x64': 1.57.0 + '@oxlint/binding-freebsd-x64': 1.57.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.57.0 + '@oxlint/binding-linux-arm-musleabihf': 1.57.0 + '@oxlint/binding-linux-arm64-gnu': 1.57.0 + '@oxlint/binding-linux-arm64-musl': 1.57.0 + '@oxlint/binding-linux-ppc64-gnu': 1.57.0 + '@oxlint/binding-linux-riscv64-gnu': 1.57.0 + '@oxlint/binding-linux-riscv64-musl': 1.57.0 + '@oxlint/binding-linux-s390x-gnu': 1.57.0 + '@oxlint/binding-linux-x64-gnu': 1.57.0 + '@oxlint/binding-linux-x64-musl': 1.57.0 + '@oxlint/binding-openharmony-arm64': 1.57.0 + '@oxlint/binding-win32-arm64-msvc': 1.57.0 + '@oxlint/binding-win32-ia32-msvc': 1.57.0 + '@oxlint/binding-win32-x64-msvc': 1.57.0 package-json-from-dist@1.0.1: {} @@ -4031,15 +4203,15 @@ snapshots: fsevents: 2.3.3 yaml: 2.8.3 - vitest@4.1.1(@types/node@25.5.0)(@vitest/ui@4.1.1)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)): + vitest@4.1.2(@types/node@25.5.0)(@vitest/ui@4.1.2)(jsdom@25.0.1)(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.1 - '@vitest/mocker': 4.1.1(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.1 - '@vitest/runner': 4.1.1 - '@vitest/snapshot': 4.1.1 - '@vitest/spy': 4.1.1 - '@vitest/utils': 4.1.1 + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@6.4.1(@types/node@25.5.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -4055,7 +4227,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.5.0 - '@vitest/ui': 4.1.1(vitest@4.1.1) + '@vitest/ui': 4.1.2(vitest@4.1.2) jsdom: 25.0.1 transitivePeerDependencies: - msw @@ -4103,3 +4275,10 @@ snapshots: yallist@3.1.1: {} yaml@2.8.3: {} + + zustand@4.5.7(@types/react@19.2.14)(react@19.2.4): + dependencies: + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.14 + react: 19.2.4 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7994462..d2b98e9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -15,6 +15,7 @@ catalog: "@types/react-dom": ^19.2.3 "@vitest/coverage-v8": ^4.1.0 "@vitest/ui": ^4.1.0 + "@xyflow/react": ^12.10.1 husky: ^9.1.7 jsdom: ^25.0.0 lint-staged: ^16.4.0