diff --git a/.gitignore b/.gitignore index 90d01aec13..fba699d5e9 100644 --- a/.gitignore +++ b/.gitignore @@ -190,6 +190,3 @@ installer/update.bat installer/update.sh installer/InvokeAI-Installer/ .aider* - -# sonda build stat visualizer -.sonda/ diff --git a/invokeai/frontend/web/.prettierignore b/invokeai/frontend/web/.prettierignore index fd36f59e47..0f53a0b0a8 100644 --- a/invokeai/frontend/web/.prettierignore +++ b/invokeai/frontend/web/.prettierignore @@ -14,4 +14,3 @@ static/ src/theme/css/overlayscrollbars.css src/theme_/css/overlayscrollbars.css pnpm-lock.yaml -.sonda/ diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 520fc6fe2c..621308b39a 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -150,7 +150,7 @@ "openapi-types": "^12.1.3", "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", - "sonda": "^0.8.2", + "rollup-plugin-visualizer": "^5.14.0", "storybook": "^8.6.12", "tsafe": "^1.8.5", "type-fest": "^4.40.0", diff --git a/invokeai/frontend/web/pnpm-lock.yaml b/invokeai/frontend/web/pnpm-lock.yaml index 16e2aa77c8..4ec994ff3f 100644 --- a/invokeai/frontend/web/pnpm-lock.yaml +++ b/invokeai/frontend/web/pnpm-lock.yaml @@ -283,9 +283,9 @@ devDependencies: prettier: specifier: ^3.5.3 version: 3.5.3 - sonda: - specifier: ^0.8.2 - version: 0.8.2 + rollup-plugin-visualizer: + specifier: ^5.14.0 + version: 5.14.0 storybook: specifier: ^8.6.12 version: 8.6.12(prettier@3.5.3) @@ -3986,13 +3986,6 @@ packages: ieee754: 1.2.1 dev: true - /bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - dependencies: - run-applescript: 7.0.0 - dev: true - /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -4460,19 +4453,6 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true - /default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} - engines: {node: '>=18'} - dev: true - - /default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} - engines: {node: '>=18'} - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.0 - dev: true - /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} requiresBuild: true @@ -4493,11 +4473,6 @@ packages: engines: {node: '>=8'} dev: true - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -5824,12 +5799,6 @@ packages: hasBin: true dev: true - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -5870,14 +5839,6 @@ packages: is-extglob: 2.1.1 dev: true - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -5999,13 +5960,6 @@ packages: is-docker: 2.2.1 dev: true - /is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - dependencies: - is-inside-container: 1.0.0 - dev: true - /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: true @@ -6611,16 +6565,6 @@ packages: mimic-fn: 2.1.0 dev: true - /open@10.1.2: - resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} - engines: {node: '>=18'} - dependencies: - default-browser: 5.2.1 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 3.1.0 - dev: true - /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -7530,6 +7474,25 @@ packages: semver-compare: 1.0.0 dev: false + /rollup-plugin-visualizer@5.14.0: + resolution: {integrity: sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + rolldown: 1.x + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + dependencies: + open: 8.4.2 + picomatch: 4.0.2 + source-map: 0.7.4 + yargs: 17.7.2 + dev: true + /rollup@2.79.2: resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} engines: {node: '>=10.0.0'} @@ -7574,11 +7537,6 @@ packages: '@babel/runtime': 7.27.0 dev: false - /run-applescript@7.0.0: - resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} - engines: {node: '>=18'} - dev: true - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -7784,15 +7742,6 @@ packages: - supports-color dev: false - /sonda@0.8.2: - resolution: {integrity: sha512-OzLlgd4TVjNzhk+Q7NWrdHc4hAU3gchF9u9ZQ4GcQLKk3IX6OTbaf4U7Itq9XssuuCPVVPTl8p0rGAjBHalxsg==} - engines: {node: '>=20.19 || >=22.12'} - hasBin: true - dependencies: - '@ampproject/remapping': 2.3.0 - open: 10.1.2 - dev: true - /source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -7812,6 +7761,11 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + /split-on-first@3.0.0: resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} engines: {node: '>=12'} diff --git a/invokeai/frontend/web/src/common/components/ColorPicker/RgbColorPicker.tsx b/invokeai/frontend/web/src/common/components/ColorPicker/RgbColorPicker.tsx index 54eadf7467..1361039b75 100644 --- a/invokeai/frontend/web/src/common/components/ColorPicker/RgbColorPicker.tsx +++ b/invokeai/frontend/web/src/common/components/ColorPicker/RgbColorPicker.tsx @@ -4,8 +4,8 @@ import { RGB_COLOR_SWATCHES } from 'common/components/ColorPicker/swatches'; import { rgbColorToString } from 'common/util/colorCodeTransformers'; import type { CSSProperties } from 'react'; import { memo, useCallback } from 'react'; -import type { RgbColor } from 'react-colorful'; import { RgbColorPicker as ColorfulRgbColorPicker } from 'react-colorful'; +import type { RgbColor } from 'react-colorful/dist/types'; import { useTranslation } from 'react-i18next'; type Props = { diff --git a/invokeai/frontend/web/src/common/components/ColorPicker/RgbaColorPicker.tsx b/invokeai/frontend/web/src/common/components/ColorPicker/RgbaColorPicker.tsx index 0d1bc4f4aa..fb3b1da2a0 100644 --- a/invokeai/frontend/web/src/common/components/ColorPicker/RgbaColorPicker.tsx +++ b/invokeai/frontend/web/src/common/components/ColorPicker/RgbaColorPicker.tsx @@ -4,8 +4,8 @@ import { RGBA_COLOR_SWATCHES } from 'common/components/ColorPicker/swatches'; import { rgbaColorToString } from 'common/util/colorCodeTransformers'; import type { CSSProperties } from 'react'; import { memo, useCallback } from 'react'; -import type { RgbaColor } from 'react-colorful'; import { RgbaColorPicker as ColorfulRgbaColorPicker } from 'react-colorful'; +import type { RgbaColor } from 'react-colorful/dist/types'; import { useTranslation } from 'react-i18next'; type Props = { diff --git a/invokeai/frontend/web/src/common/components/Picker/Picker.tsx b/invokeai/frontend/web/src/common/components/Picker/Picker.tsx index 9a8251447e..14b2476a45 100644 --- a/invokeai/frontend/web/src/common/components/Picker/Picker.tsx +++ b/invokeai/frontend/web/src/common/components/Picker/Picker.tsx @@ -14,8 +14,9 @@ import { useStore } from '@nanostores/react'; import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent'; import { typedMemo } from 'common/util/typedMemo'; import { NO_DRAG_CLASS, NO_WHEEL_CLASS } from 'features/nodes/types/constants'; -import type { ReadableAtom, WritableAtom } from 'nanostores'; +import type { AnyStore, ReadableAtom, Task, WritableAtom } from 'nanostores'; import { atom, computed } from 'nanostores'; +import type { StoreValues } from 'nanostores/computed'; import type { ChangeEvent, MouseEventHandler, PropsWithChildren, RefObject } from 'react'; import React, { createContext, @@ -471,6 +472,17 @@ const useKeyboardNavigation = () => { return keyboardNavProps; }; +const useAtom = (initialValue: T) => { + return useState(() => atom(initialValue))[0]; +}; + +const useComputed = ( + stores: [...OriginStores], + cb: (...values: StoreValues) => Task | Value +) => { + return useState(() => computed(stores, cb))[0]; +}; + const countOptions = (optionsOrGroups: OptionOrGroup[]) => { let count = 0; for (const optionOrGroup of optionsOrGroups) { @@ -503,20 +515,18 @@ export const Picker = typedMemo((props: PickerProps) => { const rootRef = useRef(null); const inputRef = useRef(null); const { $groupStatusMap, $areAllGroupsDisabled, toggleGroup } = useTogglableGroups(optionsOrGroups); - const $activeOptionId = useState(() => atom(getFirstOptionId(optionsOrGroups, getOptionId)))[0]; - const $compactView = useState(() => atom(true))[0]; - const $optionsOrGroups = useState(() => atom(optionsOrGroups))[0]; - const $totalOptionCount = useState(() => computed([$optionsOrGroups], countOptions))[0]; - const $filteredOptions = useState(() => atom[]>([]))[0]; - const $flattenedFilteredOptions = useState(() => computed([$filteredOptions], flattenOptions))[0]; - const $hasOptions = useState(() => computed([$totalOptionCount], (count) => count > 0))[0]; - const $filteredOptionsCount = useState(() => computed([$flattenedFilteredOptions], (options) => options.length))[0]; - const $hasFilteredOptions = useState(() => computed([$filteredOptionsCount], (count) => count > 0))[0]; - const $selectedItem = useState(() => atom(undefined))[0]; - const $searchTerm = useState(() => atom(''))[0]; - const $selectedItemId = useState(() => - computed([$selectedItem], (item) => (item ? getOptionId(item) : undefined)) - )[0]; + const $activeOptionId = useAtom(getFirstOptionId(optionsOrGroups, getOptionId)); + const $compactView = useAtom(true); + const $optionsOrGroups = useAtom(optionsOrGroups); + const $totalOptionCount = useComputed([$optionsOrGroups], countOptions); + const $filteredOptions = useAtom[]>([]); + const $flattenedFilteredOptions = useComputed([$filteredOptions], flattenOptions); + const $hasOptions = useComputed([$totalOptionCount], (count) => count > 0); + const $filteredOptionsCount = useComputed([$flattenedFilteredOptions], (options) => options.length); + const $hasFilteredOptions = useComputed([$filteredOptionsCount], (count) => count > 0); + const $selectedItem = useAtom(undefined); + const $searchTerm = useAtom(''); + const $selectedItemId = useComputed([$selectedItem], (item) => (item ? getOptionId(item) : undefined)); const onSelectById = useCallback( (id: string) => { @@ -799,17 +809,15 @@ SearchInput.displayName = 'SearchInput'; const GroupToggleButtons = typedMemo(() => { const { $optionsOrGroups, $groupStatusMap, $areAllGroupsDisabled } = usePickerContext(); const { t } = useTranslation(); - const $groups = useState(() => - computed([$optionsOrGroups], (optionsOrGroups) => { - const _groups: Group[] = []; - for (const optionOrGroup of optionsOrGroups) { - if (isGroup(optionOrGroup)) { - _groups.push(optionOrGroup); - } + const $groups = useComputed([$optionsOrGroups], (optionsOrGroups) => { + const _groups: Group[] = []; + for (const optionOrGroup of optionsOrGroups) { + if (isGroup(optionOrGroup)) { + _groups.push(optionOrGroup); } - return _groups; - }) - )[0]; + } + return _groups; + }); const groups = useStore($groups); const areAllGroupsDisabled = useStore($areAllGroupsDisabled); diff --git a/invokeai/frontend/web/tsconfig.json b/invokeai/frontend/web/tsconfig.json index c06be101e0..50de71b68e 100644 --- a/invokeai/frontend/web/tsconfig.json +++ b/invokeai/frontend/web/tsconfig.json @@ -11,7 +11,7 @@ "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", - "moduleResolution": "bundler", + "moduleResolution": "Node", // TODO: Disabled for IDE performance issues with our translation JSON // "resolveJsonModule": true, "noUncheckedIndexedAccess": true, diff --git a/invokeai/frontend/web/tsconfig.node.json b/invokeai/frontend/web/tsconfig.node.json index ec7d7d72ca..046964021f 100644 --- a/invokeai/frontend/web/tsconfig.node.json +++ b/invokeai/frontend/web/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "ESNext", + "moduleResolution": "Node", "allowSyntheticDefaultImports": true }, "include": ["vite.config.mts"] diff --git a/invokeai/frontend/web/vite.config.mts b/invokeai/frontend/web/vite.config.mts index 511e80c7ed..b32fe0fc74 100644 --- a/invokeai/frontend/web/vite.config.mts +++ b/invokeai/frontend/web/vite.config.mts @@ -1,7 +1,8 @@ /// import react from '@vitejs/plugin-react-swc'; import path from 'path'; -import Sonda from 'sonda/vite'; +import { visualizer } from 'rollup-plugin-visualizer'; +import type { PluginOption } from 'vite'; import { defineConfig } from 'vite'; import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'; import dts from 'vite-plugin-dts'; @@ -16,6 +17,7 @@ export default defineConfig(({ mode }) => { react(), eslint(), tsconfigPaths(), + visualizer() as unknown as PluginOption, dts({ insertTypesEntry: true, }), @@ -68,10 +70,9 @@ export default defineConfig(({ mode }) => { react(), mode !== 'test' && eslint({ failOnError: mode === 'production', failOnWarning: mode === 'production' }), tsconfigPaths(), - Sonda(), + visualizer() as unknown as PluginOption, ], build: { - sourcemap: true, chunkSizeWarningLimit: 1500, }, server: {