diff --git a/.gitignore b/.gitignore index db5315411..b3e819f18 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,3 @@ vite.config.mts.timestamp-*.mjs *storybook.log storybook-static - diff --git a/.storybook/main.ts b/.storybook/main.ts index a799ec143..3a24b68d4 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,96 +1,63 @@ import type { StorybookConfig } from '@storybook/vue3-vite' +import vue from '@vitejs/plugin-vue' import { FileSystemIconLoader } from 'unplugin-icons/loaders' import IconsResolver from 'unplugin-icons/resolver' import Icons from 'unplugin-icons/vite' import Components from 'unplugin-vue-components/vite' -import type { InlineConfig } from 'vite' const config: StorybookConfig = { - stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: ['@storybook/addon-docs'], + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-docs', + '@storybook/addon-controls', + '@storybook/addon-actions', + '@storybook/addon-viewport', + '@storybook/addon-backgrounds' + ], framework: { name: '@storybook/vue3-vite', options: {} }, - async viteFinal(config) { - // Use dynamic import to avoid CJS deprecation warning + viteFinal: async (config) => { const { mergeConfig } = await import('vite') - // Filter out any plugins that might generate import maps - if (config.plugins) { - config.plugins = config.plugins.filter((plugin: any) => { - if (plugin && plugin.name && plugin.name.includes('import-map')) { - return false - } - return true - }) - } - return mergeConfig(config, { - // Replace plugins entirely to avoid inheritance issues plugins: [ - // Only include plugins we explicitly need for Storybook + vue(), Icons({ compiler: 'vue3', customCollections: { - comfy: FileSystemIconLoader( - process.cwd() + '/src/assets/icons/custom' - ) + comfy: FileSystemIconLoader('../src/assets/icons/custom') } }), Components({ - dts: false, // Disable dts generation in Storybook + dts: false, // Disable DTS generation for Storybook resolvers: [ IconsResolver({ customCollections: ['comfy'] }) ], - dirs: [ - process.cwd() + '/src/components', - process.cwd() + '/src/layout', - process.cwd() + '/src/views' - ], + dirs: ['../src/components', '../src/layout', '../src/views'], deep: true, extensions: ['vue'] }) - // Note: Explicitly NOT including generateImportMapPlugin to avoid externalization ], - server: { - allowedHosts: true - }, resolve: { alias: { - '@': process.cwd() + '/src' + '@': new URL('../src', import.meta.url).pathname } }, - build: { - rollupOptions: { - external: () => { - // Don't externalize any modules in Storybook build - // This ensures PrimeVue and other dependencies are bundled - return false - }, - onwarn: (warning, warn) => { - // Suppress specific warnings - if ( - warning.code === 'UNUSED_EXTERNAL_IMPORT' && - warning.message?.includes('resolveComponent') - ) { - return - } - // Suppress Storybook font asset warnings - if ( - warning.code === 'UNRESOLVED_IMPORT' && - warning.message?.includes('nunito-sans') - ) { - return - } - warn(warning) - } - }, - chunkSizeWarningLimit: 1000 + define: { + ...config.define, + global: 'globalThis', + __COMFYUI_FRONTEND_VERSION__: JSON.stringify('1.26.4'), + __SENTRY_ENABLED__: JSON.stringify(false), + __SENTRY_DSN__: JSON.stringify(''), + __ALGOLIA_APP_ID__: JSON.stringify(''), + __ALGOLIA_API_KEY__: JSON.stringify(''), + __USE_PROD_CONFIG__: JSON.stringify(false) } - } satisfies InlineConfig) + }) } } export default config diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 747bbe802..b8b43aa2f 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,53 +1,57 @@ -import { definePreset } from '@primevue/themes' -import Aura from '@primevue/themes/aura' import { setup } from '@storybook/vue3' import type { Preview } from '@storybook/vue3-vite' import { createPinia } from 'pinia' -import 'primeicons/primeicons.css' import PrimeVue from 'primevue/config' -import ConfirmationService from 'primevue/confirmationservice' import ToastService from 'primevue/toastservice' import Tooltip from 'primevue/tooltip' +import { createI18n } from 'vue-i18n' +import '../public/materialdesignicons.min.css' +// Import styles import '../src/assets/css/style.css' -import { i18n } from '../src/i18n' -import '../src/lib/litegraph/public/css/litegraph.css' -import { useWidgetStore } from '../src/stores/widgetStore' -import { useColorPaletteStore } from '../src/stores/workspace/colorPaletteStore' -const ComfyUIPreset = definePreset(Aura, { - semantic: { - // @ts-expect-error fix me - primary: Aura['primitive'].blue - } -}) +// Mock Firebase for Storybook +const mockFirebase = { + auth: () => ({ + currentUser: null, + onAuthStateChanged: () => () => {} + }), + firestore: () => ({}) +} -// Setup Vue app for Storybook +// Setup Vue plugins for Storybook setup((app) => { - app.directive('tooltip', Tooltip) const pinia = createPinia() - app.use(pinia) - - // Initialize stores - useColorPaletteStore(pinia) - useWidgetStore(pinia) - - app.use(i18n) - app.use(PrimeVue, { - theme: { - preset: ComfyUIPreset, - options: { - prefix: 'p', - cssLayer: { - name: 'primevue', - order: 'primevue, tailwind-utilities' + const i18n = createI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + en: { + g: { + searchSettings: 'Search Settings', + noResultsFound: 'No Results Found', + searchFailedMessage: 'Try adjusting your search terms', + experimental: 'Experimental', + loadingPanel: 'Loading {panel}...' }, - darkModeSelector: '.dark-theme, :root:has(.dark-theme)' + settings: {}, + settingsCategories: {} } } }) - app.use(ConfirmationService) + + app.use(pinia) + app.use(i18n) + app.use(PrimeVue, { + theme: { + preset: null // Will use CSS for theming + } + }) app.use(ToastService) + app.directive('tooltip', Tooltip) + + // Provide mock services + app.provide('firebase', mockFirebase) }) // Dark theme decorator @@ -77,9 +81,40 @@ const preview: Preview = { backgrounds: { default: 'light', values: [ - { name: 'light', value: '#ffffff' }, - { name: 'dark', value: '#0a0a0a' } + { + name: 'light', + value: '#ffffff' + }, + { + name: 'dark', + value: '#1a1a1a' + } ] + }, + viewport: { + viewports: { + small: { + name: 'Small', + styles: { + width: '640px', + height: '480px' + } + }, + medium: { + name: 'Medium', + styles: { + width: '768px', + height: '1024px' + } + }, + large: { + name: 'Large', + styles: { + width: '1024px', + height: '768px' + } + } + } } }, globalTypes: { diff --git a/package-lock.json b/package-lock.json index d2192d33f..dd01527b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,8 +59,13 @@ "@lobehub/i18n-cli": "^1.20.0", "@pinia/testing": "^0.1.5", "@playwright/test": "^1.52.0", - "@storybook/addon-docs": "^9.1.1", - "@storybook/vue3-vite": "^9.1.1", + "@storybook/addon-actions": "^9.0.8", + "@storybook/addon-backgrounds": "^9.0.8", + "@storybook/addon-controls": "^9.0.8", + "@storybook/addon-docs": "^9.1.2", + "@storybook/addon-onboarding": "^9.1.2", + "@storybook/addon-viewport": "^9.0.8", + "@storybook/vue3-vite": "^9.1.2", "@trivago/prettier-plugin-sort-imports": "^5.2.0", "@types/dompurify": "^3.0.5", "@types/fs-extra": "^11.0.4", @@ -74,7 +79,7 @@ "eslint": "^9.12.0", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", - "eslint-plugin-storybook": "^9.1.1", + "eslint-plugin-storybook": "^9.1.2", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^9.27.0", "fs-extra": "^11.2.0", @@ -86,7 +91,7 @@ "lint-staged": "^15.2.7", "postcss": "^8.4.39", "prettier": "^3.3.2", - "storybook": "^9.1.1", + "storybook": "^9.1.2", "tailwindcss": "^3.4.4", "tsx": "^4.15.6", "typescript": "^5.4.5", @@ -139,9 +144,9 @@ "dev": true }, "node_modules/@adobe/css-tools": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz", - "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", "dev": true, "license": "MIT" }, @@ -4325,17 +4330,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@storybook/addon-actions": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-9.0.8.tgz", + "integrity": "sha512-LFePu7PPnWN0Il/uoUpmA5T0J0C7d6haJIbg0pXrjxW2MQVSYXE4S4LSUz8fOImltBDV3xAl6tLPYHFj6VcrOA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-9.0.8.tgz", + "integrity": "sha512-4Vvr4wYHtiZ8UVWdCahK0XEMU4zNgInnNcVQ31YkUg41MVSY+aoZqtNuxOuRbFzUtjL9/aVsbY0Sg9Lp1/EJ4g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-9.0.8.tgz", + "integrity": "sha512-6MY9QeBv2vNmBXH+ONmbpp/Gu/odSxriN1+BAY+il9OyXZBMq3OiDsjoH7xY5V7PGr+0XhZfOLkamvx3q+lQTg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/addon-docs": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.1.tgz", - "integrity": "sha512-CzgvTy3V5X4fe+VPkiZVwPKARlpEBDAKte8ajLAlHJQLFpADdYrBRQ0se6I+kcxva7rZQzdhuH7qjXMDRVcfnw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.2.tgz", + "integrity": "sha512-U3eHJ8lQFfEZ/OcgdKkUBbW2Y2tpAsHfy8lQOBgs5Pgj9biHEJcUmq+drOS/sJhle673eoBcUFmspXulI4KP1w==", "dev": true, "license": "MIT", "dependencies": { "@mdx-js/react": "^3.0.0", - "@storybook/csf-plugin": "9.1.1", + "@storybook/csf-plugin": "9.1.2", "@storybook/icons": "^1.4.0", - "@storybook/react-dom-shim": "9.1.1", + "@storybook/react-dom-shim": "9.1.2", "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", "ts-dedent": "^2.0.0" @@ -4345,7 +4383,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.1" + "storybook": "^9.1.2" } }, "node_modules/@storybook/addon-docs/node_modules/@storybook/icons": { @@ -4363,9 +4401,9 @@ } }, "node_modules/@storybook/addon-docs/node_modules/@storybook/react-dom-shim": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.1.tgz", - "integrity": "sha512-L+HCOXvOP+PwKrVS8od9aF+F4hO7zA0Nt1vnpbg2LeAHCxYghrjFVtioe7gSlzrlYdozQrPLY98a4OkDB7KGrw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.2.tgz", + "integrity": "sha512-nw7BLAHCJswPZGsuL0Gs2AvFUWriusCTgPBmcHppSw/AqvT4XRFRDE+5q3j04/XKuZBrAA2sC4L+HuC0uzEChQ==", "dev": true, "license": "MIT", "funding": { @@ -4375,7 +4413,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.1" + "storybook": "^9.1.2" } }, "node_modules/@storybook/addon-docs/node_modules/react": { @@ -4408,14 +4446,39 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/addon-onboarding": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-9.1.2.tgz", + "integrity": "sha512-WfYIBmRtwUF13Hcu6BdsqATsAuBK0dwsz7O4tL0FGrIwY/vdzZ5jNzYvzzgilzlu9QiPvzEIBvs6X4BVulN3LQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.1.2" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-9.0.8.tgz", + "integrity": "sha512-HgIFDzNXvMx0zQBM5mhwBoAJlrF9KRlxNCZnJbqrFLCJO4Ps2PMtB0HRGHcg0gm3RLcqyps0DpiF7wll3udb7Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/builder-vite": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.1.tgz", - "integrity": "sha512-rM0QOfykr39SFBRQnoAa5PU3xTHnJE1R5tigvjved1o7sumcfjrhqmEyAgNZv1SoRztOO92jwkTi7En6yheOKg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.2.tgz", + "integrity": "sha512-5Y7e5wnSzFxCGP63UNRRZVoxHe1znU4dYXazJBobAlEcUPBk7A0sH2716tA6bS4oz92oG9tgvn1g996hRrw4ow==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf-plugin": "9.1.1", + "@storybook/csf-plugin": "9.1.2", "ts-dedent": "^2.0.0" }, "funding": { @@ -4423,14 +4486,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.1", + "storybook": "^9.1.2", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.1.tgz", - "integrity": "sha512-MwdtvzzFpkard06pCfDrgRXZiBfWAQICdKh7kzpv1L8SwewsRgUr5WZQuEAVfYdSvCFJbWnNN4KirzPhe5ENCg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.2.tgz", + "integrity": "sha512-bfMh6r+RieBLPWtqqYN70le2uTE4JzOYPMYSCagHykUti3uM/1vRFaZNkZtUsRy5GwEzE5jLdDXioG1lOEeT2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4441,7 +4504,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.1" + "storybook": "^9.1.2" } }, "node_modules/@storybook/csf-plugin/node_modules/unplugin": { @@ -4466,9 +4529,9 @@ "license": "MIT" }, "node_modules/@storybook/vue3": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-9.1.1.tgz", - "integrity": "sha512-eKY1wKKmFrO8IpgHIV7XAyv7WRvI9rdvni4niy0bcho7QLD27trmJ9lJ3mAwZ8rEpUjgYOSDi6i5/jangbZc4w==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-9.1.2.tgz", + "integrity": "sha512-aYLh6/DZEuoOtsn/qePb9I/kuzwZGy+mS/ELlFoj72vpJc4d21hKZfiepO5bZ3z73XK7nLmdMVQ2tIwvsin4Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -4484,19 +4547,19 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.1", + "storybook": "^9.1.2", "vue": "^3.0.0" } }, "node_modules/@storybook/vue3-vite": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-9.1.1.tgz", - "integrity": "sha512-JdQPPYCVxvw+hXEd27JH5ESmP7o86/dwNGiWvFUZLUp1utjrtXfr68QiFWRWjWRCe/4RvNgypX3tKoZMZ3ay6w==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-9.1.2.tgz", + "integrity": "sha512-MSXNtSbY8dnlcSzmbjkzJs1gAmDVRH1b4lBYU8TPHb8YmFz9vdYi8JNjOFztEjcnFe6VPVeCys69MpzZqGF31g==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/builder-vite": "9.1.1", - "@storybook/vue3": "9.1.1", + "@storybook/builder-vite": "9.1.2", + "@storybook/vue3": "9.1.2", "find-package-json": "^1.2.0", "magic-string": "^0.30.0", "typescript": "^5.8.3", @@ -4511,7 +4574,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.1", + "storybook": "^9.1.2", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, @@ -4561,9 +4624,9 @@ "peer": true }, "node_modules/@testing-library/jest-dom": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.4.tgz", - "integrity": "sha512-xDXgLjVunjHqczScfkCJ9iyjdNOVHvvCdqHSSxwM9L0l/wHkTRum67SDc020uAlCoqktJplgO2AAQeLP1wgqDQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.7.0.tgz", + "integrity": "sha512-RI2e97YZ7MRa+vxP4UUnMuMFL2buSsf0ollxUbTgrbPLKhMn8KVTx7raS6DYjC7v1NDVrioOvaShxsguLNISCA==", "dev": true, "license": "MIT", "dependencies": { @@ -4571,7 +4634,6 @@ "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", "picocolors": "^1.1.1", "redent": "^3.0.0" }, @@ -5211,9 +5273,9 @@ } }, "node_modules/@types/react": { - "version": "19.1.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", - "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "version": "19.1.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", + "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", "dev": true, "license": "MIT", "peer": true, @@ -5354,14 +5416,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.0.tgz", - "integrity": "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.0", - "@typescript-eslint/types": "^8.39.0", + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", "debug": "^4.3.4" }, "engines": { @@ -5376,9 +5438,9 @@ } }, "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.0.tgz", - "integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", "dev": true, "license": "MIT", "engines": { @@ -5408,9 +5470,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.0.tgz", - "integrity": "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", "dev": true, "license": "MIT", "engines": { @@ -8422,7 +8484,6 @@ "version": "1.39.9", "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.9.tgz", "integrity": "sha512-9OtbkZmTA2Qc9groyA1PUNeb6knVTkvB2RSdr/LcJXDL8IdEakaxwXLHXa7VX/Wj0GmdMJPR3WhnPGhiP3E+qg==", - "license": "MIT", "workspaces": [ "docs", "benchmarks" @@ -8627,9 +8688,9 @@ } }, "node_modules/eslint-plugin-storybook": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-9.1.1.tgz", - "integrity": "sha512-g4/i9yW6cl4TCEMzYyALNvO3d/jB6TDvSs/Pmye7dHDrra2B7dgZJGzmEWILD62brVrLVHNoXgy2dNPtx80kmw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-9.1.2.tgz", + "integrity": "sha512-EQa/kChrYrekxv36q3pvW57anqxMlAP4EdPXEDyA/EDrCQJaaTbWEdsMnVZtD744RjPP0M5wzaUjHbMhNooAwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8640,18 +8701,18 @@ }, "peerDependencies": { "eslint": ">=8", - "storybook": "^9.1.1" + "storybook": "^9.1.2" } }, "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.0.tgz", - "integrity": "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0" + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8662,9 +8723,9 @@ } }, "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/types": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.0.tgz", - "integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", "dev": true, "license": "MIT", "engines": { @@ -8676,16 +8737,16 @@ } }, "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.0.tgz", - "integrity": "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.39.0", - "@typescript-eslint/tsconfig-utils": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -8705,16 +8766,16 @@ } }, "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/utils": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.0.tgz", - "integrity": "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0" + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8729,13 +8790,13 @@ } }, "node_modules/eslint-plugin-storybook/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.0.tgz", - "integrity": "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/types": "8.39.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -16163,9 +16224,9 @@ "license": "MIT" }, "node_modules/storybook": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.1.tgz", - "integrity": "sha512-q6GaGZdVZh6rjOdGnc+4hGTu8ECyhyjQDw4EZNxKtQjDO8kqtuxbFm8l/IP2l+zLVJAatGWKkaX9Qcd7QZxz+Q==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.2.tgz", + "integrity": "sha512-TYcq7WmgfVCAQge/KueGkVlM/+g33sQcmbATlC3X6y/g2FEeSSLGrb6E6d3iemht8oio+aY6ld3YOdAnMwx45Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c6e922fc2..aa31ac88e 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,13 @@ "@lobehub/i18n-cli": "^1.20.0", "@pinia/testing": "^0.1.5", "@playwright/test": "^1.52.0", - "@storybook/addon-docs": "^9.1.1", - "@storybook/vue3-vite": "^9.1.1", + "@storybook/addon-actions": "^9.0.8", + "@storybook/addon-backgrounds": "^9.0.8", + "@storybook/addon-controls": "^9.0.8", + "@storybook/addon-docs": "^9.1.2", + "@storybook/addon-onboarding": "^9.1.2", + "@storybook/addon-viewport": "^9.0.8", + "@storybook/vue3-vite": "^9.1.2", "@trivago/prettier-plugin-sort-imports": "^5.2.0", "@types/dompurify": "^3.0.5", "@types/fs-extra": "^11.0.4", @@ -55,7 +60,7 @@ "eslint": "^9.12.0", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", - "eslint-plugin-storybook": "^9.1.1", + "eslint-plugin-storybook": "^9.1.2", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^9.27.0", "fs-extra": "^11.2.0", @@ -67,7 +72,7 @@ "lint-staged": "^15.2.7", "postcss": "^8.4.39", "prettier": "^3.3.2", - "storybook": "^9.1.1", + "storybook": "^9.1.2", "tailwindcss": "^3.4.4", "tsx": "^4.15.6", "typescript": "^5.4.5", diff --git a/src/components/dialog/content/SettingDialogContent.stories.ts b/src/components/dialog/content/SettingDialogContent.stories.ts new file mode 100644 index 000000000..fe4d13804 --- /dev/null +++ b/src/components/dialog/content/SettingDialogContent.stories.ts @@ -0,0 +1,108 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import SettingDialogContent from './SettingDialogContent.vue' + +const meta: Meta = { + title: 'Components/Dialog/SettingDialogContent', + component: SettingDialogContent, + parameters: { + layout: 'fullscreen', + docs: { + description: { + component: + 'The complete settings dialog content with sidebar navigation and tabbed panels.' + } + } + }, + argTypes: { + defaultPanel: { + control: 'select', + options: [ + 'about', + 'keybinding', + 'extension', + 'server-config', + 'user', + 'credits' + ], + description: 'The default panel to show when the dialog opens' + } + }, + decorators: [ + () => ({ + template: + '
' + }) + ] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: {} +} + +export const AboutPanel: Story = { + args: { + defaultPanel: 'about' + } +} + +export const KeybindingPanel: Story = { + args: { + defaultPanel: 'keybinding' + } +} + +export const ExtensionPanel: Story = { + args: { + defaultPanel: 'extension' + } +} + +export const ServerConfigPanel: Story = { + args: { + defaultPanel: 'server-config' + } +} + +export const UserPanel: Story = { + args: { + defaultPanel: 'user' + } +} + +export const CreditsPanel: Story = { + args: { + defaultPanel: 'credits' + } +} + +// Responsive variants +export const Mobile: Story = { + args: {}, + parameters: { + viewport: { + defaultViewport: 'mobile1' + } + } +} + +export const Tablet: Story = { + args: {}, + parameters: { + viewport: { + defaultViewport: 'tablet' + } + } +} + +export const Desktop: Story = { + args: {}, + parameters: { + viewport: { + defaultViewport: 'desktop' + } + } +} diff --git a/src/components/dialog/content/setting/AboutPanel.stories.ts b/src/components/dialog/content/setting/AboutPanel.stories.ts new file mode 100644 index 000000000..acb8868eb --- /dev/null +++ b/src/components/dialog/content/setting/AboutPanel.stories.ts @@ -0,0 +1,63 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import AboutPanel from './AboutPanel.vue' + +const meta: Meta = { + title: 'Components/Setting/AboutPanel', + component: AboutPanel, + parameters: { + layout: 'padded', + docs: { + description: { + component: + 'The About panel displays project information, badges, and system statistics.' + } + } + }, + decorators: [ + () => ({ + template: + '
' + }) + ] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: {}, + parameters: { + docs: { + description: { + story: + 'The default About panel showing project badges and system information.' + } + } + } +} + +export const WithSystemStats: Story = { + args: {}, + parameters: { + docs: { + description: { + story: 'About panel with system statistics visible.' + } + } + } +} + +export const Mobile: Story = { + args: {}, + parameters: { + viewport: { + defaultViewport: 'mobile1' + }, + docs: { + description: { + story: 'About panel optimized for mobile devices.' + } + } + } +} diff --git a/src/components/dialog/content/setting/PanelTemplate.stories.ts b/src/components/dialog/content/setting/PanelTemplate.stories.ts new file mode 100644 index 000000000..ff5e0ea86 --- /dev/null +++ b/src/components/dialog/content/setting/PanelTemplate.stories.ts @@ -0,0 +1,197 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import PanelTemplate from './PanelTemplate.vue' + +const meta: Meta = { + title: 'Components/Setting/PanelTemplate', + component: PanelTemplate, + parameters: { + layout: 'padded', + docs: { + description: { + component: + 'A template component for settings panels that provides consistent layout with header, content, and footer slots.' + } + } + }, + argTypes: { + value: { + control: 'text', + description: 'The value identifier for the tab panel' + }, + class: { + control: 'text', + description: 'Additional CSS classes to apply' + } + }, + decorators: [ + () => ({ + template: + '
' + }) + ] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + value: 'example-panel' + }, + render: (args) => ({ + components: { PanelTemplate }, + setup() { + return { args } + }, + template: ` + +
+

Panel Content

+

This is the main content area of the panel.

+
+
Setting Item 1
+
Setting Item 2
+
Setting Item 3
+
+
+
+ ` + }) +} + +export const WithHeader: Story = { + args: { + value: 'header-panel' + }, + render: (args) => ({ + components: { PanelTemplate }, + setup() { + return { args } + }, + template: ` + + +
+

Panel Content

+

Content with a header message above.

+
+
+ ` + }) +} + +export const WithFooter: Story = { + args: { + value: 'footer-panel' + }, + render: (args) => ({ + components: { PanelTemplate }, + setup() { + return { args } + }, + template: ` + +
+

Panel Content

+

Content with a footer below.

+
+ +
+ ` + }) +} + +export const WithHeaderAndFooter: Story = { + args: { + value: 'full-panel' + }, + render: (args) => ({ + components: { PanelTemplate }, + setup() { + return { args } + }, + template: ` + + +
+

Settings Content

+
+
+ + +
+
+ + +
+
+
+ +
+ ` + }) +} + +export const LongContent: Story = { + args: { + value: 'long-panel' + }, + render: (args) => ({ + components: { PanelTemplate }, + setup() { + return { args } + }, + template: ` + +
+

Scrollable Content

+
+ ${Array.from( + { length: 20 }, + (_, i) => ` +
+

Setting Group ${i + 1}

+

This is setting group ${i + 1} with some description text.

+
+ ` + ).join('')} +
+
+
+ ` + }) +} diff --git a/src/components/dialog/content/setting/SettingGroup.stories.ts b/src/components/dialog/content/setting/SettingGroup.stories.ts new file mode 100644 index 000000000..a62715d63 --- /dev/null +++ b/src/components/dialog/content/setting/SettingGroup.stories.ts @@ -0,0 +1,150 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import type { SettingParams } from '@/types/settingTypes' + +import SettingGroup from './SettingGroup.vue' + +const meta: Meta = { + title: 'Components/Setting/SettingGroup', + component: SettingGroup, + parameters: { + layout: 'padded' + }, + argTypes: { + group: { + control: 'object', + description: 'The setting group configuration' + }, + divider: { + control: 'boolean', + description: 'Show divider above the group' + } + }, + decorators: [ + () => ({ + template: '
' + }) + ] +} + +export default meta +type Story = StoryObj + +const createMockSetting = ( + overrides: Partial = {} +): SettingParams => ({ + id: 'test.setting' as any, + name: 'Test Setting', + type: 'boolean', + defaultValue: false, + ...overrides +}) + +export const BasicGroup: Story = { + args: { + group: { + label: 'Basic Settings', + settings: [ + createMockSetting({ + id: 'basic.enable' as any, + name: 'Enable Feature', + type: 'boolean', + defaultValue: true, + tooltip: 'Enable or disable this feature' + }), + createMockSetting({ + id: 'basic.name' as any, + name: 'Display Name', + type: 'text', + defaultValue: 'My App', + tooltip: 'The name to display in the title bar' + }) + ] + }, + divider: false + } +} + +export const GroupWithDivider: Story = { + args: { + group: { + label: 'Advanced Settings', + settings: [ + createMockSetting({ + id: 'advanced.debug' as any, + name: 'Debug Mode', + type: 'boolean', + defaultValue: false, + experimental: true, + tooltip: 'Enable debug logging and developer tools' + }), + createMockSetting({ + id: 'advanced.timeout' as any, + name: 'Request Timeout (ms)', + type: 'number', + defaultValue: 5000, + tooltip: 'How long to wait for requests', + attrs: { + min: 1000, + max: 30000, + step: 500 + } + }) + ] + }, + divider: true + } +} + +export const PerformanceGroup: Story = { + args: { + group: { + label: 'Performance', + settings: [ + createMockSetting({ + id: 'perf.threads' as any, + name: 'Worker Threads', + type: 'slider', + defaultValue: 4, + tooltip: 'Number of worker threads to use', + attrs: { + min: 1, + max: 16, + step: 1 + } + }), + createMockSetting({ + id: 'perf.quality' as any, + name: 'Render Quality', + type: 'combo', + defaultValue: 'high', + tooltip: 'Rendering quality level', + options: [ + { text: 'Low', value: 'low' }, + { text: 'Medium', value: 'medium' }, + { text: 'High', value: 'high' }, + { text: 'Ultra', value: 'ultra' } + ] + }), + createMockSetting({ + id: 'perf.vsync' as any, + name: 'V-Sync', + type: 'boolean', + defaultValue: true, + tooltip: 'Enable vertical synchronization' + }) + ] + }, + divider: false + } +} + +export const EmptyGroup: Story = { + args: { + group: { + label: 'Empty Group', + settings: [] + }, + divider: false + } +} diff --git a/src/components/dialog/content/setting/SettingItem.stories.ts b/src/components/dialog/content/setting/SettingItem.stories.ts new file mode 100644 index 000000000..d7fbd5999 --- /dev/null +++ b/src/components/dialog/content/setting/SettingItem.stories.ts @@ -0,0 +1,159 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import type { SettingParams } from '@/types/settingTypes' + +import SettingItem from './SettingItem.vue' + +const meta: Meta = { + title: 'Components/Setting/SettingItem', + component: SettingItem, + parameters: { + layout: 'padded' + }, + argTypes: { + setting: { + control: 'object', + description: 'The setting configuration object' + } + }, + decorators: [ + () => ({ + template: '
' + }) + ] +} + +export default meta +type Story = StoryObj + +const createMockSetting = ( + overrides: Partial = {} +): SettingParams => ({ + id: 'test.setting' as any, + name: 'Test Setting', + type: 'boolean', + defaultValue: false, + tooltip: 'This is a test setting for demonstration purposes', + ...overrides +}) + +export const BooleanSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Enable Feature', + type: 'boolean', + defaultValue: true, + tooltip: 'Toggle this feature on or off' + }) + } +} + +export const TextSetting: Story = { + args: { + setting: createMockSetting({ + name: 'API Endpoint', + type: 'text', + defaultValue: 'https://api.example.com', + tooltip: 'The API endpoint to connect to' + }) + } +} + +export const NumberSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Max Connections', + type: 'number', + defaultValue: 10, + tooltip: 'Maximum number of concurrent connections', + attrs: { + min: 1, + max: 100, + step: 1 + } + }) + } +} + +export const SliderSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Volume Level', + type: 'slider', + defaultValue: 50, + tooltip: 'Adjust the volume level', + attrs: { + min: 0, + max: 100, + step: 5 + } + }) + } +} + +export const ComboSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Theme', + type: 'combo', + defaultValue: 'dark', + tooltip: 'Select your preferred theme', + options: [ + { text: 'Light', value: 'light' }, + { text: 'Dark', value: 'dark' }, + { text: 'Auto', value: 'auto' } + ] + }) + } +} + +export const ColorSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Accent Color', + type: 'color', + defaultValue: '#007bff', + tooltip: 'Choose your accent color' + }) + } +} + +export const ExperimentalSetting: Story = { + args: { + setting: createMockSetting({ + name: 'Experimental Feature', + type: 'boolean', + defaultValue: false, + experimental: true, + tooltip: 'This feature is experimental and may change' + }) + } +} + +export const WithLanguageTag: Story = { + args: { + setting: createMockSetting({ + id: 'Comfy.Locale' as any, + name: 'Language', + type: 'combo', + defaultValue: 'en', + tooltip: 'Select your preferred language', + options: [ + { text: 'English', value: 'en' }, + { text: 'Spanish', value: 'es' }, + { text: 'French', value: 'fr' } + ] + }) + } +} + +export const InteractiveBoolean: Story = { + args: { + setting: createMockSetting({ + name: 'Interactive Boolean', + type: 'boolean', + defaultValue: false, + tooltip: 'Click to toggle this setting' + }) + } +} diff --git a/src/components/dialog/content/setting/SettingsPanel.stories.ts b/src/components/dialog/content/setting/SettingsPanel.stories.ts new file mode 100644 index 000000000..ba164d92e --- /dev/null +++ b/src/components/dialog/content/setting/SettingsPanel.stories.ts @@ -0,0 +1,238 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import type { ISettingGroup, SettingParams } from '@/types/settingTypes' + +import SettingsPanel from './SettingsPanel.vue' + +const meta: Meta = { + title: 'Components/Setting/SettingsPanel', + component: SettingsPanel, + parameters: { + layout: 'padded' + }, + argTypes: { + settingGroups: { + control: 'object', + description: 'Array of setting groups to display' + } + }, + decorators: [ + () => ({ + template: '
' + }) + ] +} + +export default meta +type Story = StoryObj + +const createMockSetting = ( + overrides: Partial = {} +): SettingParams => ({ + id: 'test.setting' as any, + name: 'Test Setting', + type: 'boolean', + defaultValue: false, + ...overrides +}) + +const mockGeneralSettings: ISettingGroup = { + label: 'General', + settings: [ + createMockSetting({ + id: 'Comfy.Locale' as any, + name: 'Language', + type: 'combo', + defaultValue: 'en', + tooltip: 'Select your preferred language', + options: [ + { text: 'English', value: 'en' }, + { text: 'Spanish', value: 'es' }, + { text: 'French', value: 'fr' }, + { text: 'German', value: 'de' } + ] + }), + createMockSetting({ + id: 'Comfy.AutoSave' as any, + name: 'Auto Save', + type: 'boolean', + defaultValue: true, + tooltip: 'Automatically save your work' + }), + createMockSetting({ + id: 'Comfy.AutoSaveInterval' as any, + name: 'Auto Save Interval (seconds)', + type: 'number', + defaultValue: 30, + tooltip: 'How often to auto save in seconds', + attrs: { + min: 10, + max: 300, + step: 5 + } + }) + ] +} + +const mockAppearanceSettings: ISettingGroup = { + label: 'Appearance', + settings: [ + createMockSetting({ + id: 'Comfy.ColorPalette' as any, + name: 'Color Palette', + type: 'combo', + defaultValue: 'dark', + tooltip: 'Choose your color theme', + options: [ + { text: 'Dark', value: 'dark' }, + { text: 'Light', value: 'light' }, + { text: 'Arc', value: 'arc' }, + { text: 'Nord', value: 'nord' } + ] + }), + createMockSetting({ + id: 'Comfy.AccentColor' as any, + name: 'Accent Color', + type: 'color', + defaultValue: '#007bff', + tooltip: 'Choose your accent color' + }), + createMockSetting({ + id: 'Comfy.NodeOpacity' as any, + name: 'Node Opacity', + type: 'slider', + defaultValue: 80, + tooltip: 'Adjust node transparency', + attrs: { + min: 10, + max: 100, + step: 10 + } + }) + ] +} + +const mockPerformanceSettings: ISettingGroup = { + label: 'Performance', + settings: [ + createMockSetting({ + id: 'Comfy.MaxConcurrentTasks' as any, + name: 'Max Concurrent Tasks', + type: 'number', + defaultValue: 4, + tooltip: 'Maximum number of tasks to run simultaneously', + attrs: { + min: 1, + max: 16 + } + }), + createMockSetting({ + id: 'Comfy.EnableGPUAcceleration' as any, + name: 'GPU Acceleration', + type: 'boolean', + defaultValue: true, + tooltip: 'Enable GPU acceleration for better performance', + experimental: true + }), + createMockSetting({ + id: 'Comfy.CacheSize' as any, + name: 'Cache Size (MB)', + type: 'slider', + defaultValue: 512, + tooltip: 'Amount of memory to use for caching', + attrs: { + min: 128, + max: 2048, + step: 128 + } + }) + ] +} + +export const EmptyPanel: Story = { + args: { + settingGroups: [] + } +} + +export const SingleGroup: Story = { + args: { + settingGroups: [mockGeneralSettings] + } +} + +export const MultipleGroups: Story = { + args: { + settingGroups: [ + mockGeneralSettings, + mockAppearanceSettings, + mockPerformanceSettings + ] + } +} + +export const AppearanceOnly: Story = { + args: { + settingGroups: [mockAppearanceSettings] + } +} + +export const PerformanceOnly: Story = { + args: { + settingGroups: [mockPerformanceSettings] + } +} + +export const MixedInputTypes: Story = { + args: { + settingGroups: [ + { + label: 'Mixed Settings', + settings: [ + createMockSetting({ + id: 'mixed.boolean' as any, + name: 'Boolean Setting', + type: 'boolean', + defaultValue: true + }), + createMockSetting({ + id: 'mixed.text' as any, + name: 'Text Setting', + type: 'text', + defaultValue: 'Default text' + }), + createMockSetting({ + id: 'mixed.number' as any, + name: 'Number Setting', + type: 'number', + defaultValue: 42 + }), + createMockSetting({ + id: 'mixed.slider' as any, + name: 'Slider Setting', + type: 'slider', + defaultValue: 75, + attrs: { min: 0, max: 100 } + }), + createMockSetting({ + id: 'mixed.combo' as any, + name: 'Combo Setting', + type: 'combo', + defaultValue: 'option2', + options: [ + { text: 'Option 1', value: 'option1' }, + { text: 'Option 2', value: 'option2' }, + { text: 'Option 3', value: 'option3' } + ] + }), + createMockSetting({ + id: 'mixed.color' as any, + name: 'Color Setting', + type: 'color', + defaultValue: '#ff6b35' + }) + ] + } + ] + } +} diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 9b1635700..3eb751754 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -16,6 +16,7 @@ "scripts/**/*.js", "scripts/**/*.ts", "tests-ui/**/*.ts", - ".storybook/**/*.ts" + ".storybook/**/*.ts", + "src/**/*.stories.ts" ] }