diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/main.ts b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/main.ts
new file mode 100644
index 0000000..74f554b
--- /dev/null
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/main.ts
@@ -0,0 +1,49 @@
+import type { StorybookConfig } from '@storybook/react-vite';
+import path from 'path';
+
+const addonName = path.basename(process.cwd()); // Get the addon name dynamically
+
+const config: StorybookConfig = {
+ stories: ['../**/*.mdx', `../**/*.stories.@(js|jsx|mjs|ts|tsx)`],
+ addons: [
+ '@chromatic-com/storybook',
+ '@storybook/addon-a11y',
+ '@storybook/addon-docs',
+ '@storybook/addon-essentials',
+ '@storybook/addon-interactions',
+ '@storybook/addon-links',
+ '@storybook/addon-onboarding',
+ 'storybook-react-intl',
+ ],
+ framework: {
+ name: '@storybook/react-vite',
+ options: {},
+ },
+ staticDirs: [`../../../public`],
+ viteFinal: async (config) => {
+ // Adjust paths as needed for the dynamically named addon
+ config.resolve = {
+ ...config.resolve,
+ alias: {
+ ...config.resolve?.alias,
+ [`@${addonName}`]: path.resolve(
+ __dirname,
+ `../../../packages/${addonName}/src/`,
+ ),
+ },
+ };
+
+ // Markdown support (if needed)
+ config.plugins?.push({
+ name: 'vite-plugin-markdown',
+ transform(src, id) {
+ if (id.endsWith('.md')) {
+ return `export default ${JSON.stringify(src)}`;
+ }
+ },
+ });
+ return config;
+ },
+};
+
+export default config;
diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/preview.ts b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/preview.ts
new file mode 100644
index 0000000..ec8840e
--- /dev/null
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/.storybook/preview.ts
@@ -0,0 +1,86 @@
+import React from 'react';
+import path from 'path';
+import '@kitconcept/volto-light-theme/customizations/@root/theme';
+import '../../../core/packages/volto/test-setup-config';
+
+import {
+ Title,
+ Subtitle,
+ Description,
+ Controls,
+ Stories,
+} from '@storybook/blocks';
+import { Decorator, Preview } from '@storybook/react';
+import { deMessages, enMessages, frMessages } from './localesWrapper';
+import Wrapper from '../../../core/packages/volto/src/storybook';
+
+// Dynamically resolve the addon’s name and paths
+const addonName = path.basename(process.cwd());
+const messagesMap = {
+ de: deMessages,
+ en: enMessages,
+ fr: frMessages,
+};
+
+const getMessages = (locale: string) =>
+ messagesMap[locale as keyof typeof messagesMap];
+
+const decorators: Decorator[] = [
+ (Story, context) => {
+ return (
+
+
+
+ );
+ },
+];
+
+const parameters = {
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/,
+ },
+ },
+ docs: {
+ page: () => (
+ <>
+
+
+
+
+
+ >
+ ),
+ },
+};
+
+const reactIntl = {
+ defaultLocale: 'de',
+ locales: ['en', 'de', 'fr'],
+};
+
+const preview: Preview = {
+ globals: {
+ locale: reactIntl.defaultLocale,
+ locales: {
+ en: { icon: '🇺🇸', title: 'English', right: 'EN' },
+ de: { icon: '🇩🇪', title: 'Deutsch', right: 'DE' },
+ fr: { icon: '🇫🇷', title: 'Français', right: 'FR' },
+ },
+ },
+ parameters: {
+ reactIntl,
+ ...parameters,
+ },
+ decorators,
+};
+
+export default preview;
diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/package.json b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/package.json
index a96948d..807e104 100644
--- a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/package.json
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/package.json
@@ -24,7 +24,10 @@
"dry-release": "release-it --dry-run",
"release": "release-it",
"release-major-alpha": "release-it major --preRelease=alpha",
- "release-alpha": "release-it --preRelease=alpha"
+ "release-alpha": "release-it --preRelease=alpha",
+ "test": "vitest",
+ "storybook": "storybook dev -p 6006",
+ "storybook-build": "storybook build"
},
"dependencies": {},
"peerDependencies": {
@@ -33,6 +36,25 @@
},
"devDependencies": {
"@plone/scripts": "{{ cookiecutter.__version_plone_scripts }}",
- "release-it": "{{ cookiecutter.__version_release_it }}"
+ "@vitejs/plugin-react": "^4.3.1",
+ "release-it": "{{ cookiecutter.__version_release_it }}",
+ "vite": "^5.3.1",
+ "vite-plugin-markdown": "^2.2.0",
+ "vite-tsconfig-paths": "^4.3.2",
+ "vitest": "^1.6.0",
+ "@testing-library/react": "^16.0.0",
+ "@testing-library/jest-dom": "^6.4.6",
+ "@storybook/react": "^8.1.10",
+ "@storybook/react-vite": "^8.1.10",
+ "@storybook/addon-a11y": "^8.1.10",
+ "@storybook/addon-actions": "^8.1.10",
+ "@storybook/addon-controls": "^8.1.10",
+ "@storybook/addon-docs": "^8.1.10",
+ "@storybook/addon-essentials": "^8.1.10",
+ "@storybook/addon-interactions": "^8.1.10",
+ "@storybook/addon-links": "^8.1.10",
+ "@storybook/addon-onboarding": "^8.1.10",
+ "@storybook/blocks": "^8.1.10",
+ "storybook-react-intl": "^3.0.1"
}
}
diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/setupTests.ts b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/setupTests.ts
new file mode 100644
index 0000000..7b0828b
--- /dev/null
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/setupTests.ts
@@ -0,0 +1 @@
+import '@testing-library/jest-dom';
diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vite.config.ts b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vite.config.ts
new file mode 100644
index 0000000..d2c4cea
--- /dev/null
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vite.config.ts
@@ -0,0 +1,37 @@
+import { defineConfig } from 'vite';
+import tsconfigPaths from 'vite-tsconfig-paths';
+import react from '@vitejs/plugin-react';
+import path from 'path';
+import fixReactVirtualized from 'esbuild-plugin-react-virtualized';
+
+// Dynamically get the name of the generated addon
+const addonName = path.basename(process.cwd());
+const projectRootPath = path.resolve('../..');
+
+// Vite configuration with dynamic addon name
+export default defineConfig({
+ plugins: [react(), tsconfigPaths()],
+ optimizeDeps: {
+ esbuildOptions: {
+ plugins: [fixReactVirtualized as any],
+ },
+ include: ['@plone/volto/constants/Languages.cjs'],
+ },
+ resolve: {
+ alias: [
+ { find: /^~@root/, replacement: projectRootPath },
+ {
+ find: `@${addonName}`,
+ replacement: `${projectRootPath}/packages/${addonName}/src/`,
+ },
+ { find: /^~/, replacement: '' },
+ ],
+ },
+ logLevel: 'error',
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: './src/setupTests.ts',
+ include: ['src/**/*.test.ts', 'src/**/*.test.tsx'],
+ },
+});
diff --git a/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vitest.config.ts b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vitest.config.ts
new file mode 100644
index 0000000..4da6c87
--- /dev/null
+++ b/frontend_addon/{{ cookiecutter.__folder_name }}/packages/{{ cookiecutter.frontend_addon_name }}/vitest.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ test: {
+ include: ['**/*.vitest.tsx'],
+ globals: true,
+ reporters: 'verbose',
+ environment: 'jsdom',
+ },
+});