diff --git a/web/app/components/devtools/react-grab/loader.tsx b/web/app/components/devtools/react-grab/loader.tsx
new file mode 100644
index 0000000000..3a1ecc6be8
--- /dev/null
+++ b/web/app/components/devtools/react-grab/loader.tsx
@@ -0,0 +1,17 @@
+import Script from 'next/script'
+import { IS_DEV } from '@/config'
+
+export function ReactGrabLoader() {
+ if (!IS_DEV)
+ return null
+
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/web/app/layout.tsx b/web/app/layout.tsx
index 2aaa4dc5ce..44af079eea 100644
--- a/web/app/layout.tsx
+++ b/web/app/layout.tsx
@@ -11,6 +11,7 @@ import { cn } from '@/utils/classnames'
import { ToastProvider } from './components/base/toast'
import { TooltipProvider } from './components/base/ui/tooltip'
import BrowserInitializer from './components/browser-initializer'
+import { ReactGrabLoader } from './components/devtools/react-grab/loader'
import { ReactScanLoader } from './components/devtools/react-scan/loader'
import { I18nServerProvider } from './components/provider/i18n-server'
import SentryInitializer from './components/sentry-initializer'
@@ -56,6 +57,7 @@ const LocaleLayout = async ({
+
{
+ const i18nHmrClientMarker = 'custom-i18n-hmr-client'
+ const i18nHmrClientSnippet = `/* ${i18nHmrClientMarker} */
+if (import.meta.hot) {
+ const getI18nUpdateTarget = (file) => {
+ const match = file.match(/[/\\\\]i18n[/\\\\]([^/\\\\]+)[/\\\\]([^/\\\\]+)\\.json$/)
+ if (!match)
+ return null
+ const [, locale, namespaceFile] = match
+ return { locale, namespaceFile }
+ }
+
+ import.meta.hot.on('i18n-update', async ({ file, content }) => {
+ const target = getI18nUpdateTarget(file)
+ if (!target)
+ return
+
+ const [{ getI18n }, { camelCase }] = await Promise.all([
+ import('react-i18next'),
+ import('es-toolkit/string'),
+ ])
+
+ const i18n = getI18n()
+ if (!i18n)
+ return
+ if (target.locale !== i18n.language)
+ return
+
+ let resources
+ try {
+ resources = JSON.parse(content)
+ }
+ catch {
+ return
+ }
+
+ const namespace = camelCase(target.namespaceFile)
+ i18n.addResourceBundle(target.locale, namespace, resources, true, true)
+ i18n.emit('languageChanged', i18n.language)
+ })
+}
+`
+
+ return {
+ name: 'custom-i18n-hmr',
+ apply: 'serve',
+ handleHotUpdate({ file, server }) {
+ if (file.endsWith('.json') && file.includes('/i18n/')) {
+ server.ws.send({
+ type: 'custom',
+ event: 'i18n-update',
+ data: {
+ file,
+ content: fs.readFileSync(file, 'utf-8'),
+ },
+ })
+
+ return []
+ }
+ },
+ transform(code, id) {
+ const cleanId = normalizeViteModuleId(id)
+ if (cleanId !== injectTarget)
+ return null
+
+ const nextCode = injectClientSnippet(code, i18nHmrClientMarker, i18nHmrClientSnippet)
+ if (nextCode === code)
+ return null
+ return { code: nextCode, map: null }
+ },
+ }
+}
diff --git a/web/plugins/vite/react-grab-open-file.ts b/web/plugins/vite/react-grab-open-file.ts
new file mode 100644
index 0000000000..42e0ace3af
--- /dev/null
+++ b/web/plugins/vite/react-grab-open-file.ts
@@ -0,0 +1,92 @@
+import type { Plugin } from 'vite'
+import { injectClientSnippet, normalizeViteModuleId } from './utils'
+
+type ReactGrabOpenFilePluginOptions = {
+ injectTarget: string
+ projectRoot: string
+}
+
+export const reactGrabOpenFilePlugin = ({
+ injectTarget,
+ projectRoot,
+}: ReactGrabOpenFilePluginOptions): Plugin => {
+ const reactGrabOpenFileClientMarker = 'react-grab-open-file-client'
+ const reactGrabOpenFileClientSnippet = `/* ${reactGrabOpenFileClientMarker} */
+if (typeof window !== 'undefined') {
+ const projectRoot = ${JSON.stringify(projectRoot)};
+ const pluginName = 'dify-vite-open-file';
+ const rootRelativeSourcePathPattern = /^\\/(?!@|node_modules)(?:.+)\\.(?:[cm]?[jt]sx?|mdx?)$/;
+
+ const normalizeProjectRoot = (input) => {
+ return input.endsWith('/') ? input.slice(0, -1) : input;
+ };
+
+ const resolveFilePath = (filePath) => {
+ if (filePath.startsWith('/@fs/')) {
+ return filePath.slice('/@fs'.length);
+ }
+
+ if (!rootRelativeSourcePathPattern.test(filePath)) {
+ return filePath;
+ }
+
+ const normalizedProjectRoot = normalizeProjectRoot(projectRoot);
+ if (filePath.startsWith(normalizedProjectRoot)) {
+ return filePath;
+ }
+
+ return \`\${normalizedProjectRoot}\${filePath}\`;
+ };
+
+ const registerPlugin = () => {
+ if (window.__DIFY_REACT_GRAB_OPEN_FILE_PLUGIN_REGISTERED__) {
+ return;
+ }
+
+ const reactGrab = window.__REACT_GRAB__;
+ if (!reactGrab) {
+ return;
+ }
+
+ reactGrab.registerPlugin({
+ name: pluginName,
+ hooks: {
+ onOpenFile(filePath, lineNumber) {
+ const params = new URLSearchParams({
+ file: resolveFilePath(filePath),
+ column: '1',
+ });
+
+ if (lineNumber) {
+ params.set('line', String(lineNumber));
+ }
+
+ void fetch(\`/__open-in-editor?\${params.toString()}\`);
+ return true;
+ },
+ },
+ });
+
+ window.__DIFY_REACT_GRAB_OPEN_FILE_PLUGIN_REGISTERED__ = true;
+ };
+
+ registerPlugin();
+ window.addEventListener('react-grab:init', registerPlugin);
+}
+`
+
+ return {
+ name: 'react-grab-open-file',
+ apply: 'serve',
+ transform(code, id) {
+ const cleanId = normalizeViteModuleId(id)
+ if (cleanId !== injectTarget)
+ return null
+
+ const nextCode = injectClientSnippet(code, reactGrabOpenFileClientMarker, reactGrabOpenFileClientSnippet)
+ if (nextCode === code)
+ return null
+ return { code: nextCode, map: null }
+ },
+ }
+}
diff --git a/web/plugins/vite/utils.ts b/web/plugins/vite/utils.ts
new file mode 100644
index 0000000000..52bcc5bbbe
--- /dev/null
+++ b/web/plugins/vite/utils.ts
@@ -0,0 +1,20 @@
+export const normalizeViteModuleId = (id: string): string => {
+ const withoutQuery = id.split('?', 1)[0]
+
+ if (withoutQuery.startsWith('/@fs/'))
+ return withoutQuery.slice('/@fs'.length)
+
+ return withoutQuery
+}
+
+export const injectClientSnippet = (code: string, marker: string, snippet: string): string => {
+ if (code.includes(marker))
+ return code
+
+ const useClientMatch = code.match(/(['"])use client\1;?\s*\n/)
+ if (!useClientMatch)
+ return `${snippet}\n${code}`
+
+ const insertAt = (useClientMatch.index ?? 0) + useClientMatch[0].length
+ return `${code.slice(0, insertAt)}\n${snippet}\n${code.slice(insertAt)}`
+}
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index 77109cdbb3..0308a68d2d 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -215,7 +215,7 @@ importers:
version: 11.1.0
jotai:
specifier: 2.16.1
- version: 2.16.1(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4)
+ version: 2.16.1(@babel/core@7.28.6)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4)
js-audio-recorder:
specifier: 1.0.7
version: 1.0.7
@@ -254,13 +254,13 @@ importers:
version: 1.0.0
next:
specifier: 16.1.5
- version: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
+ version: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
next-themes:
specifier: 0.4.6
version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
nuqs:
specifier: 2.8.6
- version: 2.8.6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4)
+ version: 2.8.6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4)
pinyin-pro:
specifier: 3.27.0
version: 3.27.0
@@ -420,7 +420,7 @@ importers:
version: 10.2.13(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
'@storybook/nextjs-vite':
specifier: 10.2.13
- version: 10.2.13(@babel/core@7.29.0)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
+ version: 10.2.13(@babel/core@7.28.6)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
'@storybook/react':
specifier: 10.2.13
version: 10.2.13(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
@@ -517,9 +517,6 @@ importers:
autoprefixer:
specifier: 10.4.21
version: 10.4.21(postcss@8.5.6)
- code-inspector-plugin:
- specifier: 1.3.6
- version: 1.3.6
cross-env:
specifier: 10.1.0
version: 10.1.0
@@ -571,9 +568,6 @@ importers:
postcss-js:
specifier: 5.0.3
version: 5.0.3(postcss@8.5.6)
- react-scan:
- specifier: 0.5.3
- version: 0.5.3(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)
react-server-dom-webpack:
specifier: 19.2.4
version: 19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
@@ -597,7 +591,7 @@ importers:
version: 3.19.3
vinext:
specifier: https://pkg.pr.new/hyoban/vinext@556a6d6
- version: https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
+ version: https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
vite:
specifier: 8.0.0-beta.16
version: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
@@ -955,24 +949,6 @@ packages:
'@clack/prompts@1.0.1':
resolution: {integrity: sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==}
- '@code-inspector/core@1.3.6':
- resolution: {integrity: sha512-bSxf/PWDPY6rv9EFf0mJvTnLnz3927PPrpX6BmQcRKQab+Ez95yRqrVZY8IcBUpaqA/k3etA5rZ1qkN0V4ERtw==}
-
- '@code-inspector/esbuild@1.3.6':
- resolution: {integrity: sha512-s35dseBXI2yqfX6ZK29Ix941jaE/4KPlZZeMk6B5vDahj75FDUfVxQ7ORy4cX2hyz8CmlOycsY/au5mIvFpAFg==}
-
- '@code-inspector/mako@1.3.6':
- resolution: {integrity: sha512-FJvuTElOi3TUCWTIaYTFYk2iTUD6MlO51SC8SYfwmelhuvnOvTMa2TkylInX16OGb4f7sGNLRj2r+7NNx/gqpw==}
-
- '@code-inspector/turbopack@1.3.6':
- resolution: {integrity: sha512-pfXgvZCn4/brpTvqy8E0HTe6V/ksVKEPQo697Nt5k22kBnlEM61UT3rI2Art+fDDEMPQTxVOFpdbwCKSLwMnmQ==}
-
- '@code-inspector/vite@1.3.6':
- resolution: {integrity: sha512-vXYvzGc0S1NR4p3BeD1Xx2170OnyecZD0GtebLlTiHw/cetzlrBHVpbkIwIEzzzpTYYshwwDt8ZbuvdjmqhHgw==}
-
- '@code-inspector/webpack@1.3.6':
- resolution: {integrity: sha512-bi/+vsym9d6NXQQ++Phk74VLMiVoGKjgPHr445j/D43URG8AN8yYa+gRDBEDcZx4B128dihrVMxEO8+OgWGjTw==}
-
'@csstools/color-helpers@5.1.0':
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
engines: {node: '>=18'}
@@ -2188,11 +2164,6 @@ packages:
'@preact/signals-core@1.12.2':
resolution: {integrity: sha512-5Yf8h1Ke3SMHr15xl630KtwPTW4sYDFkkxS0vQ8UiQLWwZQnrF9IKaVG1mN5VcJz52EcWs2acsc/Npjha/7ysA==}
- '@preact/signals@1.3.2':
- resolution: {integrity: sha512-naxcJgUJ6BTOROJ7C3QML7KvwKwCXQJYTc5L/b0eEsdYgPB6SxwoQ1vDGcS0Q7GVjAenVq/tXrybVdFShHYZWg==}
- peerDependencies:
- preact: 10.x
-
'@radix-ui/primitive@1.1.3':
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
@@ -3295,9 +3266,6 @@ packages:
'@types/negotiator@0.6.4':
resolution: {integrity: sha512-elf6BsTq+AkyNsb2h5cGNst2Mc7dPliVoAPm1fXglC/BM3f2pFA40BaSSv3E5lyHteEawVKLP+8TwiY1DMNb3A==}
- '@types/node@20.19.30':
- resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==}
-
'@types/node@24.10.12':
resolution: {integrity: sha512-68e+T28EbdmLSTkPgs3+UacC6rzmqrcWFPQs1C8mwJhI/r5Uxr0yEuQotczNRROd1gq30NGxee+fo0rSIxpyAw==}
@@ -3315,11 +3283,6 @@ packages:
peerDependencies:
'@types/react': ^19.2.0
- '@types/react-reconciler@0.28.9':
- resolution: {integrity: sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==}
- peerDependencies:
- '@types/react': '*'
-
'@types/react-slider@1.3.6':
resolution: {integrity: sha512-RS8XN5O159YQ6tu3tGZIQz1/9StMLTg/FCIPxwqh2gwVixJnlfIodtVx+fpXVMZHe7A58lAX1Q4XTgAGOQaCQg==}
@@ -3818,9 +3781,6 @@ packages:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
- async@3.2.6:
- resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
-
autoprefixer@10.4.21:
resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -3862,11 +3822,6 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
- bippy@0.5.30:
- resolution: {integrity: sha512-8CFmJAHD3gmTLDOCDHuWhjm1nxHSFZdlGoWtak9r53Uxn36ynOjxBLyxXHh/7h/XiKLyPvfdXa0gXWcD9o9lLQ==}
- peerDependencies:
- react: '>=17.0.1'
-
birecord@0.1.1:
resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==}
@@ -3949,10 +3904,6 @@ packages:
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
engines: {node: '>=18'}
- chalk@4.1.1:
- resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==}
- engines: {node: '>=10'}
-
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@@ -4077,9 +4028,6 @@ packages:
react: ^18 || ^19 || ^19.0.0-rc
react-dom: ^18 || ^19 || ^19.0.0-rc
- code-inspector-plugin@1.3.6:
- resolution: {integrity: sha512-ddTg8embDqLZxKEdSNOm+/0YnVVgWKr10+Bu2qFqQDObj/3twGh0Z23TIz+5/URxfRhTPbp2sUSpWlw78piJbQ==}
-
collapse-white-space@2.1.0:
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
@@ -4110,10 +4058,6 @@ packages:
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
engines: {node: '>=18'}
- commander@14.0.3:
- resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
- engines: {node: '>=20'}
-
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -4499,10 +4443,6 @@ packages:
domutils@3.2.2:
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
- dotenv@16.6.1:
- resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
- engines: {node: '>=12'}
-
echarts-for-react@3.0.5:
resolution: {integrity: sha512-YpEI5Ty7O/2nvCfQ7ybNa+S90DwE8KYZWacGvJW4luUqywP7qStQ+pxDlYOmr4jGDu10mhEkiAuMKcUlT4W5vg==}
peerDependencies:
@@ -5612,10 +5552,6 @@ packages:
khroma@2.1.0:
resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
- kleur@3.0.3:
- resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
- engines: {node: '>=6'}
-
knip@5.78.0:
resolution: {integrity: sha512-nB7i/fgiJl7WVxdv5lX4ZPfDt9/zrw/lOgZtyioy988xtFhKuFJCRdHWT1Zg9Avc0yaojvnmEuAXU8SeMblKww==}
engines: {node: '>=18.18.0'}
@@ -5638,9 +5574,6 @@ packages:
resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==}
engines: {node: '>=16.0.0'}
- launch-ide@1.4.0:
- resolution: {integrity: sha512-c2mcqZy7mNhzXiWoBFV0lDsEOfpSFGqqxKubPffhqcnv3GV0xpeGcHWLxYFm+jz1/5VAKp796QkyVV4++07eiw==}
-
layout-base@1.0.2:
resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
@@ -6416,10 +6349,6 @@ packages:
points-on-path@0.2.1:
resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
- portfinder@1.0.38:
- resolution: {integrity: sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==}
- engines: {node: '>= 10.12'}
-
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@@ -6506,10 +6435,6 @@ packages:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
- prompts@2.4.2:
- resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
- engines: {node: '>= 6'}
-
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -6678,13 +6603,6 @@ packages:
react: '>=16.3.0'
react-dom: '>=16.3.0'
- react-scan@0.5.3:
- resolution: {integrity: sha512-qde9PupmUf0L3MU1H6bjmoukZNbCXdMyTEwP4Gh8RQ4rZPd2GGNBgEKWszwLm96E8k+sGtMpc0B9P0KyFDP6Bw==}
- hasBin: true
- peerDependencies:
- 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
-
react-server-dom-webpack@19.2.4:
resolution: {integrity: sha512-zEhkWv6RhXDctC2N7yEUHg3751nvFg81ydHj8LTTZuukF/IF1gcOKqqAL6Ds+kS5HtDVACYPik0IvzkgYXPhlQ==}
engines: {node: '>=0.10.0'}
@@ -7401,9 +7319,6 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
- undici-types@6.21.0:
- resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
-
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
@@ -7455,10 +7370,6 @@ packages:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
- unplugin@2.1.0:
- resolution: {integrity: sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==}
- engines: {node: '>=18.12.0'}
-
unplugin@2.3.11:
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
engines: {node: '>=18.12.0'}
@@ -8467,48 +8378,6 @@ snapshots:
picocolors: 1.1.1
sisteransi: 1.0.5
- '@code-inspector/core@1.3.6':
- dependencies:
- '@vue/compiler-dom': 3.5.27
- chalk: 4.1.2
- dotenv: 16.6.1
- launch-ide: 1.4.0
- portfinder: 1.0.38
- transitivePeerDependencies:
- - supports-color
-
- '@code-inspector/esbuild@1.3.6':
- dependencies:
- '@code-inspector/core': 1.3.6
- transitivePeerDependencies:
- - supports-color
-
- '@code-inspector/mako@1.3.6':
- dependencies:
- '@code-inspector/core': 1.3.6
- transitivePeerDependencies:
- - supports-color
-
- '@code-inspector/turbopack@1.3.6':
- dependencies:
- '@code-inspector/core': 1.3.6
- '@code-inspector/webpack': 1.3.6
- transitivePeerDependencies:
- - supports-color
-
- '@code-inspector/vite@1.3.6':
- dependencies:
- '@code-inspector/core': 1.3.6
- chalk: 4.1.1
- transitivePeerDependencies:
- - supports-color
-
- '@code-inspector/webpack@1.3.6':
- dependencies:
- '@code-inspector/core': 1.3.6
- transitivePeerDependencies:
- - supports-color
-
'@csstools/color-helpers@5.1.0': {}
'@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
@@ -9752,11 +9621,6 @@ snapshots:
'@preact/signals-core@1.12.2': {}
- '@preact/signals@1.3.2(preact@10.28.2)':
- dependencies:
- '@preact/signals-core': 1.12.2
- preact: 10.28.2
-
'@radix-ui/primitive@1.1.3': {}
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.9)(react@19.2.4)':
@@ -10329,18 +10193,18 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
- '@storybook/nextjs-vite@10.2.13(@babel/core@7.29.0)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))':
+ '@storybook/nextjs-vite@10.2.13(@babel/core@7.28.6)(esbuild@0.27.2)(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))':
dependencies:
'@storybook/builder-vite': 10.2.13(esbuild@0.27.2)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
'@storybook/react': 10.2.13(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
'@storybook/react-vite': 10.2.13(esbuild@0.27.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0)(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3))
- next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
+ next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
storybook: 10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
- styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4)
+ styled-jsx: 5.1.6(@babel/core@7.28.6)(react@19.2.4)
vite: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
- vite-plugin-storybook-nextjs: 3.2.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
+ vite-plugin-storybook-nextjs: 3.2.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
@@ -10869,10 +10733,6 @@ snapshots:
'@types/negotiator@0.6.4': {}
- '@types/node@20.19.30':
- dependencies:
- undici-types: 6.21.0
-
'@types/node@24.10.12':
dependencies:
undici-types: 7.16.0
@@ -10891,10 +10751,6 @@ snapshots:
dependencies:
'@types/react': 19.2.9
- '@types/react-reconciler@0.28.9(@types/react@19.2.9)':
- dependencies:
- '@types/react': 19.2.9
-
'@types/react-slider@1.3.6':
dependencies:
'@types/react': 19.2.9
@@ -11138,13 +10994,13 @@ snapshots:
dependencies:
unpic: 4.2.2
- '@unpic/react@1.0.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ '@unpic/react@1.0.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@unpic/core': 1.0.3
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
optionalDependencies:
- next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
+ next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
'@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))':
dependencies:
@@ -11286,7 +11142,7 @@ snapshots:
'@vue/compiler-core@3.5.27':
dependencies:
- '@babel/parser': 7.28.6
+ '@babel/parser': 7.29.0
'@vue/shared': 3.5.27
entities: 7.0.1
estree-walker: 2.0.2
@@ -11522,8 +11378,6 @@ snapshots:
astring@1.9.0: {}
- async@3.2.6: {}
-
autoprefixer@10.4.21(postcss@8.5.6):
dependencies:
browserslist: 4.28.1
@@ -11557,13 +11411,6 @@ snapshots:
binary-extensions@2.3.0: {}
- bippy@0.5.30(@types/react@19.2.9)(react@19.2.4):
- dependencies:
- '@types/react-reconciler': 0.28.9(@types/react@19.2.9)
- react: 19.2.4
- transitivePeerDependencies:
- - '@types/react'
-
birecord@0.1.1: {}
birpc@2.9.0: {}
@@ -11641,11 +11488,6 @@ snapshots:
chai@6.2.2: {}
- chalk@4.1.1:
- dependencies:
- ansi-styles: 4.3.0
- supports-color: 7.2.0
-
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
@@ -11774,18 +11616,6 @@ snapshots:
- '@types/react'
- '@types/react-dom'
- code-inspector-plugin@1.3.6:
- dependencies:
- '@code-inspector/core': 1.3.6
- '@code-inspector/esbuild': 1.3.6
- '@code-inspector/mako': 1.3.6
- '@code-inspector/turbopack': 1.3.6
- '@code-inspector/vite': 1.3.6
- '@code-inspector/webpack': 1.3.6
- chalk: 4.1.1
- transitivePeerDependencies:
- - supports-color
-
collapse-white-space@2.1.0: {}
color-convert@2.0.1:
@@ -11812,8 +11642,6 @@ snapshots:
commander@13.1.0: {}
- commander@14.0.3: {}
-
commander@2.20.3: {}
commander@4.1.1: {}
@@ -12203,8 +12031,6 @@ snapshots:
domelementtype: 2.3.0
domhandler: 5.0.3
- dotenv@16.6.1: {}
-
echarts-for-react@3.0.5(echarts@5.6.0)(react@19.2.4):
dependencies:
echarts: 5.6.0
@@ -13440,9 +13266,9 @@ snapshots:
jiti@2.6.1: {}
- jotai@2.16.1(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4):
+ jotai@2.16.1(@babel/core@7.28.6)(@babel/template@7.28.6)(@types/react@19.2.9)(react@19.2.4):
optionalDependencies:
- '@babel/core': 7.29.0
+ '@babel/core': 7.28.6
'@babel/template': 7.28.6
'@types/react': 19.2.9
react: 19.2.4
@@ -13541,8 +13367,6 @@ snapshots:
khroma@2.1.0: {}
- kleur@3.0.3: {}
-
knip@5.78.0(@types/node@24.10.12)(typescript@5.9.3):
dependencies:
'@nodelib/fs.walk': 1.2.8
@@ -13576,11 +13400,6 @@ snapshots:
vscode-languageserver-textdocument: 1.0.12
vscode-uri: 3.0.8
- launch-ide@1.4.0:
- dependencies:
- chalk: 4.1.2
- dotenv: 16.6.1
-
layout-base@1.0.2: {}
layout-base@2.0.1: {}
@@ -14365,7 +14184,7 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
- next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2):
+ next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2):
dependencies:
'@next/env': 16.1.5
'@swc/helpers': 0.5.15
@@ -14374,7 +14193,7 @@ snapshots:
postcss: 8.4.31
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
- styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4)
+ styled-jsx: 5.1.6(@babel/core@7.28.6)(react@19.2.4)
optionalDependencies:
'@next/swc-darwin-arm64': 16.1.5
'@next/swc-darwin-x64': 16.1.5
@@ -14420,12 +14239,12 @@ snapshots:
dependencies:
boolbase: 1.0.0
- nuqs@2.8.6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4):
+ nuqs@2.8.6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react@19.2.4):
dependencies:
'@standard-schema/spec': 1.0.0
react: 19.2.4
optionalDependencies:
- next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
+ next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
object-assign@4.1.1: {}
@@ -14637,13 +14456,6 @@ snapshots:
path-data-parser: 0.1.0
points-on-curve: 0.2.0
- portfinder@1.0.38:
- dependencies:
- async: 3.2.6
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
postcss-import@15.1.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
@@ -14703,7 +14515,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
- preact@10.28.2: {}
+ preact@10.28.2:
+ optional: true
prebuild-install@7.1.3:
dependencies:
@@ -14731,11 +14544,6 @@ snapshots:
prismjs@1.30.0: {}
- prompts@2.4.2:
- dependencies:
- kleur: 3.0.3
- sisteransi: 1.0.5
-
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@@ -14918,30 +14726,6 @@ snapshots:
react-draggable: 4.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
tslib: 2.6.2
- react-scan@0.5.3(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.56.0):
- dependencies:
- '@babel/core': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/types': 7.29.0
- '@preact/signals': 1.3.2(preact@10.28.2)
- '@rollup/pluginutils': 5.3.0(rollup@4.56.0)
- '@types/node': 20.19.30
- bippy: 0.5.30(@types/react@19.2.9)(react@19.2.4)
- commander: 14.0.3
- esbuild: 0.27.2
- estree-walker: 3.0.3
- picocolors: 1.1.1
- preact: 10.28.2
- prompts: 2.4.2
- react: 19.2.4
- react-dom: 19.2.4(react@19.2.4)
- optionalDependencies:
- unplugin: 2.1.0
- transitivePeerDependencies:
- - '@types/react'
- - rollup
- - supports-color
-
react-server-dom-webpack@19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
dependencies:
acorn-loose: 8.5.2
@@ -15561,12 +15345,12 @@ snapshots:
dependencies:
inline-style-parser: 0.2.7
- styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4):
+ styled-jsx@5.1.6(@babel/core@7.28.6)(react@19.2.4):
dependencies:
client-only: 0.0.1
react: 19.2.4
optionalDependencies:
- '@babel/core': 7.29.0
+ '@babel/core': 7.28.6
stylis@4.3.6: {}
@@ -15819,8 +15603,6 @@ snapshots:
uglify-js@3.19.3: {}
- undici-types@6.21.0: {}
-
undici-types@7.16.0: {}
undici@7.21.0: {}
@@ -15888,12 +15670,6 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
- unplugin@2.1.0:
- dependencies:
- acorn: 8.16.0
- webpack-virtual-modules: 0.6.2
- optional: true
-
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -15981,9 +15757,9 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
- vinext@https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
+ vinext@https://pkg.pr.new/hyoban/vinext@556a6d6(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)):
dependencies:
- '@unpic/react': 1.0.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ '@unpic/react': 1.0.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@vercel/og': 0.8.6
'@vitejs/plugin-rsc': 0.5.21(react-dom@19.2.4(react@19.2.4))(react-server-dom-webpack@19.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)))(react@19.2.4)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
magic-string: 0.30.21
@@ -16038,13 +15814,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- vite-plugin-storybook-nextjs@3.2.2(next@16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
+ vite-plugin-storybook-nextjs@3.2.2(next@16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2))(storybook@10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
dependencies:
'@next/env': 16.0.0
image-size: 2.0.2
magic-string: 0.30.21
module-alias: 2.3.4
- next: 16.1.5(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
+ next: 16.1.5(@babel/core@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.93.2)
storybook: 10.2.13(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
ts-dedent: 2.2.0
vite: 8.0.0-beta.16(@types/node@24.10.12)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
diff --git a/web/vite.config.ts b/web/vite.config.ts
index 83a35f8558..cbe8eb31c9 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -1,162 +1,16 @@
-import type { Plugin } from 'vite'
-import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import react from '@vitejs/plugin-react'
-import { codeInspectorPlugin } from 'code-inspector-plugin'
import vinext from 'vinext'
import { defineConfig } from 'vite'
import Inspect from 'vite-plugin-inspect'
import tsconfigPaths from 'vite-tsconfig-paths'
+import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
+import { reactGrabOpenFilePlugin } from './plugins/vite/react-grab-open-file'
-const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const projectRoot = path.dirname(fileURLToPath(import.meta.url))
const isCI = !!process.env.CI
-const inspectorPort = 5678
-const inspectorInjectTarget = path.resolve(__dirname, 'app/components/browser-initializer.tsx')
-const inspectorRuntimeFile = path.resolve(
- __dirname,
- `node_modules/code-inspector-plugin/dist/append-code-${inspectorPort}.js`,
-)
-
-const getInspectorRuntimeSnippet = (): string => {
- if (!fs.existsSync(inspectorRuntimeFile))
- return ''
-
- const raw = fs.readFileSync(inspectorRuntimeFile, 'utf-8')
- // Remove the helper module default export from append file to avoid duplicate default exports.
- return raw.replace(
- /\s*export default function CodeInspectorEmptyElement\(\)\s*\{[\s\S]*$/,
- '',
- )
-}
-
-const normalizeInspectorModuleId = (id: string): string => {
- const withoutQuery = id.split('?', 1)[0]
-
- // Vite/vinext may pass absolute fs modules as "/@fs/".
- if (withoutQuery.startsWith('/@fs/'))
- return withoutQuery.slice('/@fs'.length)
-
- return withoutQuery
-}
-
-const createCodeInspectorPlugin = (): Plugin => {
- return codeInspectorPlugin({
- bundler: 'vite',
- port: inspectorPort,
- injectTo: inspectorInjectTarget,
- exclude: [/^(?!.*\.(?:js|ts|mjs|mts|jsx|tsx|vue|svelte|html)(?:$|\?)).*/],
- }) as Plugin
-}
-
-const createForceInspectorClientInjectionPlugin = (): Plugin => {
- const clientSnippet = getInspectorRuntimeSnippet()
-
- return {
- name: 'vinext-force-code-inspector-client',
- apply: 'serve',
- enforce: 'pre',
- transform(code, id) {
- if (!clientSnippet)
- return null
-
- const cleanId = normalizeInspectorModuleId(id)
- if (cleanId !== inspectorInjectTarget)
- return null
- if (code.includes('code-inspector-component'))
- return null
-
- return `${clientSnippet}\n${code}`
- },
- }
-}
-
-function customI18nHmrPlugin(): Plugin {
- const injectTarget = inspectorInjectTarget
- const i18nHmrClientMarker = 'custom-i18n-hmr-client'
- const i18nHmrClientSnippet = `/* ${i18nHmrClientMarker} */
-if (import.meta.hot) {
- const getI18nUpdateTarget = (file) => {
- const match = file.match(/[/\\\\]i18n[/\\\\]([^/\\\\]+)[/\\\\]([^/\\\\]+)\\.json$/)
- if (!match)
- return null
- const [, locale, namespaceFile] = match
- return { locale, namespaceFile }
- }
-
- import.meta.hot.on('i18n-update', async ({ file, content }) => {
- const target = getI18nUpdateTarget(file)
- if (!target)
- return
-
- const [{ getI18n }, { camelCase }] = await Promise.all([
- import('react-i18next'),
- import('es-toolkit/string'),
- ])
-
- const i18n = getI18n()
- if (!i18n)
- return
- if (target.locale !== i18n.language)
- return
-
- let resources
- try {
- resources = JSON.parse(content)
- }
- catch {
- return
- }
-
- const namespace = camelCase(target.namespaceFile)
- i18n.addResourceBundle(target.locale, namespace, resources, true, true)
- i18n.emit('languageChanged', i18n.language)
- })
-}
-`
-
- const injectI18nHmrClient = (code: string) => {
- if (code.includes(i18nHmrClientMarker))
- return code
-
- const useClientMatch = code.match(/(['"])use client\1;?\s*\n/)
- if (!useClientMatch)
- return `${i18nHmrClientSnippet}\n${code}`
-
- const insertAt = (useClientMatch.index ?? 0) + useClientMatch[0].length
- return `${code.slice(0, insertAt)}\n${i18nHmrClientSnippet}\n${code.slice(insertAt)}`
- }
-
- return {
- name: 'custom-i18n-hmr',
- apply: 'serve',
- handleHotUpdate({ file, server }) {
- if (file.endsWith('.json') && file.includes('/i18n/')) {
- server.ws.send({
- type: 'custom',
- event: 'i18n-update',
- data: {
- file,
- content: fs.readFileSync(file, 'utf-8'),
- },
- })
-
- // return empty array to prevent the default HMR
- return []
- }
- },
- transform(code, id) {
- const cleanId = normalizeInspectorModuleId(id)
- if (cleanId !== injectTarget)
- return null
-
- const nextCode = injectI18nHmrClient(code)
- if (nextCode === code)
- return null
- return { code: nextCode, map: null }
- },
- }
-}
+const browserInitializerInjectTarget = path.resolve(projectRoot, 'app/components/browser-initializer.tsx')
export default defineConfig(({ mode }) => {
const isTest = mode === 'test'
@@ -176,7 +30,7 @@ export default defineConfig(({ mode }) => {
if (id.endsWith('.mdx'))
return { code: 'export default () => null', map: null }
},
- } as Plugin,
+ },
]
: isStorybook
? [
@@ -185,15 +39,17 @@ export default defineConfig(({ mode }) => {
]
: [
Inspect(),
- createCodeInspectorPlugin(),
- createForceInspectorClientInjectionPlugin(),
react(),
vinext(),
- customI18nHmrPlugin(),
+ customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
+ reactGrabOpenFilePlugin({
+ injectTarget: browserInitializerInjectTarget,
+ projectRoot,
+ }),
],
resolve: {
alias: {
- '~@': __dirname,
+ '~@': projectRoot,
},
},