mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): upgrade to reactflow 12
This commit is contained in:
parent
09d1e190e7
commit
3dfa8ce11f
@ -299,7 +299,7 @@ Migration logic is in [migrations.ts].
|
|||||||
[pydantic]: https://github.com/pydantic/pydantic 'pydantic'
|
[pydantic]: https://github.com/pydantic/pydantic 'pydantic'
|
||||||
[zod]: https://github.com/colinhacks/zod 'zod'
|
[zod]: https://github.com/colinhacks/zod 'zod'
|
||||||
[openapi-types]: https://github.com/kogosoftwarellc/open-api/tree/main/packages/openapi-types 'openapi-types'
|
[openapi-types]: https://github.com/kogosoftwarellc/open-api/tree/main/packages/openapi-types 'openapi-types'
|
||||||
[reactflow]: https://github.com/xyflow/xyflow 'reactflow'
|
[reactflow]: https://github.com/xyflow/xyflow '@xyflow/react'
|
||||||
[reactflow-concepts]: https://reactflow.dev/learn/concepts/terms-and-definitions
|
[reactflow-concepts]: https://reactflow.dev/learn/concepts/terms-and-definitions
|
||||||
[reactflow-events]: https://reactflow.dev/api-reference/react-flow#event-handlers
|
[reactflow-events]: https://reactflow.dev/api-reference/react-flow#event-handlers
|
||||||
[buildWorkflow.ts]: https://github.com/invoke-ai/InvokeAI/blob/main/invokeai/frontend/web/src/features/nodes/util/workflow/buildWorkflow.ts
|
[buildWorkflow.ts]: https://github.com/invoke-ai/InvokeAI/blob/main/invokeai/frontend/web/src/features/nodes/util/workflow/buildWorkflow.ts
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
"@nanostores/react": "^0.7.2",
|
"@nanostores/react": "^0.7.2",
|
||||||
"@reduxjs/toolkit": "2.2.3",
|
"@reduxjs/toolkit": "2.2.3",
|
||||||
"@roarr/browser-log-writer": "^1.3.0",
|
"@roarr/browser-log-writer": "^1.3.0",
|
||||||
|
"@xyflow/react": "^12.0.4",
|
||||||
"chakra-react-select": "^4.7.6",
|
"chakra-react-select": "^4.7.6",
|
||||||
"compare-versions": "^6.1.0",
|
"compare-versions": "^6.1.0",
|
||||||
"dateformat": "^5.0.3",
|
"dateformat": "^5.0.3",
|
||||||
@ -94,7 +95,6 @@
|
|||||||
"react-select": "5.8.0",
|
"react-select": "5.8.0",
|
||||||
"react-use": "^17.5.0",
|
"react-use": "^17.5.0",
|
||||||
"react-virtuoso": "^4.7.10",
|
"react-virtuoso": "^4.7.10",
|
||||||
"reactflow": "^11.11.3",
|
|
||||||
"redux-dynamic-middlewares": "^2.2.0",
|
"redux-dynamic-middlewares": "^2.2.0",
|
||||||
"redux-remember": "^5.1.0",
|
"redux-remember": "^5.1.0",
|
||||||
"redux-undo": "^1.1.0",
|
"redux-undo": "^1.1.0",
|
||||||
|
@ -41,6 +41,9 @@ dependencies:
|
|||||||
'@roarr/browser-log-writer':
|
'@roarr/browser-log-writer':
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.0
|
version: 1.3.0
|
||||||
|
'@xyflow/react':
|
||||||
|
specifier: ^12.0.4
|
||||||
|
version: 12.0.4(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
||||||
chakra-react-select:
|
chakra-react-select:
|
||||||
specifier: ^4.7.6
|
specifier: ^4.7.6
|
||||||
version: 4.7.6(@chakra-ui/form-control@2.2.0)(@chakra-ui/icon@3.2.0)(@chakra-ui/layout@2.3.1)(@chakra-ui/media-query@3.3.0)(@chakra-ui/menu@2.2.1)(@chakra-ui/spinner@2.1.0)(@chakra-ui/system@2.6.2)(@emotion/react@11.11.4)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
version: 4.7.6(@chakra-ui/form-control@2.2.0)(@chakra-ui/icon@3.2.0)(@chakra-ui/layout@2.3.1)(@chakra-ui/media-query@3.3.0)(@chakra-ui/menu@2.2.1)(@chakra-ui/spinner@2.1.0)(@chakra-ui/system@2.6.2)(@emotion/react@11.11.4)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
||||||
@ -134,9 +137,6 @@ dependencies:
|
|||||||
react-virtuoso:
|
react-virtuoso:
|
||||||
specifier: ^4.7.10
|
specifier: ^4.7.10
|
||||||
version: 4.7.10(react-dom@18.3.1)(react@18.3.1)
|
version: 4.7.10(react-dom@18.3.1)(react@18.3.1)
|
||||||
reactflow:
|
|
||||||
specifier: ^11.11.3
|
|
||||||
version: 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
redux-dynamic-middlewares:
|
redux-dynamic-middlewares:
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.0
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
@ -3874,114 +3874,6 @@ packages:
|
|||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@reactflow/background@11.3.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-hkvpVEhgvfTDyCvdlitw4ioKCYLaaiRXnuEG+1QM3Np+7N1DiWF1XOv5I8AFyNoJL07yXEkbECUTsHvkBvcG5A==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
classcat: 5.0.5
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reactflow/controls@11.2.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-3xgEg6ALIVkAQCS4NiBjb7ad8Cb3D8CtA7Vvl4Hf5Ar2PIVs6FOaeft9s2iDZGtsWP35ECDYId1rIFVhQL8r+A==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
classcat: 5.0.5
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reactflow/core@11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-+adHdUa7fJSEM93fWfjQwyWXeI92a1eLKwWbIstoCakHpL8UjzwhEh6sn+mN2h/59MlVI7Ehr1iGTt3MsfcIFA==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@types/d3': 7.4.3
|
|
||||||
'@types/d3-drag': 3.0.7
|
|
||||||
'@types/d3-selection': 3.0.10
|
|
||||||
'@types/d3-zoom': 3.0.8
|
|
||||||
classcat: 5.0.5
|
|
||||||
d3-drag: 3.0.0
|
|
||||||
d3-selection: 3.0.0
|
|
||||||
d3-zoom: 3.0.0
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reactflow/minimap@11.7.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-m2MvdiGSyOu44LEcERDEl1Aj6x//UQRWo3HEAejNU4HQTlJnYrSN8tgrYF8TxC1+c/9UdyzQY5VYgrTwW4QWdg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@types/d3-selection': 3.0.10
|
|
||||||
'@types/d3-zoom': 3.0.8
|
|
||||||
classcat: 5.0.5
|
|
||||||
d3-selection: 3.0.0
|
|
||||||
d3-zoom: 3.0.0
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reactflow/node-resizer@2.2.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-X7ceQ2s3jFLgbkg03n2RYr4hm3jTVrzkW2W/8ANv/SZfuVmF8XJxlERuD8Eka5voKqLda0ywIZGAbw9GoHLfUQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
classcat: 5.0.5
|
|
||||||
d3-drag: 3.0.0
|
|
||||||
d3-selection: 3.0.0
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reactflow/node-toolbar@1.3.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-aknvNICO10uWdthFSpgD6ctY/CTBeJUMV9co8T9Ilugr08Nb89IQ4uD0dPmr031ewMQxixtYIkw+sSDDzd2aaQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
classcat: 5.0.5
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@reduxjs/toolkit@2.2.3(react-redux@9.1.2)(react@18.3.1):
|
/@reduxjs/toolkit@2.2.3(react-redux@9.1.2)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-76dll9EnJXg4EVcI5YNxZA/9hSAmZsFqzMmNRHvIlzw2WS/twfcVX3ysYrWGJMClwEmChQFC4yRq74tn6fdzRA==}
|
resolution: {integrity: sha512-76dll9EnJXg4EVcI5YNxZA/9hSAmZsFqzMmNRHvIlzw2WS/twfcVX3ysYrWGJMClwEmChQFC4yRq74tn6fdzRA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -5233,137 +5125,26 @@ packages:
|
|||||||
'@types/node': 20.12.10
|
'@types/node': 20.12.10
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/d3-array@3.2.1:
|
|
||||||
resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-axis@3.0.6:
|
|
||||||
resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-selection': 3.0.10
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-brush@3.0.6:
|
|
||||||
resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-selection': 3.0.10
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-chord@3.0.6:
|
|
||||||
resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-color@3.1.3:
|
/@types/d3-color@3.1.3:
|
||||||
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
|
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/d3-contour@3.0.6:
|
|
||||||
resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-array': 3.2.1
|
|
||||||
'@types/geojson': 7946.0.14
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-delaunay@6.0.4:
|
|
||||||
resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-dispatch@3.0.6:
|
|
||||||
resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-drag@3.0.7:
|
/@types/d3-drag@3.0.7:
|
||||||
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
|
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/d3-selection': 3.0.10
|
'@types/d3-selection': 3.0.10
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/d3-dsv@3.0.7:
|
|
||||||
resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-ease@3.0.2:
|
|
||||||
resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-fetch@3.0.7:
|
|
||||||
resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-dsv': 3.0.7
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-force@3.0.9:
|
|
||||||
resolution: {integrity: sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-format@3.0.4:
|
|
||||||
resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-geo@3.1.0:
|
|
||||||
resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==}
|
|
||||||
dependencies:
|
|
||||||
'@types/geojson': 7946.0.14
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-hierarchy@3.1.7:
|
|
||||||
resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-interpolate@3.0.4:
|
/@types/d3-interpolate@3.0.4:
|
||||||
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
|
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/d3-color': 3.1.3
|
'@types/d3-color': 3.1.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/d3-path@3.1.0:
|
|
||||||
resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-polygon@3.0.2:
|
|
||||||
resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-quadtree@3.0.6:
|
|
||||||
resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-random@3.0.3:
|
|
||||||
resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-scale-chromatic@3.0.3:
|
|
||||||
resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-scale@4.0.8:
|
|
||||||
resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-time': 3.0.3
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-selection@3.0.10:
|
/@types/d3-selection@3.0.10:
|
||||||
resolution: {integrity: sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==}
|
resolution: {integrity: sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/d3-shape@3.1.6:
|
|
||||||
resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-path': 3.1.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-time-format@4.0.3:
|
|
||||||
resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-time@3.0.3:
|
|
||||||
resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-timer@3.0.2:
|
|
||||||
resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/d3-transition@3.0.8:
|
/@types/d3-transition@3.0.8:
|
||||||
resolution: {integrity: sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==}
|
resolution: {integrity: sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5377,41 +5158,6 @@ packages:
|
|||||||
'@types/d3-selection': 3.0.10
|
'@types/d3-selection': 3.0.10
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/d3@7.4.3:
|
|
||||||
resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==}
|
|
||||||
dependencies:
|
|
||||||
'@types/d3-array': 3.2.1
|
|
||||||
'@types/d3-axis': 3.0.6
|
|
||||||
'@types/d3-brush': 3.0.6
|
|
||||||
'@types/d3-chord': 3.0.6
|
|
||||||
'@types/d3-color': 3.1.3
|
|
||||||
'@types/d3-contour': 3.0.6
|
|
||||||
'@types/d3-delaunay': 6.0.4
|
|
||||||
'@types/d3-dispatch': 3.0.6
|
|
||||||
'@types/d3-drag': 3.0.7
|
|
||||||
'@types/d3-dsv': 3.0.7
|
|
||||||
'@types/d3-ease': 3.0.2
|
|
||||||
'@types/d3-fetch': 3.0.7
|
|
||||||
'@types/d3-force': 3.0.9
|
|
||||||
'@types/d3-format': 3.0.4
|
|
||||||
'@types/d3-geo': 3.1.0
|
|
||||||
'@types/d3-hierarchy': 3.1.7
|
|
||||||
'@types/d3-interpolate': 3.0.4
|
|
||||||
'@types/d3-path': 3.1.0
|
|
||||||
'@types/d3-polygon': 3.0.2
|
|
||||||
'@types/d3-quadtree': 3.0.6
|
|
||||||
'@types/d3-random': 3.0.3
|
|
||||||
'@types/d3-scale': 4.0.8
|
|
||||||
'@types/d3-scale-chromatic': 3.0.3
|
|
||||||
'@types/d3-selection': 3.0.10
|
|
||||||
'@types/d3-shape': 3.1.6
|
|
||||||
'@types/d3-time': 3.0.3
|
|
||||||
'@types/d3-time-format': 4.0.3
|
|
||||||
'@types/d3-timer': 3.0.2
|
|
||||||
'@types/d3-transition': 3.0.8
|
|
||||||
'@types/d3-zoom': 3.0.8
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/dateformat@5.0.2:
|
/@types/dateformat@5.0.2:
|
||||||
resolution: {integrity: sha512-M95hNBMa/hnwErH+a+VOD/sYgTmo15OTYTM2Hr52/e0OdOuY+Crag+kd3/ioZrhg0WGbl9Sm3hR7UU+MH6rfOw==}
|
resolution: {integrity: sha512-M95hNBMa/hnwErH+a+VOD/sYgTmo15OTYTM2Hr52/e0OdOuY+Crag+kd3/ioZrhg0WGbl9Sm3hR7UU+MH6rfOw==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -5481,10 +5227,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==}
|
resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/geojson@7946.0.14:
|
|
||||||
resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/glob@7.2.0:
|
/@types/glob@7.2.0:
|
||||||
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
|
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6008,6 +5750,34 @@ packages:
|
|||||||
resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==}
|
resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@xyflow/react@12.0.4(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
||||||
|
resolution: {integrity: sha512-eeQzw1gIbLKOB55rp2+20uB1PASDUf1q6zy2VsgugnuPEcL/olVMX3WT42XxyG8m3rcbUiHlq2NSmPTFWEjiUQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=17'
|
||||||
|
react-dom: '>=17'
|
||||||
|
dependencies:
|
||||||
|
'@xyflow/system': 0.0.37
|
||||||
|
classcat: 5.0.5
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
zustand: 4.5.2(@types/react@18.3.1)(react@18.3.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- immer
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@xyflow/system@0.0.37:
|
||||||
|
resolution: {integrity: sha512-hSIhezhxgftPUpC+xiQVIorcRILZUOWlLjpYPTyGWRu8s4RJvM4GqvrsFmD5OnMKXLgpU7/PqqUibDVO67oWQQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-drag': 3.0.7
|
||||||
|
'@types/d3-selection': 3.0.10
|
||||||
|
'@types/d3-transition': 3.0.8
|
||||||
|
'@types/d3-zoom': 3.0.8
|
||||||
|
d3-drag: 3.0.0
|
||||||
|
d3-selection: 3.0.0
|
||||||
|
d3-zoom: 3.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.20.2):
|
/@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.20.2):
|
||||||
resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==}
|
resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==}
|
||||||
engines: {node: '>=14.15.0'}
|
engines: {node: '>=14.15.0'}
|
||||||
@ -11318,25 +11088,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
|
|
||||||
/reactflow@11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-wusd1Xpn1wgsSEv7UIa4NNraCwH9syBtubBy4xVNXg3b+CDKM+sFaF3hnMx0tr0et4km9urIDdNvwm34QiZong==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=17'
|
|
||||||
react-dom: '>=17'
|
|
||||||
dependencies:
|
|
||||||
'@reactflow/background': 11.3.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@reactflow/controls': 11.2.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@reactflow/core': 11.11.3(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@reactflow/minimap': 11.7.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@reactflow/node-resizer': 2.2.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@reactflow/node-toolbar': 1.3.13(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/react'
|
|
||||||
- immer
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/read-pkg-up@7.0.1:
|
/read-pkg-up@7.0.1:
|
||||||
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
|
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { getConnectedEdges } from '@xyflow/react';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
@ -22,7 +23,6 @@ import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
|||||||
import i18n from 'i18next';
|
import i18n from 'i18next';
|
||||||
import { forEach, upperFirst } from 'lodash-es';
|
import { forEach, upperFirst } from 'lodash-es';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { getConnectedEdges } from 'reactflow';
|
|
||||||
|
|
||||||
const LAYER_TYPE_TO_TKEY: Record<Layer['type'], string> = {
|
const LAYER_TYPE_TO_TKEY: Record<Layer['type'], string> = {
|
||||||
initial_image_layer: 'controlLayers.globalInitialImage',
|
initial_image_layer: 'controlLayers.globalInitialImage',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'reactflow/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
|
|
||||||
import { Flex } from '@invoke-ai/ui-library';
|
import { Flex } from '@invoke-ai/ui-library';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import 'reactflow/dist/style.css';
|
|
||||||
|
|
||||||
import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library';
|
import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library';
|
||||||
import { Combobox, Flex, Popover, PopoverAnchor, PopoverBody, PopoverContent } from '@invoke-ai/ui-library';
|
import { Combobox, Flex, Popover, PopoverAnchor, PopoverBody, PopoverContent } from '@invoke-ai/ui-library';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { EdgeChange, NodeChange } from '@xyflow/react';
|
||||||
import { useAppDispatch, useAppStore } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppStore } from 'app/store/storeHooks';
|
||||||
import type { SelectInstance } from 'chakra-react-select';
|
import type { SelectInstance } from 'chakra-react-select';
|
||||||
import { useBuildNode } from 'features/nodes/hooks/useBuildNode';
|
import { useBuildNode } from 'features/nodes/hooks/useBuildNode';
|
||||||
@ -21,7 +20,7 @@ import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupied
|
|||||||
import { getFirstValidConnection } from 'features/nodes/store/util/getFirstValidConnection';
|
import { getFirstValidConnection } from 'features/nodes/store/util/getFirstValidConnection';
|
||||||
import { connectionToEdge } from 'features/nodes/store/util/reactFlowUtil';
|
import { connectionToEdge } from 'features/nodes/store/util/reactFlowUtil';
|
||||||
import { validateConnectionTypes } from 'features/nodes/store/util/validateConnectionTypes';
|
import { validateConnectionTypes } from 'features/nodes/store/util/validateConnectionTypes';
|
||||||
import type { AnyNode } from 'features/nodes/types/invocation';
|
import type { AppNode } from 'features/nodes/types/invocation';
|
||||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { filter, map, memoize, some } from 'lodash-es';
|
import { filter, map, memoize, some } from 'lodash-es';
|
||||||
@ -31,7 +30,6 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
|||||||
import type { HotkeyCallback } from 'react-hotkeys-hook/dist/types';
|
import type { HotkeyCallback } from 'react-hotkeys-hook/dist/types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { FilterOptionOption } from 'react-select/dist/declarations/src/filters';
|
import type { FilterOptionOption } from 'react-select/dist/declarations/src/filters';
|
||||||
import type { EdgeChange, NodeChange } from 'reactflow';
|
|
||||||
|
|
||||||
const createRegex = memoize(
|
const createRegex = memoize(
|
||||||
(inputValue: string) =>
|
(inputValue: string) =>
|
||||||
@ -120,7 +118,7 @@ const AddNodePopover = () => {
|
|||||||
}, [filteredTemplates, pendingConnection, t]);
|
}, [filteredTemplates, pendingConnection, t]);
|
||||||
|
|
||||||
const addNode = useCallback(
|
const addNode = useCallback(
|
||||||
(nodeType: string): AnyNode | null => {
|
(nodeType: string): AppNode | null => {
|
||||||
const node = buildInvocation(nodeType);
|
const node = buildInvocation(nodeType);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
const errorMessage = t('nodes.unknownNode', {
|
const errorMessage = t('nodes.unknownNode', {
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
import { useGlobalMenuClose, useToken } from '@invoke-ai/ui-library';
|
import { useGlobalMenuClose, useToken } from '@invoke-ai/ui-library';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type {
|
||||||
|
EdgeChange,
|
||||||
|
EdgeTypes,
|
||||||
|
NodeChange,
|
||||||
|
NodeTypes,
|
||||||
|
OnEdgesChange,
|
||||||
|
OnInit,
|
||||||
|
OnMoveEnd,
|
||||||
|
OnNodesChange,
|
||||||
|
OnReconnect,
|
||||||
|
ProOptions,
|
||||||
|
ReactFlowProps,
|
||||||
|
ReactFlowState,
|
||||||
|
} from '@xyflow/react';
|
||||||
|
import { Background, ReactFlow, useStore as useReactFlowStore, useUpdateNodeInternals } from '@xyflow/react';
|
||||||
import { useAppDispatch, useAppSelector, useAppStore } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector, useAppStore } from 'app/store/storeHooks';
|
||||||
import { useConnection } from 'features/nodes/hooks/useConnection';
|
import { useConnection } from 'features/nodes/hooks/useConnection';
|
||||||
import { useCopyPaste } from 'features/nodes/hooks/useCopyPaste';
|
import { useCopyPaste } from 'features/nodes/hooks/useCopyPaste';
|
||||||
@ -24,36 +39,23 @@ import { connectionToEdge } from 'features/nodes/store/util/reactFlowUtil';
|
|||||||
import type { CSSProperties, MouseEvent } from 'react';
|
import type { CSSProperties, MouseEvent } from 'react';
|
||||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import type {
|
|
||||||
EdgeChange,
|
|
||||||
NodeChange,
|
|
||||||
OnEdgesChange,
|
|
||||||
OnEdgeUpdateFunc,
|
|
||||||
OnInit,
|
|
||||||
OnMoveEnd,
|
|
||||||
OnNodesChange,
|
|
||||||
ProOptions,
|
|
||||||
ReactFlowProps,
|
|
||||||
ReactFlowState,
|
|
||||||
} from 'reactflow';
|
|
||||||
import { Background, ReactFlow, useStore as useReactFlowStore, useUpdateNodeInternals } from 'reactflow';
|
|
||||||
|
|
||||||
import CustomConnectionLine from './connectionLines/CustomConnectionLine';
|
import CustomConnectionLine from './connectionLines/CustomConnectionLine';
|
||||||
import InvocationCollapsedEdge from './edges/InvocationCollapsedEdge';
|
import InvocationCollapsedEdge from './edges/InvocationCollapsedEdge';
|
||||||
import InvocationDefaultEdge from './edges/InvocationDefaultEdge';
|
import InvocationDefaultEdge from './edges/InvocationDefaultEdge';
|
||||||
import CurrentImageNode from './nodes/CurrentImage/CurrentImageNode';
|
import CurrentImageNode from './nodes/CurrentImage/CurrentImageNode';
|
||||||
import InvocationNodeWrapper from './nodes/Invocation/InvocationNodeWrapper';
|
import InvocationNodeWrapper from './nodes/Invocation/InvocationNodeWrapper';
|
||||||
import NotesNode from './nodes/Notes/NotesNode';
|
import { NotesNodeComponent } from './nodes/Notes/NotesNode';
|
||||||
|
|
||||||
const edgeTypes = {
|
const edgeTypes: EdgeTypes = {
|
||||||
collapsed: InvocationCollapsedEdge,
|
collapsed: InvocationCollapsedEdge,
|
||||||
default: InvocationDefaultEdge,
|
default: InvocationDefaultEdge,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes: NodeTypes = {
|
||||||
invocation: InvocationNodeWrapper,
|
invocation: InvocationNodeWrapper,
|
||||||
current_image: CurrentImageNode,
|
current_image: CurrentImageNode,
|
||||||
notes: NotesNode,
|
notes: NotesNodeComponent,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
|
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
|
||||||
@ -151,13 +153,13 @@ export const Flow = memo(() => {
|
|||||||
* where the edge is deleted if you click it accidentally).
|
* where the edge is deleted if you click it accidentally).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const onEdgeUpdateStart: NonNullable<ReactFlowProps['onEdgeUpdateStart']> = useCallback((e, edge, _handleType) => {
|
const onReconnectStart: NonNullable<ReactFlowProps['onReconnectStart']> = useCallback((e, edge, _handleType) => {
|
||||||
$edgePendingUpdate.set(edge);
|
$edgePendingUpdate.set(edge);
|
||||||
$didUpdateEdge.set(false);
|
$didUpdateEdge.set(false);
|
||||||
$lastEdgeUpdateMouseEvent.set(e);
|
$lastEdgeUpdateMouseEvent.set(e);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onEdgeUpdate: OnEdgeUpdateFunc = useCallback(
|
const onReconnect: OnReconnect = useCallback(
|
||||||
(oldEdge, newConnection) => {
|
(oldEdge, newConnection) => {
|
||||||
// This event is fired when an edge update is successful
|
// This event is fired when an edge update is successful
|
||||||
$didUpdateEdge.set(true);
|
$didUpdateEdge.set(true);
|
||||||
@ -176,7 +178,7 @@ export const Flow = memo(() => {
|
|||||||
[dispatch, updateNodeInternals]
|
[dispatch, updateNodeInternals]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onEdgeUpdateEnd: NonNullable<ReactFlowProps['onEdgeUpdateEnd']> = useCallback(
|
const onReconnectEnd: NonNullable<ReactFlowProps['onReconnectEnd']> = useCallback(
|
||||||
(e, edge, _handleType) => {
|
(e, edge, _handleType) => {
|
||||||
const didUpdateEdge = $didUpdateEdge.get();
|
const didUpdateEdge = $didUpdateEdge.get();
|
||||||
// Fall back to a reasonable default event
|
// Fall back to a reasonable default event
|
||||||
@ -316,9 +318,9 @@ export const Flow = memo(() => {
|
|||||||
onMouseMove={onMouseMove}
|
onMouseMove={onMouseMove}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onEdgeUpdate={onEdgeUpdate}
|
onReconnect={onReconnect}
|
||||||
onEdgeUpdateStart={onEdgeUpdateStart}
|
onReconnectStart={onReconnectStart}
|
||||||
onEdgeUpdateEnd={onEdgeUpdateEnd}
|
onReconnectEnd={onReconnectEnd}
|
||||||
onConnectStart={onConnectStart}
|
onConnectStart={onConnectStart}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onConnectEnd={onConnectEnd}
|
onConnectEnd={onConnectEnd}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { ConnectionLineComponentProps } from '@xyflow/react';
|
||||||
|
import { getBezierPath } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
||||||
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||||
import { $pendingConnection } from 'features/nodes/store/nodesSlice';
|
import { $pendingConnection } from 'features/nodes/store/nodesSlice';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import type { ConnectionLineComponentProps } from 'reactflow';
|
|
||||||
import { getBezierPath } from 'reactflow';
|
|
||||||
|
|
||||||
const pathStyles: CSSProperties = { opacity: 0.8 };
|
const pathStyles: CSSProperties = { opacity: 0.8 };
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { Badge, Flex } from '@invoke-ai/ui-library';
|
import { Badge, Flex } from '@invoke-ai/ui-library';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { Edge, EdgeProps } from '@xyflow/react';
|
||||||
|
import { BaseEdge, EdgeLabelRenderer, getBezierPath } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||||
import { getEdgeStyles } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
import { getEdgeStyles } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||||
import { makeEdgeSelector } from 'features/nodes/components/flow/edges/util/makeEdgeSelector';
|
import { makeEdgeSelector } from 'features/nodes/components/flow/edges/util/makeEdgeSelector';
|
||||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import type { EdgeProps } from 'reactflow';
|
|
||||||
import { BaseEdge, EdgeLabelRenderer, getBezierPath } from 'reactflow';
|
export type CollapsedEdge = Edge<{ count: number }>;
|
||||||
|
|
||||||
const InvocationCollapsedEdge = ({
|
const InvocationCollapsedEdge = ({
|
||||||
sourceX,
|
sourceX,
|
||||||
@ -23,7 +25,7 @@ const InvocationCollapsedEdge = ({
|
|||||||
sourceHandleId,
|
sourceHandleId,
|
||||||
target,
|
target,
|
||||||
targetHandleId,
|
targetHandleId,
|
||||||
}: EdgeProps<{ count: number }>) => {
|
}: EdgeProps<CollapsedEdge>) => {
|
||||||
const templates = useStore($templates);
|
const templates = useStore($templates);
|
||||||
const selector = useMemo(
|
const selector = useMemo(
|
||||||
() => makeEdgeSelector(templates, source, sourceHandleId, target, targetHandleId),
|
() => makeEdgeSelector(templates, source, sourceHandleId, target, targetHandleId),
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Flex, Text } from '@invoke-ai/ui-library';
|
import { Flex, Text } from '@invoke-ai/ui-library';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { EdgeProps } from '@xyflow/react';
|
||||||
|
import { BaseEdge, EdgeLabelRenderer, getBezierPath } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { getEdgeStyles } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
import { getEdgeStyles } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import type { EdgeProps } from 'reactflow';
|
|
||||||
import { BaseEdge, EdgeLabelRenderer, getBezierPath } from 'reactflow';
|
|
||||||
|
|
||||||
import { makeEdgeSelector } from './util/makeEdgeSelector';
|
import { makeEdgeSelector } from './util/makeEdgeSelector';
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Flex, Image, Text } from '@invoke-ai/ui-library';
|
import { Flex, Image, Text } from '@invoke-ai/ui-library';
|
||||||
|
import type { NodeProps } from '@xyflow/react';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
import IAIDndImage from 'common/components/IAIDndImage';
|
||||||
@ -13,7 +14,6 @@ import { motion } from 'framer-motion';
|
|||||||
import type { CSSProperties, PropsWithChildren } from 'react';
|
import type { CSSProperties, PropsWithChildren } from 'react';
|
||||||
import { memo, useCallback, useState } from 'react';
|
import { memo, useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { NodeProps } from 'reactflow';
|
|
||||||
|
|
||||||
const selector = createMemoizedSelector(selectSystemSlice, selectGallerySlice, (system, gallery) => {
|
const selector = createMemoizedSelector(selectSystemSlice, selectGallerySlice, (system, gallery) => {
|
||||||
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import { Handle, Position } from '@xyflow/react';
|
||||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||||
import { useNodeTemplate } from 'features/nodes/hooks/useNodeTemplate';
|
import { useNodeTemplate } from 'features/nodes/hooks/useNodeTemplate';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { Handle, Position } from 'reactflow';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
|
@ -16,10 +16,10 @@ type Props = {
|
|||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
label: string;
|
label: string;
|
||||||
type: string;
|
type: string;
|
||||||
selected: boolean;
|
selected?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
export const InvocationNodeComponent = memo(({ nodeId, isOpen, label, type, selected = false }: Props) => {
|
||||||
const fieldNames = useFieldNames(nodeId);
|
const fieldNames = useFieldNames(nodeId);
|
||||||
const withFooter = useWithFooter(nodeId);
|
const withFooter = useWithFooter(nodeId);
|
||||||
const outputFieldNames = useOutputFieldNames(nodeId);
|
const outputFieldNames = useOutputFieldNames(nodeId);
|
||||||
@ -78,6 +78,6 @@ const InvocationNode = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
|||||||
)}
|
)}
|
||||||
</NodeWrapper>
|
</NodeWrapper>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default memo(InvocationNode);
|
InvocationNodeComponent.displayName = 'InvocationNodeComponent';
|
@ -11,10 +11,10 @@ type Props = {
|
|||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
label: string;
|
label: string;
|
||||||
type: string;
|
type: string;
|
||||||
selected: boolean;
|
selected?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const InvocationNodeUnknownFallback = ({ nodeId, isOpen, label, type, selected }: Props) => {
|
const InvocationNodeUnknownFallback = ({ nodeId, isOpen, label, type, selected = false }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const nodePack = useNodePack(nodeId);
|
const nodePack = useNodePack(nodeId);
|
||||||
return (
|
return (
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { NodeProps } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import InvocationNode from 'features/nodes/components/flow/nodes/Invocation/InvocationNode';
|
import { InvocationNodeComponent } from 'features/nodes/components/flow/nodes/Invocation/InvocationNodeComponent';
|
||||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||||
import type { InvocationNodeData } from 'features/nodes/types/invocation';
|
import type { InvocationNode } from 'features/nodes/types/invocation';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import type { NodeProps } from 'reactflow';
|
|
||||||
|
|
||||||
import InvocationNodeUnknownFallback from './InvocationNodeUnknownFallback';
|
import InvocationNodeUnknownFallback from './InvocationNodeUnknownFallback';
|
||||||
|
|
||||||
const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
const InvocationNodeWrapper = (props: NodeProps<InvocationNode>) => {
|
||||||
const { data, selected } = props;
|
const { data, selected } = props;
|
||||||
const { id: nodeId, type, isOpen, label } = data;
|
const { id: nodeId, type, isOpen, label } = data;
|
||||||
const templates = useStore($templates);
|
const templates = useStore($templates);
|
||||||
@ -25,7 +25,7 @@ const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <InvocationNode nodeId={nodeId} isOpen={isOpen} label={label} type={type} selected={selected} />;
|
return <InvocationNodeComponent nodeId={nodeId} isOpen={isOpen} label={label} type={type} selected={selected} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(InvocationNodeWrapper);
|
export default memo(InvocationNodeWrapper);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { Tooltip } from '@invoke-ai/ui-library';
|
import { Tooltip } from '@invoke-ai/ui-library';
|
||||||
|
import type { HandleType } from '@xyflow/react';
|
||||||
|
import { Handle, Position } from '@xyflow/react';
|
||||||
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
||||||
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||||
import { useFieldTypeName } from 'features/nodes/hooks/usePrettyFieldType';
|
import { useFieldTypeName } from 'features/nodes/hooks/usePrettyFieldType';
|
||||||
@ -8,8 +10,6 @@ import { type FieldInputTemplate, type FieldOutputTemplate, isSingle } from 'fea
|
|||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { HandleType } from 'reactflow';
|
|
||||||
import { Handle, Position } from 'reactflow';
|
|
||||||
|
|
||||||
type FieldHandleProps = {
|
type FieldHandleProps = {
|
||||||
fieldTemplate: FieldInputTemplate | FieldOutputTemplate;
|
fieldTemplate: FieldInputTemplate | FieldOutputTemplate;
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { Box, Flex, Textarea } from '@invoke-ai/ui-library';
|
import { Box, Flex, Textarea } from '@invoke-ai/ui-library';
|
||||||
|
import type { NodeProps } from '@xyflow/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import NodeCollapseButton from 'features/nodes/components/flow/nodes/common/NodeCollapseButton';
|
import NodeCollapseButton from 'features/nodes/components/flow/nodes/common/NodeCollapseButton';
|
||||||
import NodeTitle from 'features/nodes/components/flow/nodes/common/NodeTitle';
|
import NodeTitle from 'features/nodes/components/flow/nodes/common/NodeTitle';
|
||||||
import NodeWrapper from 'features/nodes/components/flow/nodes/common/NodeWrapper';
|
import NodeWrapper from 'features/nodes/components/flow/nodes/common/NodeWrapper';
|
||||||
import { notesNodeValueChanged } from 'features/nodes/store/nodesSlice';
|
import { notesNodeValueChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import type { NotesNodeData } from 'features/nodes/types/invocation';
|
import type { NotesNode } from 'features/nodes/types/invocation';
|
||||||
import type { ChangeEvent } from 'react';
|
import type { ChangeEvent } from 'react';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import type { NodeProps } from 'reactflow';
|
|
||||||
|
|
||||||
const NotesNode = (props: NodeProps<NotesNodeData>) => {
|
export const NotesNodeComponent = memo((props: NodeProps<NotesNode>) => {
|
||||||
const { id: nodeId, data, selected } = props;
|
const { id: nodeId, data, selected } = props;
|
||||||
const { notes, isOpen } = data;
|
const { notes, isOpen } = data;
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -55,6 +55,6 @@ const NotesNode = (props: NodeProps<NotesNodeData>) => {
|
|||||||
)}
|
)}
|
||||||
</NodeWrapper>
|
</NodeWrapper>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default memo(NotesNode);
|
NotesNodeComponent.displayName = 'NotesNodeComponent';
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Icon, IconButton } from '@invoke-ai/ui-library';
|
import { Icon, IconButton } from '@invoke-ai/ui-library';
|
||||||
|
import { useUpdateNodeInternals } from '@xyflow/react';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { nodeIsOpenChanged } from 'features/nodes/store/nodesSlice';
|
import { nodeIsOpenChanged } from 'features/nodes/store/nodesSlice';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { PiCaretUpBold } from 'react-icons/pi';
|
import { PiCaretUpBold } from 'react-icons/pi';
|
||||||
import { useUpdateNodeInternals } from 'reactflow';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { ChakraProps } from '@invoke-ai/ui-library';
|
import type { ChakraProps } from '@invoke-ai/ui-library';
|
||||||
import { Box, useGlobalMenuClose, useToken } from '@invoke-ai/ui-library';
|
import { Box, useGlobalMenuClose, useToken } from '@invoke-ai/ui-library';
|
||||||
|
import type { NodeChange } from '@xyflow/react';
|
||||||
import { useAppDispatch, useAppSelector, useAppStore } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector, useAppStore } from 'app/store/storeHooks';
|
||||||
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
||||||
import { useExecutionState } from 'features/nodes/hooks/useExecutionState';
|
import { useExecutionState } from 'features/nodes/hooks/useExecutionState';
|
||||||
@ -9,16 +10,15 @@ import { DRAG_HANDLE_CLASSNAME, NODE_WIDTH } from 'features/nodes/types/constant
|
|||||||
import { zNodeStatus } from 'features/nodes/types/invocation';
|
import { zNodeStatus } from 'features/nodes/types/invocation';
|
||||||
import type { MouseEvent, PropsWithChildren } from 'react';
|
import type { MouseEvent, PropsWithChildren } from 'react';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import type { NodeChange } from 'reactflow';
|
|
||||||
|
|
||||||
type NodeWrapperProps = PropsWithChildren & {
|
type NodeWrapperProps = PropsWithChildren & {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
selected: boolean;
|
selected?: boolean;
|
||||||
width?: ChakraProps['w'];
|
width?: ChakraProps['w'];
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeWrapper = (props: NodeWrapperProps) => {
|
const NodeWrapper = (props: NodeWrapperProps) => {
|
||||||
const { nodeId, width, children, selected } = props;
|
const { nodeId, width, children, selected = false } = props;
|
||||||
const store = useAppStore();
|
const store = useAppStore();
|
||||||
const { isMouseOverNode, handleMouseOut, handleMouseOver } = useMouseOverNode(nodeId);
|
const { isMouseOverNode, handleMouseOut, handleMouseOver } = useMouseOverNode(nodeId);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ButtonGroup, IconButton } from '@invoke-ai/ui-library';
|
import { ButtonGroup, IconButton } from '@invoke-ai/ui-library';
|
||||||
|
import { useReactFlow } from '@xyflow/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { shouldShowMinimapPanelChanged } from 'features/nodes/store/workflowSettingsSlice';
|
import { shouldShowMinimapPanelChanged } from 'features/nodes/store/workflowSettingsSlice';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
@ -9,7 +10,6 @@ import {
|
|||||||
PiMagnifyingGlassPlusBold,
|
PiMagnifyingGlassPlusBold,
|
||||||
PiMapPinBold,
|
PiMapPinBold,
|
||||||
} from 'react-icons/pi';
|
} from 'react-icons/pi';
|
||||||
import { useReactFlow } from 'reactflow';
|
|
||||||
|
|
||||||
const ViewportControls = () => {
|
const ViewportControls = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
||||||
import { chakra, Flex } from '@invoke-ai/ui-library';
|
import { chakra, Flex } from '@invoke-ai/ui-library';
|
||||||
|
import { MiniMap } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { MiniMap } from 'reactflow';
|
|
||||||
|
|
||||||
const ChakraMiniMap = chakra(MiniMap);
|
const ChakraMiniMap = chakra(MiniMap);
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
|
import { SelectionMode } from '@xyflow/react';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import ReloadNodeTemplatesButton from 'features/nodes/components/flow/panels/TopRightPanel/ReloadSchemaButton';
|
import ReloadNodeTemplatesButton from 'features/nodes/components/flow/panels/TopRightPanel/ReloadSchemaButton';
|
||||||
@ -31,7 +32,6 @@ import {
|
|||||||
import type { ChangeEvent, ReactNode } from 'react';
|
import type { ChangeEvent, ReactNode } from 'react';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SelectionMode } from 'reactflow';
|
|
||||||
|
|
||||||
const formLabelProps: FormLabelProps = { flexGrow: 1 };
|
const formLabelProps: FormLabelProps = { flexGrow: 1 };
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'reactflow/dist/style.css';
|
|
||||||
|
|
||||||
import { Flex } from '@invoke-ai/ui-library';
|
import { Flex } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import QueueControls from 'features/queue/components/QueueControls';
|
import QueueControls from 'features/queue/components/QueueControls';
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { useReactFlow } from '@xyflow/react';
|
||||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||||
import { NODE_WIDTH } from 'features/nodes/types/constants';
|
import { NODE_WIDTH } from 'features/nodes/types/constants';
|
||||||
import type { AnyNode, InvocationTemplate } from 'features/nodes/types/invocation';
|
import type { AppNode, InvocationTemplate } from 'features/nodes/types/invocation';
|
||||||
import { buildCurrentImageNode } from 'features/nodes/util/node/buildCurrentImageNode';
|
import { buildCurrentImageNode } from 'features/nodes/util/node/buildCurrentImageNode';
|
||||||
import { buildInvocationNode } from 'features/nodes/util/node/buildInvocationNode';
|
import { buildInvocationNode } from 'features/nodes/util/node/buildInvocationNode';
|
||||||
import { buildNotesNode } from 'features/nodes/util/node/buildNotesNode';
|
import { buildNotesNode } from 'features/nodes/util/node/buildNotesNode';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useReactFlow } from 'reactflow';
|
|
||||||
|
|
||||||
export const useBuildNode = () => {
|
export const useBuildNode = () => {
|
||||||
const templates = useStore($templates);
|
const templates = useStore($templates);
|
||||||
@ -14,7 +14,7 @@ export const useBuildNode = () => {
|
|||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
// string here is "any invocation type"
|
// string here is "any invocation type"
|
||||||
(type: string | 'current_image' | 'notes'): AnyNode => {
|
(type: string | 'current_image' | 'notes'): AppNode => {
|
||||||
let _x = window.innerWidth / 2;
|
let _x = window.innerWidth / 2;
|
||||||
let _y = window.innerHeight / 2;
|
let _y = window.innerHeight / 2;
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { EdgeChange, OnConnect, OnConnectEnd, OnConnectStart } from '@xyflow/react';
|
||||||
|
import { useUpdateNodeInternals } from '@xyflow/react';
|
||||||
import { useAppStore } from 'app/store/storeHooks';
|
import { useAppStore } from 'app/store/storeHooks';
|
||||||
import { $mouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
import { $mouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
||||||
import {
|
import {
|
||||||
@ -12,8 +14,6 @@ import {
|
|||||||
import { getFirstValidConnection } from 'features/nodes/store/util/getFirstValidConnection';
|
import { getFirstValidConnection } from 'features/nodes/store/util/getFirstValidConnection';
|
||||||
import { connectionToEdge } from 'features/nodes/store/util/reactFlowUtil';
|
import { connectionToEdge } from 'features/nodes/store/util/reactFlowUtil';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { EdgeChange, OnConnect, OnConnectEnd, OnConnectStart } from 'reactflow';
|
|
||||||
import { useUpdateNodeInternals } from 'reactflow';
|
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
export const useConnection = () => {
|
export const useConnection = () => {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { EdgeChange, NodeChange } from '@xyflow/react';
|
||||||
import { getStore } from 'app/store/nanostores/store';
|
import { getStore } from 'app/store/nanostores/store';
|
||||||
import { deepClone } from 'common/util/deepClone';
|
import { deepClone } from 'common/util/deepClone';
|
||||||
import {
|
import {
|
||||||
@ -11,7 +12,6 @@ import {
|
|||||||
} from 'features/nodes/store/nodesSlice';
|
} from 'features/nodes/store/nodesSlice';
|
||||||
import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupiedPosition';
|
import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupiedPosition';
|
||||||
import { isEqual, uniqWith } from 'lodash-es';
|
import { isEqual, uniqWith } from 'lodash-es';
|
||||||
import type { EdgeChange, NodeChange } from 'reactflow';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
const copySelection = () => {
|
const copySelection = () => {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// TODO: enable this at some point
|
// TODO: enable this at some point
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import type { IsValidConnection } from '@xyflow/react';
|
||||||
import { useAppSelector, useAppStore } from 'app/store/storeHooks';
|
import { useAppSelector, useAppStore } from 'app/store/storeHooks';
|
||||||
import { $edgePendingUpdate, $templates } from 'features/nodes/store/nodesSlice';
|
import { $edgePendingUpdate, $templates } from 'features/nodes/store/nodesSlice';
|
||||||
import { validateConnection } from 'features/nodes/store/util/validateConnection';
|
import { validateConnection } from 'features/nodes/store/util/validateConnection';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { Connection } from 'reactflow';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: The logic here must be duplicated in `invokeai/frontend/web/src/features/nodes/store/util/makeIsConnectionValidSelector.ts`
|
* NOTE: The logic here must be duplicated in `invokeai/frontend/web/src/features/nodes/store/util/makeIsConnectionValidSelector.ts`
|
||||||
@ -15,8 +15,8 @@ export const useIsValidConnection = () => {
|
|||||||
const store = useAppStore();
|
const store = useAppStore();
|
||||||
const templates = useStore($templates);
|
const templates = useStore($templates);
|
||||||
const shouldValidateGraph = useAppSelector((s) => s.workflowSettings.shouldValidateGraph);
|
const shouldValidateGraph = useAppSelector((s) => s.workflowSettings.shouldValidateGraph);
|
||||||
const isValidConnection = useCallback(
|
const isValidConnection = useCallback<IsValidConnection>(
|
||||||
({ source, sourceHandle, target, targetHandle }: Connection): boolean => {
|
({ source, sourceHandle, target, targetHandle }) => {
|
||||||
// Connection must have valid targets
|
// Connection must have valid targets
|
||||||
if (!(source && sourceHandle && target && targetHandle)) {
|
if (!(source && sourceHandle && target && targetHandle)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import type { PayloadAction, UnknownAction } from '@reduxjs/toolkit';
|
import type { PayloadAction, UnknownAction } from '@reduxjs/toolkit';
|
||||||
import { createSlice, isAnyOf } from '@reduxjs/toolkit';
|
import { createSlice, isAnyOf } from '@reduxjs/toolkit';
|
||||||
|
import type { Edge, EdgeChange, NodeChange, Viewport, XYPosition } from '@xyflow/react';
|
||||||
|
import { applyEdgeChanges, applyNodeChanges, getConnectedEdges, getIncomers, getOutgoers } from '@xyflow/react';
|
||||||
import type { PersistConfig, RootState } from 'app/store/store';
|
import type { PersistConfig, RootState } from 'app/store/store';
|
||||||
|
import type { CollapsedEdge } from 'features/nodes/components/flow/edges/InvocationCollapsedEdge';
|
||||||
import { workflowLoaded } from 'features/nodes/store/actions';
|
import { workflowLoaded } from 'features/nodes/store/actions';
|
||||||
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
||||||
import type {
|
import type {
|
||||||
@ -46,12 +49,10 @@ import {
|
|||||||
zT2IAdapterModelFieldValue,
|
zT2IAdapterModelFieldValue,
|
||||||
zVAEModelFieldValue,
|
zVAEModelFieldValue,
|
||||||
} from 'features/nodes/types/field';
|
} from 'features/nodes/types/field';
|
||||||
import type { AnyNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
import type { AppNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
||||||
import { isInvocationNode, isNotesNode } from 'features/nodes/types/invocation';
|
import { isInvocationNode, isNotesNode } from 'features/nodes/types/invocation';
|
||||||
import { atom } from 'nanostores';
|
import { atom } from 'nanostores';
|
||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
import type { Edge, EdgeChange, NodeChange, Viewport, XYPosition } from 'reactflow';
|
|
||||||
import { applyEdgeChanges, applyNodeChanges, getConnectedEdges, getIncomers, getOutgoers } from 'reactflow';
|
|
||||||
import type { UndoableOptions } from 'redux-undo';
|
import type { UndoableOptions } from 'redux-undo';
|
||||||
import type { z } from 'zod';
|
import type { z } from 'zod';
|
||||||
|
|
||||||
@ -92,10 +93,10 @@ export const nodesSlice = createSlice({
|
|||||||
name: 'nodes',
|
name: 'nodes',
|
||||||
initialState: initialNodesState,
|
initialState: initialNodesState,
|
||||||
reducers: {
|
reducers: {
|
||||||
nodesChanged: (state, action: PayloadAction<NodeChange[]>) => {
|
nodesChanged: (state, action: PayloadAction<NodeChange<AppNode>[]>) => {
|
||||||
state.nodes = applyNodeChanges(action.payload, state.nodes);
|
state.nodes = applyNodeChanges<AppNode>(action.payload, state.nodes);
|
||||||
// Remove edges that are no longer valid, due to a removed or otherwise changed node
|
// Remove edges that are no longer valid, due to a removed or otherwise changed node
|
||||||
const edgeChanges: EdgeChange[] = [];
|
const edgeChanges: EdgeChange<InvocationNodeEdge | CollapsedEdge>[] = [];
|
||||||
state.edges.forEach((e) => {
|
state.edges.forEach((e) => {
|
||||||
const sourceExists = state.nodes.some((n) => n.id === e.source);
|
const sourceExists = state.nodes.some((n) => n.id === e.source);
|
||||||
const targetExists = state.nodes.some((n) => n.id === e.target);
|
const targetExists = state.nodes.some((n) => n.id === e.target);
|
||||||
@ -103,10 +104,10 @@ export const nodesSlice = createSlice({
|
|||||||
edgeChanges.push({ type: 'remove', id: e.id });
|
edgeChanges.push({ type: 'remove', id: e.id });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
state.edges = applyEdgeChanges(edgeChanges, state.edges);
|
state.edges = applyEdgeChanges<InvocationNodeEdge | CollapsedEdge>(edgeChanges, state.edges);
|
||||||
},
|
},
|
||||||
edgesChanged: (state, action: PayloadAction<EdgeChange[]>) => {
|
edgesChanged: (state, action: PayloadAction<EdgeChange<InvocationNodeEdge | CollapsedEdge>[]>) => {
|
||||||
const changes: EdgeChange[] = [];
|
const changes: EdgeChange<InvocationNodeEdge | CollapsedEdge>[] = [];
|
||||||
// We may need to massage the edge changes or otherwise handle them
|
// We may need to massage the edge changes or otherwise handle them
|
||||||
action.payload.forEach((change) => {
|
action.payload.forEach((change) => {
|
||||||
if (change.type === 'remove' || change.type === 'select') {
|
if (change.type === 'remove' || change.type === 'select') {
|
||||||
@ -134,7 +135,7 @@ export const nodesSlice = createSlice({
|
|||||||
}
|
}
|
||||||
changes.push(change);
|
changes.push(change);
|
||||||
});
|
});
|
||||||
state.edges = applyEdgeChanges(changes, state.edges);
|
state.edges = applyEdgeChanges<InvocationNodeEdge | CollapsedEdge>(changes, state.edges);
|
||||||
},
|
},
|
||||||
fieldLabelChanged: (
|
fieldLabelChanged: (
|
||||||
state,
|
state,
|
||||||
@ -218,7 +219,7 @@ export const nodesSlice = createSlice({
|
|||||||
(node) => isInvocationNode(node) && node.data.isOpen === false
|
(node) => isInvocationNode(node) && node.data.isOpen === false
|
||||||
);
|
);
|
||||||
|
|
||||||
const collapsedEdgesToCreate: Edge<{ count: number }>[] = [];
|
const collapsedEdgesToCreate: CollapsedEdge[] = [];
|
||||||
|
|
||||||
// hide all edges
|
// hide all edges
|
||||||
connectedEdges.forEach((edge) => {
|
connectedEdges.forEach((edge) => {
|
||||||
@ -238,7 +239,7 @@ export const nodesSlice = createSlice({
|
|||||||
target: edge.target,
|
target: edge.target,
|
||||||
type: 'collapsed',
|
type: 'collapsed',
|
||||||
data: { count: 1 },
|
data: { count: 1 },
|
||||||
updatable: false,
|
reconnectable: false,
|
||||||
selected: edge.selected,
|
selected: edge.selected,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -259,14 +260,14 @@ export const nodesSlice = createSlice({
|
|||||||
target: edge.target,
|
target: edge.target,
|
||||||
type: 'collapsed',
|
type: 'collapsed',
|
||||||
data: { count: 1 },
|
data: { count: 1 },
|
||||||
updatable: false,
|
reconnectable: false,
|
||||||
selected: edge.selected,
|
selected: edge.selected,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (collapsedEdgesToCreate.length) {
|
if (collapsedEdgesToCreate.length) {
|
||||||
state.edges = applyEdgeChanges(
|
state.edges = applyEdgeChanges<CollapsedEdge | InvocationNodeEdge>(
|
||||||
collapsedEdgesToCreate.map((edge) => ({ type: 'add', item: edge })),
|
collapsedEdgesToCreate.map((edge) => ({ type: 'add', item: edge })),
|
||||||
state.edges
|
state.edges
|
||||||
);
|
);
|
||||||
@ -366,7 +367,7 @@ export const nodesSlice = createSlice({
|
|||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder.addCase(workflowLoaded, (state, action) => {
|
builder.addCase(workflowLoaded, (state, action) => {
|
||||||
const { nodes, edges } = action.payload;
|
const { nodes, edges } = action.payload;
|
||||||
state.nodes = applyNodeChanges(
|
state.nodes = applyNodeChanges<AppNode>(
|
||||||
nodes.map((node) => ({
|
nodes.map((node) => ({
|
||||||
type: 'add',
|
type: 'add',
|
||||||
item: { ...node, ...SHARED_NODE_PROPERTIES },
|
item: { ...node, ...SHARED_NODE_PROPERTIES },
|
||||||
@ -416,7 +417,7 @@ export const {
|
|||||||
|
|
||||||
export const $cursorPos = atom<XYPosition | null>(null);
|
export const $cursorPos = atom<XYPosition | null>(null);
|
||||||
export const $templates = atom<Templates>({});
|
export const $templates = atom<Templates>({});
|
||||||
export const $copiedNodes = atom<AnyNode[]>([]);
|
export const $copiedNodes = atom<AppNode[]>([]);
|
||||||
export const $copiedEdges = atom<InvocationNodeEdge[]>([]);
|
export const $copiedEdges = atom<InvocationNodeEdge[]>([]);
|
||||||
export const $edgesToCopiedNodes = atom<InvocationNodeEdge[]>([]);
|
export const $edgesToCopiedNodes = atom<InvocationNodeEdge[]>([]);
|
||||||
export const $pendingConnection = atom<PendingConnection | null>(null);
|
export const $pendingConnection = atom<PendingConnection | null>(null);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import type { ReactFlowInstance } from '@xyflow/react';
|
||||||
import { atom } from 'nanostores';
|
import { atom } from 'nanostores';
|
||||||
import type { ReactFlowInstance } from 'reactflow';
|
|
||||||
|
|
||||||
export const $flow = atom<ReactFlowInstance | null>(null);
|
export const $flow = atom<ReactFlowInstance | null>(null);
|
||||||
export const $needsFit = atom<boolean>(true);
|
export const $needsFit = atom<boolean>(true);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { HandleType } from '@xyflow/react';
|
||||||
|
import type { CollapsedEdge } from 'features/nodes/components/flow/edges/InvocationCollapsedEdge';
|
||||||
import type {
|
import type {
|
||||||
FieldIdentifier,
|
FieldIdentifier,
|
||||||
FieldInputTemplate,
|
FieldInputTemplate,
|
||||||
@ -5,13 +7,12 @@ import type {
|
|||||||
StatefulFieldValue,
|
StatefulFieldValue,
|
||||||
} from 'features/nodes/types/field';
|
} from 'features/nodes/types/field';
|
||||||
import type {
|
import type {
|
||||||
AnyNode,
|
AppNode,
|
||||||
InvocationNodeEdge,
|
InvocationNodeEdge,
|
||||||
InvocationTemplate,
|
InvocationTemplate,
|
||||||
NodeExecutionState,
|
NodeExecutionState,
|
||||||
} from 'features/nodes/types/invocation';
|
} from 'features/nodes/types/invocation';
|
||||||
import type { WorkflowV3 } from 'features/nodes/types/workflow';
|
import type { WorkflowV3 } from 'features/nodes/types/workflow';
|
||||||
import type { HandleType } from 'reactflow';
|
|
||||||
|
|
||||||
export type Templates = Record<string, InvocationTemplate>;
|
export type Templates = Record<string, InvocationTemplate>;
|
||||||
export type NodeExecutionStates = Record<string, NodeExecutionState | undefined>;
|
export type NodeExecutionStates = Record<string, NodeExecutionState | undefined>;
|
||||||
@ -25,8 +26,8 @@ export type PendingConnection = {
|
|||||||
|
|
||||||
export type NodesState = {
|
export type NodesState = {
|
||||||
_version: 1;
|
_version: 1;
|
||||||
nodes: AnyNode[];
|
nodes: AppNode[];
|
||||||
edges: InvocationNodeEdge[];
|
edges: (InvocationNodeEdge | CollapsedEdge)[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkflowMode = 'edit' | 'view';
|
export type WorkflowMode = 'edit' | 'view';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Node } from 'reactflow';
|
import type { Node } from '@xyflow/react';
|
||||||
|
|
||||||
export const findUnoccupiedPosition = (nodes: Node[], x: number, y: number) => {
|
export const findUnoccupiedPosition = (nodes: Node[], x: number, y: number) => {
|
||||||
let newX = x;
|
let newX = x;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { Templates } from 'features/nodes/store/types';
|
import type { Templates } from 'features/nodes/store/types';
|
||||||
import type { FieldType } from 'features/nodes/types/field';
|
import type { FieldType } from 'features/nodes/types/field';
|
||||||
import type { AnyNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
import type { AppNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a collect node, return the type of the items it collects. The graph is traversed to find the first node and
|
* Given a collect node, return the type of the items it collects. The graph is traversed to find the first node and
|
||||||
@ -14,7 +14,7 @@ import type { AnyNode, InvocationNodeEdge } from 'features/nodes/types/invocatio
|
|||||||
*/
|
*/
|
||||||
export const getCollectItemType = (
|
export const getCollectItemType = (
|
||||||
templates: Templates,
|
templates: Templates,
|
||||||
nodes: AnyNode[],
|
nodes: AppNode[],
|
||||||
edges: InvocationNodeEdge[],
|
edges: InvocationNodeEdge[],
|
||||||
nodeId: string
|
nodeId: string
|
||||||
): FieldType | null => {
|
): FieldType | null => {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import type { Connection, Edge } from '@xyflow/react';
|
||||||
import type { Templates } from 'features/nodes/store/types';
|
import type { Templates } from 'features/nodes/store/types';
|
||||||
import { validateConnection } from 'features/nodes/store/util/validateConnection';
|
import { validateConnection } from 'features/nodes/store/util/validateConnection';
|
||||||
import type { FieldInputTemplate, FieldOutputTemplate } from 'features/nodes/types/field';
|
import type { FieldInputTemplate, FieldOutputTemplate } from 'features/nodes/types/field';
|
||||||
import type { AnyNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
import type { AppNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
||||||
import { map } from 'lodash-es';
|
import { map } from 'lodash-es';
|
||||||
import type { Connection, Edge } from 'reactflow';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -22,7 +22,7 @@ export const getFirstValidConnection = (
|
|||||||
sourceHandle: string | null,
|
sourceHandle: string | null,
|
||||||
target: string,
|
target: string,
|
||||||
targetHandle: string | null,
|
targetHandle: string | null,
|
||||||
nodes: AnyNode[],
|
nodes: AppNode[],
|
||||||
edges: InvocationNodeEdge[],
|
edges: InvocationNodeEdge[],
|
||||||
templates: Templates,
|
templates: Templates,
|
||||||
edgePendingUpdate: Edge | null
|
edgePendingUpdate: Edge | null
|
||||||
@ -80,7 +80,7 @@ export const getTargetCandidateFields = (
|
|||||||
source: string,
|
source: string,
|
||||||
sourceHandle: string,
|
sourceHandle: string,
|
||||||
target: string,
|
target: string,
|
||||||
nodes: AnyNode[],
|
nodes: AppNode[],
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
templates: Templates,
|
templates: Templates,
|
||||||
edgePendingUpdate: Edge | null
|
edgePendingUpdate: Edge | null
|
||||||
@ -116,7 +116,7 @@ export const getSourceCandidateFields = (
|
|||||||
target: string,
|
target: string,
|
||||||
targetHandle: string,
|
targetHandle: string,
|
||||||
source: string,
|
source: string,
|
||||||
nodes: AnyNode[],
|
nodes: AppNode[],
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
templates: Templates,
|
templates: Templates,
|
||||||
edgePendingUpdate: Edge | null
|
edgePendingUpdate: Edge | null
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import graphlib from '@dagrejs/graphlib';
|
import graphlib from '@dagrejs/graphlib';
|
||||||
import type { Edge, Node } from 'reactflow';
|
import type { Edge, Node } from '@xyflow/react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if adding an edge between the source and target nodes would create a cycle in the graph.
|
* Check if adding an edge between the source and target nodes would create a cycle in the graph.
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import type { Edge, HandleType } from '@xyflow/react';
|
||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||||
import type { RootState } from 'app/store/store';
|
import type { RootState } from 'app/store/store';
|
||||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||||
import type { NodesState, PendingConnection, Templates } from 'features/nodes/store/types';
|
import type { NodesState, PendingConnection, Templates } from 'features/nodes/store/types';
|
||||||
import { buildRejectResult, validateConnection } from 'features/nodes/store/util/validateConnection';
|
import { buildRejectResult, validateConnection } from 'features/nodes/store/util/validateConnection';
|
||||||
import type { Edge, HandleType } from 'reactflow';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a selector that validates a pending connection.
|
* Creates a selector that validates a pending connection.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Connection, Edge } from 'reactflow';
|
import type { Connection, Edge } from '@xyflow/react';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import type { Templates } from 'features/nodes/store/types';
|
import type { Templates } from 'features/nodes/store/types';
|
||||||
import type { InvocationTemplate } from 'features/nodes/types/invocation';
|
import type { InvocationNodeEdge, InvocationTemplate } from 'features/nodes/types/invocation';
|
||||||
import { buildInvocationNode } from 'features/nodes/util/node/buildInvocationNode';
|
import { buildInvocationNode } from 'features/nodes/util/node/buildInvocationNode';
|
||||||
import type { OpenAPIV3_1 } from 'openapi-types';
|
import type { OpenAPIV3_1 } from 'openapi-types';
|
||||||
import type { Edge } from 'reactflow';
|
|
||||||
|
|
||||||
export const buildEdge = (source: string, sourceHandle: string, target: string, targetHandle: string): Edge => ({
|
export const buildEdge = (source: string, sourceHandle: string, target: string, targetHandle: string): InvocationNodeEdge => ({
|
||||||
source,
|
source,
|
||||||
sourceHandle,
|
sourceHandle,
|
||||||
target,
|
target,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import type { Connection as NullableConnection, Edge } from '@xyflow/react';
|
||||||
import type { Templates } from 'features/nodes/store/types';
|
import type { Templates } from 'features/nodes/store/types';
|
||||||
import { areTypesEqual } from 'features/nodes/store/util/areTypesEqual';
|
import { areTypesEqual } from 'features/nodes/store/util/areTypesEqual';
|
||||||
import { getCollectItemType } from 'features/nodes/store/util/getCollectItemType';
|
import { getCollectItemType } from 'features/nodes/store/util/getCollectItemType';
|
||||||
import { getHasCycles } from 'features/nodes/store/util/getHasCycles';
|
import { getHasCycles } from 'features/nodes/store/util/getHasCycles';
|
||||||
import { validateConnectionTypes } from 'features/nodes/store/util/validateConnectionTypes';
|
import { validateConnectionTypes } from 'features/nodes/store/util/validateConnectionTypes';
|
||||||
import type { AnyNode } from 'features/nodes/types/invocation';
|
import type { AppNode, InvocationNodeEdge } from 'features/nodes/types/invocation';
|
||||||
import type { Connection as NullableConnection, Edge } from 'reactflow';
|
|
||||||
import type { O } from 'ts-toolbelt';
|
import type { O } from 'ts-toolbelt';
|
||||||
|
|
||||||
type Connection = O.NonNullable<NullableConnection>;
|
type Connection = O.NonNullable<NullableConnection>;
|
||||||
@ -21,8 +21,8 @@ export type ValidationResult =
|
|||||||
|
|
||||||
type ValidateConnectionFunc = (
|
type ValidateConnectionFunc = (
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
nodes: AnyNode[],
|
nodes: AppNode[],
|
||||||
edges: Edge[],
|
edges: InvocationNodeEdge[],
|
||||||
templates: Templates,
|
templates: Templates,
|
||||||
ignoreEdge: Edge | null,
|
ignoreEdge: Edge | null,
|
||||||
strict?: boolean
|
strict?: boolean
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
import { SelectionMode } from '@xyflow/react';
|
||||||
import type { PersistConfig, RootState } from 'app/store/store';
|
import type { PersistConfig, RootState } from 'app/store/store';
|
||||||
import { SelectionMode } from 'reactflow';
|
|
||||||
|
|
||||||
type WorkflowSettingsState = {
|
type WorkflowSettingsState = {
|
||||||
_version: 1;
|
_version: 1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Node } from 'reactflow';
|
import type { Node } from '@xyflow/react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How long to wait before showing a tooltip when hovering a field handle.
|
* How long to wait before showing a tooltip when hovering a field handle.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Edge, Node } from 'reactflow';
|
import type { Edge, Node } from '@xyflow/react';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { zClassification, zProgressImage } from './common';
|
import { zClassification, zProgressImage } from './common';
|
||||||
@ -59,11 +59,11 @@ type AnyNodeData = z.infer<typeof zAnyNodeData>;
|
|||||||
export type InvocationNode = Node<InvocationNodeData, 'invocation'>;
|
export type InvocationNode = Node<InvocationNodeData, 'invocation'>;
|
||||||
export type NotesNode = Node<NotesNodeData, 'notes'>;
|
export type NotesNode = Node<NotesNodeData, 'notes'>;
|
||||||
export type CurrentImageNode = Node<CurrentImageNodeData, 'current_image'>;
|
export type CurrentImageNode = Node<CurrentImageNodeData, 'current_image'>;
|
||||||
export type AnyNode = Node<AnyNodeData>;
|
export type AppNode = Node<AnyNodeData>;
|
||||||
|
|
||||||
export const isInvocationNode = (node?: AnyNode | null): node is InvocationNode =>
|
export const isInvocationNode = (node?: AppNode | null): node is InvocationNode =>
|
||||||
Boolean(node && node.type === 'invocation');
|
Boolean(node && node.type === 'invocation');
|
||||||
export const isNotesNode = (node?: AnyNode | null): node is NotesNode => Boolean(node && node.type === 'notes');
|
export const isNotesNode = (node?: AppNode | null): node is NotesNode => Boolean(node && node.type === 'notes');
|
||||||
export const isInvocationNodeData = (node?: AnyNodeData | null): node is InvocationNodeData =>
|
export const isInvocationNodeData = (node?: AnyNodeData | null): node is InvocationNodeData =>
|
||||||
Boolean(node && !['notes', 'current_image'].includes(node.type)); // node.type may be 'notes', 'current_image', or any invocation type
|
Boolean(node && !['notes', 'current_image'].includes(node.type)); // node.type may be 'notes', 'current_image', or any invocation type
|
||||||
// #endregion
|
// #endregion
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import type * as ReactFlow from '@xyflow/react';
|
||||||
import type { WorkflowCategory, WorkflowV3, XYPosition } from 'features/nodes/types/workflow';
|
import type { WorkflowCategory, WorkflowV3, XYPosition } from 'features/nodes/types/workflow';
|
||||||
import type * as ReactFlow from 'reactflow';
|
|
||||||
import type { S } from 'services/api/types';
|
import type { S } from 'services/api/types';
|
||||||
import type { Equals, Extends } from 'tsafe';
|
import type { Equals, Extends } from 'tsafe';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import type { XYPosition } from '@xyflow/react';
|
||||||
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
||||||
import type { CurrentImageNode } from 'features/nodes/types/invocation';
|
import type { CurrentImageNode } from 'features/nodes/types/invocation';
|
||||||
import type { XYPosition } from 'reactflow';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export const buildCurrentImageNode = (position: XYPosition): CurrentImageNode => {
|
export const buildCurrentImageNode = (position: XYPosition): CurrentImageNode => {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import type { XYPosition } from '@xyflow/react';
|
||||||
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
||||||
import type { FieldInputInstance } from 'features/nodes/types/field';
|
import type { FieldInputInstance } from 'features/nodes/types/field';
|
||||||
import type { InvocationNode, InvocationTemplate } from 'features/nodes/types/invocation';
|
import type { InvocationNode, InvocationTemplate } from 'features/nodes/types/invocation';
|
||||||
import { buildFieldInputInstance } from 'features/nodes/util/schema/buildFieldInputInstance';
|
import { buildFieldInputInstance } from 'features/nodes/util/schema/buildFieldInputInstance';
|
||||||
import { reduce } from 'lodash-es';
|
import { reduce } from 'lodash-es';
|
||||||
import type { XYPosition } from 'reactflow';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export const buildInvocationNode = (position: XYPosition, template: InvocationTemplate): InvocationNode => {
|
export const buildInvocationNode = (position: XYPosition, template: InvocationTemplate): InvocationNode => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import type { XYPosition } from '@xyflow/react';
|
||||||
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
||||||
import type { NotesNode } from 'features/nodes/types/invocation';
|
import type { NotesNode } from 'features/nodes/types/invocation';
|
||||||
import type { XYPosition } from 'reactflow';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export const buildNotesNode = (position: XYPosition): NotesNode => {
|
export const buildNotesNode = (position: XYPosition): NotesNode => {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Box } from '@invoke-ai/ui-library';
|
import { Box } from '@invoke-ai/ui-library';
|
||||||
|
import { ReactFlowProvider } from '@xyflow/react';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { ImageComparisonDroppable } from 'features/gallery/components/ImageViewer/ImageComparisonDroppable';
|
import { ImageComparisonDroppable } from 'features/gallery/components/ImageViewer/ImageComparisonDroppable';
|
||||||
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
|
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
|
||||||
import NodeEditor from 'features/nodes/components/NodeEditor';
|
import NodeEditor from 'features/nodes/components/NodeEditor';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { ReactFlowProvider } from 'reactflow';
|
|
||||||
|
|
||||||
const NodesTab = () => {
|
const NodesTab = () => {
|
||||||
const mode = useAppSelector((s) => s.workflow.mode);
|
const mode = useAppSelector((s) => s.workflow.mode);
|
||||||
|
Loading…
Reference in New Issue
Block a user