diff --git a/examples/react/package.json b/examples/react/package.json index c60e088d..981f2054 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -38,7 +38,7 @@ "cypress": "13.6.6", "cypress-real-events": "1.12.0", "start-server-and-test": "^2.0.2", - "typescript": "5.2.2", + "typescript": "5.4.5", "vite": "4.5.0" } } diff --git a/examples/react/src/App/routes.ts b/examples/react/src/App/routes.ts index cb184b4a..2256ce52 100644 --- a/examples/react/src/App/routes.ts +++ b/examples/react/src/App/routes.ts @@ -1,5 +1,6 @@ import Basic from '../examples/Basic'; import Backgrounds from '../examples/Backgrounds'; +import BrokenNodes from '../examples/BrokenNodes'; import ColorMode from '../examples/ColorMode'; import ClickDistance from '../examples/ClickDistance'; import ControlledUncontrolled from '../examples/ControlledUncontrolled'; @@ -77,6 +78,11 @@ const routes: IRoute[] = [ path: 'backgrounds', component: Backgrounds, }, + { + name: 'Broken Nodes', + path: 'broken-nodes', + component: BrokenNodes, + }, { name: 'Color Mode', path: 'color-mode', diff --git a/examples/react/src/examples/Basic/index.tsx b/examples/react/src/examples/Basic/index.tsx index 62232a35..5754fd62 100644 --- a/examples/react/src/examples/Basic/index.tsx +++ b/examples/react/src/examples/Basic/index.tsx @@ -56,8 +56,18 @@ const initialEdges: Edge[] = [ const defaultEdgeOptions = {}; const BasicFlow = () => { - const { addNodes, setNodes, getNodes, setEdges, getEdges, deleteElements, updateNodeData, toObject, setViewport } = - useReactFlow(); + const { + addNodes, + setNodes, + getNodes, + setEdges, + getEdges, + deleteElements, + updateNodeData, + toObject, + setViewport, + fitView, + } = useReactFlow(); const updatePos = () => { setNodes((nodes) => @@ -104,6 +114,7 @@ const BasicFlow = () => { ]); setEdges([{ id: 'a-b', source: 'a', target: 'b' }]); + fitView(); }; const onUpdateNode = () => { @@ -117,6 +128,7 @@ const BasicFlow = () => { position: { x: Math.random() * 300, y: Math.random() * 300 }, className: 'light', }); + fitView(); }; return ( @@ -134,6 +146,9 @@ const BasicFlow = () => { minZoom={0.2} maxZoom={4} fitView + fitViewOptions={{ + padding: { top: '100px', left: '0%', right: '10%', bottom: 0.1 }, + }} defaultEdgeOptions={defaultEdgeOptions} selectNodesOnDrag={false} elevateEdgesOnSelect diff --git a/examples/react/src/examples/BrokenNodes/index.tsx b/examples/react/src/examples/BrokenNodes/index.tsx new file mode 100644 index 00000000..990612f9 --- /dev/null +++ b/examples/react/src/examples/BrokenNodes/index.tsx @@ -0,0 +1,80 @@ +import { useCallback, useState } from 'react'; +import { ReactFlow, addEdge, Node, Connection, Edge, OnNodeDrag } from '@xyflow/react'; + +const nodesInit: Node[] = [ + { + id: '1a', + type: 'input', + data: { label: 'Node 1' }, + position: { x: 250, y: 5 }, + className: 'light', + ariaLabel: 'Input Node 1', + }, + { + id: '2a', + data: { label: 'Node 2' }, + position: { x: 100, y: 100 }, + className: 'light', + ariaLabel: 'Default Node 2', + }, + { + id: '3a', + data: { label: 'Node 3' }, + position: { x: 400, y: 100 }, + className: 'light', + }, + { + id: '4a', + data: { label: 'Node 4' }, + position: { x: 400, y: 200 }, + className: 'light', + }, +]; + +const edgesInit: Edge[] = [ + { id: 'e1-2', source: '1a', target: '2a', ariaLabel: undefined }, + { id: 'e1-3', source: '1a', target: '3a' }, +]; + +const onNodesChange = () => {}; +const onEdgesChange = () => {}; +const BasicFlow = () => { + const [nodes, setNodes] = useState(nodesInit); + const [edges, setEdges] = useState(edgesInit); + + const onConnect = useCallback((params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)), [setEdges]); + + const onNodeDrag: OnNodeDrag = useCallback((e, node) => { + if (isNaN(node.position.x) || isNaN(node.position.y)) { + console.log('received NaN', node.position); + } + + setNodes((nds) => { + return nds.map((item) => { + if (item.id === node.id) { + return { + ...item, + position: { + x: node.position.x, + y: node.position.y, + }, + }; + } + return item; + }); + }); + }, []); + + return ( + + ); +}; + +export default BasicFlow; diff --git a/examples/react/src/examples/Stress/index.tsx b/examples/react/src/examples/Stress/index.tsx index 9020ddd6..496fd500 100644 --- a/examples/react/src/examples/Stress/index.tsx +++ b/examples/react/src/examples/Stress/index.tsx @@ -12,6 +12,8 @@ import { Controls, Background, Panel, + ReactFlowProvider, + useReactFlow, } from '@xyflow/react'; import { getNodesAndEdges } from './utils'; @@ -22,6 +24,7 @@ const { nodes: initialNodes, edges: initialEdges } = getNodesAndEdges(25, 25); const StressFlow = () => { const [nodes, setNodes] = useState(initialNodes); const [edges, setEdges] = useState(initialEdges); + const { fitView } = useReactFlow(); const onConnect = useCallback((connection: Connection) => { setEdges((eds) => addEdge(connection, eds)); }, []); @@ -191,12 +194,13 @@ const StressFlow = () => { return { ...n, position: { - x: Math.random() * window.innerWidth, - y: Math.random() * window.innerHeight, + x: Math.random() * window.innerWidth * 4, + y: Math.random() * window.innerHeight * 4, }, }; }); }); + fitView(); }; const updateElements = () => { @@ -240,4 +244,10 @@ const StressFlow = () => { ); }; -export default StressFlow; +export default function StressFlowProvider() { + return ( + + + + ); +} diff --git a/examples/react/src/examples/UseOnSelectionChange/index.tsx b/examples/react/src/examples/UseOnSelectionChange/index.tsx index b9795951..fdbe124a 100644 --- a/examples/react/src/examples/UseOnSelectionChange/index.tsx +++ b/examples/react/src/examples/UseOnSelectionChange/index.tsx @@ -10,7 +10,6 @@ import { useEdgesState, useOnSelectionChange, OnSelectionChangeParams, - OnSelectionChangeFunc, } from '@xyflow/react'; const initialNodes: Node[] = [ diff --git a/examples/svelte/package.json b/examples/svelte/package.json index 42de4302..b1fe9b38 100644 --- a/examples/svelte/package.json +++ b/examples/svelte/package.json @@ -12,20 +12,20 @@ "format": "prettier --plugin-search-dir . --write ." }, "devDependencies": { - "@sveltejs/adapter-auto": "^4.0.0", - "@sveltejs/kit": "^2.16.1", - "@typescript-eslint/eslint-plugin": "^8.22.0", - "@typescript-eslint/parser": "^8.22.0", - "eslint": "^8.53.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.46.1", - "prettier": "^3.4.2", + "@sveltejs/adapter-auto": "^6.0.0", + "@sveltejs/kit": "^2.20.4", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-svelte": "^3.5.1", + "prettier": "^3.5.3", "prettier-plugin-svelte": "^3.3.3", - "svelte": "^5.19.5", - "svelte-check": "^4.1.4", + "svelte": "^5.25.8", + "svelte-check": "^4.1.5", "tslib": "^2.8.1", - "typescript": "^5.7.3", - "vite": "^6.0.11" + "typescript": "^5.8.3", + "vite": "^6.2.5" }, "type": "module", "dependencies": { diff --git a/package.json b/package.json index 7a33c404..0e52b690 100644 --- a/package.json +++ b/package.json @@ -25,20 +25,15 @@ "@changesets/changelog-github": "^0.4.7", "@changesets/cli": "^2.25.0", "@playwright/test": "^1.44.1", - "@typescript-eslint/eslint-plugin": "latest", - "@typescript-eslint/parser": "latest", "concurrently": "^7.6.0", "eslint": "^8.22.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "latest", "prettier": "^2.7.1", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^3.0.2", "rollup": "^4.18.0", "turbo": "^2.0.3", - "typescript": "5.1.3" + "typescript": "5.4.5" }, "packageManager": "pnpm@9.2.0" } diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 3f3b6e31..8e49ed34 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,158 @@ # @xyflow/react +## 12.5.5 + +### Patch Changes + +- [#5172](https://github.com/xyflow/xyflow/pull/5172) [`e6139a00`](https://github.com/xyflow/xyflow/commit/e6139a00d4414ba2c1d3e500cdfa67d7e66e655a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useNodesData`, `useReactFlow`, `isNode` and `isEdge` + +- [#5165](https://github.com/xyflow/xyflow/pull/5165) [`d536abea`](https://github.com/xyflow/xyflow/commit/d536abea9240bad7f5c1064efc0a4713ebef87d1) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useViewport`, `useUpdateNodeInternals`, `useOnSelectionChange`, `useNodesInitialized` hooks and `UseOnSelectionChangeOptions`, `UseNodesInitializedOptions` types + +- [#5171](https://github.com/xyflow/xyflow/pull/5171) [`62d87409`](https://github.com/xyflow/xyflow/commit/62d874097337a022bebe54b559834c0d582f435e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `ReactFlowProps` + +- [#5154](https://github.com/xyflow/xyflow/pull/5154) [`d0237166`](https://github.com/xyflow/xyflow/commit/d02371662669aab91cd2ac7c45b412491c3377bd) Thanks [@ibagov](https://github.com/ibagov)! - Improve TSDoc comments for `onNodesChange` + +- [#5174](https://github.com/xyflow/xyflow/pull/5174) [`ae585d13`](https://github.com/xyflow/xyflow/commit/ae585d136e34c9e9ad9d45f75c059bc5367e73ae) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `BaseEdgeProps` + +- [#5159](https://github.com/xyflow/xyflow/pull/5159) [`0c1436d6`](https://github.com/xyflow/xyflow/commit/0c1436d6a371240cfa0adecea573c44fd42df7b3) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useConnection` hook + +- [#5167](https://github.com/xyflow/xyflow/pull/5167) [`934ea42d`](https://github.com/xyflow/xyflow/commit/934ea42d9af6027a3164e1196a78140bdd05d347) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useEdges`, `useInternalNode`, `useNodes` and `useNodeId` hooks + +- [#5163](https://github.com/xyflow/xyflow/pull/5163) [`ab800054`](https://github.com/xyflow/xyflow/commit/ab800054a50c68f9c27dfad2b0d3833b782f4797) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useNodesState` and `useEdgesState` hook + +- [#5160](https://github.com/xyflow/xyflow/pull/5160) [`b357f43d`](https://github.com/xyflow/xyflow/commit/b357f43dfa262205059ac9714198196b4aaf8870) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type UseHandleConnectionsParams` and `useHandleConnections` hook + +- [#5162](https://github.com/xyflow/xyflow/pull/5162) [`29f4aeb2`](https://github.com/xyflow/xyflow/commit/29f4aeb260df0a5d83e775c7c2ed788f997006a7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type UseNodeConnectionsParams` and `useNodeConnections` hook + +- [#5164](https://github.com/xyflow/xyflow/pull/5164) [`09021550`](https://github.com/xyflow/xyflow/commit/09021550dc72ac240fcbb6adb3cf530d91575f79) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type UseOnViewportChangeOptions` and `useOnViewportChange` hook + +- [#5166](https://github.com/xyflow/xyflow/pull/5166) [`701ad17e`](https://github.com/xyflow/xyflow/commit/701ad17ed3f523389e7d0bf9a006bef249645c3d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `useStore` hook + +- [#5170](https://github.com/xyflow/xyflow/pull/5170) [`eb2a33c6`](https://github.com/xyflow/xyflow/commit/eb2a33c6dfb0629e851ab3a0f2cd70eca92efc42) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `interface GetSimpleBezierPathParams` and `getSimpleBezierPath` + +- [#5161](https://github.com/xyflow/xyflow/pull/5161) [`c4efe749`](https://github.com/xyflow/xyflow/commit/c4efe749208e854dc9ced5bdd00933269d5b4382) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type UseKeyPressOptions` and `useKeyPress` hook + +- Updated dependencies [[`02a3b746`](https://github.com/xyflow/xyflow/commit/02a3b74645799a3f0ce670b69365fa86ecb0616e), [`cbe305e1`](https://github.com/xyflow/xyflow/commit/cbe305e15a5c5d3b92583e0ec12364b2509f49bd), [`1f671bd4`](https://github.com/xyflow/xyflow/commit/1f671bd48f06230da841fdd1d7a312413ef16d03), [`aaebc462`](https://github.com/xyflow/xyflow/commit/aaebc462951ded8e91374c3e084d77af5ed7380a), [`6ec942fc`](https://github.com/xyflow/xyflow/commit/6ec942fc6501f81009c278cc995764bef3e8d03b)]: + - @xyflow/system@0.0.55 + +## 12.5.4 + +### Patch Changes + +- [#5134](https://github.com/xyflow/xyflow/pull/5134) [`7acab1e1`](https://github.com/xyflow/xyflow/commit/7acab1e123944c296180fbf826a3fd488963608f) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Adjust `@default` TSDoc tags for `BackgroundProps` + +- [#5135](https://github.com/xyflow/xyflow/pull/5135) [`754a1671`](https://github.com/xyflow/xyflow/commit/754a167134f22fa00a139de4c7e10aaaa1953ac8) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `NodeResizerProps` and `ResizeControlProps` + +- [#5140](https://github.com/xyflow/xyflow/pull/5140) [`82e6860e`](https://github.com/xyflow/xyflow/commit/82e6860e1354b8bb8047399b7773fd090be206d7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `MiniMapProps` and `PanelProps` + +- [#5147](https://github.com/xyflow/xyflow/pull/5147) [`f819005b`](https://github.com/xyflow/xyflow/commit/f819005be362d044b16ce4c0b85432f3f300a13a) Thanks [@moklick](https://github.com/moklick)! - Pass dimensions to final resize change event + +- [#5143](https://github.com/xyflow/xyflow/pull/5143) [`b1e1cc11`](https://github.com/xyflow/xyflow/commit/b1e1cc1125d106cf1521a1524286404483e38f30) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `ReactFlowInstance` and `GeneralHelpers` + +- [#5138](https://github.com/xyflow/xyflow/pull/5138) [`d4eb8d52`](https://github.com/xyflow/xyflow/commit/d4eb8d52d0e26e9534ec5fc347211ce91d1ddd32) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `ViewportHelperFunctions` and `NodeToolbarProps` + +- [#5144](https://github.com/xyflow/xyflow/pull/5144) [`5a1ce56e`](https://github.com/xyflow/xyflow/commit/5a1ce56e8ce83f01e01ef531d90c52181c3e3a1a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Compare `nodeStrokeWidth` with `number`, not with `string` within `MiniMap` + +- [#5141](https://github.com/xyflow/xyflow/pull/5141) [`06cf4c10`](https://github.com/xyflow/xyflow/commit/06cf4c10f5d8a43f57ee0fde19d9a3fe1044cf48) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `Edge`, `BaseEdgeProps` and `ConnectionLineComponentProps` + +- Updated dependencies [[`f819005b`](https://github.com/xyflow/xyflow/commit/f819005be362d044b16ce4c0b85432f3f300a13a), [`24a1bc89`](https://github.com/xyflow/xyflow/commit/24a1bc89348817ed9b5c87f74bf2519c705143be), [`36657cd6`](https://github.com/xyflow/xyflow/commit/36657cd66322c911e87eb37275c584a80025adfe), [`89de9ca8`](https://github.com/xyflow/xyflow/commit/89de9ca83fbf9263a687a0f5f915efb2beb31654), [`2ac6e155`](https://github.com/xyflow/xyflow/commit/2ac6e155e35256ca436281df16344366e7d05761), [`f0f378e5`](https://github.com/xyflow/xyflow/commit/f0f378e5b6918c2c30d9dc1e32587063cb942d4e)]: + - @xyflow/system@0.0.54 + +## 12.5.3 + +### Patch Changes + +- [#5132](https://github.com/xyflow/xyflow/pull/5132) [`75ab8942`](https://github.com/xyflow/xyflow/commit/75ab89420e3cd0fdc34baf06eabdc50113d4de7c) Thanks [@peterkogo](https://github.com/peterkogo)! - Fix fitView not working when onNodesChange is not defined. + +## 12.5.2 + +### Patch Changes + +- [#5124](https://github.com/xyflow/xyflow/pull/5124) [`b76f7f9e`](https://github.com/xyflow/xyflow/commit/b76f7f9eb4841f139b1468b8eda0430ddd19a1ae) Thanks [@bjornosal](https://github.com/bjornosal)! - Export NodeConnection type + +- [#5127](https://github.com/xyflow/xyflow/pull/5127) [`3079c2c9`](https://github.com/xyflow/xyflow/commit/3079c2c911426f54e8d295083ddbe97ed3aad201) Thanks [@peterkogo](https://github.com/peterkogo)! - Fix `fitView` not working when returning early in `onNodesChange`. + +## 12.5.1 + +### Patch Changes + +- [#5120](https://github.com/xyflow/xyflow/pull/5120) [`6dfea686`](https://github.com/xyflow/xyflow/commit/6dfea6863a3cbd91f932bf54a6dba549bd248bd5) Thanks [@moklick](https://github.com/moklick)! - Handle fitView for uncontrolled flows + +## 12.5.0 + +### Minor Changes + +- [#5067](https://github.com/xyflow/xyflow/pull/5067) [`acba901d`](https://github.com/xyflow/xyflow/commit/acba901d861aa84cb5beba60b24fff4cfde7ada6) Thanks [@peterkogo](https://github.com/peterkogo)! - You can now express paddings in fitViewOptions as pixels ('30px'), as viewport percentages ('20%') and define different paddings for each side. + +### Patch Changes + +- [#5109](https://github.com/xyflow/xyflow/pull/5109) [`0cdda42c`](https://github.com/xyflow/xyflow/commit/0cdda42cdd1cd43d43d43c44e54b7b9f7a716ca9) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix: improve TSDoc comments for `BackgroundProps` + +- [#5059](https://github.com/xyflow/xyflow/pull/5059) [`065ff89d`](https://github.com/xyflow/xyflow/commit/065ff89d10488f9c76c56870511e45eaed299778) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Prevent onPaneClick when connection is in progress. Closes [#5057](https://github.com/xyflow/xyflow/issues/5057) + +- [#5110](https://github.com/xyflow/xyflow/pull/5110) [`7eb6eb07`](https://github.com/xyflow/xyflow/commit/7eb6eb0709e451d7628bfdbc3ced89b3bb57b626) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix: improve TSDoc comments for `EdgeLabelOptions` and `BaseEdgeProps` + +- [#5113](https://github.com/xyflow/xyflow/pull/5113) [`bce8542d`](https://github.com/xyflow/xyflow/commit/bce8542df19c33f3cd9225f483435e8a7aa4ed94) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix: improve TSDoc comments for `ControlProps` + +- [#5116](https://github.com/xyflow/xyflow/pull/5116) [`58942154`](https://github.com/xyflow/xyflow/commit/589421542386906ec49d8469cac551b8f7ea1c47) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix: improve TSDoc comments for `NodeToolbarProps` + +- [#5114](https://github.com/xyflow/xyflow/pull/5114) [`ba2bfbb4`](https://github.com/xyflow/xyflow/commit/ba2bfbb49aafac979f94b0136bb408faea12d5c6) Thanks [@dimaMachina](https://github.com/dimaMachina)! - feat: export `EdgeLabelRendererProps` + +- [#5107](https://github.com/xyflow/xyflow/pull/5107) [`c5a8c237`](https://github.com/xyflow/xyflow/commit/c5a8c23773e5985be6b37abacdac743911be8c09) Thanks [@moklick](https://github.com/moklick)! - Add TSDoc annotations for exported edges + +- [#5067](https://github.com/xyflow/xyflow/pull/5067) [`cb685281`](https://github.com/xyflow/xyflow/commit/cb685281d0eaf03e9833271c31f92b1d143af2fe) Thanks [@peterkogo](https://github.com/peterkogo)! - Fix fitView not working immediately after adding new nodes + +- [#5115](https://github.com/xyflow/xyflow/pull/5115) [`c2154557`](https://github.com/xyflow/xyflow/commit/c215455735385ef5e12e4130164b9d01f9c18aa2) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix: improve TSDoc comments for `EdgeLabelOptions` and `EdgeTextProps` + +- [#5093](https://github.com/xyflow/xyflow/pull/5093) [`65825e89`](https://github.com/xyflow/xyflow/commit/65825e89a6e2e7591087eb41ac89da4da7095f8f) Thanks [@moklick](https://github.com/moklick)! - Hidden nodes are not displayed in the mini map anymore + +- [#5090](https://github.com/xyflow/xyflow/pull/5090) [`8da1748a`](https://github.com/xyflow/xyflow/commit/8da1748a6ad5cdde9f03737ff786bd29c9c968de) Thanks [@moklick](https://github.com/moklick)! - Release key even when an inout field is focused + +- Updated dependencies [[`5d15b01b`](https://github.com/xyflow/xyflow/commit/5d15b01ba8cb349d6397a6ed8162848b4dfec293), [`cb685281`](https://github.com/xyflow/xyflow/commit/cb685281d0eaf03e9833271c31f92b1d143af2fe), [`a79f30b3`](https://github.com/xyflow/xyflow/commit/a79f30b3dd7c8ff6400c8d22214b2c2282e5bac1)]: + - @xyflow/system@0.0.53 + +## 12.4.4 + +### Patch Changes + +- [#5052](https://github.com/xyflow/xyflow/pull/5052) [`99dd7d35`](https://github.com/xyflow/xyflow/commit/99dd7d3549e7423e7d103b2c956c8b37f5747b90) Thanks [@moklick](https://github.com/moklick)! - Show an error if user drags uninitialized node + +- [#5042](https://github.com/xyflow/xyflow/pull/5042) [`2fe0e850`](https://github.com/xyflow/xyflow/commit/2fe0e850a8c415c6a3113796a2c5c80e7cad2376) Thanks [@moklick](https://github.com/moklick)! - Allow click connections when target sets `isConnectableStart` + +- [#5047](https://github.com/xyflow/xyflow/pull/5047) [`b3bf5693`](https://github.com/xyflow/xyflow/commit/b3bf5693c659069cea90bf1cb215ae65d06c5509) Thanks [@moklick](https://github.com/moklick)! - Pass generics to OnSelectionChangeFunc so that users can type it correctly + +- [#5053](https://github.com/xyflow/xyflow/pull/5053) [`25fb45b5`](https://github.com/xyflow/xyflow/commit/25fb45b5e9d6da391b9aff652b8e6e34eaf757fc) Thanks [@moklick](https://github.com/moklick)! - Remove incorrect deprecation warning + +- [#5033](https://github.com/xyflow/xyflow/pull/5033) [`7b4a81fb`](https://github.com/xyflow/xyflow/commit/7b4a81fb6b3d88f8ee7b4f070aef7ac3b962d5a6) Thanks [@dimaMachina](https://github.com/dimaMachina)! - lint: use `React.JSX` type instead of the deprecated global `JSX` namespace + +- [#5043](https://github.com/xyflow/xyflow/pull/5043) [`0292ad20`](https://github.com/xyflow/xyflow/commit/0292ad20109a3b2518dc686a82e100a0a6964fb8) Thanks [@moklick](https://github.com/moklick)! - Use current expandParent value on drag to be able to update it while dragging + +- [#5032](https://github.com/xyflow/xyflow/pull/5032) [`5867bba8`](https://github.com/xyflow/xyflow/commit/5867bba8050d07378a45a2026557c4bce7bda239) Thanks [@dimaMachina](https://github.com/dimaMachina)! - lint: remove unnecessary type assertions + +- Updated dependencies [[`99dd7d35`](https://github.com/xyflow/xyflow/commit/99dd7d3549e7423e7d103b2c956c8b37f5747b90)]: + - @xyflow/system@0.0.52 + +## 12.4.3 + +### Patch Changes + +- [#5010](https://github.com/xyflow/xyflow/pull/5010) [`6c121d42`](https://github.com/xyflow/xyflow/commit/6c121d427fea9a11e86a85f95d2c12ba8af34919) Thanks [@moklick](https://github.com/moklick)! - Add more TSDocs to components, hooks, utils funcs and types + +- [#4991](https://github.com/xyflow/xyflow/pull/4991) [`ea54d9bc`](https://github.com/xyflow/xyflow/commit/ea54d9bcb197d02d248ef3e4eaabc033a43d966a) Thanks [@waynetee](https://github.com/waynetee)! - Fix viewport shifting on node focus + +- [#5013](https://github.com/xyflow/xyflow/pull/5013) [`cde899c5`](https://github.com/xyflow/xyflow/commit/cde899c5be9715c4ff2cc331ea93821102604c62) Thanks [@moklick](https://github.com/moklick)! - Pass `NodeType` type argument from `ReactFlowProps` to `connectionLineComponent` property. + +- [#5008](https://github.com/xyflow/xyflow/pull/5008) [`12d859fe`](https://github.com/xyflow/xyflow/commit/12d859fe297593d44cf8493a4d6bf2c664b9139c) Thanks [@moklick](https://github.com/moklick)! - Add package.json to exports + +- [#5012](https://github.com/xyflow/xyflow/pull/5012) [`4d3f19e8`](https://github.com/xyflow/xyflow/commit/4d3f19e88b984ce6743970560d7367d174500f32) Thanks [@moklick](https://github.com/moklick)! - Add snapGrid option to screenToFlowPosition and set snapToGrid to false + +- [#5003](https://github.com/xyflow/xyflow/pull/5003) [`e8e0d684`](https://github.com/xyflow/xyflow/commit/e8e0d684957b95d53a6cc11598c8755ff02117c7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - repair lint command + +- [#4991](https://github.com/xyflow/xyflow/pull/4991) [`4c62f19b`](https://github.com/xyflow/xyflow/commit/4c62f19b3afac4b3db84b14e2c36f8c9e0a96116) Thanks [@waynetee](https://github.com/waynetee)! - Prevent viewport shift after using Tab + +- Updated dependencies [[`6c121d42`](https://github.com/xyflow/xyflow/commit/6c121d427fea9a11e86a85f95d2c12ba8af34919), [`4947029c`](https://github.com/xyflow/xyflow/commit/4947029cd6cda0f695e1fb4815e4030adb232234), [`e8e0d684`](https://github.com/xyflow/xyflow/commit/e8e0d684957b95d53a6cc11598c8755ff02117c7)]: + - @xyflow/system@0.0.51 + ## 12.4.2 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index fb572c1a..1f42f3aa 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/react", - "version": "12.4.2", + "version": "12.5.5", "description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.", "keywords": [ "react", @@ -28,6 +28,7 @@ "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", "exports": { + "./package.json": "./package.json", ".": { "node": { "types": "./dist/esm/index.d.ts", @@ -84,7 +85,7 @@ "postcss-nested": "^6.0.0", "postcss-rename": "^0.6.1", "react": "^18.2.0", - "typescript": "5.1.3" + "typescript": "5.4.5" }, "rollup": { "globals": { diff --git a/packages/react/src/additional-components/Background/Background.tsx b/packages/react/src/additional-components/Background/Background.tsx index e4470f10..ee89624d 100644 --- a/packages/react/src/additional-components/Background/Background.tsx +++ b/packages/react/src/additional-components/Background/Background.tsx @@ -90,4 +90,57 @@ function BackgroundComponent({ BackgroundComponent.displayName = 'Background'; +/** + * The `` component makes it convenient to render different types of backgrounds common in node-based UIs. It comes with three variants: lines, dots and cross. + * + * @example + * + * A simple example of how to use the Background component. + * + * ```tsx + * import { useState } from 'react'; + * import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react'; + * + * export default function Flow() { + * return ( + * + * + * + * ); + * } + * ``` + * + * @example + * + * In this example you can see how to combine multiple backgrounds + * + * ```tsx + * import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react'; + * import '@xyflow/react/dist/style.css'; + * + * export default function Flow() { + * return ( + * + * + * + * + * ); + * } + * ``` + * + * @remarks + * + * When combining multiple components it’s important to give each of them a unique id prop! + * + */ export const Background = memo(BackgroundComponent); diff --git a/packages/react/src/additional-components/Background/types.ts b/packages/react/src/additional-components/Background/types.ts index 0a035aae..8e8bf944 100644 --- a/packages/react/src/additional-components/Background/types.ts +++ b/packages/react/src/additional-components/Background/types.ts @@ -1,34 +1,60 @@ import { CSSProperties } from 'react'; +/** + * The three variants are exported as an enum for convenience. You can either import + * the enum and use it like `BackgroundVariant.Lines` or you can use the raw string + * value directly. + * @public + */ export enum BackgroundVariant { Lines = 'lines', Dots = 'dots', Cross = 'cross', } +/** + * @expand + */ export type BackgroundProps = { + /** When multiple backgrounds are present on the page, each one should have a unique id. */ id?: string; - /** Color of the pattern */ + /** Color of the pattern. */ color?: string; - /** Color of the background */ + /** Color of the background. */ bgColor?: string; - /** Class applied to the container */ + /** Class applied to the container. */ className?: string; - /** Class applied to the pattern */ + /** Class applied to the pattern. */ patternClassName?: string; - /** Gap between repetitions of the pattern */ + /** + * The gap between patterns. Passing in a tuple allows you to control the x and y gap + * independently. + * @default 20 + */ gap?: number | [number, number]; - /** Size of a single pattern element */ + /** + * The radius of each dot or the size of each rectangle if `BackgroundVariant.Dots` or + * `BackgroundVariant.Cross` is used. This defaults to 1 or 6 respectively, or ignored if + * `BackgroundVariant.Lines` is used. + */ size?: number; - /** Offset of the pattern */ + /** + * Offset of the pattern. + * @default 0 + */ offset?: number | [number, number]; - /** Line width of the Line pattern */ + /** + * The stroke thickness used when drawing the pattern. + * @default 1 + */ lineWidth?: number; - /** Variant of the pattern + /** + * Variant of the pattern. + * @default BackgroundVariant.Dots * @example BackgroundVariant.Lines, BackgroundVariant.Dots, BackgroundVariant.Cross * 'lines', 'dots', 'cross' */ variant?: BackgroundVariant; - /** Style applied to the container */ + /** Style applied to the container. */ style?: CSSProperties; }; diff --git a/packages/react/src/additional-components/Controls/ControlButton.tsx b/packages/react/src/additional-components/Controls/ControlButton.tsx index 744f46d4..a3cc81ad 100644 --- a/packages/react/src/additional-components/Controls/ControlButton.tsx +++ b/packages/react/src/additional-components/Controls/ControlButton.tsx @@ -2,6 +2,29 @@ import cc from 'classcat'; import type { ControlButtonProps } from './types'; +/** + * You can add buttons to the control panel by using the `` component + * and pass it as a child to the [``](/api-reference/components/controls) component. + * + * @public + * @example + *```jsx + *import { MagicWand } from '@radix-ui/react-icons' + *import { ReactFlow, Controls, ControlButton } from '@xyflow/react' + * + *export default function Flow() { + * return ( + * + * + * alert('Something magical just happened. ✨')}> + * + * + * + * + * ) + *} + *``` + */ export function ControlButton({ children, className, ...rest }: ControlButtonProps) { return ( + * + * + * + * + *
+ * {data.label} + *
+ * + * + * + * + * ); + *}; + * + *export default memo(CustomNode); + *``` + * @remarks By default, the toolbar is only visible when a node is selected. If multiple + * nodes are selected it will not be visible to prevent overlapping toolbars or + * clutter. You can override this behavior by setting the `isVisible` prop to `true`. + */ export function NodeToolbar({ nodeId, children, @@ -74,7 +109,7 @@ export function NodeToolbar({ const isActive = typeof isVisible === 'boolean' ? isVisible - : nodes.size === 1 && nodes.values().next().value.selected && selectedNodesCount === 1; + : nodes.size === 1 && nodes.values().next().value?.selected && selectedNodesCount === 1; if (!isActive || !nodes.size) { return null; diff --git a/packages/react/src/additional-components/NodeToolbar/types.ts b/packages/react/src/additional-components/NodeToolbar/types.ts index 4de679bd..6655547d 100644 --- a/packages/react/src/additional-components/NodeToolbar/types.ts +++ b/packages/react/src/additional-components/NodeToolbar/types.ts @@ -1,19 +1,31 @@ import type { HTMLAttributes } from 'react'; import type { Position, Align } from '@xyflow/system'; +/** + * @expand + */ export type NodeToolbarProps = HTMLAttributes & { - /** Id of the node, or array of ids the toolbar should be displayed at */ + /** + * By passing in an array of node id's you can render a single tooltip for a group or collection + * of nodes. + */ nodeId?: string | string[]; - /** If true, node toolbar is visible even if node is not selected */ + /** If `true`, node toolbar is visible even if node is not selected. */ isVisible?: boolean; - /** Position of the toolbar relative to the node - * @example Position.TopLeft, Position.TopRight, - * Position.BottomLeft, Position.BottomRight + /** + * Position of the toolbar relative to the node. + * @default Position.Top + * @example Position.TopLeft, Position.TopRight, Position.BottomLeft, Position.BottomRight */ position?: Position; - /** Offset the toolbar from the node */ + /** + * The space between the node and the toolbar, measured in pixels. + * @default 10 + */ offset?: number; - /** Align the toolbar relative to the node + /** + * Align the toolbar relative to the node. + * @default "center" * @example Align.Start, Align.Center, Align.End */ align?: Align; diff --git a/packages/react/src/components/BatchProvider/index.tsx b/packages/react/src/components/BatchProvider/index.tsx index 1dbab718..f41b79a8 100644 --- a/packages/react/src/components/BatchProvider/index.tsx +++ b/packages/react/src/components/BatchProvider/index.tsx @@ -28,33 +28,49 @@ export function BatchProvider(); const nodeQueueHandler = useCallback((queueItems: QueueItem[]) => { - const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup } = store.getState(); + const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup, fitViewQueued } = store.getState(); - // This is essentially an `Array.reduce` in imperative clothing. Processing - // this queue is a relatively hot path so we'd like to avoid the overhead of - // array methods where we can. - let next = nodes as NodeType[]; + /* + * This is essentially an `Array.reduce` in imperative clothing. Processing + * this queue is a relatively hot path so we'd like to avoid the overhead of + * array methods where we can. + */ + let next = nodes; for (const payload of queueItems) { next = typeof payload === 'function' ? payload(next) : payload; } if (hasDefaultNodes) { setNodes(next); - } else if (onNodesChange) { - onNodesChange( - getElementsDiffChanges({ - items: next, - lookup: nodeLookup, - }) as NodeChange[] - ); + } else { + // When a controlled flow is used we need to collect the changes + const changes = getElementsDiffChanges({ + items: next, + lookup: nodeLookup, + }) as NodeChange[]; + + // We only want to fire onNodesChange if there are changes to the nodes + if (changes.length > 0) { + onNodesChange?.(changes); + } else if (fitViewQueued) { + // If there are no changes to the nodes, we still need to call setNodes + // to trigger a re-render and fitView. + window.requestAnimationFrame(() => { + const { fitViewQueued, nodes, setNodes } = store.getState(); + if (fitViewQueued) { + setNodes(nodes); + } + }); + } } }, []); + const nodeQueue = useQueue(nodeQueueHandler); const edgeQueueHandler = useCallback((queueItems: QueueItem[]) => { const { edges = [], setEdges, hasDefaultEdges, onEdgesChange, edgeLookup } = store.getState(); - let next = edges as EdgeType[]; + let next = edges; for (const payload of queueItems) { next = typeof payload === 'function' ? payload(next) : payload; } diff --git a/packages/react/src/components/BatchProvider/useQueue.ts b/packages/react/src/components/BatchProvider/useQueue.ts index c33208d7..b1f9f793 100644 --- a/packages/react/src/components/BatchProvider/useQueue.ts +++ b/packages/react/src/components/BatchProvider/useQueue.ts @@ -12,21 +12,27 @@ import { Queue, QueueItem } from './types'; * @returns a Queue object */ export function useQueue(runQueue: (items: QueueItem[]) => void) { - // Because we're using a ref above, we need some way to let React know when to - // actually process the queue. We increment this number any time we mutate the - // queue, creating a new state to trigger the layout effect below. - // Using a boolean dirty flag here instead would lead to issues related to - // automatic batching. (https://github.com/xyflow/xyflow/issues/4779) + /* + * Because we're using a ref above, we need some way to let React know when to + * actually process the queue. We increment this number any time we mutate the + * queue, creating a new state to trigger the layout effect below. + * Using a boolean dirty flag here instead would lead to issues related to + * automatic batching. (https://github.com/xyflow/xyflow/issues/4779) + */ const [serial, setSerial] = useState(BigInt(0)); - // A reference of all the batched updates to process before the next render. We - // want a reference here so multiple synchronous calls to `setNodes` etc can be - // batched together. + /* + * A reference of all the batched updates to process before the next render. We + * want a reference here so multiple synchronous calls to `setNodes` etc can be + * batched together. + */ const [queue] = useState(() => createQueue(() => setSerial(n => n + BigInt(1)))); - // Layout effects are guaranteed to run before the next render which means we - // shouldn't run into any issues with stale state or weird issues that come from - // rendering things one frame later than expected (we used to use `setTimeout`). + /* + * Layout effects are guaranteed to run before the next render which means we + * shouldn't run into any issues with stale state or weird issues that come from + * rendering things one frame later than expected (we used to use `setTimeout`). + */ useIsomorphicLayoutEffect(() => { const queueItems = queue.get(); diff --git a/packages/react/src/components/ConnectionLine/index.tsx b/packages/react/src/components/ConnectionLine/index.tsx index a5f7e1e2..c179fae2 100644 --- a/packages/react/src/components/ConnectionLine/index.tsx +++ b/packages/react/src/components/ConnectionLine/index.tsx @@ -11,12 +11,12 @@ import { import { useStore } from '../../hooks/useStore'; import { getSimpleBezierPath } from '../Edges/SimpleBezierEdge'; -import type { ConnectionLineComponent, ReactFlowState } from '../../types'; +import type { ConnectionLineComponent, Node, ReactFlowState } from '../../types'; import { useConnection } from '../../hooks/useConnection'; -type ConnectionLineWrapperProps = { +type ConnectionLineWrapperProps = { type: ConnectionLineType; - component?: ConnectionLineComponent; + component?: ConnectionLineComponent; containerStyle?: CSSProperties; style?: CSSProperties; }; @@ -29,7 +29,12 @@ const selector = (s: ReactFlowState) => ({ height: s.height, }); -export function ConnectionLineWrapper({ containerStyle, style, type, component }: ConnectionLineWrapperProps) { +export function ConnectionLineWrapper({ + containerStyle, + style, + type, + component, +}: ConnectionLineWrapperProps) { const { nodesConnectable, width, height, isValid, inProgress } = useStore(selector, shallow); const renderConnection = !!(width && nodesConnectable && inProgress); @@ -45,21 +50,27 @@ export function ConnectionLineWrapper({ containerStyle, style, type, component } className="react-flow__connectionline react-flow__container" > - + style={style} type={type} CustomComponent={component} isValid={isValid} /> ); } -type ConnectionLineProps = { +type ConnectionLineProps = { type: ConnectionLineType; style?: CSSProperties; - CustomComponent?: ConnectionLineComponent; + CustomComponent?: ConnectionLineComponent; isValid: boolean | null; }; -const ConnectionLine = ({ style, type = ConnectionLineType.Bezier, CustomComponent, isValid }: ConnectionLineProps) => { - const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = useConnection(); +const ConnectionLine = ({ + style, + type = ConnectionLineType.Bezier, + CustomComponent, + isValid, +}: ConnectionLineProps) => { + const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition } = + useConnection(); if (!inProgress) { return; diff --git a/packages/react/src/components/EdgeLabelRenderer/index.tsx b/packages/react/src/components/EdgeLabelRenderer/index.tsx index c66b70ae..7115b495 100644 --- a/packages/react/src/components/EdgeLabelRenderer/index.tsx +++ b/packages/react/src/components/EdgeLabelRenderer/index.tsx @@ -6,7 +6,52 @@ import type { ReactFlowState } from '../../types'; const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__edgelabel-renderer'); -export function EdgeLabelRenderer({ children }: { children: ReactNode }) { +export type EdgeLabelRendererProps = { + children: ReactNode +} + +/** + * Edges are SVG-based. If you want to render more complex labels you can use the + * `` component to access a div based renderer. This component + * is a portal that renders the label in a `
` that is positioned on top of + * the edges. You can see an example usage of the component in the + * [edge label renderer example](/examples/edges/edge-label-renderer). + * @public + * + * @example + * ```jsx + * import React from 'react'; + * import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react'; + * + * export function CustomEdge({ id, data, ...props }) { + * const [edgePath, labelX, labelY] = getBezierPath(props); + * + * return ( + * <> + * + * + *
+ * {data.label} + *
+ *
+ * + * ); + * }; + * ``` + * + * @remarks The `` has no pointer events by default. If you want to + * add mouse interactions you need to set the style `pointerEvents: all` and add + * the `nopan` class on the label or the element you want to interact with. + */ +export function EdgeLabelRenderer({ children }: EdgeLabelRendererProps) { const edgeLabelRenderer = useStore(selector); if (!edgeLabelRenderer) { diff --git a/packages/react/src/components/EdgeWrapper/index.tsx b/packages/react/src/components/EdgeWrapper/index.tsx index f50ed4b9..72c5c2f8 100644 --- a/packages/react/src/components/EdgeWrapper/index.tsx +++ b/packages/react/src/components/EdgeWrapper/index.tsx @@ -1,4 +1,4 @@ -import { useState, useMemo, useRef, type KeyboardEvent, useCallback } from 'react'; +import { useState, useMemo, useRef, type KeyboardEvent, useCallback, JSX } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; import { @@ -136,28 +136,28 @@ export function EdgeWrapper({ const onEdgeDoubleClick = onDoubleClick ? (event: React.MouseEvent) => { - onDoubleClick(event, { ...edge }); - } + onDoubleClick(event, { ...edge }); + } : undefined; const onEdgeContextMenu = onContextMenu ? (event: React.MouseEvent) => { - onContextMenu(event, { ...edge }); - } + onContextMenu(event, { ...edge }); + } : undefined; const onEdgeMouseEnter = onMouseEnter ? (event: React.MouseEvent) => { - onMouseEnter(event, { ...edge }); - } + onMouseEnter(event, { ...edge }); + } : undefined; const onEdgeMouseMove = onMouseMove ? (event: React.MouseEvent) => { - onMouseMove(event, { ...edge }); - } + onMouseMove(event, { ...edge }); + } : undefined; const onEdgeMouseLeave = onMouseLeave ? (event: React.MouseEvent) => { - onMouseLeave(event, { ...edge }); - } + onMouseLeave(event, { ...edge }); + } : undefined; const onKeyDown = (event: KeyboardEvent) => { diff --git a/packages/react/src/components/Edges/BaseEdge.tsx b/packages/react/src/components/Edges/BaseEdge.tsx index 3d951796..4d1ac1da 100644 --- a/packages/react/src/components/Edges/BaseEdge.tsx +++ b/packages/react/src/components/Edges/BaseEdge.tsx @@ -4,6 +4,33 @@ import cc from 'classcat'; import { EdgeText } from './EdgeText'; import type { BaseEdgeProps } from '../../types'; +/** + * The `` component gets used internally for all the edges. It can be + * used inside a custom edge and handles the invisible helper edge and the edge label + * for you. + * + * @public + * @example + * ```jsx + *import { BaseEdge } from '@xyflow/react'; + * + *export function CustomEdge({ sourceX, sourceY, targetX, targetY, ...props }) { + * const [edgePath] = getStraightPath({ + * sourceX, + * sourceY, + * targetX, + * targetY, + * }); + * + * return ; + *} + *``` + * + * @remarks If you want to use an edge marker with the [``](/api-reference/components/base-edge) component, + * you can pass the `markerStart` or `markerEnd` props passed to your custom edge + * through to the [``](/api-reference/components/base-edge) component. + * You can see all the props passed to a custom edge by looking at the [`EdgeProps`](/api-reference/types/edge-props) type. + */ export function BaseEdge({ path, labelX, diff --git a/packages/react/src/components/Edges/BezierEdge.tsx b/packages/react/src/components/Edges/BezierEdge.tsx index 482f1fd8..3e84a39b 100644 --- a/packages/react/src/components/Edges/BezierEdge.tsx +++ b/packages/react/src/components/Edges/BezierEdge.tsx @@ -61,7 +61,34 @@ function createBezierEdge(params: { isInternal: boolean }) { ); } +/** + * Component that can be used inside a custom edge to render a bezier curve. + * + * @public + * @example + * + * ```tsx + * import { BezierEdge } from '@xyflow/react'; + * + * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { + * return ( + * + * ); + * } + * ``` + */ const BezierEdge = createBezierEdge({ isInternal: false }); + +/** + * @internal + */ const BezierEdgeInternal = createBezierEdge({ isInternal: true }); BezierEdge.displayName = 'BezierEdge'; diff --git a/packages/react/src/components/Edges/EdgeAnchor.tsx b/packages/react/src/components/Edges/EdgeAnchor.tsx index a975eaf5..9ee5f600 100644 --- a/packages/react/src/components/Edges/EdgeAnchor.tsx +++ b/packages/react/src/components/Edges/EdgeAnchor.tsx @@ -27,6 +27,9 @@ export interface EdgeAnchorProps extends SVGAttributes { const EdgeUpdaterClassName = 'react-flow__edgeupdater'; +/** + * @internal + */ export function EdgeAnchor({ position, centerX, diff --git a/packages/react/src/components/Edges/EdgeText.tsx b/packages/react/src/components/Edges/EdgeText.tsx index 2e3ad041..6646f683 100644 --- a/packages/react/src/components/Edges/EdgeText.tsx +++ b/packages/react/src/components/Edges/EdgeText.tsx @@ -8,9 +8,9 @@ function EdgeTextComponent({ x, y, label, - labelStyle = {}, + labelStyle, labelShowBg = true, - labelBgStyle = {}, + labelBgStyle, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, @@ -34,7 +34,7 @@ function EdgeTextComponent({ } }, [label]); - if (typeof label === 'undefined' || !label) { + if (!label) { return null; } @@ -73,4 +73,30 @@ function EdgeTextComponent({ EdgeTextComponent.displayName = 'EdgeText'; +/** + * You can use the `` component as a helper component to display text + * within your custom edges. + * + * @public + * + * @example + * ```jsx + * import { EdgeText } from '@xyflow/react'; + * + * export function CustomEdgeLabel({ label }) { + * return ( + * + * ); + * } + *``` + */ export const EdgeText = memo(EdgeTextComponent); diff --git a/packages/react/src/components/Edges/SimpleBezierEdge.tsx b/packages/react/src/components/Edges/SimpleBezierEdge.tsx index b3378c48..3d1cdb3d 100644 --- a/packages/react/src/components/Edges/SimpleBezierEdge.tsx +++ b/packages/react/src/components/Edges/SimpleBezierEdge.tsx @@ -7,9 +7,11 @@ import type { SimpleBezierEdgeProps } from '../../types'; export interface GetSimpleBezierPathParams { sourceX: number; sourceY: number; + /** @default Position.Bottom */ sourcePosition?: Position; targetX: number; targetY: number; + /** @default Position.Top */ targetPosition?: Position; } @@ -29,6 +31,19 @@ function getControl({ pos, x1, y1, x2, y2 }: GetControlParams): [number, number] return [x1, 0.5 * (y1 + y2)]; } +/** + * The `getSimpleBezierPath` util returns everything you need to render a simple + * bezier edge between two nodes. + * @public + * @returns + * - `path`: the path to use in an SVG `` element. + * - `labelX`: the `x` position you can use to render a label for this edge. + * - `labelY`: the `y` position you can use to render a label for this edge. + * - `offsetX`: the absolute difference between the source `x` position and the `x` position of the + * middle of this path. + * - `offsetY`: the absolute difference between the source `y` position and the `y` position of the + * middle of this path. + */ export function getSimpleBezierPath({ sourceX, sourceY, @@ -80,8 +95,8 @@ function createSimpleBezierEdge(params: { isInternal: boolean }) { sourceY, targetX, targetY, - sourcePosition = Position.Bottom, - targetPosition = Position.Top, + sourcePosition, + targetPosition, label, labelStyle, labelShowBg, diff --git a/packages/react/src/components/Edges/SmoothStepEdge.tsx b/packages/react/src/components/Edges/SmoothStepEdge.tsx index 1f6bcfd1..8b1475cf 100644 --- a/packages/react/src/components/Edges/SmoothStepEdge.tsx +++ b/packages/react/src/components/Edges/SmoothStepEdge.tsx @@ -62,7 +62,34 @@ function createSmoothStepEdge(params: { isInternal: boolean }) { ); } +/** + * Component that can be used inside a custom edge to render a smooth step edge. + * + * @public + * @example + * + * ```tsx + * import { SmoothStepEdge } from '@xyflow/react'; + * + * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { + * return ( + * + * ); + * } + * ``` + */ const SmoothStepEdge = createSmoothStepEdge({ isInternal: false }); + +/** + * @internal + */ const SmoothStepEdgeInternal = createSmoothStepEdge({ isInternal: true }); SmoothStepEdge.displayName = 'SmoothStepEdge'; diff --git a/packages/react/src/components/Edges/StepEdge.tsx b/packages/react/src/components/Edges/StepEdge.tsx index 6385e8f0..cd08758c 100644 --- a/packages/react/src/components/Edges/StepEdge.tsx +++ b/packages/react/src/components/Edges/StepEdge.tsx @@ -21,7 +21,34 @@ function createStepEdge(params: { isInternal: boolean }) { }); } +/** + * Component that can be used inside a custom edge to render a step edge. + * + * @public + * @example + * + * ```tsx + * import { StepEdge } from '@xyflow/react'; + * + * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { + * return ( + * + * ); + * } + * ``` + */ const StepEdge = createStepEdge({ isInternal: false }); + +/** + * @internal + */ const StepEdgeInternal = createStepEdge({ isInternal: true }); StepEdge.displayName = 'StepEdge'; diff --git a/packages/react/src/components/Edges/StraightEdge.tsx b/packages/react/src/components/Edges/StraightEdge.tsx index 53d1ac29..4f4cd76b 100644 --- a/packages/react/src/components/Edges/StraightEdge.tsx +++ b/packages/react/src/components/Edges/StraightEdge.tsx @@ -50,7 +50,32 @@ function createStraightEdge(params: { isInternal: boolean }) { ); } +/** + * Component that can be used inside a custom edge to render a straight line. + * + * @public + * @example + * + * ```tsx + * import { StraightEdge } from '@xyflow/react'; + * + * function CustomEdge({ sourceX, sourceY, targetX, targetY }) { + * return ( + * + * ); + * } + * ``` + */ const StraightEdge = createStraightEdge({ isInternal: false }); + +/** + * @internal + */ const StraightEdgeInternal = createStraightEdge({ isInternal: true }); StraightEdge.displayName = 'StraightEdge'; diff --git a/packages/react/src/components/Edges/index.ts b/packages/react/src/components/Edges/index.ts index 21af9667..88b274eb 100644 --- a/packages/react/src/components/Edges/index.ts +++ b/packages/react/src/components/Edges/index.ts @@ -1,6 +1,8 @@ -// We distinguish between internal and exported edges -// The internal edges are used directly like custom edges and always get an id, source and target props -// If you import an edge from the library, the id is optional and source and target are not used at all +/* + * We distinguish between internal and exported edges + * The internal edges are used directly like custom edges and always get an id, source and target props + * If you import an edge from the library, the id is optional and source and target are not used at all + */ export { SimpleBezierEdge, SimpleBezierEdgeInternal } from './SimpleBezierEdge'; export { SmoothStepEdge, SmoothStepEdgeInternal } from './SmoothStepEdge'; diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index cc86e189..b2c3373e 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -28,10 +28,14 @@ import { useNodeId } from '../../contexts/NodeIdContext'; import { type ReactFlowState } from '../../types'; import { fixedForwardRef } from '../../utils'; -export interface HandleProps extends HandlePropsSystem, Omit, 'id'> { - /** Callback called when connection is made */ - onConnect?: OnConnect; -} +/** + * @expand + */ +export type HandleProps = HandlePropsSystem & + Omit, 'id'> & { + /** Callback called when connection is made */ + onConnect?: OnConnect; + }; const selector = (s: ReactFlowState) => ({ connectOnClick: s.connectOnClick, @@ -42,9 +46,7 @@ const selector = (s: ReactFlowState) => ({ const connectingSelector = (nodeId: string | null, handleId: string | null, type: HandleType) => (state: ReactFlowState) => { const { connectionClickStartHandle: clickHandle, connectionMode, connection } = state; - const { fromHandle, toHandle, isValid } = connection; - const connectingTo = toHandle?.nodeId === nodeId && toHandle?.id === handleId && toHandle?.type === type; return { @@ -56,6 +58,7 @@ const connectingSelector = ? fromHandle?.type !== type : nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.id, connectionInProcess: !!fromHandle, + clickConnectionInProcess: !!clickHandle, valid: connectingTo && isValid, }; }; @@ -83,11 +86,15 @@ function HandleComponent( const store = useStoreApi(); const nodeId = useNodeId(); const { connectOnClick, noPanClassName, rfId } = useStore(selector, shallow); - const { connectingFrom, connectingTo, clickConnecting, isPossibleEndHandle, connectionInProcess, valid } = useStore( - connectingSelector(nodeId, handleId, type), - shallow - ); - + const { + connectingFrom, + connectingTo, + clickConnecting, + isPossibleEndHandle, + connectionInProcess, + clickConnectionInProcess, + valid, + } = useStore(connectingSelector(nodeId, handleId, type), shallow); if (!nodeId) { store.getState().onError?.('010', errorMessages['error010']()); } @@ -228,12 +235,14 @@ function HandleComponent( connectingfrom: connectingFrom, connectingto: connectingTo, valid, - // shows where you can start a connection from - // and where you can end it while connecting + /* + * shows where you can start a connection from + * and where you can end it while connecting + */ connectionindicator: isConnectable && (!connectionInProcess || isPossibleEndHandle) && - (connectionInProcess ? isConnectableEnd : isConnectableStart), + (connectionInProcess || clickConnectionInProcess ? isConnectableEnd : isConnectableStart), }, ])} onMouseDown={onPointerDown} @@ -248,6 +257,28 @@ function HandleComponent( } /** - * The Handle component is a UI element that is used to connect nodes. + * The `` component is used in your [custom nodes](/learn/customization/custom-nodes) + * to define connection points. + * + *@public + * + *@example + * + *```jsx + *import { Handle, Position } from '@xyflow/react'; + * + *export function CustomNode({ data }) { + * return ( + * <> + *
+ * {data.label} + *
+ * + * + * + * + * ); + *}; + *``` */ export const Handle = memo(fixedForwardRef(HandleComponent)); diff --git a/packages/react/src/components/NodeWrapper/index.tsx b/packages/react/src/components/NodeWrapper/index.tsx index 4b0295e9..5c0ce08b 100644 --- a/packages/react/src/components/NodeWrapper/index.tsx +++ b/packages/react/src/components/NodeWrapper/index.tsx @@ -37,7 +37,6 @@ export function NodeWrapper({ disableKeyboardA11y, rfId, nodeTypes, - nodeExtent, nodeClickDistance, onError, }: NodeWrapperProps) { @@ -109,8 +108,10 @@ export function NodeWrapper({ const { selectNodesOnDrag, nodeDragThreshold } = store.getState(); if (isSelectable && (!selectNodesOnDrag || !isDraggable || nodeDragThreshold > 0)) { - // this handler gets called by XYDrag on drag start when selectNodesOnDrag=true - // here we only need to call it when selectNodesOnDrag=false + /* + * this handler gets called by XYDrag on drag start when selectNodesOnDrag=true + * here we only need to call it when selectNodesOnDrag=false + */ handleNodeClick({ id, store, diff --git a/packages/react/src/components/NodeWrapper/useNodeObserver.ts b/packages/react/src/components/NodeWrapper/useNodeObserver.ts index 2c2910fd..de1d31e7 100644 --- a/packages/react/src/components/NodeWrapper/useNodeObserver.ts +++ b/packages/react/src/components/NodeWrapper/useNodeObserver.ts @@ -49,8 +49,10 @@ export function useNodeObserver({ useEffect(() => { if (nodeRef.current) { - // when the user programmatically changes the source or handle position, we need to update the internals - // to make sure the edges are updated correctly + /* + * when the user programmatically changes the source or handle position, we need to update the internals + * to make sure the edges are updated correctly + */ const typeChanged = prevType.current !== nodeType; const sourcePosChanged = prevSourcePosition.current !== node.sourcePosition; const targetPosChanged = prevTargetPosition.current !== node.targetPosition; diff --git a/packages/react/src/components/NodeWrapper/utils.tsx b/packages/react/src/components/NodeWrapper/utils.tsx index c8c7d5c7..8c699c64 100644 --- a/packages/react/src/components/NodeWrapper/utils.tsx +++ b/packages/react/src/components/NodeWrapper/utils.tsx @@ -23,9 +23,9 @@ export const builtinNodeTypes: NodeTypes = { export function getNodeInlineStyleDimensions( node: InternalNode ): { - width: number | string | undefined; - height: number | string | undefined; -} { + width: number | string | undefined; + height: number | string | undefined; + } { if (node.internals.handleBounds === undefined) { return { width: node.width ?? node.initialWidth ?? node.style?.width, diff --git a/packages/react/src/components/Nodes/utils.ts b/packages/react/src/components/Nodes/utils.ts index 81939bbc..146e05f8 100644 --- a/packages/react/src/components/Nodes/utils.ts +++ b/packages/react/src/components/Nodes/utils.ts @@ -4,10 +4,12 @@ import { errorMessages } from '@xyflow/system'; import type { ReactFlowState } from '../../types'; -// this handler is called by -// 1. the click handler when node is not draggable or selectNodesOnDrag = false -// or -// 2. the on drag start handler when node is draggable and selectNodesOnDrag = true +/* + * this handler is called by + * 1. the click handler when node is not draggable or selectNodesOnDrag = false + * or + * 2. the on drag start handler when node is draggable and selectNodesOnDrag = true + */ export function handleNodeClick({ id, store, diff --git a/packages/react/src/components/NodesSelection/index.tsx b/packages/react/src/components/NodesSelection/index.tsx index ecaef17b..ae587b56 100644 --- a/packages/react/src/components/NodesSelection/index.tsx +++ b/packages/react/src/components/NodesSelection/index.tsx @@ -61,9 +61,9 @@ export function NodesSelection({ const onContextMenu = onSelectionContextMenu ? (event: MouseEvent) => { - const selectedNodes = store.getState().nodes.filter((n) => n.selected); - onSelectionContextMenu(event, selectedNodes); - } + const selectedNodes = store.getState().nodes.filter((n) => n.selected); + onSelectionContextMenu(event, selectedNodes); + } : undefined; const onKeyDown = (event: KeyboardEvent) => { diff --git a/packages/react/src/components/Panel/index.tsx b/packages/react/src/components/Panel/index.tsx index 83b4a87b..16fe7841 100644 --- a/packages/react/src/components/Panel/index.tsx +++ b/packages/react/src/components/Panel/index.tsx @@ -1,20 +1,48 @@ -import { forwardRef, type HTMLAttributes, type ReactNode } from 'react'; +import { HTMLAttributes, forwardRef } from 'react'; import cc from 'classcat'; import type { PanelPosition } from '@xyflow/system'; import { useStore } from '../../hooks/useStore'; import type { ReactFlowState } from '../../types'; +/** + * @expand + */ export type PanelProps = HTMLAttributes & { - /** Set position of the panel - * @example 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' + /** + * The position of the panel. + * @default "top-left" */ position?: PanelPosition; - children: ReactNode; }; const selector = (s: ReactFlowState) => (s.userSelectionActive ? 'none' : 'all'); +/** + * The `` component helps you position content above the viewport. + * It is used internally by the [``](/api-reference/components/minimap) + * and [``](/api-reference/components/controls) components. + * + * @public + * + * @example + * ```jsx + *import { ReactFlow, Background, Panel } from '@xyflow/react'; + * + *export default function Flow() { + * return ( + * + * top-left + * top-center + * top-right + * bottom-left + * bottom-center + * bottom-right + * + * ); + *} + *``` + */ export const Panel = forwardRef( ({ position = 'top-left', children, className, style, ...rest }, ref) => { const pointerEvents = useStore(selector); @@ -32,3 +60,5 @@ export const Panel = forwardRef( ); } ); + +Panel.displayName = 'Panel'; diff --git a/packages/react/src/components/ReactFlowProvider/index.tsx b/packages/react/src/components/ReactFlowProvider/index.tsx index b29f5f17..1492ca3f 100644 --- a/packages/react/src/components/ReactFlowProvider/index.tsx +++ b/packages/react/src/components/ReactFlowProvider/index.tsx @@ -19,6 +19,40 @@ export type ReactFlowProviderProps = { children: ReactNode; }; +/** + * The `` component is a [context provider](https://react.dev/learn/passing-data-deeply-with-context#) + * that makes it possible to access a flow's internal state outside of the + * [``](/api-reference/react-flow) component. Many of the hooks we + * provide rely on this component to work. + * @public + * + * @example + * ```tsx + *import { ReactFlow, ReactFlowProvider, useNodes } from '@xyflow/react' + * + *export default function Flow() { + * return ( + * + * + * + * + * ); + *} + * + *function Sidebar() { + * // This hook will only work if the component it's used in is a child of a + * // . + * const nodes = useNodes() + * + * return ; + *} + *``` + * + * @remarks If you're using a router and want your flow's state to persist across routes, + * it's vital that you place the `` component _outside_ of + * your router. If you have multiple flows on the same page you will need to use a separate + * `` for each flow. + */ export function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, diff --git a/packages/react/src/components/SelectionListener/index.tsx b/packages/react/src/components/SelectionListener/index.tsx index 6a9a03a6..89ed2c26 100644 --- a/packages/react/src/components/SelectionListener/index.tsx +++ b/packages/react/src/components/SelectionListener/index.tsx @@ -10,8 +10,8 @@ import { shallow } from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; import type { ReactFlowState, OnSelectionChangeFunc, Node, Edge } from '../../types'; -type SelectionListenerProps = { - onSelectionChange?: OnSelectionChangeFunc; +type SelectionListenerProps = { + onSelectionChange?: OnSelectionChangeFunc; }; const selector = (s: ReactFlowState) => { @@ -44,12 +44,14 @@ function areEqual(a: SelectorSlice, b: SelectorSlice) { ); } -function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) { - const store = useStoreApi(); +function SelectionListenerInner({ + onSelectionChange, +}: SelectionListenerProps) { + const store = useStoreApi(); const { selectedNodes, selectedEdges } = useStore(selector, areEqual); useEffect(() => { - const params = { nodes: selectedNodes, edges: selectedEdges }; + const params = { nodes: selectedNodes as NodeType[], edges: selectedEdges as EdgeType[] }; onSelectionChange?.(params); store.getState().onSelectionChangeHandlers.forEach((fn) => fn(params)); @@ -60,11 +62,13 @@ function SelectionListenerInner({ onSelectionChange }: SelectionListenerProps) { const changeSelector = (s: ReactFlowState) => !!s.onSelectionChangeHandlers; -export function SelectionListener({ onSelectionChange }: SelectionListenerProps) { +export function SelectionListener({ + onSelectionChange, +}: SelectionListenerProps) { const storeHasSelectionChangeHandlers = useStore(changeSelector); if (onSelectionChange || storeHasSelectionChangeHandlers) { - return ; + return onSelectionChange={onSelectionChange} />; } return null; diff --git a/packages/react/src/components/StoreUpdater/index.tsx b/packages/react/src/components/StoreUpdater/index.tsx index cac8df0e..5cad0358 100644 --- a/packages/react/src/components/StoreUpdater/index.tsx +++ b/packages/react/src/components/StoreUpdater/index.tsx @@ -11,7 +11,7 @@ import { useStore, useStoreApi } from '../../hooks/useStore'; import type { Node, Edge, ReactFlowState, ReactFlowProps, FitViewOptions } from '../../types'; import { defaultNodeOrigin } from '../../container/ReactFlow/init-values'; -// these fields exist in the global store and we need to keep them up to date +// These fields exist in the global store, and we need to keep them up to date const reactFlowFieldsToTrack = [ 'nodes', 'edges', @@ -94,9 +94,11 @@ const selector = (s: ReactFlowState) => ({ }); const initPrevValues = { - // these are values that are also passed directly to other components - // than the StoreUpdater. We can reduce the number of setStore calls - // by setting the same values here as prev fields. + /* + * these are values that are also passed directly to other components + * than the StoreUpdater. We can reduce the number of setStore calls + * by setting the same values here as prev fields. + */ translateExtent: infiniteExtent, nodeOrigin: defaultNodeOrigin, minZoom: 0.5, @@ -152,8 +154,8 @@ export function StoreUpdater s.domNode?.querySelector('.react-flow__viewport-portal'); +/** + * The `` component can be used to add components to the same viewport + * of the flow where nodes and edges are rendered. This is useful when you want to render + * your own components that are adhere to the same coordinate system as the nodes & edges + * and are also affected by zooming and panning + * @public + * @example + * + * ```jsx + *import React from 'react'; + *import { ViewportPortal } from '@xyflow/react'; + * + *export default function () { + * return ( + * + *
+ * This div is positioned at [100, 100] on the flow. + *
+ *
+ * ); + *} + *``` + */ export function ViewportPortal({ children }: { children: ReactNode }) { const viewPortalDiv = useStore(selector); diff --git a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx index 5b6194c5..17b5950c 100644 --- a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx +++ b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx @@ -42,9 +42,11 @@ const Marker = ({ ); }; -// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore -// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper -// that we can then use for creating our unique marker ids +/* + * when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore + * when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper + * that we can then use for creating our unique marker ids + */ const MarkerDefinitions = ({ defaultColor, rfId }: MarkerDefinitionsProps) => { const edges = useStore((s) => s.edges); const defaultEdgeOptions = useStore((s) => s.defaultEdgeOptions); diff --git a/packages/react/src/container/GraphView/index.tsx b/packages/react/src/container/GraphView/index.tsx index 7356c8f4..fd0296f1 100644 --- a/packages/react/src/container/GraphView/index.tsx +++ b/packages/react/src/container/GraphView/index.tsx @@ -170,7 +170,7 @@ function GraphViewComponent - style={connectionLineStyle} type={connectionLineType} component={connectionLineComponent} diff --git a/packages/react/src/container/NodeRenderer/index.tsx b/packages/react/src/container/NodeRenderer/index.tsx index 7b0bd131..02126d73 100644 --- a/packages/react/src/container/NodeRenderer/index.tsx +++ b/packages/react/src/container/NodeRenderer/index.tsx @@ -44,29 +44,31 @@ function NodeRendererComponent(props: NodeRendererProps {nodeIds.map((nodeId) => { return ( - // The split of responsibilities between NodeRenderer and - // NodeComponentWrapper may appear weird. However, it’s designed to - // minimize the cost of updates when individual nodes change. - // - // For example, when you’re dragging a single node, that node gets - // updated multiple times per second. If `NodeRenderer` were to update - // every time, it would have to re-run the `nodes.map()` loop every - // time. This gets pricey with hundreds of nodes, especially if every - // loop cycle does more than just rendering a JSX element! - // - // As a result of this choice, we took the following implementation - // decisions: - // - NodeRenderer subscribes *only* to node IDs – and therefore - // rerender *only* when visible nodes are added or removed. - // - NodeRenderer performs all operations the result of which can be - // shared between nodes (such as creating the `ResizeObserver` - // instance, or subscribing to `selector`). This means extra prop - // drilling into `NodeComponentWrapper`, but it means we need to run - // these operations only once – instead of once per node. - // - Any operations that you’d normally write inside `nodes.map` are - // moved into `NodeComponentWrapper`. This ensures they are - // memorized – so if `NodeRenderer` *has* to rerender, it only - // needs to regenerate the list of nodes, nothing else. + /* + * The split of responsibilities between NodeRenderer and + * NodeComponentWrapper may appear weird. However, it’s designed to + * minimize the cost of updates when individual nodes change. + * + * For example, when you’re dragging a single node, that node gets + * updated multiple times per second. If `NodeRenderer` were to update + * every time, it would have to re-run the `nodes.map()` loop every + * time. This gets pricey with hundreds of nodes, especially if every + * loop cycle does more than just rendering a JSX element! + * + * As a result of this choice, we took the following implementation + * decisions: + * - NodeRenderer subscribes *only* to node IDs – and therefore + * rerender *only* when visible nodes are added or removed. + * - NodeRenderer performs all operations the result of which can be + * shared between nodes (such as creating the `ResizeObserver` + * instance, or subscribing to `selector`). This means extra prop + * drilling into `NodeComponentWrapper`, but it means we need to run + * these operations only once – instead of once per node. + * - Any operations that you’d normally write inside `nodes.map` are + * moved into `NodeComponentWrapper`. This ensures they are + * memorized – so if `NodeRenderer` *has* to rerender, it only + * needs to regenerate the list of nodes, nothing else. + */ key={nodeId} id={nodeId} diff --git a/packages/react/src/container/Pane/index.tsx b/packages/react/src/container/Pane/index.tsx index aeadde03..4d2e392a 100644 --- a/packages/react/src/container/Pane/index.tsx +++ b/packages/react/src/container/Pane/index.tsx @@ -61,6 +61,7 @@ const wrapHandler = ( const selector = (s: ReactFlowState) => ({ userSelectionActive: s.userSelectionActive, elementsSelectable: s.elementsSelectable, + connectionInProgress: s.connection.inProgress, dragging: s.paneDragging, }); @@ -81,7 +82,7 @@ export function Pane({ children, }: PaneProps) { const store = useStoreApi(); - const { userSelectionActive, elementsSelectable, dragging } = useStore(selector, shallow); + const { userSelectionActive, elementsSelectable, dragging, connectionInProgress } = useStore(selector, shallow); const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive); const container = useRef(null); @@ -96,7 +97,8 @@ export function Pane({ const onClick = (event: ReactMouseEvent) => { // We prevent click events when the user let go of the selectionKey during a selection - if (selectionInProgress.current) { + // We also prevent click events when a connection is in progress + if (selectionInProgress.current || connectionInProgress) { selectionInProgress.current = false; return; } @@ -233,8 +235,10 @@ export function Pane({ (event.target as Partial)?.releasePointerCapture?.(event.pointerId); const { userSelectionRect } = store.getState(); - // We only want to trigger click functions when in selection mode if - // the user did not move the mouse. + /* + * We only want to trigger click functions when in selection mode if + * the user did not move the mouse. + */ if (!userSelectionActive && userSelectionRect && event.target === container.current) { onClick?.(event); } @@ -246,8 +250,10 @@ export function Pane({ }); onSelectionEnd?.(event); - // If the user kept holding the selectionKey during the selection, - // we need to reset the selectionInProgress, so the next click event is not prevented + /* + * If the user kept holding the selectionKey during the selection, + * we need to reset the selectionInProgress, so the next click event is not prevented + */ if (selectionKeyPressed || selectionOnDrag) { selectionInProgress.current = false; } diff --git a/packages/react/src/container/ReactFlow/Wrapper.tsx b/packages/react/src/container/ReactFlow/Wrapper.tsx index 5856809a..71a84316 100644 --- a/packages/react/src/container/ReactFlow/Wrapper.tsx +++ b/packages/react/src/container/ReactFlow/Wrapper.tsx @@ -31,8 +31,10 @@ export function Wrapper({ const isWrapped = useContext(StoreContext); if (isWrapped) { - // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode - // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051 + /* + * we need to wrap it with a fragment because it's not allowed for children to be a ReactNode + * https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051 + */ return <>{children}; } diff --git a/packages/react/src/container/ReactFlow/index.tsx b/packages/react/src/container/ReactFlow/index.tsx index 82206fc8..31389887 100644 --- a/packages/react/src/container/ReactFlow/index.tsx +++ b/packages/react/src/container/ReactFlow/index.tsx @@ -1,4 +1,4 @@ -import { ForwardedRef, type CSSProperties } from 'react'; +import { ForwardedRef, useCallback, type CSSProperties } from 'react'; import cc from 'classcat'; import { ConnectionLineType, PanOnScrollMode, SelectionMode, infiniteExtent, isMacOs } from '@xyflow/system'; @@ -144,6 +144,7 @@ function ReactFlow( height, colorMode = 'light', debug, + onScroll, ...rest }: ReactFlowProps, ref: ForwardedRef @@ -151,10 +152,20 @@ function ReactFlow( const rfId = id || '1'; const colorModeClassName = useColorModeClass(colorMode); + // Undo scroll events, preventing viewport from shifting when nodes outside of it are focused + const wrapperOnScroll = useCallback( + (e: React.UIEvent) => { + e.currentTarget.scrollTo({ top: 0, left: 0, behavior: 'instant' }); + onScroll?.(e); + }, + [onScroll] + ); + return (
( paneClickDistance={paneClickDistance} debug={debug} /> - + onSelectionChange={onSelectionChange} /> {children} @@ -301,4 +312,24 @@ function ReactFlow( ); } +/** + * The `` component is the heart of your React Flow application. + * It renders your nodes and edges and handles user interaction + * + * @public + * + * @example + * ```tsx + *import { ReactFlow } from '@xyflow/react' + * + *export default function Flow() { + * return (); + *} + *``` + */ export default fixedForwardRef(ReactFlow); diff --git a/packages/react/src/container/ZoomPane/index.tsx b/packages/react/src/container/ZoomPane/index.tsx index 35fbb248..61af78e6 100644 --- a/packages/react/src/container/ZoomPane/index.tsx +++ b/packages/react/src/container/ZoomPane/index.tsx @@ -95,7 +95,7 @@ export function ZoomPane({ }, }); - const { x, y, zoom } = panZoom.current!.getViewport(); + const { x, y, zoom } = panZoom.current.getViewport(); store.setState({ panZoom: panZoom.current, diff --git a/packages/react/src/contexts/NodeIdContext.ts b/packages/react/src/contexts/NodeIdContext.ts index 28a14b78..4fdef045 100644 --- a/packages/react/src/contexts/NodeIdContext.ts +++ b/packages/react/src/contexts/NodeIdContext.ts @@ -4,6 +4,34 @@ export const NodeIdContext = createContext(null); export const Provider = NodeIdContext.Provider; export const Consumer = NodeIdContext.Consumer; +/** + * You can use this hook to get the id of the node it is used inside. It is useful + * if you need the node's id deeper in the render tree but don't want to manually + * drill down the id as a prop. + * + * @public + * @returns The id for a node in the flow. + * + * @example + *```jsx + *import { useNodeId } from '@xyflow/react'; + * + *export default function CustomNode() { + * return ( + *
+ * This node has an id of + * + *
+ * ); + *} + * + *function NodeIdDisplay() { + * const nodeId = useNodeId(); + * + * return {nodeId}; + *} + *``` + */ export const useNodeId = (): string | null => { const nodeId = useContext(NodeIdContext); return nodeId; diff --git a/packages/react/src/hooks/useConnection.ts b/packages/react/src/hooks/useConnection.ts index 94db5140..7c748003 100644 --- a/packages/react/src/hooks/useConnection.ts +++ b/packages/react/src/hooks/useConnection.ts @@ -24,9 +24,32 @@ function getSelector {connection ? `Someone is trying to make a connection from ${connection.fromNode} to this one.` : 'There are currently no incoming connections!'} + * + *
+ * ); + * } + * ``` + * * @returns ConnectionState */ export function useConnection>>( diff --git a/packages/react/src/hooks/useEdges.ts b/packages/react/src/hooks/useEdges.ts index 3ed9de39..46db9939 100644 --- a/packages/react/src/hooks/useEdges.ts +++ b/packages/react/src/hooks/useEdges.ts @@ -6,10 +6,22 @@ import type { Edge, ReactFlowState } from '../types'; const edgesSelector = (state: ReactFlowState) => state.edges; /** - * Hook for getting the current edges from the store. + * This hook returns an array of the current edges. Components that use this hook + * will re-render **whenever any edge changes**. * * @public - * @returns An array of edges + * @returns An array of all edges currently in the flow. + * + * @example + * ```tsx + *import { useEdges } from '@xyflow/react'; + * + *export default function () { + * const edges = useEdges(); + * + * return
There are currently {edges.length} edges!
; + *} + *``` */ export function useEdges(): EdgeType[] { const edges = useStore(edgesSelector, shallow) as EdgeType[]; diff --git a/packages/react/src/hooks/useHandleConnections.ts b/packages/react/src/hooks/useHandleConnections.ts index cad87715..a53eb2c7 100644 --- a/packages/react/src/hooks/useHandleConnections.ts +++ b/packages/react/src/hooks/useHandleConnections.ts @@ -10,11 +10,16 @@ import { import { useStore } from './useStore'; import { useNodeId } from '../contexts/NodeIdContext'; -type useHandleConnectionsParams = { +type UseHandleConnectionsParams = { + /** What type of handle connections do you want to observe? */ type: HandleType; + /** The handle id (this is only needed if the node has multiple handles of the same type). */ id?: string | null; + /** If node id is not provided, the node id from the `NodeIdContext` is used. */ nodeId?: string; + /** Gets called when a connection is established. */ onConnect?: (connections: Connection[]) => void; + /** Gets called when a connection is removed. */ onDisconnect?: (connections: Connection[]) => void; }; @@ -23,12 +28,7 @@ type useHandleConnectionsParams = { * * @public * @deprecated Use `useNodeConnections` instead. - * @param param.type - handle type 'source' or 'target' - * @param param.nodeId - node id - if not provided, the node id from the NodeIdContext is used - * @param param.id - the handle id (this is only needed if the node has multiple handles of the same type) - * @param param.onConnect - gets called when a connection is established - * @param param.onDisconnect - gets called when a connection is removed - * @returns an array with handle connections + * @returns An array with handle connections. */ export function useHandleConnections({ type, @@ -36,7 +36,7 @@ export function useHandleConnections({ nodeId, onConnect, onDisconnect, -}: useHandleConnectionsParams): HandleConnection[] { +}: UseHandleConnectionsParams): HandleConnection[] { console.warn( '[DEPRECATED] `useHandleConnections` is deprecated. Instead use `useNodeConnections` https://reactflow.dev/api-reference/hooks/useNodeConnections' ); diff --git a/packages/react/src/hooks/useInternalNode.ts b/packages/react/src/hooks/useInternalNode.ts index d16d697b..a4678aaa 100644 --- a/packages/react/src/hooks/useInternalNode.ts +++ b/packages/react/src/hooks/useInternalNode.ts @@ -5,11 +5,31 @@ import { useStore } from './useStore'; import type { InternalNode, Node } from '../types'; /** - * Hook for getting an internal node by id + * This hook returns the internal representation of a specific node. + * Components that use this hook will re-render **whenever the node changes**, + * including when a node is selected or moved. * * @public - * @param id - id of the node - * @returns array with visible node ids + * @param id - The ID of a node you want to observe. + * @returns The `InternalNode` object for the node with the given ID. + * + * @example + * ```tsx + *import { useInternalNode } from '@xyflow/react'; + * + *export default function () { + * const internalNode = useInternalNode('node-1'); + * const absolutePosition = internalNode.internals.positionAbsolute; + * + * return ( + *
+ * The absolute position of the node is at: + *

x: {absolutePosition.x}

+ *

y: {absolutePosition.y}

+ *
+ * ); + *} + *``` */ export function useInternalNode(id: string): InternalNode | undefined { const node = useStore( diff --git a/packages/react/src/hooks/useKeyPress.ts b/packages/react/src/hooks/useKeyPress.ts index 8bce0564..d378dab7 100644 --- a/packages/react/src/hooks/useKeyPress.ts +++ b/packages/react/src/hooks/useKeyPress.ts @@ -6,25 +6,58 @@ type PressedKeys = Set; type KeyOrCode = 'key' | 'code'; export type UseKeyPressOptions = { + /** + * Listen to key presses on a specific element. + * @default document + */ target?: Window | Document | HTMLElement | ShadowRoot | null; + /** + * You can use this flag to prevent triggering the key press hook when an input field is focused. + * @default true + */ actInsideInputWithModifier?: boolean; + preventDefault?: boolean; }; const defaultDoc = typeof document !== 'undefined' ? document : null; /** - * Hook for handling key events. + * This hook lets you listen for specific key codes and tells you whether they are + * currently pressed or not. * * @public - * @param param.keyCode - The key code (string or array of strings) to use - * @param param.options - Options - * @returns boolean + * @param options - Options + * + * @example + * ```tsx + *import { useKeyPress } from '@xyflow/react'; + * + *export default function () { + * const spacePressed = useKeyPress('Space'); + * const cmdAndSPressed = useKeyPress(['Meta+s', 'Strg+s']); + * + * return ( + *
+ * {spacePressed &&

Space pressed!

} + * {cmdAndSPressed &&

Cmd + S pressed!

} + *
+ * ); + *} + *``` */ export function useKeyPress( - // the keycode can be a string 'a' or an array of strings ['a', 'a+d'] - // a string means a single key 'a' or a combination when '+' is used 'a+d' - // an array means different possibilites. Explainer: ['a', 'd+s'] here the - // user can use the single key 'a' or the combination 'd' + 's' + /** + * The key code (string or array of strings) specifies which key(s) should trigger + * an action. + * + * A **string** can represent: + * - A **single key**, e.g. `'a'` + * - A **key combination**, using `'+'` to separate keys, e.g. `'a+d'` + * + * An **array of strings** represents **multiple possible key inputs**. For example, `['a', 'd+s']` + * means the user can press either the single key `'a'` or the combination of `'d'` and `'s'`. + * @default null + */ keyCode: KeyCode | null = null, options: UseKeyPressOptions = { target: defaultDoc, actInsideInputWithModifier: true } ): boolean { @@ -36,20 +69,24 @@ export function useKeyPress( // we need to remember the pressed keys in order to support combinations const pressedKeys = useRef(new Set([])); - // keyCodes = array with single keys [['a']] or key combinations [['a', 's']] - // keysToWatch = array with all keys flattened ['a', 'd', 'ShiftLeft'] - // used to check if we store event.code or event.key. When the code is in the list of keysToWatch - // we use the code otherwise the key. Explainer: When you press the left "command" key, the code is "MetaLeft" - // and the key is "Meta". We want users to be able to pass keys and codes so we assume that the key is meant when - // we can't find it in the list of keysToWatch. + /* + * keyCodes = array with single keys [['a']] or key combinations [['a', 's']] + * keysToWatch = array with all keys flattened ['a', 'd', 'ShiftLeft'] + * used to check if we store event.code or event.key. When the code is in the list of keysToWatch + * we use the code otherwise the key. Explainer: When you press the left "command" key, the code is "MetaLeft" + * and the key is "Meta". We want users to be able to pass keys and codes so we assume that the key is meant when + * we can't find it in the list of keysToWatch. + */ const [keyCodes, keysToWatch] = useMemo<[Array, Keys]>(() => { if (keyCode !== null) { const keyCodeArr = Array.isArray(keyCode) ? keyCode : [keyCode]; const keys = keyCodeArr .filter((kc) => typeof kc === 'string') - // we first replace all '+' with '\n' which we will use to split the keys on - // then we replace '\n\n' with '\n+', this way we can also support the combination 'key++' - // in the end we simply split on '\n' to get the key array + /* + * we first replace all '+' with '\n' which we will use to split the keys on + * then we replace '\n\n' with '\n+', this way we can also support the combination 'key++' + * in the end we simply split on '\n' to get the key array + */ .map((kc) => kc.replace('+', '\n').replace('\n\n', '\n+').split('\n')); const keysFlat = keys.reduce((res: Keys, item) => res.concat(...item), []); @@ -64,7 +101,7 @@ export function useKeyPress( if (keyCode !== null) { const downHandler = (event: KeyboardEvent) => { - modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey; + modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey || event.altKey; const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) && isInputDOMNode(event); @@ -76,19 +113,18 @@ export function useKeyPress( pressedKeys.current.add(event[keyOrCode]); if (isMatchingKey(keyCodes, pressedKeys.current, false)) { - event.preventDefault(); + const target = (event.composedPath?.()?.[0] || event.target) as Element | null; + const isInteractiveElement = target?.nodeName === 'BUTTON' || target?.nodeName === 'A'; + + if (options.preventDefault !== false && (modifierPressed.current || !isInteractiveElement)) { + event.preventDefault(); + } + setKeyPressed(true); } }; const upHandler = (event: KeyboardEvent) => { - const preventAction = - (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) && - isInputDOMNode(event); - - if (preventAction) { - return false; - } const keyOrCode = useKeyOrCode(event.code, keysToWatch); if (isMatchingKey(keyCodes, pressedKeys.current, true)) { @@ -133,12 +169,16 @@ export function useKeyPress( function isMatchingKey(keyCodes: Array, pressedKeys: PressedKeys, isUp: boolean): boolean { return ( keyCodes - // we only want to compare same sizes of keyCode definitions - // and pressed keys. When the user specified 'Meta' as a key somewhere - // this would also be truthy without this filter when user presses 'Meta' + 'r' + /* + * we only want to compare same sizes of keyCode definitions + * and pressed keys. When the user specified 'Meta' as a key somewhere + * this would also be truthy without this filter when user presses 'Meta' + 'r' + */ .filter((keys) => isUp || keys.length === pressedKeys.size) - // since we want to support multiple possibilities only one of the - // combinations need to be part of the pressed keys + /* + * since we want to support multiple possibilities only one of the + * combinations need to be part of the pressed keys + */ .some((keys) => keys.every((k) => pressedKeys.has(k))) ); } diff --git a/packages/react/src/hooks/useMoveSelectedNodes.ts b/packages/react/src/hooks/useMoveSelectedNodes.ts index 52503c04..0b2dacc9 100644 --- a/packages/react/src/hooks/useMoveSelectedNodes.ts +++ b/packages/react/src/hooks/useMoveSelectedNodes.ts @@ -22,8 +22,10 @@ export function useMoveSelectedNodes() { const nodeUpdates = new Map(); const isSelected = selectedAndDraggable(nodesDraggable); - // by default a node moves 5px on each key press - // if snap grid is enabled, we use that for the velocity + /* + * by default a node moves 5px on each key press + * if snap grid is enabled, we use that for the velocity + */ const xVelo = snapToGrid ? snapGrid[0] : 5; const yVelo = snapToGrid ? snapGrid[1] : 5; diff --git a/packages/react/src/hooks/useNodeConnections.ts b/packages/react/src/hooks/useNodeConnections.ts index c83a7366..6a8155ab 100644 --- a/packages/react/src/hooks/useNodeConnections.ts +++ b/packages/react/src/hooks/useNodeConnections.ts @@ -14,23 +14,39 @@ import { useNodeId } from '../contexts/NodeIdContext'; const error014 = errorMessages['error014'](); type UseNodeConnectionsParams = { + /** ID of the node, filled in automatically if used inside custom node. */ id?: string; + /** What type of handle connections do you want to observe? */ handleType?: HandleType; + /** Filter by handle id (this is only needed if the node has multiple handles of the same type). */ handleId?: string; + /** Gets called when a connection is established. */ onConnect?: (connections: Connection[]) => void; + /** Gets called when a connection is removed. */ onDisconnect?: (connections: Connection[]) => void; }; /** - * Hook to retrieve all edges connected to a node. Can be filtered by handle type and id. + * This hook returns an array of connections on a specific node, handle type ('source', 'target') or handle ID. * * @public - * @param param.id - node id - optional if called inside a custom node - * @param param.handleType - filter by handle type 'source' or 'target' - * @param param.handleId - filter by handle id (this is only needed if the node has multiple handles of the same type) - * @param param.onConnect - gets called when a connection is established - * @param param.onDisconnect - gets called when a connection is removed - * @returns an array with connections + * @returns An array with connections. + * + * @example + * ```jsx + *import { useNodeConnections } from '@xyflow/react'; + * + *export default function () { + * const connections = useNodeConnections({ + * handleType: 'target', + * handleId: 'my-handle', + * }); + * + * return ( + *
There are currently {connections.length} incoming connections!
+ * ); + *} + *``` */ export function useNodeConnections({ id, @@ -57,7 +73,7 @@ export function useNodeConnections({ ); useEffect(() => { - // @todo dicuss if onConnect/onDisconnect should be called when the component mounts/unmounts + // @todo discuss if onConnect/onDisconnect should be called when the component mounts/unmounts if (prevConnections.current && prevConnections.current !== connections) { const _connections = connections ?? new Map(); handleConnectionChange(prevConnections.current, _connections, onDisconnect); diff --git a/packages/react/src/hooks/useNodes.ts b/packages/react/src/hooks/useNodes.ts index 5e558e90..6166327d 100644 --- a/packages/react/src/hooks/useNodes.ts +++ b/packages/react/src/hooks/useNodes.ts @@ -6,10 +6,23 @@ import type { Node, ReactFlowState } from '../types'; const nodesSelector = (state: ReactFlowState) => state.nodes; /** - * Hook for getting the current nodes from the store. + * This hook returns an array of the current nodes. Components that use this hook + * will re-render **whenever any node changes**, including when a node is selected + * or moved. * * @public - * @returns An array of nodes + * @returns An array of all nodes currently in the flow. + * + * @example + * ```jsx + *import { useNodes } from '@xyflow/react'; + * + *export default function() { + * const nodes = useNodes(); + * + * return
There are currently {nodes.length} nodes!
; + *} + *``` */ export function useNodes(): NodeType[] { const nodes = useStore(nodesSelector, shallow) as NodeType[]; diff --git a/packages/react/src/hooks/useNodesData.ts b/packages/react/src/hooks/useNodesData.ts index 7472cbf7..6503f405 100644 --- a/packages/react/src/hooks/useNodesData.ts +++ b/packages/react/src/hooks/useNodesData.ts @@ -5,17 +5,31 @@ import { useStore } from '../hooks/useStore'; import type { Node } from '../types'; /** - * Hook for receiving data of one or multiple nodes + * This hook lets you subscribe to changes of a specific nodes `data` object. * * @public - * @param nodeId - The id (or ids) of the node to get the data from - * @param guard - Optional guard function to narrow down the node type - * @returns An object (or array of object) with {id, type, data} representing each node + * @returns An object (or array of object) with `id`, `type`, `data` representing each node. + * + * @example + *```jsx + *import { useNodesData } from '@xyflow/react'; + * + *export default function() { + * const nodeData = useNodesData('nodeId-1'); + * const nodesData = useNodesData(['nodeId-1', 'nodeId-2']); + * + * return null; + *} + *``` */ export function useNodesData( + /** The id of the node to get the data from. */ nodeId: string ): Pick | null; -export function useNodesData(nodeIds: string[]): Pick[]; +export function useNodesData( + /** The ids of the nodes to get the data from. */ + nodeIds: string[] +): Pick[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function useNodesData(nodeIds: any): any { const nodesData = useStore( diff --git a/packages/react/src/hooks/useNodesEdgesState.ts b/packages/react/src/hooks/useNodesEdgesState.ts index fae87c02..21d9d108 100644 --- a/packages/react/src/hooks/useNodesEdgesState.ts +++ b/packages/react/src/hooks/useNodesEdgesState.ts @@ -4,15 +4,58 @@ import { applyNodeChanges, applyEdgeChanges } from '../utils/changes'; import type { Node, Edge, OnNodesChange, OnEdgesChange } from '../types'; /** - * Hook for managing the state of nodes - should only be used for prototyping / simple use cases. + * This hook makes it easy to prototype a controlled flow where you manage the + * state of nodes and edges outside the `ReactFlowInstance`. You can think of it + * like React's `useState` hook with an additional helper callback. * * @public - * @param initialNodes - * @returns an array [nodes, setNodes, onNodesChange] + * @returns + * - `nodes`: The current array of nodes. You might pass this directly to the `nodes` prop of your + * `` component, or you may want to manipulate it first to perform some layouting, + * for example. + * - `setNodes`: A function that you can use to update the nodes. You can pass it a new array of + * nodes or a callback that receives the current array of nodes and returns a new array of nodes. + * This is the same as the second element of the tuple returned by React's `useState` hook. + * - `onNodesChange`: A handy callback that can take an array of `NodeChanges` and update the nodes + * state accordingly. You'll typically pass this directly to the `onNodesChange` prop of your + * `` component. + * @example + * + *```tsx + *import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react'; + * + *const initialNodes = []; + *const initialEdges = []; + * + *export default function () { + * const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); + * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); + * + * return ( + * + * ); + *} + *``` + * + * @remarks This hook was created to make prototyping easier and our documentation + * examples clearer. Although it is OK to use this hook in production, in + * practice you may want to use a more sophisticated state management solution + * like Zustand {@link https://reactflow.dev/docs/guides/state-management/} instead. + * */ export function useNodesState( initialNodes: NodeType[] -): [NodeType[], Dispatch>, OnNodesChange] { +): [ + // + nodes: NodeType[], + setNodes: Dispatch>, + onNodesChange: OnNodesChange +] { const [nodes, setNodes] = useState(initialNodes); const onNodesChange: OnNodesChange = useCallback( (changes) => setNodes((nds) => applyNodeChanges(changes, nds)), @@ -23,15 +66,60 @@ export function useNodesState( } /** - * Hook for managing the state of edges - should only be used for prototyping / simple use cases. + * This hook makes it easy to prototype a controlled flow where you manage the + * state of nodes and edges outside the `ReactFlowInstance`. You can think of it + * like React's `useState` hook with an additional helper callback. * * @public - * @param initialEdges - * @returns an array [edges, setEdges, onEdgesChange] + * @returns + * - `edges`: The current array of edges. You might pass this directly to the `edges` prop of your + * `` component, or you may want to manipulate it first to perform some layouting, + * for example. + * + * - `setEdges`: A function that you can use to update the edges. You can pass it a new array of + * edges or a callback that receives the current array of edges and returns a new array of edges. + * This is the same as the second element of the tuple returned by React's `useState` hook. + * + * - `onEdgesChange`: A handy callback that can take an array of `EdgeChanges` and update the edges + * state accordingly. You'll typically pass this directly to the `onEdgesChange` prop of your + * `` component. + * @example + * + *```tsx + *import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react'; + * + *const initialNodes = []; + *const initialEdges = []; + * + *export default function () { + * const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); + * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); + * + * return ( + * + * ); + *} + *``` + * + * @remarks This hook was created to make prototyping easier and our documentation + * examples clearer. Although it is OK to use this hook in production, in + * practice you may want to use a more sophisticated state management solution + * like Zustand {@link https://reactflow.dev/docs/guides/state-management/} instead. + * */ export function useEdgesState( initialEdges: EdgeType[] -): [EdgeType[], Dispatch>, OnEdgesChange] { +): [ + // + edges: EdgeType[], + setEdges: Dispatch>, + onEdgesChange: OnEdgesChange +] { const [edges, setEdges] = useState(initialEdges); const onEdgesChange: OnEdgesChange = useCallback( (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)), diff --git a/packages/react/src/hooks/useNodesInitialized.ts b/packages/react/src/hooks/useNodesInitialized.ts index 98bfa6b7..a44ab658 100644 --- a/packages/react/src/hooks/useNodesInitialized.ts +++ b/packages/react/src/hooks/useNodesInitialized.ts @@ -1,8 +1,10 @@ -import { useStore } from './useStore'; -import type { ReactFlowState } from '../types'; import { nodeHasDimensions } from '@xyflow/system'; +import { useStore } from './useStore'; +import type { ReactFlowState } from '../types'; + export type UseNodesInitializedOptions = { + /** @default false */ includeHiddenNodes?: boolean; }; @@ -22,18 +24,44 @@ const selector = (options: UseNodesInitializedOptions) => (s: ReactFlowState) => return true; }; -const defaultOptions = { - includeHiddenNodes: false, -}; - /** - * Hook which returns true when all nodes are initialized. + * This hook tells you whether all the nodes in a flow have been measured and given + *a width and height. When you add a node to the flow, this hook will return + *`false` and then `true` again once the node has been measured. * * @public - * @param options.includeHiddenNodes - defaults to false - * @returns boolean indicating whether all nodes are initialized + * @returns Whether or not the nodes have been initialized by the `` component and + * given a width and height. + * + * @example + * ```jsx + *import { useReactFlow, useNodesInitialized } from '@xyflow/react'; + *import { useEffect, useState } from 'react'; + * + *const options = { + * includeHiddenNodes: false, + *}; + * + *export default function useLayout() { + * const { getNodes } = useReactFlow(); + * const nodesInitialized = useNodesInitialized(options); + * const [layoutedNodes, setLayoutedNodes] = useState(getNodes()); + * + * useEffect(() => { + * if (nodesInitialized) { + * setLayoutedNodes(yourLayoutingFunction(getNodes())); + * } + * }, [nodesInitialized]); + * + * return layoutedNodes; + *} + *``` */ -export function useNodesInitialized(options: UseNodesInitializedOptions = defaultOptions): boolean { +export function useNodesInitialized( + options: UseNodesInitializedOptions = { + includeHiddenNodes: false, + } +): boolean { const initialized = useStore(selector(options)); return initialized; diff --git a/packages/react/src/hooks/useOnSelectionChange.ts b/packages/react/src/hooks/useOnSelectionChange.ts index 8e08191b..feff9fe3 100644 --- a/packages/react/src/hooks/useOnSelectionChange.ts +++ b/packages/react/src/hooks/useOnSelectionChange.ts @@ -1,20 +1,53 @@ import { useEffect } from 'react'; import { useStoreApi } from './useStore'; -import type { OnSelectionChangeFunc } from '../types'; +import type { OnSelectionChangeFunc, Node, Edge } from '../types'; -export type UseOnSelectionChangeOptions = { - onChange: OnSelectionChangeFunc; +export type UseOnSelectionChangeOptions = { + /** The handler to register. */ + onChange: OnSelectionChangeFunc; }; /** - * Hook for registering an onSelectionChange handler. + * This hook lets you listen for changes to both node and edge selection. As the + *name implies, the callback you provide will be called whenever the selection of + *_either_ nodes or edges changes. * * @public - * @param params.onChange - The handler to register + * @example + * ```jsx + *import { useState } from 'react'; + *import { ReactFlow, useOnSelectionChange } from '@xyflow/react'; + * + *function SelectionDisplay() { + * const [selectedNodes, setSelectedNodes] = useState([]); + * const [selectedEdges, setSelectedEdges] = useState([]); + * + * // the passed handler has to be memoized, otherwise the hook will not work correctly + * const onChange = useCallback(({ nodes, edges }) => { + * setSelectedNodes(nodes.map((node) => node.id)); + * setSelectedEdges(edges.map((edge) => edge.id)); + * }, []); + * + * useOnSelectionChange({ + * onChange, + * }); + * + * return ( + *
+ *

Selected nodes: {selectedNodes.join(', ')}

+ *

Selected edges: {selectedEdges.join(', ')}

+ *
+ * ); + *} + *``` + * + * @remarks You need to memoize the passed `onChange` handler, otherwise the hook will not work correctly. */ -export function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { - const store = useStoreApi(); +export function useOnSelectionChange({ + onChange, +}: UseOnSelectionChangeOptions) { + const store = useStoreApi(); useEffect(() => { const nextOnSelectionChangeHandlers = [...store.getState().onSelectionChangeHandlers, onChange]; diff --git a/packages/react/src/hooks/useOnViewportChange.ts b/packages/react/src/hooks/useOnViewportChange.ts index 61e4d64f..9a13c4fb 100644 --- a/packages/react/src/hooks/useOnViewportChange.ts +++ b/packages/react/src/hooks/useOnViewportChange.ts @@ -4,18 +4,35 @@ import type { OnViewportChange } from '@xyflow/system'; import { useStoreApi } from './useStore'; export type UseOnViewportChangeOptions = { + /** Gets called when the viewport starts changing. */ onStart?: OnViewportChange; + /** Gets called when the viewport changes. */ onChange?: OnViewportChange; + /** Gets called when the viewport stops changing. */ onEnd?: OnViewportChange; }; /** - * Hook for registering an onViewportChange handler. + * The `useOnViewportChange` hook lets you listen for changes to the viewport such + * as panning and zooming. You can provide a callback for each phase of a viewport + * change: `onStart`, `onChange`, and `onEnd`. * * @public - * @param params.onStart - gets called when the viewport starts changing - * @param params.onChange - gets called when the viewport changes - * @param params.onEnd - gets called when the viewport stops changing + * @example + * ```jsx + *import { useCallback } from 'react'; + *import { useOnViewportChange } from '@xyflow/react'; + * + *function ViewportChangeLogger() { + * useOnViewportChange({ + * onStart: (viewport: Viewport) => console.log('start', viewport), + * onChange: (viewport: Viewport) => console.log('change', viewport), + * onEnd: (viewport: Viewport) => console.log('end', viewport), + * }); + * + * return null; + *} + *``` */ export function useOnViewportChange({ onStart, onChange, onEnd }: UseOnViewportChangeOptions) { const store = useStoreApi(); diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts index 3d857cfa..2cfc3430 100644 --- a/packages/react/src/hooks/useReactFlow.ts +++ b/packages/react/src/hooks/useReactFlow.ts @@ -15,15 +15,44 @@ import useViewportHelper from './useViewportHelper'; import { useStore, useStoreApi } from './useStore'; import { useBatchContext } from '../components/BatchProvider'; import { elementToRemoveChange, isEdge, isNode } from '../utils'; -import type { ReactFlowInstance, Node, Edge, InternalNode, ReactFlowState, GeneralHelpers } from '../types'; +import type { + ReactFlowInstance, + Node, + Edge, + InternalNode, + ReactFlowState, + GeneralHelpers, + FitViewOptions, +} from '../types'; const selector = (s: ReactFlowState) => !!s.panZoom; /** - * Hook for accessing the ReactFlow instance. + * This hook returns a ReactFlowInstance that can be used to update nodes and edges, manipulate the viewport, or query the current state of the flow. * * @public - * @returns ReactFlowInstance + * @example + * ```jsx + *import { useCallback, useState } from 'react'; + *import { useReactFlow } from '@xyflow/react'; + * + *export function NodeCounter() { + * const reactFlow = useReactFlow(); + * const [count, setCount] = useState(0); + * const countNodes = useCallback(() => { + * setCount(reactFlow.getNodes().length); + * // you need to pass it as a dependency if you are using it with useEffect or useCallback + * // because at the first render, it's not initialized yet and some functions might not work. + * }, [reactFlow]); + * + * return ( + *
+ * + *

There are {count} nodes in the flow.

+ *
+ * ); + *} + *``` */ export function useReactFlow(): ReactFlowInstance< NodeType, @@ -72,7 +101,7 @@ export function useReactFlow prevNodes.map((node) => { if (node.id === id) { - const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node as NodeType) : nodeUpdate; + const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node) : nodeUpdate; return options.replace && isNode(nextNode) ? (nextNode as NodeType) : { ...node, ...nextNode }; } @@ -89,7 +118,7 @@ export function useReactFlow prevEdges.map((edge) => { if (edge.id === id) { - const nextEdge = typeof edgeUpdate === 'function' ? edgeUpdate(edge as EdgeType) : edgeUpdate; + const nextEdge = typeof edgeUpdate === 'function' ? edgeUpdate(edge) : edgeUpdate; return options.replace && isEdge(nextEdge) ? (nextEdge as EdgeType) : { ...edge, ...nextEdge }; } @@ -184,7 +213,7 @@ export function useReactFlow { const internalNode = store.getState().nodeLookup.get(n.id); - if (internalNode && !isRect && (n.id === nodeOrRect!.id || !internalNode.internals.positionAbsolute)) { + if (internalNode && !isRect && (n.id === nodeOrRect.id || !internalNode.internals.positionAbsolute)) { return false; } @@ -248,6 +277,17 @@ export function useReactFlow | undefined) => { + // We either create a new Promise or reuse the existing one + // Even if fitView is called multiple times in a row, we only end up with a single Promise + const fitViewResolver = store.getState().fitViewResolver ?? Promise.withResolvers(); + + // We schedule a fitView by setting fitViewQueued and triggering a setNodes + store.setState({ fitViewQueued: true, fitViewOptions: options, fitViewResolver }); + batchContext.nodeQueue.push((nodes) => [...nodes]); + + return fitViewResolver.promise; + }, }; }, []); diff --git a/packages/react/src/hooks/useResizeHandler.ts b/packages/react/src/hooks/useResizeHandler.ts index 2db37499..4348208a 100644 --- a/packages/react/src/hooks/useResizeHandler.ts +++ b/packages/react/src/hooks/useResizeHandler.ts @@ -16,7 +16,7 @@ export function useResizeHandler(domNode: MutableRefObject) => state.nodes); + * ```ts + * const nodes = useStore((state) => state.nodes); + * ``` * + * @remarks This hook should only be used if there is no other way to access the internal + * state. For many of the common use cases, there are dedicated hooks available + * such as {@link useReactFlow}, {@link useViewport}, etc. */ function useStore( selector: (state: ReactFlowState) => StateSlice, @@ -33,6 +44,19 @@ function useStore( return useZustandStore(store, selector, equalityFn); } +/** + * In some cases, you might need to access the store directly. This hook returns the store object which can be used on demand to access the state or dispatch actions. + * + * @returns The store object. + * @example + * ```ts + * const store = useStoreApi(); + * ``` + * + * @remarks This hook should only be used if there is no other way to access the internal + * state. For many of the common use cases, there are dedicated hooks available + * such as {@link useReactFlow}, {@link useViewport}, etc. + */ function useStoreApi() { const store = useContext(StoreContext) as UseBoundStoreWithEqualityFn< StoreApi> diff --git a/packages/react/src/hooks/useUpdateNodeInternals.ts b/packages/react/src/hooks/useUpdateNodeInternals.ts index 6486afd8..55765b80 100644 --- a/packages/react/src/hooks/useUpdateNodeInternals.ts +++ b/packages/react/src/hooks/useUpdateNodeInternals.ts @@ -4,10 +4,49 @@ import type { UpdateNodeInternals, InternalNodeUpdate } from '@xyflow/system'; import { useStoreApi } from '../hooks/useStore'; /** - * Hook for updating node internals. + * When you programmatically add or remove handles to a node or update a node's + * handle position, you need to let React Flow know about it using this hook. This + * will update the internal dimensions of the node and properly reposition handles + * on the canvas if necessary. * * @public - * @returns function for updating node internals + * @returns Use this function to tell React Flow to update the internal state of one or more nodes + * that you have changed programmatically. + * + * @example + * ```jsx + *import { useCallback, useState } from 'react'; + *import { Handle, useUpdateNodeInternals } from '@xyflow/react'; + * + *export default function RandomHandleNode({ id }) { + * const updateNodeInternals = useUpdateNodeInternals(); + * const [handleCount, setHandleCount] = useState(0); + * const randomizeHandleCount = useCallback(() => { + * setHandleCount(Math.floor(Math.random() * 10)); + * updateNodeInternals(id); + * }, [id, updateNodeInternals]); + * + * return ( + * <> + * {Array.from({ length: handleCount }).map((_, index) => ( + * + * ))} + * + *
+ * + *

There are {handleCount} handles on this node.

+ *
+ * + * ); + *} + *``` + * @remarks This hook can only be used in a component that is a child of a + *{@link ReactFlowProvider} or a {@link ReactFlow} component. */ export function useUpdateNodeInternals(): UpdateNodeInternals { const store = useStoreApi(); diff --git a/packages/react/src/hooks/useViewport.ts b/packages/react/src/hooks/useViewport.ts index 0b9758c1..1528fbf5 100644 --- a/packages/react/src/hooks/useViewport.ts +++ b/packages/react/src/hooks/useViewport.ts @@ -11,10 +11,33 @@ const viewportSelector = (state: ReactFlowState) => ({ }); /** - * Hook for getting the current viewport from the store. + * The `useViewport` hook is a convenient way to read the current state of the + * {@link Viewport} in a component. Components that use this hook + * will re-render **whenever the viewport changes**. * * @public - * @returns The current viewport + * @returns The current viewport. + * + * @example + * + *```jsx + *import { useViewport } from '@xyflow/react'; + * + *export default function ViewportDisplay() { + * const { x, y, zoom } = useViewport(); + * + * return ( + *
+ *

+ * The viewport is currently at ({x}, {y}) and zoomed to {zoom}. + *

+ *
+ * ); + *} + *``` + * + * @remarks This hook can only be used in a component that is a child of a + *{@link ReactFlowProvider} or a {@link ReactFlow} component. */ export function useViewport(): Viewport { const viewport = useStore(viewportSelector, shallow); diff --git a/packages/react/src/hooks/useViewportHelper.ts b/packages/react/src/hooks/useViewportHelper.ts index 5e7e6cfa..a88bd3fc 100644 --- a/packages/react/src/hooks/useViewportHelper.ts +++ b/packages/react/src/hooks/useViewportHelper.ts @@ -2,11 +2,9 @@ import { useMemo } from 'react'; import { pointToRendererPoint, getViewportForBounds, - getFitViewNodes, - fitView, type XYPosition, rendererPointToPoint, - getDimensions, + SnapGrid, } from '@xyflow/system'; import { useStoreApi } from '../hooks/useStore'; @@ -64,28 +62,6 @@ const useViewportHelper = (): ViewportHelperFunctions => { const [x, y, zoom] = store.getState().transform; return { x, y, zoom }; }, - fitView: (options) => { - const { nodeLookup, minZoom, maxZoom, panZoom, domNode } = store.getState(); - - if (!panZoom || !domNode) { - return Promise.resolve(false); - } - - const fitViewNodes = getFitViewNodes(nodeLookup, options); - const { width, height } = getDimensions(domNode); - - return fitView( - { - nodes: fitViewNodes, - width, - height, - minZoom, - maxZoom, - panZoom, - }, - options - ); - }, setCenter: async (x, y, options) => { const { width, height, maxZoom, panZoom } = store.getState(); const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom; @@ -119,21 +95,25 @@ const useViewportHelper = (): ViewportHelperFunctions => { return Promise.resolve(true); }, - screenToFlowPosition: (clientPosition: XYPosition, options: { snapToGrid: boolean } = { snapToGrid: true }) => { - const { transform, snapGrid, domNode } = store.getState(); + screenToFlowPosition: ( + clientPosition: XYPosition, + options: { snapToGrid?: boolean; snapGrid?: SnapGrid } = {} + ) => { + const { transform, snapGrid, snapToGrid, domNode } = store.getState(); if (!domNode) { return clientPosition; } const { x: domX, y: domY } = domNode.getBoundingClientRect(); - const correctedPosition = { x: clientPosition.x - domX, y: clientPosition.y - domY, }; + const _snapGrid = options.snapGrid ?? snapGrid; + const _snapToGrid = options.snapToGrid ?? snapToGrid; - return pointToRendererPoint(correctedPosition, transform, options.snapToGrid, snapGrid); + return pointToRendererPoint(correctedPosition, transform, _snapToGrid, _snapGrid); }, flowToScreenPosition: (flowPosition: XYPosition) => { const { transform, domNode } = store.getState(); diff --git a/packages/react/src/hooks/useVisibleNodeIds.ts b/packages/react/src/hooks/useVisibleNodeIds.ts index e8d14c8e..a0006940 100644 --- a/packages/react/src/hooks/useVisibleNodeIds.ts +++ b/packages/react/src/hooks/useVisibleNodeIds.ts @@ -8,8 +8,8 @@ import type { Node, ReactFlowState } from '../types'; const selector = (onlyRenderVisible: boolean) => (s: ReactFlowState) => { return onlyRenderVisible ? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map( - (node) => node.id - ) + (node) => node.id + ) : Array.from(s.nodeLookup.keys()); }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index a6e3d6d2..eb106f18 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -9,7 +9,7 @@ export { SmoothStepEdge } from './components/Edges/SmoothStepEdge'; export { BaseEdge } from './components/Edges/BaseEdge'; export { ReactFlowProvider } from './components/ReactFlowProvider'; export { Panel, type PanelProps } from './components/Panel'; -export { EdgeLabelRenderer } from './components/EdgeLabelRenderer'; +export { EdgeLabelRenderer, type EdgeLabelRendererProps } from './components/EdgeLabelRenderer'; export { ViewportPortal } from './components/ViewportPortal'; export { useReactFlow } from './hooks/useReactFlow'; @@ -106,6 +106,7 @@ export { type FinalConnectionState, type ConnectionInProgress, type NoConnection, + type NodeConnection, } from '@xyflow/system'; // we need this workaround to prevent a duplicate identifier error diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts index 2466baa5..924e83cf 100644 --- a/packages/react/src/store/index.ts +++ b/packages/react/src/store/index.ts @@ -1,7 +1,5 @@ import { createWithEqualityFn } from 'zustand/traditional'; import { - getFitViewNodes, - fitView as fitViewSystem, adoptUserNodes, updateAbsolutePositions, panBy as panBySystem, @@ -15,11 +13,12 @@ import { initialConnection, NodeOrigin, CoordinateExtent, + fitViewport, } from '@xyflow/system'; import { applyEdgeChanges, applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes'; import getInitialState from './initialState'; -import type { ReactFlowState, Node, Edge, UnselectNodesAndEdgesParams, FitViewOptions } from '../types'; +import type { ReactFlowState, Node, Edge, UnselectNodesAndEdgesParams } from '../types'; const createStore = ({ nodes, @@ -42,25 +41,60 @@ const createStore = ({ nodeOrigin?: NodeOrigin; nodeExtent?: CoordinateExtent; }) => - createWithEqualityFn( - (set, get) => ({ + createWithEqualityFn((set, get) => { + async function resolveFitView() { + const { nodeLookup, panZoom, fitViewOptions, fitViewResolver, width, height, minZoom, maxZoom } = get(); + + if (!panZoom) { + return; + } + + await fitViewport( + { + nodes: nodeLookup, + width, + height, + panZoom, + minZoom, + maxZoom, + }, + fitViewOptions + ); + + fitViewResolver?.resolve(true); + /** + * wait for the fitViewport to resolve before deleting the resolver, + * we want to reuse the old resolver if the user calls fitView again in the mean time + */ + set({ fitViewResolver: null }); + } + + return { ...getInitialState({ nodes, edges, width, height, fitView, nodeOrigin, nodeExtent, defaultNodes, defaultEdges }), setNodes: (nodes: Node[]) => { - const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get(); - // setNodes() is called exclusively in response to user actions: - // - either when the `` prop is updated in the controlled ReactFlow setup, - // - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup. - // - // When this happens, we take the note objects passed by the user and extend them with fields - // relevant for internal React Flow operations. - adoptUserNodes(nodes, nodeLookup, parentLookup, { + const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, fitViewQueued } = get(); + /* + * setNodes() is called exclusively in response to user actions: + * - either when the `` prop is updated in the controlled ReactFlow setup, + * - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup. + * + * When this happens, we take the note objects passed by the user and extend them with fields + * relevant for internal React Flow operations. + */ + + const nodesInitialized = adoptUserNodes(nodes, nodeLookup, parentLookup, { nodeOrigin, nodeExtent, elevateNodesOnSelect, checkEquality: true, }); - set({ nodes }); + if (fitViewQueued && nodesInitialized) { + resolveFitView(); + set({ nodes, fitViewQueued: false, fitViewOptions: undefined }); + } else { + set({ nodes }); + } }, setEdges: (edges: Edge[]) => { const { connectionLookup, edgeLookup } = get(); @@ -81,23 +115,14 @@ const createStore = ({ set({ hasDefaultEdges: true }); } }, - // Every node gets registerd at a ResizeObserver. Whenever a node - // changes its dimensions, this function is called to measure the - // new dimensions and update the nodes. - updateNodeInternals: (updates, params = { triggerFitView: true }) => { - const { - triggerNodeChanges, - nodeLookup, - parentLookup, - fitViewOnInit, - fitViewDone, - fitViewOnInitOptions, - domNode, - nodeOrigin, - nodeExtent, - debug, - fitViewSync, - } = get(); + /* + * Every node gets registerd at a ResizeObserver. Whenever a node + * changes its dimensions, this function is called to measure the + * new dimensions and update the nodes. + */ + updateNodeInternals: (updates) => { + const { triggerNodeChanges, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent, debug, fitViewQueued } = + get(); const { changes, updatedInternals } = updateNodeInternalsSystem( updates, @@ -114,23 +139,9 @@ const createStore = ({ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin, nodeExtent }); - if (params.triggerFitView) { - // we call fitView once initially after all dimensions are set - let nextFitViewDone = fitViewDone; - - if (!fitViewDone && fitViewOnInit) { - nextFitViewDone = fitViewSync({ - ...fitViewOnInitOptions, - nodes: fitViewOnInitOptions?.nodes, - }); - } - - // here we are cirmumventing the onNodesChange handler - // in order to be able to display nodes even if the user - // has not provided an onNodesChange handler. - // Nodes are only rendered if they have a width and height - // attribute which they get from this handler. - set({ fitViewDone: nextFitViewDone }); + if (fitViewQueued) { + resolveFitView(); + set({ fitViewQueued: false, fitViewOptions: undefined }); } else { // we always want to trigger useStore calls whenever updateNodeInternals is called set({}); @@ -146,9 +157,12 @@ const createStore = ({ updateNodePositions: (nodeDragItems, dragging = false) => { const parentExpandChildren: ParentExpandChild[] = []; const changes = []; + const { nodeLookup, triggerNodeChanges } = get(); for (const [id, dragItem] of nodeDragItems) { - const expandParent = !!(dragItem?.expandParent && dragItem?.parentId && dragItem?.position); + // we are using the nodelookup to be sure to use the current expandParent and parentId value + const node = nodeLookup.get(id); + const expandParent = !!(node?.expandParent && node?.parentId && dragItem?.position); const change: NodeChange = { id, @@ -162,14 +176,14 @@ const createStore = ({ dragging, }; - if (expandParent) { + if (expandParent && node.parentId) { parentExpandChildren.push({ id, - parentId: dragItem.parentId!, + parentId: node.parentId, rect: { ...dragItem.internals.positionAbsolute, - width: dragItem.measured.width!, - height: dragItem.measured.height!, + width: dragItem.measured.width ?? 0, + height: dragItem.measured.height ?? 0, }, }); } @@ -178,12 +192,12 @@ const createStore = ({ } if (parentExpandChildren.length > 0) { - const { nodeLookup, parentLookup, nodeOrigin } = get(); + const { parentLookup, nodeOrigin } = get(); const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin); changes.push(...parentExpandChanges); } - get().triggerNodeChanges(changes); + triggerNodeChanges(changes); }, triggerNodeChanges: (changes) => { const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get(); @@ -222,7 +236,7 @@ const createStore = ({ if (multiSelectionActive) { const nodeChanges = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true)); - triggerNodeChanges(nodeChanges as NodeSelectionChange[]); + triggerNodeChanges(nodeChanges); return; } @@ -234,7 +248,7 @@ const createStore = ({ if (multiSelectionActive) { const changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true)); - triggerEdgeChanges(changedEdges as EdgeSelectionChange[]); + triggerEdgeChanges(changedEdges); return; } @@ -248,8 +262,10 @@ const createStore = ({ const nodeChanges = nodesToUnselect.map((n) => { const internalNode = nodeLookup.get(n.id); if (internalNode) { - // we need to unselect the internal node that was selected previously before we - // send the change to the user to prevent it to be selected while dragging the new node + /* + * we need to unselect the internal node that was selected previously before we + * send the change to the user to prevent it to be selected while dragging the new node + */ internalNode.selected = false; } @@ -257,8 +273,8 @@ const createStore = ({ }); const edgeChanges = edgesToUnselect.map((edge) => createSelectionChange(edge.id, false)); - triggerNodeChanges(nodeChanges as NodeSelectionChange[]); - triggerEdgeChanges(edgeChanges as EdgeSelectionChange[]); + triggerNodeChanges(nodeChanges); + triggerEdgeChanges(edgeChanges); }, setMinZoom: (minZoom) => { const { panZoom, maxZoom } = get(); @@ -284,11 +300,11 @@ const createStore = ({ const { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = get(); const nodeChanges = nodes.reduce( - (res, node) => (node.selected ? [...res, createSelectionChange(node.id, false) as NodeSelectionChange] : res), + (res, node) => (node.selected ? [...res, createSelectionChange(node.id, false)] : res), [] ); const edgeChanges = edges.reduce( - (res, edge) => (edge.selected ? [...res, createSelectionChange(edge.id, false) as EdgeSelectionChange] : res), + (res, edge) => (edge.selected ? [...res, createSelectionChange(edge.id, false)] : res), [] ); @@ -321,52 +337,6 @@ const createStore = ({ return panBySystem({ delta, panZoom, transform, translateExtent, width, height }); }, - fitView: (options?: FitViewOptions): Promise => { - const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get(); - - if (!panZoom) { - return Promise.resolve(false); - } - - const fitViewNodes = getFitViewNodes(nodeLookup, options); - - return fitViewSystem( - { - nodes: fitViewNodes, - width, - height, - panZoom, - minZoom, - maxZoom, - }, - options - ); - }, - // we can't call an asnychronous function in updateNodeInternals - // for that we created this sync version of fitView - fitViewSync: (options?: FitViewOptions): boolean => { - const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get(); - - if (!panZoom) { - return false; - } - - const fitViewNodes = getFitViewNodes(nodeLookup, options); - - fitViewSystem( - { - nodes: fitViewNodes, - width, - height, - panZoom, - minZoom, - maxZoom, - }, - options - ); - - return fitViewNodes.size > 0; - }, cancelConnection: () => { set({ connection: { ...initialConnection }, @@ -377,8 +347,7 @@ const createStore = ({ }, reset: () => set({ ...getInitialState() }), - }), - Object.is - ); + }; + }, Object.is); export { createStore }; diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts index af52f2a2..8be408b8 100644 --- a/packages/react/src/store/initialState.ts +++ b/packages/react/src/store/initialState.ts @@ -104,13 +104,14 @@ const getInitialState = ({ elementsSelectable: true, elevateNodesOnSelect: true, elevateEdgesOnSelect: false, - fitViewOnInit: false, - fitViewDone: false, - fitViewOnInitOptions: undefined, selectNodesOnDrag: true, multiSelectionActive: false, + fitViewQueued: fitView ?? false, + fitViewOptions: undefined, + fitViewResolver: null, + connection: { ...initialConnection }, connectionClickStartHandle: null, connectOnClick: true, diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index d04875d1..63f0a1be 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -52,7 +52,9 @@ import type { */ export interface ReactFlowProps extends Omit, 'onError'> { - /** An array of nodes to render in a controlled flow. + /** + * An array of nodes to render in a controlled flow. + * @default [] * @example * const nodes = [ * { @@ -64,7 +66,9 @@ export interface ReactFlowProps; - /** This event handler is called when a user double clicks on a node */ + /** This event handler is called when a user double-clicks on a node. */ onNodeDoubleClick?: NodeMouseHandler; - /** This event handler is called when mouse of a user enters a node */ + /** This event handler is called when mouse of a user enters a node. */ onNodeMouseEnter?: NodeMouseHandler; - /** This event handler is called when mouse of a user moves over a node */ + /** This event handler is called when mouse of a user moves over a node. */ onNodeMouseMove?: NodeMouseHandler; - /** This event handler is called when mouse of a user leaves a node */ + /** This event handler is called when mouse of a user leaves a node. */ onNodeMouseLeave?: NodeMouseHandler; - /** This event handler is called when a user right clicks on a node */ + /** This event handler is called when a user right-clicks on a node. */ onNodeContextMenu?: NodeMouseHandler; - /** This event handler is called when a user starts to drag a node */ + /** This event handler is called when a user starts to drag a node. */ onNodeDragStart?: OnNodeDrag; - /** This event handler is called when a user drags a node */ + /** This event handler is called when a user drags a node. */ onNodeDrag?: OnNodeDrag; - /** This event handler is called when a user stops dragging a node */ + /** This event handler is called when a user stops dragging a node. */ onNodeDragStop?: OnNodeDrag; - /** This event handler is called when a user clicks on an edge */ + /** This event handler is called when a user clicks on an edge. */ onEdgeClick?: (event: ReactMouseEvent, edge: EdgeType) => void; - /** This event handler is called when a user right clicks on an edge */ + /** This event handler is called when a user right-clicks on an edge. */ onEdgeContextMenu?: EdgeMouseHandler; - /** This event handler is called when mouse of a user enters an edge */ + /** This event handler is called when mouse of a user enters an edge. */ onEdgeMouseEnter?: EdgeMouseHandler; - /** This event handler is called when mouse of a user moves over an edge */ + /** This event handler is called when mouse of a user moves over an edge. */ onEdgeMouseMove?: EdgeMouseHandler; - /** This event handler is called when mouse of a user leaves an edge */ + /** This event handler is called when mouse of a user leaves an edge. */ onEdgeMouseLeave?: EdgeMouseHandler; - /** This event handler is called when a user double clicks on an edge */ + /** This event handler is called when a user double-clicks on an edge. */ onEdgeDoubleClick?: EdgeMouseHandler; + /** + * This handler is called when the source or target of a reconnectable edge is dragged from the + * current node. It will fire even if the edge's source or target do not end up changing. + * + * You can use the `reconnectEdge` utility to convert the connection to a new edge. + */ onReconnect?: OnReconnect; + /** + * This event fires when the user begins dragging the source or target of an editable edge. + */ onReconnectStart?: (event: ReactMouseEvent, edge: EdgeType, handleType: HandleType) => void; + /** + * This event fires when the user releases the source or target of an editable edge. It is called + * even if an edge update does not occur. + * + */ onReconnectEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void; - /** This event handler is called when a Node is updated + /** + * Use this event handler to add interactivity to a controlled flow. + * It is called on node drag, select, and move. * @example // Use NodesState hook to create edges and get onNodesChange handler * import ReactFlow, { useNodesState } from '@xyflow/react'; - * const [edges, setNodes, onNodesChange] = useNodesState(initialNodes); + * const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); * * return () - * @example // Use helper function to update edge + * @example // Use helper function to update node * import ReactFlow, { applyNodeChanges } from '@xyflow/react'; * * const onNodeChange = useCallback( - * (changes) => setNode((eds) => applyNodeChanges(changes, eds)), + * (changes) => setNode((nds) => applyNodeChanges(changes, nds)), * [], * ); * * return () */ onNodesChange?: OnNodesChange; - /** This event handler is called when a Edge is updated + /** + * Use this event handler to add interactivity to a controlled flow. It is called on edge select + * and remove. * @example // Use EdgesState hook to create edges and get onEdgesChange handler * import ReactFlow, { useEdgesState } from '@xyflow/react'; * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); @@ -166,24 +189,28 @@ export interface ReactFlowProps) */ onEdgesChange?: OnEdgesChange; - /** This event handler gets called when a Node is deleted */ + /** This event handler gets called when a node is deleted. */ onNodesDelete?: OnNodesDelete; - /** This event handler gets called when a Edge is deleted */ + /** This event handler gets called when an edge is deleted. */ onEdgesDelete?: OnEdgesDelete; - /** This event handler gets called when a Node or Edge is deleted */ + /** This event handler gets called when a node or edge is deleted. */ onDelete?: OnDelete; - /** This event handler gets called when a user starts to drag a selection box */ + /** This event handler gets called when a user starts to drag a selection box. */ onSelectionDragStart?: SelectionDragHandler; - /** This event handler gets called when a user drags a selection box */ + /** This event handler gets called when a user drags a selection box. */ onSelectionDrag?: SelectionDragHandler; - /** This event handler gets called when a user stops dragging a selection box */ + /** This event handler gets called when a user stops dragging a selection box. */ onSelectionDragStop?: SelectionDragHandler; onSelectionStart?: (event: ReactMouseEvent) => void; onSelectionEnd?: (event: ReactMouseEvent) => void; + /** + * This event handler is called when a user right-clicks on a node selection. + */ onSelectionContextMenu?: (event: ReactMouseEvent, nodes: NodeType[]) => void; - /** When a connection line is completed and two nodes are connected by the user, this event fires with the new connection. + /** + * When a connection line is completed and two nodes are connected by the user, this event fires with the new connection. * - * You can use the addEdge utility to convert the connection to a complete edge. + * You can use the `addEdge` utility to convert the connection to a complete edge. * @example // Use helper function to update edges onConnect * import ReactFlow, { addEdge } from '@xyflow/react'; * @@ -195,178 +222,260 @@ export interface ReactFlowProps) */ onConnect?: OnConnect; - /** This event handler gets called when a user starts to drag a connection line */ + /** This event handler gets called when a user starts to drag a connection line. */ onConnectStart?: OnConnectStart; - /** This event handler gets called when a user stops dragging a connection line */ + /** + * This callback will fire regardless of whether a valid connection could be made or not. You can + * use the second `connectionState` parameter to have different behavior when a connection was + * unsuccessful. + */ onConnectEnd?: OnConnectEnd; onClickConnectStart?: OnConnectStart; onClickConnectEnd?: OnConnectEnd; - /** This event handler gets called when a flow has finished initializing */ + /** + * The `onInit` callback is called when the viewport is initialized. At this point you can use the + * instance to call methods like `fitView` or `zoomTo`. + */ onInit?: OnInit; /** This event handler is called while the user is either panning or zooming the viewport. */ onMove?: OnMove; - /** This event handler gets called when a user starts to pan or zoom the viewport */ + /** This event handler is called when the user begins to pan or zoom the viewport. */ onMoveStart?: OnMoveStart; - /** This event handler gets called when a user stops panning or zooming the viewport */ + /** + * This event handler is called when panning or zooming viewport movement stops. + * If the movement is not user-initiated, the event parameter will be `null`. + */ onMoveEnd?: OnMoveEnd; - /** This event handler gets called when a user changes group of selected elements in the flow */ - onSelectionChange?: OnSelectionChangeFunc; - /** This event handler gets called when user scroll inside the pane */ + /** This event handler gets called when a user changes group of selected elements in the flow. */ + onSelectionChange?: OnSelectionChangeFunc; + /** This event handler gets called when user scroll inside the pane. */ onPaneScroll?: (event?: WheelEvent) => void; - /** This event handler gets called when user clicks inside the pane */ + /** This event handler gets called when user clicks inside the pane. */ onPaneClick?: (event: ReactMouseEvent) => void; - /** This event handler gets called when user right clicks inside the pane */ + /** This event handler gets called when user right clicks inside the pane. */ onPaneContextMenu?: (event: ReactMouseEvent | MouseEvent) => void; - /** This event handler gets called when mouse enters the pane */ + /** This event handler gets called when mouse enters the pane. */ onPaneMouseEnter?: (event: ReactMouseEvent) => void; - /** This event handler gets called when mouse moves over the pane */ + /** This event handler gets called when mouse moves over the pane. */ onPaneMouseMove?: (event: ReactMouseEvent) => void; - /** This event handler gets called when mouse leaves the pane */ + /** This event handler gets called when mouse leaves the pane. */ onPaneMouseLeave?: (event: ReactMouseEvent) => void; - /** Distance that the mouse can move between mousedown/up that will trigger a click + /** + * Distance that the mouse can move between mousedown/up that will trigger a click. * @default 0 */ paneClickDistance?: number; - /** Distance that the mouse can move between mousedown/up that will trigger a click + /** + * Distance that the mouse can move between mousedown/up that will trigger a click. * @default 0 */ nodeClickDistance?: number; - /** This handler gets called before the user deletes nodes or edges and provides a way to abort the deletion by returning false. */ + /** + * This handler is called before nodes or edges are deleted, allowing the deletion to be aborted + * by returning `false` or modified by returning updated nodes and edges. + */ onBeforeDelete?: OnBeforeDelete; - /** Custom node types to be available in a flow. + /** + * Custom node types to be available in a flow. * - * React Flow matches a node's type to a component in the nodeTypes object. + * React Flow matches a node's type to a component in the `nodeTypes` object. + * @TODO check if @default is correct + * @default { + * input: InputNode, + * default: DefaultNode, + * output: OutputNode, + * group: GroupNode + * } * @example * import CustomNode from './CustomNode'; * * const nodeTypes = { nameOfNodeType: CustomNode }; */ nodeTypes?: NodeTypes; - /** Custom edge types to be available in a flow. + /** + * Custom edge types to be available in a flow. * - * React Flow matches an edge's type to a component in the edgeTypes object. + * React Flow matches an edge's type to a component in the `edgeTypes` object. + * @TODO check if @default is correct + * @default { + * default: BezierEdge, + * straight: StraightEdge, + * step: StepEdge, + * smoothstep: SmoothStepEdge, + * simplebezier: SimpleBezier + * } * @example * import CustomEdge from './CustomEdge'; * * const edgeTypes = { nameOfEdgeType: CustomEdge }; */ edgeTypes?: EdgeTypes; - /** The type of edge path to use for connection lines. + /** + * The type of edge path to use for connection lines. * * Although created edges can be of any type, React Flow needs to know what type of path to render for the connection line before the edge is created! + * @default ConnectionLineType.Bezier */ connectionLineType?: ConnectionLineType; - /** Styles to be applied to the connection line */ + /** Styles to be applied to the connection line. */ connectionLineStyle?: CSSProperties; - /** React Component to be used as a connection line */ - connectionLineComponent?: ConnectionLineComponent; - /** Styles to be applied to the container of the connection line */ + /** React Component to be used as a connection line. */ + connectionLineComponent?: ConnectionLineComponent; + /** Styles to be applied to the container of the connection line. */ connectionLineContainerStyle?: CSSProperties; - /** 'strict' connection mode will only allow you to connect source handles to target handles. - * - * 'loose' connection mode will allow you to connect handles of any type to one another. + /** + * A loose connection mode will allow you to connect handles with differing types, including + * source-to-source connections. However, it does not support target-to-target connections. Strict + * mode allows only connections between source handles and target handles. * @default 'strict' */ connectionMode?: ConnectionMode; - /** Pressing down this key deletes all selected nodes & edges. + /** + * If set, pressing the key or chord will delete any selected nodes and edges. Passing an array + * represents multiple keys that can be pressed. + * + * For example, `["Delete", "Backspace"]` will delete selected elements when either key is pressed. * @default 'Backspace' */ deleteKeyCode?: KeyCode | null; - /** If a key is set, you can pan the viewport while that key is held down even if panOnScroll is set to false. + /** + * If set, holding this key will let you click and drag to draw a selection box around multiple + * nodes and edges. Passing an array represents multiple keys that can be pressed. * - * By setting this prop to null you can disable this functionality. - * @default 'Space' + * For example, `["Shift", "Meta"]` will allow you to draw a selection box when either key is + * pressed. + * @default 'Shift' */ selectionKeyCode?: KeyCode | null; - /** Select multiple elements with a selection box, without pressing down selectionKey */ + /** + * Select multiple elements with a selection box, without pressing down `selectionKey`. + * @default false + */ selectionOnDrag?: boolean; - /** When set to "partial", when the user creates a selection box by click and dragging nodes that are only partially in the box are still selected. + /** + * When set to `"partial"`, when the user creates a selection box by click and dragging nodes that + * are only partially in the box are still selected. * @default 'full' */ selectionMode?: SelectionMode; - /** If a key is set, you can pan the viewport while that key is held down even if panOnScroll is set to false. + /** + * If a key is set, you can pan the viewport while that key is held down even if `panOnScroll` + * is set to `false`. * - * By setting this prop to null you can disable this functionality. + * By setting this prop to `null` you can disable this functionality. * @default 'Space' */ panActivationKeyCode?: KeyCode | null; - /** Pressing down this key you can select multiple elements by clicking. - * @default 'Meta' for macOS, "Ctrl" for other systems + /** + * Pressing down this key you can select multiple elements by clicking. + * @default "Meta" for macOS, "Control" for other systems */ multiSelectionKeyCode?: KeyCode | null; - /** If a key is set, you can zoom the viewport while that key is held down even if panOnScroll is set to false. + /** + * If a key is set, you can zoom the viewport while that key is held down even if `panOnScroll` + * is set to `false`. * - * By setting this prop to null you can disable this functionality. - * @default 'Meta' for macOS, "Ctrl" for other systems - * */ + * By setting this prop to `null` you can disable this functionality. + * @default "Meta" for macOS, "Control" for other systems + * + */ zoomActivationKeyCode?: KeyCode | null; - /** Set this prop to make the flow snap to the grid */ + /** When enabled, nodes will snap to the grid when dragged. */ snapToGrid?: boolean; - /** Grid all nodes will snap to + /** + * If `snapToGrid` is enabled, this prop configures the grid that nodes will snap to. * @example [20, 20] */ snapGrid?: SnapGrid; - /** You can enable this optimisation to instruct Svelte Flow to only render nodes and edges that would be visible in the viewport. + /** + * You can enable this optimisation to instruct React Flow to only render nodes and edges that would be visible in the viewport. * * This might improve performance when you have a large number of nodes and edges but also adds an overhead. * @default false */ onlyRenderVisibleElements?: boolean; - /** Controls if all nodes should be draggable + /** + * Controls whether all nodes should be draggable or not. Individual nodes can override this + * setting by setting their `draggable` prop. If you want to use the mouse handlers on + * non-draggable nodes, you need to add the `"nopan"` class to those nodes. * @default true */ nodesDraggable?: boolean; - /** Controls if all nodes should be connectable to each other + /** + * Controls whether all nodes should be connectable or not. Individual nodes can override this + * setting by setting their `connectable` prop. * @default true */ nodesConnectable?: boolean; - /** Controls if all nodes should be focusable + /** + * When `true`, focus between nodes can be cycled with the `Tab` key and selected with the `Enter` + * key. This option can be overridden by individual nodes by setting their `focusable` prop. * @default true */ nodesFocusable?: boolean; - /** Defines nodes relative position to its coordinates + /** + * The origin of the node to use when placing it in the flow or looking up its `x` and `y` + * position. An origin of `[0, 0]` means that a node's top left corner will be placed at the `x` + * and `y` position. + * @default [0, 0] * @example * [0, 0] // default, top left * [0.5, 0.5] // center * [1, 1] // bottom right */ nodeOrigin?: NodeOrigin; - /** Controls if all edges should be focusable + /** + * When `true`, focus between edges can be cycled with the `Tab` key and selected with the `Enter` + * key. This option can be overridden by individual edges by setting their `focusable` prop. * @default true */ edgesFocusable?: boolean; - /** Controls if all edges should be updateable + /** + * Whether edges can be updated once they are created. When both this prop is `true` and an + * `onReconnect` handler is provided, the user can drag an existing edge to a new source or + * target. Individual edges can override this value with their reconnectable property. * @default true */ edgesReconnectable?: boolean; - /** Controls if all elements should (nodes & edges) be selectable + /** + * When `true`, elements (nodes and edges) can be selected by clicking on them. This option can be + * overridden by individual elements by setting their `selectable` prop. * @default true */ elementsSelectable?: boolean; - /** If true, nodes get selected on drag + /** + * If `true`, nodes get selected on drag. * @default true */ selectNodesOnDrag?: boolean; - /** Enableing this prop allows users to pan the viewport by clicking and dragging. + /** + * Enabling this prop allows users to pan the viewport by clicking and dragging. * * You can also set this prop to an array of numbers to limit which mouse buttons can activate panning. + * @default true * @example [0, 2] // allows panning with the left and right mouse buttons * [0, 1, 2, 3, 4] // allows panning with all mouse buttons */ panOnDrag?: boolean | number[]; - /** Minimum zoom level + /** + * Minimum zoom level. * @default 0.5 */ minZoom?: number; - /** Maximum zoom level + /** + * Maximum zoom level. * @default 2 */ maxZoom?: number; - /** Controlled viewport to be used instead of internal one */ + /** + * When you pass a `viewport` prop, it's controlled, and you also need to pass `onViewportChange` + * to handle internal changes. + */ viewport?: Viewport; - /** Sets the initial position and zoom of the viewport. - * - * If a default viewport is provided but fitView is enabled, the default viewport will be ignored. + /** + * Sets the initial position and zoom of the viewport. If a default viewport is provided but + * `fitView` is enabled, the default viewport will be ignored. + * @default { x: 0, y: 0, zoom: 1 } * @example * const initialViewport = { * zoom: 0.5, @@ -375,59 +484,103 @@ export interface ReactFlowProps void; - /** By default the viewport extends infinitely. You can use this prop to set a boundary. + /** + * By default, the viewport extends infinitely. You can use this prop to set a boundary. * * The first pair of coordinates is the top left boundary and the second pair is the bottom right. + * @default [[-∞, -∞], [+∞, +∞]] * @example [[-1000, -10000], [1000, 1000]] */ translateExtent?: CoordinateExtent; - /** Disabling this prop will allow the user to scroll the page even when their pointer is over the flow. + /** + * Disabling this prop will allow the user to scroll the page even when their pointer is over the flow. * @default true */ preventScrolling?: boolean; - /** By default nodes can be placed on an infinite flow. You can use this prop to set a boundary. + /** + * By default, nodes can be placed on an infinite flow. You can use this prop to set a boundary. * * The first pair of coordinates is the top left boundary and the second pair is the bottom right. * @example [[-1000, -10000], [1000, 1000]] */ nodeExtent?: CoordinateExtent; - /** Color of edge markers - * @example "#b1b1b7" + /** + * Color of edge markers. + * @default '#b1b1b7' */ defaultMarkerColor?: string; - /** Controls if the viewport should zoom by scrolling inside the container */ + /** + * Controls if the viewport should zoom by scrolling inside the container. + * @default true + */ zoomOnScroll?: boolean; - /** Controls if the viewport should zoom by pinching on a touch screen */ + /** + * Controls if the viewport should zoom by pinching on a touch screen. + * @default true + */ zoomOnPinch?: boolean; - /** Controls if the viewport should pan by scrolling inside the container + /** + * Controls if the viewport should pan by scrolling inside the container. * - * Can be limited to a specific direction with panOnScrollMode + * Can be limited to a specific direction with `panOnScrollMode`. + * @default false */ panOnScroll?: boolean; - /** Controls how fast viewport should be panned on scroll. + /** + * Controls how fast viewport should be panned on scroll. * - * Use togther with panOnScroll prop. + * Use together with `panOnScroll` prop. + * @default 0.5 */ panOnScrollSpeed?: number; - /** This prop is used to limit the direction of panning when panOnScroll is enabled. + /** + * This prop is used to limit the direction of panning when `panOnScroll` is enabled. * - * The "free" option allows panning in any direction. + * The `"free"` option allows panning in any direction. * @default "free" * @example "horizontal" | "vertical" */ panOnScrollMode?: PanOnScrollMode; - /** Controls if the viewport should zoom by double clicking somewhere on the flow */ + /** + * Controls if the viewport should zoom by double-clicking somewhere on the flow. + * @default true + */ zoomOnDoubleClick?: boolean; + /** + * The radius around an edge connection that can trigger an edge reconnection. + * @default 10 + */ reconnectRadius?: number; + /** + * If a node is draggable, clicking and dragging that node will move it around the canvas. Adding + * the `"nodrag"` class prevents this behavior and this prop allows you to change the name of that + * class. + * @default "nodrag" + */ noDragClassName?: string; + /** + * Typically, scrolling the mouse wheel when the mouse is over the canvas will zoom the viewport. + * Adding the `"nowheel"` class to an element n the canvas will prevent this behavior and this prop + * allows you to change the name of that class. + * @default "nowheel" + */ noWheelClassName?: string; + /** + * If an element in the canvas does not stop mouse events from propagating, clicking and dragging + * that element will pan the viewport. Adding the `"nopan"` class prevents this behavior and this + * prop allows you to change the name of that class. + * @default "nopan" + */ noPanClassName?: string; - /** If set, initial viewport will show all nodes & edges */ + /** When `true`, the flow will be zoomed and panned to fit all the nodes initially provided. */ fitView?: boolean; - /** Options to be used in combination with fitView + /** + * When you typically call `fitView` on a `ReactFlowInstance`, you can provide an object of + * options to customize its behavior. This prop lets you do the same for the initial `fitView` + * call. * @example * const fitViewOptions = { * padding: 0.1, @@ -439,85 +592,105 @@ export interface ReactFlowProps true + * If you return `false`, the edge will not be added to your flow. + * If you have custom connection logic its preferred to use this callback over the + * `isValidConnection` prop on the handle component for performance reasons. */ isValidConnection?: IsValidConnection; - /** With a threshold greater than zero you can control the distinction between node drag and click events. + /** + * With a threshold greater than zero you can delay node drag events. * * If threshold equals 1, you need to drag the node 1 pixel before a drag event is fired. + * + * 1 is the default value, so clicks don't trigger drag events. * @default 1 */ nodeDragThreshold?: number; - /** Sets a fixed width for the flow */ + /** Sets a fixed width for the flow. */ width?: number; - /** Sets a fixed height for the flow */ + /** Sets a fixed height for the flow. */ height?: number; - /** Controls color scheme used for styling the flow - * @default 'system' + /** + * Controls color scheme used for styling the flow. + * @default 'light' * @example 'system' | 'light' | 'dark' */ colorMode?: ColorMode; - /** If set true, some debug information will be logged to the console like which events are fired. - * - * @default undefined + /** + * If set `true`, some debug information will be logged to the console like which events are fired. + * @default false */ debug?: boolean; } diff --git a/packages/react/src/types/edges.ts b/packages/react/src/types/edges.ts index ce21e84f..ca3f91fe 100644 --- a/packages/react/src/types/edges.ts +++ b/packages/react/src/types/edges.ts @@ -19,8 +19,18 @@ import type { import { EdgeTypes, InternalNode, Node } from '.'; +/** + * @inline + */ export type EdgeLabelOptions = { - label?: string | ReactNode; + /** + * The label or custom element to render along the edge. This is commonly a text label or some + * custom controls. + */ + label?: ReactNode; + /** + * Custom styles to apply to the label. + */ labelStyle?: CSSProperties; labelShowBg?: boolean; labelBgStyle?: CSSProperties; @@ -29,7 +39,8 @@ export type EdgeLabelOptions = { }; /** - * The Edge type is mainly used for the `edges` that get passed to the ReactFlow component + * An `Edge` is the complete description with everything React Flow needs + * to know in order to render it. * @public */ export type Edge< @@ -39,6 +50,11 @@ export type Edge< EdgeLabelOptions & { style?: CSSProperties; className?: string; + /** + * Determines whether the edge can be updated by dragging the source or target to a new node. + * This property will override the default set by the `edgesReconnectable` prop on the + * `` component. + */ reconnectable?: boolean | HandleType; focusable?: boolean; }; @@ -91,17 +107,26 @@ export type EdgeWrapperProps = { disableKeyboardA11y?: boolean; }; +/** + * Many properties on an [`Edge`](/api-reference/types/edge) are optional. When a new edge is created, + * the properties that are not provided will be filled in with the default values + * passed to the `defaultEdgeOptions` prop of the [``](/api-reference/react-flow#defaultedgeoptions) component. + */ export type DefaultEdgeOptions = DefaultEdgeOptionsBase; -export type EdgeTextProps = SVGAttributes & +export type EdgeTextProps = Omit, 'x' | 'y'> & EdgeLabelOptions & { + /** The x position where the label should be rendered. */ x: number; + /** The y position where the label should be rendered. */ y: number; }; /** - * Custom edge component props + * When you implement a custom edge it is wrapped in a component that enables some + * basic functionality. The `EdgeProps` type is the props that are passed to this. * @public + * @expand */ export type EdgeProps = Pick< EdgeType, @@ -121,22 +146,42 @@ export type EdgeProps = Pick< /** * BaseEdge component props * @public + * @expand */ -export type BaseEdgeProps = Omit, 'd'> & +export type BaseEdgeProps = Omit, 'd' | 'path' | 'markerStart' | 'markerEnd'> & EdgeLabelOptions & { - /** Additional padding where interacting with an edge is still possible */ + /** + * The width of the invisible area around the edge that the user can interact with. This is + * useful for making the edge easier to click or hover over. + * @default 20 + */ interactionWidth?: number; /** The x position of edge label */ labelX?: number; /** The y position of edge label */ labelY?: number; - /** SVG path of the edge */ + /** + * The SVG path string that defines the edge. This should look something like + * `'M 0 0 L 100 100'` for a simple line. The utility functions like `getSimpleBezierEdge` can + * be used to generate this string for you. + */ path: string; + /** + * The id of the SVG marker to use at the start of the edge. This should be defined in a + * `` element in a separate SVG document or element. + */ + markerStart?: string; + /** + * The id of the SVG marker to use at the end of the edge. This should be defined in a `` + * element in a separate SVG document or element. + */ + markerEnd?: string; }; /** * Helper type for edge components that get exported by the library * @public + * @expand */ export type EdgeComponentProps = EdgePosition & EdgeLabelOptions & { @@ -156,39 +201,53 @@ export type EdgeComponentWithPathOptions = EdgeComponentProps & { /** * BezierEdge component props * @public + * @expand */ export type BezierEdgeProps = EdgeComponentWithPathOptions; /** * SmoothStepEdge component props * @public + * @expand */ export type SmoothStepEdgeProps = EdgeComponentWithPathOptions; /** * StepEdge component props * @public + * @expand */ export type StepEdgeProps = EdgeComponentWithPathOptions; /** * StraightEdge component props * @public + * @expand */ export type StraightEdgeProps = Omit; /** * SimpleBezier component props * @public + * @expand */ export type SimpleBezierEdgeProps = EdgeComponentProps; export type OnReconnect = (oldEdge: EdgeType, newConnection: Connection) => void; +/** + * If you want to render a custom component for connection lines, you can set the + * `connectionLineComponent` prop on the [``](/api-reference/react-flow#connection-connectionLineComponent) + * component. The `ConnectionLineComponentProps` are passed to your custom component. + * + * @public + */ export type ConnectionLineComponentProps = { connectionLineStyle?: CSSProperties; connectionLineType: ConnectionLineType; + /** The node the connection line originates from. */ fromNode: InternalNode; + /** The handle on the `fromNode` that the connection line originates from. */ fromHandle: Handle; fromX: number; fromY: number; @@ -196,6 +255,10 @@ export type ConnectionLineComponentProps = { toY: number; fromPosition: Position; toPosition: Position; + /** + * If there is an `isValidConnection` callback, this prop will be set to `"valid"` or `"invalid"` + * based on the return value of that callback. Otherwise, it will be `null`. + */ connectionStatus: 'valid' | 'invalid' | null; toNode: InternalNode | null; toHandle: Handle | null; diff --git a/packages/react/src/types/general.ts b/packages/react/src/types/general.ts index 48e5b2fe..98302a86 100644 --- a/packages/react/src/types/general.ts +++ b/packages/react/src/types/general.ts @@ -18,11 +18,44 @@ import { import type { Node, Edge, ReactFlowInstance, EdgeProps, NodeProps } from '.'; +/** + * This type can be used to type the `onNodesChange` function with a custom node type. + * + * @public + * + * @example + * + * ```ts + * const onNodesChange: OnNodesChange = useCallback((changes) => { + * setNodes((nodes) => applyNodeChanges(nodes, changes)); + * },[]); + * ``` + */ export type OnNodesChange = (changes: NodeChange[]) => void; + +/** + * This type can be used to type the `onEdgesChange` function with a custom edge type. + * + * @public + * + * @example + * + * ```ts + * const onEdgesChange: OnEdgesChange = useCallback((changes) => { + * setEdges((edges) => applyEdgeChanges(edges, changes)); + * },[]); + * ``` + */ export type OnEdgesChange = (changes: EdgeChange[]) => void; export type OnNodesDelete = (nodes: NodeType[]) => void; export type OnEdgesDelete = (edges: EdgeType[]) => void; + +/** + * This type can be used to type the `onDelete` function with a custom node and edge type. + * + * @public + */ export type OnDelete = (params: { nodes: NodeType[]; edges: EdgeType[]; @@ -39,6 +72,7 @@ export type NodeTypes = Record< } > >; + export type EdgeTypes = Record< string, ComponentType< @@ -51,25 +85,38 @@ export type EdgeTypes = Record< > >; -export type UnselectNodesAndEdgesParams = { - nodes?: Node[]; - edges?: Edge[]; +export type UnselectNodesAndEdgesParams = { + nodes?: NodeType[]; + edges?: EdgeType[]; }; -export type OnSelectionChangeParams = { - nodes: Node[]; - edges: Edge[]; +export type OnSelectionChangeParams = { + nodes: NodeType[]; + edges: EdgeType[]; }; -export type OnSelectionChangeFunc = (params: OnSelectionChangeParams) => void; +export type OnSelectionChangeFunc = ( + params: OnSelectionChangeParams +) => void; export type FitViewParams = FitViewParamsBase; + +/** + * When calling [`fitView`](/api-reference/types/react-flow-instance#fitview) these options + * can be used to customize the behaviour. For example, the `duration` option can be used to + * transform the viewport smoothly over a given amount of time. + * + * @public + */ export type FitViewOptions = FitViewOptionsBase; -export type FitView = (fitViewOptions?: FitViewOptions) => Promise; +export type FitView = (fitViewOptions?: FitViewOptions) => Promise; export type OnInit = ( reactFlowInstance: ReactFlowInstance ) => void; +/** + * @inline + */ export type ViewportHelperFunctions = { /** * Zooms viewport in by 1.2. @@ -84,14 +131,15 @@ export type ViewportHelperFunctions = { */ zoomOut: ZoomInOut; /** - * Sets the current zoom level. + * Zoom the viewport to a given zoom level. Passing in a `duration` will animate the viewport to + * the new zoom level. * * @param zoomLevel - the zoom level to set * @param options.duration - optional duration. If set, a transition will be applied */ zoomTo: ZoomTo; /** - * Returns the current zoom level. + * Get the current zoom level of the viewport. * * @returns current zoom as a number */ @@ -110,18 +158,8 @@ export type ViewportHelperFunctions = { */ getViewport: GetViewport; /** - * Fits the view. - * - * @param options.padding - optional padding - * @param options.includeHiddenNodes - optional includeHiddenNodes - * @param options.minZoom - optional minZoom - * @param options.maxZoom - optional maxZoom - * @param options.duration - optional duration. If set, a transition will be applied - * @param options.nodes - optional nodes to fit the view to - */ - fitView: FitView; - /** - * Sets the center of the view to the given position. + * Center the viewport on a given position. Passing in a `duration` will animate the viewport to + * the new position. * * @param x - x position * @param y - y position @@ -129,14 +167,17 @@ export type ViewportHelperFunctions = { */ setCenter: SetCenter; /** - * Fits the view to the given bounds . + * A low-level utility function to fit the viewport to a given rectangle. By passing in a + * `duration`, the viewport will animate from its current position to the new position. The + * `padding` option can be used to add space around the bounds. * * @param bounds - the bounds ({ x: number, y: number, width: number, height: number }) to fit the view to * @param options.padding - optional padding */ fitBounds: FitBounds; /** - * Converts a screen / client position to a flow position. + * With this function you can translate a screen pixel position to a flow position. It is useful + * for implementing drag and drop from a sidebar for example. * * @param clientPosition - the screen / client position. When you are working with events you can use event.clientX and event.clientY * @param options.snapToGrid - if true, the converted position will be snapped to the grid @@ -147,7 +188,7 @@ export type ViewportHelperFunctions = { */ screenToFlowPosition: (clientPosition: XYPosition, options?: { snapToGrid: boolean }) => XYPosition; /** - * Converts a flow position to a screen / client position. + * Translate a position inside the flow's canvas to a screen pixel position. * * @param flowPosition - the screen / client position. When you are working with events you can use event.clientX and event.clientY * @returns position as { x: number, y: number } diff --git a/packages/react/src/types/instance.ts b/packages/react/src/types/instance.ts index 992655a4..d001486a 100644 --- a/packages/react/src/types/instance.ts +++ b/packages/react/src/types/instance.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-namespace */ import type { HandleConnection, HandleType, NodeConnection, Rect, Viewport } from '@xyflow/system'; -import type { Node, Edge, ViewportHelperFunctions, InternalNode } from '.'; +import type { Node, Edge, ViewportHelperFunctions, InternalNode, FitView } from '.'; export type ReactFlowJsonObject = { nodes: NodeType[]; @@ -13,6 +13,9 @@ export type DeleteElementsOptions = { edges?: (Edge | { id: Edge['id'] })[]; }; +/** + * @inline + */ export type GeneralHelpers = { /** * Returns nodes. @@ -21,13 +24,17 @@ export type GeneralHelpers NodeType[]; /** - * Sets nodes. + * Set your nodes array to something else by either overwriting it with a new array or by passing + * in a function to update the existing array. If using a function, it is important to make sure a + * new array is returned instead of mutating the existing array. Calling this function will + * trigger the `onNodesChange` handler in a controlled flow. * * @param payload - the nodes to set or a function that receives the current nodes and returns the new nodes */ setNodes: (payload: NodeType[] | ((nodes: NodeType[]) => NodeType[])) => void; /** - * Adds nodes. + * Add one or many nodes to your existing nodes array. Calling this function will trigger the + * `onNodesChange` handler in a controlled flow. * * @param payload - the nodes to add */ @@ -53,13 +60,17 @@ export type GeneralHelpers EdgeType[]; /** - * Sets edges. + * Set your edges array to something else by either overwriting it with a new array or by passing + * in a function to update the existing array. If using a function, it is important to make sure a + * new array is returned instead of mutating the existing array. Calling this function will + * trigger the `onEdgesChange` handler in a controlled flow. * * @param payload - the edges to set or a function that receives the current edges and returns the new edges */ setEdges: (payload: EdgeType[] | ((edges: EdgeType[]) => EdgeType[])) => void; /** - * Adds edges. + * Add one or many edges to your existing edges array. Calling this function will trigger the + * `onEdgesChange` handler in a controlled flow. * * @param payload - the edges to add */ @@ -90,7 +101,8 @@ export type GeneralHelpers; /** - * Returns all nodes that intersect with the given node or rect. + * Find all the nodes currently intersecting with a given node or rectangle. The `partially` + * parameter can be set to `true` to include nodes that are only partially intersecting. * * @param node - the node or rect to check for intersections * @param partially - if true, the node is considered to be intersecting if it partially overlaps with the passed node or rect @@ -104,7 +116,8 @@ export type GeneralHelpers NodeType[]; /** - * Checks if the given node or rect intersects with the passed rect. + * Determine if a given node or rectangle is intersecting with another rectangle. The `partially` + * parameter can be set to true return `true` even if the node is only partially intersecting. * * @param node - the node or rect to check for intersections * @param area - the rect to check for intersections @@ -182,7 +195,8 @@ export type GeneralHelpers Rect; /** - * Gets all connections for a given handle belonging to a specific node. + * Get all the connections of a handle belonging to a specific node. The type parameter be either + * `'source'` or `'target'`. * @deprecated * @param type - handle type 'source' or 'target' * @param id - the handle id (this is only needed if you have multiple handles of the same type, meaning you have to provide a unique id for each handle) @@ -200,7 +214,6 @@ export type GeneralHelpers HandleConnection[]; /** * Gets all connections to a node. Can be filtered by handle type and id. - * @deprecated use `getNodeConnections` instead * @param type - handle type 'source' or 'target' * @param handleId - the handle id (this is only needed if you have multiple handles of the same type, meaning you have to provide a unique id for each handle) * @param nodeId - the node id the handle belongs to @@ -215,12 +228,34 @@ export type GeneralHelpers NodeConnection[]; + // /** + // * Fits the view. + // * + // * @param options.padding - optional padding + // * @param options.includeHiddenNodes - optional includeHiddenNodes + // * @param options.minZoom - optional minZoom + // * @param options.maxZoom - optional maxZoom + // * @param options.duration - optional duration. If set, a transition will be applied + // * @param options.nodes - optional nodes to fit the view to + // */ + fitView: FitView; }; - +/** + * The `ReactFlowInstance` provides a collection of methods to query and manipulate + * the internal state of your flow. You can get an instance by using the + * [`useReactFlow`](/api-reference/hooks/use-react-flow) hook or attaching a listener + * to the [`onInit`](/api-reference/react-flow#event-oninit) event. + * + * @public + */ export type ReactFlowInstance = GeneralHelpers< NodeType, EdgeType > & - Omit & { + ViewportHelperFunctions & { + /** + * React Flow needs to mount the viewport to the DOM and initialize its zoom and pan behavior. + * This property tells you when viewport is initialized. + */ viewportInitialized: boolean; }; diff --git a/packages/react/src/types/nodes.ts b/packages/react/src/types/nodes.ts index 0d3924e4..b07c0337 100644 --- a/packages/react/src/types/nodes.ts +++ b/packages/react/src/types/nodes.ts @@ -4,7 +4,10 @@ import type { CoordinateExtent, NodeBase, OnError, NodeProps as NodePropsBase, I import { NodeTypes } from './general'; /** - * The node data structure that gets used for the nodes prop. + * The `Node` type represents everything React Flow needs to know about a given node. + * Whenever you want to update a certain attribute of a node, you need to create a new + * node object. + * * @public */ export type Node< @@ -18,9 +21,10 @@ export type Node< }; /** - * The node data structure that gets used for internal nodes. - * There are some data structures added under node.internal - * that are needed for tracking some properties + * The `InternalNode` type is identical to the base [`Node`](/api-references/types/node) + * type but is extended with some additional properties used internally. + * Some functions and callbacks that return nodes may return an `InternalNode`. + * * @public */ export type InternalNode = InternalNodeBase; @@ -56,8 +60,46 @@ export type NodeWrapperProps = { nodeClickDistance?: number; }; +/** + * The `BuiltInNode` type represents the built-in node types that are available in React Flow. + * You can use this type to extend your custom node type if you still want ot use the built-in ones. + * + * @public + * @example + * ```ts + * type CustomNode = Node<{ value: number }, 'custom'>; + * type MyAppNode = CustomNode | BuiltInNode; + * ``` + */ export type BuiltInNode = | Node<{ label: string }, 'input' | 'output' | 'default'> | Node, 'group'>; +/** + * When you implement a [custom node](/learn/customization/custom-nodes) it is + * wrapped in a component that enables basic functionality like selection and + * dragging. Your custom node receives `NodeProps` as props. + * + * @public + * @example + * ```tsx + *import { useState } from 'react'; + *import { NodeProps, Node } from '@xyflow/react'; + * + *export type CounterNode = Node<{ initialCount?: number }, 'counter'>; + * + *export default function CounterNode(props: NodeProps) { + * const [count, setCount] = useState(props.data?.initialCount ?? 0); + * + * return ( + *
+ *

Count: {count}

+ * + *
+ * ); + *} + *``` + */ export type NodeProps = NodePropsBase; diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index b060be36..efd9d957 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -119,9 +119,9 @@ export type ReactFlowStore | null; onNodesDelete?: OnNodesDelete; onEdgesDelete?: OnEdgesDelete; @@ -134,7 +134,7 @@ export type ReactFlowStore; - onSelectionChangeHandlers: OnSelectionChangeFunc[]; + onSelectionChangeHandlers: OnSelectionChangeFunc[]; ariaLiveMessage: string; autoPanOnConnect: boolean; @@ -155,7 +155,7 @@ export type ReactFlowActions = { updateNodeInternals: (updates: Map, params?: { triggerFitView: boolean }) => void; updateNodePositions: UpdateNodePositions; resetSelectedElements: () => void; - unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void; + unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void; addSelectedNodes: (nodeIds: string[]) => void; addSelectedEdges: (edgeIds: string[]) => void; setMinZoom: (minZoom: number) => void; @@ -168,8 +168,6 @@ export type ReactFlowActions = { triggerNodeChanges: (changes: NodeChange[]) => void; triggerEdgeChanges: (changes: EdgeChange[]) => void; panBy: PanBy; - fitView: (options?: FitViewOptions) => Promise; - fitViewSync: (options?: FitViewOptions) => boolean; setPaneClickDistance: (distance: number) => void; }; diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts index 6de98e3a..f1494bf4 100644 --- a/packages/react/src/utils/changes.ts +++ b/packages/react/src/utils/changes.ts @@ -11,13 +11,17 @@ import { } from '@xyflow/system'; import type { Node, Edge, InternalNode } from '../types'; -// This function applies changes to nodes or edges that are triggered by React Flow internally. -// When you drag a node for example, React Flow will send a position change update. -// This function then applies the changes and returns the updated elements. +/* + * This function applies changes to nodes or edges that are triggered by React Flow internally. + * When you drag a node for example, React Flow will send a position change update. + * This function then applies the changes and returns the updated elements. + */ function applyChanges(changes: any[], elements: any[]): any[] { const updatedElements: any[] = []; - // By storing a map of changes for each element, we can a quick lookup as we - // iterate over the elements array! + /* + * By storing a map of changes for each element, we can a quick lookup as we + * iterate over the elements array! + */ const changesMap = new Map(); const addItemChanges: any[] = []; @@ -26,15 +30,19 @@ function applyChanges(changes: any[], elements: any[]): any[] { addItemChanges.push(change); continue; } else if (change.type === 'remove' || change.type === 'replace') { - // For a 'remove' change we can safely ignore any other changes queued for - // the same element, it's going to be removed anyway! + /* + * For a 'remove' change we can safely ignore any other changes queued for + * the same element, it's going to be removed anyway! + */ changesMap.set(change.id, [change]); } else { const elementChanges = changesMap.get(change.id); if (elementChanges) { - // If we have some changes queued already, we can do a mutable update of - // that array and save ourselves some copying. + /* + * If we have some changes queued already, we can do a mutable update of + * that array and save ourselves some copying. + */ elementChanges.push(change); } else { changesMap.set(change.id, [change]); @@ -45,8 +53,10 @@ function applyChanges(changes: any[], elements: any[]): any[] { for (const element of elements) { const changes = changesMap.get(element.id); - // When there are no changes for an element we can just push it unmodified, - // no need to copy it. + /* + * When there are no changes for an element we can just push it unmodified, + * no need to copy it. + */ if (!changes) { updatedElements.push(element); continue; @@ -62,9 +72,11 @@ function applyChanges(changes: any[], elements: any[]): any[] { continue; } - // For other types of changes, we want to start with a shallow copy of the - // object so React knows this element has changed. Sequential changes will - /// each _mutate_ this object, so there's only ever one copy. + /** + * For other types of changes, we want to start with a shallow copy of the + * object so React knows this element has changed. Sequential changes will + * each _mutate_ this object, so there's only ever one copy. + */ const updatedElement = { ...element }; for (const change of changes) { @@ -74,8 +86,10 @@ function applyChanges(changes: any[], elements: any[]): any[] { updatedElements.push(updatedElement); } - // we need to wait for all changes to be applied before adding new items - // to be able to add them at the correct index + /* + * we need to wait for all changes to be applied before adding new items + * to be able to add them at the correct index + */ if (addItemChanges.length) { addItemChanges.forEach((change) => { if (change.index !== undefined) { @@ -133,22 +147,33 @@ function applyChange(change: any, element: any): any { /** * Drop in function that applies node changes to an array of nodes. * @public - * @remarks Various events on the component can produce an {@link NodeChange} that describes how to update the edges of your flow in some way. - If you don't need any custom behaviour, this util can be used to take an array of these changes and apply them to your edges. - * @param changes - Array of changes to apply - * @param nodes - Array of nodes to apply the changes to - * @returns Array of updated nodes + * @param changes - Array of changes to apply. + * @param nodes - Array of nodes to apply the changes to. + * @returns Array of updated nodes. * @example - * const onNodesChange = useCallback( - (changes) => { - setNodes((oldNodes) => applyNodeChanges(changes, oldNodes)); - }, - [setNodes], - ); - - return ( - - ); + *```tsx + *import { useState, useCallback } from 'react'; + *import { ReactFlow, applyNodeChanges, type Node, type Edge, type OnNodesChange } from '@xyflow/react'; + * + *export default function Flow() { + * const [nodes, setNodes] = useState([]); + * const [edges, setEdges] = useState([]); + * const onNodesChange: OnNodesChange = useCallback( + * (changes) => { + * setNodes((oldNodes) => applyNodeChanges(changes, oldNodes)); + * }, + * [setNodes], + * ); + * + * return ( + * + * ); + *} + *``` + * @remarks Various events on the component can produce an {@link NodeChange} + * that describes how to update the edges of your flow in some way. + * If you don't need any custom behaviour, this util can be used to take an array + * of these changes and apply them to your edges. */ export function applyNodeChanges( changes: NodeChange[], @@ -160,22 +185,33 @@ export function applyNodeChanges( /** * Drop in function that applies edge changes to an array of edges. * @public - * @remarks Various events on the component can produce an {@link EdgeChange} that describes how to update the edges of your flow in some way. - If you don't need any custom behaviour, this util can be used to take an array of these changes and apply them to your edges. - * @param changes - Array of changes to apply - * @param edges - Array of edge to apply the changes to - * @returns Array of updated edges + * @param changes - Array of changes to apply. + * @param edges - Array of edge to apply the changes to. + * @returns Array of updated edges. * @example + * ```tsx + *import { useState, useCallback } from 'react'; + *import { ReactFlow, applyEdgeChanges } from '@xyflow/react'; + * + *export default function Flow() { + * const [nodes, setNodes] = useState([]); + * const [edges, setEdges] = useState([]); * const onEdgesChange = useCallback( - (changes) => { - setEdges((oldEdges) => applyEdgeChanges(changes, oldEdges)); - }, - [setEdges], - ); - - return ( - - ); + * (changes) => { + * setEdges((oldEdges) => applyEdgeChanges(changes, oldEdges)); + * }, + * [setEdges], + * ); + * + * return ( + * + * ); + *} + *``` + * @remarks Various events on the component can produce an {@link EdgeChange} + * that describes how to update the edges of your flow in some way. + * If you don't need any custom behaviour, this util can be used to take an array + * of these changes and apply them to your edges. */ export function applyEdgeChanges( changes: EdgeChange[], @@ -205,9 +241,11 @@ export function getSelectionChanges( // we don't want to set all items to selected=false on the first selection if (!(item.selected === undefined && !willBeSelected) && item.selected !== willBeSelected) { if (mutateItem) { - // this hack is needed for nodes. When the user dragged a node, it's selected. - // When another node gets dragged, we need to deselect the previous one, - // in order to have only one selected node at a time - the onNodesChange callback comes too late here :/ + /* + * this hack is needed for nodes. When the user dragged a node, it's selected. + * When another node gets dragged, we need to deselect the previous one, + * in order to have only one selected node at a time - the onNodesChange callback comes too late here :/ + */ item.selected = willBeSelected; } changes.push(createSelectionChange(item.id, willBeSelected)); diff --git a/packages/react/src/utils/general.ts b/packages/react/src/utils/general.ts index 04608f74..c7c8a503 100644 --- a/packages/react/src/utils/general.ts +++ b/packages/react/src/utils/general.ts @@ -1,29 +1,57 @@ -import { type Ref, type RefAttributes, forwardRef } from 'react'; +import { type Ref, type RefAttributes, forwardRef, JSX } from 'react'; import { isNodeBase, isEdgeBase } from '@xyflow/system'; import type { Edge, Node } from '../types'; /** - * Test whether an object is useable as a Node + * Test whether an object is usable as an [`Node`](/api-reference/types/node). + * In TypeScript this is a type guard that will narrow the type of whatever you pass in to + * [`Node`](/api-reference/types/node) if it returns `true`. + * * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Node if it returns true - * @param element - The element to test - * @returns A boolean indicating whether the element is an Node + * @param element - The element to test. + * @returns Tests whether the provided value can be used as a `Node`. If you're using TypeScript, + * this function acts as a type guard and will narrow the type of the value to `Node` if it returns + * `true`. + * + * @example + * ```js + *import { isNode } from '@xyflow/react'; + * + *if (isNode(node)) { + * // ... + *} + *``` */ export const isNode = (element: unknown): element is NodeType => isNodeBase(element); /** - * Test whether an object is useable as an Edge + * Test whether an object is usable as an [`Edge`](/api-reference/types/edge). + * In TypeScript this is a type guard that will narrow the type of whatever you pass in to + * [`Edge`](/api-reference/types/edge) if it returns `true`. + * * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Edge if it returns true * @param element - The element to test - * @returns A boolean indicating whether the element is an Edge + * @returns Tests whether the provided value can be used as an `Edge`. If you're using TypeScript, + * this function acts as a type guard and will narrow the type of the value to `Edge` if it returns + * `true`. + * + * @example + * ```js + *import { isEdge } from '@xyflow/react'; + * + *if (isEdge(edge)) { + * // ... + *} + *``` */ export const isEdge = (element: unknown): element is EdgeType => isEdgeBase(element); -// eslint-disable-next-line @typescript-eslint/ban-types +// eslint-disable-next-line @typescript-eslint/no-empty-object-type export function fixedForwardRef( render: (props: P, ref: Ref) => JSX.Element ): (props: P & RefAttributes) => JSX.Element { diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 0a0e8306..b590226d 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,60 @@ # @xyflow/svelte +## 0.1.35 + +### Patch Changes + +- [#5158](https://github.com/xyflow/xyflow/pull/5158) [`06696060`](https://github.com/xyflow/xyflow/commit/0669606050bb2138a44a1591176ac8e16afeb0f1) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Fix typo in TSDoc comments `React Flow` -> `Svelte Flow` + +- Updated dependencies [[`02a3b746`](https://github.com/xyflow/xyflow/commit/02a3b74645799a3f0ce670b69365fa86ecb0616e), [`cbe305e1`](https://github.com/xyflow/xyflow/commit/cbe305e15a5c5d3b92583e0ec12364b2509f49bd), [`1f671bd4`](https://github.com/xyflow/xyflow/commit/1f671bd48f06230da841fdd1d7a312413ef16d03), [`aaebc462`](https://github.com/xyflow/xyflow/commit/aaebc462951ded8e91374c3e084d77af5ed7380a), [`6ec942fc`](https://github.com/xyflow/xyflow/commit/6ec942fc6501f81009c278cc995764bef3e8d03b)]: + - @xyflow/system@0.0.55 + +## 0.1.34 + +### Patch Changes + +- [#5139](https://github.com/xyflow/xyflow/pull/5139) [`89de9ca8`](https://github.com/xyflow/xyflow/commit/89de9ca83fbf9263a687a0f5f915efb2beb31654) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Use `rgba` for colors with opacity instead of `rgb` for `MiniMap` mask color + +- Updated dependencies [[`f819005b`](https://github.com/xyflow/xyflow/commit/f819005be362d044b16ce4c0b85432f3f300a13a), [`24a1bc89`](https://github.com/xyflow/xyflow/commit/24a1bc89348817ed9b5c87f74bf2519c705143be), [`36657cd6`](https://github.com/xyflow/xyflow/commit/36657cd66322c911e87eb37275c584a80025adfe), [`89de9ca8`](https://github.com/xyflow/xyflow/commit/89de9ca83fbf9263a687a0f5f915efb2beb31654), [`2ac6e155`](https://github.com/xyflow/xyflow/commit/2ac6e155e35256ca436281df16344366e7d05761), [`f0f378e5`](https://github.com/xyflow/xyflow/commit/f0f378e5b6918c2c30d9dc1e32587063cb942d4e)]: + - @xyflow/system@0.0.54 + +## 0.1.33 + +### Patch Changes + +- [#5124](https://github.com/xyflow/xyflow/pull/5124) [`b76f7f9e`](https://github.com/xyflow/xyflow/commit/b76f7f9eb4841f139b1468b8eda0430ddd19a1ae) Thanks [@bjornosal](https://github.com/bjornosal)! - Export NodeConnection type + +## 0.1.32 + +### Patch Changes + +- [#5059](https://github.com/xyflow/xyflow/pull/5059) [`065ff89d`](https://github.com/xyflow/xyflow/commit/065ff89d10488f9c76c56870511e45eaed299778) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Prevent onPaneClick when connection is in progress. Closes [#5057](https://github.com/xyflow/xyflow/issues/5057) + +- [#5067](https://github.com/xyflow/xyflow/pull/5067) [`cb685281`](https://github.com/xyflow/xyflow/commit/cb685281d0eaf03e9833271c31f92b1d143af2fe) Thanks [@peterkogo](https://github.com/peterkogo)! - Fix fitView not working immediately after adding new nodes + +- [#5093](https://github.com/xyflow/xyflow/pull/5093) [`65825e89`](https://github.com/xyflow/xyflow/commit/65825e89a6e2e7591087eb41ac89da4da7095f8f) Thanks [@moklick](https://github.com/moklick)! - Hidden nodes are not displayed in the mini map anymore + +- Updated dependencies [[`5d15b01b`](https://github.com/xyflow/xyflow/commit/5d15b01ba8cb349d6397a6ed8162848b4dfec293), [`cb685281`](https://github.com/xyflow/xyflow/commit/cb685281d0eaf03e9833271c31f92b1d143af2fe), [`a79f30b3`](https://github.com/xyflow/xyflow/commit/a79f30b3dd7c8ff6400c8d22214b2c2282e5bac1)]: + - @xyflow/system@0.0.53 + +## 0.1.31 + +### Patch Changes + +- [#5019](https://github.com/xyflow/xyflow/pull/5019) [`3e80317c`](https://github.com/xyflow/xyflow/commit/3e80317cf6da0e9fdc111c3ade88f2a88a10dbd6) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Add `"./package.json" to the `exports` field so that users can import it + +- Updated dependencies [[`99dd7d35`](https://github.com/xyflow/xyflow/commit/99dd7d3549e7423e7d103b2c956c8b37f5747b90)]: + - @xyflow/system@0.0.52 + +## 0.1.30 + +### Patch Changes + +- [#5010](https://github.com/xyflow/xyflow/pull/5010) [`6c121d42`](https://github.com/xyflow/xyflow/commit/6c121d427fea9a11e86a85f95d2c12ba8af34919) Thanks [@moklick](https://github.com/moklick)! - Add more TSDocs to components, hooks, utils funcs and types + +- Updated dependencies [[`6c121d42`](https://github.com/xyflow/xyflow/commit/6c121d427fea9a11e86a85f95d2c12ba8af34919), [`4947029c`](https://github.com/xyflow/xyflow/commit/4947029cd6cda0f695e1fb4815e4030adb232234), [`e8e0d684`](https://github.com/xyflow/xyflow/commit/e8e0d684957b95d53a6cc11598c8755ff02117c7)]: + - @xyflow/system@0.0.51 + ## 0.1.29 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index a7bc432a..46a28f7f 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -34,6 +34,7 @@ "type": "module", "module": "./dist/lib/index.js", "exports": { + "./package.json": "./package.json", ".": { "types": "./dist/lib/index.d.ts", "svelte": "./dist/lib/index.js", @@ -54,32 +55,32 @@ "@xyflow/system": "workspace:*" }, "devDependencies": { - "@sveltejs/adapter-auto": "^4.0.0", - "@sveltejs/kit": "^2.16.1", - "@sveltejs/package": "^2.3.9", + "@sveltejs/adapter-auto": "^6.0.0", + "@sveltejs/kit": "^2.20.4", + "@sveltejs/package": "^2.3.10", "@sveltejs/vite-plugin-svelte": "^5.0.3", - "@typescript-eslint/eslint-plugin": "^8.22.0", - "@typescript-eslint/parser": "^8.22.0", - "autoprefixer": "^10.4.20", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "autoprefixer": "^10.4.21", "cssnano": "^7.0.6", "dotenv": "^16.4.7", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.46.1", - "postcss": "^8.5.1", - "postcss-cli": "^11.0.0", + "eslint": "^9.24.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-svelte": "^3.5.1", + "postcss": "^8.5.3", + "postcss-cli": "^11.0.1", "postcss-combine-duplicated-selectors": "^10.0.3", "postcss-import": "^16.1.0", "postcss-nested": "^7.0.2", "postcss-rename": "^0.6.1", - "prettier": "^3.4.2", + "prettier": "^3.5.3", "prettier-plugin-svelte": "^3.3.3", - "svelte": "^5.19.5", - "svelte-check": "^4.1.4", - "svelte-eslint-parser": "^0.43.0", + "svelte": "^5.25.8", + "svelte-check": "^4.1.5", + "svelte-eslint-parser": "^1.1.2", "svelte-preprocess": "^6.0.3", "tslib": "^2.8.1", - "typescript": "^5.7.3" + "typescript": "^5.8.3" }, "peerDependencies": { "svelte": "^5.16.0" diff --git a/packages/svelte/src/lib/container/Pane/Pane.svelte b/packages/svelte/src/lib/container/Pane/Pane.svelte index cd9c0653..0d33557c 100644 --- a/packages/svelte/src/lib/container/Pane/Pane.svelte +++ b/packages/svelte/src/lib/container/Pane/Pane.svelte @@ -75,7 +75,8 @@ function onClick(event: MouseEvent) { // We prevent click events when the user let go of the selectionKey during a selection - if (selectionInProgress) { + // We also prevent click events when a connection is in progress + if (selectionInProgress || store.connection.inProgress) { selectionInProgress = false; return; } diff --git a/packages/svelte/src/lib/container/Viewport/Viewport.svelte b/packages/svelte/src/lib/container/Viewport/Viewport.svelte index 69d08fd8..821ce540 100644 --- a/packages/svelte/src/lib/container/Viewport/Viewport.svelte +++ b/packages/svelte/src/lib/container/Viewport/Viewport.svelte @@ -3,12 +3,13 @@ import type { Snippet } from 'svelte'; let { store, children }: { store: SvelteFlowStore; children: Snippet } = $props(); + + let { x, y, zoom } = $derived(store._viewport);
{@render children()}
diff --git a/packages/svelte/src/lib/container/Zoom/Zoom.svelte b/packages/svelte/src/lib/container/Zoom/Zoom.svelte index e950b7f5..6b570e50 100644 --- a/packages/svelte/src/lib/container/Zoom/Zoom.svelte +++ b/packages/svelte/src/lib/container/Zoom/Zoom.svelte @@ -1,5 +1,4 @@
{ + performance.mark('svelte-flow-zoom-transform-change'); + store.viewport = { x: transform[0], y: transform[1], zoom: transform[2] }; + } }} > {@render children()} diff --git a/packages/svelte/src/lib/index.ts b/packages/svelte/src/lib/index.ts index 6ce24219..96c5126f 100644 --- a/packages/svelte/src/lib/index.ts +++ b/packages/svelte/src/lib/index.ts @@ -107,7 +107,8 @@ export { type ResizeParams, type ResizeParamsWithDirection, type ResizeDragEvent, - type IsValidConnection + type IsValidConnection, + type NodeConnection } from '@xyflow/system'; // system utils diff --git a/packages/svelte/src/lib/plugins/Minimap/Minimap.svelte b/packages/svelte/src/lib/plugins/Minimap/Minimap.svelte index 08aa963e..7aac953c 100644 --- a/packages/svelte/src/lib/plugins/Minimap/Minimap.svelte +++ b/packages/svelte/src/lib/plugins/Minimap/Minimap.svelte @@ -63,7 +63,10 @@ }); let boundingRect = $derived( store.nodeLookup.size > 0 - ? getBoundsOfRects(getInternalNodesBounds(store.nodeLookup), viewBB) + ? getBoundsOfRects( + getInternalNodesBounds(store.nodeLookup, { filter: (n) => !n.hidden }), + viewBB + ) : viewBB ); let scaledWidth = $derived(boundingRect.width / width); diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index f31c479e..e689d6e1 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -1,5 +1,4 @@ import { - fitView as fitViewSystem, panBy as panBySystem, updateNodeInternals as updateNodeInternalsSystem, addEdge as addEdgeUtil, @@ -13,9 +12,7 @@ import { type CoordinateExtent, type UpdateConnection, type ConnectionState, - getFitViewNodes, - updateAbsolutePositions, - getDimensions + updateAbsolutePositions } from '@xyflow/system'; import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types'; @@ -72,14 +69,8 @@ export function createStore(signals: StoreSignals): SvelteFlowStore { nodeExtent: store.nodeExtent }); - if (!store.fitViewOnInitDone && store.fitViewOnInit) { - const fitViewOnInitDone = fitViewSync({ - ...store.fitViewOptions, - nodes: store.fitViewOptions?.nodes - }); - if (fitViewOnInitDone) { - store.fitViewOnInitDone = fitViewOnInitDone; - } + if (store.fitViewQueued) { + store.resolveFitView(); } const newNodes = new Map(); @@ -120,52 +111,41 @@ export function createStore(signals: StoreSignals): SvelteFlowStore { } function fitView(options?: FitViewOptions) { - const panZoom = store.panZoom; - const domNode = store.domNode; + // const panZoom = store.panZoom; + // const domNode = store.domNode; - if (!panZoom || !domNode) { - return Promise.resolve(false); - } + // if (!panZoom || !domNode) { + // return Promise.resolve(false); + // } - const { width, height } = getDimensions(domNode); + // const { width, height } = getDimensions(domNode); - const fitViewNodes = getFitViewNodes(store.nodeLookup, options); + // const fitViewNodes = getFitViewNodes(store.nodeLookup, options); - return fitViewSystem( - { - nodes: fitViewNodes, - width, - height, - minZoom: store.minZoom, - maxZoom: store.maxZoom, - panZoom - }, - options - ); - } + // return fitViewSystem( + // { + // nodes: fitViewNodes, + // width, + // height, + // minZoom: store.minZoom, + // maxZoom: store.maxZoom, + // panZoom + // }, + // options + // );e3 + // We either create a new Promise or reuse the existing one + // Even if fitView is called multiple times in a row, we only end up with a single Promise + const fitViewResolver = store.fitViewResolver ?? Promise.withResolvers(); - function fitViewSync(options?: FitViewOptions) { - const panZoom = store.panZoom; + // We schedule a fitView by setting fitViewQueued and triggering a setNodes + store.fitViewQueued = true; + store.fitViewOptions = options; + store.fitViewResolver = fitViewResolver; - if (!panZoom) { - return false; - } + // We need to update the nodes so that adoptUserNodes is triggered + store.nodes = [...store.nodes]; - const fitViewNodes = getFitViewNodes(store.nodeLookup, options); - - fitViewSystem( - { - nodes: fitViewNodes, - width: store.width, - height: store.height, - minZoom: store.minZoom, - maxZoom: store.maxZoom, - panZoom - }, - options - ); - - return fitViewNodes.size > 0; + return fitViewResolver.promise; } function zoomBy(factor: number, options?: ViewportHelperFunctionOptions) { @@ -350,10 +330,11 @@ export function createStore(signals: StoreSignals): SvelteFlowStore { } function reset() { - store.fitViewOnInitDone = false; store.selectionRect = null; store.selectionRectMode = null; + store.resetStoreValues(); + unselectNodesAndEdges(); cancelConnection(); } @@ -366,7 +347,7 @@ export function createStore(signals: StoreSignals): SvelteFlowStore { updateNodeInternals, zoomIn, zoomOut, - fitView: (options?: FitViewOptions) => fitView(options), + fitView, setMinZoom, setMaxZoom, setTranslateExtent, diff --git a/packages/svelte/src/lib/store/initial-store.svelte.ts b/packages/svelte/src/lib/store/initial-store.svelte.ts index 03cdba63..8278658d 100644 --- a/packages/svelte/src/lib/store/initial-store.svelte.ts +++ b/packages/svelte/src/lib/store/initial-store.svelte.ts @@ -27,7 +27,8 @@ import { type ParentLookup, pointToRendererPoint, type ColorModeClass, - type Transform + type Transform, + fitViewport } from '@xyflow/system'; import DefaultNode from '$lib/components/nodes/DefaultNode.svelte'; @@ -51,7 +52,6 @@ import type { OnBeforeDelete, IsValidConnection, Edge, - Node, EdgeLayouted, InternalNode } from '$lib/types'; @@ -78,14 +78,54 @@ export const getInitialStore = (signals: StoreSignals) => { // We use a class here, because Svelte adds getters & setter for us. // Inline classes have some performance implications but we just call it once (max twice). class SvelteFlowStore { - _nodes: Node[] = $derived.by(() => { - adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, { + flowId: string = $derived(signals.props.id ?? '1'); + domNode = $state(null); + panZoom: PanZoomInstance | null = $state(null); + width = $state(signals.width ?? 0); + height = $state(signals.height ?? 0); + + nodesInitialized: boolean = $derived.by(() => { + const nodesInitialized = adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, { nodeExtent: this.nodeExtent, nodeOrigin: this.nodeOrigin, elevateNodesOnSelect: signals.props.elevateNodesOnSelect ?? true, checkEquality: true }); - return signals.nodes; + + if (this.fitViewQueued && nodesInitialized) { + if (this.fitViewOptions?.duration) { + this.resolveFitView(); + } else { + /** + * When no duration is set, viewport is set immediately which prevents an update + * I do not understand why, however we are setting state in a derived which is a no-go + */ + queueMicrotask(() => { + this.resolveFitView(); + }); + } + } + + return nodesInitialized; + }); + edgesInitialized: boolean = $state(false); + viewportInitialized: boolean = $derived(this.panZoom !== null); + + // TODO: Figure out initialized + _initialNodesLength: number = signals.nodes?.length ?? 0; + _initialEdgesLength: number = signals.edges?.length ?? 0; + initialized: boolean = $derived.by(() => { + let initialized = false; + // if it hasn't been initialised check if it's now + if (this._initialNodesLength === 0) { + initialized = this.viewportInitialized; + } else if (this._initialEdgesLength === 0) { + initialized = this.viewportInitialized && this.nodesInitialized; + } else { + initialized = this.viewportInitialized && this.nodesInitialized && this.edgesInitialized; + } + + return initialized; }); _edges: Edge[] = $derived.by(() => { @@ -94,7 +134,9 @@ export const getInitialStore = (signals: StoreSignals) => { }); get nodes() { - return this._nodes; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + this.nodesInitialized; + return signals.nodes; } set nodes(nodes) { signals.nodes = nodes; @@ -116,7 +158,7 @@ export const getInitialStore = (signals: StoreSignals) => { const { // We need to access this._nodes to trigger on changes // eslint-disable-next-line @typescript-eslint/no-unused-vars - _nodes, + nodes, _edges: edges, _prevVisibleEdges: previousEdges, nodeLookup, @@ -174,11 +216,6 @@ export const getInitialStore = (signals: StoreSignals) => { signals.elementsSelectable = value; } - domNode = $state(null); - width = $state(signals.width ?? 0); - height = $state(signals.height ?? 0); - - flowId: string = $derived(signals.props.id ?? '1'); minZoom: number = $derived(signals.props.minZoom ?? 0.5); maxZoom: number = $derived(signals.props.maxZoom ?? 2); @@ -192,11 +229,10 @@ export const getInitialStore = (signals: StoreSignals) => { autoPanOnNodeDrag: boolean = $derived(signals.props.autoPanOnNodeDrag ?? true); autoPanOnConnect: boolean = $derived(signals.props.autoPanOnConnect ?? true); - fitViewOnInitDone: boolean = $state(false); - fitViewOnInit: boolean = $derived(signals.props.fitView ?? false); - fitViewOptions: FitViewOptions | undefined = $derived(signals.props.fitViewOptions); + fitViewQueued: boolean = signals.props.fitView ?? false; + fitViewOptions: FitViewOptions | undefined = signals.props.fitViewOptions; + fitViewResolver: PromiseWithResolvers | null = null; - panZoom: PanZoomInstance | null = $state(null); snapGrid: SnapGrid | null = $derived(signals.props.snapGrid ?? null); dragging: boolean = $state(false); @@ -215,15 +251,16 @@ export const getInitialStore = (signals: StoreSignals) => { // _viewport is the internal viewport. // when binding to viewport, we operate on signals.viewport instead + initial: boolean = true; _viewport: Viewport = $state(signals.props.initialViewport ?? { x: 0, y: 0, zoom: 1 }); get viewport() { return signals.viewport ?? this._viewport; } - set viewport(viewport: Viewport) { + set viewport(newViewport: Viewport) { if (signals.viewport) { - signals.viewport = viewport; + signals.viewport = newViewport; } - this._viewport = viewport; + this._viewport = newViewport; } // _connection is viewport independent and originating from XYHandle @@ -271,25 +308,32 @@ export const getInitialStore = (signals: StoreSignals) => { onconnectend?: OnConnectEnd = $derived(signals.props.onconnectend); onbeforedelete?: OnBeforeDelete = $derived(signals.props.onbeforedelete); - nodesInitialized: boolean = $state(false); - edgesInitialized: boolean = $state(false); - viewportInitialized: boolean = $state(false); - - _initialNodesLength: number = signals.nodes?.length ?? 0; - _initialEdgesLength: number = signals.edges?.length ?? 0; - initialized: boolean = $derived.by(() => { - let initialized = false; - // if it hasn't been initialised check if it's now - if (this._initialNodesLength === 0) { - initialized = this.viewportInitialized; - } else if (this._initialEdgesLength === 0) { - initialized = this.viewportInitialized && this.nodesInitialized; - } else { - initialized = this.viewportInitialized && this.nodesInitialized && this.edgesInitialized; + resolveFitView = async () => { + if (!this.panZoom) { + return; } - return initialized; - }); + await fitViewport( + { + nodes: this.nodeLookup, + width: this.width, + height: this.height, + panZoom: this.panZoom, + minZoom: this.minZoom, + maxZoom: this.maxZoom + }, + this.fitViewOptions + ); + + this.fitViewResolver?.resolve(true); + /** + * wait for the fitViewport to resolve before deleting the resolver, + * we want to reuse the old resolver if the user calls fitView again in the mean time + */ + this.fitViewQueued = false; + this.fitViewOptions = undefined; + this.fitViewResolver = null; + }; _prefersDark = new MediaQuery( '(prefers-color-scheme: dark)', @@ -328,7 +372,6 @@ export const getInitialStore = (signals: StoreSignals) => { // Only way to check if an object is a proxy // is to see if is failes to perform a structured clone -// TODO: is $state.raw really nessessary? function warnIfDeeplyReactive(array: unknown[] | undefined, name: string) { try { if (array && array.length > 0) { diff --git a/packages/svelte/src/lib/types/edges.ts b/packages/svelte/src/lib/types/edges.ts index a21a19a1..4994c948 100644 --- a/packages/svelte/src/lib/types/edges.ts +++ b/packages/svelte/src/lib/types/edges.ts @@ -12,7 +12,9 @@ import type { Node } from '$lib/types'; import type { ClassValue } from 'svelte/elements'; /** - * The Edge type is mainly used for the `edges` that get passed to the SvelteFlow component. + * An `Edge` is the complete description with everything Svelte Flow needs to know in order to + * render it. + * @public */ export type Edge< EdgeData extends Record = Record, diff --git a/packages/svelte/src/lib/utils/index.ts b/packages/svelte/src/lib/utils/index.ts index 10f205ca..ed1aef35 100644 --- a/packages/svelte/src/lib/utils/index.ts +++ b/packages/svelte/src/lib/utils/index.ts @@ -3,7 +3,7 @@ import { isNodeBase, isEdgeBase } from '@xyflow/system'; import type { Edge, Node } from '$lib/types'; /** - * Test whether an object is useable as a Node + * Test whether an object is usable as a Node * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Node if it returns true * @param element - The element to test @@ -13,7 +13,7 @@ export const isNode = (element: unknown): element isNodeBase(element); /** - * Test whether an object is useable as an Edge + * Test whether an object is usable as an Edge * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Edge if it returns true * @param element - The element to test diff --git a/packages/system/CHANGELOG.md b/packages/system/CHANGELOG.md index a1613ca3..57cef024 100644 --- a/packages/system/CHANGELOG.md +++ b/packages/system/CHANGELOG.md @@ -1,5 +1,61 @@ # @xyflow/system +## 0.0.55 + +### Patch Changes + +- [#5156](https://github.com/xyflow/xyflow/pull/5156) [`02a3b746`](https://github.com/xyflow/xyflow/commit/02a3b74645799a3f0ce670b69365fa86ecb0616e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type GetSmoothStepPathParams` and `getSmoothStepPath` function + +- [#5168](https://github.com/xyflow/xyflow/pull/5168) [`cbe305e1`](https://github.com/xyflow/xyflow/commit/cbe305e15a5c5d3b92583e0ec12364b2509f49bd) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `getOutgoers`, `getIncomers` and `type GetNodesBoundsParams` + +- [#5169](https://github.com/xyflow/xyflow/pull/5169) [`1f671bd4`](https://github.com/xyflow/xyflow/commit/1f671bd48f06230da841fdd1d7a312413ef16d03) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type ReconnectEdgeOptions` and `getViewportForBounds` + +- [#5155](https://github.com/xyflow/xyflow/pull/5155) [`aaebc462`](https://github.com/xyflow/xyflow/commit/aaebc462951ded8e91374c3e084d77af5ed7380a) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type GetStraightPathParams` and `getStraightPath` function + +- [#5157](https://github.com/xyflow/xyflow/pull/5157) [`6ec942fc`](https://github.com/xyflow/xyflow/commit/6ec942fc6501f81009c278cc995764bef3e8d03b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `type GetBezierPathParams` and `getBezierPath` function + +## 0.0.54 + +### Patch Changes + +- [#5147](https://github.com/xyflow/xyflow/pull/5147) [`f819005b`](https://github.com/xyflow/xyflow/commit/f819005be362d044b16ce4c0b85432f3f300a13a) Thanks [@moklick](https://github.com/moklick)! - Pass dimensions to final resize change event + +- [#5142](https://github.com/xyflow/xyflow/pull/5142) [`24a1bc89`](https://github.com/xyflow/xyflow/commit/24a1bc89348817ed9b5c87f74bf2519c705143be) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `HandleProps`, `NodeBase` and `InternalNodeBase` + +- [#5136](https://github.com/xyflow/xyflow/pull/5136) [`36657cd6`](https://github.com/xyflow/xyflow/commit/36657cd66322c911e87eb37275c584a80025adfe) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `EdgeBase` + +- [#5139](https://github.com/xyflow/xyflow/pull/5139) [`89de9ca8`](https://github.com/xyflow/xyflow/commit/89de9ca83fbf9263a687a0f5f915efb2beb31654) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Use `rgba` for colors with opacity instead of `rgb` for `MiniMap` mask color + +- [#5148](https://github.com/xyflow/xyflow/pull/5148) [`2ac6e155`](https://github.com/xyflow/xyflow/commit/2ac6e155e35256ca436281df16344366e7d05761) Thanks [@moklick](https://github.com/moklick)! - Prevent browser zoom for pinch zoom gestures on nowheel elements + +- [#5137](https://github.com/xyflow/xyflow/pull/5137) [`f0f378e5`](https://github.com/xyflow/xyflow/commit/f0f378e5b6918c2c30d9dc1e32587063cb942d4e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Improve TSDoc comments for `Connection` and `ConnectionInProgress` + +## 0.0.53 + +### Patch Changes + +- [#5118](https://github.com/xyflow/xyflow/pull/5118) [`5d15b01b`](https://github.com/xyflow/xyflow/commit/5d15b01ba8cb349d6397a6ed8162848b4dfec293) Thanks [@moklick](https://github.com/moklick)! - Do not swallow key events when a button is focused + +- [#5067](https://github.com/xyflow/xyflow/pull/5067) [`cb685281`](https://github.com/xyflow/xyflow/commit/cb685281d0eaf03e9833271c31f92b1d143af2fe) Thanks [@peterkogo](https://github.com/peterkogo)! - Fix fitView not working immediately after adding new nodes + +- [#5091](https://github.com/xyflow/xyflow/pull/5091) [`a79f30b3`](https://github.com/xyflow/xyflow/commit/a79f30b3dd7c8ff6400c8d22214b2c2282e5bac1) Thanks [@moklick](https://github.com/moklick)! - Add center-left and center-right as a panel position + +## 0.0.52 + +### Patch Changes + +- [#5052](https://github.com/xyflow/xyflow/pull/5052) [`99dd7d35`](https://github.com/xyflow/xyflow/commit/99dd7d3549e7423e7d103b2c956c8b37f5747b90) Thanks [@moklick](https://github.com/moklick)! - Show an error if user drags uninitialized node + +## 0.0.51 + +### Patch Changes + +- [#5010](https://github.com/xyflow/xyflow/pull/5010) [`6c121d42`](https://github.com/xyflow/xyflow/commit/6c121d427fea9a11e86a85f95d2c12ba8af34919) Thanks [@moklick](https://github.com/moklick)! - Add more TSDocs to components, hooks, utils funcs and types + +- [#4990](https://github.com/xyflow/xyflow/pull/4990) [`4947029c`](https://github.com/xyflow/xyflow/commit/4947029cd6cda0f695e1fb4815e4030adb232234) Thanks [@damianstasik](https://github.com/damianstasik)! - Make it possible to stop autoPanOnDrag by setting it to false + +- [#5003](https://github.com/xyflow/xyflow/pull/5003) [`e8e0d684`](https://github.com/xyflow/xyflow/commit/e8e0d684957b95d53a6cc11598c8755ff02117c7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - repair lint command + ## 0.0.50 ### Patch Changes diff --git a/packages/system/package.json b/packages/system/package.json index c7b1ee03..81582405 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/system", - "version": "0.0.50", + "version": "0.0.55", "description": "xyflow core system that powers React Flow and Svelte Flow.", "keywords": [ "node-based UI", @@ -63,7 +63,7 @@ "@xyflow/eslint-config": "workspace:*", "@xyflow/rollup-config": "workspace:*", "@xyflow/tsconfig": "workspace:*", - "typescript": "5.1.3" + "typescript": "5.4.5" }, "rollup": { "globals": { diff --git a/packages/system/src/constants.ts b/packages/system/src/constants.ts index 921189fa..9bb65656 100644 --- a/packages/system/src/constants.ts +++ b/packages/system/src/constants.ts @@ -26,6 +26,8 @@ export const errorMessages = { `It seems that you haven't loaded the styles. Please import '@xyflow/${lib}/dist/style.css' or base.css to make sure everything is working properly.`, error014: () => 'useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.', + error015: () => + 'It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs.', }; export const infiniteExtent: CoordinateExtent = [ diff --git a/packages/system/src/styles/init.css b/packages/system/src/styles/init.css index e167c53f..ca4d6de7 100644 --- a/packages/system/src/styles/init.css +++ b/packages/system/src/styles/init.css @@ -13,7 +13,7 @@ --xy-attribution-background-color-default: rgba(255, 255, 255, 0.5); --xy-minimap-background-color-default: #fff; - --xy-minimap-mask-background-color-default: rgb(240, 240, 240, 0.6); + --xy-minimap-mask-background-color-default: rgba(240, 240, 240, 0.6); --xy-minimap-mask-stroke-color-default: transparent; --xy-minimap-mask-stroke-width-default: 1; --xy-minimap-node-background-color-default: #e2e2e2; @@ -37,7 +37,7 @@ --xy-attribution-background-color-default: rgba(150, 150, 150, 0.25); --xy-minimap-background-color-default: #141414; - --xy-minimap-mask-background-color-default: rgb(60, 60, 60, 0.6); + --xy-minimap-mask-background-color-default: rgba(60, 60, 60, 0.6); --xy-minimap-mask-stroke-color-default: transparent; --xy-minimap-mask-stroke-width-default: 1; --xy-minimap-node-background-color-default: #2b2b2b; @@ -278,6 +278,14 @@ svg.xy-flow__connectionline { bottom: 0; } + &.top, + &.bottom { + &.center { + left: 50%; + transform: translateX(-50%); + } + } + &.left { left: 0; } @@ -286,9 +294,12 @@ svg.xy-flow__connectionline { right: 0; } - &.center { - left: 50%; - transform: translateX(-50%); + &.left, + &.right { + &.center { + top: 50%; + transform: translateY(-50%); + } } } diff --git a/packages/system/src/types/changes.ts b/packages/system/src/types/changes.ts index 9b232733..8ab81a37 100644 --- a/packages/system/src/types/changes.ts +++ b/packages/system/src/types/changes.ts @@ -42,7 +42,10 @@ export type NodeReplaceChange = { }; /** - * Union type of all possible node changes. + * The [`onNodesChange`](/api-reference/react-flow#on-nodes-change) callback takes + *an array of `NodeChange` objects that you should use to update your flow's state. + *The `NodeChange` type is a union of six different object types that represent that + *various ways an node can change in a flow. * @public */ export type NodeChange = @@ -67,6 +70,14 @@ export type EdgeReplaceChange = { type: 'replace'; }; +/** + * The [`onEdgesChange`](/api-reference/react-flow#on-edges-change) callback takes + *an array of `EdgeChange` objects that you should use to update your flow's state. + *The `EdgeChange` type is a union of four different object types that represent that + *various ways an edge can change in a flow. + * + * @public + */ export type EdgeChange = | EdgeSelectionChange | EdgeRemoveChange diff --git a/packages/system/src/types/edges.ts b/packages/system/src/types/edges.ts index 39dc97bd..c0568200 100644 --- a/packages/system/src/types/edges.ts +++ b/packages/system/src/types/edges.ts @@ -4,40 +4,41 @@ export type EdgeBase< EdgeData extends Record = Record, EdgeType extends string | undefined = string | undefined > = { - /** Unique id of an edge */ + /** Unique id of an edge. */ id: string; - /** Type of an edge defined in edgeTypes */ + /** Type of edge defined in `edgeTypes`. */ type?: EdgeType; - /** Id of source node */ + /** Id of source node. */ source: string; - /** Id of target node */ + /** Id of target node. */ target: string; - /** Id of source handle - * only needed if there are multiple handles per node - */ + /** Id of source handle, only needed if there are multiple handles per node. */ sourceHandle?: string | null; - /** Id of target handle - * only needed if there are multiple handles per node - */ + /** Id of target handle, only needed if there are multiple handles per node. */ targetHandle?: string | null; animated?: boolean; hidden?: boolean; deletable?: boolean; selectable?: boolean; - /** Arbitrary data passed to an edge */ + /** Arbitrary data passed to an edge. */ data?: EdgeData; selected?: boolean; - /** Set the marker on the beginning of an edge + /** + * Set the marker on the beginning of an edge. * @example 'arrow', 'arrowclosed' or custom marker */ markerStart?: EdgeMarkerType; - /** Set the marker on the end of an edge + /** + * Set the marker on the end of an edge. * @example 'arrow', 'arrowclosed' or custom marker */ markerEnd?: EdgeMarkerType; zIndex?: number; ariaLabel?: string; - /** Padding around the edge where interaction is still possible */ + /** + * ReactFlow renders an invisible path around each edge to make them easier to click or tap on. + * This property sets the width of that invisible path. + */ interactionWidth?: number; }; @@ -54,11 +55,24 @@ export type BezierPathOptions = { curvature?: number; }; +/** + * @inline + */ export type DefaultEdgeOptionsBase = Omit< EdgeType, 'id' | 'source' | 'target' | 'sourceHandle' | 'targetHandle' | 'selected' >; +/** + * If you set the `connectionLineType` prop on your [``](/api-reference/react-flow#connection-connectionLineType) + *component, it will dictate the style of connection line rendered when creating + *new edges. + * + * @public + * + * @remarks If you choose to render a custom connection line component, this value will be + *passed to your component as part of its [`ConnectionLineComponentProps`](/api-reference/types/connection-line-component-props). + */ export enum ConnectionLineType { Bezier = 'default', Straight = 'straight', @@ -67,6 +81,13 @@ export enum ConnectionLineType { SimpleBezier = 'simplebezier', } +/** + * Edges can optionally have markers at the start and end of an edge. The `EdgeMarker` + *type is used to configure those markers! Check the docs for [`MarkerType`](/api-reference/types/marker-type) + *for details on what types of edge marker are available. + * + * @public + */ export type EdgeMarker = { type: MarkerType; color?: string; @@ -79,6 +100,12 @@ export type EdgeMarker = { export type EdgeMarkerType = string | EdgeMarker; +/** + * Edges may optionally have a marker on either end. The MarkerType type enumerates + * the options available to you when configuring a given marker. + * + * @public + */ export enum MarkerType { Arrow = 'arrow', ArrowClosed = 'arrowclosed', @@ -88,6 +115,9 @@ export type MarkerProps = EdgeMarker & { id: string; }; +/** + * @inline + */ export type EdgePosition = { sourceX: number; sourceY: number; diff --git a/packages/system/src/types/general.ts b/packages/system/src/types/general.ts index 3c6eed52..a2fba7dd 100644 --- a/packages/system/src/types/general.ts +++ b/packages/system/src/types/general.ts @@ -2,8 +2,7 @@ import type { Selection as D3Selection } from 'd3-selection'; import type { D3DragEvent, SubjectPosition } from 'd3-drag'; import type { ZoomBehavior } from 'd3-zoom'; -// this is needed for the Selection type to include the transition function :/ -// eslint-disable-next-line @typescript-eslint/no-unused-vars +// eslint-disable-next-line @typescript-eslint/no-unused-vars -- this is needed for the Selection type to include the transition function :/ import type { Transition } from 'd3-transition'; import type { XYPosition, Rect, Position } from './utils'; @@ -26,22 +25,46 @@ export type SetViewport = (viewport: Viewport, options?: ViewportHelperFunctionO export type SetCenter = (x: number, y: number, options?: SetCenterOptions) => Promise; export type FitBounds = (bounds: Rect, options?: FitBoundsOptions) => Promise; +/** + * The `Connection` type is the basic minimal description of an [`Edge`](/api-reference/types/edge) + * between two nodes. The [`addEdge`](/api-reference/utils/add-edge) util can be used to upgrade + * a `Connection` to an [`Edge`](/api-reference/types/edge). + * + * @public + */ export type Connection = { + /** The id of the node this connection originates from. */ source: string; + /** The id of the node this connection terminates at. */ target: string; + /** When not `null`, the id of the handle on the source node that this connection originates from. */ sourceHandle: string | null; + /** When not `null`, the id of the handle on the target node that this connection terminates at. */ targetHandle: string | null; }; -// TODO: remove in next version +/** + * The `HandleConnection` type is an extension of a basic [Connection](/api-reference/types/connection) that includes the `edgeId`. + */ export type HandleConnection = Connection & { edgeId: string; }; +/** + * The `NodeConnection` type is an extension of a basic [Connection](/api-reference/types/connection) that includes the `edgeId`. + * + */ export type NodeConnection = Connection & { edgeId: string; }; +/** + * The `ConnectionMode` is used to set the mode of connection between nodes. + * The `Strict` mode is the default one and only allows source to target edges. + * `Loose` mode allows source to source and target to target edges as well. + * + * @public + */ export enum ConnectionMode { Strict = 'strict', Loose = 'loose', @@ -59,6 +82,9 @@ export type OnConnectEnd = (event: MouseEvent | TouchEvent, connectionState: Fin export type IsValidConnection = (edge: EdgeBase | Connection) => boolean; +/** + * @inline + */ export type FitViewParamsBase = { nodes: Map>; width: number; @@ -68,8 +94,25 @@ export type FitViewParamsBase = { maxZoom: number; }; +export type PaddingUnit = 'px' | '%'; +export type PaddingWithUnit = `${number}${PaddingUnit}` | number; + +export type Padding = + | PaddingWithUnit + | { + top?: PaddingWithUnit; + right?: PaddingWithUnit; + bottom?: PaddingWithUnit; + left?: PaddingWithUnit; + x?: PaddingWithUnit; + y?: PaddingWithUnit; + }; + +/** + * @inline + */ export type FitViewOptionsBase = { - padding?: number; + padding?: Padding; includeHiddenNodes?: boolean; minZoom?: number; maxZoom?: number; @@ -77,6 +120,17 @@ export type FitViewOptionsBase = { nodes?: (NodeType | { id: string })[]; }; +/** + * Internally, React Flow maintains a coordinate system that is independent of the + * rest of the page. The `Viewport` type tells you where in that system your flow + * is currently being display at and how zoomed in or out it is. + * + * @public + * @remarks A `Transform` has the same properties as the viewport, but they represent + * different things. Make sure you don't get them muddled up or things will start + * to look weird! + * + */ export type Viewport = { x: number; y: number; @@ -87,12 +141,23 @@ export type KeyCode = string | Array; export type SnapGrid = [number, number]; +/** + * This enum is used to set the different modes of panning the viewport when the + * user scrolls. The `Free` mode allows the user to pan in any direction by scrolling + * with a device like a trackpad. The `Vertical` and `Horizontal` modes restrict + * scroll panning to only the vertical or horizontal axis, respectively. + * + * @public + */ export enum PanOnScrollMode { Free = 'free', Vertical = 'vertical', Horizontal = 'horizontal', } +/** + * @inline + */ export type ViewportHelperFunctionOptions = { duration?: number; }; @@ -113,7 +178,23 @@ export type D3ZoomHandler = (this: Element, event: any, d: unknown) => void; export type UpdateNodeInternals = (nodeId: string | string[]) => void; -export type PanelPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'; +/** + * This type is mostly used to help position things on top of the flow viewport. For + * example both the [``](/api-reference/components/minimap) and + * [``](/api-reference/components/controls) components take a `position` + * prop of this type. + * + * @public + */ +export type PanelPosition = + | 'top-left' + | 'top-center' + | 'top-right' + | 'bottom-left' + | 'bottom-center' + | 'bottom-right' + | 'center-left' + | 'center-right'; export type ProOptions = { account?: string; @@ -163,17 +244,37 @@ export type NoConnection = { toNode: null; }; export type ConnectionInProgress = { + /** Indicates whether a connection is currently in progress. */ inProgress: true; + /** + * If an ongoing connection is above a handle or inside the connection radius, this will be `true` + * or `false`, otherwise `null`. + */ isValid: boolean | null; + /** Returns the xy start position or `null` if no connection is in progress. */ from: XYPosition; + /** Returns the start handle or `null` if no connection is in progress. */ fromHandle: Handle; + /** Returns the side (called position) of the start handle or `null` if no connection is in progress. */ fromPosition: Position; + /** Returns the start node or `null` if no connection is in progress. */ fromNode: NodeType; + /** Returns the xy end position or `null` if no connection is in progress. */ to: XYPosition; + /** Returns the end handle or `null` if no connection is in progress. */ toHandle: Handle | null; + /** Returns the side (called position) of the end handle or `null` if no connection is in progress. */ toPosition: Position; + /** Returns the end node or `null` if no connection is in progress. */ toNode: NodeType | null; }; + +/** + * The `ConnectionState` type bundles all information about an ongoing connection. + * It is returned by the [`useConnection`](/api-reference/hooks/use-connection) hook. + * + * @public + */ export type ConnectionState = | ConnectionInProgress | NoConnection; diff --git a/packages/system/src/types/handles.ts b/packages/system/src/types/handles.ts index 9cf2a1dd..a8b51aa3 100644 --- a/packages/system/src/types/handles.ts +++ b/packages/system/src/types/handles.ts @@ -14,26 +14,44 @@ export type Handle = { }; export type HandleProps = { - /** Type of the handle + /** + * Type of the handle. + * @default "source" * @example HandleType.Source, HandleType.Target */ type: HandleType; - /** Position of the handle - * @example Position.TopLeft, Position.TopRight, - * Position.BottomLeft, Position.BottomRight + /** + * The position of the handle relative to the node. In a horizontal flow source handles are + * typically `Position.Right` and in a vertical flow they are typically `Position.Top`. + * @default Position.Top + * @example Position.TopLeft, Position.TopRight, Position.BottomLeft, Position.BottomRight */ position: Position; - /** Should you be able to connect to/from this handle */ + /** + * Should you be able to connect to/from this handle. + * @default true + */ isConnectable?: boolean; - /** Should you be able to connect from this handle */ + /** + * Dictates whether a connection can start from this handle. + * @default true + */ isConnectableStart?: boolean; - /** Should you be able to connect to this handle */ + /** + * Dictates whether a connection can end on this handle. + * @default true + */ isConnectableEnd?: boolean; - /** Callback if connection is valid + /** + * Called when a connection is dragged to this handle. You can use this callback to perform some + * custom validation logic based on the connection target and source, for example. Where possible, + * we recommend you move this logic to the `isValidConnection` prop on the main ReactFlow + * component for performance reasons. * @remarks connection becomes an edge if isValidConnection returns true */ isValidConnection?: IsValidConnection; - /** Id of the handle + /** + * Id of the handle. * @remarks optional if there is only one handle of this type */ id?: string | null; diff --git a/packages/system/src/types/nodes.ts b/packages/system/src/types/nodes.ts index 92261205..b32d58c5 100644 --- a/packages/system/src/types/nodes.ts +++ b/packages/system/src/types/nodes.ts @@ -4,6 +4,7 @@ import { Optional } from '../utils/types'; /** * Framework independent node data structure. * + * @inline * @typeParam NodeData - type of the node data * @typeParam NodeType - type of the node */ @@ -11,47 +12,62 @@ export type NodeBase< NodeData extends Record = Record, NodeType extends string = string > = { - /** Unique id of a node */ + /** Unique id of a node. */ id: string; - /** Position of a node on the pane + /** + * Position of a node on the pane. * @example { x: 0, y: 0 } */ position: XYPosition; - /** Arbitrary data passed to a node */ + /** Arbitrary data passed to a node. */ data: NodeData; - /** Type of node defined in nodeTypes */ + /** Type of node defined in `nodeTypes`. */ type?: NodeType; - /** Only relevant for default, source, target nodeType. controls source position + /** + * Only relevant for default, source, target nodeType. Controls source position. * @example 'right', 'left', 'top', 'bottom' */ sourcePosition?: Position; - /** Only relevant for default, source, target nodeType. controls target position + /** + * Only relevant for default, source, target nodeType. Controls target position. * @example 'right', 'left', 'top', 'bottom' */ targetPosition?: Position; + /** Whether or not the node should be visible on the canvas. */ hidden?: boolean; selected?: boolean; - /** True, if node is being dragged */ + /** Whether or not the node is currently being dragged. */ dragging?: boolean; + /** Whether or not the node is able to be dragged. */ draggable?: boolean; selectable?: boolean; connectable?: boolean; deletable?: boolean; + /** + * A class name that can be applied to elements inside the node that allows those elements to act + * as drag handles, letting the user drag the node by clicking and dragging on those elements. + */ dragHandle?: string; width?: number; height?: number; initialWidth?: number; initialHeight?: number; - /** Parent node id, used for creating sub-flows */ + /** Parent node id, used for creating sub-flows. */ parentId?: string; zIndex?: number; - /** Boundary a node can be moved in + /** + * Boundary a node can be moved in. * @example 'parent' or [[0, 0], [100, 100]] */ extent?: 'parent' | CoordinateExtent; + /** + * When `true`, the parent node will automatically expand if this node is dragged to the edge of + * the parent node's bounds. + */ expandParent?: boolean; ariaLabel?: string; - /** Origin of the node relative to it's position + /** + * Origin of the node relative to its position. * @example * [0.5, 0.5] // centers the node * [0, 0] // top left @@ -65,7 +81,7 @@ export type NodeBase< }; }; -export type InternalNodeBase = NodeType & { +export type InternalNodeBase = Omit & { measured: { width?: number; height?: number; @@ -73,8 +89,10 @@ export type InternalNodeBase = NodeType & internals: { positionAbsolute: XYPosition; z: number; - /** Holds a reference to the original node object provided by the user. - * Used as an optimization to avoid certain operations. */ + /** + * Holds a reference to the original node object provided by the user. + * Used as an optimization to avoid certain operations. + */ userNode: NodeType; handleBounds?: NodeHandleBounds; bounds?: NodeBounds; @@ -82,7 +100,7 @@ export type InternalNodeBase = NodeType & }; /** - * The node data structure that gets used for the nodes prop. + * The node data structure that gets used for the custom nodes props. * * @public */ @@ -91,11 +109,11 @@ export type NodeProps = Pick< 'id' | 'data' | 'width' | 'height' | 'sourcePosition' | 'targetPosition' | 'dragHandle' | 'parentId' > & Required> & { - /** whether a node is connectable or not */ + /** Whether a node is connectable or not. */ isConnectable: boolean; - /** position absolute x value */ + /** Position absolute x value. */ positionAbsoluteX: number; - /** position absolute x value */ + /** Position absolute y value. */ positionAbsoluteY: number; }; @@ -134,10 +152,22 @@ export type NodeDragItem = { expandParent?: boolean; }; +/** + * The origin of a Node determines how it is placed relative to its own coordinates. + * `[0, 0]` places it at the top left corner, `[0.5, 0.5]` right in the center and + * `[1, 1]` at the bottom right of its position. + * + * @public + */ export type NodeOrigin = [number, number]; export type OnSelectionDrag = (event: MouseEvent, nodes: NodeBase[]) => void; +/** + * Type for the handles of a node + * + * @public + */ export type NodeHandle = Omit, 'nodeId'>; export type Align = 'center' | 'start' | 'end'; diff --git a/packages/system/src/types/utils.ts b/packages/system/src/types/utils.ts index b06786a7..274bfe55 100644 --- a/packages/system/src/types/utils.ts +++ b/packages/system/src/types/utils.ts @@ -1,3 +1,10 @@ +/** + * While [`PanelPosition`](/api-reference/types/panel-position) can be used to place a + * component in the corners of a container, the `Position` enum is less precise and used + * primarily in relation to edges and handles. + * + * @public + */ export enum Position { Left = 'left', Top = 'top', @@ -12,6 +19,11 @@ export const oppositePosition = { [Position.Bottom]: Position.Top, }; +/** + * All positions are stored in an object with x and y coordinates. + * + * @public + */ export type XYPosition = { x: number; y: number; @@ -33,4 +45,14 @@ export type Box = XYPosition & { export type Transform = [number, number, number]; +/** + * A coordinate extent represents two points in a coordinate system: one in the top + * left corner and one in the bottom right corner. It is used to represent the + * bounds of nodes in the flow or the bounds of the viewport. + * + * @public + * + * @remarks Props that expect a `CoordinateExtent` usually default to `[[-∞, -∞], [+∞, +∞]]` + * to represent an unbounded extent. + */ export type CoordinateExtent = [[number, number], [number, number]]; diff --git a/packages/system/src/utils/dom.ts b/packages/system/src/utils/dom.ts index 12188e9b..2311153f 100644 --- a/packages/system/src/utils/dom.ts +++ b/packages/system/src/utils/dom.ts @@ -61,9 +61,11 @@ export const getEventPosition = (event: MouseEvent | TouchEvent, bounds?: DOMRec }; }; -// The handle bounds are calculated relative to the node element. -// We store them in the internals object of the node in order to avoid -// unnecessary recalculations. +/* + * The handle bounds are calculated relative to the node element. + * We store them in the internals object of the node in order to avoid + * unnecessary recalculations. + */ export const getHandleBounds = ( type: 'source' | 'target', nodeElement: HTMLDivElement, diff --git a/packages/system/src/utils/edges/bezier-edge.ts b/packages/system/src/utils/edges/bezier-edge.ts index 640deffa..d5c0b6bb 100644 --- a/packages/system/src/utils/edges/bezier-edge.ts +++ b/packages/system/src/utils/edges/bezier-edge.ts @@ -1,12 +1,28 @@ import { Position } from '../../types'; export type GetBezierPathParams = { + /** The `x` position of the source handle. */ sourceX: number; + /** The `y` position of the source handle. */ sourceY: number; + /** + * The position of the source handle. + * @default Position.Bottom + */ sourcePosition?: Position; + /** The `x` position of the target handle. */ targetX: number; + /** The `y` position of the target handle. */ targetY: number; + /** + * The position of the target handle. + * @default Position.Top + */ targetPosition?: Position; + /** + * The curvature of the bezier edge. + * @default 0.25 + */ curvature?: number; }; @@ -38,8 +54,10 @@ export function getBezierEdgeCenter({ targetControlX: number; targetControlY: number; }): [number, number, number, number] { - // cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate - // https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve + /* + * cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate + * https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve + */ const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125; const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125; const offsetX = Math.abs(centerX - sourceX); @@ -70,27 +88,35 @@ function getControlWithCurvature({ pos, x1, y1, x2, y2, c }: GetControlWithCurva } /** - * Get a bezier path from source to target handle - * @param params.sourceX - The x position of the source handle - * @param params.sourceY - The y position of the source handle - * @param params.sourcePosition - The position of the source handle (default: Position.Bottom) - * @param params.targetX - The x position of the target handle - * @param params.targetY - The y position of the target handle - * @param params.targetPosition - The position of the target handle (default: Position.Top) - * @param params.curvature - The curvature of the bezier edge - * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label + * The `getBezierPath` util returns everything you need to render a bezier edge + *between two nodes. + * @public + * @returns A path string you can use in an SVG, the `labelX` and `labelY` position (center of path) + * and `offsetX`, `offsetY` between source handle and label. + * - `path`: the path to use in an SVG `` element. + * - `labelX`: the `x` position you can use to render a label for this edge. + * - `labelY`: the `y` position you can use to render a label for this edge. + * - `offsetX`: the absolute difference between the source `x` position and the `x` position of the + * middle of this path. + * - `offsetY`: the absolute difference between the source `y` position and the `y` position of the + * middle of this path. * @example + * ```js * const source = { x: 0, y: 20 }; - const target = { x: 150, y: 100 }; - - const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({ - sourceX: source.x, - sourceY: source.y, - sourcePosition: Position.Right, - targetX: target.x, - targetY: target.y, - targetPosition: Position.Left, -}); + * const target = { x: 150, y: 100 }; + * + * const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({ + * sourceX: source.x, + * sourceY: source.y, + * sourcePosition: Position.Right, + * targetX: target.x, + * targetY: target.y, + * targetPosition: Position.Left, + *}); + *``` + * + * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to + *work with multiple edge paths at once. */ export function getBezierPath({ sourceX, diff --git a/packages/system/src/utils/edges/general.ts b/packages/system/src/utils/edges/general.ts index 7dfa4b44..c094ab0b 100644 --- a/packages/system/src/utils/edges/general.ts +++ b/packages/system/src/utils/edges/general.ts @@ -90,12 +90,16 @@ const connectionExists = (edge: EdgeBase, edges: EdgeBase[]) => { }; /** - * This util is a convenience function to add a new Edge to an array of edges - * @remarks It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one. + * This util is a convenience function to add a new Edge to an array of edges. It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one. * @public - * @param edgeParams - Either an Edge or a Connection you want to add - * @param edges - The array of all current edges - * @returns A new array of edges with the new edge added + * @param edgeParams - Either an `Edge` or a `Connection` you want to add. + * @param edges - The array of all current edges. + * @returns A new array of edges with the new edge added. + * + * @remarks If an edge with the same `target` and `source` already exists (and the same + *`targetHandle` and `sourceHandle` if those are set), then this util won't add + *a new edge even if the `id` property is different. + * */ export const addEdge = ( edgeParams: EdgeType | Connection, @@ -133,16 +137,28 @@ export const addEdge = ( }; export type ReconnectEdgeOptions = { + /** + * Should the id of the old edge be replaced with the new connection id. + * @default true + */ shouldReplaceId?: boolean; }; /** - * A handy utility to reconnect an existing edge with new properties - * @param oldEdge - The edge you want to update - * @param newConnection - The new connection you want to update the edge with - * @param edges - The array of all current edges - * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id - * @returns the updated edges array + * A handy utility to update an existing [`Edge`](/api-reference/types/edge) with new properties. + *This searches your edge array for an edge with a matching `id` and updates its + *properties with the connection you provide. + * @public + * @param oldEdge - The edge you want to update. + * @param newConnection - The new connection you want to update the edge with. + * @param edges - The array of all current edges. + * @returns The updated edges array. + * + * @example + * ```js + *const onReconnect = useCallback( + * (oldEdge: Edge, newConnection: Connection) => setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),[]); + *``` */ export const reconnectEdge = ( oldEdge: EdgeType, diff --git a/packages/system/src/utils/edges/smoothstep-edge.ts b/packages/system/src/utils/edges/smoothstep-edge.ts index 5e57efcd..b10c5a07 100644 --- a/packages/system/src/utils/edges/smoothstep-edge.ts +++ b/packages/system/src/utils/edges/smoothstep-edge.ts @@ -2,15 +2,29 @@ import { getEdgeCenter } from './general'; import { Position, type XYPosition } from '../../types'; export interface GetSmoothStepPathParams { + /** The `x` position of the source handle. */ sourceX: number; + /** The `y` position of the source handle. */ sourceY: number; + /** + * The position of the source handle. + * @default Position.Bottom + */ sourcePosition?: Position; + /** The `x` position of the target handle. */ targetX: number; + /** The `y` position of the target handle. */ targetY: number; + /** + * The position of the target handle. + * @default Position.Top + */ targetPosition?: Position; + /** @default 5 */ borderRadius?: number; centerX?: number; centerY?: number; + /** @default 20 */ offset?: number; } @@ -38,8 +52,10 @@ const getDirection = ({ const distance = (a: XYPosition, b: XYPosition) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)); -// ith this function we try to mimic a orthogonal edge routing behaviour -// It's not as good as a real orthogonal edge routing but it's faster and good enough as a default for step and smooth step edges +/* + * With this function we try to mimic an orthogonal edge routing behaviour + * It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges + */ function getPoints({ source, sourcePosition = Position.Bottom, @@ -83,16 +99,20 @@ function getPoints({ if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) { centerX = center.x ?? defaultCenterX; centerY = center.y ?? defaultCenterY; - // ---> - // | - // >--- + /* + * ---> + * | + * >--- + */ const verticalSplit: XYPosition[] = [ { x: centerX, y: sourceGapped.y }, { x: centerX, y: targetGapped.y }, ]; - // | - // --- - // | + /* + * | + * --- + * | + */ const horizontalSplit: XYPosition[] = [ { x: sourceGapped.x, y: centerY }, { x: targetGapped.x, y: centerY }, @@ -191,26 +211,35 @@ function getBend(a: XYPosition, b: XYPosition, c: XYPosition, size: number): str } /** - * Get a smooth step path from source to target handle - * @param params.sourceX - The x position of the source handle - * @param params.sourceY - The y position of the source handle - * @param params.sourcePosition - The position of the source handle (default: Position.Bottom) - * @param params.targetX - The x position of the target handle - * @param params.targetY - The y position of the target handle - * @param params.targetPosition - The position of the target handle (default: Position.Top) - * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label + * The `getSmoothStepPath` util returns everything you need to render a stepped path + * between two nodes. The `borderRadius` property can be used to choose how rounded + * the corners of those steps are. + * @public + * @returns A path string you can use in an SVG, the `labelX` and `labelY` position (center of path) + * and `offsetX`, `offsetY` between source handle and label. + * + * - `path`: the path to use in an SVG `` element. + * - `labelX`: the `x` position you can use to render a label for this edge. + * - `labelY`: the `y` position you can use to render a label for this edge. + * - `offsetX`: the absolute difference between the source `x` position and the `x` position of the + * middle of this path. + * - `offsetY`: the absolute difference between the source `y` position and the `y` position of the + * middle of this path. * @example + * ```js * const source = { x: 0, y: 20 }; - const target = { x: 150, y: 100 }; - - const [path, labelX, labelY, offsetX, offsetY] = getSmoothStepPath({ - sourceX: source.x, - sourceY: source.y, - sourcePosition: Position.Right, - targetX: target.x, - targetY: target.y, - targetPosition: Position.Left, - }); + * const target = { x: 150, y: 100 }; + * + * const [path, labelX, labelY, offsetX, offsetY] = getSmoothStepPath({ + * sourceX: source.x, + * sourceY: source.y, + * sourcePosition: Position.Right, + * targetX: target.x, + * targetY: target.y, + * targetPosition: Position.Left, + * }); + * ``` + * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once. */ export function getSmoothStepPath({ sourceX, diff --git a/packages/system/src/utils/edges/straight-edge.ts b/packages/system/src/utils/edges/straight-edge.ts index 9940bfea..c5bc3db2 100644 --- a/packages/system/src/utils/edges/straight-edge.ts +++ b/packages/system/src/utils/edges/straight-edge.ts @@ -1,31 +1,44 @@ import { getEdgeCenter } from './general'; export type GetStraightPathParams = { + /** The `x` position of the source handle. */ sourceX: number; + /** The `y` position of the source handle. */ sourceY: number; + /** The `x` position of the target handle. */ targetX: number; + /** The `y` position of the target handle. */ targetY: number; }; /** - * Get a straight path from source to target handle - * @param params.sourceX - The x position of the source handle - * @param params.sourceY - The y position of the source handle - * @param params.targetX - The x position of the target handle - * @param params.targetY - The y position of the target handle - * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label + * Calculates the straight line path between two points. + * @public + * @returns A path string you can use in an SVG, the `labelX` and `labelY` position (center of path) + * and `offsetX`, `offsetY` between source handle and label. + * + * - `path`: the path to use in an SVG `` element. + * - `labelX`: the `x` position you can use to render a label for this edge. + * - `labelY`: the `y` position you can use to render a label for this edge. + * - `offsetX`: the absolute difference between the source `x` position and the `x` position of the + * middle of this path. + * - `offsetY`: the absolute difference between the source `y` position and the `y` position of the + * middle of this path. * @example + * ```js * const source = { x: 0, y: 20 }; - const target = { x: 150, y: 100 }; - - const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({ - sourceX: source.x, - sourceY: source.y, - sourcePosition: Position.Right, - targetX: target.x, - targetY: target.y, - targetPosition: Position.Left, - }); + * const target = { x: 150, y: 100 }; + * + * const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({ + * sourceX: source.x, + * sourceY: source.y, + * sourcePosition: Position.Right, + * targetX: target.x, + * targetY: target.y, + * targetPosition: Position.Left, + * }); + * ``` + * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once. */ export function getStraightPath({ sourceX, diff --git a/packages/system/src/utils/general.ts b/packages/system/src/utils/general.ts index 7f631a59..67743b5d 100644 --- a/packages/system/src/utils/general.ts +++ b/packages/system/src/utils/general.ts @@ -10,6 +10,8 @@ import type { Transform, InternalNodeBase, NodeLookup, + Padding, + PaddingWithUnit, } from '../types'; import { type Viewport } from '../types'; import { getNodePositionWithOrigin, isInternalNodeBase } from './graph'; @@ -174,20 +176,119 @@ export const rendererPointToPoint = ({ x, y }: XYPosition, [tx, ty, tScale]: Tra }; /** - * Returns a viewport that encloses the given bounds with optional padding. + * Parses a single padding value to a number + * @internal + * @param padding - Padding to parse + * @param viewport - Width or height of the viewport + * @returns The padding in pixels + */ +function parsePadding(padding: PaddingWithUnit, viewport: number): number { + if (typeof padding === 'number') { + return Math.floor(viewport - viewport / (1 + padding)); + } + + if (typeof padding === 'string' && padding.endsWith('px')) { + const paddingValue = parseFloat(padding); + if (!Number.isNaN(paddingValue)) { + return Math.floor(paddingValue); + } + } + + if (typeof padding === 'string' && padding.endsWith('%')) { + const paddingValue = parseFloat(padding); + if (!Number.isNaN(paddingValue)) { + return Math.floor(viewport * paddingValue * 0.01); + } + } + + console.error( + `[React Flow] The padding value "${padding}" is invalid. Please provide a number or a string with a valid unit (px or %).` + ); + return 0; +} + +/** + * Parses the paddings to an object with top, right, bottom, left, x and y paddings + * @internal + * @param padding - Padding to parse + * @param width - Width of the viewport + * @param height - Height of the viewport + * @returns An object with the paddings in pixels + */ +function parsePaddings( + padding: Padding, + width: number, + height: number +): { top: number; bottom: number; left: number; right: number; x: number; y: number } { + if (typeof padding === 'string' || typeof padding === 'number') { + const paddingY = parsePadding(padding, height); + const paddingX = parsePadding(padding, width); + return { + top: paddingY, + right: paddingX, + bottom: paddingY, + left: paddingX, + x: paddingX * 2, + y: paddingY * 2, + }; + } + + if (typeof padding === 'object') { + const top = parsePadding(padding.top ?? padding.y ?? 0, height); + const bottom = parsePadding(padding.bottom ?? padding.y ?? 0, height); + const left = parsePadding(padding.left ?? padding.x ?? 0, width); + const right = parsePadding(padding.right ?? padding.x ?? 0, width); + return { top, right, bottom, left, x: left + right, y: top + bottom }; + } + + return { top: 0, right: 0, bottom: 0, left: 0, x: 0, y: 0 }; +} + +/** + * Calculates the resulting paddings if the new viewport is applied + * @internal + * @param bounds - Bounds to fit inside viewport + * @param x - X position of the viewport + * @param y - Y position of the viewport + * @param zoom - Zoom level of the viewport + * @param width - Width of the viewport + * @param height - Height of the viewport + * @returns An object with the minimum padding required to fit the bounds inside the viewport + */ +function calculateAppliedPaddings(bounds: Rect, x: number, y: number, zoom: number, width: number, height: number) { + const { x: left, y: top } = rendererPointToPoint(bounds, [x, y, zoom]); + + const { x: boundRight, y: boundBottom } = rendererPointToPoint( + { x: bounds.x + bounds.width, y: bounds.y + bounds.height }, + [x, y, zoom] + ); + + const right = width - boundRight; + const bottom = height - boundBottom; + + return { + left: Math.floor(left), + top: Math.floor(top), + right: Math.floor(right), + bottom: Math.floor(bottom), + }; +} + +/** + * Returns a viewport that encloses the given bounds with padding. * @public * @remarks You can determine bounds of nodes with {@link getNodesBounds} and {@link getBoundsOfRects} - * @param bounds - Bounds to fit inside viewport - * @param width - Width of the viewport - * @param height - Height of the viewport - * @param minZoom - Minimum zoom level of the resulting viewport - * @param maxZoom - Maximum zoom level of the resulting viewport - * @param padding - Optional padding around the bounds - * @returns A transforned {@link Viewport} that encloses the given bounds which you can pass to e.g. {@link setViewport} + * @param bounds - Bounds to fit inside viewport. + * @param width - Width of the viewport. + * @param height - Height of the viewport. + * @param minZoom - Minimum zoom level of the resulting viewport. + * @param maxZoom - Maximum zoom level of the resulting viewport. + * @param padding - Padding around the bounds. + * @returns A transformed {@link Viewport} that encloses the given bounds which you can pass to e.g. {@link setViewport}. * @example * const { x, y, zoom } = getViewportForBounds( - { x: 0, y: 0, width: 100, height: 100}, - 1200, 800, 0.5, 2); + * { x: 0, y: 0, width: 100, height: 100}, + * 1200, 800, 0.5, 2); */ export const getViewportForBounds = ( bounds: Rect, @@ -195,18 +296,39 @@ export const getViewportForBounds = ( height: number, minZoom: number, maxZoom: number, - padding: number + padding: Padding ): Viewport => { - const xZoom = width / (bounds.width * (1 + padding)); - const yZoom = height / (bounds.height * (1 + padding)); + // First we resolve all the paddings to actual pixel values + const p = parsePaddings(padding, width, height); + + const xZoom = (width - p.x) / bounds.width; + const yZoom = (height - p.y) / bounds.height; + + // We calculate the new x, y, zoom for a centered view const zoom = Math.min(xZoom, yZoom); const clampedZoom = clamp(zoom, minZoom, maxZoom); + const boundsCenterX = bounds.x + bounds.width / 2; const boundsCenterY = bounds.y + bounds.height / 2; const x = width / 2 - boundsCenterX * clampedZoom; const y = height / 2 - boundsCenterY * clampedZoom; - return { x, y, zoom: clampedZoom }; + // Then we calculate the minimum padding, to respect asymmetric paddings + const newPadding = calculateAppliedPaddings(bounds, x, y, clampedZoom, width, height); + + // We only want to have an offset if the newPadding is smaller than the required padding + const offset = { + left: Math.min(newPadding.left - p.left, 0), + top: Math.min(newPadding.top - p.top, 0), + right: Math.min(newPadding.right - p.right, 0), + bottom: Math.min(newPadding.bottom - p.bottom, 0), + }; + + return { + x: x - offset.left + offset.right, + y: y - offset.top + offset.bottom, + zoom: clampedZoom, + }; }; export const isMacOs = () => typeof navigator !== 'undefined' && navigator?.userAgent?.indexOf('Mac') >= 0; diff --git a/packages/system/src/utils/graph.ts b/packages/system/src/utils/graph.ts index ddec917c..9bd7beff 100644 --- a/packages/system/src/utils/graph.ts +++ b/packages/system/src/utils/graph.ts @@ -30,7 +30,7 @@ import { import { errorMessages } from '../constants'; /** - * Test whether an object is useable as an Edge + * Test whether an object is usable as an Edge * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Edge if it returns true * @param element - The element to test @@ -40,7 +40,7 @@ export const isEdgeBase = (element: any): 'id' in element && 'source' in element && 'target' in element; /** - * Test whether an object is useable as a Node + * Test whether an object is usable as a Node * @public * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Node if it returns true * @param element - The element to test @@ -54,12 +54,27 @@ export const isInternalNodeBase = 'id' in element && 'internals' in element && !('source' in element) && !('target' in element); /** - * Pass in a node, and get connected nodes where edge.source === node.id + * This util is used to tell you what nodes, if any, are connected to the given node + * as the _target_ of an edge. * @public - * @param node - The node to get the connected nodes from - * @param nodes - The array of all nodes - * @param edges - The array of all edges - * @returns An array of nodes that are connected over eges where the source is the given node + * @param node - The node to get the connected nodes from. + * @param nodes - The array of all nodes. + * @param edges - The array of all edges. + * @returns An array of nodes that are connected over edges where the source is the given node. + * + * @example + * ```ts + *import { getOutgoers } from '@xyflow/react'; + * + *const nodes = []; + *const edges = []; + * + *const outgoers = getOutgoers( + * { id: '1', position: { x: 0, y: 0 }, data: { label: 'node' } }, + * nodes, + * edges, + *); + *``` */ export const getOutgoers = ( node: NodeType | { id: string }, @@ -81,12 +96,27 @@ export const getOutgoers = ( node: NodeType | { id: string }, @@ -119,21 +149,52 @@ export const getNodePositionWithOrigin = (node: NodeBase, nodeOrigin: NodeOrigin }; export type GetNodesBoundsParams = { + /** + * Origin of the nodes: `[0, 0]` for top-left, `[0.5, 0.5]` for center. + * @default [0, 0] + */ nodeOrigin?: NodeOrigin; nodeLookup?: NodeLookup>; }; /** - * Internal function for determining a bounding box that contains all given nodes in an array. + * Returns the bounding box that contains all the given nodes in an array. This can + * be useful when combined with [`getViewportForBounds`](/api-reference/utils/get-viewport-for-bounds) + * to calculate the correct transform to fit the given nodes in a viewport. * @public * @remarks Useful when combined with {@link getViewportForBounds} to calculate the correct transform to fit the given nodes in a viewport. - * @param nodes - Nodes to calculate the bounds for - * @param params.nodeOrigin - Origin of the nodes: [0, 0] - top left, [0.5, 0.5] - center - * @returns Bounding box enclosing all nodes + * @param nodes - Nodes to calculate the bounds for. + * @returns Bounding box enclosing all nodes. + * + * @remarks This function was previously called `getRectOfNodes` + * + * @example + * ```js + *import { getNodesBounds } from '@xyflow/react'; + * + *const nodes = [ + * { + * id: 'a', + * position: { x: 0, y: 0 }, + * data: { label: 'a' }, + * width: 50, + * height: 25, + * }, + * { + * id: 'b', + * position: { x: 100, y: 100 }, + * data: { label: 'b' }, + * width: 50, + * height: 25, + * }, + *]; + * + *const bounds = getNodesBounds(nodes); + *``` */ export const getNodesBounds = ( nodes: (NodeType | InternalNodeBase | string)[], - params: GetNodesBoundsParams = { nodeOrigin: [0, 0], nodeLookup: undefined } + params: GetNodesBoundsParams = { nodeOrigin: [0, 0] } ): Rect => { if (process.env.NODE_ENV === 'development' && !params.nodeLookup) { console.warn( @@ -238,10 +299,30 @@ export const getNodesInside = ( }; /** - * Get all connecting edges for a given set of nodes - * @param nodes - Nodes you want to get the connected edges for - * @param edges - All edges - * @returns Array of edges that connect any of the given nodes with each other + * This utility filters an array of edges, keeping only those where either the source or target + * node is present in the given array of nodes. + * @public + * @param nodes - Nodes you want to get the connected edges for. + * @param edges - All edges. + * @returns Array of edges that connect any of the given nodes with each other. + * + * @example + * ```js + *import { getConnectedEdges } from '@xyflow/react'; + * + *const nodes = [ + * { id: 'a', position: { x: 0, y: 0 } }, + * { id: 'b', position: { x: 100, y: 0 } }, + *]; + * + *const edges = [ + * { id: 'a->c', source: 'a', target: 'c' }, + * { id: 'c->d', source: 'c', target: 'd' }, + *]; + * + *const connectedEdges = getConnectedEdges(nodes, edges); + * // => [{ id: 'a->c', source: 'a', target: 'c' }] + *``` */ export const getConnectedEdges = ( nodes: NodeType[], @@ -255,10 +336,10 @@ export const getConnectedEdges = nodeIds.has(edge.source) || nodeIds.has(edge.target)); }; -export function getFitViewNodes< +function getFitViewNodes< Params extends NodeLookup>, Options extends FitViewOptionsBase ->(nodeLookup: Params, options?: Pick) { +>(nodeLookup: Params, options?: Options) { const fitViewNodes: NodeLookup = new Map(); const optionNodeIds = options?.nodes ? new Set(options.nodes.map((node) => node.id)) : null; @@ -273,15 +354,20 @@ export function getFitViewNodes< return fitViewNodes; } -export async function fitView, Options extends FitViewOptionsBase>( +export async function fitViewport< + Params extends FitViewParamsBase, + Options extends FitViewOptionsBase +>( { nodes, width, height, panZoom, minZoom, maxZoom }: Params, options?: Omit ): Promise { if (nodes.size === 0) { - return Promise.resolve(false); + return Promise.resolve(true); } - const bounds = getInternalNodesBounds(nodes); + const nodesToFit = getFitViewNodes(nodes, options); + + const bounds = getInternalNodesBounds(nodesToFit); const viewport = getViewportForBounds( bounds, @@ -350,10 +436,14 @@ export function calculateNodePosition({ ? clampPosition(nextPosition, extent, node.measured) : nextPosition; + if (node.measured.width === undefined || node.measured.height === undefined) { + onError?.('015', errorMessages['error015']()); + } + return { position: { - x: positionAbsolute.x - parentX + node.measured.width! * origin[0], - y: positionAbsolute.y - parentY + node.measured.height! * origin[1], + x: positionAbsolute.x - parentX + (node.measured.width ?? 0) * origin[0], + y: positionAbsolute.y - parentY + (node.measured.height ?? 0) * origin[1], }, positionAbsolute, }; diff --git a/packages/system/src/utils/node-toolbar.ts b/packages/system/src/utils/node-toolbar.ts index 1813513c..f5246bcc 100644 --- a/packages/system/src/utils/node-toolbar.ts +++ b/packages/system/src/utils/node-toolbar.ts @@ -15,8 +15,10 @@ export function getNodeToolbarTransform( alignmentOffset = 1; } - // position === Position.Top - // we set the x any y position of the toolbar based on the nodes position + /* + * position === Position.Top + * we set the x any y position of the toolbar based on the nodes position + */ let pos = [ (nodeRect.x + nodeRect.width * alignmentOffset) * viewport.zoom + viewport.x, nodeRect.y * viewport.zoom + viewport.y - offset, diff --git a/packages/system/src/utils/store.ts b/packages/system/src/utils/store.ts index 77c5b369..14fc710a 100644 --- a/packages/system/src/utils/store.ts +++ b/packages/system/src/utils/store.ts @@ -85,9 +85,10 @@ export function adoptUserNodes( nodeLookup: NodeLookup>, parentLookup: ParentLookup>, options?: UpdateNodesOptions -) { +): boolean { const _options = mergeObjects(adoptUserNodesDefaultOptions, options); + let nodesInitialized = true; const tmpLookup = new Map(nodeLookup); const selectedNodeZ: number = _options?.elevateNodesOnSelect ? 1000 : 0; @@ -123,10 +124,19 @@ export function adoptUserNodes( nodeLookup.set(userNode.id, internalNode); } + if ( + (!internalNode.measured || !internalNode.measured.width || !internalNode.measured.height) && + !internalNode.hidden + ) { + nodesInitialized = false; + } + if (userNode.parentId) { updateChildNode(internalNode, nodeLookup, parentLookup, options); } } + + return nodesInitialized; } function updateParentLookup( @@ -276,8 +286,10 @@ export function handleExpandParent( }, }); - // We move all child nodes in the oppsite direction - // so the x,y changes of the parent do not move the children + /* + * We move all child nodes in the oppsite direction + * so the x,y changes of the parent do not move the children + */ parentLookup.get(parentId)?.forEach((childNode) => { if (!children.some((child) => child.id === childNode.id)) { changes.push({ @@ -472,9 +484,11 @@ function addConnectionToLookup( nodeId: string, handleId: string | null ) { - // We add the connection to the connectionLookup at the following keys - // 1. nodeId, 2. nodeId-type, 3. nodeId-type-handleId - // If the key already exists, we add the connection to the existing map + /* + * We add the connection to the connectionLookup at the following keys + * 1. nodeId, 2. nodeId-type, 3. nodeId-type-handleId + * If the key already exists, we add the connection to the existing map + */ let key = nodeId; const nodeMap = connectionLookup.get(key) || new Map(); connectionLookup.set(key, nodeMap.set(connectionKey, connection)); diff --git a/packages/system/src/xydrag/XYDrag.ts b/packages/system/src/xydrag/XYDrag.ts index eb2ea80a..33658aad 100644 --- a/packages/system/src/xydrag/XYDrag.ts +++ b/packages/system/src/xydrag/XYDrag.ts @@ -140,8 +140,10 @@ export function XYDrag voi for (const [id, dragItem] of dragItems) { if (!nodeLookup.has(id)) { - // if the node is not in the nodeLookup anymore, it was probably deleted while dragging - // and we don't need to update it anymore + /* + * if the node is not in the nodeLookup anymore, it was probably deleted while dragging + * and we don't need to update it anymore + */ continue; } @@ -150,8 +152,10 @@ export function XYDrag voi nextPosition = snapPosition(nextPosition, snapGrid); } - // if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node - // based on its position so that the node stays at it's position relative to the selection. + /* + * if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node + * based on its position so that the node stays at it's position relative to the selection. + */ let adjustedNodeExtent: CoordinateExtent = [ [nodeExtent[0][0], nodeExtent[0][1]], [nodeExtent[1][0], nodeExtent[1][1]], @@ -214,7 +218,13 @@ export function XYDrag voi return; } - const { transform, panBy, autoPanSpeed } = getStoreItems(); + const { transform, panBy, autoPanSpeed, autoPanOnNodeDrag } = getStoreItems(); + + if (!autoPanOnNodeDrag) { + autoPanStarted = false; + cancelAnimationFrame(autoPanId); + return; + } const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds, autoPanSpeed); diff --git a/packages/system/src/xydrag/utils.ts b/packages/system/src/xydrag/utils.ts index 5c0eda0a..dc980281 100644 --- a/packages/system/src/xydrag/utils.ts +++ b/packages/system/src/xydrag/utils.ts @@ -74,9 +74,11 @@ export function getDragItems( return dragItems; } -// returns two params: -// 1. the dragged node (or the first of the list, if we are dragging a node selection) -// 2. array of selected nodes (for multi selections) +/* + * returns two params: + * 1. the dragged node (or the first of the list, if we are dragging a node selection) + * 2. array of selected nodes (for multi selections) + */ export function getEventHandlerParams({ nodeId, dragItems, @@ -112,10 +114,10 @@ export function getEventHandlerParams({ !node ? nodesFromDragItems[0] : { - ...node, - position: dragItems.get(nodeId)?.position || node.position, - dragging, - }, + ...node, + position: dragItems.get(nodeId)?.position || node.position, + dragging, + }, nodesFromDragItems, ]; } diff --git a/packages/system/src/xyhandle/XYHandle.ts b/packages/system/src/xyhandle/XYHandle.ts index 5f4fc610..9c2af456 100644 --- a/packages/system/src/xyhandle/XYHandle.ts +++ b/packages/system/src/xyhandle/XYHandle.ts @@ -165,8 +165,10 @@ function onPointerDown( toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)! : null, }; - // we don't want to trigger an update when the connection - // is snapped to the same handle as before + /* + * we don't want to trigger an update when the connection + * is snapped to the same handle as before + */ if ( isValid && closestHandle && @@ -190,8 +192,10 @@ function onPointerDown( onConnect?.(connection); } - // it's important to get a fresh reference from the store here - // in order to get the latest state of onConnectEnd + /* + * it's important to get a fresh reference from the store here + * in order to get the latest state of onConnectEnd + */ // eslint-disable-next-line @typescript-eslint/no-unused-vars const { inProgress, ...connectionState } = previousConnection; const finalConnectionState = { @@ -248,8 +252,10 @@ function isValidHandle( const { x, y } = getEventPosition(event); const handleBelow = doc.elementFromPoint(x, y); - // we always want to prioritize the handle below the mouse cursor over the closest distance handle, - // because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor + /* + * we always want to prioritize the handle below the mouse cursor over the closest distance handle, + * because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor + */ const handleToCheck = handleBelow?.classList.contains(`${lib}-flow__handle`) ? handleBelow : handleDomNode; const result: Result = { diff --git a/packages/system/src/xyhandle/types.ts b/packages/system/src/xyhandle/types.ts index 6e468b0a..d3625c9b 100644 --- a/packages/system/src/xyhandle/types.ts +++ b/packages/system/src/xyhandle/types.ts @@ -11,7 +11,6 @@ import { type UpdateConnection, type IsValidConnection, NodeLookup, - ConnectionState, FinalConnectionState, } from '../types'; diff --git a/packages/system/src/xyhandle/utils.ts b/packages/system/src/xyhandle/utils.ts index ecc9b1cc..4650f192 100644 --- a/packages/system/src/xyhandle/utils.ts +++ b/packages/system/src/xyhandle/utils.ts @@ -19,8 +19,10 @@ function getNodesWithinDistance(position: XYPosition, nodeLookup: NodeLookup, di return nodes; } -// this distance is used for the area around the user pointer -// while doing a connection for finding the closest nodes +/* + * this distance is used for the area around the user pointer + * while doing a connection for finding the closest nodes + */ const ADDITIONAL_DISTANCE = 250; export function getClosestHandle( diff --git a/packages/system/src/xypanzoom/XYPanZoom.ts b/packages/system/src/xypanzoom/XYPanZoom.ts index 54b97e30..93bc79f8 100644 --- a/packages/system/src/xypanzoom/XYPanZoom.ts +++ b/packages/system/src/xypanzoom/XYPanZoom.ts @@ -114,22 +114,22 @@ export function XYPanZoom({ const wheelHandler = isPanOnScroll ? createPanOnScrollHandler({ - zoomPanValues, - noWheelClassName, - d3Selection, - d3Zoom: d3ZoomInstance, - panOnScrollMode, - panOnScrollSpeed, - zoomOnPinch, - onPanZoomStart, - onPanZoom, - onPanZoomEnd, - }) + zoomPanValues, + noWheelClassName, + d3Selection, + d3Zoom: d3ZoomInstance, + panOnScrollMode, + panOnScrollSpeed, + zoomOnPinch, + onPanZoomStart, + onPanZoom, + onPanZoomEnd, + }) : createZoomOnScrollHandler({ - noWheelClassName, - preventScrolling, - d3ZoomHandler, - }); + noWheelClassName, + preventScrolling, + d3ZoomHandler, + }); d3Selection.on('wheel.zoom', wheelHandler, { passive: false }); @@ -178,9 +178,11 @@ export function XYPanZoom({ }); d3ZoomInstance.filter(filter); - // We cannot add zoomOnDoubleClick to the filter above because - // double tapping on touch screens circumvents the filter and - // dblclick.zoom is fired on the selection directly + /* + * We cannot add zoomOnDoubleClick to the filter above because + * double tapping on touch screens circumvents the filter and + * dblclick.zoom is fired on the selection directly + */ if (zoomOnDoubleClick) { d3Selection.on('dblclick.zoom', d3DblClickZoomHandler); } else { diff --git a/packages/system/src/xypanzoom/eventhandler.ts b/packages/system/src/xypanzoom/eventhandler.ts index 2e78b90a..e6dda425 100644 --- a/packages/system/src/xypanzoom/eventhandler.ts +++ b/packages/system/src/xypanzoom/eventhandler.ts @@ -90,8 +90,10 @@ export function createPanOnScrollHandler({ return; } - // increase scroll speed in firefox - // firefox: deltaMode === 1; chrome: deltaMode === 0 + /* + * increase scroll speed in firefox + * firefox: deltaMode === 1; chrome: deltaMode === 0 + */ const deltaNormalize = event.deltaMode === 1 ? 20 : 1; let deltaX = panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize; let deltaY = panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize; @@ -114,9 +116,11 @@ export function createPanOnScrollHandler({ clearTimeout(zoomPanValues.panScrollTimeout); - // for pan on scroll we need to handle the event calls on our own - // we can't use the start, zoom and end events from d3-zoom - // because start and move gets called on every scroll event and not once at the beginning + /* + * for pan on scroll we need to handle the event calls on our own + * we can't use the start, zoom and end events from d3-zoom + * because start and move gets called on every scroll event and not once at the beginning + */ if (!zoomPanValues.isPanScrolling) { zoomPanValues.isPanScrolling = true; @@ -137,10 +141,17 @@ export function createPanOnScrollHandler({ export function createZoomOnScrollHandler({ noWheelClassName, preventScrolling, d3ZoomHandler }: ZoomOnScrollParams) { return function (this: Element, event: any, d: unknown) { + const isWheel = event.type === 'wheel'; // we still want to enable pinch zooming even if preventScrolling is set to false - const preventZoom = !preventScrolling && event.type === 'wheel' && !event.ctrlKey; + const preventZoom = !preventScrolling && isWheel && !event.ctrlKey; + const hasNoWheelClass = isWrappedWithClass(event, noWheelClassName); - if (preventZoom || isWrappedWithClass(event, noWheelClassName)) { + // if user is pinch zooming above a nowheel element, we don't want the browser to zoom + if (event.ctrlKey && isWheel && hasNoWheelClass) { + event.preventDefault(); + } + + if (preventZoom || hasNoWheelClass) { return null; } diff --git a/packages/system/src/xyresizer/XYResizer.ts b/packages/system/src/xyresizer/XYResizer.ts index 1f4ba321..f4cd150b 100644 --- a/packages/system/src/xyresizer/XYResizer.ts +++ b/packages/system/src/xyresizer/XYResizer.ts @@ -48,7 +48,7 @@ type XYResizerParams = { paneDomNode: HTMLDivElement | null; }; onChange: (changes: XYResizerChange, childChanges: XYResizerChildChange[]) => void; - onEnd?: () => void; + onEnd?: (change: Required) => void; }; type XYResizerUpdateParams = { @@ -154,8 +154,10 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X parentExtent = parentNode && node.extent === 'parent' ? nodeToParentExtent(parentNode) : undefined; } - // Collect all child nodes to correct their relative positions when top/left changes - // Determine largest minimal extent the parent node is allowed to resize to + /* + * Collect all child nodes to correct their relative positions when top/left changes + * Determine largest minimal extent the parent node is allowed to resize to + */ childNodes = []; childExtent = undefined; @@ -186,13 +188,13 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X }) .on('drag', (event: ResizeDragEvent) => { const { transform, snapGrid, snapToGrid, nodeOrigin: storeNodeOrigin } = getStoreItems(); - const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds, }); + const childChanges: XYResizerChildChange[] = []; if (!node) { @@ -230,8 +232,10 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X prevValues.x = change.x; prevValues.y = change.y; - // when top/left changes, correct the relative positions of child nodes - // so that they stay in the same position + /* + * when top/left changes, correct the relative positions of child nodes + * so that they stay in the same position + */ if (childNodes.length > 0) { const xChange = x - prevX; const yChange = y - prevY; @@ -290,7 +294,7 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X }) .on('end', (event: ResizeDragEvent) => { onResizeEnd?.(event, { ...prevValues }); - onEnd?.(); + onEnd?.({ ...prevValues }); }); selection.call(dragHandler); } diff --git a/packages/system/src/xyresizer/types.ts b/packages/system/src/xyresizer/types.ts index 99480512..34cad9e8 100644 --- a/packages/system/src/xyresizer/types.ts +++ b/packages/system/src/xyresizer/types.ts @@ -11,10 +11,25 @@ export type ResizeParamsWithDirection = ResizeParams & { direction: number[]; }; +/** + * Used to determine the control line position of the NodeResizer + * + * @public + */ export type ControlLinePosition = 'top' | 'bottom' | 'left' | 'right'; +/** + * Used to determine the control position of the NodeResizer + * + * @public + */ export type ControlPosition = ControlLinePosition | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; +/** + * Used to determine the variant of the resize control + * + * @public + */ export enum ResizeControlVariant { Line = 'line', Handle = 'handle', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9af370c6..8fba6311 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,27 +17,12 @@ importers: '@playwright/test': specifier: ^1.44.1 version: 1.44.1 - '@typescript-eslint/eslint-plugin': - specifier: latest - version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@8.43.0)(typescript@5.1.3))(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/parser': - specifier: latest - version: 8.0.0(eslint@8.43.0)(typescript@5.1.3) concurrently: specifier: ^7.6.0 version: 7.6.0 eslint: specifier: ^8.22.0 version: 8.43.0 - eslint-config-prettier: - specifier: ^8.5.0 - version: 8.8.0(eslint@8.43.0) - eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.8.0(eslint@8.43.0))(eslint@8.43.0)(prettier@2.8.8) - eslint-plugin-react: - specifier: latest - version: 7.35.0(eslint@8.43.0) prettier: specifier: ^2.7.1 version: 2.8.8 @@ -57,8 +42,8 @@ importers: specifier: ^2.0.3 version: 2.0.3 typescript: - specifier: 5.1.3 - version: 5.1.3 + specifier: 5.4.5 + version: 5.4.5 examples/astro-xyflow: dependencies: @@ -67,7 +52,7 @@ importers: version: 3.0.2(@types/react-dom@18.2.8)(@types/react@18.2.24)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0)) '@astrojs/svelte': specifier: ^4.0.2 - version: 4.0.2(astro@3.2.2(@types/node@20.14.6)(terser@5.31.0))(svelte@4.2.1)(typescript@5.7.3)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0)) + version: 4.0.2(astro@3.2.2(@types/node@20.14.6)(terser@5.31.0))(svelte@4.2.1)(typescript@5.8.3)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0)) '@types/react': specifier: ^18.2.24 version: 18.2.24 @@ -160,8 +145,8 @@ importers: specifier: ^2.0.2 version: 2.0.2 typescript: - specifier: 5.2.2 - version: 5.2.2 + specifier: 5.4.5 + version: 5.4.5 vite: specifier: 4.5.0 version: 4.5.0(@types/node@20.14.6)(terser@5.31.0) @@ -173,53 +158,53 @@ importers: version: 1.1.4 '@sveltejs/vite-plugin-svelte': specifier: ^5.0.3 - version: 5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + version: 5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@xyflow/svelte': specifier: workspace:^ version: link:../../packages/svelte devDependencies: '@sveltejs/adapter-auto': - specifier: ^4.0.0 - version: 4.0.0(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))) + specifier: ^6.0.0 + version: 6.0.0(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))) '@sveltejs/kit': - specifier: ^2.16.1 - version: 2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + specifier: ^2.20.4 + version: 2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@typescript-eslint/eslint-plugin': - specifier: ^8.22.0 - version: 8.22.0(@typescript-eslint/parser@8.22.0(eslint@8.53.0)(typescript@5.7.3))(eslint@8.53.0)(typescript@5.7.3) + specifier: ^8.29.1 + version: 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3) '@typescript-eslint/parser': - specifier: ^8.22.0 - version: 8.22.0(eslint@8.53.0)(typescript@5.7.3) + specifier: ^8.29.1 + version: 8.29.1(eslint@9.24.0)(typescript@5.8.3) eslint: - specifier: ^8.53.0 - version: 8.53.0 + specifier: ^9.24.0 + version: 9.24.0 eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.53.0) + specifier: ^10.1.1 + version: 10.1.1(eslint@9.24.0) eslint-plugin-svelte: - specifier: ^2.46.1 - version: 2.46.1(eslint@8.53.0)(svelte@5.19.5) + specifier: ^3.5.1 + version: 3.5.1(eslint@9.24.0)(svelte@5.25.8) prettier: - specifier: ^3.4.2 - version: 3.4.2 + specifier: ^3.5.3 + version: 3.5.3 prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.3.3(prettier@3.4.2)(svelte@5.19.5) + version: 3.3.3(prettier@3.5.3)(svelte@5.25.8) svelte: - specifier: ^5.19.5 - version: 5.19.5 + specifier: ^5.25.8 + version: 5.25.8 svelte-check: - specifier: ^4.1.4 - version: 4.1.4(svelte@5.19.5)(typescript@5.7.3) + specifier: ^4.1.5 + version: 4.1.5(picomatch@4.0.2)(svelte@5.25.8)(typescript@5.8.3) tslib: specifier: ^2.8.1 version: 2.8.1 typescript: - specifier: ^5.7.3 - version: 5.7.3 + specifier: ^5.8.3 + version: 5.8.3 vite: - specifier: ^6.0.11 - version: 6.0.11(@types/node@20.14.6)(terser@5.31.0) + specifier: ^6.2.5 + version: 6.2.5(@types/node@20.14.6)(terser@5.31.0) packages/react: dependencies: @@ -282,96 +267,96 @@ importers: specifier: ^18.2.0 version: 18.2.0 typescript: - specifier: 5.1.3 - version: 5.1.3 + specifier: 5.4.5 + version: 5.4.5 packages/svelte: dependencies: '@svelte-put/shortcut': specifier: ^4.1.0 - version: 4.1.0(svelte@5.19.5) + version: 4.1.0(svelte@5.25.8) '@xyflow/system': specifier: workspace:* version: link:../system devDependencies: '@sveltejs/adapter-auto': - specifier: ^4.0.0 - version: 4.0.0(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))) + specifier: ^6.0.0 + version: 6.0.0(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))) '@sveltejs/kit': - specifier: ^2.16.1 - version: 2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + specifier: ^2.20.4 + version: 2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@sveltejs/package': - specifier: ^2.3.9 - version: 2.3.9(svelte@5.19.5)(typescript@5.7.3) + specifier: ^2.3.10 + version: 2.3.10(svelte@5.25.8)(typescript@5.8.3) '@sveltejs/vite-plugin-svelte': specifier: ^5.0.3 - version: 5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + version: 5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@typescript-eslint/eslint-plugin': - specifier: ^8.22.0 - version: 8.22.0(@typescript-eslint/parser@8.22.0(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0)(typescript@5.7.3) + specifier: ^8.29.1 + version: 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3) '@typescript-eslint/parser': - specifier: ^8.22.0 - version: 8.22.0(eslint@8.57.0)(typescript@5.7.3) + specifier: ^8.29.1 + version: 8.29.1(eslint@9.24.0)(typescript@5.8.3) autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) + specifier: ^10.4.21 + version: 10.4.21(postcss@8.5.3) cssnano: specifier: ^7.0.6 - version: 7.0.6(postcss@8.5.1) + version: 7.0.6(postcss@8.5.3) dotenv: specifier: ^16.4.7 version: 16.4.7 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.24.0 + version: 9.24.0 eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + specifier: ^10.1.1 + version: 10.1.1(eslint@9.24.0) eslint-plugin-svelte: - specifier: ^2.46.1 - version: 2.46.1(eslint@8.57.0)(svelte@5.19.5) + specifier: ^3.5.1 + version: 3.5.1(eslint@9.24.0)(svelte@5.25.8) postcss: - specifier: ^8.5.1 - version: 8.5.1 + specifier: ^8.5.3 + version: 8.5.3 postcss-cli: - specifier: ^11.0.0 - version: 11.0.0(postcss@8.5.1) + specifier: ^11.0.1 + version: 11.0.1(postcss@8.5.3) postcss-combine-duplicated-selectors: specifier: ^10.0.3 - version: 10.0.3(postcss@8.5.1) + version: 10.0.3(postcss@8.5.3) postcss-import: specifier: ^16.1.0 - version: 16.1.0(postcss@8.5.1) + version: 16.1.0(postcss@8.5.3) postcss-nested: specifier: ^7.0.2 - version: 7.0.2(postcss@8.5.1) + version: 7.0.2(postcss@8.5.3) postcss-rename: specifier: ^0.6.1 - version: 0.6.1(postcss@8.5.1) + version: 0.6.1(postcss@8.5.3) prettier: - specifier: ^3.4.2 - version: 3.4.2 + specifier: ^3.5.3 + version: 3.5.3 prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.3.3(prettier@3.4.2)(svelte@5.19.5) + version: 3.3.3(prettier@3.5.3)(svelte@5.25.8) svelte: - specifier: ^5.19.5 - version: 5.19.5 + specifier: ^5.25.8 + version: 5.25.8 svelte-check: - specifier: ^4.1.4 - version: 4.1.4(svelte@5.19.5)(typescript@5.7.3) + specifier: ^4.1.5 + version: 4.1.5(picomatch@4.0.2)(svelte@5.25.8)(typescript@5.8.3) svelte-eslint-parser: - specifier: ^0.43.0 - version: 0.43.0(svelte@5.19.5) + specifier: ^1.1.2 + version: 1.1.2(svelte@5.25.8) svelte-preprocess: specifier: ^6.0.3 - version: 6.0.3(@babel/core@7.24.7)(postcss-load-config@5.0.2(postcss@8.5.1))(postcss@8.5.1)(svelte@5.19.5)(typescript@5.7.3) + version: 6.0.3(@babel/core@7.24.7)(postcss-load-config@5.0.2(postcss@8.5.3))(postcss@8.5.3)(svelte@5.25.8)(typescript@5.8.3) tslib: specifier: ^2.8.1 version: 2.8.1 typescript: - specifier: ^5.7.3 - version: 5.7.3 + specifier: ^5.8.3 + version: 5.8.3 packages/system: dependencies: @@ -410,14 +395,14 @@ importers: specifier: workspace:* version: link:../../tooling/tsconfig typescript: - specifier: 5.1.3 - version: 5.1.3 + specifier: 5.4.5 + version: 5.4.5 tests/playwright: dependencies: '@playwright/experimental-ct-react': specifier: ^1.49.1 - version: 1.49.1(@types/node@20.14.6)(terser@5.31.0)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + version: 1.49.1(@types/node@20.14.6)(terser@5.31.0)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -443,18 +428,24 @@ importers: tooling/eslint-config: devDependencies: - eslint: - specifier: ^8.22.0 - version: 8.43.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.23.0 + version: 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.23.0 + version: 8.29.1(eslint@9.24.0)(typescript@5.8.3) eslint-config-prettier: - specifier: ^8.5.0 - version: 8.8.0(eslint@8.43.0) + specifier: ^10.0.1 + version: 10.1.1(eslint@9.24.0) eslint-config-turbo: - specifier: ^2.0.3 - version: 2.0.3(eslint@8.43.0) + specifier: ^2.4.0 + version: 2.5.0(eslint@9.24.0)(turbo@2.0.3) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@10.1.1(eslint@9.24.0))(eslint@9.24.0)(prettier@3.5.3) eslint-plugin-react: - specifier: ^7.33.2 - version: 7.33.2(eslint@8.43.0) + specifier: ^7.37.4 + version: 7.37.5(eslint@9.24.0) tooling/rollup-config: devDependencies: @@ -472,7 +463,7 @@ importers: version: 0.4.4(rollup@4.18.0) '@rollup/plugin-typescript': specifier: 11.1.6 - version: 11.1.6(rollup@4.18.0)(tslib@2.8.1)(typescript@5.4.2) + version: 11.1.6(rollup@4.18.0)(tslib@2.8.1)(typescript@5.7.3) rollup: specifier: ^4.18.0 version: 4.18.0 @@ -480,8 +471,8 @@ importers: specifier: ^2.2.4 version: 2.2.4(rollup@4.18.0) typescript: - specifier: ^5.1.3 - version: 5.4.2 + specifier: ^5.4.5 + version: 5.7.3 tooling/tsconfig: {} @@ -869,8 +860,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.24.2': - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -893,8 +884,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.24.2': - resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -917,8 +908,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.24.2': - resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -941,8 +932,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.24.2': - resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -965,8 +956,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.24.2': - resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -989,8 +980,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.24.2': - resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -1013,8 +1004,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.24.2': - resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -1037,8 +1028,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.2': - resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -1061,8 +1052,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.24.2': - resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -1085,8 +1076,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.24.2': - resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -1109,8 +1100,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.24.2': - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -1133,8 +1124,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.24.2': - resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -1157,8 +1148,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.24.2': - resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -1181,8 +1172,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.24.2': - resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -1205,8 +1196,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.24.2': - resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -1229,8 +1220,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.24.2': - resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -1253,14 +1244,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.24.2': - resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.24.2': - resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -1283,14 +1274,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.2': - resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.24.2': - resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -1313,8 +1304,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.2': - resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -1337,8 +1328,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.24.2': - resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1361,8 +1352,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.24.2': - resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1385,8 +1376,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.24.2': - resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1409,8 +1400,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.24.2': - resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1421,37 +1412,63 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.10.0': resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.9.1': resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.12.0': + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.2': resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/eslintrc@2.1.3': - resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@8.43.0': resolution: {integrity: sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.53.0': - resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/js@9.24.0': + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@fastify/busboy@2.0.0': resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} @@ -1463,16 +1480,19 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/config-array@0.11.13': resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -1481,9 +1501,13 @@ packages: resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} deprecated: Use @eslint/object-schema instead - '@humanwhocodes/object-schema@2.0.2': - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - deprecated: Use @eslint/object-schema instead + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} '@jridgewell/gen-mapping@0.3.3': resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} @@ -1647,6 +1671,11 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.39.0': + resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.18.0': resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] @@ -1657,6 +1686,11 @@ packages: cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.39.0': + resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.18.0': resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] @@ -1667,6 +1701,11 @@ packages: cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.39.0': + resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.18.0': resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] @@ -1677,16 +1716,31 @@ packages: cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.39.0': + resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-freebsd-arm64@4.25.0': resolution: {integrity: sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==} cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.39.0': + resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.25.0': resolution: {integrity: sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==} cpu: [x64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.39.0': + resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] @@ -1697,6 +1751,11 @@ packages: cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.39.0': + resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.18.0': resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] @@ -1707,6 +1766,11 @@ packages: cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.39.0': + resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.18.0': resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] @@ -1717,6 +1781,11 @@ packages: cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.39.0': + resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.18.0': resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] @@ -1727,6 +1796,16 @@ packages: cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.39.0': + resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.39.0': + resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==} + cpu: [loong64] + os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] @@ -1737,6 +1816,11 @@ packages: cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.39.0': + resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.18.0': resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] @@ -1747,6 +1831,16 @@ packages: cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.39.0': + resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.39.0': + resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.18.0': resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] @@ -1757,6 +1851,11 @@ packages: cpu: [s390x] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.39.0': + resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.18.0': resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] @@ -1767,6 +1866,11 @@ packages: cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.39.0': + resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.18.0': resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] @@ -1777,6 +1881,11 @@ packages: cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.39.0': + resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==} + cpu: [x64] + os: [linux] + '@rollup/rollup-win32-arm64-msvc@4.18.0': resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] @@ -1787,6 +1896,11 @@ packages: cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.39.0': + resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.18.0': resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] @@ -1797,6 +1911,11 @@ packages: cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.39.0': + resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.18.0': resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] @@ -1807,6 +1926,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.39.0': + resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==} + cpu: [x64] + os: [win32] + '@sideway/address@4.1.4': resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} @@ -1825,13 +1949,18 @@ packages: peerDependencies: svelte: ^5.1.0 - '@sveltejs/adapter-auto@4.0.0': - resolution: {integrity: sha512-kmuYSQdD2AwThymQF0haQhM8rE5rhutQXG4LNbnbShwhMO4qQGnKaaTy+88DuNSuoQDi58+thpq8XpHc1+oEKQ==} + '@sveltejs/acorn-typescript@1.0.5': + resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/adapter-auto@6.0.0': + resolution: {integrity: sha512-7mR2/G7vlXakaOj6QBSG9dwBfTgWjV+UnEMB5Z6Xu0ZbdXda6c0su1fNkg0ab0zlilSkloMA2NjCna02/DR7sA==} peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/kit@2.16.1': - resolution: {integrity: sha512-2pF5sgGJx9brYZ/9nNDYnh5KX0JguPF14dnvvtf/MqrvlWrDj/e7Rk3LBJPecFLLK1GRs6ZniD24gFPqZm/NFw==} + '@sveltejs/kit@2.20.4': + resolution: {integrity: sha512-B3Y1mb1Qjt57zXLVch5tfqsK/ebHe6uYTcFSnGFNwRpId3+fplLgQK6Z2zhDVBezSsPuhDq6Pry+9PA88ocN6Q==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1839,8 +1968,8 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.3 || ^6.0.0 - '@sveltejs/package@2.3.9': - resolution: {integrity: sha512-POIiQknGmcGCcM7ZbFG7cjsJ51GndFOY3PTXa8XFzZ+C/GJfx/JufvVXiWcXVsteP74FeXSSgcC+b5sIayXXKw==} + '@sveltejs/package@2.3.10': + resolution: {integrity: sha512-A4fQacgjJ7C/7oSmxR61/TdB14u6ecyMZ8V9JCR5Lol0bLj/PdJPU4uFodFBsKzO3iFiJMpNTgZZ+zYsYZNpUg==} engines: {node: ^16.14 || >=18} hasBin: true peerDependencies: @@ -2015,12 +2144,18 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/hast@2.3.7': resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} '@types/is-ci@3.0.3': resolution: {integrity: sha512-FdHbjLiN2e8fk9QYQyVYZrK8svUDJpxSaSWLUga8EZS1RGAvvrqM9zbVARBtQuYPeLgnJxM2xloOswPwj1o2cQ==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/json5@0.0.30': resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==} @@ -2108,113 +2243,53 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.0.0': - resolution: {integrity: sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==} + '@typescript-eslint/eslint-plugin@8.29.1': + resolution: {integrity: sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/eslint-plugin@8.22.0': - resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/parser@8.0.0': - resolution: {integrity: sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==} + '@typescript-eslint/parser@8.29.1': + resolution: {integrity: sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.22.0': - resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==} + '@typescript-eslint/scope-manager@8.29.1': + resolution: {integrity: sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.29.1': + resolution: {integrity: sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.0.0': - resolution: {integrity: sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==} + '@typescript-eslint/types@8.29.1': + resolution: {integrity: sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.22.0': - resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.0.0': - resolution: {integrity: sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==} + '@typescript-eslint/typescript-estree@8.29.1': + resolution: {integrity: sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/type-utils@8.22.0': - resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==} + '@typescript-eslint/utils@8.29.1': + resolution: {integrity: sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.0.0': - resolution: {integrity: sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==} + '@typescript-eslint/visitor-keys@8.29.1': + resolution: {integrity: sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.22.0': - resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.0.0': - resolution: {integrity: sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/typescript-estree@8.22.0': - resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/utils@8.0.0': - resolution: {integrity: sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - - '@typescript-eslint/utils@8.22.0': - resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' - - '@typescript-eslint/visitor-keys@8.0.0': - resolution: {integrity: sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/visitor-keys@8.22.0': - resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-react-swc@3.4.1': resolution: {integrity: sha512-7YQOQcVV5x1luD8nkbCDdyYygFvn1hjqJk68UvNAzY2QG4o4N5EwAhLLFNOcd1HrdMwDl0VElP8VutoWf9IvJg==} peerDependencies: @@ -2237,11 +2312,6 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-typescript@1.4.13: - resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} - peerDependencies: - acorn: '>=8.9.0' - acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} @@ -2328,8 +2398,8 @@ packages: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} - array-includes@3.1.7: - resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} array-includes@3.1.8: @@ -2351,13 +2421,10 @@ packages: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} - array.prototype.tosorted@1.1.2: - resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} - array.prototype.tosorted@1.1.4: resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} engines: {node: '>= 0.4'} @@ -2370,6 +2437,10 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} @@ -2393,9 +2464,6 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - asynciterator.prototype@1.0.0: - resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -2410,8 +2478,8 @@ packages: peerDependencies: postcss: ^8.1.0 - autoprefixer@10.4.20: - resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + autoprefixer@10.4.21: + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: @@ -2506,6 +2574,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -2526,6 +2599,10 @@ packages: resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} engines: {node: '>=6'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + call-bind@1.0.5: resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} @@ -2533,6 +2610,14 @@ packages: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -2558,6 +2643,9 @@ packages: caniuse-lite@1.0.30001680: resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} + caniuse-lite@1.0.30001712: + resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} + caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -2600,6 +2688,10 @@ packages: resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} engines: {node: '>= 14.16.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -2743,6 +2835,10 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + css-declaration-sorter@6.4.1: resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} engines: {node: ^10 || ^12 || >=14} @@ -2890,14 +2986,26 @@ packages: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + data-view-byte-length@1.0.1: resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} engines: {node: '>= 0.4'} + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + data-view-byte-offset@1.0.0: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} engines: {node: '>= 0.4'} + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} @@ -3012,6 +3120,10 @@ packages: resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} engines: {node: '>= 0.6.0'} + dependency-graph@1.0.0: + resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==} + engines: {node: '>=4'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -3078,6 +3190,10 @@ packages: resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} engines: {node: '>=4'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -3090,6 +3206,9 @@ packages: electron-to-chromium@1.4.563: resolution: {integrity: sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==} + electron-to-chromium@1.5.134: + resolution: {integrity: sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og==} + electron-to-chromium@1.5.56: resolution: {integrity: sha512-7lXb9dAvimCFdvUMTyucD4mnIndt/xhRKFAlky0CyFogdnNmdPQNoHI23msF/2V4mpTxMzgMdjK4+YRlFlRQZw==} @@ -3124,19 +3243,24 @@ packages: resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-iterator-helpers@1.0.15: - resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} - - es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} es-module-lexer@1.3.1: @@ -3146,6 +3270,10 @@ packages: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.2: resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} engines: {node: '>= 0.4'} @@ -3154,6 +3282,10 @@ packages: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-shim-unscopables@1.0.2: resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} @@ -3161,6 +3293,10 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + esbuild@0.18.20: resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} engines: {node: '>=12'} @@ -3176,8 +3312,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.24.2: - resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} engines: {node: '>=18'} hasBin: true @@ -3201,28 +3337,17 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-compat-utils@0.5.1: - resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=6.0.0' - - eslint-config-prettier@8.8.0: - resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + eslint-config-prettier@10.1.1: + resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} hasBin: true peerDependencies: eslint: '>=7.0.0' - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-config-turbo@2.0.3: - resolution: {integrity: sha512-D1+lNOpTFEuAgPWJfRHXHjzvAfO+0TVmORfftmYQNw+uk2UIBjhelhwERBceYFy2oFJnckHsqt69dp/zIM6/0g==} + eslint-config-turbo@2.5.0: + resolution: {integrity: sha512-QJvZBEWDWQx1JyQCr0uwf4aQYhDSAGoHBdx+cPtpPzNEjZw16Ig8BglXxHZBh3I8/fI1U53cLgXwvb28BUZhPA==} peerDependencies: eslint: '>6.6.0' + turbo: '>2.0.0' eslint-plugin-prettier@4.2.1: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} @@ -3235,37 +3360,36 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-react@7.33.2: - resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - - eslint-plugin-react@7.35.0: - resolution: {integrity: sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==} + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-plugin-svelte@2.46.1: - resolution: {integrity: sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==} - engines: {node: ^14.17.0 || >=16.0.0} + eslint-plugin-svelte@3.5.1: + resolution: {integrity: sha512-Qn1slddZHfqYiDO6IN8/iN3YL+VuHlgYjm30FT+hh0Jf/TX0jeZMTJXQMajFm5f6f6hURi+XO8P+NPYD+T4jkg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 + eslint: ^8.57.1 || ^9.0.0 svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: svelte: optional: true - eslint-plugin-turbo@2.0.3: - resolution: {integrity: sha512-mplP4nYaRvtTNuwF5QTLYKLu0/8LTRsHPgX4ARhaof+QZI2ttglONe1/iJpKB4pg0KqFp7WHziKoJL+s0+CJ1w==} + eslint-plugin-turbo@2.5.0: + resolution: {integrity: sha512-qQk54MrUZv0gnpxV23sccTc+FL3UJ8q7vG7HmXuS2RP8gdjWDwI1CCJTJD8EdRIDjsMxF0xi0AKcMY0CwIlXVg==} peerDependencies: eslint: '>6.6.0' + turbo: '>2.0.0' eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3279,19 +3403,23 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true - eslint@8.53.0: - resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint@9.24.0: + resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true esm-env@1.2.2: resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3305,8 +3433,8 @@ packages: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} - esrap@1.4.3: - resolution: {integrity: sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==} + esrap@1.4.6: + resolution: {integrity: sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -3412,6 +3540,14 @@ packages: picomatch: optional: true + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -3420,6 +3556,10 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -3439,6 +3579,10 @@ packages: resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} engines: {node: '>=12.0.0'} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} @@ -3454,6 +3598,10 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} @@ -3510,6 +3658,10 @@ packages: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} @@ -3528,6 +3680,14 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stdin@9.0.0: resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} engines: {node: '>=12'} @@ -3552,6 +3712,10 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + getos@3.2.1: resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} @@ -3593,10 +3757,18 @@ packages: resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -3608,6 +3780,10 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -3653,10 +3829,18 @@ packages: resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} engines: {node: '>= 0.4'} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} @@ -3790,6 +3974,10 @@ packages: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} @@ -3797,6 +3985,10 @@ packages: resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} engines: {node: '>= 0.4'} + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -3810,6 +4002,10 @@ packages: is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -3818,6 +4014,10 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} @@ -3841,10 +4041,18 @@ packages: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3858,8 +4066,9 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -3886,8 +4095,9 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} - is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} @@ -3904,6 +4114,10 @@ packages: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -3933,8 +4147,13 @@ packages: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} - is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} @@ -3943,6 +4162,10 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -3955,6 +4178,10 @@ packages: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} @@ -3963,6 +4190,10 @@ packages: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + is-typed-array@1.1.12: resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} @@ -3971,6 +4202,10 @@ packages: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} @@ -3982,14 +4217,20 @@ packages: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} - is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} @@ -4008,8 +4249,9 @@ packages: isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} joi@17.11.0: resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==} @@ -4218,6 +4460,10 @@ packages: markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + mdast-util-definitions@5.1.2: resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} @@ -4490,6 +4736,9 @@ packages: node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -4519,6 +4768,10 @@ packages: object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -4527,31 +4780,20 @@ packages: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} - object.entries@1.1.7: - resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.7: - resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} engines: {node: '>= 0.4'} object.fromentries@2.0.8: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} - object.hasown@1.1.3: - resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} - - object.values@1.1.7: - resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} - engines: {node: '>= 0.4'} - - object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} once@1.4.0: @@ -4583,6 +4825,10 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -4681,9 +4927,6 @@ packages: picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -4691,6 +4934,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -4746,6 +4993,13 @@ packages: peerDependencies: postcss: ^8.0.0 + postcss-cli@11.0.1: + resolution: {integrity: sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + postcss: ^8.0.0 + postcss-colormin@6.0.0: resolution: {integrity: sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==} engines: {node: ^14 || ^16 || >=18.0} @@ -5100,11 +5354,11 @@ packages: peerDependencies: postcss: ^8.1.0 - postcss-safe-parser@6.0.0: - resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} - engines: {node: '>=12.0'} + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} peerDependencies: - postcss: ^8.3.3 + postcss: ^8.4.31 postcss-scss@4.0.9: resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} @@ -5159,12 +5413,8 @@ packages: resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} - engines: {node: ^10 || ^12 || >=14} - - postcss@8.5.1: - resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} prebuild-install@7.1.1: @@ -5195,8 +5445,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} hasBin: true @@ -5374,8 +5624,8 @@ packages: redux@5.0.1: resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - reflect.getprototypeof@1.0.4: - resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} regenerator-runtime@0.14.0: @@ -5389,6 +5639,10 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + rehype-parse@8.0.5: resolution: {integrity: sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==} @@ -5498,6 +5752,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.39.0: + resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -5516,9 +5775,17 @@ packages: resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} @@ -5526,6 +5793,10 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -5585,6 +5856,10 @@ packages: resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==} engines: {node: '>= 0.4'} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} engines: {node: '>= 0.4'} @@ -5593,6 +5868,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + sharp@0.32.6: resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} engines: {node: '>=14.15.0'} @@ -5619,13 +5898,26 @@ packages: shiki@0.14.5: resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==} - side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -5753,16 +6045,17 @@ packages: resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} engines: {node: '>=16'} - string.prototype.matchall@4.0.10: - resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} - - string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} string.prototype.repeat@1.0.0: resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} @@ -5777,6 +6070,10 @@ packages: string.prototype.trimend@1.0.8: resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} @@ -5858,17 +6155,17 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte-check@4.1.4: - resolution: {integrity: sha512-v0j7yLbT29MezzaQJPEDwksybTE2Ups9rUxEXy92T06TiA0cbqcO8wAOwNUVkFW6B0hsYHA+oAX3BS8b/2oHtw==} + svelte-check@4.1.5: + resolution: {integrity: sha512-Gb0T2IqBNe1tLB9EB1Qh+LOe+JB8wt2/rNBDGvkxQVvk8vNeAoG+vZgFB/3P5+zC7RWlyBlzm9dVjZFph/maIg==} engines: {node: '>= 18.0.0'} hasBin: true peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' - svelte-eslint-parser@0.43.0: - resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + svelte-eslint-parser@1.1.2: + resolution: {integrity: sha512-vqFBRamDKo1l70KMfxxXj1/0Cco5TfMDnqaAjgz6D8PyoMhfMcDOLRkAwPg8WkMyZjMtQL3wW66TZ0x59iqO2w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -5934,8 +6231,8 @@ packages: resolution: {integrity: sha512-LpLqY2Jr7cRxkrTc796/AaaoMLF/1ax7cto8Ot76wrvKQhrPmZ0JgajiWPmg9mTSDqO16SSLiD17r9MsvAPTmw==} engines: {node: '>=16'} - svelte@5.19.5: - resolution: {integrity: sha512-vVAntseegJX80sgbY8CxQISSE/VoDSfP7VZHoQaf2+z+2XOPOz/N+k455HJmO9O0g8oxTtuE0TBhC/5LAP4lPg==} + svelte@5.25.8: + resolution: {integrity: sha512-yRmjmT5rgCZUMfCKS5varGlSe/nQyr2oClyIirbBChfTFc00YjVAyVWo1zOH74La3hi5KRSkNJKncyJ04PwIYA==} engines: {node: '>=18'} svgo@3.0.2: @@ -5982,6 +6279,10 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -6023,14 +6324,8 @@ packages: trough@2.1.0: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -6122,6 +6417,10 @@ packages: resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} engines: {node: '>= 0.4'} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.0: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} engines: {node: '>= 0.4'} @@ -6130,6 +6429,10 @@ packages: resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.0: resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} engines: {node: '>= 0.4'} @@ -6138,6 +6441,10 @@ packages: resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} @@ -6145,18 +6452,12 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} - typescript@5.1.3: - resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} - engines: {node: '>=14.17'} - hasBin: true + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} - typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} - engines: {node: '>=14.17'} - hasBin: true - - typescript@5.4.2: - resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true @@ -6165,12 +6466,21 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + ultrahtml@1.5.2: resolution: {integrity: sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw==} unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -6375,8 +6685,8 @@ packages: terser: optional: true - vite@6.0.11: - resolution: {integrity: sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==} + vite@6.2.5: + resolution: {integrity: sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -6457,12 +6767,17 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} - which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} @@ -6487,6 +6802,10 @@ packages: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -6659,12 +6978,12 @@ snapshots: - supports-color - vite - '@astrojs/svelte@4.0.2(astro@3.2.2(@types/node@20.14.6)(terser@5.31.0))(svelte@4.2.1)(typescript@5.7.3)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0))': + '@astrojs/svelte@4.0.2(astro@3.2.2(@types/node@20.14.6)(terser@5.31.0))(svelte@4.2.1)(typescript@5.8.3)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0))': dependencies: '@sveltejs/vite-plugin-svelte': 2.5.3(svelte@4.2.1)(vite@4.5.3(@types/node@20.14.6)(terser@5.31.0)) astro: 3.2.2(@types/node@20.14.6)(terser@5.31.0) svelte: 4.2.1 - svelte2tsx: 0.6.23(svelte@4.2.1)(typescript@5.7.3) + svelte2tsx: 0.6.23(svelte@4.2.1)(typescript@5.8.3) transitivePeerDependencies: - supports-color - typescript @@ -7225,7 +7544,7 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.24.2': + '@esbuild/aix-ppc64@0.25.2': optional: true '@esbuild/android-arm64@0.18.20': @@ -7237,7 +7556,7 @@ snapshots: '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.24.2': + '@esbuild/android-arm64@0.25.2': optional: true '@esbuild/android-arm@0.18.20': @@ -7249,7 +7568,7 @@ snapshots: '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.24.2': + '@esbuild/android-arm@0.25.2': optional: true '@esbuild/android-x64@0.18.20': @@ -7261,7 +7580,7 @@ snapshots: '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.24.2': + '@esbuild/android-x64@0.25.2': optional: true '@esbuild/darwin-arm64@0.18.20': @@ -7273,7 +7592,7 @@ snapshots: '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.24.2': + '@esbuild/darwin-arm64@0.25.2': optional: true '@esbuild/darwin-x64@0.18.20': @@ -7285,7 +7604,7 @@ snapshots: '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.24.2': + '@esbuild/darwin-x64@0.25.2': optional: true '@esbuild/freebsd-arm64@0.18.20': @@ -7297,7 +7616,7 @@ snapshots: '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.24.2': + '@esbuild/freebsd-arm64@0.25.2': optional: true '@esbuild/freebsd-x64@0.18.20': @@ -7309,7 +7628,7 @@ snapshots: '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.24.2': + '@esbuild/freebsd-x64@0.25.2': optional: true '@esbuild/linux-arm64@0.18.20': @@ -7321,7 +7640,7 @@ snapshots: '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.24.2': + '@esbuild/linux-arm64@0.25.2': optional: true '@esbuild/linux-arm@0.18.20': @@ -7333,7 +7652,7 @@ snapshots: '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.24.2': + '@esbuild/linux-arm@0.25.2': optional: true '@esbuild/linux-ia32@0.18.20': @@ -7345,7 +7664,7 @@ snapshots: '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.24.2': + '@esbuild/linux-ia32@0.25.2': optional: true '@esbuild/linux-loong64@0.18.20': @@ -7357,7 +7676,7 @@ snapshots: '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.24.2': + '@esbuild/linux-loong64@0.25.2': optional: true '@esbuild/linux-mips64el@0.18.20': @@ -7369,7 +7688,7 @@ snapshots: '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.24.2': + '@esbuild/linux-mips64el@0.25.2': optional: true '@esbuild/linux-ppc64@0.18.20': @@ -7381,7 +7700,7 @@ snapshots: '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.24.2': + '@esbuild/linux-ppc64@0.25.2': optional: true '@esbuild/linux-riscv64@0.18.20': @@ -7393,7 +7712,7 @@ snapshots: '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.24.2': + '@esbuild/linux-riscv64@0.25.2': optional: true '@esbuild/linux-s390x@0.18.20': @@ -7405,7 +7724,7 @@ snapshots: '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.24.2': + '@esbuild/linux-s390x@0.25.2': optional: true '@esbuild/linux-x64@0.18.20': @@ -7417,10 +7736,10 @@ snapshots: '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.24.2': + '@esbuild/linux-x64@0.25.2': optional: true - '@esbuild/netbsd-arm64@0.24.2': + '@esbuild/netbsd-arm64@0.25.2': optional: true '@esbuild/netbsd-x64@0.18.20': @@ -7432,10 +7751,10 @@ snapshots: '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.24.2': + '@esbuild/netbsd-x64@0.25.2': optional: true - '@esbuild/openbsd-arm64@0.24.2': + '@esbuild/openbsd-arm64@0.25.2': optional: true '@esbuild/openbsd-x64@0.18.20': @@ -7447,7 +7766,7 @@ snapshots: '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.24.2': + '@esbuild/openbsd-x64@0.25.2': optional: true '@esbuild/sunos-x64@0.18.20': @@ -7459,7 +7778,7 @@ snapshots: '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.24.2': + '@esbuild/sunos-x64@0.25.2': optional: true '@esbuild/win32-arm64@0.18.20': @@ -7471,7 +7790,7 @@ snapshots: '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.24.2': + '@esbuild/win32-arm64@0.25.2': optional: true '@esbuild/win32-ia32@0.18.20': @@ -7483,7 +7802,7 @@ snapshots: '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.24.2': + '@esbuild/win32-ia32@0.25.2': optional: true '@esbuild/win32-x64@0.18.20': @@ -7495,7 +7814,7 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.24.2': + '@esbuild/win32-x64@0.25.2': optional: true '@eslint-community/eslint-utils@4.4.0(eslint@8.43.0)': @@ -7503,20 +7822,40 @@ snapshots: eslint: 8.43.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@8.53.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.24.0)': dependencies: - eslint: 8.53.0 + eslint: 9.24.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.5.1(eslint@9.24.0)': dependencies: - eslint: 8.57.0 + eslint: 9.24.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.9.1': {} + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.1': {} + + '@eslint/core@0.12.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@2.1.2': dependencies: ajv: 6.12.6 @@ -7531,27 +7870,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/eslintrc@2.1.3': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.23.0 - ignore: 5.3.0 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.23.0 - ignore: 5.3.0 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -7561,9 +7886,14 @@ snapshots: '@eslint/js@8.43.0': {} - '@eslint/js@8.53.0': {} + '@eslint/js@9.24.0': {} - '@eslint/js@8.57.0': {} + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 '@fastify/busboy@2.0.0': {} @@ -7573,6 +7903,13 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/config-array@0.11.13': dependencies: '@humanwhocodes/object-schema': 2.0.1 @@ -7581,19 +7918,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/object-schema@2.0.1': {} - '@humanwhocodes/object-schema@2.0.2': {} + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} '@jridgewell/gen-mapping@0.3.3': dependencies: @@ -7677,10 +8008,10 @@ snapshots: - sugarss - terser - '@playwright/experimental-ct-react@1.49.1(@types/node@20.14.6)(terser@5.31.0)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))': + '@playwright/experimental-ct-react@1.49.1(@types/node@20.14.6)(terser@5.31.0)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))': dependencies: '@playwright/experimental-ct-core': 1.49.1(@types/node@20.14.6)(terser@5.31.0) - '@vitejs/plugin-react': 4.3.1(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + '@vitejs/plugin-react': 4.3.1(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) transitivePeerDependencies: - '@types/node' - less @@ -7752,11 +8083,11 @@ snapshots: optionalDependencies: rollup: 4.18.0 - '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.8.1)(typescript@5.4.2)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.8.1)(typescript@5.7.3)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 - typescript: 5.4.2 + typescript: 5.7.3 optionalDependencies: rollup: 4.18.0 tslib: 2.8.1 @@ -7775,102 +8106,162 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.25.0': optional: true + '@rollup/rollup-android-arm-eabi@4.39.0': + optional: true + '@rollup/rollup-android-arm64@4.18.0': optional: true '@rollup/rollup-android-arm64@4.25.0': optional: true + '@rollup/rollup-android-arm64@4.39.0': + optional: true + '@rollup/rollup-darwin-arm64@4.18.0': optional: true '@rollup/rollup-darwin-arm64@4.25.0': optional: true + '@rollup/rollup-darwin-arm64@4.39.0': + optional: true + '@rollup/rollup-darwin-x64@4.18.0': optional: true '@rollup/rollup-darwin-x64@4.25.0': optional: true + '@rollup/rollup-darwin-x64@4.39.0': + optional: true + '@rollup/rollup-freebsd-arm64@4.25.0': optional: true + '@rollup/rollup-freebsd-arm64@4.39.0': + optional: true + '@rollup/rollup-freebsd-x64@4.25.0': optional: true + '@rollup/rollup-freebsd-x64@4.39.0': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.25.0': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.39.0': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true '@rollup/rollup-linux-arm-musleabihf@4.25.0': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.39.0': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true '@rollup/rollup-linux-arm64-gnu@4.25.0': optional: true + '@rollup/rollup-linux-arm64-gnu@4.39.0': + optional: true + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true '@rollup/rollup-linux-arm64-musl@4.25.0': optional: true + '@rollup/rollup-linux-arm64-musl@4.39.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.39.0': + optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true '@rollup/rollup-linux-powerpc64le-gnu@4.25.0': optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.39.0': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true '@rollup/rollup-linux-riscv64-gnu@4.25.0': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.39.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.39.0': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true '@rollup/rollup-linux-s390x-gnu@4.25.0': optional: true + '@rollup/rollup-linux-s390x-gnu@4.39.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true '@rollup/rollup-linux-x64-gnu@4.25.0': optional: true + '@rollup/rollup-linux-x64-gnu@4.39.0': + optional: true + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true '@rollup/rollup-linux-x64-musl@4.25.0': optional: true + '@rollup/rollup-linux-x64-musl@4.39.0': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true '@rollup/rollup-win32-arm64-msvc@4.25.0': optional: true + '@rollup/rollup-win32-arm64-msvc@4.39.0': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true '@rollup/rollup-win32-ia32-msvc@4.25.0': optional: true + '@rollup/rollup-win32-ia32-msvc@4.39.0': + optional: true + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true '@rollup/rollup-win32-x64-msvc@4.25.0': optional: true + '@rollup/rollup-win32-x64-msvc@4.39.0': + optional: true + '@sideway/address@4.1.4': dependencies: '@hapi/hoek': 9.3.0 @@ -7881,18 +8272,22 @@ snapshots: '@sindresorhus/merge-streams@1.0.0': {} - '@svelte-put/shortcut@4.1.0(svelte@5.19.5)': + '@svelte-put/shortcut@4.1.0(svelte@5.25.8)': dependencies: - svelte: 5.19.5 + svelte: 5.25.8 - '@sveltejs/adapter-auto@4.0.0(@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))': + '@sveltejs/acorn-typescript@1.0.5(acorn@8.14.0)': dependencies: - '@sveltejs/kit': 2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + acorn: 8.14.0 + + '@sveltejs/adapter-auto@6.0.0(@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))': + dependencies: + '@sveltejs/kit': 2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) import-meta-resolve: 4.1.0 - '@sveltejs/kit@2.16.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))': + '@sveltejs/kit@2.20.4(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -7904,17 +8299,17 @@ snapshots: sade: 1.8.1 set-cookie-parser: 2.6.0 sirv: 3.0.0 - svelte: 5.19.5 - vite: 6.0.11(@types/node@20.14.6)(terser@5.31.0) + svelte: 5.25.8 + vite: 6.2.5(@types/node@20.14.6)(terser@5.31.0) - '@sveltejs/package@2.3.9(svelte@5.19.5)(typescript@5.7.3)': + '@sveltejs/package@2.3.10(svelte@5.25.8)(typescript@5.8.3)': dependencies: - chokidar: 4.0.1 + chokidar: 4.0.3 kleur: 4.1.5 sade: 1.8.1 semver: 7.6.3 - svelte: 5.19.5 - svelte2tsx: 0.7.34(svelte@5.19.5)(typescript@5.7.3) + svelte: 5.25.8 + svelte2tsx: 0.7.34(svelte@5.25.8)(typescript@5.8.3) transitivePeerDependencies: - typescript @@ -7927,12 +8322,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) debug: 4.4.0 - svelte: 5.19.5 - vite: 6.0.11(@types/node@20.14.6)(terser@5.31.0) + svelte: 5.25.8 + vite: 6.2.5(@types/node@20.14.6)(terser@5.31.0) transitivePeerDependencies: - supports-color @@ -7950,16 +8345,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))': + '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.19.5)(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)))(svelte@5.25.8)(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) debug: 4.4.0 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.17 - svelte: 5.19.5 - vite: 6.0.11(@types/node@20.14.6)(terser@5.31.0) - vitefu: 1.0.4(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)) + svelte: 5.25.8 + vite: 6.2.5(@types/node@20.14.6)(terser@5.31.0) + vitefu: 1.0.4(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)) transitivePeerDependencies: - supports-color @@ -8095,6 +8490,8 @@ snapshots: '@types/estree@1.0.6': {} + '@types/estree@1.0.7': {} + '@types/hast@2.3.7': dependencies: '@types/unist': 2.0.9 @@ -8103,6 +8500,8 @@ snapshots: dependencies: ci-info: 3.9.0 + '@types/json-schema@7.0.15': {} + '@types/json5@0.0.30': {} '@types/mdast@3.0.14': @@ -8189,217 +8588,83 @@ snapshots: '@types/node': 18.7.16 optional: true - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@8.43.0)(typescript@5.1.3))(eslint@8.43.0)(typescript@5.1.3)': + '@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 8.0.0(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/type-utils': 8.0.0(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/utils': 8.0.0(eslint@8.43.0)(typescript@5.1.3) - '@typescript-eslint/visitor-keys': 8.0.0 - eslint: 8.43.0 + '@typescript-eslint/parser': 8.29.1(eslint@9.24.0)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/type-utils': 8.29.1(eslint@9.24.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.29.1 + eslint: 9.24.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.1.3) - optionalDependencies: - typescript: 5.1.3 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@8.53.0)(typescript@5.7.3))(eslint@8.53.0)(typescript@5.7.3)': + '@typescript-eslint/parser@8.29.1(eslint@9.24.0)(typescript@5.8.3)': dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 8.22.0(eslint@8.53.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@8.53.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@8.53.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 8.53.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 8.22.0(eslint@8.57.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/type-utils': 8.22.0(eslint@8.57.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@8.57.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.0.0(eslint@8.43.0)(typescript@5.1.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.1.3) - '@typescript-eslint/visitor-keys': 8.0.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.43.0 - optionalDependencies: - typescript: 5.1.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.22.0(eslint@8.53.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.29.1 debug: 4.4.0 - eslint: 8.53.0 - typescript: 5.7.3 + eslint: 9.24.0 + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.22.0(eslint@8.57.0)(typescript@5.7.3)': + '@typescript-eslint/scope-manager@8.29.1': dependencies: - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.22.0 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 + + '@typescript-eslint/type-utils@8.29.1(eslint@9.24.0)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0)(typescript@5.8.3) debug: 4.4.0 - eslint: 8.57.0 - typescript: 5.7.3 + eslint: 9.24.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.0.0': + '@typescript-eslint/types@8.29.1': {} + + '@typescript-eslint/typescript-estree@8.29.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 - - '@typescript-eslint/scope-manager@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 - - '@typescript-eslint/type-utils@8.0.0(eslint@8.43.0)(typescript@5.1.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.1.3) - '@typescript-eslint/utils': 8.0.0(eslint@8.43.0)(typescript@5.1.3) - debug: 4.3.5 - ts-api-utils: 1.3.0(typescript@5.1.3) - optionalDependencies: - typescript: 5.1.3 - transitivePeerDependencies: - - eslint - - supports-color - - '@typescript-eslint/type-utils@8.22.0(eslint@8.53.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@8.53.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 8.53.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/type-utils@8.22.0(eslint@8.57.0)(typescript@5.7.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.22.0(eslint@8.57.0)(typescript@5.7.3) - debug: 4.4.0 - eslint: 8.57.0 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.0.0': {} - - '@typescript-eslint/types@8.22.0': {} - - '@typescript-eslint/typescript-estree@8.0.0(typescript@5.1.3)': - dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.1.3) - optionalDependencies: - typescript: 5.1.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3)': - dependencies: - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/visitor-keys': 8.22.0 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 debug: 4.4.0 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 2.0.0(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.0.0(eslint@8.43.0)(typescript@5.1.3)': + '@typescript-eslint/utils@8.29.1(eslint@9.24.0)(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.43.0) - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.1.3) - eslint: 8.43.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@8.22.0(eslint@8.53.0)(typescript@5.7.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 8.53.0 - typescript: 5.7.3 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.24.0) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.8.3) + eslint: 9.24.0 + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.22.0(eslint@8.57.0)(typescript@5.7.3)': + '@typescript-eslint/visitor-keys@8.29.1': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 8.22.0 - '@typescript-eslint/types': 8.22.0 - '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3) - eslint: 8.57.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.0.0': - dependencies: - '@typescript-eslint/types': 8.0.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@8.22.0': - dependencies: - '@typescript-eslint/types': 8.22.0 + '@typescript-eslint/types': 8.29.1 eslint-visitor-keys: 4.2.0 - '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react-swc@3.4.1(vite@4.5.0(@types/node@20.14.6)(terser@5.31.0))': dependencies: '@swc/core': 1.3.96 @@ -8429,14 +8694,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.3.1(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0))': + '@vitejs/plugin-react@4.3.1(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0))': dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.7) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.0.11(@types/node@20.14.6)(terser@5.31.0) + vite: 6.2.5(@types/node@20.14.6)(terser@5.31.0) transitivePeerDependencies: - supports-color @@ -8444,7 +8709,7 @@ snapshots: dependencies: acorn: 8.10.0 - acorn-typescript@1.4.13(acorn@8.14.0): + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -8523,13 +8788,10 @@ snapshots: call-bind: 1.0.7 is-array-buffer: 3.0.4 - array-includes@3.1.7: + array-buffer-byte-length@1.0.2: dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-string: 1.0.7 + call-bound: 1.0.4 + is-array-buffer: 3.0.5 array-includes@3.1.8: dependencies: @@ -8560,21 +8822,13 @@ snapshots: es-abstract: 1.22.3 es-shim-unscopables: 1.0.2 - array.prototype.flatmap@1.3.2: + array.prototype.flatmap@1.3.3: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.9 es-shim-unscopables: 1.0.2 - array.prototype.tosorted@1.1.2: - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 - array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.7 @@ -8604,6 +8858,16 @@ snapshots: is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + arrify@1.0.1: {} asn1@0.2.6: @@ -8686,10 +8950,6 @@ snapshots: async@3.2.5: {} - asynciterator.prototype@1.0.0: - dependencies: - has-symbols: 1.0.3 - asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -8704,14 +8964,14 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - autoprefixer@10.4.20(postcss@8.5.1): + autoprefixer@10.4.21(postcss@8.5.3): dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001680 + browserslist: 4.24.4 + caniuse-lite: 1.0.30001712 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 - postcss: 8.5.1 + picocolors: 1.1.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.5: {} @@ -8817,6 +9077,13 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001712 + electron-to-chromium: 1.5.134 + node-releases: 2.0.19 + update-browserslist-db: 1.1.1(browserslist@4.24.4) + buffer-crc32@0.2.13: {} buffer-from@1.1.2: {} @@ -8835,6 +9102,11 @@ snapshots: cachedir@2.4.0: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + call-bind@1.0.5: dependencies: function-bind: 1.1.2 @@ -8849,6 +9121,18 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.1 + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.0 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} camelcase-keys@6.2.2: @@ -8872,6 +9156,8 @@ snapshots: caniuse-lite@1.0.30001680: {} + caniuse-lite@1.0.30001712: {} + caseless@0.12.0: {} ccount@2.0.1: {} @@ -8915,6 +9201,10 @@ snapshots: dependencies: readdirp: 4.0.2 + chokidar@4.0.3: + dependencies: + readdirp: 4.0.2 + chownr@1.1.4: optional: true @@ -9053,13 +9343,19 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + css-declaration-sorter@6.4.1(postcss@8.4.21): dependencies: postcss: 8.4.21 - css-declaration-sorter@7.2.0(postcss@8.5.1): + css-declaration-sorter@7.2.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 css-select@5.1.0: dependencies: @@ -9116,47 +9412,47 @@ snapshots: postcss-svgo: 6.0.0(postcss@8.4.21) postcss-unique-selectors: 6.0.0(postcss@8.4.21) - cssnano-preset-default@7.0.6(postcss@8.5.1): + cssnano-preset-default@7.0.6(postcss@8.5.3): dependencies: browserslist: 4.24.2 - css-declaration-sorter: 7.2.0(postcss@8.5.1) - cssnano-utils: 5.0.0(postcss@8.5.1) - postcss: 8.5.1 - postcss-calc: 10.0.2(postcss@8.5.1) - postcss-colormin: 7.0.2(postcss@8.5.1) - postcss-convert-values: 7.0.4(postcss@8.5.1) - postcss-discard-comments: 7.0.3(postcss@8.5.1) - postcss-discard-duplicates: 7.0.1(postcss@8.5.1) - postcss-discard-empty: 7.0.0(postcss@8.5.1) - postcss-discard-overridden: 7.0.0(postcss@8.5.1) - postcss-merge-longhand: 7.0.4(postcss@8.5.1) - postcss-merge-rules: 7.0.4(postcss@8.5.1) - postcss-minify-font-values: 7.0.0(postcss@8.5.1) - postcss-minify-gradients: 7.0.0(postcss@8.5.1) - postcss-minify-params: 7.0.2(postcss@8.5.1) - postcss-minify-selectors: 7.0.4(postcss@8.5.1) - postcss-normalize-charset: 7.0.0(postcss@8.5.1) - postcss-normalize-display-values: 7.0.0(postcss@8.5.1) - postcss-normalize-positions: 7.0.0(postcss@8.5.1) - postcss-normalize-repeat-style: 7.0.0(postcss@8.5.1) - postcss-normalize-string: 7.0.0(postcss@8.5.1) - postcss-normalize-timing-functions: 7.0.0(postcss@8.5.1) - postcss-normalize-unicode: 7.0.2(postcss@8.5.1) - postcss-normalize-url: 7.0.0(postcss@8.5.1) - postcss-normalize-whitespace: 7.0.0(postcss@8.5.1) - postcss-ordered-values: 7.0.1(postcss@8.5.1) - postcss-reduce-initial: 7.0.2(postcss@8.5.1) - postcss-reduce-transforms: 7.0.0(postcss@8.5.1) - postcss-svgo: 7.0.1(postcss@8.5.1) - postcss-unique-selectors: 7.0.3(postcss@8.5.1) + css-declaration-sorter: 7.2.0(postcss@8.5.3) + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-calc: 10.0.2(postcss@8.5.3) + postcss-colormin: 7.0.2(postcss@8.5.3) + postcss-convert-values: 7.0.4(postcss@8.5.3) + postcss-discard-comments: 7.0.3(postcss@8.5.3) + postcss-discard-duplicates: 7.0.1(postcss@8.5.3) + postcss-discard-empty: 7.0.0(postcss@8.5.3) + postcss-discard-overridden: 7.0.0(postcss@8.5.3) + postcss-merge-longhand: 7.0.4(postcss@8.5.3) + postcss-merge-rules: 7.0.4(postcss@8.5.3) + postcss-minify-font-values: 7.0.0(postcss@8.5.3) + postcss-minify-gradients: 7.0.0(postcss@8.5.3) + postcss-minify-params: 7.0.2(postcss@8.5.3) + postcss-minify-selectors: 7.0.4(postcss@8.5.3) + postcss-normalize-charset: 7.0.0(postcss@8.5.3) + postcss-normalize-display-values: 7.0.0(postcss@8.5.3) + postcss-normalize-positions: 7.0.0(postcss@8.5.3) + postcss-normalize-repeat-style: 7.0.0(postcss@8.5.3) + postcss-normalize-string: 7.0.0(postcss@8.5.3) + postcss-normalize-timing-functions: 7.0.0(postcss@8.5.3) + postcss-normalize-unicode: 7.0.2(postcss@8.5.3) + postcss-normalize-url: 7.0.0(postcss@8.5.3) + postcss-normalize-whitespace: 7.0.0(postcss@8.5.3) + postcss-ordered-values: 7.0.1(postcss@8.5.3) + postcss-reduce-initial: 7.0.2(postcss@8.5.3) + postcss-reduce-transforms: 7.0.0(postcss@8.5.3) + postcss-svgo: 7.0.1(postcss@8.5.3) + postcss-unique-selectors: 7.0.3(postcss@8.5.3) cssnano-utils@4.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - cssnano-utils@5.0.0(postcss@8.5.1): + cssnano-utils@5.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 cssnano@6.0.1(postcss@8.4.21): dependencies: @@ -9164,11 +9460,11 @@ snapshots: lilconfig: 2.1.0 postcss: 8.4.21 - cssnano@7.0.6(postcss@8.5.1): + cssnano@7.0.6(postcss@8.5.3): dependencies: - cssnano-preset-default: 7.0.6(postcss@8.5.1) + cssnano-preset-default: 7.0.6(postcss@8.5.3) lilconfig: 3.1.2 - postcss: 8.5.1 + postcss: 8.5.3 csso@5.0.5: dependencies: @@ -9289,18 +9585,36 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.1 + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + data-view-byte-length@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + data-view-byte-offset@1.0.0: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + dataloader@1.4.0: {} date-fns@2.30.0: @@ -9388,6 +9702,8 @@ snapshots: dependency-graph@0.11.0: {} + dependency-graph@1.0.0: {} + dequal@2.0.3: {} detect-indent@6.1.0: {} @@ -9441,6 +9757,12 @@ snapshots: dset@3.1.2: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + duplexer@0.1.2: {} eastasianwidth@0.2.0: {} @@ -9452,6 +9774,8 @@ snapshots: electron-to-chromium@1.4.563: {} + electron-to-chromium@1.5.134: {} + electron-to-chromium@1.5.56: {} emoji-regex@10.3.0: {} @@ -9566,45 +9890,86 @@ snapshots: unbox-primitive: 1.0.2 which-typed-array: 1.1.15 + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} + es-errors@1.3.0: {} - es-iterator-helpers@1.0.15: + es-iterator-helpers@1.2.1: dependencies: - asynciterator.prototype: 1.0.0 - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.22.3 - es-set-tostringtag: 2.0.2 - function-bind: 1.1.2 - get-intrinsic: 1.2.2 - globalthis: 1.0.3 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - iterator.prototype: 1.1.2 - safe-array-concat: 1.0.1 - - es-iterator-helpers@1.0.19: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.9 es-errors: 1.3.0 es-set-tostringtag: 2.0.3 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 es-module-lexer@1.3.1: {} @@ -9612,6 +9977,10 @@ snapshots: dependencies: es-errors: 1.3.0 + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + es-set-tostringtag@2.0.2: dependencies: get-intrinsic: 1.2.4 @@ -9620,7 +9989,14 @@ snapshots: es-set-tostringtag@2.0.3: dependencies: - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 hasown: 2.0.2 @@ -9634,6 +10010,12 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + esbuild@0.18.20: optionalDependencies: '@esbuild/android-arm': 0.18.20 @@ -9710,33 +10092,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.24.2: + esbuild@0.25.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.24.2 - '@esbuild/android-arm': 0.24.2 - '@esbuild/android-arm64': 0.24.2 - '@esbuild/android-x64': 0.24.2 - '@esbuild/darwin-arm64': 0.24.2 - '@esbuild/darwin-x64': 0.24.2 - '@esbuild/freebsd-arm64': 0.24.2 - '@esbuild/freebsd-x64': 0.24.2 - '@esbuild/linux-arm': 0.24.2 - '@esbuild/linux-arm64': 0.24.2 - '@esbuild/linux-ia32': 0.24.2 - '@esbuild/linux-loong64': 0.24.2 - '@esbuild/linux-mips64el': 0.24.2 - '@esbuild/linux-ppc64': 0.24.2 - '@esbuild/linux-riscv64': 0.24.2 - '@esbuild/linux-s390x': 0.24.2 - '@esbuild/linux-x64': 0.24.2 - '@esbuild/netbsd-arm64': 0.24.2 - '@esbuild/netbsd-x64': 0.24.2 - '@esbuild/openbsd-arm64': 0.24.2 - '@esbuild/openbsd-x64': 0.24.2 - '@esbuild/sunos-x64': 0.24.2 - '@esbuild/win32-arm64': 0.24.2 - '@esbuild/win32-ia32': 0.24.2 - '@esbuild/win32-x64': 0.24.2 + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 escalade@3.1.1: {} @@ -9748,131 +10130,79 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.5.1(eslint@8.53.0): + eslint-config-prettier@10.1.1(eslint@9.24.0): dependencies: - eslint: 8.53.0 - semver: 7.6.3 + eslint: 9.24.0 - eslint-compat-utils@0.5.1(eslint@8.57.0): + eslint-config-turbo@2.5.0(eslint@9.24.0)(turbo@2.0.3): dependencies: - eslint: 8.57.0 - semver: 7.6.3 + eslint: 9.24.0 + eslint-plugin-turbo: 2.5.0(eslint@9.24.0)(turbo@2.0.3) + turbo: 2.0.3 - eslint-config-prettier@8.8.0(eslint@8.43.0): + eslint-plugin-prettier@4.2.1(eslint-config-prettier@10.1.1(eslint@9.24.0))(eslint@9.24.0)(prettier@3.5.3): dependencies: - eslint: 8.43.0 - - eslint-config-prettier@9.1.0(eslint@8.53.0): - dependencies: - eslint: 8.53.0 - - eslint-config-prettier@9.1.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - - eslint-config-turbo@2.0.3(eslint@8.43.0): - dependencies: - eslint: 8.43.0 - eslint-plugin-turbo: 2.0.3(eslint@8.43.0) - - eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0(eslint@8.43.0))(eslint@8.43.0)(prettier@2.8.8): - dependencies: - eslint: 8.43.0 - prettier: 2.8.8 + eslint: 9.24.0 + prettier: 3.5.3 prettier-linter-helpers: 1.0.0 optionalDependencies: - eslint-config-prettier: 8.8.0(eslint@8.43.0) + eslint-config-prettier: 10.1.1(eslint@9.24.0) - eslint-plugin-react@7.33.2(eslint@8.43.0): - dependencies: - array-includes: 3.1.7 - array.prototype.flatmap: 1.3.2 - array.prototype.tosorted: 1.1.2 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.15 - eslint: 8.43.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - object.hasown: 1.1.3 - object.values: 1.1.7 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.10 - - eslint-plugin-react@7.35.0(eslint@8.43.0): + eslint-plugin-react@7.37.5(eslint@9.24.0): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 + array.prototype.flatmap: 1.3.3 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 - eslint: 8.43.0 + es-iterator-helpers: 1.2.1 + eslint: 9.24.0 estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 minimatch: 3.1.2 - object.entries: 1.1.8 + object.entries: 1.1.9 object.fromentries: 2.0.8 - object.values: 1.2.0 + object.values: 1.2.1 prop-types: 15.8.1 resolve: 2.0.0-next.5 semver: 6.3.1 - string.prototype.matchall: 4.0.11 + string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-svelte@2.46.1(eslint@8.53.0)(svelte@5.19.5): + eslint-plugin-svelte@3.5.1(eslint@9.24.0)(svelte@5.25.8): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0) '@jridgewell/sourcemap-codec': 1.5.0 - eslint: 8.53.0 - eslint-compat-utils: 0.5.1(eslint@8.53.0) + eslint: 9.24.0 esutils: 2.0.3 known-css-properties: 0.35.0 - postcss: 8.4.49 - postcss-load-config: 3.1.4(postcss@8.4.49) - postcss-safe-parser: 6.0.0(postcss@8.4.49) - postcss-selector-parser: 6.1.2 + postcss: 8.5.3 + postcss-load-config: 3.1.4(postcss@8.5.3) + postcss-safe-parser: 7.0.1(postcss@8.5.3) semver: 7.6.3 - svelte-eslint-parser: 0.43.0(svelte@5.19.5) + svelte-eslint-parser: 1.1.2(svelte@5.25.8) optionalDependencies: - svelte: 5.19.5 + svelte: 5.25.8 transitivePeerDependencies: - ts-node - eslint-plugin-svelte@2.46.1(eslint@8.57.0)(svelte@5.19.5): - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@jridgewell/sourcemap-codec': 1.5.0 - eslint: 8.57.0 - eslint-compat-utils: 0.5.1(eslint@8.57.0) - esutils: 2.0.3 - known-css-properties: 0.35.0 - postcss: 8.4.49 - postcss-load-config: 3.1.4(postcss@8.4.49) - postcss-safe-parser: 6.0.0(postcss@8.4.49) - postcss-selector-parser: 6.1.2 - semver: 7.6.3 - svelte-eslint-parser: 0.43.0(svelte@5.19.5) - optionalDependencies: - svelte: 5.19.5 - transitivePeerDependencies: - - ts-node - - eslint-plugin-turbo@2.0.3(eslint@8.43.0): + eslint-plugin-turbo@2.5.0(eslint@9.24.0)(turbo@2.0.3): dependencies: dotenv: 16.0.3 - eslint: 8.43.0 + eslint: 9.24.0 + turbo: 2.0.3 eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} eslint-visitor-keys@4.2.0: {} @@ -9921,94 +10251,54 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@8.53.0: + eslint@9.24.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.3 - '@eslint/js': 8.53.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.24.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.24.0 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 + cross-spawn: 7.0.6 + debug: 4.4.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.23.0 - graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - eslint@8.57.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.23.0 - graphemer: 1.4.0 - ignore: 5.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 transitivePeerDependencies: - supports-color esm-env@1.2.2: {} + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + espree@9.6.1: dependencies: acorn: 8.10.0 @@ -10021,7 +10311,7 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@1.4.3: + esrap@1.4.6: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -10155,7 +10445,13 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.4.2: {} + fdir@6.4.2(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 figures@3.2.0: dependencies: @@ -10165,6 +10461,10 @@ snapshots: dependencies: flat-cache: 3.1.1 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 @@ -10190,6 +10490,11 @@ snapshots: keyv: 4.5.4 rimraf: 3.0.2 + flat-cache@4.0.1: + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + flatted@3.2.9: {} follow-redirects@1.15.3(debug@4.3.4): @@ -10200,6 +10505,10 @@ snapshots: dependencies: is-callable: 1.2.7 + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + forever-agent@0.6.1: {} form-data@2.3.3: @@ -10263,6 +10572,15 @@ snapshots: es-abstract: 1.22.3 functions-have-names: 1.2.3 + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + functions-have-names@1.2.3: {} gensync@1.0.0-beta.2: {} @@ -10284,6 +10602,24 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.0.0 + get-stdin@9.0.0: {} get-stream@5.2.0: @@ -10305,6 +10641,12 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + getos@3.2.1: dependencies: async: 3.2.5 @@ -10353,10 +10695,17 @@ snapshots: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + globalthis@1.0.3: dependencies: define-properties: 1.2.1 + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + globby@11.1.0: dependencies: array-union: 2.1.0 @@ -10379,6 +10728,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + gopd@1.2.0: {} + graceful-fs@4.2.11: {} grapheme-splitter@1.0.4: {} @@ -10416,15 +10767,21 @@ snapshots: has-proto@1.0.3: {} + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + has-symbols@1.0.3: {} + has-symbols@1.1.0: {} + has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 has-tostringtag@1.0.2: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown@2.0.1: dependencies: @@ -10570,6 +10927,12 @@ snapshots: hasown: 2.0.2 side-channel: 1.0.6 + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + is-array-buffer@3.0.2: dependencies: call-bind: 1.0.7 @@ -10581,6 +10944,12 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-arrayish@0.2.1: {} is-arrayish@0.3.2: @@ -10588,12 +10957,16 @@ snapshots: is-async-function@2.0.0: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 + is-bigint@1.1.0: + dependencies: + has-bigints: 1.0.2 + is-binary-path@2.1.0: dependencies: binary-extensions: 2.2.0 @@ -10603,6 +10976,11 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.0 + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-buffer@2.0.5: {} is-builtin-module@3.2.1: @@ -10623,25 +11001,36 @@ snapshots: dependencies: is-typed-array: 1.1.13 + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + is-date-object@1.0.5: dependencies: has-tostringtag: 1.0.0 + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-docker@3.0.0: {} is-extendable@0.1.1: {} is-extglob@2.1.1: {} - is-finalizationregistry@1.0.2: + is-finalizationregistry@1.1.1: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 is-fullwidth-code-point@3.0.0: {} is-generator-function@1.0.10: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-glob@4.0.3: dependencies: @@ -10658,7 +11047,7 @@ snapshots: is-interactive@2.0.0: {} - is-map@2.0.2: {} + is-map@2.0.3: {} is-module@1.0.0: {} @@ -10670,6 +11059,11 @@ snapshots: dependencies: has-tostringtag: 1.0.0 + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-number@7.0.0: {} is-path-inside@3.0.3: {} @@ -10695,7 +11089,14 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.0 - is-set@2.0.2: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} is-shared-array-buffer@1.0.2: dependencies: @@ -10705,6 +11106,10 @@ snapshots: dependencies: call-bind: 1.0.7 + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -10713,6 +11118,11 @@ snapshots: dependencies: has-tostringtag: 1.0.0 + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 @@ -10721,6 +11131,12 @@ snapshots: dependencies: has-symbols: 1.0.3 + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + is-typed-array@1.1.12: dependencies: which-typed-array: 1.1.13 @@ -10729,22 +11145,30 @@ snapshots: dependencies: which-typed-array: 1.1.15 + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + is-typedarray@1.0.0: {} is-unicode-supported@0.1.0: {} is-unicode-supported@1.3.0: {} - is-weakmap@2.0.1: {} + is-weakmap@2.0.2: {} is-weakref@1.0.2: dependencies: call-bind: 1.0.7 - is-weakset@2.0.2: + is-weakref@1.1.1: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 is-windows@1.0.2: {} @@ -10758,13 +11182,14 @@ snapshots: isstream@0.1.2: {} - iterator.prototype@1.1.2: + iterator.prototype@1.1.5: dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.4 - set-function-name: 2.0.1 + define-data-property: 1.1.4 + es-object-atoms: 1.0.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 joi@17.11.0: dependencies: @@ -10827,7 +11252,7 @@ snapshots: array-includes: 3.1.8 array.prototype.flat: 1.3.2 object.assign: 4.1.5 - object.values: 1.2.0 + object.values: 1.2.1 keyv@4.5.4: dependencies: @@ -10966,6 +11391,8 @@ snapshots: markdown-table@3.0.3: {} + math-intrinsics@1.1.0: {} + mdast-util-definitions@5.1.2: dependencies: '@types/mdast': 3.0.14 @@ -11391,6 +11818,8 @@ snapshots: node-releases@2.0.18: {} + node-releases@2.0.19: {} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -11418,6 +11847,8 @@ snapshots: object-inspect@1.13.1: {} + object-inspect@1.13.4: {} + object-keys@1.1.1: {} object.assign@4.1.5: @@ -11427,23 +11858,21 @@ snapshots: has-symbols: 1.0.3 object-keys: 1.1.1 - object.entries@1.1.7: + object.assign@4.1.7: dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - - object.entries@1.1.8: - dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.0.0 + has-symbols: 1.1.0 + object-keys: 1.1.1 - object.fromentries@2.0.7: + object.entries@1.1.9: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.1.1 object.fromentries@2.0.8: dependencies: @@ -11452,20 +11881,10 @@ snapshots: es-abstract: 1.23.3 es-object-atoms: 1.0.0 - object.hasown@1.1.3: + object.values@1.2.1: dependencies: - define-properties: 1.2.1 - es-abstract: 1.22.3 - - object.values@1.1.7: - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - - object.values@1.2.0: - dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.0.0 @@ -11508,6 +11927,12 @@ snapshots: outdent@0.5.0: {} + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -11596,12 +12021,12 @@ snapshots: picocolors@1.0.0: {} - picocolors@1.0.1: {} - picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pify@2.3.0: {} pify@4.0.1: {} @@ -11628,9 +12053,9 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-calc@10.0.2(postcss@8.5.1): + postcss-calc@10.0.2(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 @@ -11658,20 +12083,19 @@ snapshots: transitivePeerDependencies: - jiti - postcss-cli@11.0.0(postcss@8.5.1): + postcss-cli@11.0.1(postcss@8.5.3): dependencies: chokidar: 3.5.3 - dependency-graph: 0.11.0 + dependency-graph: 1.0.0 fs-extra: 11.2.0 - get-stdin: 9.0.0 - globby: 14.0.0 - picocolors: 1.0.0 - postcss: 8.5.1 - postcss-load-config: 5.0.2(postcss@8.5.1) - postcss-reporter: 7.0.5(postcss@8.5.1) + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-load-config: 5.0.2(postcss@8.5.3) + postcss-reporter: 7.0.5(postcss@8.5.3) pretty-hrtime: 1.0.3 read-cache: 1.0.0 slash: 5.1.0 + tinyglobby: 0.2.12 yargs: 17.7.2 transitivePeerDependencies: - jiti @@ -11684,12 +12108,12 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-colormin@7.0.2(postcss@8.5.1): + postcss-colormin@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 colord: 2.9.3 - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-combine-duplicated-selectors@10.0.3(postcss@8.4.21): @@ -11697,9 +12121,9 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-combine-duplicated-selectors@10.0.3(postcss@8.5.1): + postcss-combine-duplicated-selectors@10.0.3(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.0.13 postcss-convert-values@6.0.0(postcss@8.4.21): @@ -11708,44 +12132,44 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-convert-values@7.0.4(postcss@8.5.1): + postcss-convert-values@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-discard-comments@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - postcss-discard-comments@7.0.3(postcss@8.5.1): + postcss-discard-comments@7.0.3(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-discard-duplicates@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - postcss-discard-duplicates@7.0.1(postcss@8.5.1): + postcss-discard-duplicates@7.0.1(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-discard-empty@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - postcss-discard-empty@7.0.0(postcss@8.5.1): + postcss-discard-empty@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-discard-overridden@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - postcss-discard-overridden@7.0.0(postcss@8.5.1): + postcss-discard-overridden@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-import@15.1.0(postcss@8.4.21): dependencies: @@ -11754,19 +12178,19 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.8 - postcss-import@16.1.0(postcss@8.5.1): + postcss-import@16.1.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-load-config@3.1.4(postcss@8.4.49): + postcss-load-config@3.1.4(postcss@8.5.3): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-load-config@5.0.2(postcss@8.4.21): dependencies: @@ -11775,12 +12199,12 @@ snapshots: optionalDependencies: postcss: 8.4.21 - postcss-load-config@5.0.2(postcss@8.5.1): + postcss-load-config@5.0.2(postcss@8.5.3): dependencies: lilconfig: 3.0.0 yaml: 2.3.4 optionalDependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-merge-longhand@6.0.0(postcss@8.4.21): dependencies: @@ -11788,11 +12212,11 @@ snapshots: postcss-value-parser: 4.2.0 stylehacks: 6.0.0(postcss@8.4.21) - postcss-merge-longhand@7.0.4(postcss@8.5.1): + postcss-merge-longhand@7.0.4(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 - stylehacks: 7.0.4(postcss@8.5.1) + stylehacks: 7.0.4(postcss@8.5.3) postcss-merge-rules@6.0.1(postcss@8.4.21): dependencies: @@ -11802,12 +12226,12 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-merge-rules@7.0.4(postcss@8.5.1): + postcss-merge-rules@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 - cssnano-utils: 5.0.0(postcss@8.5.1) - postcss: 8.5.1 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-minify-font-values@6.0.0(postcss@8.4.21): @@ -11815,9 +12239,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-minify-font-values@7.0.0(postcss@8.5.1): + postcss-minify-font-values@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-minify-gradients@6.0.0(postcss@8.4.21): @@ -11827,11 +12251,11 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-minify-gradients@7.0.0(postcss@8.5.1): + postcss-minify-gradients@7.0.0(postcss@8.5.3): dependencies: colord: 2.9.3 - cssnano-utils: 5.0.0(postcss@8.5.1) - postcss: 8.5.1 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-minify-params@6.0.0(postcss@8.4.21): @@ -11841,11 +12265,11 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-minify-params@7.0.2(postcss@8.5.1): + postcss-minify-params@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 - cssnano-utils: 5.0.0(postcss@8.5.1) - postcss: 8.5.1 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-minify-selectors@6.0.0(postcss@8.4.21): @@ -11853,10 +12277,10 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-minify-selectors@7.0.4(postcss@8.5.1): + postcss-minify-selectors@7.0.4(postcss@8.5.3): dependencies: cssesc: 3.0.0 - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-nested@6.0.0(postcss@8.4.21): @@ -11864,27 +12288,27 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-nested@7.0.2(postcss@8.5.1): + postcss-nested@7.0.2(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 7.0.0 postcss-normalize-charset@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 - postcss-normalize-charset@7.0.0(postcss@8.5.1): + postcss-normalize-charset@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-normalize-display-values@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-display-values@7.0.0(postcss@8.5.1): + postcss-normalize-display-values@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-positions@6.0.0(postcss@8.4.21): @@ -11892,9 +12316,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-positions@7.0.0(postcss@8.5.1): + postcss-normalize-positions@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-repeat-style@6.0.0(postcss@8.4.21): @@ -11902,9 +12326,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@7.0.0(postcss@8.5.1): + postcss-normalize-repeat-style@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-string@6.0.0(postcss@8.4.21): @@ -11912,9 +12336,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-string@7.0.0(postcss@8.5.1): + postcss-normalize-string@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-timing-functions@6.0.0(postcss@8.4.21): @@ -11922,9 +12346,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@7.0.0(postcss@8.5.1): + postcss-normalize-timing-functions@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-unicode@6.0.0(postcss@8.4.21): @@ -11933,10 +12357,10 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@7.0.2(postcss@8.5.1): + postcss-normalize-unicode@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-url@6.0.0(postcss@8.4.21): @@ -11944,9 +12368,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-url@7.0.0(postcss@8.5.1): + postcss-normalize-url@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-normalize-whitespace@6.0.0(postcss@8.4.21): @@ -11954,9 +12378,9 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@7.0.0(postcss@8.5.1): + postcss-normalize-whitespace@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-ordered-values@6.0.0(postcss@8.4.21): @@ -11965,10 +12389,10 @@ snapshots: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-ordered-values@7.0.1(postcss@8.5.1): + postcss-ordered-values@7.0.1(postcss@8.5.3): dependencies: - cssnano-utils: 5.0.0(postcss@8.5.1) - postcss: 8.5.1 + cssnano-utils: 5.0.0(postcss@8.5.3) + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-reduce-initial@6.0.0(postcss@8.4.21): @@ -11977,20 +12401,20 @@ snapshots: caniuse-api: 3.0.0 postcss: 8.4.21 - postcss-reduce-initial@7.0.2(postcss@8.5.1): + postcss-reduce-initial@7.0.2(postcss@8.5.3): dependencies: browserslist: 4.24.2 caniuse-api: 3.0.0 - postcss: 8.5.1 + postcss: 8.5.3 postcss-reduce-transforms@6.0.0(postcss@8.4.21): dependencies: postcss: 8.4.21 postcss-value-parser: 4.2.0 - postcss-reduce-transforms@7.0.0(postcss@8.5.1): + postcss-reduce-transforms@7.0.0(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 postcss-rename@0.6.1(postcss@8.4.21): @@ -11998,9 +12422,9 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-rename@0.6.1(postcss@8.5.1): + postcss-rename@0.6.1(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.0.13 postcss-reporter@7.0.5(postcss@8.4.21): @@ -12009,19 +12433,19 @@ snapshots: postcss: 8.4.21 thenby: 1.3.4 - postcss-reporter@7.0.5(postcss@8.5.1): + postcss-reporter@7.0.5(postcss@8.5.3): dependencies: picocolors: 1.0.0 - postcss: 8.5.1 + postcss: 8.5.3 thenby: 1.3.4 - postcss-safe-parser@6.0.0(postcss@8.4.49): + postcss-safe-parser@7.0.1(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 - postcss-scss@4.0.9(postcss@8.5.1): + postcss-scss@4.0.9(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser@6.0.13: dependencies: @@ -12044,9 +12468,9 @@ snapshots: postcss-value-parser: 4.2.0 svgo: 3.0.2 - postcss-svgo@7.0.1(postcss@8.5.1): + postcss-svgo@7.0.1(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-value-parser: 4.2.0 svgo: 3.3.2 @@ -12055,9 +12479,9 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - postcss-unique-selectors@7.0.3(postcss@8.5.1): + postcss-unique-selectors@7.0.3(postcss@8.5.3): dependencies: - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-value-parser@4.2.0: {} @@ -12074,13 +12498,7 @@ snapshots: picocolors: 1.0.0 source-map-js: 1.0.2 - postcss@8.4.49: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postcss@8.5.1: + postcss@8.5.3: dependencies: nanoid: 3.3.8 picocolors: 1.1.1 @@ -12115,14 +12533,14 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@3.3.3(prettier@3.4.2)(svelte@5.19.5): + prettier-plugin-svelte@3.3.3(prettier@3.5.3)(svelte@5.25.8): dependencies: - prettier: 3.4.2 - svelte: 5.19.5 + prettier: 3.5.3 + svelte: 5.25.8 prettier@2.8.8: {} - prettier@3.4.2: {} + prettier@3.5.3: {} pretty-bytes@5.6.0: {} @@ -12291,14 +12709,16 @@ snapshots: redux@5.0.1: {} - reflect.getprototypeof@1.0.4: + reflect.getprototypeof@1.0.10: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.3 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 regenerator-runtime@0.14.0: {} @@ -12315,6 +12735,15 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + rehype-parse@8.0.5: dependencies: '@types/hast': 2.3.7 @@ -12498,6 +12927,32 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.25.0 fsevents: 2.3.3 + rollup@4.39.0: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.39.0 + '@rollup/rollup-android-arm64': 4.39.0 + '@rollup/rollup-darwin-arm64': 4.39.0 + '@rollup/rollup-darwin-x64': 4.39.0 + '@rollup/rollup-freebsd-arm64': 4.39.0 + '@rollup/rollup-freebsd-x64': 4.39.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.39.0 + '@rollup/rollup-linux-arm-musleabihf': 4.39.0 + '@rollup/rollup-linux-arm64-gnu': 4.39.0 + '@rollup/rollup-linux-arm64-musl': 4.39.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.39.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.39.0 + '@rollup/rollup-linux-riscv64-gnu': 4.39.0 + '@rollup/rollup-linux-riscv64-musl': 4.39.0 + '@rollup/rollup-linux-s390x-gnu': 4.39.0 + '@rollup/rollup-linux-x64-gnu': 4.39.0 + '@rollup/rollup-linux-x64-musl': 4.39.0 + '@rollup/rollup-win32-arm64-msvc': 4.39.0 + '@rollup/rollup-win32-ia32-msvc': 4.39.0 + '@rollup/rollup-win32-x64-msvc': 4.39.0 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -12524,8 +12979,21 @@ snapshots: has-symbols: 1.0.3 isarray: 2.0.5 + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + safe-regex-test@1.0.0: dependencies: call-bind: 1.0.7 @@ -12538,6 +13006,12 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + safer-buffer@2.1.2: {} sax@1.3.0: {} @@ -12595,6 +13069,15 @@ snapshots: gopd: 1.0.1 has-property-descriptors: 1.0.2 + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + set-function-name@2.0.1: dependencies: define-data-property: 1.1.1 @@ -12608,6 +13091,12 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + sharp@0.32.6: dependencies: color: 4.2.3 @@ -12641,11 +13130,25 @@ snapshots: vscode-oniguruma: 1.7.0 vscode-textmate: 8.0.0 - side-channel@1.0.4: + side-channel-list@1.0.0: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 side-channel@1.0.6: dependencies: @@ -12654,6 +13157,14 @@ snapshots: get-intrinsic: 1.2.4 object-inspect: 1.13.1 + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -12815,37 +13326,36 @@ snapshots: emoji-regex: 10.3.0 strip-ansi: 7.1.0 - string.prototype.matchall@4.0.10: + string.prototype.matchall@4.0.12: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - has-symbols: 1.0.3 - internal-slot: 1.0.6 - regexp.prototype.flags: 1.5.1 - set-function-name: 2.0.1 - side-channel: 1.0.4 - - string.prototype.matchall@4.0.11: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.9 es-errors: 1.3.0 es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 set-function-name: 2.0.2 - side-channel: 1.0.6 + side-channel: 1.1.0 string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.0.0 + has-property-descriptors: 1.0.2 string.prototype.trim@1.2.8: dependencies: @@ -12872,6 +13382,13 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + string.prototype.trimstart@1.0.7: dependencies: call-bind: 1.0.7 @@ -12926,10 +13443,10 @@ snapshots: postcss: 8.4.21 postcss-selector-parser: 6.0.13 - stylehacks@7.0.4(postcss@8.5.1): + stylehacks@7.0.4(postcss@8.5.3): dependencies: browserslist: 4.24.2 - postcss: 8.5.1 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 supports-color@5.5.0: @@ -12946,54 +13463,55 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@4.1.4(svelte@5.19.5)(typescript@5.7.3): + svelte-check@4.1.5(picomatch@4.0.2)(svelte@5.25.8)(typescript@5.8.3): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 4.0.1 - fdir: 6.4.2 + fdir: 6.4.2(picomatch@4.0.2) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.19.5 - typescript: 5.7.3 + svelte: 5.25.8 + typescript: 5.8.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@0.43.0(svelte@5.19.5): + svelte-eslint-parser@1.1.2(svelte@5.25.8): dependencies: - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - postcss: 8.5.1 - postcss-scss: 4.0.9(postcss@8.5.1) + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + postcss: 8.5.3 + postcss-scss: 4.0.9(postcss@8.5.3) + postcss-selector-parser: 7.0.0 optionalDependencies: - svelte: 5.19.5 + svelte: 5.25.8 svelte-hmr@0.15.3(svelte@4.2.1): dependencies: svelte: 4.2.1 - svelte-preprocess@6.0.3(@babel/core@7.24.7)(postcss-load-config@5.0.2(postcss@8.5.1))(postcss@8.5.1)(svelte@5.19.5)(typescript@5.7.3): + svelte-preprocess@6.0.3(@babel/core@7.24.7)(postcss-load-config@5.0.2(postcss@8.5.3))(postcss@8.5.3)(svelte@5.25.8)(typescript@5.8.3): dependencies: - svelte: 5.19.5 + svelte: 5.25.8 optionalDependencies: '@babel/core': 7.24.7 - postcss: 8.5.1 - postcss-load-config: 5.0.2(postcss@8.5.1) - typescript: 5.7.3 + postcss: 8.5.3 + postcss-load-config: 5.0.2(postcss@8.5.3) + typescript: 5.8.3 - svelte2tsx@0.6.23(svelte@4.2.1)(typescript@5.7.3): + svelte2tsx@0.6.23(svelte@4.2.1)(typescript@5.8.3): dependencies: dedent-js: 1.0.1 pascal-case: 3.1.2 svelte: 4.2.1 - typescript: 5.7.3 + typescript: 5.8.3 - svelte2tsx@0.7.34(svelte@5.19.5)(typescript@5.7.3): + svelte2tsx@0.7.34(svelte@5.25.8)(typescript@5.8.3): dependencies: dedent-js: 1.0.1 pascal-case: 3.1.2 - svelte: 5.19.5 - typescript: 5.7.3 + svelte: 5.25.8 + typescript: 5.8.3 svelte@4.2.1: dependencies: @@ -13011,18 +13529,18 @@ snapshots: magic-string: 0.30.5 periscopic: 3.1.0 - svelte@5.19.5: + svelte@5.25.8: dependencies: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.0 + '@sveltejs/acorn-typescript': 1.0.5(acorn@8.14.0) '@types/estree': 1.0.6 acorn: 8.14.0 - acorn-typescript: 1.4.13(acorn@8.14.0) aria-query: 5.3.2 axobject-query: 4.1.0 clsx: 2.1.1 esm-env: 1.2.2 - esrap: 1.4.3 + esrap: 1.4.6 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.17 @@ -13095,6 +13613,11 @@ snapshots: through@2.3.8: {} + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -13126,13 +13649,9 @@ snapshots: trough@2.1.0: {} - ts-api-utils@1.3.0(typescript@5.1.3): + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: - typescript: 5.1.3 - - ts-api-utils@2.0.0(typescript@5.7.3): - dependencies: - typescript: 5.7.3 + typescript: 5.8.3 tsconfig-resolver@3.0.1: dependencies: @@ -13216,6 +13735,12 @@ snapshots: es-errors: 1.3.0 is-typed-array: 1.1.13 + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + typed-array-byte-length@1.0.0: dependencies: call-bind: 1.0.7 @@ -13231,6 +13756,14 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + typed-array-byte-offset@1.0.0: dependencies: available-typed-arrays: 1.0.5 @@ -13248,6 +13781,16 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + typed-array-length@1.0.4: dependencies: call-bind: 1.0.7 @@ -13263,14 +13806,21 @@ snapshots: is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - typescript@5.1.3: {} + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.0.0 + reflect.getprototypeof: 1.0.10 - typescript@5.2.2: {} - - typescript@5.4.2: {} + typescript@5.4.5: {} typescript@5.7.3: {} + typescript@5.8.3: {} + ultrahtml@1.5.2: {} unbox-primitive@1.0.2: @@ -13280,6 +13830,13 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.0.2 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + undici-types@5.26.5: {} undici@5.26.5: @@ -13369,6 +13926,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.1.1(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.0 @@ -13434,7 +13997,7 @@ snapshots: vite@4.5.3(@types/node@20.14.6)(terser@5.31.0): dependencies: esbuild: 0.18.20 - postcss: 8.5.1 + postcss: 8.5.3 rollup: 3.29.4 optionalDependencies: '@types/node': 20.14.6 @@ -13444,18 +14007,18 @@ snapshots: vite@5.4.11(@types/node@20.14.6)(terser@5.31.0): dependencies: esbuild: 0.21.5 - postcss: 8.5.1 + postcss: 8.5.3 rollup: 4.25.0 optionalDependencies: '@types/node': 20.14.6 fsevents: 2.3.3 terser: 5.31.0 - vite@6.0.11(@types/node@20.14.6)(terser@5.31.0): + vite@6.2.5(@types/node@20.14.6)(terser@5.31.0): dependencies: - esbuild: 0.24.2 - postcss: 8.5.1 - rollup: 4.25.0 + esbuild: 0.25.2 + postcss: 8.5.3 + rollup: 4.39.0 optionalDependencies: '@types/node': 20.14.6 fsevents: 2.3.3 @@ -13465,9 +14028,9 @@ snapshots: optionalDependencies: vite: 4.5.3(@types/node@20.14.6)(terser@5.31.0) - vitefu@1.0.4(vite@6.0.11(@types/node@20.14.6)(terser@5.31.0)): + vitefu@1.0.4(vite@6.2.5(@types/node@20.14.6)(terser@5.31.0)): optionalDependencies: - vite: 6.0.11(@types/node@20.14.6)(terser@5.31.0) + vite: 6.2.5(@types/node@20.14.6)(terser@5.31.0) vscode-oniguruma@1.7.0: {} @@ -13504,27 +14067,36 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.1.3: + which-boxed-primitive@1.1.1: dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.13 + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 - which-collection@1.0.1: + which-builtin-type@1.2.1: dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.0.10 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 which-module@2.0.1: {} @@ -13556,6 +14128,16 @@ snapshots: gopd: 1.0.1 has-tostringtag: 1.0.2 + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + which@1.3.1: dependencies: isexe: 2.0.0 diff --git a/tests/playwright/e2e/pane.spec.ts b/tests/playwright/e2e/pane.spec.ts index fade5e0c..4c27e33c 100644 --- a/tests/playwright/e2e/pane.spec.ts +++ b/tests/playwright/e2e/pane.spec.ts @@ -20,18 +20,21 @@ test.describe('Pane default', () => { await expect(pane).toBeAttached(); const paneBox = await pane.boundingBox(); - const transformsBefore = await getTransform(viewport); + const movementPx = 100; await pane.hover(); await page.mouse.down(); // Move pane by 100, 100 - await page.mouse.move(paneBox!.x + paneBox!.width * 0.5 + 100, paneBox!.y + paneBox!.height * 0.5 + 100); + await page.mouse.move( + paneBox!.x + paneBox!.width * 0.5 + movementPx, + paneBox!.y + paneBox!.height * 0.5 + movementPx + ); const transformsAfter = await getTransform(viewport); - expect(transformsAfter.translateX - transformsBefore.translateX).toBe(100); - expect(transformsAfter.translateY - transformsBefore.translateY).toBe(100); + expect(movementPx - Math.floor(transformsAfter.translateX - transformsBefore.translateX)).toBeLessThan(1); + expect(movementPx - Math.floor(transformsAfter.translateY - transformsBefore.translateY)).toBeLessThan(1); }); test('scrolling the default pane zooms it', async ({ page }) => { diff --git a/tooling/eslint-config/CHANGELOG.md b/tooling/eslint-config/CHANGELOG.md new file mode 100644 index 00000000..f10cdc0f --- /dev/null +++ b/tooling/eslint-config/CHANGELOG.md @@ -0,0 +1,7 @@ +# @xyflow/eslint-config + +## 0.0.1 + +### Patch Changes + +- [#5003](https://github.com/xyflow/xyflow/pull/5003) [`e8e0d684`](https://github.com/xyflow/xyflow/commit/e8e0d684957b95d53a6cc11598c8755ff02117c7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - repair lint command diff --git a/tooling/eslint-config/package.json b/tooling/eslint-config/package.json index b0ab4c4e..48b1dcbb 100644 --- a/tooling/eslint-config/package.json +++ b/tooling/eslint-config/package.json @@ -1,13 +1,15 @@ { "name": "@xyflow/eslint-config", - "version": "0.0.0", + "version": "0.0.1", "private": true, "license": "MIT", "main": "src/index.js", "devDependencies": { - "eslint": "^8.22.0", - "eslint-config-prettier": "^8.5.0", - "eslint-config-turbo": "^2.0.3", - "eslint-plugin-react": "^7.33.2" + "@typescript-eslint/eslint-plugin": "^8.23.0", + "@typescript-eslint/parser": "^8.23.0", + "eslint-config-prettier": "^10.0.1", + "eslint-config-turbo": "^2.4.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.37.4" } } diff --git a/tooling/eslint-config/src/index.js b/tooling/eslint-config/src/index.js index f2ce34a0..60f82b0e 100644 --- a/tooling/eslint-config/src/index.js +++ b/tooling/eslint-config/src/index.js @@ -29,4 +29,16 @@ module.exports = { rules: { '@typescript-eslint/no-non-null-assertion': 'off', }, + overrides: [ + { + files: ['**/*.{ts,tsx,cts,mts}'], + parserOptions: { + projectService: true, + }, + rules: { + '@typescript-eslint/no-deprecated': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + }, + }, + ], }; diff --git a/tooling/rollup-config/package.json b/tooling/rollup-config/package.json index c8871f61..d04d3d93 100644 --- a/tooling/rollup-config/package.json +++ b/tooling/rollup-config/package.json @@ -14,6 +14,6 @@ "@rollup/plugin-typescript": "11.1.6", "rollup": "^4.18.0", "rollup-plugin-peer-deps-external": "^2.2.4", - "typescript": "^5.1.3" + "typescript": "^5.4.5" } }