From f79d115231077aa9b8b7188f82bd5a43551b2254 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Mon, 18 Nov 2024 15:13:42 +0100 Subject: [PATCH 01/91] wip: working version with vite --- .storybook/main.ts | 195 +-- package.json | 17 +- yarn.lock | 2863 ++++++++++---------------------------------- 3 files changed, 792 insertions(+), 2283 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index e15763f77a8..24b3d871ee0 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,4 +1,4 @@ -import { StorybookConfig } from '@storybook/react-webpack5'; +import type { StorybookConfig } from '@storybook/react-vite'; import fs from 'fs'; import path, { dirname, join } from 'path'; @@ -12,79 +12,140 @@ const config: StorybookConfig = { ), ], addons: [ - '@storybook/addon-webpack5-compiler-babel', + // '@storybook/addon-storysource', + { + name: '@storybook/addon-storysource', + options: { + loaderOptions: { + injectStoryParameters: false, + }, + }, + }, + // '@storybook/addon-webpack5-compiler-babel', + // '@storybook/addon-storysource', + // { + // name: '@storybook/addon-storysource', + // options: { + // loaderOptions: { + // parser: 'typescript', + // }, + // }, + // }, + // { + // name: '@storybook/addon-storysource', + // options: { + // rule: { + // include: [ + // path.resolve( + // __dirname, + // `../packages/${process.env.ONLY || '**'}/**/*.stories.@(tsx)` + // ), + // ], + // }, + // loaderOptions: { + // parser: 'typescript', + // injectStoryParameters: false, + // }, + // }, + // }, '@storybook/addon-actions', '@storybook/addon-controls', ], - typescript: { - check: false, - reactDocgen: false, - }, - babel: async options => { - const { plugins = [] } = options; - return { - ...options, - presets: [ - '@babel/preset-env', - '@babel/preset-react', - '@babel/preset-typescript', - ], - plugins: [ - ...plugins, - [ - '@babel/plugin-proposal-private-property-in-object', - { - loose: true, - }, - ], - [ - '@babel/plugin-proposal-private-methods', - { - loose: true, - }, - ], - [ - '@babel/plugin-proposal-class-properties', - { - loose: true, - }, - ], - ], - }; + // typescript: { + // check: false, + // reactDocgen: 'react-docgen-typescript', // TEST + // }, + // babel: async options => { + // const { plugins = [] } = options; + // return { + // ...options, + // presets: [ + // '@babel/preset-env', + // '@babel/preset-react', + // '@babel/preset-typescript', + // ], + // plugins: [ + // ...plugins, + // [ + // '@babel/plugin-proposal-private-property-in-object', + // { + // loose: true, + // }, + // ], + // [ + // '@babel/plugin-proposal-private-methods', + // { + // loose: true, + // }, + // ], + // [ + // '@babel/plugin-proposal-class-properties', + // { + // loose: true, + // }, + // ], + // ], + // }; + // }, + // webpackFinal: async (config, { configType }) => { + // // config.module?.rules?.push({ + // // test: /\.stories\.tsx?$/, + // // use: [ + // // { + // // loader: require.resolve('@storybook/source-loader'), + // // options: { parser: 'typescript' }, + // // }, + // // ], + // // enforce: 'pre', + // // }); + // return { + // ...config, + // resolve: { + // ...config.resolve, + // alias: packages.reduce( + // (acc, pkg) => ({ + // ...acc, + // [pkg]: path.resolve( + // __dirname, + // `../packages/${pkg}/src` + // ), + // }), + // { ...config.resolve?.alias } + // ), + // plugins: [ + // ...(config.resolve?.plugins || []), + // new TsconfigPathsPlugin({ + // extensions: config.resolve?.extensions, + // }), + // ], + // }, + // }; + // }, + // framework: { + // name: getAbsolutePath('@storybook/react-webpack5'), + // options: {}, + // }, + framework: { + name: '@storybook/react-vite', + options: {}, }, - webpackFinal: async (config, { configType }) => { - config.module?.rules?.push({ - test: /\.stories\.tsx?$/, - use: [ - { - loader: require.resolve('@storybook/source-loader'), - options: { parser: 'typescript' }, - }, - ], - enforce: 'pre', - }); - return { - ...config, + // docs: {}, + async viteFinal(config) { + // Merge custom configuration into the default config + const { mergeConfig } = await import('vite'); + + return mergeConfig(config, { resolve: { - ...config.resolve, - alias: packages.reduce( - (acc, pkg) => ({ - ...acc, - [pkg]: path.resolve( - __dirname, - `../packages/${pkg}/src` - ), - }), - {} - ), + alias: packages.map(pkg => ({ + find: new RegExp(`^${pkg}$`), + replacement: path.resolve( + __dirname, + `../packages/${pkg}/src` + ), + })), }, - }; - }, - framework: { - name: getAbsolutePath('@storybook/react-webpack5'), - options: {}, + }); }, - docs: {}, }; export default config; diff --git a/package.json b/package.json index 47500b59b03..558cc5a3bfc 100644 --- a/package.json +++ b/package.json @@ -25,14 +25,14 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@storybook/addon-actions": "^8.1.9", - "@storybook/addon-controls": "^8.1.9", - "@storybook/addon-docs": "^8.1.9", - "@storybook/addon-storysource": "^8.1.9", + "@storybook/addon-actions": "^8.4.4", + "@storybook/addon-controls": "^8.4.4", + "@storybook/addon-storysource": "^8.4.4", "@storybook/addon-webpack5-compiler-babel": "^3.0.3", - "@storybook/react": "^8.1.9", - "@storybook/react-webpack5": "^8.1.9", - "@storybook/source-loader": "^8.1.9", + "@storybook/react": "^8.4.4", + "@storybook/react-vite": "^8.4.4", + "@storybook/react-webpack5": "^8.4.4", + "@storybook/source-loader": "^8.4.4", "@types/jest": "^29.5.2", "@types/react": "^18.3.3", "@typescript-eslint/eslint-plugin": "^5.60.0", @@ -59,8 +59,9 @@ "raf": "~3.4.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "storybook": "^8.1.9", + "storybook": "^8.4.4", "ts-jest": "^29.1.0", + "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "^5.1.3", "whatwg-fetch": "^3.0.0" }, diff --git a/yarn.lock b/yarn.lock index 2fddc6555da..bfc894747ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -69,17 +69,6 @@ __metadata: languageName: node linkType: hard -"@aw-web-design/x-default-browser@npm:1.4.126": - version: 1.4.126 - resolution: "@aw-web-design/x-default-browser@npm:1.4.126" - dependencies: - default-browser-id: "npm:3.0.0" - bin: - x-default-browser: bin/x-default-browser.js - checksum: 634c7fad7a5f4df86e3fcd3a11e50034fcb6f6302281569727574cbda7532850063cb34ec328384a686ab0812f297bf301a5e2450bc7b93b5f80a006b1f2dfd7 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.24.7": version: 7.24.7 resolution: "@babel/code-frame@npm:7.24.7" @@ -97,7 +86,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.0.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.18.9, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.5, @babel/core@npm:^7.23.7, @babel/core@npm:^7.24.4": +"@babel/core@npm:^7.0.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.18.9, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.5, @babel/core@npm:^7.23.7": version: 7.24.7 resolution: "@babel/core@npm:7.24.7" dependencies: @@ -134,7 +123,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.24.4, @babel/generator@npm:^7.24.7, @babel/generator@npm:^7.7.2": +"@babel/generator@npm:^7.24.7, @babel/generator@npm:^7.7.2": version: 7.24.7 resolution: "@babel/generator@npm:7.24.7" dependencies: @@ -410,7 +399,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.24.7": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.24.7": version: 7.24.7 resolution: "@babel/parser@npm:7.24.7" bin: @@ -1501,7 +1490,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:^7.16.4, @babel/preset-env@npm:^7.24.4": +"@babel/preset-env@npm:^7.16.4": version: 7.24.5 resolution: "@babel/preset-env@npm:7.24.5" dependencies: @@ -1701,7 +1690,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.24.1, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.7.2": +"@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.7.2": version: 7.24.7 resolution: "@babel/traverse@npm:7.24.7" dependencies: @@ -1719,7 +1708,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.24.0, @babel/types@npm:^7.24.5, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.24.5, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.24.7 resolution: "@babel/types@npm:7.24.7" dependencies: @@ -1730,13 +1719,6 @@ __metadata: languageName: node linkType: hard -"@base2/pretty-print-object@npm:1.0.1": - version: 1.0.1 - resolution: "@base2/pretty-print-object@npm:1.0.1" - checksum: 98f77ea185a30c854897feb2a68fe51be8451a1a0b531bac61a5dd67033926a0ba0c9be6e0f819b8cb72ca349b3e7648bf81c12fd21df0b45219c75a3a75784b - languageName: node - linkType: hard - "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -1780,13 +1762,6 @@ __metadata: languageName: node linkType: hard -"@discoveryjs/json-ext@npm:^0.5.3": - version: 0.5.7 - resolution: "@discoveryjs/json-ext@npm:0.5.7" - checksum: e10f1b02b78e4812646ddf289b7d9f2cb567d336c363b266bd50cd223cf3de7c2c74018d91cd2613041568397ef3a4a2b500aba588c6e5bd78c38374ba68f38c - languageName: node - linkType: hard - "@emotion/babel-plugin@npm:^11.3.0": version: 11.7.2 resolution: "@emotion/babel-plugin@npm:11.7.2" @@ -1924,15 +1899,6 @@ __metadata: languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.1": - version: 1.0.1 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.1" - peerDependencies: - react: ">=16.8.0" - checksum: a15b2167940e3a908160687b73fc4fcd81e59ab45136b6967f02c7c419d9a149acd22a416b325c389642d4f1c3d33cf4196cad6b618128b55b7c74f6807a240b - languageName: node - linkType: hard - "@emotion/utils@npm:^1.0.0, @emotion/utils@npm:^1.2.1": version: 1.2.1 resolution: "@emotion/utils@npm:1.2.1" @@ -1954,13 +1920,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/aix-ppc64@npm:0.20.2" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - "@esbuild/aix-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/aix-ppc64@npm:0.21.5" @@ -1968,10 +1927,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm64@npm:0.20.2" - conditions: os=android & cpu=arm64 +"@esbuild/aix-ppc64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/aix-ppc64@npm:0.24.0" + conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -1982,10 +1941,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm@npm:0.20.2" - conditions: os=android & cpu=arm +"@esbuild/android-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-arm64@npm:0.24.0" + conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -1996,10 +1955,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-x64@npm:0.20.2" - conditions: os=android & cpu=x64 +"@esbuild/android-arm@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-arm@npm:0.24.0" + conditions: os=android & cpu=arm languageName: node linkType: hard @@ -2010,10 +1969,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-arm64@npm:0.20.2" - conditions: os=darwin & cpu=arm64 +"@esbuild/android-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-x64@npm:0.24.0" + conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -2024,10 +1983,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-x64@npm:0.20.2" - conditions: os=darwin & cpu=x64 +"@esbuild/darwin-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/darwin-arm64@npm:0.24.0" + conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -2038,10 +1997,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-arm64@npm:0.20.2" - conditions: os=freebsd & cpu=arm64 +"@esbuild/darwin-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/darwin-x64@npm:0.24.0" + conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -2052,10 +2011,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-x64@npm:0.20.2" - conditions: os=freebsd & cpu=x64 +"@esbuild/freebsd-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/freebsd-arm64@npm:0.24.0" + conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -2066,10 +2025,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm64@npm:0.20.2" - conditions: os=linux & cpu=arm64 +"@esbuild/freebsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/freebsd-x64@npm:0.24.0" + conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -2080,10 +2039,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm@npm:0.20.2" - conditions: os=linux & cpu=arm +"@esbuild/linux-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-arm64@npm:0.24.0" + conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -2094,10 +2053,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ia32@npm:0.20.2" - conditions: os=linux & cpu=ia32 +"@esbuild/linux-arm@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-arm@npm:0.24.0" + conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -2108,10 +2067,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-loong64@npm:0.20.2" - conditions: os=linux & cpu=loong64 +"@esbuild/linux-ia32@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-ia32@npm:0.24.0" + conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -2122,10 +2081,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-mips64el@npm:0.20.2" - conditions: os=linux & cpu=mips64el +"@esbuild/linux-loong64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-loong64@npm:0.24.0" + conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -2136,10 +2095,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ppc64@npm:0.20.2" - conditions: os=linux & cpu=ppc64 +"@esbuild/linux-mips64el@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-mips64el@npm:0.24.0" + conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -2150,10 +2109,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-riscv64@npm:0.20.2" - conditions: os=linux & cpu=riscv64 +"@esbuild/linux-ppc64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-ppc64@npm:0.24.0" + conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -2164,10 +2123,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-s390x@npm:0.20.2" - conditions: os=linux & cpu=s390x +"@esbuild/linux-riscv64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-riscv64@npm:0.24.0" + conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -2178,10 +2137,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-x64@npm:0.20.2" - conditions: os=linux & cpu=x64 +"@esbuild/linux-s390x@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-s390x@npm:0.24.0" + conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -2192,10 +2151,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/netbsd-x64@npm:0.20.2" - conditions: os=netbsd & cpu=x64 +"@esbuild/linux-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-x64@npm:0.24.0" + conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -2206,10 +2165,17 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/openbsd-x64@npm:0.20.2" - conditions: os=openbsd & cpu=x64 +"@esbuild/netbsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/netbsd-x64@npm:0.24.0" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/openbsd-arm64@npm:0.24.0" + conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard @@ -2220,10 +2186,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/sunos-x64@npm:0.20.2" - conditions: os=sunos & cpu=x64 +"@esbuild/openbsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/openbsd-x64@npm:0.24.0" + conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -2234,10 +2200,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-arm64@npm:0.20.2" - conditions: os=win32 & cpu=arm64 +"@esbuild/sunos-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/sunos-x64@npm:0.24.0" + conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2248,10 +2214,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-ia32@npm:0.20.2" - conditions: os=win32 & cpu=ia32 +"@esbuild/win32-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-arm64@npm:0.24.0" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2262,10 +2228,10 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-x64@npm:0.20.2" - conditions: os=win32 & cpu=x64 +"@esbuild/win32-ia32@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-ia32@npm:0.24.0" + conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2276,6 +2242,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-x64@npm:0.24.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -2311,13 +2284,6 @@ __metadata: languageName: node linkType: hard -"@fal-works/esbuild-plugin-global-externals@npm:^2.1.2": - version: 2.1.2 - resolution: "@fal-works/esbuild-plugin-global-externals@npm:2.1.2" - checksum: 2c84a8e6121b00ac8e4eb2469ab8f188142db2f1927391758e5d0142cb684b7eb0fad0c9d6caf358616eb2a77af2c067e08b9ec8e05749b415fc4dd0ef96d0fe - languageName: node - linkType: hard - "@floating-ui/core@npm:^1.0.0": version: 1.6.0 resolution: "@floating-ui/core@npm:1.6.0" @@ -2759,6 +2725,24 @@ __metadata: languageName: node linkType: hard +"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0": + version: 0.3.0 + resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0" + dependencies: + glob: "npm:^7.2.0" + glob-promise: "npm:^4.2.0" + magic-string: "npm:^0.27.0" + react-docgen-typescript: "npm:^2.2.2" + peerDependencies: + typescript: ">= 4.3.x" + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 31098ad8fcc2440437534599c111d9f2951dd74821e8ba46c521b969bae4c918d830b7bb0484efbad29a51711bb62d3bc623d5a1ed5b1695b5b5594ea9dd4ca0 + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -2801,6 +2785,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.15, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -2901,18 +2892,6 @@ __metadata: languageName: node linkType: hard -"@mdx-js/react@npm:^3.0.0": - version: 3.0.1 - resolution: "@mdx-js/react@npm:3.0.1" - dependencies: - "@types/mdx": "npm:^2.0.0" - peerDependencies: - "@types/react": ">=16" - react: ">=16" - checksum: d210d926ef488d39ad65f04d821936b668eadcdde3b6421e94ec4200ca7ad17f17d24c5cbc543882586af9f08b10e2eea715c728ce6277487945e05c5199f532 - languageName: node - linkType: hard - "@mui/base@npm:5.0.0-beta.40": version: 5.0.0-beta.40 resolution: "@mui/base@npm:5.0.0-beta.40" @@ -3087,17 +3066,6 @@ __metadata: languageName: node linkType: hard -"@ndelangen/get-tarball@npm:^3.0.7": - version: 3.0.7 - resolution: "@ndelangen/get-tarball@npm:3.0.7" - dependencies: - gunzip-maybe: "npm:^1.4.2" - pump: "npm:^3.0.0" - tar-fs: "npm:^2.1.1" - checksum: b60324b165656fa4c6adfce2f521ba44c12773a293e83ec7469c2fe0e71f4b352756db73867b6ce197610b6ad0dcbc2bb1add2b24165351b60337f0bf492f998 - languageName: node - linkType: hard - "@nivo/annotations@npm:0.80.0": version: 0.80.0 resolution: "@nivo/annotations@npm:0.80.0" @@ -3675,390 +3643,102 @@ __metadata: languageName: node linkType: hard -"@radix-ui/primitive@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/primitive@npm:1.0.1" +"@react-spring/animated@npm:~9.4.5": + version: 9.4.5 + resolution: "@react-spring/animated@npm:9.4.5" dependencies: - "@babel/runtime": "npm:^7.13.10" - checksum: 912216455537db3ca77f3e7f70174fb2b454fbd4a37a0acb7cfadad9ab6131abdfb787472242574460a3c301edf45738340cc84f6717982710082840fde7d916 + "@react-spring/shared": "npm:~9.4.5" + "@react-spring/types": "npm:~9.4.5" + peerDependencies: + react: ^16.8.0 || >=17.0.0 || >=18.0.0 + checksum: aba2a64e7e0d120de51346e534a1b1bf2c7d9516baf3c200fc2c506e84703c0ffdc08ace2e0466a2fb759350653aa774b3b39e9b14884f767a8098509c7e1aaf languageName: node linkType: hard -"@radix-ui/react-compose-refs@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-compose-refs@npm:1.0.1" +"@react-spring/core@npm:~9.4.5": + version: 9.4.5 + resolution: "@react-spring/core@npm:9.4.5" dependencies: - "@babel/runtime": "npm:^7.13.10" + "@react-spring/animated": "npm:~9.4.5" + "@react-spring/rafz": "npm:~9.4.5" + "@react-spring/shared": "npm:~9.4.5" + "@react-spring/types": "npm:~9.4.5" peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: be06f8dab35b5a1bffa7a5982fb26218ddade1acb751288333e3b89d7b4a7dfb5a6371be83876dac0ec2ebe0866d295e8618b778608e1965342986ea448040ec + react: ^16.8.0 || >=17.0.0 || >=18.0.0 + checksum: bf1a81d9d1eb93727c98112d3b31ee788e495348a26073dc4eb88d7b3d669d6400fccf190f39f4cbb8417a64fb1e6b7fd71ae4152a4592922c75ddf685dfe54d languageName: node linkType: hard -"@radix-ui/react-context@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-context@npm:1.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 3de5761b32cc70cd61715527f29d8c699c01ab28c195ced972ccbc7025763a373a68f18c9f948c7a7b922e469fd2df7fee5f7536e3f7bad44ffc06d959359333 +"@react-spring/rafz@npm:~9.4.5": + version: 9.4.5 + resolution: "@react-spring/rafz@npm:9.4.5" + checksum: e4889c548e4627bf312767544360ade2ddf5e93a464033d041d7bf37763457a9a0f56a3abf473f002d30b15440b4b8cfe94a8d9cfe85160f16cdb9754147f6c2 languageName: node linkType: hard -"@radix-ui/react-dialog@npm:^1.0.5": - version: 1.0.5 - resolution: "@radix-ui/react-dialog@npm:1.0.5" +"@react-spring/shared@npm:~9.4.5": + version: 9.4.5 + resolution: "@react-spring/shared@npm:9.4.5" dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/primitive": "npm:1.0.1" - "@radix-ui/react-compose-refs": "npm:1.0.1" - "@radix-ui/react-context": "npm:1.0.1" - "@radix-ui/react-dismissable-layer": "npm:1.0.5" - "@radix-ui/react-focus-guards": "npm:1.0.1" - "@radix-ui/react-focus-scope": "npm:1.0.4" - "@radix-ui/react-id": "npm:1.0.1" - "@radix-ui/react-portal": "npm:1.0.4" - "@radix-ui/react-presence": "npm:1.0.1" - "@radix-ui/react-primitive": "npm:1.0.3" - "@radix-ui/react-slot": "npm:1.0.2" - "@radix-ui/react-use-controllable-state": "npm:1.0.1" - aria-hidden: "npm:^1.1.1" - react-remove-scroll: "npm:2.5.5" + "@react-spring/rafz": "npm:~9.4.5" + "@react-spring/types": "npm:~9.4.5" peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: c5b3069397379e79857a3203f3ead4d12d87736b59899f02a63e620a07dd1e6704e15523926cdf8e39afe1c945a7ff0f2533c5ea5be1e17c3114820300a51133 + react: ^16.8.0 || >=17.0.0 || >=18.0.0 + checksum: 0edcc4c417027e9ea24ee63739cfd4e380eb32bcff672cea7d93006e068b5ed92a8fc28f868ee205f222498a38191ec5e5245674ed948617b06595a3349b7f46 languageName: node linkType: hard -"@radix-ui/react-dismissable-layer@npm:1.0.5": - version: 1.0.5 - resolution: "@radix-ui/react-dismissable-layer@npm:1.0.5" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/primitive": "npm:1.0.1" - "@radix-ui/react-compose-refs": "npm:1.0.1" - "@radix-ui/react-primitive": "npm:1.0.3" - "@radix-ui/react-use-callback-ref": "npm:1.0.1" - "@radix-ui/react-use-escape-keydown": "npm:1.0.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 7e4308867aecfb07b506330c1964d94a52247ab9453725613cd326762aa13e483423c250f107219c131b0449600eb8d1576ce3159c2b96e8c978f75e46062cb2 +"@react-spring/types@npm:~9.4.5": + version: 9.4.5 + resolution: "@react-spring/types@npm:9.4.5" + checksum: 498a03e4e101c903af5d7c933535efa38025c95f7b19341a4af1d3a3336a3929a44e625cf8b9ad9ab2efdd7d22f4fc19505b127e652211e6f2f7c40a86ab92cf languageName: node linkType: hard -"@radix-ui/react-focus-guards@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-focus-guards@npm:1.0.1" +"@react-spring/web@npm:9.4.5": + version: 9.4.5 + resolution: "@react-spring/web@npm:9.4.5" dependencies: - "@babel/runtime": "npm:^7.13.10" + "@react-spring/animated": "npm:~9.4.5" + "@react-spring/core": "npm:~9.4.5" + "@react-spring/shared": "npm:~9.4.5" + "@react-spring/types": "npm:~9.4.5" peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: d5fd4e5aa9d9a87c8ad490b3b4992d6f1d9eddf18e56df2a2bcf8744c4332b275d73377fd193df3e6ba0ad9608dc497709beca5c64de2b834d5f5350b3c9a272 + react: ^16.8.0 || >=17.0.0 || >=18.0.0 + react-dom: ^16.8.0 || >=17.0.0 || >=18.0.0 + checksum: bd66cfb918466a74022696e672fa69ff0e8f8e5cc67a1369c894e7d9e17fcc70861fe2ac9f4ab2fc3cbdd6e3cac9149c12edda6e3b842ac600bf04117cb0e89d languageName: node linkType: hard -"@radix-ui/react-focus-scope@npm:1.0.4": - version: 1.0.4 - resolution: "@radix-ui/react-focus-scope@npm:1.0.4" +"@remirror/core-constants@npm:^2.0.0": + version: 2.0.0 + resolution: "@remirror/core-constants@npm:2.0.0" dependencies: "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-compose-refs": "npm:1.0.1" - "@radix-ui/react-primitive": "npm:1.0.3" - "@radix-ui/react-use-callback-ref": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 2fce0bafcab4e16cf4ed7560bda40654223f3d0add6b231e1c607433030c14e6249818b444b7b58ee7a6ff6bbf8e192c9c81d22c3a5c88c2daade9d1f881b5be + checksum: b5795f7deb34ea618dbe61d865963ad384e872fc432c8aacd59d40267371b76e82039b3ffb4c9ccbb978d4ff2d753cd76a8daa0e092e7349c08d4ae545bd7a6d languageName: node linkType: hard -"@radix-ui/react-id@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-id@npm:1.0.1" +"@remirror/core-helpers@npm:^2.0.1": + version: 2.0.1 + resolution: "@remirror/core-helpers@npm:2.0.1" dependencies: "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-use-layout-effect": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: e2859ca58bea171c956098ace7ecf615cf9432f58a118b779a14720746b3adcf0351c36c75de131548672d3cd290ca238198acbd33b88dc4706f98312e9317ad - languageName: node - linkType: hard - -"@radix-ui/react-portal@npm:1.0.4": - version: 1.0.4 - resolution: "@radix-ui/react-portal@npm:1.0.4" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-primitive": "npm:1.0.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: fed32f8148b833fe852fb5e2f859979ffdf2fb9a9ef46583b9b52915d764ad36ba5c958a64e61d23395628ccc09d678229ee94cd112941e8fe2575021f820c29 - languageName: node - linkType: hard - -"@radix-ui/react-presence@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-presence@npm:1.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-compose-refs": "npm:1.0.1" - "@radix-ui/react-use-layout-effect": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 90780618b265fe794a8f1ddaa5bfd3c71a1127fa79330a14d32722e6265b44452a9dd36efe4e769129d33e57f979f6b8713e2cbf2e2755326aa3b0f337185b6e - languageName: node - linkType: hard - -"@radix-ui/react-primitive@npm:1.0.3": - version: 1.0.3 - resolution: "@radix-ui/react-primitive@npm:1.0.3" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-slot": "npm:1.0.2" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 67a66ff8898a5e7739eda228ab6f5ce808858da1dce967014138d87e72b6bbfc93dc1467c706d98d1a2b93bf0b6e09233d1a24d31c78227b078444c1a69c42be - languageName: node - linkType: hard - -"@radix-ui/react-slot@npm:1.0.2, @radix-ui/react-slot@npm:^1.0.2": - version: 1.0.2 - resolution: "@radix-ui/react-slot@npm:1.0.2" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-compose-refs": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 3af6ea4891e6fa8091e666802adffe7718b3cd390a10fa9229a5f40f8efded9f3918ea01b046103d93923d41cc32119505ebb6bde76cad07a87b6cf4f2119347 - languageName: node - linkType: hard - -"@radix-ui/react-use-callback-ref@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-use-callback-ref@npm:1.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 331b432be1edc960ca148637ae6087220873ee828ceb13bd155926ef8f49e862812de5b379129f6aaefcd11be53715f3237e6caa9a33d9c0abfff43f3ba58938 - languageName: node - linkType: hard - -"@radix-ui/react-use-controllable-state@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-use-controllable-state@npm:1.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-use-callback-ref": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 29b069dbf09e48bca321af6272574ad0fc7283174e7d092731a10663fe00c0e6b4bde5e1b5ea67725fe48dcbe8026e7ff0d69d42891c62cbb9ca408498171fbe - languageName: node - linkType: hard - -"@radix-ui/react-use-escape-keydown@npm:1.0.3": - version: 1.0.3 - resolution: "@radix-ui/react-use-escape-keydown@npm:1.0.3" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@radix-ui/react-use-callback-ref": "npm:1.0.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 3c94c78902dcb40b60083ee2184614f45c95a189178f52d89323b467bd04bcf5fdb1bc4d43debecd7f0b572c3843c7e04edbcb56f40a4b4b43936fb2770fb8ad - languageName: node - linkType: hard - -"@radix-ui/react-use-layout-effect@npm:1.0.1": - version: 1.0.1 - resolution: "@radix-ui/react-use-layout-effect@npm:1.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 13cd0c38395c5838bc9a18238020d3bcf67fb340039e6d1cbf438be1b91d64cf6900b78121f3dc9219faeb40dcc7b523ce0f17e4a41631655690e5a30a40886a - languageName: node - linkType: hard - -"@react-spring/animated@npm:~9.4.5": - version: 9.4.5 - resolution: "@react-spring/animated@npm:9.4.5" - dependencies: - "@react-spring/shared": "npm:~9.4.5" - "@react-spring/types": "npm:~9.4.5" - peerDependencies: - react: ^16.8.0 || >=17.0.0 || >=18.0.0 - checksum: aba2a64e7e0d120de51346e534a1b1bf2c7d9516baf3c200fc2c506e84703c0ffdc08ace2e0466a2fb759350653aa774b3b39e9b14884f767a8098509c7e1aaf - languageName: node - linkType: hard - -"@react-spring/core@npm:~9.4.5": - version: 9.4.5 - resolution: "@react-spring/core@npm:9.4.5" - dependencies: - "@react-spring/animated": "npm:~9.4.5" - "@react-spring/rafz": "npm:~9.4.5" - "@react-spring/shared": "npm:~9.4.5" - "@react-spring/types": "npm:~9.4.5" - peerDependencies: - react: ^16.8.0 || >=17.0.0 || >=18.0.0 - checksum: bf1a81d9d1eb93727c98112d3b31ee788e495348a26073dc4eb88d7b3d669d6400fccf190f39f4cbb8417a64fb1e6b7fd71ae4152a4592922c75ddf685dfe54d - languageName: node - linkType: hard - -"@react-spring/rafz@npm:~9.4.5": - version: 9.4.5 - resolution: "@react-spring/rafz@npm:9.4.5" - checksum: e4889c548e4627bf312767544360ade2ddf5e93a464033d041d7bf37763457a9a0f56a3abf473f002d30b15440b4b8cfe94a8d9cfe85160f16cdb9754147f6c2 - languageName: node - linkType: hard - -"@react-spring/shared@npm:~9.4.5": - version: 9.4.5 - resolution: "@react-spring/shared@npm:9.4.5" - dependencies: - "@react-spring/rafz": "npm:~9.4.5" - "@react-spring/types": "npm:~9.4.5" - peerDependencies: - react: ^16.8.0 || >=17.0.0 || >=18.0.0 - checksum: 0edcc4c417027e9ea24ee63739cfd4e380eb32bcff672cea7d93006e068b5ed92a8fc28f868ee205f222498a38191ec5e5245674ed948617b06595a3349b7f46 - languageName: node - linkType: hard - -"@react-spring/types@npm:~9.4.5": - version: 9.4.5 - resolution: "@react-spring/types@npm:9.4.5" - checksum: 498a03e4e101c903af5d7c933535efa38025c95f7b19341a4af1d3a3336a3929a44e625cf8b9ad9ab2efdd7d22f4fc19505b127e652211e6f2f7c40a86ab92cf - languageName: node - linkType: hard - -"@react-spring/web@npm:9.4.5": - version: 9.4.5 - resolution: "@react-spring/web@npm:9.4.5" - dependencies: - "@react-spring/animated": "npm:~9.4.5" - "@react-spring/core": "npm:~9.4.5" - "@react-spring/shared": "npm:~9.4.5" - "@react-spring/types": "npm:~9.4.5" - peerDependencies: - react: ^16.8.0 || >=17.0.0 || >=18.0.0 - react-dom: ^16.8.0 || >=17.0.0 || >=18.0.0 - checksum: bd66cfb918466a74022696e672fa69ff0e8f8e5cc67a1369c894e7d9e17fcc70861fe2ac9f4ab2fc3cbdd6e3cac9149c12edda6e3b842ac600bf04117cb0e89d - languageName: node - linkType: hard - -"@remirror/core-constants@npm:^2.0.0": - version: 2.0.0 - resolution: "@remirror/core-constants@npm:2.0.0" - dependencies: - "@babel/runtime": "npm:^7.13.10" - checksum: b5795f7deb34ea618dbe61d865963ad384e872fc432c8aacd59d40267371b76e82039b3ffb4c9ccbb978d4ff2d753cd76a8daa0e092e7349c08d4ae545bd7a6d - languageName: node - linkType: hard - -"@remirror/core-helpers@npm:^2.0.1": - version: 2.0.1 - resolution: "@remirror/core-helpers@npm:2.0.1" - dependencies: - "@babel/runtime": "npm:^7.13.10" - "@linaria/core": "npm:3.0.0-beta.13" - "@remirror/core-constants": "npm:^2.0.0" - "@remirror/types": "npm:^1.0.0" - "@types/object.omit": "npm:^3.0.0" - "@types/object.pick": "npm:^1.3.1" - "@types/throttle-debounce": "npm:^2.1.0" - case-anything: "npm:^2.1.10" - dash-get: "npm:^1.0.2" - deepmerge: "npm:^4.2.2" - fast-deep-equal: "npm:^3.1.3" - make-error: "npm:^1.3.6" - object.omit: "npm:^3.0.0" - object.pick: "npm:^1.3.0" - throttle-debounce: "npm:^3.0.1" - checksum: fdba5204ceafe1af7e3c5986a23362814d32dea1ca9cea2d977d6b1ff728cc964c9421e5bfaf185cc486e7f3b051b94067be8d0210c6872695564fa0e5c8bc01 + "@linaria/core": "npm:3.0.0-beta.13" + "@remirror/core-constants": "npm:^2.0.0" + "@remirror/types": "npm:^1.0.0" + "@types/object.omit": "npm:^3.0.0" + "@types/object.pick": "npm:^1.3.1" + "@types/throttle-debounce": "npm:^2.1.0" + case-anything: "npm:^2.1.10" + dash-get: "npm:^1.0.2" + deepmerge: "npm:^4.2.2" + fast-deep-equal: "npm:^3.1.3" + make-error: "npm:^1.3.6" + object.omit: "npm:^3.0.0" + object.pick: "npm:^1.3.0" + throttle-debounce: "npm:^3.0.1" + checksum: fdba5204ceafe1af7e3c5986a23362814d32dea1ca9cea2d977d6b1ff728cc964c9421e5bfaf185cc486e7f3b051b94067be8d0210c6872695564fa0e5c8bc01 languageName: node linkType: hard @@ -4078,6 +3758,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.2": + version: 5.1.3 + resolution: "@rollup/pluginutils@npm:5.1.3" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: ba46ad588733fb01d184ee3bc7a127d626158bc840b5874a94c129ff62689d12f16f537530709c54da6f3b71f67d705c4e09235b1dc9542e9d47ee8f2d0b8b9e + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.22.4": version: 4.22.4 resolution: "@rollup/rollup-android-arm-eabi@npm:4.22.4" @@ -4222,13 +3918,6 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/merge-streams@npm:^2.1.0": - version: 2.3.0 - resolution: "@sindresorhus/merge-streams@npm:2.3.0" - checksum: 69ee906f3125fb2c6bb6ec5cdd84e8827d93b49b3892bce8b62267116cc7e197b5cccf20c160a1d32c26014ecd14470a72a5e3ee37a58f1d6dadc0db1ccf3894 - languageName: node - linkType: hard - "@sinonjs/commons@npm:^3.0.0": version: 3.0.0 resolution: "@sinonjs/commons@npm:3.0.0" @@ -4247,68 +3936,44 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-actions@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/addon-actions@npm:8.1.9" +"@storybook/addon-actions@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/addon-actions@npm:8.4.4" dependencies: - "@storybook/core-events": "npm:8.1.9" "@storybook/global": "npm:^5.0.0" "@types/uuid": "npm:^9.0.1" dequal: "npm:^2.0.2" polished: "npm:^4.2.2" uuid: "npm:^9.0.0" - checksum: 06af4d9d430e92f2e755072e566690a0b581e898d969320575021225553c797a519026d066d186106254c71865230b7b64cc760f004e896a1e579f2cc4538fc4 - languageName: node - linkType: hard - -"@storybook/addon-controls@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/addon-controls@npm:8.1.9" - dependencies: - "@storybook/blocks": "npm:8.1.9" - dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" - ts-dedent: "npm:^2.0.0" - checksum: 38d0ee88c7478ad73abef859a00c6a134cf1ffdbcd8d7fa54053b9e797efe71fc20d0d2d4f001e53c0b0dbdea0c432e03c3b248563efe57f48bb31a4668097de + peerDependencies: + storybook: ^8.4.4 + checksum: ba4f310a047f3c0c8eed7ac61d47470dcd388e0bd584e1f17918c22e89fc060e06b403ceb7c591746b12c1fdbf796fe46fe5f797ee2ff69f5272b29c173979f8 languageName: node linkType: hard -"@storybook/addon-docs@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/addon-docs@npm:8.1.9" +"@storybook/addon-controls@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/addon-controls@npm:8.4.4" dependencies: - "@babel/core": "npm:^7.24.4" - "@mdx-js/react": "npm:^3.0.0" - "@storybook/blocks": "npm:8.1.9" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/components": "npm:8.1.9" - "@storybook/csf-plugin": "npm:8.1.9" - "@storybook/csf-tools": "npm:8.1.9" "@storybook/global": "npm:^5.0.0" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/preview-api": "npm:8.1.9" - "@storybook/react-dom-shim": "npm:8.1.9" - "@storybook/theming": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/react": "npm:^16.8.0 || ^17.0.0 || ^18.0.0" - fs-extra: "npm:^11.1.0" - react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0" - react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0" - rehype-external-links: "npm:^3.0.0" - rehype-slug: "npm:^6.0.0" + dequal: "npm:^2.0.2" ts-dedent: "npm:^2.0.0" - checksum: 08d8049e0830635b4a0b867f1d0606cf0aab2f67dedd555882fd960b6afe9c884e4c2b8617425cf4e32c0989c14fe5490a3b4e390a1ec2e99e7393135511ef4f + peerDependencies: + storybook: ^8.4.4 + checksum: a7e0de38fee916193441a35e89e4a922e1beb6b295758fd39b88b31899e78a27651eb184cf1d36c98eda94865a3cc9d1484acef68c8c495f5602f2989d8f0495 languageName: node linkType: hard -"@storybook/addon-storysource@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/addon-storysource@npm:8.1.9" +"@storybook/addon-storysource@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/addon-storysource@npm:8.4.4" dependencies: - "@storybook/source-loader": "npm:8.1.9" + "@storybook/source-loader": "npm:8.4.4" estraverse: "npm:^5.2.0" tiny-invariant: "npm:^1.3.1" - checksum: 0769b5cf0bec8d2105341ce3b4ee397a06670859554669f33e62de61bcd82bb89382a58a64ef7bc3fb6b65ee3b7f67aa5e5c76f116c5c47b9b44beef387fc689 + peerDependencies: + storybook: ^8.4.4 + checksum: 592bbd2ea71fdbb96584eceab44ff11dce9089ef18cfad4016d9b43d505cc1c8f6a19bece35c6b73e8ede3e8b3be57d8eec3e2cc23b7061810fca4a0df89d223 languageName: node linkType: hard @@ -4322,81 +3987,26 @@ __metadata: languageName: node linkType: hard -"@storybook/blocks@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/blocks@npm:8.1.9" +"@storybook/builder-vite@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/builder-vite@npm:8.4.4" dependencies: - "@storybook/channels": "npm:8.1.9" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/components": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/csf": "npm:^0.1.7" - "@storybook/docs-tools": "npm:8.1.9" - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^1.2.5" - "@storybook/manager-api": "npm:8.1.9" - "@storybook/preview-api": "npm:8.1.9" - "@storybook/theming": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/lodash": "npm:^4.14.167" - color-convert: "npm:^2.0.1" - dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" - markdown-to-jsx: "npm:7.3.2" - memoizerific: "npm:^1.11.3" - polished: "npm:^4.2.2" - react-colorful: "npm:^5.1.2" - telejson: "npm:^7.2.0" - tocbot: "npm:^4.20.1" + "@storybook/csf-plugin": "npm:8.4.4" + browser-assert: "npm:^1.2.1" ts-dedent: "npm:^2.0.0" - util-deprecate: "npm:^1.0.2" 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 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - checksum: 6d68e44135ab5b8570365c7ab5ae07e4dad52606deb20ad906c417bfbb4ab96cd5125445fe5554c4530a3345ac6d43910d8d234a734f3b3639485b3486a0d3dc - languageName: node - linkType: hard - -"@storybook/builder-manager@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/builder-manager@npm:8.1.9" - dependencies: - "@fal-works/esbuild-plugin-global-externals": "npm:^2.1.2" - "@storybook/core-common": "npm:8.1.9" - "@storybook/manager": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@types/ejs": "npm:^3.1.1" - "@yarnpkg/esbuild-plugin-pnp": "npm:^3.0.0-rc.10" - browser-assert: "npm:^1.2.1" - ejs: "npm:^3.1.10" - esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0" - esbuild-plugin-alias: "npm:^0.2.1" - express: "npm:^4.17.3" - fs-extra: "npm:^11.1.0" - process: "npm:^0.11.10" - util: "npm:^0.12.4" - checksum: a20ad19008f9bfb8798fd1e93b63c91e254f1c3650c1ff27ac4ae4c79c1a29f3c8a7f0e92874293e921bf28b3c80cd5227dc2f5668abacb630444f93ecdf29a8 + storybook: ^8.4.4 + vite: ^4.0.0 || ^5.0.0 + checksum: f5fd27b048930fe17db4bd90becaee9980d952998149d1e9fce7cdb273898eb2d954787c9e7bb3829f9858e1a2503fce02afce67d7941f9b996f5363e9f3d063 languageName: node linkType: hard -"@storybook/builder-webpack5@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/builder-webpack5@npm:8.1.9" +"@storybook/builder-webpack5@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/builder-webpack5@npm:8.4.4" dependencies: - "@storybook/channels": "npm:8.1.9" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/core-common": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/core-webpack": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/preview": "npm:8.1.9" - "@storybook/preview-api": "npm:8.1.9" - "@types/node": "npm:^18.0.0" + "@storybook/core-webpack": "npm:8.4.4" + "@types/node": "npm:^22.0.0" "@types/semver": "npm:^7.3.4" browser-assert: "npm:^1.2.1" case-sensitive-paths-webpack-plugin: "npm:^2.4.0" @@ -4404,9 +4014,7 @@ __metadata: constants-browserify: "npm:^1.0.0" css-loader: "npm:^6.7.1" es-module-lexer: "npm:^1.5.0" - express: "npm:^4.17.3" fork-ts-checker-webpack-plugin: "npm:^8.0.0" - fs-extra: "npm:^11.1.0" html-webpack-plugin: "npm:^5.5.0" magic-string: "npm:^0.30.5" path-browserify: "npm:^1.0.1" @@ -4421,301 +4029,78 @@ __metadata: webpack: "npm:5" webpack-dev-middleware: "npm:^6.1.2" webpack-hot-middleware: "npm:^2.25.1" - webpack-virtual-modules: "npm:^0.5.0" + webpack-virtual-modules: "npm:^0.6.0" + peerDependencies: + storybook: ^8.4.4 peerDependenciesMeta: typescript: optional: true - checksum: 03ccfa17e2c8f13b4f92f3c1d7286c558e0605a95a4f364425b187313832bc649c4b1a935fa8ee69b8c0d38f76dcfdb01a039169f45151e4f14933391db32ed7 - languageName: node - linkType: hard - -"@storybook/channels@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/channels@npm:8.1.9" - dependencies: - "@storybook/client-logger": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/global": "npm:^5.0.0" - telejson: "npm:^7.2.0" - tiny-invariant: "npm:^1.3.1" - checksum: 9b21a03faa860e10bc00c0152cc6b59dad9042fa7529cc9804d15a18c522c43de1822b90821a209af5c05a05b83608b7ba2f15d775ee392f0b24a765feac4a90 + checksum: 6669db22a8a875c0bd883b5a22e181a97aed00122484ad79f15fe86a88e1e2523d552f602c613f0a87cd5063a3f2a0c0b75102d6c96f00791922053a3c0b0200 languageName: node linkType: hard -"@storybook/cli@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/cli@npm:8.1.9" - dependencies: - "@babel/core": "npm:^7.24.4" - "@babel/types": "npm:^7.24.0" - "@ndelangen/get-tarball": "npm:^3.0.7" - "@storybook/codemod": "npm:8.1.9" - "@storybook/core-common": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/core-server": "npm:8.1.9" - "@storybook/csf-tools": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/telemetry": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/semver": "npm:^7.3.4" - "@yarnpkg/fslib": "npm:2.10.3" - "@yarnpkg/libzip": "npm:2.3.0" - chalk: "npm:^4.1.0" - commander: "npm:^6.2.1" - cross-spawn: "npm:^7.0.3" - detect-indent: "npm:^6.1.0" - envinfo: "npm:^7.7.3" - execa: "npm:^5.0.0" - find-up: "npm:^5.0.0" - fs-extra: "npm:^11.1.0" - get-npm-tarball-url: "npm:^2.0.3" - giget: "npm:^1.0.0" - globby: "npm:^14.0.1" - jscodeshift: "npm:^0.15.1" - leven: "npm:^3.1.0" - ora: "npm:^5.4.1" - prettier: "npm:^3.1.1" - prompts: "npm:^2.4.0" - read-pkg-up: "npm:^7.0.1" - semver: "npm:^7.3.7" - strip-json-comments: "npm:^3.0.1" - tempy: "npm:^3.1.0" - tiny-invariant: "npm:^1.3.1" - ts-dedent: "npm:^2.0.0" - bin: - getstorybook: ./bin/index.js - sb: ./bin/index.js - checksum: 6bb86d7181fe617657431257d9717a82c1d3f07bb3b45535275b5914d398604041012e8f9cc2facf21db421d26053635e0fd1ad481373e19cc13657e7c328159 - languageName: node - linkType: hard - -"@storybook/client-logger@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/client-logger@npm:8.1.9" - dependencies: - "@storybook/global": "npm:^5.0.0" - checksum: bcc1363f6d3234120710b6c9a4cc0335a0aa9b150fe702888736168422b9f049e3e88f41b1eb65524fe863b587cba160f8bda57b055124c49ee88ba8516c6b2d - languageName: node - linkType: hard - -"@storybook/codemod@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/codemod@npm:8.1.9" - dependencies: - "@babel/core": "npm:^7.24.4" - "@babel/preset-env": "npm:^7.24.4" - "@babel/types": "npm:^7.24.0" - "@storybook/csf": "npm:^0.1.7" - "@storybook/csf-tools": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/cross-spawn": "npm:^6.0.2" - cross-spawn: "npm:^7.0.3" - globby: "npm:^14.0.1" - jscodeshift: "npm:^0.15.1" - lodash: "npm:^4.17.21" - prettier: "npm:^3.1.1" - recast: "npm:^0.23.5" - tiny-invariant: "npm:^1.3.1" - checksum: f1d0be459c10a188c31a5953fb66e713f9584be9507e06c6ada36813acaf06d56aeb8cd41dd11344be110317ab47e19ee576cab56a2c5b0621712e793367f9a0 - languageName: node - linkType: hard - -"@storybook/components@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/components@npm:8.1.9" - dependencies: - "@radix-ui/react-dialog": "npm:^1.0.5" - "@radix-ui/react-slot": "npm:^1.0.2" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/csf": "npm:^0.1.7" - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^1.2.5" - "@storybook/theming": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - memoizerific: "npm:^1.11.3" - util-deprecate: "npm:^1.0.2" +"@storybook/components@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/components@npm:8.4.4" 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 - checksum: a678a54e6333ee783fa379ec5eb28e6e37b89b17e39487d76c3b00d86b69619abfdb8b731c778e0a2d1d57fd68790be6b2acff5b6cb6416e4f7197dd5151727d + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: fd87c6e38d62a72256fea85a3ff4a865c5f8357dc02ee6a0f09be8e9897c0bfbc886460126b1d277e8642d438241ad76f83d01035278989eac6f6a0c23f13f5a languageName: node linkType: hard -"@storybook/core-common@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/core-common@npm:8.1.9" +"@storybook/core-webpack@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/core-webpack@npm:8.4.4" dependencies: - "@storybook/core-events": "npm:8.1.9" - "@storybook/csf-tools": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@yarnpkg/fslib": "npm:2.10.3" - "@yarnpkg/libzip": "npm:2.3.0" - chalk: "npm:^4.1.0" - cross-spawn: "npm:^7.0.3" - esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0" - esbuild-register: "npm:^3.5.0" - execa: "npm:^5.0.0" - file-system-cache: "npm:2.3.0" - find-cache-dir: "npm:^3.0.0" - find-up: "npm:^5.0.0" - fs-extra: "npm:^11.1.0" - glob: "npm:^10.0.0" - handlebars: "npm:^4.7.7" - lazy-universal-dotenv: "npm:^4.0.0" - node-fetch: "npm:^2.0.0" - picomatch: "npm:^2.3.0" - pkg-dir: "npm:^5.0.0" - prettier-fallback: "npm:prettier@^3" - pretty-hrtime: "npm:^1.0.3" - resolve-from: "npm:^5.0.0" - semver: "npm:^7.3.7" - tempy: "npm:^3.1.0" - tiny-invariant: "npm:^1.3.1" + "@types/node": "npm:^22.0.0" ts-dedent: "npm:^2.0.0" - util: "npm:^0.12.4" peerDependencies: - prettier: ^2 || ^3 - peerDependenciesMeta: - prettier: - optional: true - checksum: 3ee22de36519f43338bc775eea100c974837ff394274a9e710f33fd091a94da0bc8a77ce71b037f52e387e170b96c81773301ac015a81e94b67dfa6b06a561d8 + storybook: ^8.4.4 + checksum: d774d66f231492274574da80f4973e35eee086fa61b6ae4a3d7f2b37ed7d34afffceceeb95f27c616ab8e9aa6623b27c5172f8e79fd179edb2a59271f3aed4fd languageName: node linkType: hard -"@storybook/core-events@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/core-events@npm:8.1.9" +"@storybook/core@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/core@npm:8.4.4" dependencies: - "@storybook/csf": "npm:^0.1.7" - ts-dedent: "npm:^2.0.0" - checksum: 27886c18892e0292f56a218c8b11b253f560d62f5621907eceae91ac01f6571eccd95068ebb9d0bbc6fc94afb951004d882942680d1afc7a170f3ae5be490a2b - languageName: node - linkType: hard - -"@storybook/core-server@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/core-server@npm:8.1.9" - dependencies: - "@aw-web-design/x-default-browser": "npm:1.4.126" - "@babel/core": "npm:^7.24.4" - "@babel/parser": "npm:^7.24.4" - "@discoveryjs/json-ext": "npm:^0.5.3" - "@storybook/builder-manager": "npm:8.1.9" - "@storybook/channels": "npm:8.1.9" - "@storybook/core-common": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/csf": "npm:^0.1.7" - "@storybook/csf-tools": "npm:8.1.9" - "@storybook/docs-mdx": "npm:3.1.0-next.0" - "@storybook/global": "npm:^5.0.0" - "@storybook/manager": "npm:8.1.9" - "@storybook/manager-api": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/preview-api": "npm:8.1.9" - "@storybook/telemetry": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/detect-port": "npm:^1.3.0" - "@types/diff": "npm:^5.0.9" - "@types/node": "npm:^18.0.0" - "@types/pretty-hrtime": "npm:^1.0.0" - "@types/semver": "npm:^7.3.4" + "@storybook/csf": "npm:^0.1.11" better-opn: "npm:^3.0.2" - chalk: "npm:^4.1.0" - cli-table3: "npm:^0.6.1" - compression: "npm:^1.7.4" - detect-port: "npm:^1.3.0" - diff: "npm:^5.2.0" - express: "npm:^4.17.3" - fs-extra: "npm:^11.1.0" - globby: "npm:^14.0.1" - lodash: "npm:^4.17.21" - open: "npm:^8.4.0" - pretty-hrtime: "npm:^1.0.3" - prompts: "npm:^2.4.0" - read-pkg-up: "npm:^7.0.1" - semver: "npm:^7.3.7" - telejson: "npm:^7.2.0" - tiny-invariant: "npm:^1.3.1" - ts-dedent: "npm:^2.0.0" - util: "npm:^0.12.4" - util-deprecate: "npm:^1.0.2" - watchpack: "npm:^2.2.0" - ws: "npm:^8.2.3" - checksum: 6b00f1ee0216554e6bc503a02219b5755a54fa2865115270d167936ced27fef875dbfba98dfc8cce5d01b481b7a3759bf7a11b1f242560e0b33d56c77dd7bda7 - languageName: node - linkType: hard - -"@storybook/core-webpack@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/core-webpack@npm:8.1.9" - dependencies: - "@storybook/core-common": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/node": "npm:^18.0.0" - ts-dedent: "npm:^2.0.0" - checksum: 130fe864bbc568cb8ab3752f74c0fb4cfc1387761d54b84d594b0ff86982eb1f59d343c82096709a91217769fe8fcbae5f088db71e3a7ad27a6f4dfa51d795b8 - languageName: node - linkType: hard - -"@storybook/csf-plugin@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/csf-plugin@npm:8.1.9" - dependencies: - "@storybook/csf-tools": "npm:8.1.9" - unplugin: "npm:^1.3.1" - checksum: 53ab66ba49402e6316f0ce4163ea1ee446e814eb717819b8eb425bfa7abb272fbaf10fa584e635482137741d8a944cc2ed92bf81447549ce1b3259c6943a11e4 - languageName: node - linkType: hard - -"@storybook/csf-tools@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/csf-tools@npm:8.1.9" - dependencies: - "@babel/generator": "npm:^7.24.4" - "@babel/parser": "npm:^7.24.4" - "@babel/traverse": "npm:^7.24.1" - "@babel/types": "npm:^7.24.0" - "@storybook/csf": "npm:^0.1.7" - "@storybook/types": "npm:8.1.9" - fs-extra: "npm:^11.1.0" + browser-assert: "npm:^1.2.1" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0" + esbuild-register: "npm:^3.5.0" + jsdoc-type-pratt-parser: "npm:^4.0.0" + process: "npm:^0.11.10" recast: "npm:^0.23.5" - ts-dedent: "npm:^2.0.0" - checksum: d7c8a9181fdf68aafd577269ada5195447a4e5dbb34d105c9dec6ee05df20177670d6acc98d7c849b2a9c3f3cea80e2a6c730ac53cd72d0d3c1ca2d2c8ac63fa + semver: "npm:^7.6.2" + util: "npm:^0.12.5" + ws: "npm:^8.2.3" + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + checksum: 101bb9c13bc339572c071215bb9d2e5a7c514c67f6957dba1d0ed28ec993d6b1f8bd0d367fb3b49c80b5489131c744647878f6701695b868dfd5dbd73581a82c languageName: node linkType: hard -"@storybook/csf@npm:^0.1.7": - version: 0.1.7 - resolution: "@storybook/csf@npm:0.1.7" +"@storybook/csf-plugin@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/csf-plugin@npm:8.4.4" dependencies: - type-fest: "npm:^2.19.0" - checksum: aaebc9fa5f850cebef1fd9d786d7b5844e2d88e5c8078904ea4571c053f858fab064392960274b854037b9f8693d12c7c45c3c4c9142ec88a08fb498f3f056a5 - languageName: node - linkType: hard - -"@storybook/docs-mdx@npm:3.1.0-next.0": - version: 3.1.0-next.0 - resolution: "@storybook/docs-mdx@npm:3.1.0-next.0" - checksum: 7622d7c6318e842c90a71c1836d68531236c31fff7081c885803eddfafb7e3f8998689f612eaa0292209ada8352a36657dcacb5d3ef4632b8e8b8a283c39602e + unplugin: "npm:^1.3.1" + peerDependencies: + storybook: ^8.4.4 + checksum: d62e1288b0ed900af8f3c617496ceb908ffafd4b6cf7fc97c5e008cfa153d04245a18c9a008d6a59beb7720bbc88f272224dc19e2425db4b0d5d88ac38d2a885 languageName: node linkType: hard -"@storybook/docs-tools@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/docs-tools@npm:8.1.9" +"@storybook/csf@npm:^0.1.11": + version: 0.1.11 + resolution: "@storybook/csf@npm:0.1.11" dependencies: - "@storybook/core-common": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/preview-api": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/doctrine": "npm:^0.0.3" - assert: "npm:^2.1.0" - doctrine: "npm:^3.0.0" - lodash: "npm:^4.17.21" - checksum: 024b3b2d40eca87743f80c2846736d7071c8154220e107c72ea73dbdb7a8f1e1a30a1d17748a22097289760eb0aa6739983a2504f3e34cb397b7a123f5d07be3 + type-fest: "npm:^2.19.0" + checksum: c5329fc13e7d762049b5c91df1bc1c0e510a1a898c401b72b68f1ff64139a85ab64a92f8e681d2fcb226c0a4a55d0f23b569b2bdb517e0f067bd05ea46228356 languageName: node linkType: hard @@ -4726,66 +4111,25 @@ __metadata: languageName: node linkType: hard -"@storybook/icons@npm:^1.2.5": - version: 1.2.9 - resolution: "@storybook/icons@npm:1.2.9" +"@storybook/manager-api@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/manager-api@npm:8.4.4" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 37513dbf526bf827941ee274e0f8358c6db41c963ffd0c408a674d794fa9af8d835e0dc4e58fd589106c4f33da5552aa8315ae45745f0c107ade0f6299cbf710 + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 00d83105b8cd451c7b420d96eefaa8918254a9c362d852f8e825dd02a861994b0e80fc190f6bfab95d742a947319178587bbccb64d9051ad8f1b36533e7cb4ed languageName: node linkType: hard -"@storybook/manager-api@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/manager-api@npm:8.1.9" +"@storybook/preset-react-webpack@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/preset-react-webpack@npm:8.4.4" dependencies: - "@storybook/channels": "npm:8.1.9" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/csf": "npm:^0.1.7" - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^1.2.5" - "@storybook/router": "npm:8.1.9" - "@storybook/theming": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" - memoizerific: "npm:^1.11.3" - store2: "npm:^2.14.2" - telejson: "npm:^7.2.0" - ts-dedent: "npm:^2.0.0" - checksum: 279f066c53da7374766aa1f174914a54aa2b5a3151f7c67ccfe3f4b493f1329ba156cf968811bd5e22853e4a84ee40c32ade66e235ec1908b9ac162096450cbe - languageName: node - linkType: hard - -"@storybook/manager@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/manager@npm:8.1.9" - checksum: d20af7064fadee4f5e757f1d162b8d62e8d3c133db15c2878ec96fbd024902e73a68ce45f313c893463c6cf4c60a1a20c6334c056995f910a4e8fedfa65d78d9 - languageName: node - linkType: hard - -"@storybook/node-logger@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/node-logger@npm:8.1.9" - checksum: a75e4bc2b8560b0a74a0d0ef2afd825bd4e8419ce523a057af08d5dbda991a8fb4a52a5b9639325b70c68be53c77edab2bbf8e1c8bd4345d3f91940f98910f48 - languageName: node - linkType: hard - -"@storybook/preset-react-webpack@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/preset-react-webpack@npm:8.1.9" - dependencies: - "@storybook/core-webpack": "npm:8.1.9" - "@storybook/docs-tools": "npm:8.1.9" - "@storybook/node-logger": "npm:8.1.9" - "@storybook/react": "npm:8.1.9" + "@storybook/core-webpack": "npm:8.4.4" + "@storybook/react": "npm:8.4.4" "@storybook/react-docgen-typescript-plugin": "npm:1.0.6--canary.9.0c3f3b7.0" - "@types/node": "npm:^18.0.0" + "@types/node": "npm:^22.0.0" "@types/semver": "npm:^7.3.4" find-up: "npm:^5.0.0" - fs-extra: "npm:^11.1.0" magic-string: "npm:^0.30.5" react-docgen: "npm:^7.0.0" resolve: "npm:^1.22.8" @@ -4795,39 +4139,20 @@ __metadata: 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: ^8.4.4 peerDependenciesMeta: typescript: optional: true - checksum: f8dc63bbdba1abd05358c25960901603895a0654eb73ebfca4bf16fa9ca8d03c0b97e00b56222f63534779f7668689c428c7e4a5b9f6a49ef61839306a486512 - languageName: node - linkType: hard - -"@storybook/preview-api@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/preview-api@npm:8.1.9" - dependencies: - "@storybook/channels": "npm:8.1.9" - "@storybook/client-logger": "npm:8.1.9" - "@storybook/core-events": "npm:8.1.9" - "@storybook/csf": "npm:^0.1.7" - "@storybook/global": "npm:^5.0.0" - "@storybook/types": "npm:8.1.9" - "@types/qs": "npm:^6.9.5" - dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" - memoizerific: "npm:^1.11.3" - qs: "npm:^6.10.0" - tiny-invariant: "npm:^1.3.1" - ts-dedent: "npm:^2.0.0" - util-deprecate: "npm:^1.0.2" - checksum: a8b066cd7f136fc41d4026e3f9863fd527d874d84bc37c034dfccb3ffe5dba6c0ea54f81eedeae35cc09cbf0251ab6714829226ef04698984c3a476433752cec + checksum: c7e9b9b28e0247b5fb6cb92cc28c07a8d7b4d13dc17fb3806da1c9900625a7e56bdb20e3235f1acc0851ee263ec0d42a892ce9114dab766daa7c0b1726dbf71d languageName: node linkType: hard -"@storybook/preview@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/preview@npm:8.1.9" - checksum: 092a1ba03026a99cf4d25728e6cfb6b128fee004202889b46665caefc9dc44becaf807f97713deb5cf19f3379bf1d7f2acacdbbdcae23969e793dc359d47ccb6 +"@storybook/preview-api@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/preview-api@npm:8.4.4" + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 7adc0a4adde3a55cdd18fe645428a239c4d3802b92afdb17914719201893be8aec7cbd53203c9914c532ecd8970469df745f0097b677a04326e696470bc110cd languageName: node linkType: hard @@ -4849,140 +4174,104 @@ __metadata: languageName: node linkType: hard -"@storybook/react-dom-shim@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/react-dom-shim@npm:8.1.9" +"@storybook/react-dom-shim@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/react-dom-shim@npm:8.4.4" 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 - checksum: cf45b66c1f51000d6d4863eb148c6b2fbb27f06f67ab51630e60e0f546c70491c97c8a9ce8504632ab0e0cd3bdec2dc9b5cbec9cb2115aad48d92cf8add672f8 + storybook: ^8.4.4 + checksum: 112467460ce65d23311bd9f559f5c6af1343287f98ab765695e4dda5d17f3d7acb696d96457087285b8781f20bd8e0ace26eb00624affdc2620b9699a9b28591 languageName: node linkType: hard -"@storybook/react-webpack5@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/react-webpack5@npm:8.1.9" +"@storybook/react-vite@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/react-vite@npm:8.4.4" dependencies: - "@storybook/builder-webpack5": "npm:8.1.9" - "@storybook/preset-react-webpack": "npm:8.1.9" - "@storybook/react": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/node": "npm:^18.0.0" + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" + "@rollup/pluginutils": "npm:^5.0.2" + "@storybook/builder-vite": "npm:8.4.4" + "@storybook/react": "npm:8.4.4" + find-up: "npm:^5.0.0" + magic-string: "npm:^0.30.0" + react-docgen: "npm:^7.0.0" + resolve: "npm:^1.22.8" + tsconfig-paths: "npm:^4.2.0" 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 - typescript: ">= 4.2.x" - peerDependenciesMeta: - typescript: - optional: true - checksum: 59af36d070702a2b3163fc9bd9b5aa4d9d47461d788641fb4fdb52bde24b873e1f42d0f68ce362d37cfede670340715949a72887d0dd2c3b5ef091f3e217afd1 + storybook: ^8.4.4 + vite: ^4.0.0 || ^5.0.0 + checksum: 2e3abd5b61fe05a2aa784a744d4700d1c5e2644cf5cc2b23b083a7227627a550c2cb8744f4571b693c6a24e783b931c1bd87441d89d960d6f5da7eef14c8a7e2 languageName: node linkType: hard -"@storybook/react@npm:8.1.9, @storybook/react@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/react@npm:8.1.9" +"@storybook/react-webpack5@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/react-webpack5@npm:8.4.4" dependencies: - "@storybook/client-logger": "npm:8.1.9" - "@storybook/docs-tools": "npm:8.1.9" - "@storybook/global": "npm:^5.0.0" - "@storybook/preview-api": "npm:8.1.9" - "@storybook/react-dom-shim": "npm:8.1.9" - "@storybook/types": "npm:8.1.9" - "@types/escodegen": "npm:^0.0.6" - "@types/estree": "npm:^0.0.51" - "@types/node": "npm:^18.0.0" - acorn: "npm:^7.4.1" - acorn-jsx: "npm:^5.3.1" - acorn-walk: "npm:^7.2.0" - escodegen: "npm:^2.1.0" - html-tags: "npm:^3.1.0" - lodash: "npm:^4.17.21" - prop-types: "npm:^15.7.2" - react-element-to-jsx-string: "npm:^15.0.0" - semver: "npm:^7.3.7" - ts-dedent: "npm:^2.0.0" - type-fest: "npm:~2.19" - util-deprecate: "npm:^1.0.2" + "@storybook/builder-webpack5": "npm:8.4.4" + "@storybook/preset-react-webpack": "npm:8.4.4" + "@storybook/react": "npm:8.4.4" + "@types/node": "npm:^22.0.0" 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: ^8.4.4 typescript: ">= 4.2.x" peerDependenciesMeta: typescript: optional: true - checksum: 6cc8740057c632acb71af33afe7319d80dbffef52dc32e3dfb5ad1bc396fb5acd5bcf7ff78f717c9e0e33d5ff1ebd258fbf863d7dffba9eb2ed926a9d9eb758c - languageName: node - linkType: hard - -"@storybook/router@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/router@npm:8.1.9" - dependencies: - "@storybook/client-logger": "npm:8.1.9" - memoizerific: "npm:^1.11.3" - qs: "npm:^6.10.0" - checksum: 386ff4052441d1e5076b818fd888aeee33babd7da1c667dee40a8fd61109f3f2275abe7f06c6b6e0143ef2fb098f0b304091141cee8db7d7f447972554423e63 - languageName: node - linkType: hard - -"@storybook/source-loader@npm:8.1.9, @storybook/source-loader@npm:^8.1.9": - version: 8.1.9 - resolution: "@storybook/source-loader@npm:8.1.9" - dependencies: - "@storybook/csf": "npm:^0.1.7" - "@storybook/types": "npm:8.1.9" - estraverse: "npm:^5.2.0" - lodash: "npm:^4.17.21" - prettier: "npm:^3.1.1" - checksum: c6db6e38b48fac4bfaee6cd97ca5e06f3eadc748b66eddf0f3a7ebe50c14a80aa6aca1549a332fbd3690b89e884fdfabb91845a0ec7ccbff774b0ba64b7baa58 - languageName: node - linkType: hard - -"@storybook/telemetry@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/telemetry@npm:8.1.9" - dependencies: - "@storybook/client-logger": "npm:8.1.9" - "@storybook/core-common": "npm:8.1.9" - "@storybook/csf-tools": "npm:8.1.9" - chalk: "npm:^4.1.0" - detect-package-manager: "npm:^2.0.1" - fetch-retry: "npm:^5.0.2" - fs-extra: "npm:^11.1.0" - read-pkg-up: "npm:^7.0.1" - checksum: 4ad91964fd3a7af768ae660583862afec81f107b9d1d08a440d17b37aa32836c06fc00d4ab2871dc2bacc7e699b88aa46bf43cdf353a4aaaaa5457be5314d97c + checksum: c83d4e60c4a527aaff6e187bcff0f71f77ddc8dce32bd619d6c56c776f70a6087f1fa5835355be51478a645e0869c30a316af205ef6d61b835d2a2a94699dec3 languageName: node linkType: hard -"@storybook/theming@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/theming@npm:8.1.9" +"@storybook/react@npm:8.4.4, @storybook/react@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/react@npm:8.4.4" dependencies: - "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1" - "@storybook/client-logger": "npm:8.1.9" + "@storybook/components": "npm:8.4.4" "@storybook/global": "npm:^5.0.0" - memoizerific: "npm:^1.11.3" + "@storybook/manager-api": "npm:8.4.4" + "@storybook/preview-api": "npm:8.4.4" + "@storybook/react-dom-shim": "npm:8.4.4" + "@storybook/theming": "npm:8.4.4" peerDependencies: + "@storybook/test": 8.4.4 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: ^8.4.4 + typescript: ">= 4.2.x" peerDependenciesMeta: - react: + "@storybook/test": optional: true - react-dom: + typescript: optional: true - checksum: c340d53086527a5bd8ea8af7a8961679eecdefe5ce23c12d05127180a460e1824b667c27dfe42106d1812d75e8c754ca890c928b39e6947ef7ad8228a305188c + checksum: aabbfeb09efca705ee23673b62673760bbfa60307ca0f36d562b3541cbd999f943d4c5537971b67bc84ad513f53e82a0be56b418d5777ea499c33c04c7ca935d languageName: node linkType: hard -"@storybook/types@npm:8.1.9": - version: 8.1.9 - resolution: "@storybook/types@npm:8.1.9" +"@storybook/source-loader@npm:8.4.4, @storybook/source-loader@npm:^8.4.4": + version: 8.4.4 + resolution: "@storybook/source-loader@npm:8.4.4" dependencies: - "@storybook/channels": "npm:8.1.9" - "@types/express": "npm:^4.7.0" - file-system-cache: "npm:2.3.0" - checksum: e046651fdab5bcd64a4f91345ff79065bfd6b67fe5d88ccf9e19509906df484dbca59254e2ff7c8cc9bdd556e8cc0cf2e9f6cf5d7c529289583b5ebe8443dcb6 + "@storybook/csf": "npm:^0.1.11" + es-toolkit: "npm:^1.22.0" + estraverse: "npm:^5.2.0" + prettier: "npm:^3.1.1" + peerDependencies: + storybook: ^8.4.4 + checksum: 3f6edd3a0131c23023facd9d79475959bfbd2dbdcd8571326451a55c04e516e032400eb85f2cc796c7df0fcfda35d4fe435bd05e2dfece8c29cc517d5fac6470 + languageName: node + linkType: hard + +"@storybook/theming@npm:8.4.4": + version: 8.4.4 + resolution: "@storybook/theming@npm:8.4.4" + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 29b58bc6ef5ca7e2231f171ab360c12b3eeeac22747bed53cd61749f85cbe3f91c3cc6e3abf144f194043f624e79b3caa2ec6c77a0ea2584d7771b96061eb55e languageName: node linkType: hard @@ -5554,34 +4843,6 @@ __metadata: languageName: node linkType: hard -"@types/body-parser@npm:*": - version: 1.19.2 - resolution: "@types/body-parser@npm:1.19.2" - dependencies: - "@types/connect": "npm:*" - "@types/node": "npm:*" - checksum: c2dd533e1d4af958d656bdba7f376df68437d8dfb7e4522c88b6f3e6f827549e4be5bf0be68a5f1878accf5752ea37fba7e8a4b6dda53d0d122d77e27b69c750 - languageName: node - linkType: hard - -"@types/connect@npm:*": - version: 3.4.35 - resolution: "@types/connect@npm:3.4.35" - dependencies: - "@types/node": "npm:*" - checksum: f11a1ccfed540723dddd7cb496543ad40a2f663f22ff825e9b220f0bae86db8b1ced2184ee41d3fb358b019ad6519e39481b06386db91ebb859003ad1d54fe6a - languageName: node - linkType: hard - -"@types/cross-spawn@npm:^6.0.2": - version: 6.0.4 - resolution: "@types/cross-spawn@npm:6.0.4" - dependencies: - "@types/node": "npm:*" - checksum: 33df54e348b634d27a80c0512ec6c7d85ddcff000f53e14b906ed86e307222e6fff4a39f894ff2eb5f3d4543105eb9ba1af138a96e4d30eb9c1a17130b936018 - languageName: node - linkType: hard - "@types/d3-color@npm:^2": version: 2.0.3 resolution: "@types/d3-color@npm:2.0.3" @@ -5646,27 +4907,6 @@ __metadata: languageName: node linkType: hard -"@types/detect-port@npm:^1.3.0": - version: 1.3.2 - resolution: "@types/detect-port@npm:1.3.2" - checksum: 4c9ab349b8724e32879c1d241c374e674ce040783dc6768b19d844afff011d1a70adaaf93bf96e1ed33eef9c88cc6c27ce7dce82a1cec8c6e9992ae445a5a255 - languageName: node - linkType: hard - -"@types/diff@npm:^5.0.9": - version: 5.2.1 - resolution: "@types/diff@npm:5.2.1" - checksum: 62dcab32197ac67f212939cdd79aa3953327a482bec55c6a38ad9de8a0662a9f920b59504609a322fc242593bd9afb3d2704702f4bc98087a13171234b952361 - languageName: node - linkType: hard - -"@types/doctrine@npm:^0.0.3": - version: 0.0.3 - resolution: "@types/doctrine@npm:0.0.3" - checksum: 566dcdc988c97ff01d14493ceb2223643347f07cf0a88c86cd7cb7c2821cfc837fd39295e6809a29614fdfdc6c4e981408155ca909b2e5da5d947af939b6c966 - languageName: node - linkType: hard - "@types/doctrine@npm:^0.0.9": version: 0.0.9 resolution: "@types/doctrine@npm:0.0.9" @@ -5683,27 +4923,6 @@ __metadata: languageName: node linkType: hard -"@types/ejs@npm:^3.1.1": - version: 3.1.2 - resolution: "@types/ejs@npm:3.1.2" - checksum: 8e55275011009e7a44043d97348a4a1b5a7583e1f048b6ad8998f1b30667995314f15bc9cc9ed3e0e79722cce9a06845d06d5d023bca179bb00d52016b41ad7d - languageName: node - linkType: hard - -"@types/emscripten@npm:^1.39.6": - version: 1.39.9 - resolution: "@types/emscripten@npm:1.39.9" - checksum: d11461453315f4ba382f304717c64e907b10646af0f9ec0f64f34d604a79d8d839b9227dc9b95311b247c86a3bb4a7b95f5c971ad4fe079296836ad2245a48fe - languageName: node - linkType: hard - -"@types/escodegen@npm:^0.0.6": - version: 0.0.6 - resolution: "@types/escodegen@npm:0.0.6" - checksum: bbef189319c7b0386486bc7224369f118c7aedf35cc13e40ae5879b9ab4f848936f31e8eea50e71d4de72d4b7a77d9e6e9e5ceec4406c648fbc0077ede634ed5 - languageName: node - linkType: hard - "@types/estree@npm:1.0.5, @types/estree@npm:^1.0.5": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" @@ -5711,34 +4930,10 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:^0.0.51": - version: 0.0.51 - resolution: "@types/estree@npm:0.0.51" - checksum: a70c60d5e634e752fcd45b58c9c046ef22ad59ede4bc93ad5193c7e3b736ebd6bcd788ade59d9c3b7da6eeb0939235f011d4c59bb4fc04d8c346b76035099dd1 - languageName: node - linkType: hard - -"@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.35 - resolution: "@types/express-serve-static-core@npm:4.17.35" - dependencies: - "@types/node": "npm:*" - "@types/qs": "npm:*" - "@types/range-parser": "npm:*" - "@types/send": "npm:*" - checksum: 08db6ffff07b5d53d852bb0a078ea5ee6dc3eb581d8c8fdf0d65f48c641db2830658074c797844e618b0933ce4ca2ddd08191f9d79b12eb2ec3d66f8551716ec - languageName: node - linkType: hard - -"@types/express@npm:^4.7.0": - version: 4.17.17 - resolution: "@types/express@npm:4.17.17" - dependencies: - "@types/body-parser": "npm:*" - "@types/express-serve-static-core": "npm:^4.17.33" - "@types/qs": "npm:*" - "@types/serve-static": "npm:*" - checksum: 5802a0a28f7473744dd6a118479440d8c5c801c973d34fb6f31b5ee645a41fee936193978a8e905d55deefda9b675d19924167bf11a31339874c3161a3fc2922 +"@types/estree@npm:^1.0.0": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a languageName: node linkType: hard @@ -5756,21 +4951,22 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.3": - version: 4.1.6 - resolution: "@types/graceful-fs@npm:4.1.6" +"@types/glob@npm:^7.1.3": + version: 7.2.0 + resolution: "@types/glob@npm:7.2.0" dependencies: + "@types/minimatch": "npm:*" "@types/node": "npm:*" - checksum: b1d32c5ae7bd52cf60e29df20407904c4312a39612e7ec2ee23c1e3731c1cfe31d97c6941bf6cb52f5f929d50d86d92dd506436b63fafa833181d439b628885e + checksum: a8eb5d5cb5c48fc58c7ca3ff1e1ddf771ee07ca5043da6e4871e6757b4472e2e73b4cfef2644c38983174a4bc728c73f8da02845c28a1212f98cabd293ecae98 languageName: node linkType: hard -"@types/hast@npm:^3.0.0": - version: 3.0.4 - resolution: "@types/hast@npm:3.0.4" +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.6 + resolution: "@types/graceful-fs@npm:4.1.6" dependencies: - "@types/unist": "npm:*" - checksum: 3249781a511b38f1d330fd1e3344eed3c4e7ea8eff82e835d35da78e637480d36fad37a78be5a7aed8465d237ad0446abc1150859d0fde395354ea634decf9f7 + "@types/node": "npm:*" + checksum: b1d32c5ae7bd52cf60e29df20407904c4312a39612e7ec2ee23c1e3731c1cfe31d97c6941bf6cb52f5f929d50d86d92dd506436b63fafa833181d439b628885e languageName: node linkType: hard @@ -5870,31 +5066,17 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.167, @types/lodash@npm:^4.14.168, @types/lodash@npm:^4.14.175, @types/lodash@npm:~4.14.168": +"@types/lodash@npm:^4.14.168, @types/lodash@npm:^4.14.175, @types/lodash@npm:~4.14.168": version: 4.14.194 resolution: "@types/lodash@npm:4.14.194" checksum: 2d1ecf21a356bf089d3b5de2e8ddb1376526f0c75456fea61c03c14d276898f29a8ff75d290a32865dc74933617c9eed4ecdec048257031569df927a2c053c0e languageName: node linkType: hard -"@types/mdx@npm:^2.0.0": - version: 2.0.5 - resolution: "@types/mdx@npm:2.0.5" - checksum: f46932365a24ad6927dd87678598b839fa64ef8c9d0714b45a0185ac52427b374899ba96022f97330b27aca3572a6815f844cf345a50b9c0c483f485c243eda1 - languageName: node - linkType: hard - -"@types/mime@npm:*": - version: 3.0.1 - resolution: "@types/mime@npm:3.0.1" - checksum: c4c0fc89042822a3b5ffd6ef0da7006513454ee8376ffa492372d17d2925a4e4b1b194c977b718c711df38b33eb9d06deb5dbf9f851bcfb7e5e65f06b2a87f97 - languageName: node - linkType: hard - -"@types/mime@npm:^1": - version: 1.3.2 - resolution: "@types/mime@npm:1.3.2" - checksum: 61d144e5170c6cdf6de334ec0ee4bb499b1a0fb0233834a9e8cec6d289b0e3042bedf35cbc1c995d71a247635770dae3f13a9ddae69098bb54b933429bc08d35 +"@types/minimatch@npm:*": + version: 5.1.2 + resolution: "@types/minimatch@npm:5.1.2" + checksum: 83cf1c11748891b714e129de0585af4c55dd4c2cafb1f1d5233d79246e5e1e19d1b5ad9e8db449667b3ffa2b6c80125c429dbee1054e9efb45758dbc4e118562 languageName: node linkType: hard @@ -5935,10 +5117,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^18.0.0": - version: 18.18.6 - resolution: "@types/node@npm:18.18.6" - checksum: 50312053b0906058aa026e1c85c9125b4f0e8d6ae5e3699fb5bc8e0d5b9d1c2b12303902b2b91477c389f15ad40235d240b882819dd93a49bd6b46983f63be1c +"@types/node@npm:^22.0.0": + version: 22.9.0 + resolution: "@types/node@npm:22.9.0" + dependencies: + undici-types: "npm:~6.19.8" + checksum: 3f46cbe0a49bab4ba30494025e4c8a6e699b98ac922857aa1f0209ce11a1313ee46e6808b8f13fe5b8b960a9d7796b77c8d542ad4e9810e85ef897d5593b5d51 languageName: node linkType: hard @@ -5986,13 +5170,6 @@ __metadata: languageName: node linkType: hard -"@types/pretty-hrtime@npm:^1.0.0": - version: 1.0.1 - resolution: "@types/pretty-hrtime@npm:1.0.1" - checksum: e990110a3626e987319092c5149d5ea244785b83fbbd8e62605714ec1fa4317a3524ae0b6381cdc2ca92619d9a451b3fe9ff4085c42826f5398e3380d3031bff - languageName: node - linkType: hard - "@types/prop-types@npm:*, @types/prop-types@npm:^15.7.11": version: 15.7.11 resolution: "@types/prop-types@npm:15.7.11" @@ -6000,20 +5177,6 @@ __metadata: languageName: node linkType: hard -"@types/qs@npm:*, @types/qs@npm:^6.9.5": - version: 6.9.7 - resolution: "@types/qs@npm:6.9.7" - checksum: 157eb05f4c75790b0ebdcf7b0547ff117feabc8cda03c3cac3d3ea82bb19a1912e76a411df3eb0bdd01026a9770f07bc0e7e3fbe39ebb31c1be4564c16be35f1 - languageName: node - linkType: hard - -"@types/range-parser@npm:*": - version: 1.2.4 - resolution: "@types/range-parser@npm:1.2.4" - checksum: 8e3c3cda88675efd9145241bcb454449715b7d015a7fb80d018dcb3d441fa1938b302242cc0dfa6b02c5d014dd8bc082ae90091e62b1e816cae3ec36c2a7dbcb - languageName: node - linkType: hard - "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.3.0": version: 18.3.0 resolution: "@types/react-dom@npm:18.3.0" @@ -6041,7 +5204,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:>=18.0.0, @types/react@npm:^16.8.0 || ^17.0.0 || ^18.0.0, @types/react@npm:^18.3.3": +"@types/react@npm:*, @types/react@npm:>=18.0.0, @types/react@npm:^18.3.3": version: 18.3.3 resolution: "@types/react@npm:18.3.3" dependencies: @@ -6075,26 +5238,6 @@ __metadata: languageName: node linkType: hard -"@types/send@npm:*": - version: 0.17.1 - resolution: "@types/send@npm:0.17.1" - dependencies: - "@types/mime": "npm:^1" - "@types/node": "npm:*" - checksum: 1aad6bfafdaa3a3cadad1b441843dfd166821c0e93513daabe979de85b552a1298cfb6f07d40f80b5ecf14a3194dc148deb138605039841f1dadc7132c73e634 - languageName: node - linkType: hard - -"@types/serve-static@npm:*": - version: 1.15.1 - resolution: "@types/serve-static@npm:1.15.1" - dependencies: - "@types/mime": "npm:*" - "@types/node": "npm:*" - checksum: dc934e2adce730480af5af6081b99f50be4dfb7f44537893444bcf1dc97f5d5ffb16b38350ecd89dd114184d751ba3271500631fa56cf1faa35be56f8e45971b - languageName: node - linkType: hard - "@types/sinonjs__fake-timers@npm:8.1.1": version: 8.1.1 resolution: "@types/sinonjs__fake-timers@npm:8.1.1" @@ -6137,13 +5280,6 @@ __metadata: languageName: node linkType: hard -"@types/unist@npm:*, @types/unist@npm:^3.0.0": - version: 3.0.2 - resolution: "@types/unist@npm:3.0.2" - checksum: 39f220ce184a773c55c18a127062bfc4d0d30c987250cd59bab544d97be6cfec93717a49ef96e81f024b575718f798d4d329eb81c452fc57d6d051af8b043ebf - languageName: node - linkType: hard - "@types/use-sync-external-store@npm:^0.0.3": version: 0.0.3 resolution: "@types/use-sync-external-store@npm:0.0.3" @@ -6356,13 +5492,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.0.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d - languageName: node - linkType: hard - "@vitejs/plugin-react@npm:^4.2.1": version: 4.2.1 resolution: "@vitejs/plugin-react@npm:4.2.1" @@ -6588,37 +5717,6 @@ __metadata: languageName: node linkType: hard -"@yarnpkg/esbuild-plugin-pnp@npm:^3.0.0-rc.10": - version: 3.0.0-rc.15 - resolution: "@yarnpkg/esbuild-plugin-pnp@npm:3.0.0-rc.15" - dependencies: - tslib: "npm:^2.4.0" - peerDependencies: - esbuild: ">=0.10.0" - checksum: 5095bc316862971add31ca1fadb0095b6ad15f25120f6ab3a06086bb6a7be93c2f3c45bff80d5976689fc89b0e9bf82bd3d410e205c852739874d32d050c4e57 - languageName: node - linkType: hard - -"@yarnpkg/fslib@npm:2.10.3": - version: 2.10.3 - resolution: "@yarnpkg/fslib@npm:2.10.3" - dependencies: - "@yarnpkg/libzip": "npm:^2.3.0" - tslib: "npm:^1.13.0" - checksum: c4fbbed99e801f17c381204e9699d9ea4fb51b14e99968985f477bdbc7b02b61e026860173f3f46bd60d9f46ae6a06f420a3edb3c02c3a45ae83779095928094 - languageName: node - linkType: hard - -"@yarnpkg/libzip@npm:2.3.0, @yarnpkg/libzip@npm:^2.3.0": - version: 2.3.0 - resolution: "@yarnpkg/libzip@npm:2.3.0" - dependencies: - "@types/emscripten": "npm:^1.39.6" - tslib: "npm:^1.13.0" - checksum: 0c2361ccb002e28463ed98541f3bdaab54f52aad6a2080666c2a9ea605ebd9cdfb7b0340b1db6f105820d05bcb803cdfb3ce755a8f6034657298c291bf884f81 - languageName: node - linkType: hard - "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -6689,7 +5787,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.5, accepts@npm:~1.3.8": +"accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -6727,7 +5825,7 @@ __metadata: languageName: node linkType: hard -"acorn-jsx@npm:^5.2.0, acorn-jsx@npm:^5.3.1, acorn-jsx@npm:^5.3.2": +"acorn-jsx@npm:^5.2.0, acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" peerDependencies: @@ -6736,13 +5834,6 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^7.2.0": - version: 7.2.0 - resolution: "acorn-walk@npm:7.2.0" - checksum: ff99f3406ed8826f7d6ef6ac76b7608f099d45a1ff53229fa267125da1924188dbacf02e7903dfcfd2ae4af46f7be8847dc7d564c73c4e230dfb69c8ea8e6b4c - languageName: node - linkType: hard - "acorn-walk@npm:^8.0.2": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" @@ -6759,7 +5850,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.1.1, acorn@npm:^7.4.1": +"acorn@npm:^7.1.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" bin: @@ -6768,7 +5859,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.1.0, acorn@npm:^8.10.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2": +"acorn@npm:^8.1.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -6777,6 +5868,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.14.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" + bin: + acorn: bin/acorn + checksum: 6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7 + languageName: node + linkType: hard + "add-stream@npm:^1.0.0": version: 1.0.0 resolution: "add-stream@npm:1.0.0" @@ -6784,13 +5884,6 @@ __metadata: languageName: node linkType: hard -"address@npm:^1.0.1": - version: 1.1.2 - resolution: "address@npm:1.1.2" - checksum: 3ac908133d1d8cc52110473833718e82775428e73b4eb51b42cd7c7f571c7459c28c3c54592231efdcb96f6ed376eb490194e97c533df9e8efb910fa29a34e55 - languageName: node - linkType: hard - "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -6995,13 +6088,6 @@ __metadata: languageName: node linkType: hard -"app-root-dir@npm:^1.0.2": - version: 1.0.2 - resolution: "app-root-dir@npm:1.0.2" - checksum: 0225e4be7788968a82bb76df9b14b0d7f212a5c12e8c625cdc34f80548780bcbfc5f3287d0806dddd83bf9dbf9ce302e76b2887cd3a6f4be52b79df7f3aa9e7c - languageName: node - linkType: hard - "aproba@npm:^1.0.3 || ^2.0.0": version: 2.0.0 resolution: "aproba@npm:2.0.0" @@ -7042,15 +6128,6 @@ __metadata: languageName: node linkType: hard -"aria-hidden@npm:^1.1.1": - version: 1.2.3 - resolution: "aria-hidden@npm:1.2.3" - dependencies: - tslib: "npm:^2.0.0" - checksum: 46b07b7273167ad3fc2625f1ecbb43f8e6f73115c66785cbb5dcf1e2508133a43b6419d610c39676ceaeb563239efbd8974d5c0187695db8b3e8c3e11f549c2d - languageName: node - linkType: hard - "aria-query@npm:5.3.0, aria-query@npm:^5.0.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" @@ -7177,19 +6254,6 @@ __metadata: languageName: node linkType: hard -"assert@npm:^2.1.0": - version: 2.1.0 - resolution: "assert@npm:2.1.0" - dependencies: - call-bind: "npm:^1.0.2" - is-nan: "npm:^1.3.2" - object-is: "npm:^1.1.5" - object.assign: "npm:^4.1.4" - util: "npm:^0.12.5" - checksum: 7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 - languageName: node - linkType: hard - "ast-types-flow@npm:^0.0.7": version: 0.0.7 resolution: "ast-types-flow@npm:0.0.7" @@ -7581,13 +6645,6 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: c8139662d57f8833a44802f4b65be911679c569535ea73c5cfd3c1c8994eaead1b84b6f63e1db63833e4d4cacb6b6a9e5522178113dfdc8e4c81ed8436f1e8cc - languageName: node - linkType: hard - "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -7647,15 +6704,6 @@ __metadata: languageName: node linkType: hard -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: "npm:^1.6.44" - checksum: ce79c69e0f6efe506281e7c84e3712f7d12978991675b6e3a58a295b16f13ca81aa9b845c335614a545e0af728c8311b6aa3142af76ba1cb616af9bbac5c4a9f - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -7691,15 +6739,6 @@ __metadata: languageName: node linkType: hard -"browserify-zlib@npm:^0.1.4": - version: 0.1.4 - resolution: "browserify-zlib@npm:0.1.4" - dependencies: - pako: "npm:~0.2.0" - checksum: 0cde7ca5d33d43125649330fd75c056397e53731956a2593c4a2529f4e609a8e6abdb2b8e1921683abf5645375b92cfb2a21baa42fe3c9fc3e2556d32043af93 - languageName: node - linkType: hard - "browserslist@npm:^4.21.10, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0": version: 4.23.3 resolution: "browserslist@npm:4.23.3" @@ -7793,13 +6832,6 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.0.0": - version: 3.0.0 - resolution: "bytes@npm:3.0.0" - checksum: 91d42c38601c76460519ffef88371caacaea483a354c8e4b8808e7b027574436a5713337c003ea3de63ee4991c2a9a637884fdfe7f761760d746929d9e8fec60 - languageName: node - linkType: hard - "bytes@npm:3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -8089,13 +7121,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^1.1.1": - version: 1.1.4 - resolution: "chownr@npm:1.1.4" - checksum: ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db - languageName: node - linkType: hard - "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -8193,7 +7218,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.1, cli-table3@npm:~0.6.1": +"cli-table3@npm:~0.6.1": version: 0.6.1 resolution: "cli-table3@npm:0.6.1" dependencies: @@ -8361,7 +7386,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.10, colorette@npm:^2.0.16, colorette@npm:^2.0.17, colorette@npm:^2.0.19": +"colorette@npm:^2.0.10, colorette@npm:^2.0.16, colorette@npm:^2.0.17": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40 @@ -8404,14 +7429,7 @@ __metadata: "commander@npm:^5.1.0": version: 5.1.0 resolution: "commander@npm:5.1.0" - checksum: da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d - languageName: node - linkType: hard - -"commander@npm:^6.2.1": - version: 6.2.1 - resolution: "commander@npm:6.2.1" - checksum: 85748abd9d18c8bc88febed58b98f66b7c591d9b5017cad459565761d7b29ca13b7783ea2ee5ce84bf235897333706c4ce29adf1ce15c8252780e7000e2ce9ea + checksum: da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d languageName: node linkType: hard @@ -8460,30 +7478,6 @@ __metadata: languageName: node linkType: hard -"compressible@npm:~2.0.16": - version: 2.0.18 - resolution: "compressible@npm:2.0.18" - dependencies: - mime-db: "npm:>= 1.43.0 < 2" - checksum: 8a03712bc9f5b9fe530cc5a79e164e665550d5171a64575d7dcf3e0395d7b4afa2d79ab176c61b5b596e28228b350dd07c1a2a6ead12fd81d1b6cd632af2fef7 - languageName: node - linkType: hard - -"compression@npm:^1.7.4": - version: 1.7.4 - resolution: "compression@npm:1.7.4" - dependencies: - accepts: "npm:~1.3.5" - bytes: "npm:3.0.0" - compressible: "npm:~2.0.16" - debug: "npm:2.6.9" - on-headers: "npm:~1.0.2" - safe-buffer: "npm:5.1.2" - vary: "npm:~1.1.2" - checksum: 138db836202a406d8a14156a5564fb1700632a76b6e7d1546939472895a5304f2b23c80d7a22bf44c767e87a26e070dbc342ea63bb45ee9c863354fa5556bbbc - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -8846,15 +7840,6 @@ __metadata: languageName: node linkType: hard -"crypto-random-string@npm:^4.0.0": - version: 4.0.0 - resolution: "crypto-random-string@npm:4.0.0" - dependencies: - type-fest: "npm:^1.0.1" - checksum: 16e11a3c8140398f5408b7fded35a961b9423c5dac39a60cbbd08bd3f0e07d7de130e87262adea7db03ec1a7a4b7551054e0db07ee5408b012bac5400cfc07a5 - languageName: node - linkType: hard - "css-box-model@npm:^1.2.1": version: 1.2.1 resolution: "css-box-model@npm:1.2.1" @@ -9231,7 +8216,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.6.0, debug@npm:^2.6.9": +"debug@npm:2.6.9, debug@npm:^2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -9320,16 +8305,6 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: "npm:^0.2.0" - untildify: "npm:^4.0.0" - checksum: 8db3ab882eb3e1e8b59d84c8641320e6c66d8eeb17eb4bb848b7dd549b1e6fd313988e4a13542e95fbaeff03f6e9dedc5ad191ad4df7996187753eb0d45c00b7 - languageName: node - linkType: hard - "defaults@npm:^1.0.3": version: 1.0.3 resolution: "defaults@npm:1.0.3" @@ -9368,13 +8343,6 @@ __metadata: languageName: node linkType: hard -"defu@npm:^6.1.2": - version: 6.1.2 - resolution: "defu@npm:6.1.2" - checksum: ceb467f8f30d4000ae5300105904736113826a3d4124640b70e145b243d6c78c868de03634038d870e0855ff4cdfd17324a8caf7386229501a5bb776adb682f4 - languageName: node - linkType: hard - "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -9476,13 +8444,6 @@ __metadata: languageName: node linkType: hard -"detect-indent@npm:^6.1.0": - version: 6.1.0 - resolution: "detect-indent@npm:6.1.0" - checksum: dd83cdeda9af219cf77f5e9a0dc31d828c045337386cfb55ce04fad94ba872ee7957336834154f7647b89b899c3c7acc977c57a79b7c776b506240993f97acc7 - languageName: node - linkType: hard - "detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -9490,35 +8451,6 @@ __metadata: languageName: node linkType: hard -"detect-node-es@npm:^1.1.0": - version: 1.1.0 - resolution: "detect-node-es@npm:1.1.0" - checksum: e562f00de23f10c27d7119e1af0e7388407eb4b06596a25f6d79a360094a109ff285de317f02b090faae093d314cf6e73ac3214f8a5bb3a0def5bece94557fbe - languageName: node - linkType: hard - -"detect-package-manager@npm:^2.0.1": - version: 2.0.1 - resolution: "detect-package-manager@npm:2.0.1" - dependencies: - execa: "npm:^5.1.1" - checksum: 56ffd65228d1ff3ead5ea7f8ab951a517a29270de27510b790c9a8b77d4f36efbd61493e170ca77ee3dc13cbb5218583ce65b78ad14a59dc48565c9bcbbf3c71 - languageName: node - linkType: hard - -"detect-port@npm:^1.3.0": - version: 1.3.0 - resolution: "detect-port@npm:1.3.0" - dependencies: - address: "npm:^1.0.1" - debug: "npm:^2.6.0" - bin: - detect: ./bin/detect-port - detect-port: ./bin/detect-port - checksum: 6cafbd72d4f20860ea580b2f06e4c3350452ecb9acdfc1051c49b8a3dfa6f3d6bb252a69c0e97b3c5e13a2fa31a368aca2f7102e996e2caa7c938f3053b72b62 - languageName: node - linkType: hard - "diacritic@npm:0.0.2": version: 0.0.2 resolution: "diacritic@npm:0.0.2" @@ -9540,13 +8472,6 @@ __metadata: languageName: node linkType: hard -"diff@npm:^5.2.0": - version: 5.2.0 - resolution: "diff@npm:5.2.0" - checksum: aed0941f206fe261ecb258dc8d0ceea8abbde3ace5827518ff8d302f0fc9cc81ce116c4d8f379151171336caf0516b79e01abdc1ed1201b6440d895a66689eb4 - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -9696,14 +8621,14 @@ __metadata: languageName: node linkType: hard -"dotenv-expand@npm:^10.0.0, dotenv-expand@npm:~10.0.0": +"dotenv-expand@npm:~10.0.0": version: 10.0.0 resolution: "dotenv-expand@npm:10.0.0" checksum: 298f5018e29cfdcb0b5f463ba8e8627749103fbcf6cf81c561119115754ed582deee37b49dfc7253028aaba875ab7aea5fa90e5dac88e511d009ab0e6677924e languageName: node linkType: hard -"dotenv@npm:^16.0.0, dotenv@npm:~16.3.1": +"dotenv@npm:~16.3.1": version: 16.3.2 resolution: "dotenv@npm:16.3.2" checksum: a87d62cef0810b670cb477db1a24a42a093b6b428c9e65c185ce1d6368ad7175234b13547718ba08da18df43faae4f814180cc0366e11be1ded2277abc4dd22e @@ -9724,18 +8649,6 @@ __metadata: languageName: node linkType: hard -"duplexify@npm:^3.5.0, duplexify@npm:^3.6.0": - version: 3.7.1 - resolution: "duplexify@npm:3.7.1" - dependencies: - end-of-stream: "npm:^1.0.0" - inherits: "npm:^2.0.1" - readable-stream: "npm:^2.0.0" - stream-shift: "npm:^1.0.0" - checksum: 59d1440c1b4e3a4db35ae96933392703ce83518db1828d06b9b6322920d6cbbf0b7159e88be120385fe459e77f1eb0c7622f26e9ec1f47c9ff05c2b35747dbd3 - languageName: node - linkType: hard - "e2e@workspace:cypress": version: 0.0.0-use.local resolution: "e2e@workspace:cypress" @@ -9847,7 +8760,7 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.0.0, end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": version: 1.4.4 resolution: "end-of-stream@npm:1.4.4" dependencies: @@ -9867,7 +8780,7 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.17.1": +"enhanced-resolve@npm:^5.17.1, enhanced-resolve@npm:^5.7.0": version: 5.17.1 resolution: "enhanced-resolve@npm:5.17.1" dependencies: @@ -9914,7 +8827,7 @@ __metadata: languageName: node linkType: hard -"envinfo@npm:7.8.1, envinfo@npm:^7.7.3": +"envinfo@npm:7.8.1": version: 7.8.1 resolution: "envinfo@npm:7.8.1" bin: @@ -10015,10 +8928,15 @@ __metadata: languageName: node linkType: hard -"esbuild-plugin-alias@npm:^0.2.1": - version: 0.2.1 - resolution: "esbuild-plugin-alias@npm:0.2.1" - checksum: a67bc6bc2744fc8637f7321f00c1f00e4fae86c182662421738ebfabf3ad344967b9c667185c6c34d9edd5b289807d34bfdceef94620e94e0a45683534af69e0 +"es-toolkit@npm:^1.22.0": + version: 1.27.0 + resolution: "es-toolkit@npm:1.27.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + checksum: c2ac707635237252efd8cade7301cdf313926ad6fabf67fdcf04dca37dbd446247b6c2a350f3081515b1e6ce1c8044f7331ed306124483cfdf4e371ddc944b1f languageName: node linkType: hard @@ -10033,33 +8951,34 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0": - version: 0.20.2 - resolution: "esbuild@npm:0.20.2" - dependencies: - "@esbuild/aix-ppc64": "npm:0.20.2" - "@esbuild/android-arm": "npm:0.20.2" - "@esbuild/android-arm64": "npm:0.20.2" - "@esbuild/android-x64": "npm:0.20.2" - "@esbuild/darwin-arm64": "npm:0.20.2" - "@esbuild/darwin-x64": "npm:0.20.2" - "@esbuild/freebsd-arm64": "npm:0.20.2" - "@esbuild/freebsd-x64": "npm:0.20.2" - "@esbuild/linux-arm": "npm:0.20.2" - "@esbuild/linux-arm64": "npm:0.20.2" - "@esbuild/linux-ia32": "npm:0.20.2" - "@esbuild/linux-loong64": "npm:0.20.2" - "@esbuild/linux-mips64el": "npm:0.20.2" - "@esbuild/linux-ppc64": "npm:0.20.2" - "@esbuild/linux-riscv64": "npm:0.20.2" - "@esbuild/linux-s390x": "npm:0.20.2" - "@esbuild/linux-x64": "npm:0.20.2" - "@esbuild/netbsd-x64": "npm:0.20.2" - "@esbuild/openbsd-x64": "npm:0.20.2" - "@esbuild/sunos-x64": "npm:0.20.2" - "@esbuild/win32-arm64": "npm:0.20.2" - "@esbuild/win32-ia32": "npm:0.20.2" - "@esbuild/win32-x64": "npm:0.20.2" +"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0": + version: 0.24.0 + resolution: "esbuild@npm:0.24.0" + dependencies: + "@esbuild/aix-ppc64": "npm:0.24.0" + "@esbuild/android-arm": "npm:0.24.0" + "@esbuild/android-arm64": "npm:0.24.0" + "@esbuild/android-x64": "npm:0.24.0" + "@esbuild/darwin-arm64": "npm:0.24.0" + "@esbuild/darwin-x64": "npm:0.24.0" + "@esbuild/freebsd-arm64": "npm:0.24.0" + "@esbuild/freebsd-x64": "npm:0.24.0" + "@esbuild/linux-arm": "npm:0.24.0" + "@esbuild/linux-arm64": "npm:0.24.0" + "@esbuild/linux-ia32": "npm:0.24.0" + "@esbuild/linux-loong64": "npm:0.24.0" + "@esbuild/linux-mips64el": "npm:0.24.0" + "@esbuild/linux-ppc64": "npm:0.24.0" + "@esbuild/linux-riscv64": "npm:0.24.0" + "@esbuild/linux-s390x": "npm:0.24.0" + "@esbuild/linux-x64": "npm:0.24.0" + "@esbuild/netbsd-x64": "npm:0.24.0" + "@esbuild/openbsd-arm64": "npm:0.24.0" + "@esbuild/openbsd-x64": "npm:0.24.0" + "@esbuild/sunos-x64": "npm:0.24.0" + "@esbuild/win32-arm64": "npm:0.24.0" + "@esbuild/win32-ia32": "npm:0.24.0" + "@esbuild/win32-x64": "npm:0.24.0" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -10097,6 +9016,8 @@ __metadata: optional: true "@esbuild/netbsd-x64": optional: true + "@esbuild/openbsd-arm64": + optional: true "@esbuild/openbsd-x64": optional: true "@esbuild/sunos-x64": @@ -10109,7 +9030,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 66398f9fb2c65e456a3e649747b39af8a001e47963b25e86d9c09d2a48d61aa641b27da0ce5cad63df95ad246105e1d83e7fee0e1e22a0663def73b1c5101112 + checksum: 9f1aadd8d64f3bff422ae78387e66e51a5e09de6935a6f987b6e4e189ed00fdc2d1bc03d2e33633b094008529c8b6e06c7ad1a9782fb09fec223bf95998c0683 languageName: node linkType: hard @@ -10228,7 +9149,7 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.0.0, escodegen@npm:^2.1.0": +"escodegen@npm:^2.0.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" dependencies: @@ -10669,6 +9590,13 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^2.0.2": + version: 2.0.2 + resolution: "estree-walker@npm:2.0.2" + checksum: 53a6c54e2019b8c914dc395890153ffdc2322781acf4bd7d1a32d7aedc1710807bdcd866ac133903d5629ec601fbb50abe8c2e5553c7f5a0afdd9b6af6c945af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -10967,7 +9895,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.9": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -11051,13 +9979,6 @@ __metadata: languageName: node linkType: hard -"fetch-retry@npm:^5.0.2": - version: 5.0.6 - resolution: "fetch-retry@npm:5.0.6" - checksum: 349f50db631039630e915f70c763469cb696f3ac92ca6f63823109334a2bc62f63670b8c5a5c7e0195c39df517e60ef385cc5264f4c4904d0c6707d371fa8999 - languageName: node - linkType: hard - "figures@npm:3.2.0, figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -11126,16 +10047,6 @@ __metadata: languageName: node linkType: hard -"file-system-cache@npm:2.3.0": - version: 2.3.0 - resolution: "file-system-cache@npm:2.3.0" - dependencies: - fs-extra: "npm:11.1.1" - ramda: "npm:0.29.0" - checksum: 43de19f0db32e6546bb7abeecb1d6ea83c1eca23b38905c9415a29f6219cc9d6d87b0c1a6aca92c46a0f1bc276241a339f2f68b8aa0ca5c2eb64b6e1e3e4da01 - languageName: node - linkType: hard - "filelist@npm:^1.0.1": version: 1.0.2 resolution: "filelist@npm:1.0.2" @@ -11194,7 +10105,7 @@ __metadata: languageName: node linkType: hard -"find-cache-dir@npm:^3.0.0, find-cache-dir@npm:^3.3.1": +"find-cache-dir@npm:^3.3.1": version: 3.3.2 resolution: "find-cache-dir@npm:3.3.2" dependencies: @@ -11444,25 +10355,25 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:11.1.1, fs-extra@npm:^11.1.0, fs-extra@npm:^11.1.1": - version: 11.1.1 - resolution: "fs-extra@npm:11.1.1" +"fs-extra@npm:^10.0.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: a2480243d7dcfa7d723c5f5b24cf4eba02a6ccece208f1524a2fbde1c629492cfb9a59e4b6d04faff6fbdf71db9fdc8ef7f396417a02884195a625f5d8dc9427 + checksum: 5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e languageName: node linkType: hard -"fs-extra@npm:^10.0.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" +"fs-extra@npm:^11.1.0, fs-extra@npm:^11.1.1": + version: 11.1.1 + resolution: "fs-extra@npm:11.1.1" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e + checksum: a2480243d7dcfa7d723c5f5b24cf4eba02a6ccece208f1524a2fbde1c629492cfb9a59e4b6d04faff6fbdf71db9fdc8ef7f396417a02884195a625f5d8dc9427 languageName: node linkType: hard @@ -11612,20 +10523,6 @@ __metadata: languageName: node linkType: hard -"get-nonce@npm:^1.0.0": - version: 1.0.1 - resolution: "get-nonce@npm:1.0.1" - checksum: 2d7df55279060bf0568549e1ffc9b84bc32a32b7541675ca092dce56317cdd1a59a98dcc4072c9f6a980779440139a3221d7486f52c488e69dc0fd27b1efb162 - languageName: node - linkType: hard - -"get-npm-tarball-url@npm:^2.0.3": - version: 2.0.3 - resolution: "get-npm-tarball-url@npm:2.0.3" - checksum: fdf7a830d2602dd3d86285f412c9b2984ffe6ce854e1854e9548ea2b2f09f663b83791a31703552f8c72266d67c72e94c70f8d50a886fe5179d2f07a383660d8 - languageName: node - linkType: hard - "get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" @@ -11721,23 +10618,6 @@ __metadata: languageName: node linkType: hard -"giget@npm:^1.0.0": - version: 1.1.2 - resolution: "giget@npm:1.1.2" - dependencies: - colorette: "npm:^2.0.19" - defu: "npm:^6.1.2" - https-proxy-agent: "npm:^5.0.1" - mri: "npm:^1.2.0" - node-fetch-native: "npm:^1.0.2" - pathe: "npm:^1.1.0" - tar: "npm:^6.1.13" - bin: - giget: dist/cli.mjs - checksum: fc76d1042df3027c468f74320f7333ce3f99a84b7cd701683cffc386a35c53699a5c32b816b635f3cdf12956c3e85df4592ffbb31f01b8da6a8d943521c9e2e4 - languageName: node - linkType: hard - "git-raw-commits@npm:^3.0.0": version: 3.0.0 resolution: "git-raw-commits@npm:3.0.0" @@ -11801,13 +10681,6 @@ __metadata: languageName: node linkType: hard -"github-slugger@npm:^2.0.0": - version: 2.0.0 - resolution: "github-slugger@npm:2.0.0" - checksum: 21b912b6b1e48f1e5a50b2292b48df0ff6abeeb0691b161b3d93d84f4ae6b1acd6ae23702e914af7ea5d441c096453cf0f621b72d57893946618d21dd1a1c486 - languageName: node - linkType: hard - "glob-parent@npm:5.1.2, glob-parent@npm:^5.0.0, glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -11826,6 +10699,17 @@ __metadata: languageName: node linkType: hard +"glob-promise@npm:^4.2.0": + version: 4.2.2 + resolution: "glob-promise@npm:4.2.2" + dependencies: + "@types/glob": "npm:^7.1.3" + peerDependencies: + glob: ^7.1.6 + checksum: 3eb01bed2901539365df6a4d27800afb8788840647d01f9bf3500b3de756597f2ff4b8c823971ace34db228c83159beca459dc42a70968d4e9c8200ed2cc96bd + languageName: node + linkType: hard + "glob-to-regexp@npm:^0.4.0, glob-to-regexp@npm:^0.4.1": version: 0.4.1 resolution: "glob-to-regexp@npm:0.4.1" @@ -11847,7 +10731,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2": +"glob@npm:^10.2.2": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -11876,6 +10760,20 @@ __metadata: languageName: node linkType: hard +"glob@npm:^7.2.0": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + "glob@npm:^8.0.1": version: 8.0.3 resolution: "glob@npm:8.0.3" @@ -11968,20 +10866,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^14.0.1": - version: 14.0.1 - resolution: "globby@npm:14.0.1" - dependencies: - "@sindresorhus/merge-streams": "npm:^2.1.0" - fast-glob: "npm:^3.3.2" - ignore: "npm:^5.2.4" - path-type: "npm:^5.0.0" - slash: "npm:^5.1.0" - unicorn-magic: "npm:^0.1.0" - checksum: 749a6be91cf455c161ebb5c9130df3991cb9fd7568425db850a8279a6cf45acd031c5069395beb7aeb4dd606b64f0d6ff8116c93726178d8e6182fee58c2736d - languageName: node - linkType: hard - "gopd@npm:^1.0.1": version: 1.0.1 resolution: "gopd@npm:1.0.1" @@ -12057,22 +10941,6 @@ __metadata: languageName: node linkType: hard -"gunzip-maybe@npm:^1.4.2": - version: 1.4.2 - resolution: "gunzip-maybe@npm:1.4.2" - dependencies: - browserify-zlib: "npm:^0.1.4" - is-deflate: "npm:^1.0.0" - is-gzip: "npm:^1.0.0" - peek-stream: "npm:^1.1.0" - pumpify: "npm:^1.3.3" - through2: "npm:^2.0.3" - bin: - gunzip-maybe: bin.js - checksum: 42798a8061759885c2084e1804e51313d14f2dc9cf6c137e222953ec802f914e592d6f9dbf6ad67f4e78eb036e86db017d9c7c93bb23e90cd5ae09326296ed77 - languageName: node - linkType: hard - "handlebars@npm:^4.7.7": version: 4.7.7 resolution: "handlebars@npm:4.7.7" @@ -12176,33 +11044,6 @@ __metadata: languageName: node linkType: hard -"hast-util-heading-rank@npm:^3.0.0": - version: 3.0.0 - resolution: "hast-util-heading-rank@npm:3.0.0" - dependencies: - "@types/hast": "npm:^3.0.0" - checksum: 1879c84f629e73f1f13247ab349324355cd801363b44e3d46f763aa5c0ea3b42dcd47b46e5643a0502cf01a6b1fdb9208fd12852e44ca6c671b3e4bccf9369a1 - languageName: node - linkType: hard - -"hast-util-is-element@npm:^3.0.0": - version: 3.0.0 - resolution: "hast-util-is-element@npm:3.0.0" - dependencies: - "@types/hast": "npm:^3.0.0" - checksum: f5361e4c9859c587ca8eb0d8343492f3077ccaa0f58a44cd09f35d5038f94d65152288dcd0c19336ef2c9491ec4d4e45fde2176b05293437021570aa0bc3613b - languageName: node - linkType: hard - -"hast-util-to-string@npm:^3.0.0": - version: 3.0.0 - resolution: "hast-util-to-string@npm:3.0.0" - dependencies: - "@types/hast": "npm:^3.0.0" - checksum: 649edd993cf244563ad86d861aa0863759a4fbec49c43b3d92240e42aa4b69f0c3332ddff9e80954bbd8756c86b0fddc20e97d281c6da59d00427f45da8dab68 - languageName: node - linkType: hard - "he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -12304,13 +11145,6 @@ __metadata: languageName: node linkType: hard -"html-tags@npm:^3.1.0": - version: 3.3.1 - resolution: "html-tags@npm:3.3.1" - checksum: 680165e12baa51bad7397452d247dbcc5a5c29dac0e6754b1187eee3bf26f514bc1907a431dd2f7eb56207611ae595ee76a0acc8eaa0d931e72c791dd6463d79 - languageName: node - linkType: hard - "html-webpack-plugin@npm:^5.5.0": version: 5.5.1 resolution: "html-webpack-plugin@npm:5.5.1" @@ -12535,7 +11369,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.0.4, ignore@npm:^5.2.0, ignore@npm:^5.2.4": +"ignore@npm:^5.0.4, ignore@npm:^5.2.0": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd @@ -12626,7 +11460,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -12792,15 +11626,6 @@ __metadata: languageName: node linkType: hard -"invariant@npm:^2.2.4": - version: 2.2.4 - resolution: "invariant@npm:2.2.4" - dependencies: - loose-envify: "npm:^1.0.0" - checksum: 5af133a917c0bcf65e84e7f23e779e7abc1cd49cb7fdc62d00d1de74b0d8c1b5ee74ac7766099fb3be1b05b26dfc67bab76a17030d2fe7ea2eef867434362dfc - languageName: node - linkType: hard - "ip@npm:^1.1.5": version: 1.1.9 resolution: "ip@npm:1.1.9" @@ -12815,13 +11640,6 @@ __metadata: languageName: node linkType: hard -"is-absolute-url@npm:^4.0.0": - version: 4.0.1 - resolution: "is-absolute-url@npm:4.0.1" - checksum: 6f8f603945bd9f2c6031758bbc12352fc647bd5d807cad10d96cc6300fd0e15240cc091521a61db767e4ec0bacff257b4f1015fd5249c147bbb4a4497356c72e - languageName: node - linkType: hard - "is-arguments@npm:^1.0.4": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" @@ -12914,13 +11732,6 @@ __metadata: languageName: node linkType: hard -"is-deflate@npm:^1.0.0": - version: 1.0.0 - resolution: "is-deflate@npm:1.0.0" - checksum: 35f7ffcbef3549dd8a4d8df5dc09b4f4656a0fc88326e8b5201cda54114a9c2d8efb689d87c16f3f35c95bd71dcf13dc790d62b7504745b42c53ab4b40238f5a - languageName: node - linkType: hard - "is-directory@npm:^0.3.1": version: 0.3.1 resolution: "is-directory@npm:0.3.1" @@ -13008,13 +11819,6 @@ __metadata: languageName: node linkType: hard -"is-gzip@npm:^1.0.0": - version: 1.0.0 - resolution: "is-gzip@npm:1.0.0" - checksum: cbc1db080c636a6fb0f7346e3076f8276a29a9d8b52ae67c1971a8131c43f308e98ed227d1a6f49970e6c6ebabee0568e60aed7a3579dd4e1817cddf2faaf9b7 - languageName: node - linkType: hard - "is-in-ci@npm:^0.1.0": version: 0.1.0 resolution: "is-in-ci@npm:0.1.0" @@ -13048,16 +11852,6 @@ __metadata: languageName: node linkType: hard -"is-nan@npm:^1.3.2": - version: 1.3.2 - resolution: "is-nan@npm:1.3.2" - dependencies: - call-bind: "npm:^1.0.0" - define-properties: "npm:^1.1.3" - checksum: 8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 - languageName: node - linkType: hard - "is-negative-zero@npm:^2.0.1": version: 2.0.2 resolution: "is-negative-zero@npm:2.0.2" @@ -13102,13 +11896,6 @@ __metadata: languageName: node linkType: hard -"is-plain-object@npm:5.0.0, is-plain-object@npm:^5.0.0": - version: 5.0.0 - resolution: "is-plain-object@npm:5.0.0" - checksum: 893e42bad832aae3511c71fd61c0bf61aa3a6d853061c62a307261842727d0d25f761ce9379f7ba7226d6179db2a3157efa918e7fe26360f3bf0842d9f28942c - languageName: node - linkType: hard - "is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -13118,6 +11905,13 @@ __metadata: languageName: node linkType: hard +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: 893e42bad832aae3511c71fd61c0bf61aa3a6d853061c62a307261842727d0d25f761ce9379f7ba7226d6179db2a3157efa918e7fe26360f3bf0842d9f28942c + languageName: node + linkType: hard + "is-potential-custom-element-name@npm:^1.0.1": version: 1.0.1 resolution: "is-potential-custom-element-name@npm:1.0.1" @@ -13950,7 +12744,7 @@ __metadata: languageName: node linkType: hard -"jscodeshift@npm:^0.15.1, jscodeshift@npm:^0.15.2": +"jscodeshift@npm:^0.15.2": version: 0.15.2 resolution: "jscodeshift@npm:0.15.2" dependencies: @@ -13985,6 +12779,13 @@ __metadata: languageName: node linkType: hard +"jsdoc-type-pratt-parser@npm:^4.0.0": + version: 4.1.0 + resolution: "jsdoc-type-pratt-parser@npm:4.1.0" + checksum: 7700372d2e733a32f7ea0a1df9cec6752321a5345c11a91b2ab478a031a426e934f16d5c1f15c8566c7b2c10af9f27892a29c2c789039f595470e929a4aa60ea + languageName: node + linkType: hard + "jsdom@npm:^20.0.0": version: 20.0.3 resolution: "jsdom@npm:20.0.3" @@ -14235,17 +13036,6 @@ __metadata: languageName: node linkType: hard -"lazy-universal-dotenv@npm:^4.0.0": - version: 4.0.0 - resolution: "lazy-universal-dotenv@npm:4.0.0" - dependencies: - app-root-dir: "npm:^1.0.2" - dotenv: "npm:^16.0.0" - dotenv-expand: "npm:^10.0.0" - checksum: 3bc4fe649c46c4a20561ca1fd10cd1df641d2c6c42c61af6c65a5fe0546cb548f449e13e6c7440be445c9fe5b4973c25f499e7d899b8704b7b9bd0ec85bbfe2d - languageName: node - linkType: hard - "lerna@npm:~7.1.3": version: 7.1.5 resolution: "lerna@npm:7.1.5" @@ -14753,6 +13543,24 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.27.0": + version: 0.27.0 + resolution: "magic-string@npm:0.27.0" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.4.13" + checksum: cddacfea14441ca57ae8a307bc3cf90bac69efaa4138dd9a80804cffc2759bf06f32da3a293fb13eaa96334b7d45b7768a34f1d226afae25d2f05b05a3bb37d8 + languageName: node + linkType: hard + +"magic-string@npm:^0.30.0": + version: 0.30.12 + resolution: "magic-string@npm:0.30.12" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: 469f457d18af37dfcca8617086ea8a65bcd8b60ba8a1182cb024ce43e470ace3c9d1cb6bee58d3b311768fb16bc27bd50bdeebcaa63dadd0fd46cac4d2e11d5f + languageName: node + linkType: hard + "magic-string@npm:^0.30.5": version: 0.30.10 resolution: "magic-string@npm:0.30.10" @@ -14882,13 +13690,6 @@ __metadata: languageName: node linkType: hard -"map-or-similar@npm:^1.5.0": - version: 1.5.0 - resolution: "map-or-similar@npm:1.5.0" - checksum: 33c6ccfdc272992e33e4e99a69541a3e7faed9de3ac5bc732feb2500a9ee71d3f9d098980a70b7746e7eeb7f859ff7dfb8aa9b5ecc4e34170a32ab78cfb18def - languageName: node - linkType: hard - "markdown-it@npm:^13.0.1": version: 13.0.1 resolution: "markdown-it@npm:13.0.1" @@ -14904,15 +13705,6 @@ __metadata: languageName: node linkType: hard -"markdown-to-jsx@npm:7.3.2": - version: 7.3.2 - resolution: "markdown-to-jsx@npm:7.3.2" - peerDependencies: - react: ">= 0.14.0" - checksum: 191b9a9defeed02e12dd340cebf279f577266dac7b34574fa44ce4d64ee8536f9967d455b8303c853f84413feb473118290a6160d8221eeaf3b9e4961b8980e3 - languageName: node - linkType: hard - "mdurl@npm:^1.0.1": version: 1.0.1 resolution: "mdurl@npm:1.0.1" @@ -14943,15 +13735,6 @@ __metadata: languageName: node linkType: hard -"memoizerific@npm:^1.11.3": - version: 1.11.3 - resolution: "memoizerific@npm:1.11.3" - dependencies: - map-or-similar: "npm:^1.5.0" - checksum: 661bf69b7afbfad57f0208f0c63324f4c96087b480708115b78ee3f0237d86c7f91347f6db31528740b2776c2e34c709bcb034e1e910edee2270c9603a0a469e - languageName: node - linkType: hard - "meow@npm:^8.1.2": version: 8.1.2 resolution: "meow@npm:8.1.2" @@ -15029,7 +13812,7 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa @@ -15102,7 +13885,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -15287,13 +14070,6 @@ __metadata: languageName: node linkType: hard -"mkdirp-classic@npm:^0.5.2": - version: 0.5.3 - resolution: "mkdirp-classic@npm:0.5.3" - checksum: 95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 - languageName: node - linkType: hard - "mkdirp@npm:^0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" @@ -15321,13 +14097,6 @@ __metadata: languageName: node linkType: hard -"mri@npm:^1.2.0": - version: 1.2.0 - resolution: "mri@npm:1.2.0" - checksum: a3d32379c2554cf7351db6237ddc18dc9e54e4214953f3da105b97dc3babe0deb3ffe99cf409b38ea47cc29f9430561ba6b53b24ab8f9ce97a4b50409e4a50e7 - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -15478,13 +14247,6 @@ __metadata: languageName: node linkType: hard -"node-fetch-native@npm:^1.0.2": - version: 1.1.1 - resolution: "node-fetch-native@npm:1.1.1" - checksum: 4b12e42c7bd80688acbfd8cceaa246aa00c532d00193e049d9ccce7038b135932a7f1d8a12107e790b827f295d1fd9e76706b634bce7c7e375e6a2f96e233e0f - languageName: node - linkType: hard - "node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -15499,7 +14261,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.0.0, node-fetch@npm:^2.6.7": +"node-fetch@npm:^2.6.7": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -15920,16 +14682,6 @@ __metadata: languageName: node linkType: hard -"object-is@npm:^1.1.5": - version: 1.1.6 - resolution: "object-is@npm:1.1.6" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - checksum: 506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 - languageName: node - linkType: hard - "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -15937,7 +14689,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.2": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -16026,13 +14778,6 @@ __metadata: languageName: node linkType: hard -"on-headers@npm:~1.0.2": - version: 1.0.2 - resolution: "on-headers@npm:1.0.2" - checksum: f649e65c197bf31505a4c0444875db0258e198292f34b884d73c2f751e91792ef96bb5cf89aa0f4fecc2e4dc662461dda606b1274b0e564f539cae5d2f5fc32f - languageName: node - linkType: hard - "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -16337,13 +15082,6 @@ __metadata: languageName: node linkType: hard -"pako@npm:~0.2.0": - version: 0.2.9 - resolution: "pako@npm:0.2.9" - checksum: 79c1806ebcf325b60ae599e4d7227c2e346d7b829dc20f5cf24cef07c934079dc3a61c5b3c8278a2f7a190c4a613e343ea11e5302dbe252efd11712df4b6b041 - languageName: node - linkType: hard - "papaparse@npm:^5.3.0, papaparse@npm:^5.4.1": version: 5.4.1 resolution: "papaparse@npm:5.4.1" @@ -16534,40 +15272,15 @@ __metadata: version: 3.0.0 resolution: "path-type@npm:3.0.0" dependencies: - pify: "npm:^3.0.0" - checksum: 1332c632f1cac15790ebab8dd729b67ba04fc96f81647496feb1c2975d862d046f41e4b975dbd893048999b2cc90721f72924ad820acc58c78507ba7141a8e56 - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c - languageName: node - linkType: hard - -"path-type@npm:^5.0.0": - version: 5.0.0 - resolution: "path-type@npm:5.0.0" - checksum: e8f4b15111bf483900c75609e5e74e3fcb79f2ddb73e41470028fcd3e4b5162ec65da9907be077ee5012c18801ff7fffb35f9f37a077f3f81d85a0b7d6578efd - languageName: node - linkType: hard - -"pathe@npm:^1.1.0": - version: 1.1.0 - resolution: "pathe@npm:1.1.0" - checksum: 1c5d07378475bcdf4f435684566190d35d06be2db8b8e61cf9e866ae649941fdb093d732fa01b0f51d86e3f94140543c2571b0bf65a87ca7b5d1f52152aabe03 + pify: "npm:^3.0.0" + checksum: 1332c632f1cac15790ebab8dd729b67ba04fc96f81647496feb1c2975d862d046f41e4b975dbd893048999b2cc90721f72924ad820acc58c78507ba7141a8e56 languageName: node linkType: hard -"peek-stream@npm:^1.1.0": - version: 1.1.3 - resolution: "peek-stream@npm:1.1.3" - dependencies: - buffer-from: "npm:^1.0.0" - duplexify: "npm:^3.5.0" - through2: "npm:^2.0.3" - checksum: 3c35d1951b8640036f93b1b5628a90f849e49ca4f2e6aba393ff4978413931d9c491c83f71a92f878d5ea4c670af0bba04dfcfb79b310ead22601db7c1420e36 +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c languageName: node linkType: hard @@ -16599,13 +15312,20 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.0, picomatch@npm:^2.3.1": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc + languageName: node + linkType: hard + "pidtree@npm:^0.6.0": version: 0.6.0 resolution: "pidtree@npm:0.6.0" @@ -16668,15 +15388,6 @@ __metadata: languageName: node linkType: hard -"pkg-dir@npm:^5.0.0": - version: 5.0.0 - resolution: "pkg-dir@npm:5.0.0" - dependencies: - find-up: "npm:^5.0.0" - checksum: 793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 - languageName: node - linkType: hard - "pkg-dir@npm:^7.0.0": version: 7.0.0 resolution: "pkg-dir@npm:7.0.0" @@ -16822,15 +15533,6 @@ __metadata: languageName: node linkType: hard -"prettier-fallback@npm:prettier@^3, prettier@npm:^3.1.1, prettier@npm:~3.2.5": - version: 3.2.5 - resolution: "prettier@npm:3.2.5" - bin: - prettier: bin/prettier.cjs - checksum: ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 - languageName: node - linkType: hard - "prettier-linter-helpers@npm:^1.0.0": version: 1.0.0 resolution: "prettier-linter-helpers@npm:1.0.0" @@ -16840,6 +15542,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.1.1, prettier@npm:~3.2.5": + version: 3.2.5 + resolution: "prettier@npm:3.2.5" + bin: + prettier: bin/prettier.cjs + checksum: ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 + languageName: node + linkType: hard + "pretty-bytes@npm:^5.6.0": version: 5.6.0 resolution: "pretty-bytes@npm:5.6.0" @@ -16879,13 +15590,6 @@ __metadata: languageName: node linkType: hard -"pretty-hrtime@npm:^1.0.3": - version: 1.0.3 - resolution: "pretty-hrtime@npm:1.0.3" - checksum: 67cb3fc283a72252b49ac488647e6a01b78b7aa1b8f2061834aa1650691229081518ef3ca940f77f41cc8a8f02ba9eeb74b843481596670209e493062f2e89e0 - languageName: node - linkType: hard - "proc-log@npm:^3.0.0": version: 3.0.0 resolution: "proc-log@npm:3.0.0" @@ -16931,7 +15635,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.0.1, prompts@npm:^2.4.0": +"prompts@npm:^2.0.1": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -17200,16 +15904,6 @@ __metadata: languageName: node linkType: hard -"pump@npm:^2.0.0": - version: 2.0.1 - resolution: "pump@npm:2.0.1" - dependencies: - end-of-stream: "npm:^1.1.0" - once: "npm:^1.3.1" - checksum: f1fe8960f44d145f8617ea4c67de05392da4557052980314c8f85081aee26953bdcab64afad58a2b1df0e8ff7203e3710e848cbe81a01027978edc6e264db355 - languageName: node - linkType: hard - "pump@npm:^3.0.0": version: 3.0.0 resolution: "pump@npm:3.0.0" @@ -17220,17 +15914,6 @@ __metadata: languageName: node linkType: hard -"pumpify@npm:^1.3.3": - version: 1.5.1 - resolution: "pumpify@npm:1.5.1" - dependencies: - duplexify: "npm:^3.6.0" - inherits: "npm:^2.0.3" - pump: "npm:^2.0.0" - checksum: 0bcabf9e3dbf2d0cc1f9b84ac80d3c75386111caf8963bfd98817a1e2192000ac0ccc804ca6ccd5b2b8430fdb71347b20fb2f014fe3d41adbacb1b502a841c45 - languageName: node - linkType: hard - "punycode@npm:1.3.2": version: 1.3.2 resolution: "punycode@npm:1.3.2" @@ -17252,7 +15935,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.13.0, qs@npm:^6.10.0": +"qs@npm:6.13.0": version: 6.13.0 resolution: "qs@npm:6.13.0" dependencies: @@ -17656,13 +16339,6 @@ __metadata: languageName: node linkType: hard -"ramda@npm:0.29.0": - version: 0.29.0 - resolution: "ramda@npm:0.29.0" - checksum: b00eaaf1c62b06a99affa1d583e256bd65ad27ab9d0ef512f55d7d93b842e7cd244a4a09179f61fdd8548362e409323867a2b0477cbd0626b5644eb6ac7c53da - languageName: node - linkType: hard - "randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -17737,14 +16413,14 @@ __metadata: resolution: "react-admin-lerna@workspace:." dependencies: "@babel/plugin-proposal-private-property-in-object": "npm:^7.21.11" - "@storybook/addon-actions": "npm:^8.1.9" - "@storybook/addon-controls": "npm:^8.1.9" - "@storybook/addon-docs": "npm:^8.1.9" - "@storybook/addon-storysource": "npm:^8.1.9" + "@storybook/addon-actions": "npm:^8.4.4" + "@storybook/addon-controls": "npm:^8.4.4" + "@storybook/addon-storysource": "npm:^8.4.4" "@storybook/addon-webpack5-compiler-babel": "npm:^3.0.3" - "@storybook/react": "npm:^8.1.9" - "@storybook/react-webpack5": "npm:^8.1.9" - "@storybook/source-loader": "npm:^8.1.9" + "@storybook/react": "npm:^8.4.4" + "@storybook/react-vite": "npm:^8.4.4" + "@storybook/react-webpack5": "npm:^8.4.4" + "@storybook/source-loader": "npm:^8.4.4" "@types/jest": "npm:^29.5.2" "@types/react": "npm:^18.3.3" "@typescript-eslint/eslint-plugin": "npm:^5.60.0" @@ -17771,8 +16447,9 @@ __metadata: raf: "npm:~3.4.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" - storybook: "npm:^8.1.9" + storybook: "npm:^8.4.4" ts-jest: "npm:^29.1.0" + tsconfig-paths-webpack-plugin: "npm:^4.2.0" typescript: "npm:^5.1.3" whatwg-fetch: "npm:^3.0.0" dependenciesMeta: @@ -17806,16 +16483,6 @@ __metadata: languageName: unknown linkType: soft -"react-colorful@npm:^5.1.2": - version: 5.5.1 - resolution: "react-colorful@npm:5.5.1" - peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" - checksum: f5991c675f82d204d73638b49077d710934cc1e6a47f95a6fc8a14761d926bd416346cedc7ac4da98a942561e053b675fa0ab0d52120ec9fbdb25027502d2dde - languageName: node - linkType: hard - "react-cropper@npm:^2.3.3": version: 2.3.3 resolution: "react-cropper@npm:2.3.3" @@ -17854,7 +16521,7 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^16.8.0 || ^17.0.0 || ^18.0.0, react-dom@npm:^18.3.1": +"react-dom@npm:^18.3.1": version: 18.3.1 resolution: "react-dom@npm:18.3.1" dependencies: @@ -17879,20 +16546,6 @@ __metadata: languageName: node linkType: hard -"react-element-to-jsx-string@npm:^15.0.0": - version: 15.0.0 - resolution: "react-element-to-jsx-string@npm:15.0.0" - dependencies: - "@base2/pretty-print-object": "npm:1.0.1" - is-plain-object: "npm:5.0.0" - react-is: "npm:18.1.0" - peerDependencies: - react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - checksum: 0d60a0ea758529c32a706d0c69d70b69fb94de3c46442fffdee34f08f51ffceddbb5395b41dfd1565895653e9f60f98ca525835be9d5db1f16d6b22be12f4cd4 - languageName: node - linkType: hard - "react-error-boundary@npm:^4.0.13, react-error-boundary@npm:^4.0.3": version: 4.0.13 resolution: "react-error-boundary@npm:4.0.13" @@ -17931,13 +16584,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:18.1.0": - version: 18.1.0 - resolution: "react-is@npm:18.1.0" - checksum: 558874e4c3bd9805a9294426e090919ee6901be3ab07f80b997c36b5a01a8d691112802e7438d146f6c82fd6495d8c030f276ef05ec3410057f8740a8d723f8c - languageName: node - linkType: hard - "react-is@npm:^16.10.2, react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -18017,41 +16663,6 @@ __metadata: languageName: node linkType: hard -"react-remove-scroll-bar@npm:^2.3.3": - version: 2.3.4 - resolution: "react-remove-scroll-bar@npm:2.3.4" - dependencies: - react-style-singleton: "npm:^2.2.1" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 2262750dc1022c56d2c79e8d865c00045881c57bcaca74810ae8adac35cfdf723ff7d6b3b0e95c85eb9a0cff90bb4b1e0af801bd703ce8c0a2e35ab14ff1babb - languageName: node - linkType: hard - -"react-remove-scroll@npm:2.5.5": - version: 2.5.5 - resolution: "react-remove-scroll@npm:2.5.5" - dependencies: - react-remove-scroll-bar: "npm:^2.3.3" - react-style-singleton: "npm:^2.2.1" - tslib: "npm:^2.1.0" - use-callback-ref: "npm:^1.3.0" - use-sidecar: "npm:^1.1.2" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 4952657e6a7b9d661d4ad4dfcef81b9c7fa493e35164abff99c35c0b27b3d172ef7ad70c09416dc44dd14ff2e6b38a5ec7da27e27e90a15cbad36b8fd2fd8054 - languageName: node - linkType: hard - "react-resize-detector@npm:^7.1.2": version: 7.1.2 resolution: "react-resize-detector@npm:7.1.2" @@ -18124,23 +16735,6 @@ __metadata: languageName: node linkType: hard -"react-style-singleton@npm:^2.2.1": - version: 2.2.1 - resolution: "react-style-singleton@npm:2.2.1" - dependencies: - get-nonce: "npm:^1.0.0" - invariant: "npm:^2.2.4" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 6d66f3bdb65e1ec79089f80314da97c9a005087a04ee034255a5de129a4c0d9fd0bf99fa7bf642781ac2dc745ca687aae3de082bd8afdd0d117bc953241e15ad - languageName: node - linkType: hard - "react-test-renderer@npm:^18.2.0": version: 18.2.0 resolution: "react-test-renderer@npm:18.2.0" @@ -18184,7 +16778,7 @@ __metadata: languageName: node linkType: hard -"react@npm:^16.8.0 || ^17.0.0 || ^18.0.0, react@npm:^18.3.1": +"react@npm:^18.3.1": version: 18.3.1 resolution: "react@npm:18.3.1" dependencies: @@ -18275,7 +16869,18 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:~2.3.6": +"readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": + version: 3.6.0 + resolution: "readable-stream@npm:3.6.0" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 937bedd29ac8a68331666291922bea892fa2be1a33269e582de9f844a2002f146cf831e39cd49fe6a378d3f0c27358f259ed0e20d20f0bdc6a3f8fc21fce42dc + languageName: node + linkType: hard + +"readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -18290,17 +16895,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": - version: 3.6.0 - resolution: "readable-stream@npm:3.6.0" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 937bedd29ac8a68331666291922bea892fa2be1a33269e582de9f844a2002f146cf831e39cd49fe6a378d3f0c27358f259ed0e20d20f0bdc6a3f8fc21fce42dc - languageName: node - linkType: hard - "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -18503,33 +17097,6 @@ __metadata: languageName: node linkType: hard -"rehype-external-links@npm:^3.0.0": - version: 3.0.0 - resolution: "rehype-external-links@npm:3.0.0" - dependencies: - "@types/hast": "npm:^3.0.0" - "@ungap/structured-clone": "npm:^1.0.0" - hast-util-is-element: "npm:^3.0.0" - is-absolute-url: "npm:^4.0.0" - space-separated-tokens: "npm:^2.0.0" - unist-util-visit: "npm:^5.0.0" - checksum: 486b5db73d8fe72611d62b4eb0b56ec71025ea32bba764ad54473f714ca627be75e057ac29243763f85a77c3810f31727ce3e03c975b3803c1c98643d038e9ae - languageName: node - linkType: hard - -"rehype-slug@npm:^6.0.0": - version: 6.0.0 - resolution: "rehype-slug@npm:6.0.0" - dependencies: - "@types/hast": "npm:^3.0.0" - github-slugger: "npm:^2.0.0" - hast-util-heading-rank: "npm:^3.0.0" - hast-util-to-string: "npm:^3.0.0" - unist-util-visit: "npm:^5.0.0" - checksum: 51303c33d039c271cabe62161b49fa737be488f70ced62f00c165e47a089a99de2060050385e5c00d0df83ed30c7fa1c79a51b78508702836aefa51f7e7a6760 - languageName: node - linkType: hard - "reify@npm:^0.20.12": version: 0.20.12 resolution: "reify@npm:0.20.12" @@ -18915,13 +17482,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: 780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 - languageName: node - linkType: hard - "safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -18929,6 +17489,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -19024,6 +17591,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.2": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + languageName: node + linkType: hard + "send@npm:0.19.0": version: 0.19.0 resolution: "send@npm:0.19.0" @@ -19230,7 +17806,7 @@ __metadata: languageName: node linkType: hard -"slash@npm:^5.0.0, slash@npm:^5.1.0": +"slash@npm:^5.0.0": version: 5.1.0 resolution: "slash@npm:5.1.0" checksum: eb48b815caf0bdc390d0519d41b9e0556a14380f6799c72ba35caf03544d501d18befdeeef074bc9c052acf69654bc9e0d79d7f1de0866284137a40805299eb3 @@ -19400,13 +17976,6 @@ __metadata: languageName: node linkType: hard -"space-separated-tokens@npm:^2.0.0": - version: 2.0.2 - resolution: "space-separated-tokens@npm:2.0.2" - checksum: 6173e1d903dca41dcab6a2deed8b4caf61bd13b6d7af8374713500570aa929ff9414ae09a0519f4f8772df993300305a395d4871f35bc4ca72b6db57e1f30af8 - languageName: node - linkType: hard - "spdx-correct@npm:^3.0.0": version: 3.1.1 resolution: "spdx-correct@npm:3.1.1" @@ -19537,29 +18106,21 @@ __metadata: languageName: node linkType: hard -"store2@npm:^2.14.2": - version: 2.14.2 - resolution: "store2@npm:2.14.2" - checksum: 2f27c3eaa7207b81410e170e7c41379816d22c1566308a9d97fbf853c4facff531fcb2a85f085c7503c578736570972f747c26018ebeaba7d1341fb82a7b6d52 - languageName: node - linkType: hard - -"storybook@npm:^8.1.9": - version: 8.1.9 - resolution: "storybook@npm:8.1.9" +"storybook@npm:^8.4.4": + version: 8.4.4 + resolution: "storybook@npm:8.4.4" dependencies: - "@storybook/cli": "npm:8.1.9" + "@storybook/core": "npm:8.4.4" + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true bin: - sb: ./index.js - storybook: ./index.js - checksum: 598fea66bfa24fdb0c25671d10c5edbdc0c81f14c5fb0e3e501cefcfb7aadaa8e28286a9eb1344ac105b826e803d2cd7e895927e5273a9122fc9ddd86c3ae4dc - languageName: node - linkType: hard - -"stream-shift@npm:^1.0.0": - version: 1.0.1 - resolution: "stream-shift@npm:1.0.1" - checksum: b63a0d178cde34b920ad93e2c0c9395b840f408d36803b07c61416edac80ef9e480a51910e0ceea0d679cec90921bcd2cccab020d3a9fa6c73a98b0fbec132fd + getstorybook: ./bin/index.cjs + sb: ./bin/index.cjs + storybook: ./bin/index.cjs + checksum: cf680b8451fc4941812af91844b332fec83aa71739e1ce528bb6de623d89b119b7db6c4a3f6b4e600604d39e3c4e04f0cc6d500815c473da7ee676208fa3c782 languageName: node linkType: hard @@ -19913,19 +18474,7 @@ __metadata: languageName: node linkType: hard -"tar-fs@npm:^2.1.1": - version: 2.1.1 - resolution: "tar-fs@npm:2.1.1" - dependencies: - chownr: "npm:^1.1.1" - mkdirp-classic: "npm:^0.5.2" - pump: "npm:^3.0.0" - tar-stream: "npm:^2.1.4" - checksum: 871d26a934bfb7beeae4c4d8a09689f530b565f79bd0cf489823ff0efa3705da01278160da10bb006d1a793fa0425cf316cec029b32a9159eacbeaff4965fb6d - languageName: node - linkType: hard - -"tar-stream@npm:^2.1.4, tar-stream@npm:~2.2.0": +"tar-stream@npm:~2.2.0": version: 2.2.0 resolution: "tar-stream@npm:2.2.0" dependencies: @@ -19952,7 +18501,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.13, tar@npm:^6.1.2": +"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.1.15 resolution: "tar@npm:6.1.15" dependencies: @@ -19966,15 +18515,6 @@ __metadata: languageName: node linkType: hard -"telejson@npm:^7.2.0": - version: 7.2.0 - resolution: "telejson@npm:7.2.0" - dependencies: - memoizerific: "npm:^1.11.3" - checksum: d26e6cc93e54bfdcdb207b49905508c5db45862e811a2e2193a735409e47b14530e1c19351618a3e03ad2fd4ffc3759364fcd72851aba2df0300fab574b6151c - languageName: node - linkType: hard - "temp-dir@npm:1.0.0": version: 1.0.0 resolution: "temp-dir@npm:1.0.0" @@ -19982,13 +18522,6 @@ __metadata: languageName: node linkType: hard -"temp-dir@npm:^3.0.0": - version: 3.0.0 - resolution: "temp-dir@npm:3.0.0" - checksum: a86978a400984cd5f315b77ebf3fe53bb58c61f192278cafcb1f3fb32d584a21dc8e08b93171d7874b7cc972234d3455c467306cc1bfc4524b622e5ad3bfd671 - languageName: node - linkType: hard - "temp@npm:^0.8.4": version: 0.8.4 resolution: "temp@npm:0.8.4" @@ -19998,18 +18531,6 @@ __metadata: languageName: node linkType: hard -"tempy@npm:^3.1.0": - version: 3.1.0 - resolution: "tempy@npm:3.1.0" - dependencies: - is-stream: "npm:^3.0.0" - temp-dir: "npm:^3.0.0" - type-fest: "npm:^2.12.2" - unique-string: "npm:^3.0.0" - checksum: b88e70baa8d935ba8f0e0372b59ad1a961121f098da5fb4a6e05bec98ec32a49026b553532fb75c1c102ec782fd4c6a6bde0d46cbe87013fa324451ce476fb76 - languageName: node - linkType: hard - "terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.10": version: 5.3.10 resolution: "terser-webpack-plugin@npm:5.3.10" @@ -20085,7 +18606,7 @@ __metadata: languageName: node linkType: hard -"through2@npm:^2.0.0, through2@npm:^2.0.3": +"through2@npm:^2.0.0": version: 2.0.5 resolution: "through2@npm:2.0.5" dependencies: @@ -20166,13 +18687,6 @@ __metadata: languageName: node linkType: hard -"tocbot@npm:^4.20.1": - version: 4.21.2 - resolution: "tocbot@npm:4.21.2" - checksum: 3b3f138368aca22757e85c56230d7db7a0bbcf1d3642258f3c4a16ac910d1dc01f99d0e78b0d965727e1eb9c63ec672f93c55d09554a5807e43459185d5a227b - languageName: node - linkType: hard - "toidentifier@npm:1.0.1": version: 1.0.1 resolution: "toidentifier@npm:1.0.1" @@ -20290,6 +18804,18 @@ __metadata: languageName: node linkType: hard +"tsconfig-paths-webpack-plugin@npm:^4.2.0": + version: 4.2.0 + resolution: "tsconfig-paths-webpack-plugin@npm:4.2.0" + dependencies: + chalk: "npm:^4.1.0" + enhanced-resolve: "npm:^5.7.0" + tapable: "npm:^2.2.1" + tsconfig-paths: "npm:^4.1.2" + checksum: 495c5ab7c1cb079217d98fe25d61def01e4bab38047c7ab25ec11876cc8c697ff01f43ea6c9933181875e51e49835407fc71afd92ea6cca1ba1bebf513dfb510 + languageName: node + linkType: hard + "tsconfig-paths@npm:^3.12.0": version: 3.14.1 resolution: "tsconfig-paths@npm:3.14.1" @@ -20313,7 +18839,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.13.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0": +"tslib@npm:^1.8.1, tslib@npm:^1.9.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 @@ -20448,14 +18974,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^1.0.1": - version: 1.4.0 - resolution: "type-fest@npm:1.4.0" - checksum: a3c0f4ee28ff6ddf800d769eafafcdeab32efa38763c1a1b8daeae681920f6e345d7920bf277245235561d8117dab765cb5f829c76b713b4c9de0998a5397141 - languageName: node - linkType: hard - -"type-fest@npm:^2.0.0, type-fest@npm:^2.12.2, type-fest@npm:^2.19.0, type-fest@npm:~2.19": +"type-fest@npm:^2.0.0, type-fest@npm:^2.19.0": version: 2.19.0 resolution: "type-fest@npm:2.19.0" checksum: a5a7ecf2e654251613218c215c7493574594951c08e52ab9881c9df6a6da0aeca7528c213c622bc374b4e0cb5c443aa3ab758da4e3c959783ce884c3194e12cb @@ -20548,6 +19067,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.8": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -20579,13 +19105,6 @@ __metadata: languageName: node linkType: hard -"unicorn-magic@npm:^0.1.0": - version: 0.1.0 - resolution: "unicorn-magic@npm:0.1.0" - checksum: e4ed0de05b0a05e735c7d8a2930881e5efcfc3ec897204d5d33e7e6247f4c31eac92e383a15d9a6bccb7319b4271ee4bea946e211bf14951fec6ff2cbbb66a92 - languageName: node - linkType: hard - "unique-filename@npm:^1.1.1": version: 1.1.1 resolution: "unique-filename@npm:1.1.1" @@ -20622,45 +19141,6 @@ __metadata: languageName: node linkType: hard -"unique-string@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-string@npm:3.0.0" - dependencies: - crypto-random-string: "npm:^4.0.0" - checksum: b35ea034b161b2a573666ec16c93076b4b6106b8b16c2415808d747ab3a0566b5db0c4be231d4b11cfbc16d7fd915c9d8a45884bff0e2db11b799775b2e1e017 - languageName: node - linkType: hard - -"unist-util-is@npm:^6.0.0": - version: 6.0.0 - resolution: "unist-util-is@npm:6.0.0" - dependencies: - "@types/unist": "npm:^3.0.0" - checksum: 9419352181eaa1da35eca9490634a6df70d2217815bb5938a04af3a662c12c5607a2f1014197ec9c426fbef18834f6371bfdb6f033040fa8aa3e965300d70e7e - languageName: node - linkType: hard - -"unist-util-visit-parents@npm:^6.0.0": - version: 6.0.1 - resolution: "unist-util-visit-parents@npm:6.0.1" - dependencies: - "@types/unist": "npm:^3.0.0" - unist-util-is: "npm:^6.0.0" - checksum: 51b1a5b0aa23c97d3e03e7288f0cdf136974df2217d0999d3de573c05001ef04cccd246f51d2ebdfb9e8b0ed2704451ad90ba85ae3f3177cf9772cef67f56206 - languageName: node - linkType: hard - -"unist-util-visit@npm:^5.0.0": - version: 5.0.0 - resolution: "unist-util-visit@npm:5.0.0" - dependencies: - "@types/unist": "npm:^3.0.0" - unist-util-is: "npm:^6.0.0" - unist-util-visit-parents: "npm:^6.0.0" - checksum: 51434a1d80252c1540cce6271a90fd1a106dbe624997c09ed8879279667fb0b2d3a685e02e92bf66598dcbe6cdffa7a5f5fb363af8fdf90dda6c855449ae39a5 - languageName: node - linkType: hard - "universal-user-agent@npm:^6.0.0": version: 6.0.0 resolution: "universal-user-agent@npm:6.0.0" @@ -20690,14 +19170,12 @@ __metadata: linkType: hard "unplugin@npm:^1.3.1": - version: 1.5.0 - resolution: "unplugin@npm:1.5.0" + version: 1.16.0 + resolution: "unplugin@npm:1.16.0" dependencies: - acorn: "npm:^8.10.0" - chokidar: "npm:^3.5.3" - webpack-sources: "npm:^3.2.3" - webpack-virtual-modules: "npm:^0.5.0" - checksum: 2f79a7bf6b428a6aac80bf21852ed83cafead0ae3ed8866db1dca1cd4489f3b50c95874275e9a9b0f10c2e3c4892bfe0431c70d13635775c4c620a6a3f9eae37 + acorn: "npm:^8.14.0" + webpack-virtual-modules: "npm:^0.6.2" + checksum: 547f6bd5ec1dd7411533e68e73c60d5e9527e68d52aa326442650d084866ed3307ac68719068abae23ceab09db197cad43b382a7e69c2d8ca338b27802392fed languageName: node linkType: hard @@ -20758,21 +19236,6 @@ __metadata: languageName: node linkType: hard -"use-callback-ref@npm:^1.3.0": - version: 1.3.0 - resolution: "use-callback-ref@npm:1.3.0" - dependencies: - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 8a0867ffd441f358c66d79567970a745cc78ac2f98840a81c1fa749a525e8716116c645497d886a815e1dcf40ad81a107ebd6a7d15fd9ab5925c44a994a1d89a - languageName: node - linkType: hard - "use-memo-one@npm:^1.1.3": version: 1.1.3 resolution: "use-memo-one@npm:1.1.3" @@ -20782,22 +19245,6 @@ __metadata: languageName: node linkType: hard -"use-sidecar@npm:^1.1.2": - version: 1.1.2 - resolution: "use-sidecar@npm:1.1.2" - dependencies: - detect-node-es: "npm:^1.1.0" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.9.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 89f0018fd9aee1fc17c85ac18c4bf8944d460d453d0d0e04ddbc8eaddf3fa591e9c74a1f8a438a1bff368a7a2417fab380bdb3df899d2194c4375b0982736de0 - languageName: node - linkType: hard - "use-sync-external-store@npm:^1.0.0": version: 1.2.0 resolution: "use-sync-external-store@npm:1.2.0" @@ -21014,7 +19461,7 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.2.0, watchpack@npm:^2.4.1": +"watchpack@npm:^2.4.1": version: 2.4.2 resolution: "watchpack@npm:2.4.2" dependencies: @@ -21097,10 +19544,10 @@ __metadata: languageName: node linkType: hard -"webpack-virtual-modules@npm:^0.5.0": - version: 0.5.0 - resolution: "webpack-virtual-modules@npm:0.5.0" - checksum: 0742e069cd49d91ccd0b59431b3666903d321582c1b1062fa6bdae005c3538af55ff8787ea5eafbf72662f3496d3a879e2c705d55ca0af8283548a925be18484 +"webpack-virtual-modules@npm:^0.6.0, webpack-virtual-modules@npm:^0.6.2": + version: 0.6.2 + resolution: "webpack-virtual-modules@npm:0.6.2" + checksum: 5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add languageName: node linkType: hard From e5cc4b766c0155dc16d2102838d10891ebd0a307 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Tue, 19 Nov 2024 18:08:40 +0100 Subject: [PATCH 02/91] wip: working version with webpack, requiring import_typescript.parsers.typescript fix --- .storybook/main.ts | 207 ++++++++---------- package.json | 2 +- .../ra-core/src/auth/CanAccess.stories.tsx | 1 + 3 files changed, 89 insertions(+), 121 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 24b3d871ee0..8fdaf9860aa 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,4 +1,4 @@ -import type { StorybookConfig } from '@storybook/react-vite'; +import { StorybookConfig } from '@storybook/react-webpack5'; import fs from 'fs'; import path, { dirname, join } from 'path'; @@ -12,140 +12,107 @@ const config: StorybookConfig = { ), ], addons: [ + '@storybook/addon-webpack5-compiler-babel', // '@storybook/addon-storysource', { name: '@storybook/addon-storysource', options: { loaderOptions: { - injectStoryParameters: false, + parser: 'typescript', + // foo: 'bar', + // injectDecorator: true, + // injectStoryParameters: false, }, }, }, - // '@storybook/addon-webpack5-compiler-babel', - // '@storybook/addon-storysource', - // { - // name: '@storybook/addon-storysource', - // options: { - // loaderOptions: { - // parser: 'typescript', - // }, - // }, - // }, - // { - // name: '@storybook/addon-storysource', - // options: { - // rule: { - // include: [ - // path.resolve( - // __dirname, - // `../packages/${process.env.ONLY || '**'}/**/*.stories.@(tsx)` - // ), - // ], - // }, - // loaderOptions: { - // parser: 'typescript', - // injectStoryParameters: false, - // }, - // }, - // }, '@storybook/addon-actions', '@storybook/addon-controls', ], - // typescript: { - // check: false, - // reactDocgen: 'react-docgen-typescript', // TEST - // }, - // babel: async options => { - // const { plugins = [] } = options; - // return { - // ...options, - // presets: [ - // '@babel/preset-env', - // '@babel/preset-react', - // '@babel/preset-typescript', - // ], - // plugins: [ - // ...plugins, - // [ - // '@babel/plugin-proposal-private-property-in-object', - // { - // loose: true, - // }, - // ], - // [ - // '@babel/plugin-proposal-private-methods', - // { - // loose: true, - // }, - // ], - // [ - // '@babel/plugin-proposal-class-properties', - // { - // loose: true, - // }, - // ], - // ], - // }; - // }, - // webpackFinal: async (config, { configType }) => { - // // config.module?.rules?.push({ - // // test: /\.stories\.tsx?$/, - // // use: [ - // // { - // // loader: require.resolve('@storybook/source-loader'), - // // options: { parser: 'typescript' }, - // // }, - // // ], - // // enforce: 'pre', - // // }); - // return { - // ...config, - // resolve: { - // ...config.resolve, - // alias: packages.reduce( - // (acc, pkg) => ({ - // ...acc, - // [pkg]: path.resolve( - // __dirname, - // `../packages/${pkg}/src` - // ), - // }), - // { ...config.resolve?.alias } - // ), - // plugins: [ - // ...(config.resolve?.plugins || []), - // new TsconfigPathsPlugin({ - // extensions: config.resolve?.extensions, - // }), - // ], - // }, - // }; - // }, - // framework: { - // name: getAbsolutePath('@storybook/react-webpack5'), - // options: {}, - // }, - framework: { - name: '@storybook/react-vite', - options: {}, + typescript: { + check: false, + reactDocgen: false, }, - // docs: {}, - async viteFinal(config) { - // Merge custom configuration into the default config - const { mergeConfig } = await import('vite'); - - return mergeConfig(config, { + babel: async options => { + const { plugins = [] } = options; + return { + ...options, + presets: [ + '@babel/preset-env', + '@babel/preset-react', + '@babel/preset-typescript', + ], + plugins: [ + ...plugins, + // [ + // '@babel/plugin-proposal-private-property-in-object', + // { + // loose: true, + // }, + // ], + // [ + // '@babel/plugin-proposal-private-methods', + // { + // loose: true, + // }, + // ], + // [ + // '@babel/plugin-proposal-class-properties', + // { + // loose: true, + // }, + // ], + ], + }; + }, + webpackFinal: async (config, { configType }) => { + config.module.rules = [ + ...config.module.rules.filter(rule => { + try { + return ( + rule.use[0].loader !== + require.resolve('@storybook/source-loader') + ); + } catch { + return true; + } + }), + { + test: /\.stories\.tsx?$/, + use: [ + { + loader: require.resolve('@storybook/source-loader'), + options: { + parser: 'typescript', + injectDecorator: true, + injectStoryParameters: false, + }, + }, + ], + enforce: 'pre', + }, + ]; + return { + ...config, resolve: { - alias: packages.map(pkg => ({ - find: new RegExp(`^${pkg}$`), - replacement: path.resolve( - __dirname, - `../packages/${pkg}/src` - ), - })), + ...config.resolve, + alias: packages.reduce( + (acc, pkg) => ({ + ...acc, + [pkg]: path.resolve( + __dirname, + `../packages/${pkg}/src` + ), + }), + { ...config.resolve?.alias } + ), }, - }); + }; + }, + framework: { + name: getAbsolutePath('@storybook/react-webpack5'), + options: {}, }, + docs: {}, }; export default config; diff --git a/package.json b/package.json index 558cc5a3bfc..826239a7986 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "run-graphql-demo": "cd examples/demo && cross-env REACT_APP_DATA_PROVIDER=graphql yarn dev", "run-crm": "cd examples/crm && yarn dev", "build-crm": "cd examples/crm && yarn build", - "storybook": "storybook dev -p 9010", + "storybook": "storybook dev -p 9010 --debug --debug-webpack --loglevel verbose", "build-storybook": "storybook build -c .storybook -o public --quiet" }, "devDependencies": { diff --git a/packages/ra-core/src/auth/CanAccess.stories.tsx b/packages/ra-core/src/auth/CanAccess.stories.tsx index b7c9b625828..2f40a68c7bc 100644 --- a/packages/ra-core/src/auth/CanAccess.stories.tsx +++ b/packages/ra-core/src/auth/CanAccess.stories.tsx @@ -28,6 +28,7 @@ export const Basic = ({ ); +// Basic.parameters = { storySource: { source: 'TEST JB' } }; export const AccessDenied = ({ authProvider = defaultAuthProvider, From adedebc4f8e4d47d3b3dee539b39607134d61e6a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Wed, 20 Nov 2024 09:53:27 +0100 Subject: [PATCH 03/91] cleanup test code --- .storybook/main.ts | 87 +++++++------------ package.json | 4 +- .../ra-core/src/auth/CanAccess.stories.tsx | 1 - 3 files changed, 31 insertions(+), 61 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 8fdaf9860aa..41247207047 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -13,18 +13,7 @@ const config: StorybookConfig = { ], addons: [ '@storybook/addon-webpack5-compiler-babel', - // '@storybook/addon-storysource', - { - name: '@storybook/addon-storysource', - options: { - loaderOptions: { - parser: 'typescript', - // foo: 'bar', - // injectDecorator: true, - // injectStoryParameters: false, - }, - }, - }, + '@storybook/addon-storysource', '@storybook/addon-actions', '@storybook/addon-controls', ], @@ -43,54 +32,38 @@ const config: StorybookConfig = { ], plugins: [ ...plugins, - // [ - // '@babel/plugin-proposal-private-property-in-object', - // { - // loose: true, - // }, - // ], - // [ - // '@babel/plugin-proposal-private-methods', - // { - // loose: true, - // }, - // ], - // [ - // '@babel/plugin-proposal-class-properties', - // { - // loose: true, - // }, - // ], - ], - }; - }, - webpackFinal: async (config, { configType }) => { - config.module.rules = [ - ...config.module.rules.filter(rule => { - try { - return ( - rule.use[0].loader !== - require.resolve('@storybook/source-loader') - ); - } catch { - return true; - } - }), - { - test: /\.stories\.tsx?$/, - use: [ + [ + '@babel/plugin-proposal-private-property-in-object', { - loader: require.resolve('@storybook/source-loader'), - options: { - parser: 'typescript', - injectDecorator: true, - injectStoryParameters: false, - }, + loose: true, }, ], - enforce: 'pre', - }, - ]; + [ + '@babel/plugin-proposal-private-methods', + { + loose: true, + }, + ], + [ + '@babel/plugin-proposal-class-properties', + { + loose: true, + }, + ], + ], + }; + }, + webpackFinal: async config => { + config.module?.rules?.push({ + test: /\.stories\.tsx?$/, + use: [ + { + loader: require.resolve('@storybook/source-loader'), + options: { parser: 'typescript' }, + }, + ], + enforce: 'pre', + }); return { ...config, resolve: { diff --git a/package.json b/package.json index 826239a7986..ea831480b81 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "run-graphql-demo": "cd examples/demo && cross-env REACT_APP_DATA_PROVIDER=graphql yarn dev", "run-crm": "cd examples/crm && yarn dev", "build-crm": "cd examples/crm && yarn build", - "storybook": "storybook dev -p 9010 --debug --debug-webpack --loglevel verbose", + "storybook": "storybook dev -p 9010", "build-storybook": "storybook build -c .storybook -o public --quiet" }, "devDependencies": { @@ -30,7 +30,6 @@ "@storybook/addon-storysource": "^8.4.4", "@storybook/addon-webpack5-compiler-babel": "^3.0.3", "@storybook/react": "^8.4.4", - "@storybook/react-vite": "^8.4.4", "@storybook/react-webpack5": "^8.4.4", "@storybook/source-loader": "^8.4.4", "@types/jest": "^29.5.2", @@ -61,7 +60,6 @@ "react-dom": "^18.3.1", "storybook": "^8.4.4", "ts-jest": "^29.1.0", - "tsconfig-paths-webpack-plugin": "^4.2.0", "typescript": "^5.1.3", "whatwg-fetch": "^3.0.0" }, diff --git a/packages/ra-core/src/auth/CanAccess.stories.tsx b/packages/ra-core/src/auth/CanAccess.stories.tsx index 2f40a68c7bc..b7c9b625828 100644 --- a/packages/ra-core/src/auth/CanAccess.stories.tsx +++ b/packages/ra-core/src/auth/CanAccess.stories.tsx @@ -28,7 +28,6 @@ export const Basic = ({ ); -// Basic.parameters = { storySource: { source: 'TEST JB' } }; export const AccessDenied = ({ authProvider = defaultAuthProvider, From 58e1f6ba5845f5bc5663bd9c1fc4e2b0cbcd911d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Wed, 20 Nov 2024 11:01:16 +0100 Subject: [PATCH 04/91] fix cleanup --- .storybook/main.ts | 2 +- yarn.lock | 208 +-------------------------------------------- 2 files changed, 4 insertions(+), 206 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 41247207047..410cb31cad8 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -76,7 +76,7 @@ const config: StorybookConfig = { `../packages/${pkg}/src` ), }), - { ...config.resolve?.alias } + {} ), }, }; diff --git a/yarn.lock b/yarn.lock index bfc894747ed..51434a03376 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2725,24 +2725,6 @@ __metadata: languageName: node linkType: hard -"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0": - version: 0.3.0 - resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0" - dependencies: - glob: "npm:^7.2.0" - glob-promise: "npm:^4.2.0" - magic-string: "npm:^0.27.0" - react-docgen-typescript: "npm:^2.2.2" - peerDependencies: - typescript: ">= 4.3.x" - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 31098ad8fcc2440437534599c111d9f2951dd74821e8ba46c521b969bae4c918d830b7bb0484efbad29a51711bb62d3bc623d5a1ed5b1695b5b5594ea9dd4ca0 - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -2785,13 +2767,6 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 - languageName: node - linkType: hard - "@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.15, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -3758,22 +3733,6 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.2": - version: 5.1.3 - resolution: "@rollup/pluginutils@npm:5.1.3" - dependencies: - "@types/estree": "npm:^1.0.0" - estree-walker: "npm:^2.0.2" - picomatch: "npm:^4.0.2" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: ba46ad588733fb01d184ee3bc7a127d626158bc840b5874a94c129ff62689d12f16f537530709c54da6f3b71f67d705c4e09235b1dc9542e9d47ee8f2d0b8b9e - languageName: node - linkType: hard - "@rollup/rollup-android-arm-eabi@npm:4.22.4": version: 4.22.4 resolution: "@rollup/rollup-android-arm-eabi@npm:4.22.4" @@ -3987,20 +3946,6 @@ __metadata: languageName: node linkType: hard -"@storybook/builder-vite@npm:8.4.4": - version: 8.4.4 - resolution: "@storybook/builder-vite@npm:8.4.4" - dependencies: - "@storybook/csf-plugin": "npm:8.4.4" - browser-assert: "npm:^1.2.1" - ts-dedent: "npm:^2.0.0" - peerDependencies: - storybook: ^8.4.4 - vite: ^4.0.0 || ^5.0.0 - checksum: f5fd27b048930fe17db4bd90becaee9980d952998149d1e9fce7cdb273898eb2d954787c9e7bb3829f9858e1a2503fce02afce67d7941f9b996f5363e9f3d063 - languageName: node - linkType: hard - "@storybook/builder-webpack5@npm:8.4.4": version: 8.4.4 resolution: "@storybook/builder-webpack5@npm:8.4.4" @@ -4084,17 +4029,6 @@ __metadata: languageName: node linkType: hard -"@storybook/csf-plugin@npm:8.4.4": - version: 8.4.4 - resolution: "@storybook/csf-plugin@npm:8.4.4" - dependencies: - unplugin: "npm:^1.3.1" - peerDependencies: - storybook: ^8.4.4 - checksum: d62e1288b0ed900af8f3c617496ceb908ffafd4b6cf7fc97c5e008cfa153d04245a18c9a008d6a59beb7720bbc88f272224dc19e2425db4b0d5d88ac38d2a885 - languageName: node - linkType: hard - "@storybook/csf@npm:^0.1.11": version: 0.1.11 resolution: "@storybook/csf@npm:0.1.11" @@ -4185,28 +4119,6 @@ __metadata: languageName: node linkType: hard -"@storybook/react-vite@npm:^8.4.4": - version: 8.4.4 - resolution: "@storybook/react-vite@npm:8.4.4" - dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" - "@rollup/pluginutils": "npm:^5.0.2" - "@storybook/builder-vite": "npm:8.4.4" - "@storybook/react": "npm:8.4.4" - find-up: "npm:^5.0.0" - magic-string: "npm:^0.30.0" - react-docgen: "npm:^7.0.0" - resolve: "npm:^1.22.8" - tsconfig-paths: "npm:^4.2.0" - 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: ^8.4.4 - vite: ^4.0.0 || ^5.0.0 - checksum: 2e3abd5b61fe05a2aa784a744d4700d1c5e2644cf5cc2b23b083a7227627a550c2cb8744f4571b693c6a24e783b931c1bd87441d89d960d6f5da7eef14c8a7e2 - languageName: node - linkType: hard - "@storybook/react-webpack5@npm:^8.4.4": version: 8.4.4 resolution: "@storybook/react-webpack5@npm:8.4.4" @@ -4930,13 +4842,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:^1.0.0": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a - languageName: node - linkType: hard - "@types/faker@npm:^5.1.7": version: 5.5.9 resolution: "@types/faker@npm:5.5.9" @@ -4951,16 +4856,6 @@ __metadata: languageName: node linkType: hard -"@types/glob@npm:^7.1.3": - version: 7.2.0 - resolution: "@types/glob@npm:7.2.0" - dependencies: - "@types/minimatch": "npm:*" - "@types/node": "npm:*" - checksum: a8eb5d5cb5c48fc58c7ca3ff1e1ddf771ee07ca5043da6e4871e6757b4472e2e73b4cfef2644c38983174a4bc728c73f8da02845c28a1212f98cabd293ecae98 - languageName: node - linkType: hard - "@types/graceful-fs@npm:^4.1.3": version: 4.1.6 resolution: "@types/graceful-fs@npm:4.1.6" @@ -5073,13 +4968,6 @@ __metadata: languageName: node linkType: hard -"@types/minimatch@npm:*": - version: 5.1.2 - resolution: "@types/minimatch@npm:5.1.2" - checksum: 83cf1c11748891b714e129de0585af4c55dd4c2cafb1f1d5233d79246e5e1e19d1b5ad9e8db449667b3ffa2b6c80125c429dbee1054e9efb45758dbc4e118562 - languageName: node - linkType: hard - "@types/minimatch@npm:^3.0.3": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" @@ -5868,15 +5756,6 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.14.0": - version: 8.14.0 - resolution: "acorn@npm:8.14.0" - bin: - acorn: bin/acorn - checksum: 6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7 - languageName: node - linkType: hard - "add-stream@npm:^1.0.0": version: 1.0.0 resolution: "add-stream@npm:1.0.0" @@ -8780,7 +8659,7 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.17.1, enhanced-resolve@npm:^5.7.0": +"enhanced-resolve@npm:^5.17.1": version: 5.17.1 resolution: "enhanced-resolve@npm:5.17.1" dependencies: @@ -9590,13 +9469,6 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^2.0.2": - version: 2.0.2 - resolution: "estree-walker@npm:2.0.2" - checksum: 53a6c54e2019b8c914dc395890153ffdc2322781acf4bd7d1a32d7aedc1710807bdcd866ac133903d5629ec601fbb50abe8c2e5553c7f5a0afdd9b6af6c945af - languageName: node - linkType: hard - "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -10699,17 +10571,6 @@ __metadata: languageName: node linkType: hard -"glob-promise@npm:^4.2.0": - version: 4.2.2 - resolution: "glob-promise@npm:4.2.2" - dependencies: - "@types/glob": "npm:^7.1.3" - peerDependencies: - glob: ^7.1.6 - checksum: 3eb01bed2901539365df6a4d27800afb8788840647d01f9bf3500b3de756597f2ff4b8c823971ace34db228c83159beca459dc42a70968d4e9c8200ed2cc96bd - languageName: node - linkType: hard - "glob-to-regexp@npm:^0.4.0, glob-to-regexp@npm:^0.4.1": version: 0.4.1 resolution: "glob-to-regexp@npm:0.4.1" @@ -10760,20 +10621,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - "glob@npm:^8.0.1": version: 8.0.3 resolution: "glob@npm:8.0.3" @@ -13543,24 +13390,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.27.0": - version: 0.27.0 - resolution: "magic-string@npm:0.27.0" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.4.13" - checksum: cddacfea14441ca57ae8a307bc3cf90bac69efaa4138dd9a80804cffc2759bf06f32da3a293fb13eaa96334b7d45b7768a34f1d226afae25d2f05b05a3bb37d8 - languageName: node - linkType: hard - -"magic-string@npm:^0.30.0": - version: 0.30.12 - resolution: "magic-string@npm:0.30.12" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 469f457d18af37dfcca8617086ea8a65bcd8b60ba8a1182cb024ce43e470ace3c9d1cb6bee58d3b311768fb16bc27bd50bdeebcaa63dadd0fd46cac4d2e11d5f - languageName: node - linkType: hard - "magic-string@npm:^0.30.5": version: 0.30.10 resolution: "magic-string@npm:0.30.10" @@ -13885,7 +13714,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -15319,13 +15148,6 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - "pidtree@npm:^0.6.0": version: 0.6.0 resolution: "pidtree@npm:0.6.0" @@ -16418,7 +16240,6 @@ __metadata: "@storybook/addon-storysource": "npm:^8.4.4" "@storybook/addon-webpack5-compiler-babel": "npm:^3.0.3" "@storybook/react": "npm:^8.4.4" - "@storybook/react-vite": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" "@storybook/source-loader": "npm:^8.4.4" "@types/jest": "npm:^29.5.2" @@ -16449,7 +16270,6 @@ __metadata: react-dom: "npm:^18.3.1" storybook: "npm:^8.4.4" ts-jest: "npm:^29.1.0" - tsconfig-paths-webpack-plugin: "npm:^4.2.0" typescript: "npm:^5.1.3" whatwg-fetch: "npm:^3.0.0" dependenciesMeta: @@ -18804,18 +18624,6 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths-webpack-plugin@npm:^4.2.0": - version: 4.2.0 - resolution: "tsconfig-paths-webpack-plugin@npm:4.2.0" - dependencies: - chalk: "npm:^4.1.0" - enhanced-resolve: "npm:^5.7.0" - tapable: "npm:^2.2.1" - tsconfig-paths: "npm:^4.1.2" - checksum: 495c5ab7c1cb079217d98fe25d61def01e4bab38047c7ab25ec11876cc8c697ff01f43ea6c9933181875e51e49835407fc71afd92ea6cca1ba1bebf513dfb510 - languageName: node - linkType: hard - "tsconfig-paths@npm:^3.12.0": version: 3.14.1 resolution: "tsconfig-paths@npm:3.14.1" @@ -19169,16 +18977,6 @@ __metadata: languageName: node linkType: hard -"unplugin@npm:^1.3.1": - version: 1.16.0 - resolution: "unplugin@npm:1.16.0" - dependencies: - acorn: "npm:^8.14.0" - webpack-virtual-modules: "npm:^0.6.2" - checksum: 547f6bd5ec1dd7411533e68e73c60d5e9527e68d52aa326442650d084866ed3307ac68719068abae23ceab09db197cad43b382a7e69c2d8ca338b27802392fed - languageName: node - linkType: hard - "untildify@npm:^4.0.0": version: 4.0.0 resolution: "untildify@npm:4.0.0" @@ -19544,7 +19342,7 @@ __metadata: languageName: node linkType: hard -"webpack-virtual-modules@npm:^0.6.0, webpack-virtual-modules@npm:^0.6.2": +"webpack-virtual-modules@npm:^0.6.0": version: 0.6.2 resolution: "webpack-virtual-modules@npm:0.6.2" checksum: 5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add From 74dcf496c1f1913c797d0cbc5ec345da6a472e66 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Wed, 20 Nov 2024 14:33:05 +0100 Subject: [PATCH 05/91] [Chore] Reorganize ra-core/form directory --- packages/ra-core/src/form/Form.spec.tsx | 2 +- packages/ra-core/src/form/Form.stories.tsx | 3 +- packages/ra-core/src/form/Form.tsx | 4 +- .../src/form/FormDataConsumer.spec.tsx | 2 +- .../ra-core/src/form/FormDataConsumer.tsx | 6 +-- packages/ra-core/src/form/choices/index.ts | 1 + .../form/{ => choices}/useChoices.spec.tsx | 4 +- .../src/form/{ => choices}/useChoices.tsx | 6 +-- .../src/form/{ => groups}/FormGroupContext.ts | 0 .../{ => groups}/FormGroupContextProvider.tsx | 0 .../form/{ => groups}/FormGroupsContext.tsx | 0 .../form/{ => groups}/FormGroupsProvider.tsx | 0 packages/ra-core/src/form/groups/index.tsx | 6 +++ .../form/{ => groups}/useFormGroup.spec.tsx | 4 +- .../src/form/{ => groups}/useFormGroup.ts | 2 +- .../form/{ => groups}/useFormGroupContext.ts | 0 .../src/form/{ => groups}/useFormGroups.ts | 0 packages/ra-core/src/form/index.ts | 45 ++----------------- packages/ra-core/src/form/isRequired.ts | 11 ----- packages/ra-core/src/form/useAugmentedForm.ts | 6 +-- packages/ra-core/src/form/useInput.spec.tsx | 2 +- packages/ra-core/src/form/useInput.ts | 6 +-- packages/ra-core/src/form/useSuggestions.ts | 6 ++- .../{ => validation}/ValidationError.spec.tsx | 4 +- .../form/{ => validation}/ValidationError.tsx | 6 +-- .../getSimpleValidationResolver.spec.ts | 0 .../getSimpleValidationResolver.ts | 0 packages/ra-core/src/form/validation/index.ts | 7 +++ .../setSubmissionErrors.spec.ts | 0 .../{ => validation}/setSubmissionErrors.ts | 0 .../useGetValidationErrorMessage.ts | 2 +- .../useNotifyIsFormInvalid.ts | 2 +- .../form/{ => validation}/useUnique.spec.tsx | 4 +- .../{ => validation}/useUnique.stories.tsx | 8 ++-- .../src/form/{ => validation}/useUnique.ts | 14 +++--- .../form/{ => validation}/validate.spec.ts | 0 .../src/form/{ => validation}/validate.ts | 0 37 files changed, 63 insertions(+), 100 deletions(-) rename packages/ra-core/src/form/{ => choices}/useChoices.spec.tsx (96%) rename packages/ra-core/src/form/{ => choices}/useChoices.tsx (94%) rename packages/ra-core/src/form/{ => groups}/FormGroupContext.ts (100%) rename packages/ra-core/src/form/{ => groups}/FormGroupContextProvider.tsx (100%) rename packages/ra-core/src/form/{ => groups}/FormGroupsContext.tsx (100%) rename packages/ra-core/src/form/{ => groups}/FormGroupsProvider.tsx (100%) create mode 100644 packages/ra-core/src/form/groups/index.tsx rename packages/ra-core/src/form/{ => groups}/useFormGroup.spec.tsx (98%) rename packages/ra-core/src/form/{ => groups}/useFormGroup.ts (99%) rename packages/ra-core/src/form/{ => groups}/useFormGroupContext.ts (100%) rename packages/ra-core/src/form/{ => groups}/useFormGroups.ts (100%) delete mode 100644 packages/ra-core/src/form/isRequired.ts rename packages/ra-core/src/form/{ => validation}/ValidationError.spec.tsx (96%) rename packages/ra-core/src/form/{ => validation}/ValidationError.tsx (90%) rename packages/ra-core/src/form/{ => validation}/getSimpleValidationResolver.spec.ts (100%) rename packages/ra-core/src/form/{ => validation}/getSimpleValidationResolver.ts (100%) create mode 100644 packages/ra-core/src/form/validation/index.ts rename packages/ra-core/src/form/{ => validation}/setSubmissionErrors.spec.ts (100%) rename packages/ra-core/src/form/{ => validation}/setSubmissionErrors.ts (100%) rename packages/ra-core/src/form/{ => validation}/useGetValidationErrorMessage.ts (96%) rename packages/ra-core/src/form/{ => validation}/useNotifyIsFormInvalid.ts (96%) rename packages/ra-core/src/form/{ => validation}/useUnique.spec.tsx (98%) rename packages/ra-core/src/form/{ => validation}/useUnique.stories.tsx (98%) rename packages/ra-core/src/form/{ => validation}/useUnique.ts (93%) rename packages/ra-core/src/form/{ => validation}/validate.spec.ts (100%) rename packages/ra-core/src/form/{ => validation}/validate.ts (100%) diff --git a/packages/ra-core/src/form/Form.spec.tsx b/packages/ra-core/src/form/Form.spec.tsx index d99356b9907..fef541ead55 100644 --- a/packages/ra-core/src/form/Form.spec.tsx +++ b/packages/ra-core/src/form/Form.spec.tsx @@ -11,7 +11,7 @@ import { CoreAdminContext } from '../core'; import { Form } from './Form'; import { useNotificationContext } from '../notification'; import { useInput } from './useInput'; -import { required } from './validate'; +import { required } from './validation/validate'; import { FormLevelValidation, InputLevelValidation, diff --git a/packages/ra-core/src/form/Form.stories.tsx b/packages/ra-core/src/form/Form.stories.tsx index 45cf423956d..32402820bbb 100644 --- a/packages/ra-core/src/form/Form.stories.tsx +++ b/packages/ra-core/src/form/Form.stories.tsx @@ -13,8 +13,7 @@ import { Route, Routes, useNavigate, Link, HashRouter } from 'react-router-dom'; import { CoreAdminContext } from '../core'; import { Form } from './Form'; import { useInput } from './useInput'; -import { required } from './validate'; -import ValidationError from './ValidationError'; +import { required, ValidationError } from './validation'; import { mergeTranslations } from '../i18n'; import { I18nProvider } from '../types'; import { SaveContextProvider, useNotificationContext } from '..'; diff --git a/packages/ra-core/src/form/Form.tsx b/packages/ra-core/src/form/Form.tsx index a75fdf35932..bc3aa2d3ef7 100644 --- a/packages/ra-core/src/form/Form.tsx +++ b/packages/ra-core/src/form/Form.tsx @@ -11,7 +11,7 @@ import { UNSAFE_DataRouterStateContext, } from 'react-router'; -import { FormGroupsProvider } from './FormGroupsProvider'; +import { FormGroupsProvider } from './groups/FormGroupsProvider'; import { RaRecord } from '../types'; import { useRecordContext, @@ -23,7 +23,7 @@ import { SourceContextValue, useResourceContext, } from '../core'; -import { ValidateForm } from './getSimpleValidationResolver'; +import { ValidateForm } from './validation/getSimpleValidationResolver'; import { WarnWhenUnsavedChanges } from './WarnWhenUnsavedChanges'; import { useAugmentedForm } from './useAugmentedForm'; diff --git a/packages/ra-core/src/form/FormDataConsumer.spec.tsx b/packages/ra-core/src/form/FormDataConsumer.spec.tsx index c7ac43d64cd..6bfb2fdcf11 100644 --- a/packages/ra-core/src/form/FormDataConsumer.spec.tsx +++ b/packages/ra-core/src/form/FormDataConsumer.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { render, waitFor, screen, fireEvent } from '@testing-library/react'; -import FormDataConsumer, { FormDataConsumerView } from './FormDataConsumer'; +import { FormDataConsumer, FormDataConsumerView } from './FormDataConsumer'; import { testDataProvider } from '../dataProvider'; import { AdminContext, diff --git a/packages/ra-core/src/form/FormDataConsumer.tsx b/packages/ra-core/src/form/FormDataConsumer.tsx index 84c0c2c4663..39205f7ec27 100644 --- a/packages/ra-core/src/form/FormDataConsumer.tsx +++ b/packages/ra-core/src/form/FormDataConsumer.tsx @@ -42,7 +42,9 @@ import { useWrappedSource } from '../core'; * * ); */ -const FormDataConsumer = ( +export const FormDataConsumer = < + TFieldValues extends FieldValues = FieldValues, +>( props: ConnectedProps ) => { const form = useFormContext(); @@ -83,8 +85,6 @@ export const FormDataConsumerView = < return ret === undefined ? null : ret; }; -export default FormDataConsumer; - const ArraySourceRegex = new RegExp(/.+\.\d+$/); export interface FormDataConsumerRenderParams< diff --git a/packages/ra-core/src/form/choices/index.ts b/packages/ra-core/src/form/choices/index.ts index 6ca3a50a0c6..94587291021 100644 --- a/packages/ra-core/src/form/choices/index.ts +++ b/packages/ra-core/src/form/choices/index.ts @@ -1,3 +1,4 @@ export * from './ChoicesContext'; export * from './ChoicesContextProvider'; export * from './useChoicesContext'; +export * from './useChoices'; diff --git a/packages/ra-core/src/form/useChoices.spec.tsx b/packages/ra-core/src/form/choices/useChoices.spec.tsx similarity index 96% rename from packages/ra-core/src/form/useChoices.spec.tsx rename to packages/ra-core/src/form/choices/useChoices.spec.tsx index 659deb84d91..1d8598ff96b 100644 --- a/packages/ra-core/src/form/useChoices.spec.tsx +++ b/packages/ra-core/src/form/choices/useChoices.spec.tsx @@ -3,8 +3,8 @@ import expect from 'expect'; import { render, screen } from '@testing-library/react'; import { useChoices } from './useChoices'; -import { TestTranslationProvider } from '../i18n'; -import { useRecordContext } from '../controller'; +import { TestTranslationProvider } from '../../i18n'; +import { useRecordContext } from '../../controller'; describe('useChoices hook', () => { const defaultProps = { diff --git a/packages/ra-core/src/form/useChoices.tsx b/packages/ra-core/src/form/choices/useChoices.tsx similarity index 94% rename from packages/ra-core/src/form/useChoices.tsx rename to packages/ra-core/src/form/choices/useChoices.tsx index b24ecbeafa2..03de60d7a1b 100644 --- a/packages/ra-core/src/form/useChoices.tsx +++ b/packages/ra-core/src/form/choices/useChoices.tsx @@ -2,9 +2,9 @@ import * as React from 'react'; import { ReactElement, isValidElement, useCallback } from 'react'; import get from 'lodash/get'; -import { useTranslate } from '../i18n'; -import { RaRecord } from '../types'; -import { RecordContextProvider } from '../controller'; +import { useTranslate } from '../../i18n'; +import { RaRecord } from '../../types'; +import { RecordContextProvider } from '../../controller'; export type OptionTextElement = ReactElement<{ record: RaRecord; diff --git a/packages/ra-core/src/form/FormGroupContext.ts b/packages/ra-core/src/form/groups/FormGroupContext.ts similarity index 100% rename from packages/ra-core/src/form/FormGroupContext.ts rename to packages/ra-core/src/form/groups/FormGroupContext.ts diff --git a/packages/ra-core/src/form/FormGroupContextProvider.tsx b/packages/ra-core/src/form/groups/FormGroupContextProvider.tsx similarity index 100% rename from packages/ra-core/src/form/FormGroupContextProvider.tsx rename to packages/ra-core/src/form/groups/FormGroupContextProvider.tsx diff --git a/packages/ra-core/src/form/FormGroupsContext.tsx b/packages/ra-core/src/form/groups/FormGroupsContext.tsx similarity index 100% rename from packages/ra-core/src/form/FormGroupsContext.tsx rename to packages/ra-core/src/form/groups/FormGroupsContext.tsx diff --git a/packages/ra-core/src/form/FormGroupsProvider.tsx b/packages/ra-core/src/form/groups/FormGroupsProvider.tsx similarity index 100% rename from packages/ra-core/src/form/FormGroupsProvider.tsx rename to packages/ra-core/src/form/groups/FormGroupsProvider.tsx diff --git a/packages/ra-core/src/form/groups/index.tsx b/packages/ra-core/src/form/groups/index.tsx new file mode 100644 index 00000000000..f58e1a4b4cf --- /dev/null +++ b/packages/ra-core/src/form/groups/index.tsx @@ -0,0 +1,6 @@ +export * from './FormGroupContext'; +export * from './FormGroupContextProvider'; +export * from './FormGroupsProvider'; +export * from './useFormGroup'; +export * from './useFormGroups'; +export * from './useFormGroupContext'; diff --git a/packages/ra-core/src/form/useFormGroup.spec.tsx b/packages/ra-core/src/form/groups/useFormGroup.spec.tsx similarity index 98% rename from packages/ra-core/src/form/useFormGroup.spec.tsx rename to packages/ra-core/src/form/groups/useFormGroup.spec.tsx index 726f7523c46..12ddb377c3c 100644 --- a/packages/ra-core/src/form/useFormGroup.spec.tsx +++ b/packages/ra-core/src/form/groups/useFormGroup.spec.tsx @@ -10,8 +10,8 @@ import { import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import expect from 'expect'; import { FormGroupContextProvider } from './FormGroupContextProvider'; -import { testDataProvider } from '../dataProvider'; -import { ResourceContextProvider } from '..'; +import { testDataProvider } from '../../dataProvider'; +import { ResourceContextProvider } from '../..'; describe('useFormGroup', () => { test.each([ diff --git a/packages/ra-core/src/form/useFormGroup.ts b/packages/ra-core/src/form/groups/useFormGroup.ts similarity index 99% rename from packages/ra-core/src/form/useFormGroup.ts rename to packages/ra-core/src/form/groups/useFormGroup.ts index 5aaa915f33d..f6f168640cc 100644 --- a/packages/ra-core/src/form/useFormGroup.ts +++ b/packages/ra-core/src/form/groups/useFormGroup.ts @@ -3,7 +3,7 @@ import get from 'lodash/get'; import isEqual from 'lodash/isEqual'; import { useFormState } from 'react-hook-form'; import { useFormGroups } from './useFormGroups'; -import { useEvent } from '../util'; +import { useEvent } from '../../util'; type FieldState = { name: string; diff --git a/packages/ra-core/src/form/useFormGroupContext.ts b/packages/ra-core/src/form/groups/useFormGroupContext.ts similarity index 100% rename from packages/ra-core/src/form/useFormGroupContext.ts rename to packages/ra-core/src/form/groups/useFormGroupContext.ts diff --git a/packages/ra-core/src/form/useFormGroups.ts b/packages/ra-core/src/form/groups/useFormGroups.ts similarity index 100% rename from packages/ra-core/src/form/useFormGroups.ts rename to packages/ra-core/src/form/groups/useFormGroups.ts diff --git a/packages/ra-core/src/form/index.ts b/packages/ra-core/src/form/index.ts index eff073babf8..f7a5799dded 100644 --- a/packages/ra-core/src/form/index.ts +++ b/packages/ra-core/src/form/index.ts @@ -1,50 +1,11 @@ -import FormDataConsumer, { - FormDataConsumerRender, - FormDataConsumerRenderParams, -} from './FormDataConsumer'; -import { - FormGroupsContext, - FormGroupsContextValue, - FormGroupSubscriber, -} from './FormGroupsContext'; -import ValidationError, { ValidationErrorProps } from './ValidationError'; -import { - getSimpleValidationResolver, - ValidateForm, -} from './getSimpleValidationResolver'; - -export type { - FormGroupsContextValue, - FormGroupSubscriber, - FormDataConsumerRender, - FormDataConsumerRenderParams, - ValidationErrorProps, - ValidateForm, -}; - -export { - FormDataConsumer, - FormGroupsContext, - ValidationError, - getSimpleValidationResolver, -}; export * from './choices'; export * from './Form'; -export * from './validate'; -export * from './FormGroupContext'; -export * from './FormGroupContextProvider'; -export * from './FormGroupsProvider'; -export * from './setSubmissionErrors'; +export * from './FormDataConsumer'; +export * from './groups'; export * from './useApplyInputDefaultValues'; -export * from './useChoices'; -export * from './useFormGroup'; -export * from './useFormGroups'; -export * from './useFormGroupContext'; -export * from './useGetValidationErrorMessage'; -export * from './useNotifyIsFormInvalid'; export * from './useAugmentedForm'; export * from './useInput'; export * from './useSuggestions'; -export * from './useUnique'; export * from './useWarnWhenUnsavedChanges'; +export * from './validation'; export * from './WarnWhenUnsavedChanges'; diff --git a/packages/ra-core/src/form/isRequired.ts b/packages/ra-core/src/form/isRequired.ts deleted file mode 100644 index 72b21442951..00000000000 --- a/packages/ra-core/src/form/isRequired.ts +++ /dev/null @@ -1,11 +0,0 @@ -const isRequired = validate => { - if (validate && validate.isRequired) { - return true; - } - if (Array.isArray(validate)) { - return validate.some(it => it.isRequired); - } - return false; -}; - -export default isRequired; diff --git a/packages/ra-core/src/form/useAugmentedForm.ts b/packages/ra-core/src/form/useAugmentedForm.ts index 7931bfa0272..d497e9a14b0 100644 --- a/packages/ra-core/src/form/useAugmentedForm.ts +++ b/packages/ra-core/src/form/useAugmentedForm.ts @@ -13,9 +13,9 @@ import getFormInitialValues from './getFormInitialValues'; import { getSimpleValidationResolver, ValidateForm, -} from './getSimpleValidationResolver'; -import { setSubmissionErrors } from './setSubmissionErrors'; -import { useNotifyIsFormInvalid } from './useNotifyIsFormInvalid'; +} from './validation/getSimpleValidationResolver'; +import { setSubmissionErrors } from './validation/setSubmissionErrors'; +import { useNotifyIsFormInvalid } from './validation/useNotifyIsFormInvalid'; import { sanitizeEmptyValues as sanitizeValues } from './sanitizeEmptyValues'; /** diff --git a/packages/ra-core/src/form/useInput.spec.tsx b/packages/ra-core/src/form/useInput.spec.tsx index 78ea8262969..43628bad231 100644 --- a/packages/ra-core/src/form/useInput.spec.tsx +++ b/packages/ra-core/src/form/useInput.spec.tsx @@ -6,7 +6,7 @@ import { CoreAdminContext, SourceContextProvider } from '../core'; import { testDataProvider } from '../dataProvider'; import { Form } from './Form'; import { useInput, InputProps, UseInputValue } from './useInput'; -import { required } from './validate'; +import { required } from './validation/validate'; const Input: FunctionComponent< { diff --git a/packages/ra-core/src/form/useInput.ts b/packages/ra-core/src/form/useInput.ts index 5913950ecdc..29f0f39b898 100644 --- a/packages/ra-core/src/form/useInput.ts +++ b/packages/ra-core/src/form/useInput.ts @@ -10,10 +10,8 @@ import { import get from 'lodash/get'; import { useRecordContext } from '../controller'; -import { composeValidators, Validator } from './validate'; -import isRequired from './isRequired'; -import { useFormGroupContext } from './useFormGroupContext'; -import { useFormGroups } from './useFormGroups'; +import { composeValidators, Validator, isRequired } from './validation'; +import { useFormGroupContext, useFormGroups } from './groups'; import { useApplyInputDefaultValues } from './useApplyInputDefaultValues'; import { useEvent } from '../util'; import { useWrappedSource } from '../core'; diff --git a/packages/ra-core/src/form/useSuggestions.ts b/packages/ra-core/src/form/useSuggestions.ts index bac3730de7f..f2f6fdf4cd6 100644 --- a/packages/ra-core/src/form/useSuggestions.ts +++ b/packages/ra-core/src/form/useSuggestions.ts @@ -1,6 +1,10 @@ import { useCallback, isValidElement, ReactElement } from 'react'; import set from 'lodash/set'; -import { useChoices, OptionText, UseChoicesOptions } from './useChoices'; +import { + useChoices, + OptionText, + UseChoicesOptions, +} from './choices/useChoices'; import { useTranslate } from '../i18n'; /* diff --git a/packages/ra-core/src/form/ValidationError.spec.tsx b/packages/ra-core/src/form/validation/ValidationError.spec.tsx similarity index 96% rename from packages/ra-core/src/form/ValidationError.spec.tsx rename to packages/ra-core/src/form/validation/ValidationError.spec.tsx index 27e79bcded5..9f35a9f4432 100644 --- a/packages/ra-core/src/form/ValidationError.spec.tsx +++ b/packages/ra-core/src/form/validation/ValidationError.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { render } from '@testing-library/react'; -import ValidationError from './ValidationError'; -import { TestTranslationProvider } from '../i18n'; +import { ValidationError } from './ValidationError'; +import { TestTranslationProvider } from '../../i18n'; const translate = jest.fn(key => { return key; diff --git a/packages/ra-core/src/form/ValidationError.tsx b/packages/ra-core/src/form/validation/ValidationError.tsx similarity index 90% rename from packages/ra-core/src/form/ValidationError.tsx rename to packages/ra-core/src/form/validation/ValidationError.tsx index 85112ebab7d..a6ce35c21ca 100644 --- a/packages/ra-core/src/form/ValidationError.tsx +++ b/packages/ra-core/src/form/validation/ValidationError.tsx @@ -3,14 +3,14 @@ import { ValidationErrorMessage, ValidationErrorMessageWithArgs, } from './validate'; -import { useTranslate } from '../i18n'; +import { useTranslate } from '../../i18n'; export interface ValidationErrorProps { error: ValidationErrorMessage; } const ValidationErrorSpecialFormatPrefix = '@@react-admin@@'; -const ValidationError = (props: ValidationErrorProps) => { +export const ValidationError = (props: ValidationErrorProps) => { const { error } = props; let errorMessage = error; const translate = useTranslate(); @@ -35,5 +35,3 @@ const ValidationError = (props: ValidationErrorProps) => { return <>{translate(errorMessage as string, { _: errorMessage })}; }; - -export default ValidationError; diff --git a/packages/ra-core/src/form/getSimpleValidationResolver.spec.ts b/packages/ra-core/src/form/validation/getSimpleValidationResolver.spec.ts similarity index 100% rename from packages/ra-core/src/form/getSimpleValidationResolver.spec.ts rename to packages/ra-core/src/form/validation/getSimpleValidationResolver.spec.ts diff --git a/packages/ra-core/src/form/getSimpleValidationResolver.ts b/packages/ra-core/src/form/validation/getSimpleValidationResolver.ts similarity index 100% rename from packages/ra-core/src/form/getSimpleValidationResolver.ts rename to packages/ra-core/src/form/validation/getSimpleValidationResolver.ts diff --git a/packages/ra-core/src/form/validation/index.ts b/packages/ra-core/src/form/validation/index.ts new file mode 100644 index 00000000000..a872b5bfca4 --- /dev/null +++ b/packages/ra-core/src/form/validation/index.ts @@ -0,0 +1,7 @@ +export * from './getSimpleValidationResolver'; +export * from './setSubmissionErrors'; +export * from './useGetValidationErrorMessage'; +export * from './useNotifyIsFormInvalid'; +export * from './useUnique'; +export * from './validate'; +export * from './ValidationError'; diff --git a/packages/ra-core/src/form/setSubmissionErrors.spec.ts b/packages/ra-core/src/form/validation/setSubmissionErrors.spec.ts similarity index 100% rename from packages/ra-core/src/form/setSubmissionErrors.spec.ts rename to packages/ra-core/src/form/validation/setSubmissionErrors.spec.ts diff --git a/packages/ra-core/src/form/setSubmissionErrors.ts b/packages/ra-core/src/form/validation/setSubmissionErrors.ts similarity index 100% rename from packages/ra-core/src/form/setSubmissionErrors.ts rename to packages/ra-core/src/form/validation/setSubmissionErrors.ts diff --git a/packages/ra-core/src/form/useGetValidationErrorMessage.ts b/packages/ra-core/src/form/validation/useGetValidationErrorMessage.ts similarity index 96% rename from packages/ra-core/src/form/useGetValidationErrorMessage.ts rename to packages/ra-core/src/form/validation/useGetValidationErrorMessage.ts index 5ac07152aed..42ee20a9ab4 100644 --- a/packages/ra-core/src/form/useGetValidationErrorMessage.ts +++ b/packages/ra-core/src/form/validation/useGetValidationErrorMessage.ts @@ -2,7 +2,7 @@ import { ValidationErrorMessage, ValidationErrorMessageWithArgs, } from './validate'; -import { useTranslate } from '../i18n'; +import { useTranslate } from '../../i18n'; /** * @deprecated diff --git a/packages/ra-core/src/form/useNotifyIsFormInvalid.ts b/packages/ra-core/src/form/validation/useNotifyIsFormInvalid.ts similarity index 96% rename from packages/ra-core/src/form/useNotifyIsFormInvalid.ts rename to packages/ra-core/src/form/validation/useNotifyIsFormInvalid.ts index 9731631863a..57f3ef26f3b 100644 --- a/packages/ra-core/src/form/useNotifyIsFormInvalid.ts +++ b/packages/ra-core/src/form/validation/useNotifyIsFormInvalid.ts @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; import { useFormState, Control } from 'react-hook-form'; -import { useNotify } from '../notification'; +import { useNotify } from '../../notification'; /** * This hook display an error message on submit in Form and SaveButton. diff --git a/packages/ra-core/src/form/useUnique.spec.tsx b/packages/ra-core/src/form/validation/useUnique.spec.tsx similarity index 98% rename from packages/ra-core/src/form/useUnique.spec.tsx rename to packages/ra-core/src/form/validation/useUnique.spec.tsx index 30292100779..9eeecece9cb 100644 --- a/packages/ra-core/src/form/useUnique.spec.tsx +++ b/packages/ra-core/src/form/validation/useUnique.spec.tsx @@ -8,8 +8,8 @@ import { WithAdditionalFilters, WithMessage, } from './useUnique.stories'; -import { testDataProvider } from '../dataProvider'; -import { DataProvider } from '../types'; +import { testDataProvider } from '../../dataProvider'; +import { DataProvider } from '../../types'; describe('useUnique', () => { const baseDataProvider = (overrides?: Partial) => diff --git a/packages/ra-core/src/form/useUnique.stories.tsx b/packages/ra-core/src/form/validation/useUnique.stories.tsx similarity index 98% rename from packages/ra-core/src/form/useUnique.stories.tsx rename to packages/ra-core/src/form/validation/useUnique.stories.tsx index cfa57fc92db..97aa3b85a35 100644 --- a/packages/ra-core/src/form/useUnique.stories.tsx +++ b/packages/ra-core/src/form/validation/useUnique.stories.tsx @@ -2,8 +2,8 @@ import * as React from 'react'; import fakerestDataProvider from 'ra-data-fakerest'; import polyglotI18nProvider from 'ra-i18n-polyglot'; import englishMessages from 'ra-language-english'; -import { Form } from './Form'; -import { useInput } from './useInput'; +import { Form } from '../Form'; +import { useInput } from '../useInput'; import { CoreAdminContext, CreateBase, @@ -13,9 +13,9 @@ import { ValidationError, mergeTranslations, useUnique, -} from '..'; +} from '../..'; import { QueryClient } from '@tanstack/react-query'; -import { TestMemoryRouter } from '../routing'; +import { TestMemoryRouter } from '../../routing'; export default { title: 'ra-core/form/useUnique', diff --git a/packages/ra-core/src/form/useUnique.ts b/packages/ra-core/src/form/validation/useUnique.ts similarity index 93% rename from packages/ra-core/src/form/useUnique.ts rename to packages/ra-core/src/form/validation/useUnique.ts index 631827d9533..825a9213cd8 100644 --- a/packages/ra-core/src/form/useUnique.ts +++ b/packages/ra-core/src/form/validation/useUnique.ts @@ -1,12 +1,12 @@ -import merge from 'lodash/merge'; -import { useResourceContext } from '../core'; -import { useDataProvider } from '../dataProvider'; -import { useTranslate, useTranslateLabel } from '../i18n'; -import { InputProps } from './useInput'; import { useCallback, useRef } from 'react'; +import merge from 'lodash/merge'; import set from 'lodash/set'; -import { asyncDebounce } from '../util'; -import { useRecordContext } from '../controller'; +import { useResourceContext } from '../../core'; +import { useDataProvider } from '../../dataProvider'; +import { useTranslate, useTranslateLabel } from '../../i18n'; +import { asyncDebounce } from '../../util'; +import { useRecordContext } from '../../controller'; +import { InputProps } from '../useInput'; import { isEmpty } from './validate'; /** diff --git a/packages/ra-core/src/form/validate.spec.ts b/packages/ra-core/src/form/validation/validate.spec.ts similarity index 100% rename from packages/ra-core/src/form/validate.spec.ts rename to packages/ra-core/src/form/validation/validate.spec.ts diff --git a/packages/ra-core/src/form/validate.ts b/packages/ra-core/src/form/validation/validate.ts similarity index 100% rename from packages/ra-core/src/form/validate.ts rename to packages/ra-core/src/form/validation/validate.ts From 0ca75bde1245c49926797a1ddd1c731271d3a702 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Wed, 20 Nov 2024 19:36:23 +0100 Subject: [PATCH 06/91] document `` as a filter --- docs/DateRangeInput.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/docs/DateRangeInput.md b/docs/DateRangeInput.md index ca646e1dc93..354ab924cc0 100644 --- a/docs/DateRangeInput.md +++ b/docs/DateRangeInput.md @@ -56,7 +56,7 @@ export const EventEdit = () => ( | `sx` | - | `SxProps` | - | The style to apply to the component. | | `validate` | - | `function|Array` | - | Validation rules for the input. See the [Validation Documentation](./Validation.md#per-input-validation-built-in-field-validators) for details. | -`` also accept the same props as [MUI X's ``](https://mui.com/x/api/date-pickers/date-range-picker/), except for the `format` prop (renamed `mask`), +`` also accept the same props as [MUI X's ``](https://mui.com/x/api/date-pickers/date-range-picker/), except for the `format` prop (renamed `mask`), **Tip:** Since `` stores its value as a date array, [react-admin's validators](./Validation.md#per-input-validation-built-in-field-validators) like `minValue` or `maxValue` won't work out of the box. @@ -142,6 +142,44 @@ const EventEdit = () => { }; ``` +## Using `` as a Filter + +`` can also be used to filter a ``. + +However, by default, `` returns `Date` objects with their time set to 00:00:00, which makes the upper bound *exclusive*. Usually, users will expect the upper bound to be *inclusive*. + +This can be achieved by providing a `parse` function that sets the time of the upper bound to 23:59:59. + +Here is an example: + +```tsx +import { DateRangeInput } from '@react-admin/ra-form-layout/DateRangeInput'; +import { List, Datagrid, NumberField, TextField, DateField } from 'react-admin'; +import { endOfDay } from 'date-fns'; + +const dateRangeFilterParse = (dates: (Date | null)[]) => { + return [dates[0], dates[1] ? endOfDay(dates[1]) : dates[1]]; +}; + +const eventsFilters = [ + , +]; + +export const EventsList = () => ( + + + + + + + +); +``` + ## Providing your own `LocalizationProvider` MUI X Pickers need to be wrapped in a [LocalizationProvider](https://mui.com/components/pickers/#localization) to work properly. `` already includes a default `` using the `date-fns` adapter and the `enUS` locale. @@ -171,4 +209,4 @@ export const App = () => ( **Note:** React-admin only supports the `date-fns` adapter for now. -**Tip**: React-admin already depends on `date-fns` v3 but your package manager may require you to add it to your dependencies. \ No newline at end of file +**Tip**: React-admin already depends on `date-fns` v3 but your package manager may require you to add it to your dependencies. From e607fa5f204bdaac281a3f435ae3ece3a1d1d9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Zaninotto?= Date: Wed, 20 Nov 2024 23:48:23 +0100 Subject: [PATCH 07/91] Fix SortButton default translation --- packages/ra-ui-materialui/src/button/SortButton.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/ra-ui-materialui/src/button/SortButton.tsx b/packages/ra-ui-materialui/src/button/SortButton.tsx index 74a3dfd269a..97b0799aaa5 100644 --- a/packages/ra-ui-materialui/src/button/SortButton.tsx +++ b/packages/ra-ui-materialui/src/button/SortButton.tsx @@ -91,11 +91,16 @@ const SortButton = (props: SortButtonProps) => { setAnchorEl(null); }; + const fieldLabel = translateLabel({ + resource, + source: sort.field, + }); const buttonLabel = translate(label, { - field: translateLabel({ - resource, - source: sort.field, - }), + field: fieldLabel, + field_lower_first: + typeof fieldLabel === 'string' + ? fieldLabel.charAt(0).toLowerCase() + fieldLabel.slice(1) + : undefined, order: translate(`ra.sort.${sort.order}`), _: label, }); From 4aec101553b49594f8fa0362543514def59e6802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Zaninotto?= Date: Wed, 20 Nov 2024 23:53:50 +0100 Subject: [PATCH 08/91] [Demo] Showcase tabs with icons --- examples/demo/src/products/ProductEdit.tsx | 19 ++++++++++++++++--- examples/demo/src/visitors/FullNameField.tsx | 2 ++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/demo/src/products/ProductEdit.tsx b/examples/demo/src/products/ProductEdit.tsx index ed7fed6a6c4..38f2d2ccadb 100644 --- a/examples/demo/src/products/ProductEdit.tsx +++ b/examples/demo/src/products/ProductEdit.tsx @@ -13,6 +13,10 @@ import { TextInput, useRecordContext, } from 'react-admin'; +import PhotoCameraIcon from '@mui/icons-material/PhotoCamera'; +import AspectRatioIcon from '@mui/icons-material/AspectRatio'; +import EditNoteIcon from '@mui/icons-material/EditNote'; +import ReviewIcon from '@mui/icons-material/Comment'; import { ProductEditDetails } from './ProductEditDetails'; import CustomerReferenceField from '../visitors/CustomerReferenceField'; @@ -37,7 +41,9 @@ const ProductEdit = () => ( } > @@ -46,14 +52,18 @@ const ProductEdit = () => ( } > } > @@ -67,6 +77,9 @@ const ProductEdit = () => ( /> } path="reviews" + sx={{ minHeight: 48 }} + iconPosition="start" + icon={} > { mr: 1, mt: -0.5, mb: -0.5, + textDecoration: 'underline', + textDecorationColor: '#bdbdbd', }} /> {record.first_name} {record.last_name} From d8950e9bacab1e04b88d016fb47481343d11de39 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 21 Nov 2024 09:36:27 +0100 Subject: [PATCH 09/91] Fix story path --- packages/ra-core/src/form/validation/useUnique.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ra-core/src/form/validation/useUnique.stories.tsx b/packages/ra-core/src/form/validation/useUnique.stories.tsx index 97aa3b85a35..be25d73c971 100644 --- a/packages/ra-core/src/form/validation/useUnique.stories.tsx +++ b/packages/ra-core/src/form/validation/useUnique.stories.tsx @@ -18,7 +18,7 @@ import { QueryClient } from '@tanstack/react-query'; import { TestMemoryRouter } from '../../routing'; export default { - title: 'ra-core/form/useUnique', + title: 'ra-core/form/validation/useUnique', }; const Input = props => { From bc48fb5375330ff569e00a504f99bf6031f4b207 Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Thu, 21 Nov 2024 10:12:09 +0100 Subject: [PATCH 10/91] Fix iconPosition prop is passed to DOM elements in Tab and FormTab --- packages/ra-ui-materialui/src/detail/Tab.tsx | 2 ++ packages/ra-ui-materialui/src/form/FormTab.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/ra-ui-materialui/src/detail/Tab.tsx b/packages/ra-ui-materialui/src/detail/Tab.tsx index 20234b545ae..6377d514198 100644 --- a/packages/ra-ui-materialui/src/detail/Tab.tsx +++ b/packages/ra-ui-materialui/src/detail/Tab.tsx @@ -66,6 +66,7 @@ export const Tab = ({ className, divider, icon, + iconPosition, label, record, spacing = 1, @@ -97,6 +98,7 @@ export const Tab = ({ label={tabLabel} value={value} icon={icon} + iconPosition={iconPosition} className={clsx('show-tab', className)} {...(syncWithLocation ? propsForLink : {})} // to avoid TypeScript screams, see https://github.com/mui/material-ui/issues/9106#issuecomment-451270521 {...rest} diff --git a/packages/ra-ui-materialui/src/form/FormTab.tsx b/packages/ra-ui-materialui/src/form/FormTab.tsx index 511c1204ca6..6e4cb326f2c 100644 --- a/packages/ra-ui-materialui/src/form/FormTab.tsx +++ b/packages/ra-ui-materialui/src/form/FormTab.tsx @@ -13,6 +13,7 @@ export const FormTab = (props: FormTabProps) => { count, hidden, icon, + iconPosition, intent, label, onChange, @@ -32,6 +33,7 @@ export const FormTab = (props: FormTabProps) => { count={count} value={value} icon={icon} + iconPosition={iconPosition} className={className} syncWithLocation={syncWithLocation} onChange={onChange} From 500de904dc7600359f4b90912201cbe2a1606a0b Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Thu, 21 Nov 2024 10:16:22 +0100 Subject: [PATCH 11/91] Update changelog for 5.4.0 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 353762a4a23..62b643a18f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 5.4.0 + +* Introduce `` ([#10344](https://github.com/marmelab/react-admin/pull/10344)) ([slax57](https://github.com/slax57)) +* Fix: Remove redundant optimization of cache lookup for `useGetMany`(Aggregate) placeholderData ([#10256](https://github.com/marmelab/react-admin/pull/10256)) ([wattroll](https://github.com/wattroll)) +* Fix `` default translation ([#10368](https://github.com/marmelab/react-admin/pull/10368)) ([fzaninotto](https://github.com/fzaninotto)) +* Fix `useCanAccessResources` cannot have react-query options ([#10362](https://github.com/marmelab/react-admin/pull/10362)) ([djhi](https://github.com/djhi)) +* Fix `FilterListItem` story shows wrong way of resetting a filter ([#10358](https://github.com/marmelab/react-admin/pull/10358)) ([fzaninotto](https://github.com/fzaninotto)) +* [TypeScript] Add missing parameter to `add` function type of `` ([#10359](https://github.com/marmelab/react-admin/pull/10359)) ([Aikain](https://github.com/Aikain)) +* [Demo] Showcase tabs with icons ([#10369](https://github.com/marmelab/react-admin/pull/10369)) ([fzaninotto](https://github.com/fzaninotto)) +* [Chore] Reorganize ra-core/form directory ([#10364](https://github.com/marmelab/react-admin/pull/10364)) ([fzaninotto](https://github.com/fzaninotto)) +* [Chore] Remove `useSafeSetState` hook ([#10341](https://github.com/marmelab/react-admin/pull/10341)) ([geobde](https://github.com/geobde)) +* [Doc] Document `` as a filter ([#10365](https://github.com/marmelab/react-admin/pull/10365)) ([erwanMarmelab](https://github.com/erwanMarmelab)) +* [Doc] Fix `useRegisterMutationMiddleware` documentation ([#10360](https://github.com/marmelab/react-admin/pull/10360)) ([djhi](https://github.com/djhi)) +* [Doc] Improve Access Control for Custom Pages ([#10357](https://github.com/marmelab/react-admin/pull/10357)) ([fzaninotto](https://github.com/fzaninotto)) +* [Doc] Fix `` example usage ([#10356](https://github.com/marmelab/react-admin/pull/10356)) ([fzaninotto](https://github.com/fzaninotto)) +* Build(deps): Bump cross-spawn from 6.0.5 to 6.0.6 ([#10361](https://github.com/marmelab/react-admin/pull/10361)) ([dependabot[bot]](https://github.com/apps/dependabot)) + ## 5.3.4 * Fix `` `ErrorInFetch` story ([#10353](https://github.com/marmelab/react-admin/pull/10353)) ([erwanMarmelab](https://github.com/erwanMarmelab)) From 8c362d57d91944a900431295db552cb2688965ff Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Thu, 21 Nov 2024 10:17:29 +0100 Subject: [PATCH 12/91] Update create-react-admin for 5.4.0 --- packages/create-react-admin/templates/common/package.json | 2 +- .../create-react-admin/templates/ra-data-fakerest/package.json | 2 +- .../templates/ra-data-json-server/package.json | 2 +- .../templates/ra-data-simple-rest/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-react-admin/templates/common/package.json b/packages/create-react-admin/templates/common/package.json index bfa7ed082e2..cbd290a4d03 100644 --- a/packages/create-react-admin/templates/common/package.json +++ b/packages/create-react-admin/templates/common/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "react": "^18.3.0", - "react-admin": "^5.3.0", + "react-admin": "^5.4.0", "react-dom": "^18.3.0" }, "devDependencies": { diff --git a/packages/create-react-admin/templates/ra-data-fakerest/package.json b/packages/create-react-admin/templates/ra-data-fakerest/package.json index 8ac658fc2c3..46296218d0a 100644 --- a/packages/create-react-admin/templates/ra-data-fakerest/package.json +++ b/packages/create-react-admin/templates/ra-data-fakerest/package.json @@ -3,7 +3,7 @@ "test": "vitest" }, "dependencies": { - "ra-data-fakerest": "^5.3.0" + "ra-data-fakerest": "^5.4.0" }, "devDependencies": { "@testing-library/dom": "^10.4.0", diff --git a/packages/create-react-admin/templates/ra-data-json-server/package.json b/packages/create-react-admin/templates/ra-data-json-server/package.json index 33375b3f14d..51b064085f5 100644 --- a/packages/create-react-admin/templates/ra-data-json-server/package.json +++ b/packages/create-react-admin/templates/ra-data-json-server/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "ra-data-json-server": "^5.3.0" + "ra-data-json-server": "^5.4.0" } } diff --git a/packages/create-react-admin/templates/ra-data-simple-rest/package.json b/packages/create-react-admin/templates/ra-data-simple-rest/package.json index 75402b08f13..a133ea6800f 100644 --- a/packages/create-react-admin/templates/ra-data-simple-rest/package.json +++ b/packages/create-react-admin/templates/ra-data-simple-rest/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "ra-data-simple-rest": "^5.3.0" + "ra-data-simple-rest": "^5.4.0" } } From 8a0b04b7dd0507f4ed9310a7e963c3488a48423d Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Thu, 21 Nov 2024 10:17:55 +0100 Subject: [PATCH 13/91] v5.4.0 --- examples/data-generator/package.json | 4 ++-- examples/simple/package.json | 14 +++++++------- lerna.json | 2 +- packages/create-react-admin/package.json | 2 +- packages/ra-core/package.json | 2 +- packages/ra-data-fakerest/package.json | 4 ++-- packages/ra-data-graphql-simple/package.json | 4 ++-- packages/ra-data-graphql/package.json | 2 +- packages/ra-data-json-server/package.json | 4 ++-- packages/ra-data-localforage/package.json | 4 ++-- packages/ra-data-localstorage/package.json | 4 ++-- packages/ra-data-simple-rest/package.json | 4 ++-- packages/ra-i18n-i18next/package.json | 4 ++-- packages/ra-i18n-polyglot/package.json | 4 ++-- packages/ra-input-rich-text/package.json | 10 +++++----- packages/ra-language-english/package.json | 4 ++-- packages/ra-language-french/package.json | 4 ++-- packages/ra-no-code/package.json | 6 +++--- packages/ra-ui-materialui/package.json | 8 ++++---- packages/react-admin/package.json | 10 +++++----- 20 files changed, 50 insertions(+), 50 deletions(-) diff --git a/examples/data-generator/package.json b/examples/data-generator/package.json index af10984fec4..85d7368cec4 100644 --- a/examples/data-generator/package.json +++ b/examples/data-generator/package.json @@ -1,6 +1,6 @@ { "name": "data-generator-retail", - "version": "5.3.4", + "version": "5.4.0", "homepage": "https://github.com/marmelab/react-admin/tree/master/examples/data-generator", "bugs": "https://github.com/marmelab/react-admin/issues", "license": "MIT", @@ -19,7 +19,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "ra-core": "^5.3.4", + "ra-core": "^5.4.0", "rimraf": "^3.0.2", "typescript": "^5.1.3" }, diff --git a/examples/simple/package.json b/examples/simple/package.json index 81bb45964da..f0721b19911 100644 --- a/examples/simple/package.json +++ b/examples/simple/package.json @@ -1,6 +1,6 @@ { "name": "simple", - "version": "5.3.4", + "version": "5.4.0", "private": true, "type": "module", "scripts": { @@ -18,13 +18,13 @@ "@tanstack/react-query-devtools": "^5.21.7", "jsonexport": "^3.2.0", "lodash": "~4.17.5", - "ra-data-fakerest": "^5.3.4", - "ra-i18n-polyglot": "^5.3.4", - "ra-input-rich-text": "^5.3.4", - "ra-language-english": "^5.3.4", - "ra-language-french": "^5.3.4", + "ra-data-fakerest": "^5.4.0", + "ra-i18n-polyglot": "^5.4.0", + "ra-input-rich-text": "^5.4.0", + "ra-language-english": "^5.4.0", + "ra-language-french": "^5.4.0", "react": "^18.3.1", - "react-admin": "^5.3.4", + "react-admin": "^5.4.0", "react-dom": "^18.3.1", "react-hook-form": "^7.53.0", "react-router": "^6.22.0", diff --git a/lerna.json b/lerna.json index 09aa63c89fc..e7a621ac872 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "lerna": "2.5.1", "packages": ["examples/data-generator", "examples/simple", "packages/*"], - "version": "5.3.4" + "version": "5.4.0" } diff --git a/packages/create-react-admin/package.json b/packages/create-react-admin/package.json index 33e21918e50..fc7752fcc69 100644 --- a/packages/create-react-admin/package.json +++ b/packages/create-react-admin/package.json @@ -1,7 +1,7 @@ { "name": "create-react-admin", "description": "A CLI to quickly start a new react-admin project", - "version": "5.3.4", + "version": "5.4.0", "license": "MIT", "bin": "lib/cli.js", "type": "module", diff --git a/packages/ra-core/package.json b/packages/ra-core/package.json index 7bf48a20fac..c44dc7239db 100644 --- a/packages/ra-core/package.json +++ b/packages/ra-core/package.json @@ -1,6 +1,6 @@ { "name": "ra-core", - "version": "5.3.4", + "version": "5.4.0", "description": "Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React", "files": [ "*.md", diff --git a/packages/ra-data-fakerest/package.json b/packages/ra-data-fakerest/package.json index 768f5434c2b..4a16f8b2e83 100644 --- a/packages/ra-data-fakerest/package.json +++ b/packages/ra-data-fakerest/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-fakerest", - "version": "5.3.4", + "version": "5.4.0", "description": "JSON Server data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -43,7 +43,7 @@ "@types/jest": "^29.5.2", "cross-env": "^5.2.0", "expect": "^27.4.6", - "ra-core": "^5.3.4", + "ra-core": "^5.4.0", "rimraf": "^3.0.2", "typescript": "^5.1.3" }, diff --git a/packages/ra-data-graphql-simple/package.json b/packages/ra-data-graphql-simple/package.json index 344ed48a29b..17d12fd14e0 100644 --- a/packages/ra-data-graphql-simple/package.json +++ b/packages/ra-data-graphql-simple/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-graphql-simple", - "version": "5.3.4", + "version": "5.4.0", "description": "A GraphQL simple data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -37,7 +37,7 @@ "graphql-ast-types-browser": "~1.0.2", "lodash": "~4.17.5", "pluralize": "~7.0.0", - "ra-data-graphql": "^5.3.4" + "ra-data-graphql": "^5.4.0" }, "peerDependencies": { "graphql": "^15.6.0", diff --git a/packages/ra-data-graphql/package.json b/packages/ra-data-graphql/package.json index 3d60237c2d9..dcb6948a6c2 100644 --- a/packages/ra-data-graphql/package.json +++ b/packages/ra-data-graphql/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-graphql", - "version": "5.3.4", + "version": "5.4.0", "description": "A GraphQL data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", diff --git a/packages/ra-data-json-server/package.json b/packages/ra-data-json-server/package.json index 06f061ad51e..c2924774040 100644 --- a/packages/ra-data-json-server/package.json +++ b/packages/ra-data-json-server/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-json-server", - "version": "5.3.4", + "version": "5.4.0", "description": "JSON Server data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -26,7 +26,7 @@ }, "dependencies": { "query-string": "^7.1.3", - "ra-core": "^5.3.4" + "ra-core": "^5.4.0" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-data-localforage/package.json b/packages/ra-data-localforage/package.json index fdb4ef4a3f6..bc7ffc89dd8 100644 --- a/packages/ra-data-localforage/package.json +++ b/packages/ra-data-localforage/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-local-forage", - "version": "5.3.4", + "version": "5.4.0", "description": "LocalForage data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -42,7 +42,7 @@ "dependencies": { "localforage": "^1.7.1", "lodash": "~4.17.5", - "ra-data-fakerest": "^5.3.4" + "ra-data-fakerest": "^5.4.0" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-data-localstorage/package.json b/packages/ra-data-localstorage/package.json index 85b29646a90..2dbebd958a1 100644 --- a/packages/ra-data-localstorage/package.json +++ b/packages/ra-data-localstorage/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-local-storage", - "version": "5.3.4", + "version": "5.4.0", "description": "Local storage data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -38,7 +38,7 @@ }, "dependencies": { "lodash": "~4.17.5", - "ra-data-fakerest": "^5.3.4" + "ra-data-fakerest": "^5.4.0" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-data-simple-rest/package.json b/packages/ra-data-simple-rest/package.json index 35e95382b83..b1b47a81859 100644 --- a/packages/ra-data-simple-rest/package.json +++ b/packages/ra-data-simple-rest/package.json @@ -1,6 +1,6 @@ { "name": "ra-data-simple-rest", - "version": "5.3.4", + "version": "5.4.0", "description": "Simple REST data provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "ra-core": "^5.3.4", + "ra-core": "^5.4.0", "rimraf": "^3.0.2", "typescript": "^5.1.3" }, diff --git a/packages/ra-i18n-i18next/package.json b/packages/ra-i18n-i18next/package.json index 067ff14a694..2d2bb607b19 100644 --- a/packages/ra-i18n-i18next/package.json +++ b/packages/ra-i18n-i18next/package.json @@ -1,6 +1,6 @@ { "name": "ra-i18n-i18next", - "version": "5.3.4", + "version": "5.4.0", "description": "i18next i18n provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -26,7 +26,7 @@ }, "dependencies": { "i18next": "^23.5.1", - "ra-core": "^5.3.4", + "ra-core": "^5.4.0", "react-i18next": "^14.1.1" }, "devDependencies": { diff --git a/packages/ra-i18n-polyglot/package.json b/packages/ra-i18n-polyglot/package.json index f1c481761b1..fd7d529f668 100644 --- a/packages/ra-i18n-polyglot/package.json +++ b/packages/ra-i18n-polyglot/package.json @@ -1,6 +1,6 @@ { "name": "ra-i18n-polyglot", - "version": "5.3.4", + "version": "5.4.0", "description": "Polyglot i18n provider for react-admin", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -26,7 +26,7 @@ }, "dependencies": { "node-polyglot": "^2.2.2", - "ra-core": "^5.3.4" + "ra-core": "^5.4.0" }, "devDependencies": { "cross-env": "^5.2.0", diff --git a/packages/ra-input-rich-text/package.json b/packages/ra-input-rich-text/package.json index fd70da7ddcf..ee6818febc3 100644 --- a/packages/ra-input-rich-text/package.json +++ b/packages/ra-input-rich-text/package.json @@ -1,6 +1,6 @@ { "name": "ra-input-rich-text", - "version": "5.3.4", + "version": "5.4.0", "description": " component for react-admin, useful for editing HTML code in admin GUIs.", "author": "Gildas Garcia", "repository": "marmelab/react-admin", @@ -51,10 +51,10 @@ "@testing-library/react": "^15.0.7", "@tiptap/extension-mention": "^2.0.3", "@tiptap/suggestion": "^2.0.3", - "data-generator-retail": "^5.3.4", - "ra-core": "^5.3.4", - "ra-data-fakerest": "^5.3.4", - "ra-ui-materialui": "^5.3.4", + "data-generator-retail": "^5.4.0", + "ra-core": "^5.4.0", + "ra-data-fakerest": "^5.4.0", + "ra-ui-materialui": "^5.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.53.0", diff --git a/packages/ra-language-english/package.json b/packages/ra-language-english/package.json index 4c062c61b84..cbabceb6dbb 100644 --- a/packages/ra-language-english/package.json +++ b/packages/ra-language-english/package.json @@ -1,6 +1,6 @@ { "name": "ra-language-english", - "version": "5.3.4", + "version": "5.4.0", "description": "English messages for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", "repository": { "type": "git", @@ -21,7 +21,7 @@ "watch": "tsc --outDir dist/esm --module es2015 --watch" }, "dependencies": { - "ra-core": "^5.3.4" + "ra-core": "^5.4.0" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/packages/ra-language-french/package.json b/packages/ra-language-french/package.json index 11f7d7521c9..71e85e09e4f 100644 --- a/packages/ra-language-french/package.json +++ b/packages/ra-language-french/package.json @@ -1,6 +1,6 @@ { "name": "ra-language-french", - "version": "5.3.4", + "version": "5.4.0", "description": "French messages for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", "repository": { "type": "git", @@ -21,7 +21,7 @@ "watch": "tsc --outDir dist/esm --module es2015 --watch" }, "dependencies": { - "ra-core": "^5.3.4" + "ra-core": "^5.4.0" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/packages/ra-no-code/package.json b/packages/ra-no-code/package.json index 5d96601e961..8fbcd4d8a43 100644 --- a/packages/ra-no-code/package.json +++ b/packages/ra-no-code/package.json @@ -1,6 +1,6 @@ { "name": "ra-no-code", - "version": "5.3.4", + "version": "5.4.0", "description": "", "files": [ "*.md", @@ -48,8 +48,8 @@ "inflection": "^3.0.0", "lodash": "~4.17.5", "papaparse": "^5.3.0", - "ra-data-local-storage": "^5.3.4", - "react-admin": "^5.3.4", + "ra-data-local-storage": "^5.4.0", + "react-admin": "^5.4.0", "react-dropzone": "^14.2.3" }, "gitHead": "587df4c27bfcec4a756df4f95e5fc14728dfc0d7" diff --git a/packages/ra-ui-materialui/package.json b/packages/ra-ui-materialui/package.json index 366566afa0d..e4ac68beb4b 100644 --- a/packages/ra-ui-materialui/package.json +++ b/packages/ra-ui-materialui/package.json @@ -1,6 +1,6 @@ { "name": "ra-ui-materialui", - "version": "5.3.4", + "version": "5.4.0", "description": "UI Components for react-admin with Material UI", "files": [ "*.md", @@ -39,9 +39,9 @@ "expect": "^27.4.6", "file-api": "~0.10.4", "ignore-styles": "~5.0.1", - "ra-core": "^5.3.4", - "ra-i18n-polyglot": "^5.3.4", - "ra-language-english": "^5.3.4", + "ra-core": "^5.4.0", + "ra-i18n-polyglot": "^5.4.0", + "ra-language-english": "^5.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.53.0", diff --git a/packages/react-admin/package.json b/packages/react-admin/package.json index 06d65fc745a..64530b37404 100644 --- a/packages/react-admin/package.json +++ b/packages/react-admin/package.json @@ -1,6 +1,6 @@ { "name": "react-admin", - "version": "5.3.4", + "version": "5.4.0", "description": "A frontend Framework for building admin applications on top of REST services, using ES6, React and Material UI", "files": [ "*.md", @@ -40,10 +40,10 @@ "@emotion/styled": "^11.3.0", "@mui/icons-material": "^5.15.20", "@mui/material": "^5.15.20", - "ra-core": "^5.3.4", - "ra-i18n-polyglot": "^5.3.4", - "ra-language-english": "^5.3.4", - "ra-ui-materialui": "^5.3.4", + "ra-core": "^5.4.0", + "ra-i18n-polyglot": "^5.4.0", + "ra-language-english": "^5.4.0", + "ra-ui-materialui": "^5.4.0", "react-hook-form": "^7.53.0", "react-router": "^6.22.0", "react-router-dom": "^6.22.0" From 83000fae69cccb155279b3b9c2018761beb1fc15 Mon Sep 17 00:00:00 2001 From: React-Admin CI Date: Thu, 21 Nov 2024 10:18:34 +0100 Subject: [PATCH 14/91] Update yarn.lock for 5.4.0 --- yarn.lock | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index cda1bc22940..175d867fcf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9176,14 +9176,14 @@ __metadata: languageName: node linkType: hard -"data-generator-retail@npm:^5.0.0, data-generator-retail@npm:^5.3.4, data-generator-retail@workspace:examples/data-generator": +"data-generator-retail@npm:^5.0.0, data-generator-retail@npm:^5.4.0, data-generator-retail@workspace:examples/data-generator": version: 0.0.0-use.local resolution: "data-generator-retail@workspace:examples/data-generator" dependencies: cross-env: "npm:^5.2.0" date-fns: "npm:^3.6.0" faker: "npm:^4.1.0" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17307,7 +17307,7 @@ __metadata: languageName: node linkType: hard -"ra-core@npm:^5.3.4, ra-core@workspace:packages/ra-core": +"ra-core@npm:^5.4.0, ra-core@workspace:packages/ra-core": version: 0.0.0-use.local resolution: "ra-core@workspace:packages/ra-core" dependencies: @@ -17352,7 +17352,7 @@ __metadata: languageName: unknown linkType: soft -"ra-data-fakerest@npm:^5.3.0, ra-data-fakerest@npm:^5.3.4, ra-data-fakerest@workspace:packages/ra-data-fakerest": +"ra-data-fakerest@npm:^5.3.0, ra-data-fakerest@npm:^5.4.0, ra-data-fakerest@workspace:packages/ra-data-fakerest": version: 0.0.0-use.local resolution: "ra-data-fakerest@workspace:packages/ra-data-fakerest" dependencies: @@ -17360,7 +17360,7 @@ __metadata: cross-env: "npm:^5.2.0" expect: "npm:^27.4.6" fakerest: "npm:^4.0.1" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17378,7 +17378,7 @@ __metadata: graphql-ast-types-browser: "npm:~1.0.2" lodash: "npm:~4.17.5" pluralize: "npm:~7.0.0" - ra-data-graphql: "npm:^5.3.4" + ra-data-graphql: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17387,7 +17387,7 @@ __metadata: languageName: unknown linkType: soft -"ra-data-graphql@npm:^5.0.0, ra-data-graphql@npm:^5.3.4, ra-data-graphql@workspace:packages/ra-data-graphql": +"ra-data-graphql@npm:^5.0.0, ra-data-graphql@npm:^5.4.0, ra-data-graphql@workspace:packages/ra-data-graphql": version: 0.0.0-use.local resolution: "ra-data-graphql@workspace:packages/ra-data-graphql" dependencies: @@ -17410,7 +17410,7 @@ __metadata: dependencies: cross-env: "npm:^5.2.0" query-string: "npm:^7.1.3" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" languageName: unknown @@ -17423,7 +17423,7 @@ __metadata: cross-env: "npm:^5.2.0" localforage: "npm:^1.7.1" lodash: "npm:~4.17.5" - ra-data-fakerest: "npm:^5.3.4" + ra-data-fakerest: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17431,13 +17431,13 @@ __metadata: languageName: unknown linkType: soft -"ra-data-local-storage@npm:^5.0.0, ra-data-local-storage@npm:^5.3.4, ra-data-local-storage@workspace:packages/ra-data-localstorage": +"ra-data-local-storage@npm:^5.0.0, ra-data-local-storage@npm:^5.4.0, ra-data-local-storage@workspace:packages/ra-data-localstorage": version: 0.0.0-use.local resolution: "ra-data-local-storage@workspace:packages/ra-data-localstorage" dependencies: cross-env: "npm:^5.2.0" lodash: "npm:~4.17.5" - ra-data-fakerest: "npm:^5.3.4" + ra-data-fakerest: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17451,7 +17451,7 @@ __metadata: dependencies: cross-env: "npm:^5.2.0" query-string: "npm:^7.1.3" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" peerDependencies: @@ -17466,26 +17466,26 @@ __metadata: cross-env: "npm:^5.2.0" i18next: "npm:^23.5.1" i18next-resources-to-backend: "npm:^1.1.4" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" react-i18next: "npm:^14.1.1" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" languageName: unknown linkType: soft -"ra-i18n-polyglot@npm:^5.0.0, ra-i18n-polyglot@npm:^5.3.4, ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot": +"ra-i18n-polyglot@npm:^5.0.0, ra-i18n-polyglot@npm:^5.4.0, ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot": version: 0.0.0-use.local resolution: "ra-i18n-polyglot@workspace:packages/ra-i18n-polyglot" dependencies: cross-env: "npm:^5.2.0" node-polyglot: "npm:^2.2.2" - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" languageName: unknown linkType: soft -"ra-input-rich-text@npm:^5.0.0, ra-input-rich-text@npm:^5.3.4, ra-input-rich-text@workspace:packages/ra-input-rich-text": +"ra-input-rich-text@npm:^5.0.0, ra-input-rich-text@npm:^5.4.0, ra-input-rich-text@workspace:packages/ra-input-rich-text": version: 0.0.0-use.local resolution: "ra-input-rich-text@workspace:packages/ra-input-rich-text" dependencies: @@ -17507,10 +17507,10 @@ __metadata: "@tiptap/starter-kit": "npm:^2.0.3" "@tiptap/suggestion": "npm:^2.0.3" clsx: "npm:^2.1.1" - data-generator-retail: "npm:^5.3.4" - ra-core: "npm:^5.3.4" - ra-data-fakerest: "npm:^5.3.4" - ra-ui-materialui: "npm:^5.3.4" + data-generator-retail: "npm:^5.4.0" + ra-core: "npm:^5.4.0" + ra-data-fakerest: "npm:^5.4.0" + ra-ui-materialui: "npm:^5.4.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-hook-form: "npm:^7.53.0" @@ -17527,21 +17527,21 @@ __metadata: languageName: unknown linkType: soft -"ra-language-english@npm:^5.0.0, ra-language-english@npm:^5.3.4, ra-language-english@workspace:packages/ra-language-english": +"ra-language-english@npm:^5.0.0, ra-language-english@npm:^5.4.0, ra-language-english@workspace:packages/ra-language-english": version: 0.0.0-use.local resolution: "ra-language-english@workspace:packages/ra-language-english" dependencies: - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" languageName: unknown linkType: soft -"ra-language-french@npm:^5.0.0, ra-language-french@npm:^5.3.4, ra-language-french@workspace:packages/ra-language-french": +"ra-language-french@npm:^5.0.0, ra-language-french@npm:^5.4.0, ra-language-french@workspace:packages/ra-language-french": version: 0.0.0-use.local resolution: "ra-language-french@workspace:packages/ra-language-french" dependencies: - ra-core: "npm:^5.3.4" + ra-core: "npm:^5.4.0" rimraf: "npm:^3.0.2" typescript: "npm:^5.1.3" languageName: unknown @@ -17560,9 +17560,9 @@ __metadata: inflection: "npm:^3.0.0" lodash: "npm:~4.17.5" papaparse: "npm:^5.3.0" - ra-data-local-storage: "npm:^5.3.4" + ra-data-local-storage: "npm:^5.4.0" react: "npm:^18.3.1" - react-admin: "npm:^5.3.4" + react-admin: "npm:^5.4.0" react-dom: "npm:^18.3.1" react-dropzone: "npm:^14.2.3" react-router: "npm:^6.22.0" @@ -17577,7 +17577,7 @@ __metadata: languageName: unknown linkType: soft -"ra-ui-materialui@npm:^5.3.4, ra-ui-materialui@workspace:packages/ra-ui-materialui": +"ra-ui-materialui@npm:^5.4.0, ra-ui-materialui@workspace:packages/ra-ui-materialui": version: 0.0.0-use.local resolution: "ra-ui-materialui@workspace:packages/ra-ui-materialui" dependencies: @@ -17603,9 +17603,9 @@ __metadata: jsonexport: "npm:^3.2.0" lodash: "npm:~4.17.5" query-string: "npm:^7.1.3" - ra-core: "npm:^5.3.4" - ra-i18n-polyglot: "npm:^5.3.4" - ra-language-english: "npm:^5.3.4" + ra-core: "npm:^5.4.0" + ra-i18n-polyglot: "npm:^5.4.0" + ra-language-english: "npm:^5.4.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-dropzone: "npm:^14.2.3" @@ -17773,7 +17773,7 @@ __metadata: languageName: unknown linkType: soft -"react-admin@npm:^5.0.0, react-admin@npm:^5.3.0, react-admin@npm:^5.3.4, react-admin@workspace:packages/react-admin": +"react-admin@npm:^5.0.0, react-admin@npm:^5.3.0, react-admin@npm:^5.4.0, react-admin@workspace:packages/react-admin": version: 0.0.0-use.local resolution: "react-admin@workspace:packages/react-admin" dependencies: @@ -17783,10 +17783,10 @@ __metadata: "@mui/material": "npm:^5.15.20" cross-env: "npm:^5.2.0" expect: "npm:^27.4.6" - ra-core: "npm:^5.3.4" - ra-i18n-polyglot: "npm:^5.3.4" - ra-language-english: "npm:^5.3.4" - ra-ui-materialui: "npm:^5.3.4" + ra-core: "npm:^5.4.0" + ra-i18n-polyglot: "npm:^5.4.0" + ra-language-english: "npm:^5.4.0" + ra-ui-materialui: "npm:^5.4.0" react-hook-form: "npm:^7.53.0" react-router: "npm:^6.22.0" react-router-dom: "npm:^6.22.0" @@ -19192,13 +19192,13 @@ __metadata: "@vitejs/plugin-react": "npm:^4.2.1" jsonexport: "npm:^3.2.0" lodash: "npm:~4.17.5" - ra-data-fakerest: "npm:^5.3.4" - ra-i18n-polyglot: "npm:^5.3.4" - ra-input-rich-text: "npm:^5.3.4" - ra-language-english: "npm:^5.3.4" - ra-language-french: "npm:^5.3.4" + ra-data-fakerest: "npm:^5.4.0" + ra-i18n-polyglot: "npm:^5.4.0" + ra-input-rich-text: "npm:^5.4.0" + ra-language-english: "npm:^5.4.0" + ra-language-french: "npm:^5.4.0" react: "npm:^18.3.1" - react-admin: "npm:^5.3.4" + react-admin: "npm:^5.4.0" react-dom: "npm:^18.3.1" react-hook-form: "npm:^7.53.0" react-router: "npm:^6.22.0" From a68b3daa1005d6c48ed96ae6daf27fb30609b1e0 Mon Sep 17 00:00:00 2001 From: Sefa Bulak Date: Thu, 21 Nov 2024 17:46:22 +0300 Subject: [PATCH 15/91] docs: fix Supabase link formatting in `DataProviderList.md` Updated the Supabase link format for better consistency by moving "(GraphQL)" inside the clickable link text. --- docs/DataProviderList.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DataProviderList.md b/docs/DataProviderList.md index b59ada0bced..1b28c2ce8b9 100644 --- a/docs/DataProviderList.md +++ b/docs/DataProviderList.md @@ -75,7 +75,7 @@ If you can't find a Data Provider for your backend below, no worries! [Writing a * ![strapi Logo](./img/backend-logos/strapi.png "strapi Logo")**[Strapi v3/v4](https://strapi.io/)**: [nazirov91/ra-strapi-rest](https://github.com/nazirov91/ra-strapi-rest) * ![strapi Logo](./img/backend-logos/strapi.png "strapi Logo")**[Strapi v4](https://strapi.io/)**: [garridorafa/ra-strapi-v4-rest](https://github.com/garridorafa/ra-strapi-v4-rest) * ![supabase Logo](./img/backend-logos/supabase.svg "supabase Logo")**[Supabase](https://supabase.io/)**: [marmelab/ra-supabase](https://github.com/marmelab/ra-supabase/blob/main/packages/ra-supabase/README.md) -* ![graphql Logo](./img/backend-logos/graphql.svg "graphql Logo")**[Supabase](https://supabase.io/) (GraphQL)**: [@groovestack/ra-data-graphql-supabase](https://github.com/maxschridde1494/ra-data-graphql-supabase) +* ![graphql Logo](./img/backend-logos/graphql.svg "graphql Logo")**[Supabase (GraphQL)](https://supabase.io/)**: [@groovestack/ra-data-graphql-supabase](https://github.com/maxschridde1494/ra-data-graphql-supabase) * ![surrealDB Logo](./img/backend-logos/surrealdb.svg "surrealDB Logo")**[SurrealDB](https://surrealdb.com/)**: [djedi23/ra-surrealdb](https://github.com/djedi23/ra-surrealdb) * ![treeql Logo](./img/backend-logos/treeql.png "treeql Logo")**[TreeQL / PHP-CRUD-API](https://treeql.org/)**: [nkappler/ra-data-treeql](https://github.com/nkappler/ra-data-treeql) * ![wooCommerce Logo](./img/backend-logos/wooCommerce.png "wooCommerce Logo")**[WooCommerce REST API](https://woocommerce.github.io/woocommerce-rest-api-docs)**: [zackha/ra-data-woocommerce](https://github.com/zackha/ra-data-woocommerce) From 7b319c451d448fe9db00b76fa7ddcc10d4d6dedd Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 21 Nov 2024 16:43:12 +0100 Subject: [PATCH 16/91] Fix ReferenceManyField executes filter reset filter too often --- .../src/controller/field/useReferenceManyFieldController.ts | 2 +- packages/ra-core/src/controller/list/useList.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts index 06a8bb99e31..817d9f4aa09 100644 --- a/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceManyFieldController.ts @@ -154,7 +154,7 @@ export const useReferenceManyFieldController = < filterRef.current = filter; setFilterValues(filter); } - }); + }, [filter]); const { data, diff --git a/packages/ra-core/src/controller/list/useList.ts b/packages/ra-core/src/controller/list/useList.ts index f4188d5cd1b..2bf8c31cf96 100644 --- a/packages/ra-core/src/controller/list/useList.ts +++ b/packages/ra-core/src/controller/list/useList.ts @@ -168,7 +168,7 @@ export const useList = ( filterRef.current = filter; setFilterValues(filter); } - }); + }, [filter]); // We do all the data processing (filtering, sorting, paginating) client-side useEffect( From 9bdee820b2cf72f0eb1a0428574037223fde79c8 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 21 Nov 2024 17:44:09 +0100 Subject: [PATCH 17/91] [Doc] Update `useUpdate` doc to explain `returnPromise` option --- docs/useUpdate.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/useUpdate.md b/docs/useUpdate.md index c9066c1ee6a..2600ff49d22 100644 --- a/docs/useUpdate.md +++ b/docs/useUpdate.md @@ -110,6 +110,7 @@ const IncreaseLikeButton = () => { - `onError`, - `onSettled`, - `onSuccess`, +- `returnPromise`. ```jsx const notify = useNotify(); @@ -326,6 +327,32 @@ In `optimistic` mutation mode, `onSuccess` executes *before* the `dataProvider.u In `undoable` mutation mode, `onSuccess` executes *before* the `dataProvider.update()` is called. The actual call to the dataProvider is delayed until the update notification hides. If the user clicks the undo button, the `dataProvider.update()` call is never made. The callback receives no argument. +## `returnPromise` + +By default, the `update` callback that `useUpdate` returns is synchronous and returns nothing. To execute a side effect after the mutation has succeeded, you can use the `onSuccess` callback. + +If this is not enough, you can use the `returnPromise` option so that the `update` callback returns a promise that resolves when the mutation has succeeded and rejects when the mutation has failed. + +This can be useful if the server changes the record, and you need the updated data to update another record. + +```jsx +const [update] = useUpdate( + 'posts', + { id: record.id, data: { isPublished: true } }, + { returnPromise: true } +); +const [create] = useCreate('auditLogs'); + +const publishPost = async () => { + try { + const post = await update(); + create('auditLogs', { data: { action: 'publish', recordId: post.id, date: post.updatedAt } }); + } catch (error) { + // handle error + } +}; +``` + ## TypeScript The `useUpdate` hook accepts a generic parameter for the record type and another for the error type: From 54a1be9aaed185fbefff2907e41547ab38b08002 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Fri, 22 Nov 2024 14:49:27 +0100 Subject: [PATCH 18/91] remove useless tip from the doc --- docs/AutocompleteArrayInput.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/AutocompleteArrayInput.md b/docs/AutocompleteArrayInput.md index be79926e89c..005b0d464a1 100644 --- a/docs/AutocompleteArrayInput.md +++ b/docs/AutocompleteArrayInput.md @@ -560,8 +560,6 @@ In that case, set the `translateChoice` prop to `false`. ``` {% endraw %} -**Tip**: Like many other inputs, `` accept a `fullWidth` prop. - **Tip**: To use the `disableCloseOnSelect` prop, you must also set `blurOnSelect={false}`, since this is enabled by default. ## Fetching Choices From a6e1b97b8b2a556bde80d8320ffb5ea87e759a24 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Mon, 25 Nov 2024 10:11:21 +0100 Subject: [PATCH 19/91] [no ci] Add story for the Confirm component --- .../src/layout/Confirm.stories.tsx | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 packages/ra-ui-materialui/src/layout/Confirm.stories.tsx diff --git a/packages/ra-ui-materialui/src/layout/Confirm.stories.tsx b/packages/ra-ui-materialui/src/layout/Confirm.stories.tsx new file mode 100644 index 00000000000..a369cb3137e --- /dev/null +++ b/packages/ra-ui-materialui/src/layout/Confirm.stories.tsx @@ -0,0 +1,45 @@ +import * as React from 'react'; + +import { Confirm } from './Confirm'; + +export default { + title: 'ra-ui-materialui/layout/Confirm', +}; + +export const BackClick = () => { + const [isOpen, setIsOpen] = React.useState(false); + const [isClicked, setIsClicked] = React.useState(false); + + return ( + <> + +
setIsClicked(true)} + style={{ + height: '100vh', + width: '100%', + backgroundColor: 'red', + padding: 10, + }} + > +
Back layer {isClicked ? 'clicked' : 'not Clicked'}
+ setIsOpen(false)} + onClose={() => setIsOpen(false)} + /> +
+ + ); +}; From 9fac8dbd54b4b67001eaf045e470964ed9d83663 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Mon, 25 Nov 2024 10:28:57 +0100 Subject: [PATCH 20/91] [Doc] Add video tutorial to Access Control documentation --- docs/Permissions.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/Permissions.md b/docs/Permissions.md index 98bac633902..e85552efc08 100644 --- a/docs/Permissions.md +++ b/docs/Permissions.md @@ -5,6 +5,8 @@ title: "Authorization" # Authorization + + Once a user is authenticated, your application may need to check if the user has the right to access a specific resource or perform a particular action. React-admin provides two ways to do so: 1. **Access control** relies on `authProvider.canAccess({ resource, action })`, which returns whether the user can access the given resource and action. @@ -12,11 +14,6 @@ Once a user is authenticated, your application may need to check if the user has Depending on your needs, you can implement one or the other or both. We recommend Access Control because it allows you to put the authorization logic in the `authProvider` rather than in the code. - - ## Access Control With Access Control, the `authProvider`is responsible for checking if the user can access a specific resource or perform a particular action. This flexibility allows you to implement various authorization strategies, such as: @@ -27,6 +24,11 @@ With Access Control, the `authProvider`is responsible for checking if the user c Use the `authProvider` to integrate react-admin with popular authorization solutions like Okta, Casbin, Cerbos, and more. + + ### `authProvider.canAccess()` To use Access Control, the `authProvider` must implement a `canAccess` method with the following signature: From 92ff6abbca6d01fcc32b3f3cee0a2c2f50bb2625 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:51:06 +0100 Subject: [PATCH 21/91] Fix access control basename handling --- packages/ra-core/src/auth/CanAccess.spec.tsx | 60 +++++++++++- .../ra-core/src/auth/CanAccess.stories.tsx | 95 ++++++++++++------- packages/ra-core/src/auth/CanAccess.tsx | 10 +- .../src/auth/useRequireAccess.spec.tsx | 51 +++++++++- .../src/auth/useRequireAccess.stories.tsx | 9 +- .../ra-core/src/auth/useRequireAccess.tsx | 12 ++- 6 files changed, 193 insertions(+), 44 deletions(-) diff --git a/packages/ra-core/src/auth/CanAccess.spec.tsx b/packages/ra-core/src/auth/CanAccess.spec.tsx index 3bc48a0a009..ccce8bc4772 100644 --- a/packages/ra-core/src/auth/CanAccess.spec.tsx +++ b/packages/ra-core/src/auth/CanAccess.spec.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { Location } from 'react-router'; import { Basic, CustomLoading, @@ -89,6 +90,63 @@ describe('', () => { resolveCheckAuth(false); await screen.findByText('Not allowed'); }); + it('redirects to the /authentication-error route by default in case of error', async () => { + let rejectCheckAuth; + let location: Location; + const authProvider: AuthProvider = { + login: () => Promise.reject('bad method'), + logout: () => Promise.reject('bad method'), + checkAuth: () => Promise.reject('bad method'), + checkError: () => Promise.reject('bad method'), + getPermissions: () => Promise.reject('bad method'), + canAccess: () => + new Promise((_, reject) => { + rejectCheckAuth = reject; + }), + }; + const { container } = render( + { + location = l; + }} + /> + ); + expect(container.textContent).toEqual(''); + rejectCheckAuth(new Error('failed')); + await waitFor(() => + expect(location.pathname).toEqual('/authentication-error') + ); + }); + it('redirects to the /authentication-error route by default in case of error in an Admin with a basename', async () => { + let rejectCheckAuth; + let location: Location; + const authProvider: AuthProvider = { + login: () => Promise.reject('bad method'), + logout: () => Promise.reject('bad method'), + checkAuth: () => Promise.reject('bad method'), + checkError: () => Promise.reject('bad method'), + getPermissions: () => Promise.reject('bad method'), + canAccess: () => + new Promise((_, reject) => { + rejectCheckAuth = reject; + }), + }; + const { container } = render( + { + location = l; + }} + /> + ); + expect(container.textContent).toEqual(''); + rejectCheckAuth(new Error('failed')); + await waitFor(() => + expect(location.pathname).toEqual('/admin/authentication-error') + ); + }); it('shows the protected content when users are authorized', async () => { let resolveCheckAuth; const authProvider: AuthProvider = { diff --git a/packages/ra-core/src/auth/CanAccess.stories.tsx b/packages/ra-core/src/auth/CanAccess.stories.tsx index b7c9b625828..97d5109407d 100644 --- a/packages/ra-core/src/auth/CanAccess.stories.tsx +++ b/packages/ra-core/src/auth/CanAccess.stories.tsx @@ -1,7 +1,10 @@ import * as React from 'react'; +import { Location } from 'react-router'; +import { QueryClient } from '@tanstack/react-query'; import { AuthProvider } from '../types'; import { CoreAdminContext } from '../core'; import { CanAccess } from './CanAccess'; +import { TestMemoryRouter } from '..'; export default { title: 'ra-core/auth/CanAccess', @@ -19,14 +22,32 @@ const defaultAuthProvider: AuthProvider = { export const Basic = ({ authProvider = defaultAuthProvider, + basename, + locationCallback, }: { authProvider?: AuthProvider; + basename?: string; + locationCallback?: (location: Location) => void; }) => ( - - - protected content - - + + + + protected content + + + ); export const AccessDenied = ({ @@ -34,11 +55,13 @@ export const AccessDenied = ({ }: { authProvider?: AuthProvider; }) => ( - - - protected content - - + + + + protected content + + + ); export const CustomLoading = ({ @@ -46,15 +69,17 @@ export const CustomLoading = ({ }: { authProvider?: AuthProvider; }) => ( - - Please wait...} - > - protected content - - + + + Please wait...} + > + protected content + + + ); export const CustomAccessDenied = ({ @@ -62,21 +87,25 @@ export const CustomAccessDenied = ({ }: { authProvider?: AuthProvider; }) => ( - - Not allowed} - > - protected content - - + + + Not allowed} + > + protected content + + + ); export const NoAuthProvider = () => ( - - - protected content - - + + + + protected content + + + ); diff --git a/packages/ra-core/src/auth/CanAccess.tsx b/packages/ra-core/src/auth/CanAccess.tsx index a504cb4f2a0..c583b3a74e8 100644 --- a/packages/ra-core/src/auth/CanAccess.tsx +++ b/packages/ra-core/src/auth/CanAccess.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; +import { Navigate } from 'react-router'; import { useCanAccess, UseCanAccessOptions } from './useCanAccess'; import { RaRecord } from '../types'; -import { Navigate } from 'react-router'; +import { useBasename } from '../routing'; /** * A component that only displays its children after checking whether users are authorized to access the provided resource and action. @@ -50,4 +51,9 @@ export interface CanAccessProps< error?: React.ReactNode; } -const DEFAULT_ERROR = ; +const CanAccessDefaultError = () => { + const basename = useBasename(); + return ; +}; + +const DEFAULT_ERROR = ; diff --git a/packages/ra-core/src/auth/useRequireAccess.spec.tsx b/packages/ra-core/src/auth/useRequireAccess.spec.tsx index 29aae0ff945..671b91979f6 100644 --- a/packages/ra-core/src/auth/useRequireAccess.spec.tsx +++ b/packages/ra-core/src/auth/useRequireAccess.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import expect from 'expect'; import { waitFor, render, screen } from '@testing-library/react'; - import { QueryClient } from '@tanstack/react-query'; +import { Location } from 'react-router'; import { Basic } from './useRequireAccess.stories'; describe('useRequireAccess', () => { @@ -77,6 +77,55 @@ describe('useRequireAccess', () => { await screen.findByText('Authentication Error'); }); + it('should redirect to /access-denied when users do not have access in an Admin with basename', async () => { + let location: Location; + const authProvider = { + login: () => Promise.reject('bad method'), + logout: () => Promise.reject('bad method'), + checkAuth: () => Promise.reject('bad method'), + checkError: () => Promise.reject('bad method'), + getPermissions: () => Promise.reject('bad method'), + canAccess: () => Promise.resolve(false), + }; + render( + { + location = l; + }} + /> + ); + + await waitFor(() => { + expect(location.pathname).toEqual('/admin/access-denied'); + }); + }); + + it('should redirect to /authentication-error when auth.canAccess call fails in an Admin with basename', async () => { + let location: Location; + const authProvider = { + login: () => Promise.reject('bad method'), + logout: () => Promise.reject('bad method'), + checkAuth: () => Promise.reject('bad method'), + getPermissions: () => Promise.reject('bad method'), + checkError: () => Promise.reject('bad method'), + canAccess: () => Promise.reject('not good'), + }; + render( + { + location = l; + }} + /> + ); + await waitFor(() => { + expect(location.pathname).toEqual('/admin/authentication-error'); + }); + }); + it('should abort the request if the query is canceled', async () => { const abort = jest.fn(); const authProvider = { diff --git a/packages/ra-core/src/auth/useRequireAccess.stories.tsx b/packages/ra-core/src/auth/useRequireAccess.stories.tsx index 15e39f7e522..4f6c88a3bf7 100644 --- a/packages/ra-core/src/auth/useRequireAccess.stories.tsx +++ b/packages/ra-core/src/auth/useRequireAccess.stories.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { QueryClient } from '@tanstack/react-query'; -import { Route, Routes } from 'react-router'; +import { Location, Route, Routes } from 'react-router'; import { AuthProvider } from '../types'; import { CoreAdminContext } from '../core'; import { useRequireAccess, UseRequireAccessResult } from './useRequireAccess'; @@ -50,15 +50,20 @@ const defaultAuthProvider: AuthProvider = { export const Basic = ({ authProvider = defaultAuthProvider, + basename, + locationCallback, queryClient, }: { authProvider?: AuthProvider | null; + basename?: string; + locationCallback?: (l: Location) => void; queryClient?: QueryClient; }) => ( - + { const { canAccess, data, error, ...rest } = useCanAccess(params); const navigate = useNavigate(); + const basename = useBasename(); useEffect(() => { if (rest.isPending) return; if (canAccess === false) { - navigate('/access-denied'); + navigate(`${basename}/access-denied`); } - }, [canAccess, navigate, rest.isPending]); + }, [basename, canAccess, navigate, rest.isPending]); useEffect(() => { if (error) { - navigate('/authentication-error'); + navigate(`${basename}/authentication-error`); } - }, [navigate, error]); + }, [basename, navigate, error]); return rest; }; From b06972b7cfa1ea23330f8ce0a97f993404737fb0 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:41:17 +0100 Subject: [PATCH 22/91] Fix ResourceMenuItem should not render in case of access control error --- .../src/layout/ResourceMenuItem.spec.tsx | 19 +++++++++++++++++++ .../src/layout/ResourceMenuItem.stories.tsx | 18 ++++++++++++------ .../src/layout/ResourceMenuItem.tsx | 10 ++++++++-- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/packages/ra-ui-materialui/src/layout/ResourceMenuItem.spec.tsx b/packages/ra-ui-materialui/src/layout/ResourceMenuItem.spec.tsx index d5434eb9830..476f3f68175 100644 --- a/packages/ra-ui-materialui/src/layout/ResourceMenuItem.spec.tsx +++ b/packages/ra-ui-materialui/src/layout/ResourceMenuItem.spec.tsx @@ -19,6 +19,25 @@ describe('ResourceMenuItem', () => { await screen.findByText('resources.posts.name'); expect(screen.queryByText('resources.users.name')).toBeNull(); }); + it('should not render when authProvider.canAccess throws', async () => { + render( + Promise.resolve(), + canAccess: ({ resource }) => + resource === 'posts' + ? Promise.resolve(true) + : Promise.reject( + new Error('access control error') + ), + } as any + } + /> + ); + await screen.findByText('resources.posts.name'); + expect(screen.queryByText('resources.users.name')).toBeNull(); + }); it('should not render when authProvider.canAccess returns false with a Function as child', async () => { render(); await screen.findByText('resources.posts.name'); diff --git a/packages/ra-ui-materialui/src/layout/ResourceMenuItem.stories.tsx b/packages/ra-ui-materialui/src/layout/ResourceMenuItem.stories.tsx index 897fb0f7947..b7ef6e4755d 100644 --- a/packages/ra-ui-materialui/src/layout/ResourceMenuItem.stories.tsx +++ b/packages/ra-ui-materialui/src/layout/ResourceMenuItem.stories.tsx @@ -1,5 +1,10 @@ import * as React from 'react'; -import { Resource, testDataProvider, TestMemoryRouter } from 'ra-core'; +import { + AuthProvider, + Resource, + testDataProvider, + TestMemoryRouter, +} from 'ra-core'; import { Menu } from './Menu'; import { Layout, LayoutProps } from './Layout'; import { AdminContext } from '../AdminContext'; @@ -100,12 +105,13 @@ export const AccessControlInsideAdminChildFunction = () => ( ); -export const AccessControl = () => ( +export const AccessControl = ({ + authProvider = authProviderForAccessControl, +}: { + authProvider?: AuthProvider; +}) => ( - + The users page

} /> { const resources = useResourceDefinitions(); - const { canAccess, isPending } = useCanAccess({ + const { canAccess, error, isPending } = useCanAccess({ action: 'list', resource: name, }); const getResourceLabel = useGetResourceLabel(); const createPath = useCreatePath(); - if (!resources || !resources[name] || isPending || canAccess === false) + if ( + !resources || + !resources[name] || + isPending || + canAccess === false || + error != null + ) return null; return ( Date: Tue, 26 Nov 2024 11:41:32 +0100 Subject: [PATCH 23/91] Add a story to test access control in a sub path --- packages/react-admin/src/Admin.stories.tsx | 56 ++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/packages/react-admin/src/Admin.stories.tsx b/packages/react-admin/src/Admin.stories.tsx index d12f9b23f99..4600df7db64 100644 --- a/packages/react-admin/src/Admin.stories.tsx +++ b/packages/react-admin/src/Admin.stories.tsx @@ -10,9 +10,9 @@ import { } from 'ra-ui-materialui'; import { Box, Typography, Button } from '@mui/material'; import fakeRestDataProvider from 'ra-data-fakerest'; -import { useQueryClient } from '@tanstack/react-query'; +import { useQueryClient, QueryClient } from '@tanstack/react-query'; -import { Admin } from './Admin'; +import { Admin, AdminProps } from './Admin'; export default { title: 'react-admin/Admin', @@ -122,7 +122,32 @@ const dataProvider = fakeRestDataProvider({ ], }); -export const AccessControl = () => { +export const AccessControl = () => ; +export const AccessControlInSubPath = () => ( + + + +

Main

+
+ Go to admin +
+ + } + /> + + } + /> +
+
+); + +const AccessControlAdmin = ({ AdminProps }: { AdminProps?: AdminProps }) => { const readerPermissions = [ { action: 'list', resource: 'books' }, { action: 'show', resource: 'books' }, @@ -148,6 +173,8 @@ export const AccessControl = () => { { action: 'delete', resource: 'users' }, ]; const [permissions, setPermissions] = React.useState(readerPermissions); + const [triggerAccessControlError, setTriggerAccessControlError] = + React.useState(false); const authProvider: AuthProvider = { // authentication async login() {}, @@ -160,6 +187,9 @@ export const AccessControl = () => { async handleCallback() {}, // for third-party authentication only // authorization (optional) async canAccess({ resource, action }) { + if (triggerAccessControlError) { + throw new Error('Access control error'); + } return permissions.some( p => p.resource === resource && p.action === action ); @@ -225,6 +255,18 @@ export const AccessControl = () => { > View as admin + {children} @@ -235,6 +277,14 @@ export const AccessControl = () => { dataProvider={dataProvider} authProvider={authProvider} layout={CustomLayout} + queryClient={ + new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }) + } + {...AdminProps} > Date: Tue, 26 Nov 2024 15:35:47 +0100 Subject: [PATCH 24/91] Add TextArrayInput to edit arrays of strings --- docs/ArrayInput.md | 1 + docs/Inputs.md | 2 +- docs/Reference.md | 1 + docs/TextArrayInput.md | 110 ++++++ docs/img/TextArrayInput.mp4 | Bin 0 -> 138303 bytes docs/navigation.html | 1 + .../src/input/TextArrayInput.stories.tsx | 322 ++++++++++++++++++ .../src/input/TextArrayInput.tsx | 129 +++++++ packages/ra-ui-materialui/src/input/index.ts | 1 + 9 files changed, 566 insertions(+), 1 deletion(-) create mode 100644 docs/TextArrayInput.md create mode 100644 docs/img/TextArrayInput.mp4 create mode 100644 packages/ra-ui-materialui/src/input/TextArrayInput.stories.tsx create mode 100644 packages/ra-ui-materialui/src/input/TextArrayInput.tsx diff --git a/docs/ArrayInput.md b/docs/ArrayInput.md index 8d048781fb4..1dc23c2596a 100644 --- a/docs/ArrayInput.md +++ b/docs/ArrayInput.md @@ -38,6 +38,7 @@ To edit arrays of data embedded inside a record, `` creates a list o } ``` +**Tip**: If you need to edit an array of *strings*, like a list of email addresses or a list of tags, you should use a [``](./TextArrayInput.md) instead. `` expects a single child, which must be a *form iterator* component. A form iterator is a component rendering a field array (the object returned by react-hook-form's [`useFieldArray`](https://react-hook-form.com/docs/usefieldarray)). For instance, [the `` component](./SimpleFormIterator.md) displays an array of react-admin Inputs in an unordered list (`
    `), one sub-form by list item (`
  • `). It also provides controls for adding and removing a sub-record. diff --git a/docs/Inputs.md b/docs/Inputs.md index 41e87eb5437..30186752cd0 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -79,7 +79,7 @@ React-admin provides a set of Input components, each one designed for a specific | Tree node | `42` | [``](./TreeInput.md) | | Foreign key | `42` | [``](./ReferenceInput.md) | | Array of objects | `[{ item: 'jeans', qty: 3 }, { item: 'shirt', qty: 1 }]` | [``](./ArrayInput.md) | -| Array of Enums | `['foo', 'bar']` | [``](./SelectArrayInput.md), [``](./AutocompleteArrayInput.md), [``](./CheckboxGroupInput.md), [``](./DualListInput.md) | +| Array of Enums | `['foo', 'bar']` | [``](./TextArrayinput.md), [``](./SelectArrayInput.md), [``](./AutocompleteArrayInput.md), [``](./CheckboxGroupInput.md), [``](./DualListInput.md) | | Array of foreign keys | `[42, 43]` | [``](./ReferenceArrayInput.md) | | Translations | `{ en: 'Hello', fr: 'Bonjour' }` | [``](./TranslatableInputs.md) | | Related records | `[{ id: 42, title: 'Hello' }, { id: 43, title: 'World' }]` | [``](./ReferenceManyInput.md), [``](./ReferenceManyToManyInput.md), [``](./ReferenceNodeInput.md), [``](./ReferenceOneInput.md) | diff --git a/docs/Reference.md b/docs/Reference.md index 3983cda09a1..0759ec1b43e 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -188,6 +188,7 @@ title: "Index" * [``](./TabbedForm.md) * [``](./TabbedForm.md#versioning) * [``](./TabbedShowLayout.md) +* [``](./TextArrayInput.md) * [``](./TextField.md) * [``](./TextInput.md) * [``](./TimeInput.md) diff --git a/docs/TextArrayInput.md b/docs/TextArrayInput.md new file mode 100644 index 00000000000..ac8c46ea364 --- /dev/null +++ b/docs/TextArrayInput.md @@ -0,0 +1,110 @@ +--- +layout: default +title: "The TextArrayInput Component" +--- + +# `` + +`` lets you edit an array of strings, like a list of email addresses or a list of tags. It renders as an input where the current values are represented as chips. Users can add or delete new values. + + + + +## Usage + +Use `` to edit an array of strings: + +```jsx +import { Create, SimpleForm, TextArrayInput, TextInput } from 'react-admin'; + +export const EmailCreate = () => ( + + + + + + + +); +``` + +This form will allow users to input multiple email addresses in the `to` field. The resulting email will look like this: + +```jsx +{ + "to": ["jane.smith@example.com", "john.doe@acme.com"], + "subject": "Request for a quote", + "body": "Hi,\n\nI would like to know if you can provide a quote for the following items:\n\n- 100 units of product A\n- 50 units of product B\n- 25 units of product C\n\nBest regards,\n\nJulie\n", + "id": 123, + "date": "2024-11-26T11:37:22.564Z", + "from": "julie.green@example.com", +} +``` + +`` is designed for simple string arrays. For more complex use cases, consider the following alternatives: + +- [``](./SelectArrayInput.md) or [``](./AutocompleteArrayInput.md) if the possible values are limited to a predefined list. +- [``](./ReferenceArrayInput.md) if the possible values are stored in another resource. +- [``](./ArrayInput.md) if the stored value is an array of *objects* instead of an array of strings. + +## Props + +| Prop | Required | Type | Default | Description | +| ------------ | -------- | --------- | ------- | -------------------------------------------------------------------- | +| `options` | Optional | `string[]` | | Optional list of possible values for the input. If provided, the input will suggest these values as the user types. | +| `renderTags` | Optional | `(value, getTagProps) => ReactNode` | | A function to render selected value. | + +`` also accepts the [common input props](./Inputs.md#common-input-props). + +Additional props are passed down to the underlying Material UI [``](https://mui.com/material-ui/react-autocomplete/) component. + +## `options` + +You can make show a list of suggestions to the user by setting the `options` prop: + +```jsx + +``` + +## `renderTags` + +To customize the rendering of the chips, use the `renderTags` prop. This prop is a function that takes two arguments: + +- `value`: The input value (an array of strings) +- `getTagProps`: A props getter for an individual tag. + +```jsx + + value.map((option: string, index: number) => { + const { key, ...tagProps } = getTagProps({ index }); + return ( + + ); + }) + } +/> +``` \ No newline at end of file diff --git a/docs/img/TextArrayInput.mp4 b/docs/img/TextArrayInput.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..06fc4ed5e2ae08a0e02371d2485e350a88ecf397 GIT binary patch literal 138303 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
  • <SimpleFormIterator>
  • <SmartRichTextInput>
  • +
  • <TextArrayInput>
  • <TextInput>
  • <TimeInput>
  • <TranslatableInputs>
  • diff --git a/packages/ra-ui-materialui/src/input/TextArrayInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextArrayInput.stories.tsx new file mode 100644 index 00000000000..389b1deef8d --- /dev/null +++ b/packages/ra-ui-materialui/src/input/TextArrayInput.stories.tsx @@ -0,0 +1,322 @@ +import * as React from 'react'; +import { required, email, Resource, TestMemoryRouter } from 'ra-core'; +import fakeRestDataProvider from 'ra-data-fakerest'; +import polyglotI18nProvider from 'ra-i18n-polyglot'; +import englishMessages from 'ra-language-english'; +import { Chip } from '@mui/material'; + +import { + AdminUI, + AdminContext, + Create, + List, + SimpleList, + SimpleForm, + ShowGuesser, + TextInput, +} from '../'; +import { TextArrayInput } from './TextArrayInput'; +import { FormInspector } from './common'; + +export default { title: 'ra-ui-materialui/input/TextArrayInput' }; + +const Wrapper = ({ + children, + record = { id: 123, to: ['john@example.com', 'albert@target.dev'] }, +}: { + children: React.ReactNode; + record?: any; +}) => ( + + + {children} + + +); + +export const Basic = () => ( + + + + +); + +export const Disabled = () => ( + + + + +); + +export const ReadOnly = () => ( + + + + +); + +export const DefaultValue = () => ( + + + + +); + +export const HelperText = () => ( + + + + + +); + +export const Label = () => ( + + + + + +); + +export const NonFullWidth = () => ( + + + + +); + +export const Margin = () => ( + + + + + +); + +export const Variant = () => ( + + + + + +); + +export const Validate = () => ( + + { + if (value.some(email())) { + return 'Not an array of valid emails'; + } + return undefined; + }} + /> + +); + +export const Required = () => ( + + + + + +); + +export const Options = () => ( + + + +); + +export const RenderTags = () => ( + + + value.map((option: string, index: number) => { + const { key, ...tagProps } = getTagProps({ index }); + return ( + + ); + }) + } + /> + +); + +export const Sx = () => ( + + + +); + +export const ExtraProps = () => ( + + + +); + +export const ValueUndefined = () => ( + + + + +); + +export const ValueNull = () => ( + + + + +); + +export const Parse = () => ( + + v.map(v1 => `${v1}@example.com`)} + /> + + +); + +export const Format = () => ( + + v?.map(v1 => v1.replace('@example.com', ''))} + /> + + +); + +const i18nProvider = polyglotI18nProvider(() => englishMessages, 'en'); + +const dataProvider = fakeRestDataProvider({ + emails: [ + { + id: 123, + date: '2024-11-26T11:37:22.564Z', + from: 'julie.green@example.com', + to: ['john.doe@example.com', 'jane.smith@example.com'], + subject: 'Feedback on your website', + body: `Hi, I found a bug on your website. Here is how to reproduce it: +1. Go to the home page +2. Click on the button +3. See the error + +Best regards, + +Julie +`, + }, + { + id: 124, + date: '2024-11-28T11:49:22.009Z', + from: 'julie.green@example.com', + to: ['grace.harris@example.com'], + subject: 'Request for a quote', + body: `Hi, + +I would like to know if you can provide a quote for the following items: + +- 100 units of product A +- 50 units of product B +- 25 units of product C + +Best regards, + +Julie +`, + }, + ], +}); + +export const FullApp = () => ( + + + + ( + + + `to: ${email.to.join(', ')}` + } + secondaryText="%{subject}" + tertiaryText={email => + new Date(email.date).toLocaleDateString() + } + linkType="show" + /> + + )} + show={ShowGuesser} + create={() => ( + + + + + + + + )} + /> + + + +); diff --git a/packages/ra-ui-materialui/src/input/TextArrayInput.tsx b/packages/ra-ui-materialui/src/input/TextArrayInput.tsx new file mode 100644 index 00000000000..071c473690e --- /dev/null +++ b/packages/ra-ui-materialui/src/input/TextArrayInput.tsx @@ -0,0 +1,129 @@ +import * as React from 'react'; +import clsx from 'clsx'; +import { + Chip, + Autocomplete, + AutocompleteProps, + TextField, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import { useInput, FieldTitle } from 'ra-core'; +import { InputHelperText } from './InputHelperText'; +import { CommonInputProps } from './CommonInputProps'; + +export type TextArrayInputProps = CommonInputProps & + Omit< + AutocompleteProps, + 'options' | 'renderInput' | 'renderTags' | 'multiple' | 'freeSolo' + > & + // allow to override options and renderTags + Partial< + Pick< + AutocompleteProps, + 'options' | 'renderTags' + > + >; + +export const TextArrayInput = ({ + className, + disabled, + format, + helperText, + label, + margin, + parse, + readOnly, + size, + source, + sx, + validate, + variant, + ...props +}: TextArrayInputProps) => { + const { + field, + fieldState: { error, invalid }, + id, + isRequired, + } = useInput({ + disabled, + format, + parse, + readOnly, + source, + validate, + ...props, + }); + + const renderHelperText = helperText !== false || invalid; + + return ( + + value.map((option: string, index: number) => { + const { key, ...tagProps } = getTagProps({ index }); + return ( + + ); + }) + } + renderInput={params => ( + + ) : null + } + helperText={ + renderHelperText ? ( + + ) : null + } + error={invalid} + variant={variant} + margin={margin} + size={size} + /> + )} + sx={sx} + {...field} + value={field.value || emptyArray} // Autocomplete does not accept null or undefined + onChange={(e, newValue: string[]) => field.onChange(newValue)} + {...props} + disabled={disabled || readOnly} + /> + ); +}; + +const emptyArray = []; + +const PREFIX = 'RaTextArrayInput'; + +const StyledAutocomplete = styled( + Autocomplete, + { + name: PREFIX, + overridesResolver: (props, styles) => styles.root, + } +)(({ theme }) => ({ + minWidth: theme.spacing(20), +})); diff --git a/packages/ra-ui-materialui/src/input/index.ts b/packages/ra-ui-materialui/src/input/index.ts index eba17198ff6..52a7f53824e 100644 --- a/packages/ra-ui-materialui/src/input/index.ts +++ b/packages/ra-ui-materialui/src/input/index.ts @@ -24,6 +24,7 @@ export * from './sanitizeInputRestProps'; export * from './SearchInput'; export * from './SelectArrayInput'; export * from './SelectInput'; +export * from './TextArrayInput'; export * from './TextInput'; export * from './TranslatableInputs'; export * from './TranslatableInputsTabContent'; From 76ddad3e8db945ceec53a0b9c903a420718be20a Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:04:07 +0100 Subject: [PATCH 25/91] Introduce SimpleList rowClick --- docs/SimpleList.md | 21 +- .../src/routing/useGetPathForRecord.ts | 5 + .../src/list/SimpleList/SimpleList.spec.tsx | 139 +++--- .../list/SimpleList/SimpleList.stories.tsx | 165 +++++-- .../src/list/SimpleList/SimpleList.tsx | 435 +++++++++++------- .../src/list/datagrid/Datagrid.tsx | 2 +- .../src/list/datagrid/DatagridBody.tsx | 3 +- .../src/list/datagrid/DatagridRow.tsx | 7 +- .../src/list/datagrid/index.ts | 7 +- packages/ra-ui-materialui/src/list/index.ts | 1 + packages/ra-ui-materialui/src/list/types.ts | 7 + 11 files changed, 525 insertions(+), 267 deletions(-) create mode 100644 packages/ra-ui-materialui/src/list/types.ts diff --git a/docs/SimpleList.md b/docs/SimpleList.md index 2bf275370cf..7a4cdbad752 100644 --- a/docs/SimpleList.md +++ b/docs/SimpleList.md @@ -28,7 +28,7 @@ export const PostList = () => ( primaryText={record => record.title} secondaryText={record => `${record.views} views`} tertiaryText={record => new Date(record.published_at).toLocaleDateString()} - linkType={record => record.canEdit ? "edit" : "show"} + rowClick={(id, resource, record) => record.canEdit ? "edit" : "show"} rowSx={record => ({ backgroundColor: record.nb_views >= 500 ? '#efe' : 'white' })} /> @@ -44,7 +44,7 @@ export const PostList = () => ( | `primaryText` | Optional | mixed | record representation | The primary text to display. | | `secondaryText` | Optional | mixed | | The secondary text to display. | | `tertiaryText` | Optional | mixed | | The tertiary text to display. | -| `linkType` | Optional |mixed | `"edit"` | The target of each item click. | +| `rowClick` | Optional |mixed | `"edit"` | The action to trigger when the user clicks on a row. | | `leftAvatar` | Optional | function | | A function returning an `` component to display before the primary text. | | `leftIcon` | Optional | function | | A function returning an `` component to display before the primary text. | | `rightAvatar` | Optional | function | | A function returning an `` component to display after the primary text. | @@ -80,9 +80,9 @@ This prop should be a function returning an `` component. When present, This prop should be a function returning an `` component. When present, the `` renders a `` before the `` -## `linkType` +## `rowClick` -The `` items link to the edition page by default. You can also set the `linkType` prop to `show` directly to link to the `` page instead. +The `` items link to the edition page by default. You can also set the `rowClick` prop to `show` directly to link to the `` page instead. ```jsx import { List, SimpleList } from 'react-admin'; @@ -93,17 +93,18 @@ export const PostList = () => ( primaryText={record => record.title} secondaryText={record => `${record.views} views`} tertiaryText={record => new Date(record.published_at).toLocaleDateString()} - linkType="show" + rowClick="show" /> ); ``` -`linkType` accepts the following values: +`rowClick` accepts the following values: -* `linkType="edit"`: links to the edit page. This is the default behavior. -* `linkType="show"`: links to the show page. -* `linkType={false}`: does not create any link. +* `rowClick="edit"`: links to the edit page. This is the default behavior. +* `rowClick="show"`: links to the show page. +* `rowClick={false}`: does not link to anything. +* `rowClick={(id, resource, record) => path}`: path can be any of the above values ## `primaryText` @@ -254,7 +255,7 @@ export const PostList = () => { primaryText={record => record.title} secondaryText={record => `${record.views} views`} tertiaryText={record => new Date(record.published_at).toLocaleDateString()} - linkType={record => record.canEdit ? "edit" : "show"} + rowClick={(id, resource, record) => record.canEdit ? "edit" : "show"} /> ) : ( diff --git a/packages/ra-core/src/routing/useGetPathForRecord.ts b/packages/ra-core/src/routing/useGetPathForRecord.ts index 7d1fa19d77a..4a34aa559d0 100644 --- a/packages/ra-core/src/routing/useGetPathForRecord.ts +++ b/packages/ra-core/src/routing/useGetPathForRecord.ts @@ -81,6 +81,11 @@ export const useGetPathForRecord = ( useEffect(() => { if (!record) return; + if (link === false) { + setPath(false); + return; + } + // Handle the inferred link type case if (link == null) { // We must check whether the resource has an edit view because if there is no diff --git a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.spec.tsx b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.spec.tsx index 04734497c80..37bb980fa6c 100644 --- a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.spec.tsx +++ b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.spec.tsx @@ -6,13 +6,20 @@ import { waitFor, within, } from '@testing-library/react'; -import { ListContext, ResourceContextProvider } from 'ra-core'; +import { + ListContext, + ResourceContextProvider, + ResourceDefinitionContextProvider, +} from 'ra-core'; +import { Location } from 'react-router'; import { AdminContext } from '../../AdminContext'; import { SimpleList } from './SimpleList'; import { TextField } from '../../field/TextField'; import { + LinkType, NoPrimaryText, + RowClick, Standalone, StandaloneEmpty, } from './SimpleList.stories'; @@ -20,9 +27,20 @@ import { Basic } from '../filter/FilterButton.stories'; const Wrapper = ({ children }: any) => ( - - {children} - + + + {children} + + ); @@ -59,58 +77,24 @@ describe('', () => { }); it.each([ - [ - 'edit', - 'edit', - ['http://localhost/#/posts/1', 'http://localhost/#/posts/2'], - ], - [ - 'show', - 'show', - [ - 'http://localhost/#/posts/1/show', - 'http://localhost/#/posts/2/show', - ], - ], - [ - 'custom', - (record, id) => `/posts/${id}/custom`, - [ - 'http://localhost/#/posts/1/custom', - 'http://localhost/#/posts/2/custom', - ], - ], + ['edit', 'edit', '/books/1'], + ['show', 'show', '/books/1/show'], + ['custom', (record, id) => `/books/${id}/custom`, '/books/1/custom'], ])( - 'should render %s links for each item', - async (_, link, expectedUrls) => { + 'should render %s links for each item with linkType', + async (_, linkType, expectedUrls) => { + let location: Location; render( - { + location = l; }} - > - record.id.toString()} - secondaryText={} - /> - , - { wrapper: Wrapper } + /> ); - + fireEvent.click(await screen.findByText('War and Peace')); await waitFor(() => { - expect(screen.getByText('1').closest('a').href).toEqual( - expectedUrls[0] - ); - expect(screen.getByText('2').closest('a').href).toEqual( - expectedUrls[1] - ); + expect(location?.pathname).toEqual(expectedUrls); }); } ); @@ -143,6 +127,57 @@ describe('', () => { }); }); + it.each([ + ['edit', 'edit', '/books/1'], + ['show', 'show', '/books/1/show'], + ['custom', id => `/books/${id}/custom`, '/books/1/custom'], + ])( + 'should render %s links for each item with rowClick', + async (_, rowClick, expectedUrls) => { + let location: Location; + render( + { + location = l; + }} + /> + ); + fireEvent.click(await screen.findByText('War and Peace')); + await waitFor(() => { + expect(location?.pathname).toEqual(expectedUrls); + }); + } + ); + + it('should not render links if rowClick is false', async () => { + render( + + record.id.toString()} + secondaryText={} + /> + , + { wrapper: Wrapper } + ); + + await waitFor(() => { + expect(screen.getByText('1').closest('a')).toBeNull(); + expect(screen.getByText('2').closest('a')).toBeNull(); + }); + }); + it('should display a message when there is no result', () => { render( ', () => { }); it('should display a message when there is no result', async () => { render(); - await screen.findByText('No results found.'); + await screen.findByText('ra.navigation.no_results'); }); }); }); diff --git a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.stories.tsx b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.stories.tsx index 91386aae39e..2ff72ddad5a 100644 --- a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.stories.tsx +++ b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.stories.tsx @@ -7,16 +7,19 @@ import { TestMemoryRouter, ResourceContextProvider, ResourceProps, + ResourceDefinitionContextProvider, } from 'ra-core'; import defaultMessages from 'ra-language-english'; import polyglotI18nProvider from 'ra-i18n-polyglot'; -import { Box, FormControlLabel, FormGroup, Switch } from '@mui/material'; +import { Alert, Box, FormControlLabel, FormGroup, Switch } from '@mui/material'; +import { Location } from 'react-router'; -import { SimpleList } from './SimpleList'; +import { FunctionLinkType, SimpleList } from './SimpleList'; import { AdminUI } from '../../AdminUI'; import { AdminContext, AdminContextProps } from '../../AdminContext'; import { EditGuesser } from '../../detail'; import { List, ListProps } from '../List'; +import { RowClickFunction } from '../types'; export default { title: 'ra-ui-materialui/list/SimpleList' }; @@ -105,17 +108,121 @@ const data = { export const Basic = () => ( - - record.title} - secondaryText={record => record.author} - tertiaryText={record => record.year} - /> - + + + record.title} + secondaryText={record => record.author} + tertiaryText={record => record.year} + /> + + ); +export const LinkType = ({ + linkType, + locationCallback, +}: { + linkType: string | FunctionLinkType | false; + locationCallback?: (l: Location) => void; +}) => ( + + + + + Inferred should target edit + record.title} + secondaryText={record => record.author} + tertiaryText={record => record.year} + linkType={linkType} + /> + + + + +); + +LinkType.args = { + linkType: 'edit', +}; +LinkType.argTypes = { + linkType: { + options: ['inferred', 'edit', 'show', 'no-link', 'function'], + mapping: { + inferred: undefined, + show: 'show', + edit: 'edit', + 'no-link': false, + function: (record, id) => alert(`Clicked on ${id}`), + }, + control: { type: 'select' }, + }, +}; + +export const RowClick = ({ + locationCallback, + rowClick, +}: { + locationCallback?: (l: Location) => void; + rowClick: string | RowClickFunction | false; +}) => ( + + + + + Inferred should target edit + record.title} + secondaryText={record => record.author} + tertiaryText={record => record.year} + rowClick={rowClick} + /> + + + + +); + +RowClick.args = { + rowClick: 'edit', +}; +RowClick.argTypes = { + rowClick: { + options: ['inferred', 'edit', 'show', 'no-link', 'function'], + mapping: { + inferred: undefined, + show: 'show', + edit: 'edit', + 'no-link': false, + function: id => alert(`Clicked on ${id}`), + }, + control: { type: 'select' }, + }, +}; + const myDataProvider = fakeRestDataProvider(data); const Wrapper = ({ @@ -289,26 +396,32 @@ export const FullAppInError = () => ( export const Standalone = () => ( - record.title} - secondaryText={record => record.author} - tertiaryText={record => record.year} - linkType={false} - /> + + + record.title} + secondaryText={record => record.author} + tertiaryText={record => record.year} + linkType={false} + /> + + ); export const StandaloneEmpty = () => ( - - - data={[]} - primaryText={record => record.title} - secondaryText={record => record.author} - tertiaryText={record => record.year} - linkType={false} - /> - + + + + data={[]} + primaryText={record => record.title} + secondaryText={record => record.author} + tertiaryText={record => record.year} + linkType={false} + /> + + ); diff --git a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx index eb2fe10364f..165a3afeef5 100644 --- a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx +++ b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx @@ -1,11 +1,7 @@ -import * as React from 'react'; -import { styled } from '@mui/material/styles'; import type { SxProps } from '@mui/material'; -import { isValidElement, ReactNode, ReactElement } from 'react'; import { Avatar, List, - ListProps, ListItem, ListItemAvatar, ListItemButton, @@ -13,22 +9,31 @@ import { ListItemProps, ListItemSecondaryAction, ListItemText, + ListProps, } from '@mui/material'; -import { Link } from 'react-router-dom'; +import { styled } from '@mui/material/styles'; import { Identifier, + LinkToType, RaRecord, RecordContextProvider, sanitizeListRestProps, + useEvent, + useGetPathForRecord, + useGetPathForRecordCallback, + useGetRecordRepresentation, useListContextWithProps, + useRecordContext, useResourceContext, - useGetRecordRepresentation, - useCreatePath, useTranslate, } from 'ra-core'; +import * as React from 'react'; +import { isValidElement, ReactElement, ReactNode } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; -import { SimpleListLoading } from './SimpleListLoading'; import { ListNoResults } from '../ListNoResults'; +import { SimpleListLoading } from './SimpleListLoading'; +import { RowClickFunction } from '../types'; /** * The component renders a list of records as a Material UI . @@ -44,7 +49,8 @@ import { ListNoResults } from '../ListNoResults'; * - leftIcon: same * - rightAvatar: same * - rightIcon: same - * - linkType: 'edit' or 'show', or a function returning 'edit' or 'show' based on the record + * - linkType: deprecated 'edit' or 'show', or a function returning 'edit' or 'show' based on the record + * - rowClick: The action to trigger when the user clicks on a row. * - rowStyle: function returning a style object based on (record, index) * - rowSx: function returning a sx object based on (record, index) * @@ -74,21 +80,20 @@ export const SimpleList = ( hasBulkActions, leftAvatar, leftIcon, - linkType = 'edit', + linkType, + rowClick, primaryText, rightAvatar, rightIcon, secondaryText, tertiaryText, + ref, rowSx, rowStyle, ...rest } = props; const { data, isPending, total } = useListContextWithProps(props); - const resource = useResourceContext(props); - const getRecordRepresentation = useGetRecordRepresentation(resource); - const translate = useTranslate(); if (isPending === true) { return ( @@ -102,21 +107,6 @@ export const SimpleList = ( ); } - const renderAvatar = ( - record: RecordType, - avatarCallback: FunctionToElement - ) => { - const avatarValue = avatarCallback(record, record.id); - if ( - typeof avatarValue === 'string' && - (avatarValue.startsWith('http') || avatarValue.startsWith('data:')) - ) { - return ; - } else { - return {avatarValue}; - } - }; - if (data == null || data.length === 0 || total === 0) { if (empty) { return empty; @@ -129,114 +119,21 @@ export const SimpleList = ( {data.map((record, rowIndex) => ( - - - {leftIcon && ( - - {leftIcon(record, record.id)} - - )} - {leftAvatar && ( - - {renderAvatar(record, leftAvatar)} - - )} - - {primaryText - ? typeof primaryText === 'string' - ? translate(primaryText, { - ...record, - _: primaryText, - }) - : isValidElement(primaryText) - ? primaryText - : // @ts-ignore - primaryText( - record, - record.id - ) - : getRecordRepresentation(record)} - - {!!tertiaryText && - (isValidElement(tertiaryText) ? ( - tertiaryText - ) : ( - - {typeof tertiaryText === - 'string' - ? translate( - tertiaryText, - { - ...record, - _: tertiaryText, - } - ) - : isValidElement( - tertiaryText - ) - ? tertiaryText - : // @ts-ignore - tertiaryText( - record, - record.id - )} - - ))} - - } - secondary={ - !!secondaryText && - (typeof secondaryText === 'string' - ? translate(secondaryText, { - ...record, - _: secondaryText, - }) - : isValidElement(secondaryText) - ? secondaryText - : // @ts-ignore - secondaryText(record, record.id)) - } - /> - {(rightAvatar || rightIcon) && ( - - {rightAvatar && ( - - {renderAvatar(record, rightAvatar)} - - )} - {rightIcon && ( - - {rightIcon(record, record.id)} - - )} - - )} - - + ))} @@ -248,21 +145,45 @@ export type FunctionToElement = ( id: Identifier ) => ReactNode; -export interface SimpleListProps - extends Omit { - className?: string; - empty?: ReactElement; - hasBulkActions?: boolean; +interface SimpleListBaseProps { leftAvatar?: FunctionToElement; leftIcon?: FunctionToElement; primaryText?: FunctionToElement | ReactElement | string; + /** + * @deprecated use rowClick instead + */ linkType?: string | FunctionLinkType | false; + + /** + * The action to trigger when the user clicks on a row. + * + * @see https://marmelab.com/react-admin/Datagrid.html#rowclick + * @example + * import { List, Datagrid } from 'react-admin'; + * + * export const PostList = () => ( + * + * + * ... + * + + * + * ); + */ + rowClick?: string | RowClickFunction | false; rightAvatar?: FunctionToElement; rightIcon?: FunctionToElement; secondaryText?: FunctionToElement | ReactElement | string; tertiaryText?: FunctionToElement | ReactElement | string; rowSx?: (record: RecordType, index: number) => SxProps; rowStyle?: (record: RecordType, index: number) => any; +} +export interface SimpleListProps + extends SimpleListBaseProps, + Omit { + className?: string; + empty?: ReactElement; + hasBulkActions?: boolean; // can be injected when using the component without context resource?: string; data?: RecordType[]; @@ -272,41 +193,225 @@ export interface SimpleListProps total?: number; } -const LinkOrNot = ( - props: LinkOrNotProps & Omit +const SimpleListItem = ( + props: SimpleListItemProps ) => { - const { - classes: classesOverride, - linkType, - resource, - id, - children, - record, - ...rest - } = props; - const createPath = useCreatePath(); - const type = - typeof linkType === 'function' ? linkType(record, id) : linkType; + const { linkType, rowClick, rowIndex, rowSx, rowStyle } = props; + const resource = useResourceContext(props); + const record = useRecordContext(props); + const navigate = useNavigate(); + // If we don't have a function to get the path, we can compute the path immediately and set the href + // on the Link correctly without onClick (better for accessibility) + const isFunctionLink = + typeof linkType === 'function' || typeof rowClick === 'function'; + const pathForRecord = useGetPathForRecord({ + link: isFunctionLink ? false : linkType ?? rowClick, + }); + const getPathForRecord = useGetPathForRecordCallback(); + const handleClick = useEvent( + async (event: React.MouseEvent) => { + // No need to handle non function linkType or rowClick + if (!isFunctionLink) return; + if (!record) return; + event.persist(); - if (type === false) { - return {children}; + let link: LinkToType = + typeof linkType === 'function' + ? linkType(record, record.id) + : typeof rowClick === 'function' + ? (record, resource) => + rowClick(record.id, resource, record) + : false; + + const path = await getPathForRecord({ + record, + resource, + link, + }); + if (path === false || path == null) { + return; + } + navigate(path); + } + ); + + if (!record) return null; + + if (isFunctionLink) { + return ( + + {/* @ts-ignore */} + + + + + ); } + + if (pathForRecord) { + return ( + + + + + + ); + } + return ( - // @ts-ignore - - {children} - + + ); }; +const SimpleListItemContent = ( + props: SimpleListItemProps +) => { + const { + leftAvatar, + leftIcon, + primaryText, + rightAvatar, + rightIcon, + secondaryText, + tertiaryText, + } = props; + const resource = useResourceContext(props); + const record = useRecordContext(props); + const getRecordRepresentation = useGetRecordRepresentation(resource); + const translate = useTranslate(); + + const renderAvatar = ( + record: RecordType, + avatarCallback: FunctionToElement + ) => { + const avatarValue = avatarCallback(record, record.id); + if ( + typeof avatarValue === 'string' && + (avatarValue.startsWith('http') || avatarValue.startsWith('data:')) + ) { + return ; + } else { + return {avatarValue}; + } + }; + + if (!record) return null; + + return ( + <> + {leftIcon && ( + {leftIcon(record, record.id)} + )} + {leftAvatar && ( + + {renderAvatar(record, leftAvatar)} + + )} + + {primaryText + ? typeof primaryText === 'string' + ? translate(primaryText, { + ...record, + _: primaryText, + }) + : isValidElement(primaryText) + ? primaryText + : // @ts-ignore + primaryText(record, record.id) + : getRecordRepresentation(record)} + + {!!tertiaryText && + (isValidElement(tertiaryText) ? ( + tertiaryText + ) : ( + + {typeof tertiaryText === 'string' + ? translate(tertiaryText, { + ...record, + _: tertiaryText, + }) + : isValidElement(tertiaryText) + ? tertiaryText + : // @ts-ignore + tertiaryText(record, record.id)} + + ))} + + } + secondary={ + !!secondaryText && + (typeof secondaryText === 'string' + ? translate(secondaryText, { + ...record, + _: secondaryText, + }) + : isValidElement(secondaryText) + ? secondaryText + : // @ts-ignore + secondaryText(record, record.id)) + } + /> + {(rightAvatar || rightIcon) && ( + + {rightAvatar && ( + {renderAvatar(record, rightAvatar)} + )} + {rightIcon && ( + + {rightIcon(record, record.id)} + + )} + + )} + + ); +}; + +interface SimpleListItemProps + extends SimpleListBaseProps, + Omit { + rowIndex: number; +} + export type FunctionLinkType = (record: RaRecord, id: Identifier) => string; export interface LinkOrNotProps { - linkType: string | FunctionLinkType | false; + // @deprecated: use rowClick instead + linkType?: string | FunctionLinkType | false; + rowClick?: string | RowClickFunction | false; resource?: string; id: Identifier; record: RaRecord; diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx index 9a373ad9ba6..48ed65064c7 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.tsx @@ -29,7 +29,7 @@ import difference from 'lodash/difference'; import { DatagridHeader } from './DatagridHeader'; import DatagridLoading from './DatagridLoading'; import DatagridBody, { PureDatagridBody } from './DatagridBody'; -import { RowClickFunction } from './DatagridRow'; +import { RowClickFunction } from '../types'; import DatagridContextProvider from './DatagridContextProvider'; import { DatagridClasses, DatagridRoot } from './useDatagridStyles'; import { BulkActionsToolbar } from '../BulkActionsToolbar'; diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridBody.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridBody.tsx index 84c68e6f020..1504d05c348 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/DatagridBody.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridBody.tsx @@ -4,8 +4,9 @@ import { SxProps, TableBody, TableBodyProps } from '@mui/material'; import clsx from 'clsx'; import { Identifier, RaRecord, RecordContextProvider } from 'ra-core'; +import { RowClickFunction } from '../types'; import { DatagridClasses } from './useDatagridStyles'; -import DatagridRow, { PureDatagridRow, RowClickFunction } from './DatagridRow'; +import DatagridRow, { PureDatagridRow } from './DatagridRow'; const DatagridBody: React.ForwardRefExoticComponent< Omit & diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.tsx index 1197027ed18..dac125aad37 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.tsx +++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.tsx @@ -27,6 +27,7 @@ import DatagridCell from './DatagridCell'; import ExpandRowButton from './ExpandRowButton'; import { DatagridClasses } from './useDatagridStyles'; import { useDatagridContext } from './useDatagridContext'; +import { RowClickFunction } from '../types'; const computeNbColumns = (expand, children, hasBulkActions) => expand @@ -265,12 +266,6 @@ export interface DatagridRowProps selectable?: boolean; } -export type RowClickFunction = ( - id: Identifier, - resource: string, - record: RaRecord -) => string | false | Promise; - const areEqual = (prevProps, nextProps) => { const { children: _1, expand: _2, ...prevPropsWithoutChildren } = prevProps; const { children: _3, expand: _4, ...nextPropsWithoutChildren } = nextProps; diff --git a/packages/ra-ui-materialui/src/list/datagrid/index.ts b/packages/ra-ui-materialui/src/list/datagrid/index.ts index 6c343b05785..4691d44d4ed 100644 --- a/packages/ra-ui-materialui/src/list/datagrid/index.ts +++ b/packages/ra-ui-materialui/src/list/datagrid/index.ts @@ -8,11 +8,7 @@ import DatagridHeaderCell, { DatagridHeaderCellProps, } from './DatagridHeaderCell'; import DatagridLoading, { DatagridLoadingProps } from './DatagridLoading'; -import DatagridRow, { - DatagridRowProps, - PureDatagridRow, - RowClickFunction, -} from './DatagridRow'; +import DatagridRow, { DatagridRowProps, PureDatagridRow } from './DatagridRow'; import ExpandRowButton, { ExpandRowButtonProps } from './ExpandRowButton'; export * from './Datagrid'; @@ -43,5 +39,4 @@ export type { DatagridLoadingProps, DatagridRowProps, ExpandRowButtonProps, - RowClickFunction, }; diff --git a/packages/ra-ui-materialui/src/list/index.ts b/packages/ra-ui-materialui/src/list/index.ts index 4f66d57ec52..3b826932002 100644 --- a/packages/ra-ui-materialui/src/list/index.ts +++ b/packages/ra-ui-materialui/src/list/index.ts @@ -16,3 +16,4 @@ export * from './pagination'; export * from './Placeholder'; export * from './SimpleList'; export * from './SingleFieldList'; +export * from './types'; diff --git a/packages/ra-ui-materialui/src/list/types.ts b/packages/ra-ui-materialui/src/list/types.ts new file mode 100644 index 00000000000..73b472b17fa --- /dev/null +++ b/packages/ra-ui-materialui/src/list/types.ts @@ -0,0 +1,7 @@ +import { Identifier, RaRecord } from 'ra-core'; + +export type RowClickFunction = ( + id: Identifier, + resource: string, + record: RecordType +) => string | false | Promise; From ffbac39d867a9fdf7043b563e9522d73f6d64eab Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:26:56 +0100 Subject: [PATCH 26/91] Extract SimpleListItem --- .../src/list/SimpleList/SimpleList.tsx | 196 ++---------------- .../src/list/SimpleList/SimpleListItem.tsx | 164 +++++++++++++++ 2 files changed, 183 insertions(+), 177 deletions(-) create mode 100644 packages/ra-ui-materialui/src/list/SimpleList/SimpleListItem.tsx diff --git a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx index 165a3afeef5..76efa55943c 100644 --- a/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx +++ b/packages/ra-ui-materialui/src/list/SimpleList/SimpleList.tsx @@ -1,26 +1,17 @@ -import type { SxProps } from '@mui/material'; import { Avatar, List, - ListItem, ListItemAvatar, - ListItemButton, ListItemIcon, - ListItemProps, ListItemSecondaryAction, ListItemText, ListProps, } from '@mui/material'; import { styled } from '@mui/material/styles'; import { - Identifier, - LinkToType, RaRecord, RecordContextProvider, sanitizeListRestProps, - useEvent, - useGetPathForRecord, - useGetPathForRecordCallback, useGetRecordRepresentation, useListContextWithProps, useRecordContext, @@ -28,12 +19,16 @@ import { useTranslate, } from 'ra-core'; import * as React from 'react'; -import { isValidElement, ReactElement, ReactNode } from 'react'; -import { Link, useNavigate } from 'react-router-dom'; +import { isValidElement, ReactElement } from 'react'; import { ListNoResults } from '../ListNoResults'; import { SimpleListLoading } from './SimpleListLoading'; -import { RowClickFunction } from '../types'; +import { + FunctionToElement, + SimpleListBaseProps, + SimpleListItem, + SimpleListItemProps, +} from './SimpleListItem'; /** * The component renders a list of records as a Material UI . @@ -122,62 +117,28 @@ export const SimpleList = ( + > + + ))} ); }; -export type FunctionToElement = ( - record: RecordType, - id: Identifier -) => ReactNode; - -interface SimpleListBaseProps { - leftAvatar?: FunctionToElement; - leftIcon?: FunctionToElement; - primaryText?: FunctionToElement | ReactElement | string; - /** - * @deprecated use rowClick instead - */ - linkType?: string | FunctionLinkType | false; - - /** - * The action to trigger when the user clicks on a row. - * - * @see https://marmelab.com/react-admin/Datagrid.html#rowclick - * @example - * import { List, Datagrid } from 'react-admin'; - * - * export const PostList = () => ( - * - * - * ... - * - - * - * ); - */ - rowClick?: string | RowClickFunction | false; - rightAvatar?: FunctionToElement; - rightIcon?: FunctionToElement; - secondaryText?: FunctionToElement | ReactElement | string; - tertiaryText?: FunctionToElement | ReactElement | string; - rowSx?: (record: RecordType, index: number) => SxProps; - rowStyle?: (record: RecordType, index: number) => any; -} export interface SimpleListProps extends SimpleListBaseProps, Omit { @@ -193,107 +154,6 @@ export interface SimpleListProps total?: number; } -const SimpleListItem = ( - props: SimpleListItemProps -) => { - const { linkType, rowClick, rowIndex, rowSx, rowStyle } = props; - const resource = useResourceContext(props); - const record = useRecordContext(props); - const navigate = useNavigate(); - // If we don't have a function to get the path, we can compute the path immediately and set the href - // on the Link correctly without onClick (better for accessibility) - const isFunctionLink = - typeof linkType === 'function' || typeof rowClick === 'function'; - const pathForRecord = useGetPathForRecord({ - link: isFunctionLink ? false : linkType ?? rowClick, - }); - const getPathForRecord = useGetPathForRecordCallback(); - const handleClick = useEvent( - async (event: React.MouseEvent) => { - // No need to handle non function linkType or rowClick - if (!isFunctionLink) return; - if (!record) return; - event.persist(); - - let link: LinkToType = - typeof linkType === 'function' - ? linkType(record, record.id) - : typeof rowClick === 'function' - ? (record, resource) => - rowClick(record.id, resource, record) - : false; - - const path = await getPathForRecord({ - record, - resource, - link, - }); - if (path === false || path == null) { - return; - } - navigate(path); - } - ); - - if (!record) return null; - - if (isFunctionLink) { - return ( - - {/* @ts-ignore */} - - - - - ); - } - - if (pathForRecord) { - return ( - - - - - - ); - } - - return ( - - - - ); -}; - const SimpleListItemContent = ( props: SimpleListItemProps ) => { @@ -400,24 +260,6 @@ const SimpleListItemContent = ( ); }; -interface SimpleListItemProps - extends SimpleListBaseProps, - Omit { - rowIndex: number; -} - -export type FunctionLinkType = (record: RaRecord, id: Identifier) => string; - -export interface LinkOrNotProps { - // @deprecated: use rowClick instead - linkType?: string | FunctionLinkType | false; - rowClick?: string | RowClickFunction | false; - resource?: string; - id: Identifier; - record: RaRecord; - children: ReactNode; -} - const PREFIX = 'RaSimpleList'; export const SimpleListClasses = { diff --git a/packages/ra-ui-materialui/src/list/SimpleList/SimpleListItem.tsx b/packages/ra-ui-materialui/src/list/SimpleList/SimpleListItem.tsx new file mode 100644 index 00000000000..a05ffe65be9 --- /dev/null +++ b/packages/ra-ui-materialui/src/list/SimpleList/SimpleListItem.tsx @@ -0,0 +1,164 @@ +import * as React from 'react'; +import { ReactElement, ReactNode } from 'react'; +import type { SxProps } from '@mui/material'; +import { ListItem, ListItemButton, ListItemProps } from '@mui/material'; +import { + Identifier, + LinkToType, + RaRecord, + useEvent, + useGetPathForRecord, + useGetPathForRecordCallback, + useRecordContext, + useResourceContext, +} from 'ra-core'; +import { Link, useNavigate } from 'react-router-dom'; +import { RowClickFunction } from '../types'; + +export const SimpleListItem = ( + props: SimpleListItemProps +) => { + const { children, linkType, rowClick, rowIndex, rowSx, rowStyle } = props; + const resource = useResourceContext(props); + const record = useRecordContext(props); + const navigate = useNavigate(); + // If we don't have a function to get the path, we can compute the path immediately and set the href + // on the Link correctly without onClick (better for accessibility) + const isFunctionLink = + typeof linkType === 'function' || typeof rowClick === 'function'; + const pathForRecord = useGetPathForRecord({ + link: isFunctionLink ? false : linkType ?? rowClick, + }); + const getPathForRecord = useGetPathForRecordCallback(); + const handleClick = useEvent( + async (event: React.MouseEvent) => { + // No need to handle non function linkType or rowClick + if (!isFunctionLink) return; + if (!record) return; + event.persist(); + + let link: LinkToType = + typeof linkType === 'function' + ? linkType(record, record.id) + : typeof rowClick === 'function' + ? (record, resource) => + rowClick(record.id, resource, record) + : false; + + const path = await getPathForRecord({ + record, + resource, + link, + }); + if (path === false || path == null) { + return; + } + navigate(path); + } + ); + + if (!record) return null; + + if (isFunctionLink) { + return ( + + {/* @ts-ignore */} + + {children} + + + ); + } + + if (pathForRecord) { + return ( + + + {children} + + + ); + } + + return ( + + {children} + + ); +}; + +export type FunctionToElement = ( + record: RecordType, + id: Identifier +) => ReactNode; + +export type FunctionLinkType = (record: RaRecord, id: Identifier) => string; + +export interface SimpleListBaseProps { + leftAvatar?: FunctionToElement; + leftIcon?: FunctionToElement; + primaryText?: FunctionToElement | ReactElement | string; + /** + * @deprecated use rowClick instead + */ + linkType?: string | FunctionLinkType | false; + + /** + * The action to trigger when the user clicks on a row. + * + * @see https://marmelab.com/react-admin/Datagrid.html#rowclick + * @example + * import { List, Datagrid } from 'react-admin'; + * + * export const PostList = () => ( + * + * + * ... + * + + * + * ); + */ + rowClick?: string | RowClickFunction | false; + rightAvatar?: FunctionToElement; + rightIcon?: FunctionToElement; + secondaryText?: FunctionToElement | ReactElement | string; + tertiaryText?: FunctionToElement | ReactElement | string; + rowSx?: (record: RecordType, index: number) => SxProps; + rowStyle?: (record: RecordType, index: number) => any; +} + +export interface SimpleListItemProps + extends SimpleListBaseProps, + Omit { + rowIndex: number; +} From f08887cf9092f4d75be0227b19ada483b31a431b Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Wed, 27 Nov 2024 15:41:29 +0100 Subject: [PATCH 27/91] Add a story when `TextInput` trigger a server error --- .../src/input/TextInput.stories.tsx | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index 9d1dd1fc0d6..eb22227101b 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { required } from 'ra-core'; +import { required, Resource, useNotify } from 'ra-core'; import { useFormState, useFormContext } from 'react-hook-form'; import { TextInput } from './TextInput'; @@ -9,6 +9,8 @@ import { Edit } from '../detail'; import { SimpleForm, Toolbar } from '../form'; import { SaveButton } from '../button'; import { FormInspector } from './common'; +import { Admin } from 'react-admin'; +import { MemoryRouter } from 'react-router'; export default { title: 'ra-ui-materialui/input/TextInput' }; @@ -176,6 +178,43 @@ export const Error = () => ( ); +const ServerErrorCreate = () => { + const notify = useNotify(); + const onSuccess = () => notify('Created with success', { type: 'success' }); + const onError = () => + notify('Error during item creation', { type: 'error' }); + return ( + + + + + + + ); +}; + +export const ServerError = () => ( + + { + console.log(`reject create on ${resource}: `, data); + return Promise.reject({ data }); + }, + } as any + } + > + + + +); + export const Sx = () => ( Date: Wed, 27 Nov 2024 15:55:33 +0100 Subject: [PATCH 28/91] Fix TextInput stories --- .../src/input/TextInput.stories.tsx | 78 ++++++++++++++----- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index eb22227101b..2eea11112fb 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -178,39 +178,75 @@ export const Error = () => ( ); -const ServerErrorCreate = () => { - const notify = useNotify(); - const onSuccess = () => notify('Created with success', { type: 'success' }); - const onError = () => - notify('Error during item creation', { type: 'error' }); - return ( - ( + + { + console.log(`reject create on ${resource}: `, data); + return Promise.reject({ + data, + message: + 'An article with this title already exists. The title must be unique.', + }); + }, + } as any + } > - - - - - - ); -}; + ( + + + + + + + )} + /> + + +); -export const ServerError = () => ( +export const ServerValidationError = () => ( { console.log(`reject create on ${resource}: `, data); - return Promise.reject({ data }); + return Promise.reject({ + data, + body: { + errors: { + title: 'An article with this title already exists. The title must be unique.', + }, + }, + }); }, } as any } > - + ( + + + + + + + )} + /> ); From 88e2d1de25a7ee424a9868e5c65bedc0ec42c3b2 Mon Sep 17 00:00:00 2001 From: erwanMarmelab <131013150+erwanMarmelab@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:20:13 +0100 Subject: [PATCH 29/91] remove useless import --- packages/ra-ui-materialui/src/input/TextInput.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index 2eea11112fb..612793e0255 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { required, Resource, useNotify } from 'ra-core'; +import { required, Resource } from 'ra-core'; import { useFormState, useFormContext } from 'react-hook-form'; import { TextInput } from './TextInput'; From ae131f3e15e3b1772e69e11d90170f734235c61e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Wed, 27 Nov 2024 16:54:53 +0100 Subject: [PATCH 30/91] patch @storybook/source-loader using yarn --- ...k-source-loader-npm-8.4.4-55dafc88e2.patch | 28 +++++++++++++++++++ package.json | 5 ++-- yarn.lock | 18 ++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 .yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch diff --git a/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch b/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch new file mode 100644 index 00000000000..d0df2ea20e3 --- /dev/null +++ b/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch @@ -0,0 +1,28 @@ +diff --git a/dist/index.js b/dist/index.js +index cd2269f6fd73854cf5f48ed3b283c95f8e127f5d..624928c8b594dc409a8a79bfed15138152e1af8e 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -1,5 +1,5 @@ + "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var src_exports={};__export(src_exports,{default:()=>src_default,extractSource:()=>extractSource});module.exports=__toCommonJS(src_exports);var import_promises=require("fs/promises");var import_csf3=require("@storybook/csf"),import_compat=require("es-toolkit/compat");function extractSource(location,lines){let{startBody:start,endBody:end}=location;if(start.line===end.line&&lines[start.line-1]!==void 0)return lines[start.line-1].substring(start.col,end.col);let startLine=lines[start.line-1],endLine=lines[end.line-1];return startLine===void 0||endLine===void 0?null:[startLine.substring(start.col),...lines.slice(start.line,end.line-1),endLine.substring(0,end.col)].join(` +-`)}var import_csf=require("@storybook/csf"),STORIES_OF="storiesOf";function pushParts(source,parts,from,to){let start=source.slice(from,to);parts.push(start);let end=source.slice(to);parts.push(end)}function patchNode(node){if(node.range&&node.range.length===2&&node.start===void 0&&node.end===void 0){let[start,end]=node.range;node.start=start,node.end=end}return!node.range&&node.start!==void 0&&node.end!==void 0&&(node.range=[node.start,node.end]),node}function findTemplate(templateName,program){let template=null;return program.body.find(node=>{let declarations=null;return node.type==="VariableDeclaration"?declarations=node.declarations:node.type==="ExportNamedDeclaration"&&node.declaration?.type==="VariableDeclaration"&&(declarations=node.declaration.declarations),declarations&&declarations.find(decl=>decl.type==="VariableDeclarator"&&decl.id.type==="Identifier"&&decl.id.name===templateName?(template=decl.init,!0):!1)}),template}function expandBindExpression(node,parent){if(node.type==="CallExpression"){let{callee,arguments:bindArguments}=node;if(parent.type==="Program"&&callee.type==="MemberExpression"&&callee.object.type==="Identifier"&&callee.property.type==="Identifier"&&callee.property.name==="bind"&&(bindArguments.length===0||bindArguments.length===1&&bindArguments[0].type==="ObjectExpression"&&bindArguments[0].properties.length===0)){let boundIdentifier=callee.object.name,template=findTemplate(boundIdentifier,parent);if(template)return template}}return node}function handleExportedName(storyName,originalNode,parent){let node=expandBindExpression(originalNode,parent),startLoc={col:node.loc.start.column,line:node.loc.start.line},endLoc={col:node.loc.end.column,line:node.loc.end.line};return{[storyName]:{startLoc,endLoc,startBody:startLoc,endBody:endLoc}}}function handleADD(node,parent,storiesOfIdentifiers){if(!node.property||!node.property.name||node.property.name!=="add")return{};let addArgs=parent.arguments;if(!addArgs||addArgs.length<2)return{};let tmp=node.object;for(;tmp.callee&&tmp.callee.object;)tmp=tmp.callee.object;let framework=tmp.callee&&tmp.callee.name&&storiesOfIdentifiers[tmp.callee.name],storyName=addArgs[0],body=addArgs[1],lastArg=addArgs[addArgs.length-1];if(storyName.type!=="Literal"&&storyName.type!=="StringLiteral")return{};if(storyName.value&&typeof storyName.value=="string"){let key=(0,import_csf.sanitize)(storyName.value),idToFramework;return key&&framework&&(idToFramework={[key]:framework}),{toAdd:{[key]:{startLoc:{col:storyName.loc.start.column,line:storyName.loc.start.line},endLoc:{col:lastArg.loc.end.column,line:lastArg.loc.end.line},startBody:{col:body.loc.start.column,line:body.loc.start.line},endBody:{col:body.loc.end.column,line:body.loc.end.line}}},idToFramework}}return{}}function handleSTORYOF(node,parts,source,lastIndex){return!node.callee||!node.callee.name||node.callee.name!==STORIES_OF?lastIndex:(parts.pop(),pushParts(source,parts,lastIndex,node.end),node.end)}var import_flow=__toESM(require("prettier/plugins/flow"));function parse(source){return import_flow.default.parsers.flow.parse(source)}function format(source){return import_flow.default.parsers.flow.format(source)}var parser_flow_default={parse,format};var import_babel=__toESM(require("prettier/plugins/babel"));function parse2(source){try{return import_babel.default.parsers.babel.parse(source)}catch(error1){try{return JSON.stringify(source)}catch{throw error1}}}function format2(source){return import_babel.default.parsers.babel.format(source)}var parser_js_default={parse:parse2,format:format2};var import_typescript=__toESM(require("prettier/plugins/typescript"));function parse3(source){try{return import_typescript.default.parsers.typescript.parse(source)}catch(error1){try{return JSON.stringify(source)}catch{throw error1}}}function format3(source){return import_typescript.default.parsers.typescript.format(source)}var parser_ts_default={parse:parse3,format:format3};function getParser(type){if(type==="javascript"||/\.jsx?/.test(type)||!type)return parser_js_default;if(type==="typescript"||/\.tsx?/.test(type))return parser_ts_default;if(type==="flow")return parser_flow_default;throw new Error(`Parser of type "${type}" is not supported`)}var parsers_default=getParser;var import_csf2=require("@storybook/csf"),import_estraverse=__toESM(require("estraverse"));function splitSTORYOF(ast,source){let lastIndex=0,parts=[source];return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node),node.type==="CallExpression"&&(lastIndex=handleSTORYOF(node,parts,source,lastIndex))}}),parts}function isFunctionVariable(declarations,includeExclude){return declarations&&declarations.length===1&&declarations[0].type==="VariableDeclarator"&&declarations[0].id&&declarations[0].id.name&&declarations[0].init&&["CallExpression","ArrowFunctionExpression","FunctionExpression","ObjectExpression"].includes(declarations[0].init.type)&&(0,import_csf2.isExportStory)(declarations[0].id.name,includeExclude)}function isFunctionDeclaration(declaration,includeExclude){return declaration.type==="FunctionDeclaration"&&declaration.id&&declaration.id.name&&(0,import_csf2.isExportStory)(declaration.id.name,includeExclude)}function getDescriptor(metaDeclaration,propertyName){let property=metaDeclaration&&metaDeclaration.declaration&&metaDeclaration.declaration.properties.find(p=>p.key&&p.key.name===propertyName);if(!property)return;let{type}=property.value;switch(type){case"ArrayExpression":return property.value.elements.map(t=>{if(!["StringLiteral","Literal"].includes(t.type))throw new Error(`Unexpected descriptor element: ${t.type}`);return t.value});case"Literal":case"RegExpLiteral":return property.value.value;default:throw new Error(`Unexpected descriptor: ${type}`)}}function findIncludeExclude(ast){let program=ast&&ast.program||ast,metaDeclaration=program&&program.body&&program.body.find(d=>d.type==="ExportDefaultDeclaration"&&d.declaration.type==="ObjectExpression"&&(d.declaration.properties||[]).length),includeStories=getDescriptor(metaDeclaration,"includeStories"),excludeStories=getDescriptor(metaDeclaration,"excludeStories");return{includeStories,excludeStories}}function splitExports(ast,source){let parts=[],lastIndex=0,includeExclude=findIncludeExclude(ast);return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node);let isNamedExport=node.type==="ExportNamedDeclaration"&&node.declaration,isFunctionVariableExport=isNamedExport&&isFunctionVariable(node.declaration.declarations,includeExclude);if(isNamedExport&&isFunctionDeclaration(node.declaration,includeExclude)||isFunctionVariableExport){let functionNode=isFunctionVariableExport?node.declaration.declarations[0].init:node.declaration;parts.push({source:source.substring(lastIndex,functionNode.start-1)}),parts.push({source:source.substring(functionNode.start,functionNode.end),declaration:{isVariableDeclaration:isFunctionVariableExport,ident:isFunctionVariableExport?node.declaration.declarations[0].id.name:functionNode.id.name}}),lastIndex=functionNode.end}}}),source.length>lastIndex+1&&parts.push({source:source.substring(lastIndex+1)}),parts.length===1?[source]:parts}function findAddsMap(ast,storiesOfIdentifiers){let addsMap={};return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:(node,parent)=>{if(patchNode(node),node.type==="MemberExpression"){let{toAdd,idToFramework}=handleADD(node,parent,storiesOfIdentifiers);Object.assign(addsMap,toAdd)}}}),addsMap}function findExportsMap(ast){let addsMap={};return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:(node,parent)=>{patchNode(node);let isNamedExport=node.type==="ExportNamedDeclaration"&&node.declaration,isFunctionVariableExport=isNamedExport&&node.declaration.declarations&&node.declaration.declarations.length===1&&node.declaration.declarations[0].type==="VariableDeclarator"&&node.declaration.declarations[0].id&&node.declaration.declarations[0].id.name&&node.declaration.declarations[0].init&&["CallExpression","ArrowFunctionExpression","FunctionExpression","ObjectExpression"].includes(node.declaration.declarations[0].init.type);if(isNamedExport&&node.declaration.type==="FunctionDeclaration"&&node.declaration.id&&node.declaration.id.name||isFunctionVariableExport){let exportDeclaration=isFunctionVariableExport?node.declaration.declarations[0]:node.declaration,toAdd=handleExportedName(exportDeclaration.id.name,exportDeclaration.init||exportDeclaration,parent);Object.assign(addsMap,toAdd)}}}),addsMap}function popParametersObjectFromDefaultExport(source,ast){let splicedSource=source,parametersSliceOfCode="",indexWhereToAppend=-1,foundParametersProperty=!1;return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node);let isDefaultExport=node.type==="ExportDefaultDeclaration",decl=node.declaration;isDefaultExport&&decl?.type==="Identifier"&&ast.body.forEach(n=>{n.type==="VariableDeclaration"&&n.declarations.forEach(d=>{d.id.name===decl.name&&(decl=d.init)})});let isObjectExpression=decl?.type==="ObjectExpression",isTsAsExpression=decl?.type==="TSAsExpression",targetNode=isObjectExpression?decl:decl?.expression;if(isDefaultExport&&(isObjectExpression||isTsAsExpression)&&(targetNode.properties||[]).length){let parametersProperty=targetNode.properties.find(p=>p.key&&p.key.name==="parameters"&&p.value.type==="ObjectExpression");foundParametersProperty=!!parametersProperty,foundParametersProperty?patchNode(parametersProperty.value):patchNode(targetNode),splicedSource=parametersProperty?source.substring(0,parametersProperty.value.start)+source.substring(parametersProperty.value.end+1):splicedSource,parametersSliceOfCode=parametersProperty?source.substring(parametersProperty.value.start,parametersProperty.value.end):"{}",indexWhereToAppend=parametersProperty?parametersProperty.value.start:targetNode.start+1}}}),{splicedSource,parametersSliceOfCode,indexWhereToAppend,foundParametersProperty}}function sanitizeSource(source){return JSON.stringify(source,null,2).trim().replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function isUglyComment(comment,uglyCommentsRegex){return uglyCommentsRegex.some(regex=>regex.test(comment))}function generateSourceWithoutUglyComments(source,{comments,uglyCommentsRegex}){let lastIndex=0,parts=[source];return comments.filter(comment=>isUglyComment(comment.value.trim(),uglyCommentsRegex)).map(patchNode).forEach(comment=>{parts.pop();let start=source.slice(lastIndex,comment.start),end=source.slice(comment.end);parts.push(start,end),lastIndex=comment.end}),parts.join("")}function prettifyCode(source,{prettierConfig,parser,filepath}){let config=prettierConfig,foundParser=null;parser==="flow"&&(foundParser="flow"),(parser==="javascript"||/jsx?/.test(parser))&&(foundParser="javascript"),(parser==="typescript"||/tsx?/.test(parser))&&(foundParser="typescript"),config.parser?filepath?config={...prettierConfig,filepath}:config={...prettierConfig}:config={...prettierConfig};try{return parsers_default(foundParser||"javascript").format(source,config)}catch{return source}}var ADD_PARAMETERS_STATEMENT=".addParameters({ storySource: { source: __STORY__, locationsMap: __LOCATIONS_MAP__ } })",applyExportDecoratorStatement=part=>part.declaration.isVariableDeclaration?` ${part.source};`:` const ${part.declaration.ident} = ${part.source};`;function generateSourceWithDecorators(source,ast){let{comments=[]}=ast,partsUsingStoryOfToken=splitSTORYOF(ast,source);if(partsUsingStoryOfToken.length>1){let newSource2=partsUsingStoryOfToken.join(ADD_PARAMETERS_STATEMENT);return{storyOfTokenFound:!0,changed:partsUsingStoryOfToken.length>1,source:newSource2,comments}}let partsUsingExports=splitExports(ast,source),newSource=partsUsingExports.map((part,i)=>i%2===0?part.source:applyExportDecoratorStatement(part)).join("");return{exportTokenFound:!0,changed:partsUsingExports.length>1,source:newSource,comments}}function generateSourceWithoutDecorators(source,ast){let{comments=[]}=ast;return{changed:!0,source,comments}}function generateAddsMap(ast,storiesOfIdentifiers){return findAddsMap(ast,storiesOfIdentifiers)}function generateStoriesLocationsMap(ast,storiesOfIdentifiers){let usingAddsMap=generateAddsMap(ast,storiesOfIdentifiers);return Object.keys(usingAddsMap).length>0?usingAddsMap:findExportsMap(ast)||usingAddsMap}function generateStorySource({source,...options}){let storySource=source;return storySource=generateSourceWithoutUglyComments(storySource,options),storySource=prettifyCode(storySource,options),storySource}function transformLocationMapToIds(parameters){if(!parameters?.locationsMap)return parameters;let locationsMap=(0,import_compat.mapKeys)(parameters.locationsMap,(_value,key)=>(0,import_csf3.sanitize)((0,import_csf3.storyNameFromExport)(key)));return{...parameters,locationsMap}}function generateSourcesInExportedParameters(source,ast,additionalParameters){let{splicedSource,parametersSliceOfCode,indexWhereToAppend,foundParametersProperty}=popParametersObjectFromDefaultExport(source,ast);if(indexWhereToAppend!==-1){let additionalParametersAsJson=JSON.stringify({storySource:transformLocationMapToIds(additionalParameters)},null,2).trim().slice(0,-1),propertyDeclaration=foundParametersProperty?"":"parameters: ",comma=foundParametersProperty?"":",",newParameters=`${propertyDeclaration}${additionalParametersAsJson},${parametersSliceOfCode.substring(1)}${comma}`,additionalComma=comma===","?"":",";return`${splicedSource.substring(0,indexWhereToAppend)}${newParameters}${additionalComma}${splicedSource.substring(indexWhereToAppend)}`}return source}function addStorySourceParameter(key,snippet){let source=sanitizeSource(snippet);return`${key}.parameters = { storySource: { source: ${source} }, ...${key}.parameters };`}function generateSourcesInStoryParameters(source,ast,additionalParameters){if(!additionalParameters||!additionalParameters.source||!additionalParameters.locationsMap)return source;let{source:sanitizedSource,locationsMap}=additionalParameters,lines=sanitizedSource.split(` ++`)}var import_csf=require("@storybook/csf"),STORIES_OF="storiesOf";function pushParts(source,parts,from,to){let start=source.slice(from,to);parts.push(start);let end=source.slice(to);parts.push(end)}function patchNode(node){if(node.range&&node.range.length===2&&node.start===void 0&&node.end===void 0){let[start,end]=node.range;node.start=start,node.end=end}return!node.range&&node.start!==void 0&&node.end!==void 0&&(node.range=[node.start,node.end]),node}function findTemplate(templateName,program){let template=null;return program.body.find(node=>{let declarations=null;return node.type==="VariableDeclaration"?declarations=node.declarations:node.type==="ExportNamedDeclaration"&&node.declaration?.type==="VariableDeclaration"&&(declarations=node.declaration.declarations),declarations&&declarations.find(decl=>decl.type==="VariableDeclarator"&&decl.id.type==="Identifier"&&decl.id.name===templateName?(template=decl.init,!0):!1)}),template}function expandBindExpression(node,parent){if(node.type==="CallExpression"){let{callee,arguments:bindArguments}=node;if(parent.type==="Program"&&callee.type==="MemberExpression"&&callee.object.type==="Identifier"&&callee.property.type==="Identifier"&&callee.property.name==="bind"&&(bindArguments.length===0||bindArguments.length===1&&bindArguments[0].type==="ObjectExpression"&&bindArguments[0].properties.length===0)){let boundIdentifier=callee.object.name,template=findTemplate(boundIdentifier,parent);if(template)return template}}return node}function handleExportedName(storyName,originalNode,parent){let node=expandBindExpression(originalNode,parent),startLoc={col:node.loc.start.column,line:node.loc.start.line},endLoc={col:node.loc.end.column,line:node.loc.end.line};return{[storyName]:{startLoc,endLoc,startBody:startLoc,endBody:endLoc}}}function handleADD(node,parent,storiesOfIdentifiers){if(!node.property||!node.property.name||node.property.name!=="add")return{};let addArgs=parent.arguments;if(!addArgs||addArgs.length<2)return{};let tmp=node.object;for(;tmp.callee&&tmp.callee.object;)tmp=tmp.callee.object;let framework=tmp.callee&&tmp.callee.name&&storiesOfIdentifiers[tmp.callee.name],storyName=addArgs[0],body=addArgs[1],lastArg=addArgs[addArgs.length-1];if(storyName.type!=="Literal"&&storyName.type!=="StringLiteral")return{};if(storyName.value&&typeof storyName.value=="string"){let key=(0,import_csf.sanitize)(storyName.value),idToFramework;return key&&framework&&(idToFramework={[key]:framework}),{toAdd:{[key]:{startLoc:{col:storyName.loc.start.column,line:storyName.loc.start.line},endLoc:{col:lastArg.loc.end.column,line:lastArg.loc.end.line},startBody:{col:body.loc.start.column,line:body.loc.start.line},endBody:{col:body.loc.end.column,line:body.loc.end.line}}},idToFramework}}return{}}function handleSTORYOF(node,parts,source,lastIndex){return!node.callee||!node.callee.name||node.callee.name!==STORIES_OF?lastIndex:(parts.pop(),pushParts(source,parts,lastIndex,node.end),node.end)}var parseFlow=__toESM(require("prettier/plugins/flow"));function parse(source){return parseFlow.parsers.flow.parse(source)}function format(source){return parseFlow.parsers.flow.format(source)}var parser_flow_default={parse,format};var parseJs=__toESM(require("prettier/plugins/babel"));function parse2(source){try{return parseJs.parsers.babel.parse(source)}catch(error1){try{return JSON.stringify(source)}catch{throw error1}}}function format2(source){return parseJs.parsers.babel.format(source)}var parser_js_default={parse:parse2,format:format2};var parseTs=__toESM(require("prettier/plugins/typescript"));function parse3(source){try{return parseTs.parsers.typescript.parse(source)}catch(error1){try{return JSON.stringify(source)}catch{throw error1}}}function format3(source){return parseTs.parsers.typescript.format(source)}var parser_ts_default={parse:parse3,format:format3};function getParser(type){if(type==="javascript"||/\.jsx?/.test(type)||!type)return parser_js_default;if(type==="typescript"||/\.tsx?/.test(type))return parser_ts_default;if(type==="flow")return parser_flow_default;throw new Error(`Parser of type "${type}" is not supported`)}var parsers_default=getParser;var import_csf2=require("@storybook/csf"),import_estraverse=__toESM(require("estraverse"));function splitSTORYOF(ast,source){let lastIndex=0,parts=[source];return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node),node.type==="CallExpression"&&(lastIndex=handleSTORYOF(node,parts,source,lastIndex))}}),parts}function isFunctionVariable(declarations,includeExclude){return declarations&&declarations.length===1&&declarations[0].type==="VariableDeclarator"&&declarations[0].id&&declarations[0].id.name&&declarations[0].init&&["CallExpression","ArrowFunctionExpression","FunctionExpression","ObjectExpression"].includes(declarations[0].init.type)&&(0,import_csf2.isExportStory)(declarations[0].id.name,includeExclude)}function isFunctionDeclaration(declaration,includeExclude){return declaration.type==="FunctionDeclaration"&&declaration.id&&declaration.id.name&&(0,import_csf2.isExportStory)(declaration.id.name,includeExclude)}function getDescriptor(metaDeclaration,propertyName){let property=metaDeclaration&&metaDeclaration.declaration&&metaDeclaration.declaration.properties.find(p=>p.key&&p.key.name===propertyName);if(!property)return;let{type}=property.value;switch(type){case"ArrayExpression":return property.value.elements.map(t=>{if(!["StringLiteral","Literal"].includes(t.type))throw new Error(`Unexpected descriptor element: ${t.type}`);return t.value});case"Literal":case"RegExpLiteral":return property.value.value;default:throw new Error(`Unexpected descriptor: ${type}`)}}function findIncludeExclude(ast){let program=ast&&ast.program||ast,metaDeclaration=program&&program.body&&program.body.find(d=>d.type==="ExportDefaultDeclaration"&&d.declaration.type==="ObjectExpression"&&(d.declaration.properties||[]).length),includeStories=getDescriptor(metaDeclaration,"includeStories"),excludeStories=getDescriptor(metaDeclaration,"excludeStories");return{includeStories,excludeStories}}function splitExports(ast,source){let parts=[],lastIndex=0,includeExclude=findIncludeExclude(ast);return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node);let isNamedExport=node.type==="ExportNamedDeclaration"&&node.declaration,isFunctionVariableExport=isNamedExport&&isFunctionVariable(node.declaration.declarations,includeExclude);if(isNamedExport&&isFunctionDeclaration(node.declaration,includeExclude)||isFunctionVariableExport){let functionNode=isFunctionVariableExport?node.declaration.declarations[0].init:node.declaration;parts.push({source:source.substring(lastIndex,functionNode.start-1)}),parts.push({source:source.substring(functionNode.start,functionNode.end),declaration:{isVariableDeclaration:isFunctionVariableExport,ident:isFunctionVariableExport?node.declaration.declarations[0].id.name:functionNode.id.name}}),lastIndex=functionNode.end}}}),source.length>lastIndex+1&&parts.push({source:source.substring(lastIndex+1)}),parts.length===1?[source]:parts}function findAddsMap(ast,storiesOfIdentifiers){let addsMap={};return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:(node,parent)=>{if(patchNode(node),node.type==="MemberExpression"){let{toAdd,idToFramework}=handleADD(node,parent,storiesOfIdentifiers);Object.assign(addsMap,toAdd)}}}),addsMap}function findExportsMap(ast){let addsMap={};return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:(node,parent)=>{patchNode(node);let isNamedExport=node.type==="ExportNamedDeclaration"&&node.declaration,isFunctionVariableExport=isNamedExport&&node.declaration.declarations&&node.declaration.declarations.length===1&&node.declaration.declarations[0].type==="VariableDeclarator"&&node.declaration.declarations[0].id&&node.declaration.declarations[0].id.name&&node.declaration.declarations[0].init&&["CallExpression","ArrowFunctionExpression","FunctionExpression","ObjectExpression"].includes(node.declaration.declarations[0].init.type);if(isNamedExport&&node.declaration.type==="FunctionDeclaration"&&node.declaration.id&&node.declaration.id.name||isFunctionVariableExport){let exportDeclaration=isFunctionVariableExport?node.declaration.declarations[0]:node.declaration,toAdd=handleExportedName(exportDeclaration.id.name,exportDeclaration.init||exportDeclaration,parent);Object.assign(addsMap,toAdd)}}}),addsMap}function popParametersObjectFromDefaultExport(source,ast){let splicedSource=source,parametersSliceOfCode="",indexWhereToAppend=-1,foundParametersProperty=!1;return import_estraverse.default.traverse(ast,{fallback:"iteration",enter:node=>{patchNode(node);let isDefaultExport=node.type==="ExportDefaultDeclaration",decl=node.declaration;isDefaultExport&&decl?.type==="Identifier"&&ast.body.forEach(n=>{n.type==="VariableDeclaration"&&n.declarations.forEach(d=>{d.id.name===decl.name&&(decl=d.init)})});let isObjectExpression=decl?.type==="ObjectExpression",isTsAsExpression=decl?.type==="TSAsExpression",targetNode=isObjectExpression?decl:decl?.expression;if(isDefaultExport&&(isObjectExpression||isTsAsExpression)&&(targetNode.properties||[]).length){let parametersProperty=targetNode.properties.find(p=>p.key&&p.key.name==="parameters"&&p.value.type==="ObjectExpression");foundParametersProperty=!!parametersProperty,foundParametersProperty?patchNode(parametersProperty.value):patchNode(targetNode),splicedSource=parametersProperty?source.substring(0,parametersProperty.value.start)+source.substring(parametersProperty.value.end+1):splicedSource,parametersSliceOfCode=parametersProperty?source.substring(parametersProperty.value.start,parametersProperty.value.end):"{}",indexWhereToAppend=parametersProperty?parametersProperty.value.start:targetNode.start+1}}}),{splicedSource,parametersSliceOfCode,indexWhereToAppend,foundParametersProperty}}function sanitizeSource(source){return JSON.stringify(source,null,2).trim().replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function isUglyComment(comment,uglyCommentsRegex){return uglyCommentsRegex.some(regex=>regex.test(comment))}function generateSourceWithoutUglyComments(source,{comments,uglyCommentsRegex}){let lastIndex=0,parts=[source];return comments.filter(comment=>isUglyComment(comment.value.trim(),uglyCommentsRegex)).map(patchNode).forEach(comment=>{parts.pop();let start=source.slice(lastIndex,comment.start),end=source.slice(comment.end);parts.push(start,end),lastIndex=comment.end}),parts.join("")}function prettifyCode(source,{prettierConfig,parser,filepath}){let config=prettierConfig,foundParser=null;parser==="flow"&&(foundParser="flow"),(parser==="javascript"||/jsx?/.test(parser))&&(foundParser="javascript"),(parser==="typescript"||/tsx?/.test(parser))&&(foundParser="typescript"),config.parser?filepath?config={...prettierConfig,filepath}:config={...prettierConfig}:config={...prettierConfig};try{return parsers_default(foundParser||"javascript").format(source,config)}catch{return source}}var ADD_PARAMETERS_STATEMENT=".addParameters({ storySource: { source: __STORY__, locationsMap: __LOCATIONS_MAP__ } })",applyExportDecoratorStatement=part=>part.declaration.isVariableDeclaration?` ${part.source};`:` const ${part.declaration.ident} = ${part.source};`;function generateSourceWithDecorators(source,ast){let{comments=[]}=ast,partsUsingStoryOfToken=splitSTORYOF(ast,source);if(partsUsingStoryOfToken.length>1){let newSource2=partsUsingStoryOfToken.join(ADD_PARAMETERS_STATEMENT);return{storyOfTokenFound:!0,changed:partsUsingStoryOfToken.length>1,source:newSource2,comments}}let partsUsingExports=splitExports(ast,source),newSource=partsUsingExports.map((part,i)=>i%2===0?part.source:applyExportDecoratorStatement(part)).join("");return{exportTokenFound:!0,changed:partsUsingExports.length>1,source:newSource,comments}}function generateSourceWithoutDecorators(source,ast){let{comments=[]}=ast;return{changed:!0,source,comments}}function generateAddsMap(ast,storiesOfIdentifiers){return findAddsMap(ast,storiesOfIdentifiers)}function generateStoriesLocationsMap(ast,storiesOfIdentifiers){let usingAddsMap=generateAddsMap(ast,storiesOfIdentifiers);return Object.keys(usingAddsMap).length>0?usingAddsMap:findExportsMap(ast)||usingAddsMap}function generateStorySource({source,...options}){let storySource=source;return storySource=generateSourceWithoutUglyComments(storySource,options),storySource=prettifyCode(storySource,options),storySource}function transformLocationMapToIds(parameters){if(!parameters?.locationsMap)return parameters;let locationsMap=(0,import_compat.mapKeys)(parameters.locationsMap,(_value,key)=>(0,import_csf3.sanitize)((0,import_csf3.storyNameFromExport)(key)));return{...parameters,locationsMap}}function generateSourcesInExportedParameters(source,ast,additionalParameters){let{splicedSource,parametersSliceOfCode,indexWhereToAppend,foundParametersProperty}=popParametersObjectFromDefaultExport(source,ast);if(indexWhereToAppend!==-1){let additionalParametersAsJson=JSON.stringify({storySource:transformLocationMapToIds(additionalParameters)},null,2).trim().slice(0,-1),propertyDeclaration=foundParametersProperty?"":"parameters: ",comma=foundParametersProperty?"":",",newParameters=`${propertyDeclaration}${additionalParametersAsJson},${parametersSliceOfCode.substring(1)}${comma}`,additionalComma=comma===","?"":",";return`${splicedSource.substring(0,indexWhereToAppend)}${newParameters}${additionalComma}${splicedSource.substring(indexWhereToAppend)}`}return source}function addStorySourceParameter(key,snippet){let source=sanitizeSource(snippet);return`${key}.parameters = { storySource: { source: ${source} }, ...${key}.parameters };`}function generateSourcesInStoryParameters(source,ast,additionalParameters){if(!additionalParameters||!additionalParameters.source||!additionalParameters.locationsMap)return source;let{source:sanitizedSource,locationsMap}=additionalParameters,lines=sanitizedSource.split(` + `),suffix=Object.entries(locationsMap).reduce((acc,[exportName,location])=>{let exportSource=extractSource(location,lines);if(exportSource){let generated=addStorySourceParameter(exportName,exportSource);return`${acc} + ${generated}`}return acc},"");return suffix?`${source} + +diff --git a/dist/index.mjs b/dist/index.mjs +index 8fac2b4b669cd7ccffd93d9ec52cb8722e6bfb6a..a8f8421e232aebf834ab8dcdea2f22f6ce1489b1 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -1,9 +1,9 @@ + import { readFile } from 'node:fs/promises'; + import { sanitize, storyNameFromExport, isExportStory } from '@storybook/csf'; + import { mapKeys } from 'es-toolkit/compat'; +-import parseFlow from 'prettier/plugins/flow'; +-import parseJs from 'prettier/plugins/babel'; +-import parseTs from 'prettier/plugins/typescript'; ++import * as parseFlow from 'prettier/plugins/flow'; ++import * as parseJs from 'prettier/plugins/babel'; ++import * as parseTs from 'prettier/plugins/typescript'; + import estraverse from 'estraverse'; + + function extractSource(location,lines){let{startBody:start,endBody:end}=location;if(start.line===end.line&&lines[start.line-1]!==void 0)return lines[start.line-1].substring(start.col,end.col);let startLine=lines[start.line-1],endLine=lines[end.line-1];return startLine===void 0||endLine===void 0?null:[startLine.substring(start.col),...lines.slice(start.line,end.line-1),endLine.substring(0,end.col)].join(` diff --git a/package.json b/package.json index ea831480b81..499cba7418a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@storybook/addon-webpack5-compiler-babel": "^3.0.3", "@storybook/react": "^8.4.4", "@storybook/react-webpack5": "^8.4.4", - "@storybook/source-loader": "^8.4.4", + "@storybook/source-loader": "patch:@storybook/source-loader@npm%3A8.4.4#~/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch", "@types/jest": "^29.5.2", "@types/react": "^18.3.3", "@typescript-eslint/eslint-plugin": "^5.60.0", @@ -78,7 +78,8 @@ "@typescript-eslint/parser": "^5.60.0", "@typescript-eslint/eslint-plugin": "^5.60.0", "minimist": "^1.2.6", - "ejs": "^3.1.7" + "ejs": "^3.1.7", + "@storybook/source-loader@npm:8.4.4": "patch:@storybook/source-loader@npm%3A8.4.4#~/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch" }, "packageManager": "yarn@4.0.2", "changelog": { diff --git a/yarn.lock b/yarn.lock index f95f48e2568..f2eaf058177 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4164,7 +4164,7 @@ __metadata: languageName: node linkType: hard -"@storybook/source-loader@npm:8.4.4, @storybook/source-loader@npm:^8.4.4": +"@storybook/source-loader@npm:8.4.4": version: 8.4.4 resolution: "@storybook/source-loader@npm:8.4.4" dependencies: @@ -4178,6 +4178,20 @@ __metadata: languageName: node linkType: hard +"@storybook/source-loader@patch:@storybook/source-loader@npm%3A8.4.4#~/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch": + version: 8.4.4 + resolution: "@storybook/source-loader@patch:@storybook/source-loader@npm%3A8.4.4#~/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch::version=8.4.4&hash=2358ba" + dependencies: + "@storybook/csf": "npm:^0.1.11" + es-toolkit: "npm:^1.22.0" + estraverse: "npm:^5.2.0" + prettier: "npm:^3.1.1" + peerDependencies: + storybook: ^8.4.4 + checksum: 476c82a8439e3e09810df3abe3efdce2a61a2008e9c6c3522549038a2e88f1adf448a009b7071968a3bf5a761f4cc08350fbee2c2bc7c3a57752650acb12b7be + languageName: node + linkType: hard + "@storybook/theming@npm:8.4.4": version: 8.4.4 resolution: "@storybook/theming@npm:8.4.4" @@ -16233,7 +16247,7 @@ __metadata: "@storybook/addon-webpack5-compiler-babel": "npm:^3.0.3" "@storybook/react": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" - "@storybook/source-loader": "npm:^8.4.4" + "@storybook/source-loader": "patch:@storybook/source-loader@npm%3A8.4.4#~/.yarn/patches/@storybook-source-loader-npm-8.4.4-55dafc88e2.patch" "@types/jest": "npm:^29.5.2" "@types/react": "npm:^18.3.3" "@typescript-eslint/eslint-plugin": "npm:^5.60.0" From d7705a4f19e5a70d9bb178b9f10caa1e4fc2df96 Mon Sep 17 00:00:00 2001 From: erwanMarmelab <131013150+erwanMarmelab@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:57:18 +0100 Subject: [PATCH 31/91] Simplify stories --- packages/ra-ui-materialui/src/input/TextInput.stories.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index 612793e0255..046606c3dc7 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -199,8 +199,7 @@ export const ServerError = () => ( create={() => ( @@ -237,8 +236,7 @@ export const ServerValidationError = () => ( create={() => ( From f278b4234513f12e68fb92a30cf414c2f6d2cf35 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Wed, 27 Nov 2024 17:03:40 +0100 Subject: [PATCH 32/91] fix prettier error --- .../ra-ui-materialui/src/input/TextInput.stories.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index 046606c3dc7..7f0c9f0b046 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -197,10 +197,7 @@ export const ServerError = () => ( ( - + @@ -234,10 +231,7 @@ export const ServerValidationError = () => ( ( - + From 4ad7a5a14b9d4362085da9edad7ee92063e858f4 Mon Sep 17 00:00:00 2001 From: dricholm Date: Wed, 27 Nov 2024 17:30:53 +0100 Subject: [PATCH 33/91] fix: Align Reference(Array)Field queryOptions type with controller --- .../ra-ui-materialui/src/field/ReferenceArrayField.tsx | 5 ++++- packages/ra-ui-materialui/src/field/ReferenceField.tsx | 7 +++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx b/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx index 72531c2e966..11154826e56 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceArrayField.tsx @@ -126,7 +126,10 @@ export interface ReferenceArrayFieldProps< reference: string; sort?: SortPayload; sx?: SxProps; - queryOptions?: UseQueryOptions; + queryOptions?: Omit< + UseQueryOptions, + 'queryFn' | 'queryKey' + >; } export interface ReferenceArrayFieldViewProps diff --git a/packages/ra-ui-materialui/src/field/ReferenceField.tsx b/packages/ra-ui-materialui/src/field/ReferenceField.tsx index b2a3c779199..5ea9d53bb57 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceField.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceField.tsx @@ -83,10 +83,9 @@ export interface ReferenceFieldProps< ReferenceRecordType extends RaRecord = RaRecord, > extends FieldProps { children?: ReactNode; - queryOptions?: Partial< - UseQueryOptions & { - meta?: any; - } + queryOptions?: Omit< + UseQueryOptions, + 'queryFn' | 'queryKey' >; reference: string; translateChoice?: Function | boolean; From 2b0498f81f3d2b047d0472b1e4e3c4a6720a182c Mon Sep 17 00:00:00 2001 From: dricholm Date: Wed, 27 Nov 2024 17:43:25 +0100 Subject: [PATCH 34/91] fix: Unify queryOptions type in useReferenceFieldController --- .../src/controller/field/useReferenceFieldController.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/ra-core/src/controller/field/useReferenceFieldController.ts b/packages/ra-core/src/controller/field/useReferenceFieldController.ts index b992e06fd45..917b3c54cde 100644 --- a/packages/ra-core/src/controller/field/useReferenceFieldController.ts +++ b/packages/ra-core/src/controller/field/useReferenceFieldController.ts @@ -52,10 +52,9 @@ export interface UseReferenceFieldControllerOptions< ReferenceRecordType extends RaRecord = RaRecord, > { source: string; - queryOptions?: Partial< - UseQueryOptions & { - meta?: any; - } + queryOptions?: Omit< + UseQueryOptions, + 'queryFn' | 'queryKey' >; reference: string; link?: LinkToType; From 2c821b23aa415ab1ba895efd369e767edd68a9ad Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Wed, 27 Nov 2024 19:06:02 +0100 Subject: [PATCH 35/91] Add unit tests --- .../src/input/TextArrayInput.spec.tsx | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 packages/ra-ui-materialui/src/input/TextArrayInput.spec.tsx diff --git a/packages/ra-ui-materialui/src/input/TextArrayInput.spec.tsx b/packages/ra-ui-materialui/src/input/TextArrayInput.spec.tsx new file mode 100644 index 00000000000..6622e3e8322 --- /dev/null +++ b/packages/ra-ui-materialui/src/input/TextArrayInput.spec.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; +import { render, fireEvent, screen } from '@testing-library/react'; + +import { Basic, HelperText, Label, Required } from './TextArrayInput.stories'; + +describe('', () => { + it('should render the values as chips', () => { + render(); + const chip1 = screen.getByText('john@example.com'); + expect(chip1.classList.contains('MuiChip-label')).toBe(true); + const chip2 = screen.getByText('albert@target.dev'); + expect(chip2.classList.contains('MuiChip-label')).toBe(true); + }); + it('should allow to remove a value', async () => { + render(); + await screen.findByText( + '["john@example.com","albert@target.dev"] (object)' + ); + const deleteButtons = screen.getAllByTestId('CancelIcon'); + fireEvent.click(deleteButtons[0]); + await screen.findByText('["albert@target.dev"] (object)'); + }); + it('should allow to remove all values one by one', async () => { + render(); + await screen.findByText( + '["john@example.com","albert@target.dev"] (object)' + ); + const deleteButtons = screen.getAllByTestId('CancelIcon'); + fireEvent.click(deleteButtons[1]); + fireEvent.click(deleteButtons[0]); + await screen.findByText('[] (object)'); + }); + it('should allow to remove all values using the reset button', async () => { + render(); + const input = screen.getByLabelText('resources.emails.fields.to'); + fireEvent.click(input); + const clearButton = screen.getByLabelText('Clear'); + fireEvent.click(clearButton); + await screen.findByText('[] (object)'); + }); + it('should allow to add a value', async () => { + render(); + const input = screen.getByLabelText('resources.emails.fields.to'); + fireEvent.change(input, { target: { value: 'bob.brown@example.com' } }); + fireEvent.keyDown(input, { key: 'Enter' }); + await screen.findByText( + '["john@example.com","albert@target.dev","bob.brown@example.com"] (object)' + ); + }); + it('should render the helper text', () => { + render(); + screen.getByText('Email addresses of the recipients'); + }); + it('should render the custom label', () => { + render( )} show={ShowGuesser} + edit={() => ( + + + + + + + + )} create={() => ( Date: Thu, 5 Dec 2024 10:39:46 +0100 Subject: [PATCH 54/91] [Doc] Update `` documentation [no ci] --- docs/TreeWithDetails.md | 44 +++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/docs/TreeWithDetails.md b/docs/TreeWithDetails.md index 9be7e365c88..f8072dafe0b 100644 --- a/docs/TreeWithDetails.md +++ b/docs/TreeWithDetails.md @@ -72,22 +72,23 @@ Check [the `ra-tree` documentation](https://react-admin-ee.marmelab.com/document ## Props -| Prop | Required | Type | Default | Description | -| -------------------- | -------- | ---------------------- | ------- |---------------------------------------------------------------------------------------------| -| `addRootButton` | Optional | `ReactNode` or `false` | - | The create button to add a root node | -| `allowMultipleRoots` | Optional | `boolean` | `false` | To allow trees with multiple roots | -| `create` | Required | `ReactNode` | - | The create form of your resource | -| `draggable` | Optional | `boolean` | `false` | To allow user to reorder nodes | -| `edit` | Required | `ReactNode` | - | The edit form of your resource | -| `hideRootNodes` | Optional | `boolean` | `false` | To hide all root nodes | -| `lazy` | Optional | `boolean` | `false` | To load children only when they are expanded | +| Prop | Required | Type | Default | Description | +| -------------------- | -------- | ---------------------- | ------- |----------------------------------------------------------------------------------------------- | +| `addRootButton` | Optional | `ReactNode` or `false` | - | The create button to add a root node | +| `allowMultipleRoots` | Optional | `boolean` | `false` | To allow trees with multiple roots | +| `create` | Required | `ReactNode` | - | The create form of your resource | +| `draggable` | Optional | `boolean` | `false` | To allow user to reorder nodes | +| `edit` | Required | `ReactNode` | - | The edit form of your resource | +| `filter` | Optional | `object` | - | The permanent filter values | +| `hideRootNodes` | Optional | `boolean` | `false` | To hide all root nodes | +| `lazy` | Optional | `boolean` | `false` | To load children only when they are expanded | | `motion` | Optional | `boolean` | `false` | To enable [rc-tree's ``](https://github.com/react-component/tree#tree-props) transitions | -| `nodeActions` | Optional | `ReactNode` | - | To customize the default dropdown action | -| `show` | Required | `ReactNode` | - | The show view of your resource | -| `showLine` | Optional | `boolean` | `false` | Shows a connecting line | -| `sx` | Optional | `SxProps` | - | Material UI shortcut for defining custom styles | -| `title` | Optional | `string` | - | The title to display in the `` | -| `titleField` | Optional | `string` | `title` | Set the record field to display in the tree | +| `nodeActions` | Optional | `ReactNode` | - | To customize the default dropdown action | +| `show` | Required | `ReactNode` | - | The show view of your resource | +| `showLine` | Optional | `boolean` | `false` | Shows a connecting line | +| `sx` | Optional | `SxProps` | - | Material UI shortcut for defining custom styles | +| `title` | Optional | `string` | - | The title to display in the `` | +| `titleField` | Optional | `string` | `title` | Set the record field to display in the tree | `` also accepts the [rc-tree](https://tree-react-component.vercel.app/) props. @@ -244,6 +245,19 @@ If you want to allow user to reorder nodes in the tree, simply add the `draggabl export const CategoriesList = () => ; ``` + +### `filter` + +You can choose to permanently filter the tree to display only a sub tree. + +For instance, imagine you have one `employees` resource with a `department` field, and you want to display a tree for the Finance department. Use the `filter` prop to filter the tree: + +```jsx +export const EmployeeList = () => ; +``` + +**Note**: This only works if the filter field allows to extract a subtree with its own root node. If you use the `filter` prop to display a sparse selection of nodes (e.g. only the `male` employees), dragging nodes in this tree will not work as expected. + ## `hideRootNodes` Sometimes, a tree only has one root node for technical reasons and users should probably not see it at all. Use the `hideRootNodes` prop to hide all root nodes. From 546cadb5f1470ae0f0081b651c996118aee0460f Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Thu, 5 Dec 2024 11:21:13 +0100 Subject: [PATCH 55/91] Fix DateRangeInput doc import --- docs/DateRangeInput.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DateRangeInput.md b/docs/DateRangeInput.md index 354ab924cc0..00386534f11 100644 --- a/docs/DateRangeInput.md +++ b/docs/DateRangeInput.md @@ -16,7 +16,7 @@ This [Enterprise Edition](https://react-admin-ee.marmelab.com)` inside a form component (``, ``, ``, etc.) to allow users to pick a start and an end date. ```tsx -import { DateRangeInput } from '@react-admin/ra-form-layout'; +import { DateRangeInput } from '@react-admin/ra-form-layout/DateRangeInput'; import { Edit, SimpleForm } from 'react-admin'; export const EventEdit = () => ( @@ -106,7 +106,7 @@ import { SimpleForm, TextInput, } from "react-admin"; -import { DateRangeInput } from '@react-admin/ra-form-layout'; +import { DateRangeInput } from '@react-admin/ra-form-layout/DateRangeInput'; const requiredValues = dates => !dates || isEmpty(dates[0]) || isEmpty(dates[1]) From 15dce7420826aca4f05b84079a7e2bffd2c2f374 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Thu, 5 Dec 2024 14:46:54 +0100 Subject: [PATCH 56/91] Update examples/simple/src/data.tsx --- examples/simple/src/data.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple/src/data.tsx b/examples/simple/src/data.tsx index 69a0ac1fd47..f1276b78534 100644 --- a/examples/simple/src/data.tsx +++ b/examples/simple/src/data.tsx @@ -1,7 +1,7 @@ export default { posts: [ { - id: '1 1', + id: 1, title: 'Accusantium qui nihil voluptatum quia voluptas maxime ab similique', teaser: 'In facilis aut aut odit hic doloribus. Fugit possimus perspiciatis sit molestias in. Sunt dignissimos sed quis at vitae veniam amet. Sint sunt perspiciatis quis doloribus aperiam numquam consequatur et. Blanditiis aut earum incidunt eos magnam et voluptatem. Minima iure voluptatum autem. At eaque sit aperiam minima aut in illum.', body: '

    Rerum velit quos est similique. Consectetur tempora eos ullam velit nobis sit debitis. Magni explicabo omnis delectus labore vel recusandae.

    Aut a minus laboriosam harum placeat quas minima fuga. Quos nulla fuga quam officia tempore. Rerum occaecati ut eum et tempore. Nam ab repudiandae et nemo praesentium.

    Cumque corporis officia occaecati ducimus sequi laborum omnis ut. Nam aspernatur veniam fugit. Nihil eum libero ea dolorum ducimus impedit sed. Quidem inventore porro corporis debitis eum in. Nesciunt unde est est qui nulla. Esse sunt placeat molestiae molestiae sed quia. Sunt qui quidem quos velit reprehenderit quos blanditiis ducimus. Sint et molestiae maxime ut consequatur minima. Quaerat rem voluptates voluptatem quos. Corporis perferendis in provident iure. Commodi odit exercitationem excepturi et deserunt qui.

    Optio iste necessitatibus velit non. Neque sed occaecati culpa porro culpa. Quia quam in molestias ratione et necessitatibus consequatur. Est est tempora consequatur voluptatem vel. Mollitia tenetur non quis omnis perspiciatis deserunt sed necessitatibus. Ad rerum reiciendis sunt aspernatur.

    Est ullam ut magni aspernatur. Eum et sed tempore modi.

    Earum aperiam sit neque quo laborum suscipit unde. Expedita nostrum itaque non non adipisci. Ut delectus quis delectus est at sint. Iste hic qui ea eaque eaque sed id. Hic placeat rerum numquam id velit deleniti voluptatem. Illum adipisci voluptas adipisci ut alias. Earum exercitationem iste quidem eveniet aliquid hic reiciendis. Exercitationem est sunt in minima consequuntur. Aut quaerat libero dolorem.

    ', From 8a4ec6b8d5e942a94da429f75d59973ad20b40f9 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Thu, 5 Dec 2024 18:17:25 +0100 Subject: [PATCH 57/91] backport install tip --- docs/DateRangeInput.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/DateRangeInput.md b/docs/DateRangeInput.md index 00386534f11..3e17687dc1a 100644 --- a/docs/DateRangeInput.md +++ b/docs/DateRangeInput.md @@ -9,7 +9,13 @@ This [Enterprise Edition](https://react-admin-ee.marmelab.com)` is a wrapper around the [Material UI X Date Range Picker](https://mui.com/x/react-date-pickers/date-range-picker/), which is a MUI X Pro package. This means that you need to own a [MUI X Pro license](https://mui.com/x/introduction/licensing/#pro-plan) to use it. +**Note**: `` is a wrapper around the [Material UI X Date Range Picker](https://mui.com/x/react-date-pickers/date-range-picker/), which is a MUI X Pro package. This means that you need to own a [MUI X Pro license](https://mui.com/x/introduction/licensing/#pro-plan) to use it and install the package: + +```sh +npm install --save @mui/x-date-pickers-pro +# or +yarn add @mui/x-date-pickers-pro +``` ## Usage From 8c6932f1abdc02bed196410b23513b539ce42fb3 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 5 Dec 2024 18:54:55 +0100 Subject: [PATCH 58/91] Fix markdown syntax error --- docs/TreeWithDetails.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/TreeWithDetails.md b/docs/TreeWithDetails.md index f8072dafe0b..a5995f6a5cb 100644 --- a/docs/TreeWithDetails.md +++ b/docs/TreeWithDetails.md @@ -252,9 +252,11 @@ You can choose to permanently filter the tree to display only a sub tree. For instance, imagine you have one `employees` resource with a `department` field, and you want to display a tree for the Finance department. Use the `filter` prop to filter the tree: +{% raw %} ```jsx -export const EmployeeList = () => ; +const EmployeeList = () => ; ``` +{% endraw %} **Note**: This only works if the filter field allows to extract a subtree with its own root node. If you use the `filter` prop to display a sparse selection of nodes (e.g. only the `male` employees), dragging nodes in this tree will not work as expected. From fbf8a861d5896aa5f95110337002255b6a034e6c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Mon, 9 Dec 2024 10:27:42 +0100 Subject: [PATCH 59/91] Fix FileInput triggers onChange twice with latest react-dropzone --- .../src/input/FileInput.stories.tsx | 18 ++++++++++++++++++ .../ra-ui-materialui/src/input/FileInput.tsx | 2 ++ 2 files changed, 20 insertions(+) diff --git a/packages/ra-ui-materialui/src/input/FileInput.stories.tsx b/packages/ra-ui-materialui/src/input/FileInput.stories.tsx index ba33618b51a..1cb6c68a8de 100644 --- a/packages/ra-ui-materialui/src/input/FileInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/FileInput.stories.tsx @@ -114,6 +114,24 @@ export const CustomRemoveIcon = () => ( ); +export const OnChange = ({ onChange = console.log }) => ( + + + + + + +); + +export const OnChangeMultiple = ({ onChange = console.log }) => ( + + + + + + +); + const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( diff --git a/packages/ra-ui-materialui/src/input/FileInput.tsx b/packages/ra-ui-materialui/src/input/FileInput.tsx index 74d41265f73..aa7580bcd21 100644 --- a/packages/ra-ui-materialui/src/input/FileInput.tsx +++ b/packages/ra-ui-materialui/src/input/FileInput.tsx @@ -40,6 +40,7 @@ export const FileInput = (props: FileInputProps) => { labelMultiple = 'ra.input.file.upload_several', labelSingle = 'ra.input.file.upload_single', options = {}, + onChange: onChangeProp, onRemove: onRemoveProp, parse, placeholder, @@ -95,6 +96,7 @@ export const FileInput = (props: FileInputProps) => { validate, disabled, readOnly, + onChange: onChangeProp, ...rest, }); const { error, invalid } = fieldState; From 3b80f764aa4f3fd8a73986fee892950d333c3443 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Mon, 9 Dec 2024 10:37:08 +0100 Subject: [PATCH 60/91] Backport `` doc + fix linter issues --- docs/ReferenceManyToManyField.md | 42 ++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/docs/ReferenceManyToManyField.md b/docs/ReferenceManyToManyField.md index 87c7ada4fbc..4c083957deb 100644 --- a/docs/ReferenceManyToManyField.md +++ b/docs/ReferenceManyToManyField.md @@ -5,7 +5,7 @@ title: "The ReferenceManyToManyField Component" # `` -This [Enterprise Edition](https://react-admin-ee.marmelab.com) component fetches a list of referenced records by lookup in an associative table, and passes the records down to its child component, which must be an iterator component (e.g. ``). +This [Enterprise Edition](https://react-admin-ee.marmelab.com)premium icon component fetches a list of referenced records by lookup in an associative table, and passes the records down to its child component, which must be an iterator component (e.g. ``). !["ReferenceManyToManyField example showing band's venues"](./img/reference-many-to-many-field.png) @@ -15,7 +15,7 @@ Note: The `` cannot currently display multiple records Let's imagine that you're writing an app managing concerts for artists. The data model features a many-to-many relationship between the `bands` and `venues` tables through a `performances` associative table. -``` +```txt ┌─────────┐ ┌──────────────┐ ┌───────────────┐ │ bands │ │ performances │ │ venues │ │---------│ │--------------│ │---------------│ @@ -28,7 +28,7 @@ Let's imagine that you're writing an app managing concerts for artists. The data In this example, `bands.id` matches `performances.band_id`, and `performances.venue_id` matches `venues.id`. -To allow users see the `venues` for a given `band` in ``, wrap that component in `` where you define the relationship via the `reference`, `through` and `using` props: +To allow users see the `venues` for a given `band` in ``, wrap that component in `` where you define the relationship via the `reference`, `through` and `using` props: ```tsx import React from 'react'; @@ -61,17 +61,18 @@ export const BandShow = () => ( | ----------- | -------- | ------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `children` | Required | `element` | - | An iterator element (e.g. `` or ``). The iterator element usually has one or more child `` components. | | `reference` | Required | `string` | - | Name of the reference resource, e.g. 'venues' | -| `through` | Required | `string` | - | Name of the resource for the associative table, e.g. 'performances' +| `through` | Required | `string` | - | Name of the resource for the associative table, e.g. 'performances' | | `filter` | Optional | `object` | `{}` | Filter for the associative table (passed to the `getManyReference()` call) | | `joinLimit` | Optional | `number` | 100 | Limit for the number of results fetched from the associative table. Should be **greater than `perPage`** | | `perPage` | Optional | `number` | 25 | Limit the number of displayed result after `getManyReference` is called. Useful when using a pagination component. Should be **smaller than `joinLimit`** | +| `queryOptions` | Optional | `UseQueryOptions` | - | Query options for the `getMany` and `getManyReference` calls | | `sort` | Optional | `{ field: string, order: 'ASC' or 'DESC' }` | `{ field: 'id', order: 'DESC' }` | Sort for the associative table (passed to the `getManyReference()` call) | | `source` | Optional | `string` | `'id'` | Name of the field containing the identity of the main resource. Used determine the value to look for in the associative table. | | `using` | Optional | `string` | `'[resource]_id,[reference]_id'` | Tuple (comma separated) of the two field names used as foreign keys, e.g 'band_id,venue_id'. The tuple should start with the field pointing to the resource, and finish with the field pointing to the reference | ## `children` -`` expects an _iterator_ component as child, i.e. a component working inside a `ListContext`. +`` expects an _iterator_ component as child, i.e. a component working inside a `ListContext`. This means you can use a `` instead of a ``, which is useful if you want to display more details about related records. For instance, to display the venue `name` and `location`: @@ -105,6 +106,7 @@ export const BandShow = () => ( You can filter the records of the associative table (e.g. `performances`) using the `filter` prop. This `filter` is passed to the `getManyReference()` call. {% raw %} + ```tsx ``` + {% endraw %} ## `joinLimit` @@ -165,6 +168,27 @@ import { Pagination } from 'react-admin'; ``` +## `queryOptions` + +Use the `queryOptions` prop to customize the queries for `getMany` and `getManyReference`. + +You can for instance use it to pass [a custom meta](./Actions.md#meta-parameter) to the dataProvider. + +{% raw %} + +```tsx + + {/* ... */} + +``` + +{% endraw %} + ## `reference` The name of the target resource to fetch. @@ -187,6 +211,7 @@ For instance, if you want to display the `venues` of a given `bands`, through `p By default, react-admin orders the possible values by `id` desc for the associative table (e.g. `performances`). You can change this order by setting the `sort` prop (an object with `field` and `order` properties) to be applied to the associative resource. {% raw %} + ```tsx ``` + {% endraw %} ## `source` @@ -242,8 +268,8 @@ You can specify the columns to use in the associative `using` the using prop. `` fetches the `dataProvider` twice in a row: -- once to get the records of the associative resource (`performances` in this case), using a `getManyReference()` call -- once to get the records of the reference resource (`venues` in this case), using a `getMany()` call. +- once to get the records of the associative resource (`performances` in this case), using a `getManyReference()` call +- once to get the records of the reference resource (`venues` in this case), using a `getMany()` call. For instance, if the user displays the band of id `123`, `` first issues the following query to the `dataProvider`: @@ -286,4 +312,4 @@ And receives the reference venues: ], "total": 3 } -``` \ No newline at end of file +``` From c441872fed630d807b522d18421d6a9851f52da0 Mon Sep 17 00:00:00 2001 From: erwanMarmelab Date: Mon, 9 Dec 2024 10:41:19 +0100 Subject: [PATCH 61/91] Backport `` doc + fix linter issues --- docs/ReferenceManyToManyInput.md | 74 +++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/docs/ReferenceManyToManyInput.md b/docs/ReferenceManyToManyInput.md index bb1a571404d..4f5d6f667ff 100644 --- a/docs/ReferenceManyToManyInput.md +++ b/docs/ReferenceManyToManyInput.md @@ -5,7 +5,7 @@ title: "The ReferenceManyToManyInput Component" # `` -This [Enterprise Edition](https://react-admin-ee.marmelab.com) component allows to create, edit or remove relationships between two resources sharing an associative table. The changes in the associative table are sent to the dataProvider _when the user submits the form_, so that they can cancel the changes before submission. +This [Enterprise Edition](https://react-admin-ee.marmelab.com)premium icon component allows to create, edit or remove relationships between two resources sharing an associative table. The changes in the associative table are sent to the dataProvider _when the user submits the form_, so that they can cancel the changes before submission.
From be8eab81b27de142cbfd3950c2bb63e6c2669119 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:18:55 +0100 Subject: [PATCH 88/91] Remove unnecessary story --- .../edit/useEditController.stories.tsx | 90 +------------------ 1 file changed, 2 insertions(+), 88 deletions(-) diff --git a/packages/ra-core/src/controller/edit/useEditController.stories.tsx b/packages/ra-core/src/controller/edit/useEditController.stories.tsx index b5e4e05c873..74f3b86eb1a 100644 --- a/packages/ra-core/src/controller/edit/useEditController.stories.tsx +++ b/packages/ra-core/src/controller/edit/useEditController.stories.tsx @@ -2,13 +2,9 @@ import * as React from 'react'; import { Route, Routes, useLocation } from 'react-router'; import { CoreAdminContext, - EditBase, EditController, - Form, - InputProps, testDataProvider, TestMemoryRouter, - useInput, } from '../..'; export default { @@ -79,93 +75,11 @@ export const EncodedIdWithPercentage = ({ ); }; -export const OverrideRecordWithLocation = ({ - url = '/posts/1', - dataProvider = testDataProvider({ - // @ts-expect-error - getOne: () => - Promise.resolve({ - data: { id: 1, title: 'hello', value: 'a value' }, - }), - }), -}) => { - return ( - - - - -
- -
-
- - -
-
-
- - } - /> -
-
-
- ); -}; - -OverrideRecordWithLocation.argTypes = { - url: { - options: [ - 'unmodified', - 'modified with location state', - 'modified with location search', - ], - mapping: { - unmodified: '/posts/1', - 'modified with location state': { - pathname: '/posts/1', - state: { record: { value: 'from-state' } }, - }, - 'modified with location search': `/posts/1?source=${encodeURIComponent(JSON.stringify({ value: 'from-search' }))}`, - }, - control: { type: 'select' }, - }, -}; - -const LocationInspector = ({ deep }: { deep?: boolean }) => { +const LocationInspector = () => { const location = useLocation(); return (

- Location:{' '} - {deep ? JSON.stringify(location) : location.pathname} + Location: {location.pathname}

); }; - -const TextInput = (props: InputProps) => { - const input = useInput(props); - - return ( -
- - -
- ); -}; From 994e5b75a89fbaa48dad3ba1126a04ff8dc3c057 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:19:12 +0100 Subject: [PATCH 89/91] Remove duplicate test --- .../src/form/useRecordFromLocation.spec.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/packages/ra-core/src/form/useRecordFromLocation.spec.tsx b/packages/ra-core/src/form/useRecordFromLocation.spec.tsx index e20d0486593..f8c9654de9c 100644 --- a/packages/ra-core/src/form/useRecordFromLocation.spec.tsx +++ b/packages/ra-core/src/form/useRecordFromLocation.spec.tsx @@ -13,20 +13,6 @@ describe('useRecordFromLocation', () => { return
{JSON.stringify(recordFromLocation)}
; }; - it('return the record from the location search', async () => { - const record = { test: 'value' }; - render( - - - - ); - - await screen.findByText(JSON.stringify(record)); - }); it('return null if there is no location search nor state that contains a record', async () => { render( From 46a15e6c5e4eebc3c0b5f0809f84214f1ab5be10 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:19:21 +0100 Subject: [PATCH 90/91] Renaming --- packages/ra-core/src/form/useRecordFromLocation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ra-core/src/form/useRecordFromLocation.ts b/packages/ra-core/src/form/useRecordFromLocation.ts index 6b4d19ef459..d071596038d 100644 --- a/packages/ra-core/src/form/useRecordFromLocation.ts +++ b/packages/ra-core/src/form/useRecordFromLocation.ts @@ -25,7 +25,7 @@ export const useRecordFromLocation = ( // To avoid having the form resets when the location changes but the final record is the same // This is needed for forms such as TabbedForm or WizardForm that may change the location for their sections - const finalRecordRef = useRef(recordFromLocation); + const previousRecordRef = useRef(recordFromLocation); useEffect(() => { const newRecordFromLocation = getRecordFromLocation(location, { @@ -33,8 +33,8 @@ export const useRecordFromLocation = ( searchSource, }); - if (!isEqual(newRecordFromLocation, finalRecordRef.current)) { - finalRecordRef.current = newRecordFromLocation; + if (!isEqual(newRecordFromLocation, previousRecordRef.current)) { + previousRecordRef.current = newRecordFromLocation; setRecordFromLocation(newRecordFromLocation); } }, [location, stateSource, searchSource]); From b2026b8f9cf4af541467085ac45c14ef49afd9c8 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:19:32 +0100 Subject: [PATCH 91/91] Ensure we include default values --- packages/ra-core/src/form/Form.spec.tsx | 26 +++++++++++++++++- packages/ra-core/src/form/Form.stories.tsx | 27 ++++++++++++++----- packages/ra-core/src/form/useAugmentedForm.ts | 4 +-- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/packages/ra-core/src/form/Form.spec.tsx b/packages/ra-core/src/form/Form.spec.tsx index bec86cb8757..a3fd7aa02b5 100644 --- a/packages/ra-core/src/form/Form.spec.tsx +++ b/packages/ra-core/src/form/Form.spec.tsx @@ -833,22 +833,46 @@ describe('Form', () => { state: { record: { body: 'from-state' } }, }, expectedValue: 'from-state', + expectedDefaultValue: '', + }, + { + from: 'state with default values', + url: { + pathname: '/form/general', + state: { record: { body: 'from-state' } }, + }, + expectedValue: 'from-state', + defaultValues: { category: 'default category' }, + expectedDefaultValue: 'default category', }, { from: 'search query', url: `/form/general?source=${encodeURIComponent(JSON.stringify({ body: 'from-search' }))}` as To, expectedValue: 'from-search', + expectedDefaultValue: '', + }, + { + from: 'search query with default values', + url: `/form/general?source=${encodeURIComponent(JSON.stringify({ body: 'from-search' }))}` as To, + expectedValue: 'from-search', + defaultValues: { category: 'default category' }, + expectedDefaultValue: 'default category', }, ])( 'should support overriding the record values from the location $from', - async ({ url, expectedValue }) => { + async ({ url, defaultValues, expectedValue, expectedDefaultValue }) => { render( ); await screen.findByDisplayValue('lorem'); + expect( + (await screen.findByLabelText('category')) + .value + ).toEqual(expectedDefaultValue); expect( (screen.getByText('Submit') as HTMLInputElement).disabled ).toEqual(false); diff --git a/packages/ra-core/src/form/Form.stories.tsx b/packages/ra-core/src/form/Form.stories.tsx index 63c2d487772..0570b36fbd3 100644 --- a/packages/ra-core/src/form/Form.stories.tsx +++ b/packages/ra-core/src/form/Form.stories.tsx @@ -19,7 +19,7 @@ import { import { CoreAdminContext } from '../core'; import { RecordContextProvider, SaveContextProvider } from '../controller'; -import { Form } from './Form'; +import { Form, FormProps } from './Form'; import { useInput } from './useInput'; import { required, ValidationError } from './validation'; import { mergeTranslations } from '../i18n'; @@ -58,10 +58,12 @@ const Input = props => { }; const SubmitButton = () => { - const state = useFormState(); + const { dirtyFields } = useFormState(); + // useFormState().isDirty might differ from useFormState().dirtyFields (https://github.com/react-hook-form/react-hook-form/issues/4740) + const isDirty = Object.keys(dirtyFields).length > 0; return ( - ); @@ -416,9 +418,11 @@ export const ServerSideValidation = () => { export const MultiRoutesForm = ({ url, initialRecord, + defaultValues, }: { url?: any; initialRecord?: Partial; + defaultValues?: Partial; }) => ( @@ -427,7 +431,7 @@ export const MultiRoutesForm = ({ path="/form/*" element={ - + } /> @@ -458,6 +462,16 @@ MultiRoutesForm.argTypes = { }, control: { type: 'select' }, }, + defaultValues: { + options: ['none', 'provided'], + mapping: { + none: undefined, + provided: { + category: 'default category', + }, + }, + control: { type: 'select' }, + }, initialRecord: { options: ['none', 'provided'], mapping: { @@ -468,9 +482,9 @@ MultiRoutesForm.argTypes = { }, }; -const FormWithSubRoutes = () => { +const FormWithSubRoutes = (props: Partial) => { return ( -
+ @@ -502,6 +516,7 @@ const TabbedForm = () => { + diff --git a/packages/ra-core/src/form/useAugmentedForm.ts b/packages/ra-core/src/form/useAugmentedForm.ts index 393cd50d0e5..6f47a36fb43 100644 --- a/packages/ra-core/src/form/useAugmentedForm.ts +++ b/packages/ra-core/src/form/useAugmentedForm.ts @@ -92,12 +92,12 @@ export const useAugmentedForm = ( const { reset } = form; useEffect(() => { if (recordFromLocation && !recordFromLocationApplied.current) { - reset(merge({}, record, recordFromLocation), { + reset(merge({}, defaultValuesIncludingRecord, recordFromLocation), { keepDefaultValues: true, }); recordFromLocationApplied.current = true; } - }, [record, recordFromLocation, reset]); + }, [defaultValuesIncludingRecord, recordFromLocation, reset]); // submit callbacks const handleSubmit = useCallback(