diff --git a/.i18nrc.cjs b/.i18nrc.cjs index 14c958591..f0ed79099 100644 --- a/.i18nrc.cjs +++ b/.i18nrc.cjs @@ -6,6 +6,7 @@ const { defineConfig } = require('@lobehub/i18n-cli'); module.exports = defineConfig({ modelName: 'gpt-4.1', splitToken: 1024, + saveImmediately: true, entry: 'src/locales/en', entryLocale: 'en', output: 'src/locales', diff --git a/.storybook/main.ts b/.storybook/main.ts index 897094ade..af23c6db3 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -7,7 +7,7 @@ import type { InlineConfig } from 'vite' const config: StorybookConfig = { stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: ['@storybook/addon-docs'], + addons: ['@storybook/addon-docs', '@storybook/addon-mcp'], framework: { name: '@storybook/vue3-vite', options: {} diff --git a/AGENTS.md b/AGENTS.md index 0d80ec8a0..b68246d4f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -63,6 +63,9 @@ The project uses **Nx** for build orchestration and task management - Imports: - sorted/grouped by plugin - run `pnpm format` before committing + - use separate `import type` statements, not inline `type` in mixed imports + - ✅ `import type { Foo } from './foo'` + `import { bar } from './foo'` + - ❌ `import { bar, type Foo } from './foo'` - ESLint: - Vue + TS rules - no floating promises @@ -119,7 +122,10 @@ The project uses **Nx** for build orchestration and task management - Prefer reactive props destructuring to `const props = defineProps<...>` - Do not use `withDefaults` or runtime props declaration - Do not import Vue macros unnecessarily - - Prefer `useModel` to separately defining a prop and emit + - Prefer `defineModel` to separately defining a prop and emit for v-model bindings + - Define slots via template usage, not `defineSlots` + - Use same-name shorthand for slot prop bindings: `:isExpanded` instead of `:is-expanded="isExpanded"` + - Derive component types using `vue-component-type-helpers` (`ComponentProps`, `ComponentSlots`) instead of separate type files - Be judicious with addition of new refs or other state - If it's possible to accomplish the design goals with just a prop, don't add a `ref` - If it's possible to use the `ref` or prop directly, don't add a `computed` @@ -137,7 +143,7 @@ The project uses **Nx** for build orchestration and task management 8. Implement proper error handling 9. Follow Vue 3 style guide and naming conventions 10. Use Vite for fast development and building -11. Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json +11. Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json. Use the plurals system in i18n instead of hardcoding pluralization in templates. 12. Avoid new usage of PrimeVue components 13. Write tests for all changes, especially bug fixes to catch future regressions 14. Write code that is expressive and self-documenting to the furthest degree possible. This reduces the need for code comments which can get out of sync with the code itself. Try to avoid comments unless absolutely necessary @@ -268,6 +274,8 @@ When referencing Comfy-Org repos: - Use `cn()` inline in the template when feasible instead of creating a `computed` to hold the value - NEVER use `!important` or the `!` important prefix for tailwind classes - Find existing `!important` classes that are interfering with the styling and propose corrections of those instead. +- NEVER use arbitrary percentage values like `w-[80%]` when a Tailwind fraction utility exists + - Use `w-4/5` instead of `w-[80%]`, `w-1/2` instead of `w-[50%]`, etc. ## Agent-only rules diff --git a/browser_tests/tests/mobileBaseline.spec.ts-snapshots/mobile-settings-dialog-mobile-chrome-linux.png b/browser_tests/tests/mobileBaseline.spec.ts-snapshots/mobile-settings-dialog-mobile-chrome-linux.png index 207d037bf..c179d1c75 100644 Binary files a/browser_tests/tests/mobileBaseline.spec.ts-snapshots/mobile-settings-dialog-mobile-chrome-linux.png and b/browser_tests/tests/mobileBaseline.spec.ts-snapshots/mobile-settings-dialog-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png index 7a1bb89ce..809061b1d 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png index 8d8b4dea8..6c8966f04 100644 Binary files a/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png and b/browser_tests/tests/vueNodes/widgets/load/uploadWidgets.spec.ts-snapshots/vue-nodes-upload-widgets-chromium-linux.png differ diff --git a/package.json b/package.json index 228513ac6..64eeb3cf5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.37.5", + "version": "1.37.6", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org", @@ -66,6 +66,7 @@ "@prettier/plugin-oxc": "catalog:", "@sentry/vite-plugin": "catalog:", "@storybook/addon-docs": "catalog:", + "@storybook/addon-mcp": "catalog:", "@storybook/vue3": "catalog:", "@storybook/vue3-vite": "catalog:", "@tailwindcss/vite": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6eea18564..b0fd3de72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,9 @@ catalogs: '@storybook/addon-docs': specifier: ^10.1.9 version: 10.1.9 + '@storybook/addon-mcp': + specifier: 0.1.6 + version: 0.1.6 '@storybook/vue3': specifier: ^10.1.9 version: 10.1.9 @@ -549,6 +552,9 @@ importers: '@storybook/addon-docs': specifier: 'catalog:' version: 10.1.9(@types/react@19.1.9)(esbuild@0.27.1)(rollup@4.53.5)(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2)) + '@storybook/addon-mcp': + specifier: 'catalog:' + version: 0.1.6(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3) '@storybook/vue3': specifier: 'catalog:' version: 10.1.9(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vue@3.5.13(typescript@5.9.3)) @@ -3148,6 +3154,11 @@ packages: peerDependencies: storybook: ^10.1.9 + '@storybook/addon-mcp@0.1.6': + resolution: {integrity: sha512-+EagCHqwIb9tg3DKskEsXpsqQVnMljxgR5Tt3Bu0ZpWweB1HdMy+ok128gzNfTZ3r+5ljksr0q66YCEkrQwdDA==} + peerDependencies: + storybook: ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 + '@storybook/builder-vite@10.1.9': resolution: {integrity: sha512-rUILpjGV7gKfXrUeZzpNAer9PspB3LJI1d+gJHISx2Gs24bdneA3y/gu0fWw46ccOSIcwb91xoK5QxliJcWsWg==} peerDependencies: @@ -3181,6 +3192,9 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@storybook/mcp@0.1.1': + resolution: {integrity: sha512-+AivFDms1XkY2VUvZBBYy0co5qvRh20eYXYwhaDPQXX2Q4y96arSkWn22e/l3DQwA9Ywzv481vj4gl4zPrCQkg==} + '@storybook/react-dom-shim@10.1.9': resolution: {integrity: sha512-gJsR6fI1gG4DSin6sQx8RmGDQF8Lije0cZbxHyVedNleBsveGXIPFUKFVi+pRNdwBPni1Z2g/gYyHzkOEqPD2w==} peerDependencies: @@ -3453,6 +3467,26 @@ packages: '@tiptap/starter-kit@2.10.4': resolution: {integrity: sha512-tu/WCs9Mkr5Nt8c3/uC4VvAbQlVX0OY7ygcqdzHGUeG9zP3twdW7o5xM3kyDKR2++sbVzqu5Ll5qNU+1JZvPGQ==} + '@tmcp/adapter-valibot@0.1.5': + resolution: {integrity: sha512-9P2wrVYPngemNK0UvPb/opC722/jfd09QxXmme1TRp/wPsl98vpSk/MXt24BCMqBRv4Dvs0xxJH4KHDcjXW52Q==} + peerDependencies: + tmcp: ^1.17.0 + valibot: ^1.1.0 + + '@tmcp/session-manager@0.2.1': + resolution: {integrity: sha512-DOGy9LfufXCy1wfpGHZ6qPSDQtRnTVwOb71+41ffovTqzLMZlK3iLK/LIsekHxIiku+iIAUiqEKN+DHbqEm8IA==} + peerDependencies: + tmcp: ^1.16.3 + + '@tmcp/transport-http@0.8.3': + resolution: {integrity: sha512-gnoBjDBd8/ppl4WRrNKPKHlioCxE8D0zTyNUOzqUjsg0s6GRsyB5iMirh9lC4QjQt0NEOrI+sIJdz+9ymf0MDA==} + peerDependencies: + '@tmcp/auth': ^0.3.3 || ^0.4.0 + tmcp: ^1.18.0 + peerDependenciesMeta: + '@tmcp/auth': + optional: true + '@trivago/prettier-plugin-sort-imports@5.2.2': resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==} engines: {node: '>18.12'} @@ -3786,6 +3820,11 @@ packages: cpu: [x64] os: [win32] + '@valibot/to-json-schema@1.5.0': + resolution: {integrity: sha512-GE7DmSr1C2UCWPiV0upRH6mv0cCPsqYGs819fb6srCS1tWhyXrkGGe+zxUiwzn/L1BOfADH4sNjY/YHCuP8phQ==} + peerDependencies: + valibot: ^1.2.0 + '@vitejs/plugin-vue@6.0.3': resolution: {integrity: sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5170,6 +5209,9 @@ packages: jiti: optional: true + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + esm-resolve@1.0.11: resolution: {integrity: sha512-LxF0wfUQm3ldUDHkkV2MIbvvY0TgzIpJ420jHSV1Dm+IlplBEWiJTKWM61GtxUfvjV6iD4OtTYFGAGM2uuIUWg==} @@ -5978,6 +6020,9 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-rpc-2.0@1.7.1: + resolution: {integrity: sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -7386,6 +7431,9 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sqids@0.3.0: + resolution: {integrity: sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==} + stable-hash-x@0.2.0: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} @@ -7613,6 +7661,9 @@ packages: resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} hasBin: true + tmcp@1.19.0: + resolution: {integrity: sha512-wOY449EdaWDo7wLZEOVjeH9fn/AqfFF4f+3pDerCI8xHpy2Z8msUjAF0Vkg01aEFIdFMmiNDiY4hu6E7jVX79w==} + tmp@0.2.5: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} @@ -7858,6 +7909,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-template-matcher@1.1.2: + resolution: {integrity: sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==} + use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: @@ -7873,6 +7927,14 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + valibot@1.2.0: + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + vfile-message@4.0.3: resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} @@ -8019,6 +8081,9 @@ packages: vue-component-type-helpers@3.2.1: resolution: {integrity: sha512-gKV7XOkQl4urSuLHNY1tnVQf7wVgtb/mKbRyxSLWGZUY9RK7aDPhBenTjm+i8ZFe0zC2PZeHMPtOZXZfyaFOzQ==} + vue-component-type-helpers@3.2.2: + resolution: {integrity: sha512-x8C2nx5XlUNM0WirgfTkHjJGO/ABBxlANZDtHw2HclHtQnn+RFPTnbjMJn8jHZW4TlUam0asHcA14lf1C6Jb+A==} + vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} @@ -10949,6 +11014,18 @@ snapshots: - vite - webpack + '@storybook/addon-mcp@0.1.6(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)': + dependencies: + '@storybook/mcp': 0.1.1(typescript@5.9.3) + '@tmcp/adapter-valibot': 0.1.5(tmcp@1.19.0(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3)) + '@tmcp/transport-http': 0.8.3(tmcp@1.19.0(typescript@5.9.3)) + storybook: 10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + tmcp: 1.19.0(typescript@5.9.3) + valibot: 1.2.0(typescript@5.9.3) + transitivePeerDependencies: + - '@tmcp/auth' + - typescript + '@storybook/builder-vite@10.1.9(esbuild@0.27.1)(rollup@4.53.5)(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2))': dependencies: '@storybook/csf-plugin': 10.1.9(esbuild@0.27.1)(rollup@4.53.5)(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2)) @@ -10978,6 +11055,16 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@storybook/mcp@0.1.1(typescript@5.9.3)': + dependencies: + '@tmcp/adapter-valibot': 0.1.5(tmcp@1.19.0(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3)) + '@tmcp/transport-http': 0.8.3(tmcp@1.19.0(typescript@5.9.3)) + tmcp: 1.19.0(typescript@5.9.3) + valibot: 1.2.0(typescript@5.9.3) + transitivePeerDependencies: + - '@tmcp/auth' + - typescript + '@storybook/react-dom-shim@10.1.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': dependencies: react: 19.2.3 @@ -11007,7 +11094,7 @@ snapshots: storybook: 10.1.9(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) type-fest: 2.19.0 vue: 3.5.13(typescript@5.9.3) - vue-component-type-helpers: 3.2.1 + vue-component-type-helpers: 3.2.2 '@swc/helpers@0.5.17': dependencies: @@ -11275,6 +11362,23 @@ snapshots: '@tiptap/extension-text-style': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) '@tiptap/pm': 2.10.4 + '@tmcp/adapter-valibot@0.1.5(tmcp@1.19.0(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3))': + dependencies: + '@standard-schema/spec': 1.1.0 + '@valibot/to-json-schema': 1.5.0(valibot@1.2.0(typescript@5.9.3)) + tmcp: 1.19.0(typescript@5.9.3) + valibot: 1.2.0(typescript@5.9.3) + + '@tmcp/session-manager@0.2.1(tmcp@1.19.0(typescript@5.9.3))': + dependencies: + tmcp: 1.19.0(typescript@5.9.3) + + '@tmcp/transport-http@0.8.3(tmcp@1.19.0(typescript@5.9.3))': + dependencies: + '@tmcp/session-manager': 0.2.1(tmcp@1.19.0(typescript@5.9.3)) + esm-env: 1.2.2 + tmcp: 1.19.0(typescript@5.9.3) + '@trivago/prettier-plugin-sort-imports@5.2.2(@vue/compiler-sfc@3.5.25)(prettier@3.7.4)': dependencies: '@babel/generator': 7.28.5 @@ -11623,6 +11727,10 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))': + dependencies: + valibot: 1.2.0(typescript@5.9.3) + '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2))(vue@3.5.13(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.53 @@ -13303,6 +13411,8 @@ snapshots: transitivePeerDependencies: - supports-color + esm-env@1.2.2: {} + esm-resolve@1.0.11: {} espree@10.4.0: @@ -14189,6 +14299,8 @@ snapshots: json-parse-even-better-errors@2.3.1: {} + json-rpc-2.0@1.7.1: {} + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -16055,6 +16167,8 @@ snapshots: sprintf-js@1.0.3: {} + sqids@0.3.0: {} + stable-hash-x@0.2.0: {} stack-utils@2.0.6: @@ -16347,6 +16461,16 @@ snapshots: dependencies: tldts-core: 7.0.19 + tmcp@1.19.0(typescript@5.9.3): + dependencies: + '@standard-schema/spec': 1.1.0 + json-rpc-2.0: 1.7.1 + sqids: 0.3.0 + uri-template-matcher: 1.1.2 + valibot: 1.2.0(typescript@5.9.3) + transitivePeerDependencies: + - typescript + tmp@0.2.5: {} to-regex-range@5.0.1: @@ -16644,6 +16768,8 @@ snapshots: dependencies: punycode: 2.3.1 + uri-template-matcher@1.1.2: {} + use-sync-external-store@1.6.0(react@19.2.3): dependencies: react: 19.2.3 @@ -16654,6 +16780,10 @@ snapshots: uuid@11.1.0: {} + valibot@1.2.0(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 @@ -16914,6 +17044,8 @@ snapshots: vue-component-type-helpers@3.2.1: {} + vue-component-type-helpers@3.2.2: {} + vue-demi@0.14.10(vue@3.5.13(typescript@5.9.3)): dependencies: vue: 3.5.13(typescript@5.9.3) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bd4638b0d..56f3f394d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -29,6 +29,7 @@ catalog: '@sentry/vue': ^10.32.1 '@sparkjsdev/spark': ^0.1.10 '@storybook/addon-docs': ^10.1.9 + '@storybook/addon-mcp': 0.1.6 '@storybook/vue3': ^10.1.9 '@storybook/vue3-vite': ^10.1.9 '@tailwindcss/vite': ^4.1.12 diff --git a/src/components/TopMenuSection.vue b/src/components/TopMenuSection.vue index 448a081f9..7cdd5418a 100644 --- a/src/components/TopMenuSection.vue +++ b/src/components/TopMenuSection.vue @@ -20,9 +20,14 @@ variant="secondary" size="icon" :aria-label="t('menu.customNodesManager')" + class="relative" @click="openCustomNodeManager" > + @@ -49,7 +54,7 @@ {{ queuedCount }} @@ -91,12 +96,14 @@ import Button from '@/components/ui/button/Button.vue' import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { useErrorHandling } from '@/composables/useErrorHandling' import { buildTooltipConfig } from '@/composables/useTooltipConfig' +import { useReleaseStore } from '@/platform/updates/common/releaseStore' import { app } from '@/scripts/app' import { useCommandStore } from '@/stores/commandStore' import { useQueueStore, useQueueUIStore } from '@/stores/queueStore' import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore' import { useWorkspaceStore } from '@/stores/workspaceStore' import { isElectron } from '@/utils/envUtil' +import { useConflictAcknowledgment } from '@/workbench/extensions/manager/composables/useConflictAcknowledgment' import { useManagerState } from '@/workbench/extensions/manager/composables/useManagerState' import { ManagerTab } from '@/workbench/extensions/manager/types/comfyManagerTypes' @@ -111,6 +118,10 @@ const commandStore = useCommandStore() const queueStore = useQueueStore() const queueUIStore = useQueueUIStore() const { isOverlayExpanded: isQueueOverlayExpanded } = storeToRefs(queueUIStore) +const releaseStore = useReleaseStore() +const { shouldShowRedDot: showReleaseRedDot } = storeToRefs(releaseStore) +const { shouldShowRedDot: shouldShowConflictRedDot } = + useConflictAcknowledgment() const isTopMenuHovered = ref(false) const queuedCount = computed(() => queueStore.pendingTasks.length) const queueHistoryTooltipConfig = computed(() => @@ -120,6 +131,12 @@ const customNodesManagerTooltipConfig = computed(() => buildTooltipConfig(t('menu.customNodesManager')) ) +// Use either release red dot or conflict red dot +const shouldShowRedDot = computed((): boolean => { + const releaseRedDot = showReleaseRedDot.value + return releaseRedDot || shouldShowConflictRedDot.value +}) + // Right side panel toggle const { isOpen: isRightSidePanelOpen } = storeToRefs(rightSidePanelStore) const rightSidePanelTooltipConfig = computed(() => diff --git a/src/components/button/IconGroup.vue b/src/components/button/IconGroup.vue index c533125d6..81a23c5ce 100644 --- a/src/components/button/IconGroup.vue +++ b/src/components/button/IconGroup.vue @@ -2,8 +2,8 @@
diff --git a/src/components/common/StatusBadge.vue b/src/components/common/StatusBadge.vue new file mode 100644 index 000000000..46ef7ac79 --- /dev/null +++ b/src/components/common/StatusBadge.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/components/dialog/content/MissingNodesHeader.vue b/src/components/dialog/content/MissingNodesHeader.vue index 4dd483fd0..1e150c3d3 100644 --- a/src/components/dialog/content/MissingNodesHeader.vue +++ b/src/components/dialog/content/MissingNodesHeader.vue @@ -1,7 +1,7 @@