@aurelia/storybook 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +12 -20
  2. package/apps/hello-world/.storybook/main.ts +27 -5
  3. package/apps/hello-world/package-lock.json +781 -3474
  4. package/apps/hello-world/package.json +12 -8
  5. package/apps/hello-world/src/stories/hello-world.stories.ts +6 -6
  6. package/apps/hello-world-webpack/.storybook/main.ts +0 -1
  7. package/apps/hello-world-webpack/package-lock.json +229 -2042
  8. package/apps/hello-world-webpack/package.json +8 -7
  9. package/apps/hello-world-webpack/src/hello-world.html +6 -0
  10. package/apps/hello-world-webpack/src/hello-world.ts +17 -0
  11. package/apps/hello-world-webpack/src/my-app.stories.ts +10 -7
  12. package/apps/hello-world-webpack/src/stories/hello-world.stories.ts +54 -0
  13. package/dist/index.js +65 -121
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +62 -115
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/preset.js +17 -10
  18. package/dist/preset.js.map +1 -1
  19. package/dist/preset.mjs +15 -1
  20. package/dist/preset.mjs.map +1 -1
  21. package/dist/preview/render.js +44 -124
  22. package/dist/preview/render.js.map +1 -1
  23. package/dist/preview/render.mjs +41 -116
  24. package/dist/preview/render.mjs.map +1 -1
  25. package/dist/preview/types.js +0 -1
  26. package/dist/preview/types.js.map +1 -1
  27. package/dist/preview.js +84 -44
  28. package/dist/preview.js.map +1 -1
  29. package/dist/preview.mjs +81 -39
  30. package/dist/preview.mjs.map +1 -1
  31. package/dist/webpack.js +1 -3
  32. package/dist/webpack.js.map +1 -1
  33. package/package.json +16 -19
  34. package/rollup.config.mjs +10 -8
  35. package/src/index.ts +28 -0
  36. package/src/preset.ts +20 -2
  37. package/src/preview/render.ts +49 -47
  38. package/src/preview.ts +1 -50
  39. package/tsconfig.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"preview.mjs","sources":["../src/preview/render.ts","../src/preview.ts"],"sourcesContent":["import { STORY_CHANGED } from 'storybook/internal/core-events';\nimport type { RenderContext, ArgsStoryFn } from 'storybook/internal/types';\nimport type { AureliaRenderer } from './types';\nimport Aurelia, { Constructable, CustomElement } from 'aurelia';\n\ninterface AureliaStoryResult {\n template: string;\n components?: unknown[];\n Component?: unknown;\n container?: any;\n items?: unknown[];\n innerHtml?: string;\n props?: Record<string, any>;\n}\n\n/**\n * Merges multiple sources into a single object.\n * Sources can be story parameters, args, or story.props.\n */\nfunction mergeStoryProps(\n ...sources: Array<Record<string, any> | undefined>\n): Record<string, any> {\n return Object.assign({}, ...sources);\n}\n\n// Track Aurelia apps for cleanup\nconst appMap = new Map<HTMLElement, Aurelia>();\n\nasync function teardown(element: HTMLElement) {\n if (appMap.has(element)) {\n const app = appMap.get(element);\n if (app) {\n await app.stop();\n appMap.delete(element);\n }\n }\n}\n\nexport const render: ArgsStoryFn<AureliaRenderer> = (args, { id, component: Component }) => {\n if (!Component) {\n throw new Error(\n `Unable to render story ${id} as the component annotation is missing from the default export`\n );\n }\n return { Component, props: args, template: '' };\n};\n\nexport async function renderToCanvas(\n {\n storyFn,\n title,\n name,\n showMain,\n showError,\n storyContext,\n forceRemount,\n }: RenderContext<AureliaRenderer>,\n canvasElement: HTMLElement,\n bootstrapAppFn?: typeof bootstrapAureliaApp\n) {\n const appBootstrapFn = bootstrapAppFn || bootstrapAureliaApp;\n\n const { parameters, component, args } = storyContext;\n let app = appMap.get(canvasElement);\n\n const story = storyFn() as AureliaStoryResult;\n\n if (!story) {\n showError({\n title: `Expecting an Aurelia component from the story: \"${name}\" of \"${title}\".`,\n description: `\n Did you forget to return the Aurelia component from the story?\n Use \"() => ({ template: '<custom-component></custom-component>' })\" when defining the story.\n `,\n });\n return () => {};\n }\n\n showMain();\n\n let mergedProps;\n // Use full merge (including story.props) when bootstrapping a new app or force remounting.\n if (!app || forceRemount) {\n mergedProps = mergeStoryProps(parameters?.args, args, story.props);\n if (app) {\n await teardown(canvasElement);\n }\n app = appBootstrapFn(\n story,\n mergedProps,\n canvasElement,\n component as Constructable\n ) as Aurelia;\n await app.start();\n appMap.set(canvasElement, app);\n } else {\n // Update the existing app viewModel only with parameters and args (exclude story.props).\n mergedProps = mergeStoryProps(parameters?.args, args);\n if (app.root?.controller?.viewModel) {\n Object.assign(app.root.controller.viewModel, mergedProps);\n }\n }\n\n // Set up story change listener for cleanup\n const channel = storyContext.viewMode === 'story' ? storyContext.channel : null;\n let onStoryChange: () => void;\n if (channel) {\n onStoryChange = () => {\n // When the story changes, clean up the Aurelia app\n teardown(canvasElement);\n };\n channel.on(STORY_CHANGED, onStoryChange);\n }\n\n // Return teardown function that also unsubscribes from STORY_CHANGED\n return async () => {\n if (channel && onStoryChange) {\n channel.off(STORY_CHANGED, onStoryChange);\n }\n await teardown(canvasElement);\n };\n}\n\nexport function bootstrapAureliaApp(\n story: AureliaStoryResult,\n args: Record<string, any>,\n domElement: HTMLElement,\n component?: Constructable\n) {\n const aurelia = new Aurelia(story.container);\n\n if (story.items?.length) {\n aurelia.register(...story.items);\n }\n\n if (story.components?.length) {\n aurelia.register(...story.components);\n }\n\n let { template } = story;\n\n if (component) {\n template = template ?? createComponentTemplate(component, story.innerHtml);\n aurelia.register(component);\n }\n\n const App = CustomElement.define(\n {\n name: 'au-storybook',\n template,\n containerless: true,\n },\n class {}\n );\n\n const app = Object.assign(new App(), args);\n\n return aurelia.app({\n host: domElement,\n component: app,\n });\n}\n\nexport function createComponentTemplate(\n component: Constructable,\n innerHtml?: string\n): string {\n const def = CustomElement.getDefinition(component);\n\n return `<${def.name} ${Object.values(def.bindables)\n .map((bindable) => `${bindable.attribute}.bind=\"${bindable.name}\"`)\n .join(' ')}>${innerHtml ?? ''}</${def.name}>`;\n}","import { renderToCanvas, bootstrapAureliaApp } from './preview/render';\nimport Aurelia from 'aurelia';\n\n// Track the current story's cleanup function\nlet currentCleanup: (() => void) | null = null;\n\nexport const render = (args: any, context: any) => {\n // Clean up previous story if exists\n if (currentCleanup) {\n currentCleanup();\n currentCleanup = null;\n }\n\n // Create a container element\n const container = document.createElement('div');\n \n // Get the story function result\n const story = context.storyFn();\n \n // Bootstrap Aurelia app immediately\n if (story && (story.Component || story.template)) {\n const app = bootstrapAureliaApp(\n story,\n args,\n container,\n story.Component || context.component\n ) as Aurelia;\n \n // Start the app asynchronously\n const startPromise = app.start();\n if (startPromise && typeof startPromise.catch === 'function') {\n startPromise.catch((error: any) => {\n console.error('Failed to start Aurelia app:', error);\n });\n }\n \n // Set cleanup function\n currentCleanup = () => {\n const stopPromise = app.stop();\n if (stopPromise && typeof stopPromise.catch === 'function') {\n stopPromise.catch((error: any) => {\n console.error('Failed to stop Aurelia app:', error);\n });\n }\n };\n }\n \n // Return the container element immediately\n return container;\n}; "],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"preview.mjs","sources":["../src/preview/render.ts"],"sourcesContent":["import { STORY_CHANGED } from 'storybook/internal/core-events';\nimport type { RenderContext, ArgsStoryFn } from 'storybook/internal/types';\nimport type { AureliaRenderer } from './types';\nimport Aurelia, { Constructable, CustomElement } from 'aurelia';\n\ninterface AureliaStoryResult {\n template: string;\n components?: unknown[];\n Component?: unknown;\n container?: any;\n items?: unknown[];\n innerHtml?: string;\n props?: Record<string, any>;\n}\n\n// Track Aurelia apps for cleanup\nconst appMap = new Map<HTMLElement, any>();\n\nasync function teardown(element: HTMLElement) {\n if (appMap.has(element)) {\n const app = appMap.get(element);\n if (app) {\n await app.stop();\n appMap.delete(element);\n }\n }\n}\n\nexport const render: ArgsStoryFn<AureliaRenderer> = (args, context) => {\n const { id, component: Component } = context;\n \n if (!Component) {\n throw new Error(\n `Unable to render story ${id} as the component annotation is missing from the default export`\n );\n }\n return { Component, props: args, template: '' };\n};\n\nexport async function renderToCanvas(\n {\n storyFn,\n title,\n name,\n showMain,\n showError,\n storyContext,\n forceRemount,\n }: RenderContext<AureliaRenderer>,\n canvasElement: HTMLElement,\n bootstrapAppFn?: typeof createAureliaApp\n) {\n // Store reference to the original storybook root element\n const rootElement = canvasElement;\n\n // Ensure we have (or create) a single container inside the root where the Aurelia app actually renders\n let hostElement: HTMLElement;\n if (rootElement.id === 'storybook-root') {\n hostElement = rootElement.querySelector('.aurelia-story-container') as HTMLElement;\n if (!hostElement) {\n hostElement = document.createElement('div');\n hostElement.className = 'aurelia-story-container';\n hostElement.style.height = '100%';\n rootElement.appendChild(hostElement);\n }\n } else {\n hostElement = rootElement;\n }\n\n // All app instances are now tracked by the *root* element, ensuring we only ever have one per story iframe\n const appBootstrapFn = bootstrapAppFn ?? createAureliaApp;\n const { parameters, component, args } = storyContext;\n \n let app = appMap.get(rootElement);\n const story = storyFn() as AureliaStoryResult;\n \n // Temporary debug logging\n console.log(`[DEBUG] Story: ${name}, forceRemount: ${forceRemount}, hasExistingApp: ${!!app}, canvasId: ${canvasElement.className}`);\n\n if (!story) {\n showError({\n title: `Expecting an Aurelia component from the story: \"${name}\" of \"${title}\".`,\n description: `\n Did you forget to return the Aurelia component from the story?\n Use \"() => ({ template: '<custom-component></custom-component>' })\" when defining the story.\n `,\n });\n return () => {};\n }\n\n showMain();\n\n if (!app || forceRemount) {\n if (forceRemount && app) {\n await teardown(rootElement);\n app = undefined;\n }\n // Clear container before mounting new app\n hostElement.innerHTML = '';\n\n const mergedProps = { ...parameters?.args, ...args, ...story.props };\n\n const aureliaApp = appBootstrapFn(\n story,\n mergedProps,\n hostElement,\n component as Constructable\n );\n await aureliaApp.start();\n appMap.set(rootElement, aureliaApp);\n app = aureliaApp;\n } else {\n // update existing app props\n const mergedProps = { ...parameters?.args, ...args, ...story.props };\n if (app?.root?.controller?.viewModel) {\n Object.assign(app.root.controller.viewModel, mergedProps);\n }\n }\n\n // Return cleanup fn\n return async () => {\n await teardown(rootElement);\n };\n}\n\nexport function createAureliaApp(\n story: AureliaStoryResult,\n args: Record<string, any>,\n domElement: HTMLElement,\n component?: Constructable\n) {\n const aurelia = new Aurelia(story.container);\n\n if (story.items?.length) {\n aurelia.register(...story.items);\n }\n\n if (story.components?.length) {\n aurelia.register(...story.components);\n }\n\n let { template } = story;\n\n if (component) {\n template = template ?? createComponentTemplate(component, story.innerHtml);\n aurelia.register(component);\n }\n\n const App = CustomElement.define(\n {\n name: 'sb-app',\n template,\n containerless: true,\n },\n class {}\n );\n\n const app = Object.assign(new App(), args);\n\n return aurelia.app({\n host: domElement,\n component: app,\n });\n}\n\nexport function createComponentTemplate(\n component: Constructable,\n innerHtml?: string\n): string {\n const def = CustomElement.getDefinition(component);\n\n return `<${def.name} ${Object.values(def.bindables)\n .map((bindable) => `${bindable.attribute}.bind=\"${bindable.name}\"`)\n .join(' ')}>${innerHtml ?? ''}</${def.name}>`;\n}"],"names":[],"mappings":"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"}
package/dist/webpack.js CHANGED
@@ -1,5 +1,3 @@
1
- 'use strict';
2
-
3
1
  /**
4
2
  * A set of rules to be added to the webpack configuration.
5
3
  * @returns
@@ -19,5 +17,5 @@ function getRules() {
19
17
  ];
20
18
  }
21
19
 
22
- exports.getRules = getRules;
20
+ export { getRules };
23
21
  //# sourceMappingURL=webpack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"webpack.js","sources":["../src/webpack.ts"],"sourcesContent":["// src/webpack.ts\nimport type { RuleSetRule } from 'webpack';\n\n/**\n * A set of rules to be added to the webpack configuration.\n * @returns\n */\nexport function getRules(): RuleSetRule[] {\n return [\n {\n test: /\\.ts$/i,\n use: ['ts-loader', '@aurelia/webpack-loader'],\n exclude: /node_modules/,\n },\n {\n test: /\\.html$/i,\n use: '@aurelia/webpack-loader',\n exclude: /node_modules/,\n },\n ];\n}\n"],"names":[],"mappings":";;AAGA;;;AAGG;SACa,QAAQ,GAAA;IACtB,OAAO;AACL,QAAA;AACE,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,GAAG,EAAE,CAAC,WAAW,EAAE,yBAAyB,CAAC;AAC7C,YAAA,OAAO,EAAE,cAAc;AACxB,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,GAAG,EAAE,yBAAyB;AAC9B,YAAA,OAAO,EAAE,cAAc;AACxB,SAAA;KACF;AACH;;;;"}
1
+ {"version":3,"file":"webpack.js","sources":["../src/webpack.ts"],"sourcesContent":["// src/webpack.ts\nimport type { RuleSetRule } from 'webpack';\n\n/**\n * A set of rules to be added to the webpack configuration.\n * @returns\n */\nexport function getRules(): RuleSetRule[] {\n return [\n {\n test: /\\.ts$/i,\n use: ['ts-loader', '@aurelia/webpack-loader'],\n exclude: /node_modules/,\n },\n {\n test: /\\.html$/i,\n use: '@aurelia/webpack-loader',\n exclude: /node_modules/,\n },\n ];\n}\n"],"names":[],"mappings":"AAGA;;;AAGG;SACa,QAAQ,GAAA;IACtB,OAAO;AACL,QAAA;AACE,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,GAAG,EAAE,CAAC,WAAW,EAAE,yBAAyB,CAAC;AAC7C,YAAA,OAAO,EAAE,cAAc;AACxB,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,GAAG,EAAE,yBAAyB;AAC9B,YAAA,OAAO,EAAE,cAAc;AACxB,SAAA;KACF;AACH;;;;"}
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@aurelia/storybook",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "A Storybook plugin to render Aurelia 2 components using Vite or Webpack",
5
+ "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "types": "dist/index.d.ts",
7
- "module": "dist/index.mjs",
8
8
  "publishConfig": {
9
9
  "access": "public"
10
10
  },
11
+ "engines": {
12
+ "node": ">=20.19.0 || >=22.12.0"
13
+ },
11
14
  "scripts": {
12
15
  "build": "rollup -c",
13
16
  "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly",
@@ -15,37 +18,31 @@
15
18
  "test": "NODE_OPTIONS=--no-deprecation jest"
16
19
  },
17
20
  "peerDependencies": {
18
- "@aurelia/runtime-html": "^2.0.0-beta.24",
19
- "@aurelia/vite-plugin": "^2.0.0-beta.24",
20
- "@storybook/builder-vite": "^9.0.0",
21
- "@storybook/builder-webpack5": "^9.0.0",
22
- "aurelia": "^2.0.0-beta.24",
23
- "storybook": "^9.0.0"
21
+ "@aurelia/runtime-html": "^2.0.0-beta.25",
22
+ "@aurelia/vite-plugin": "^2.0.0-beta.25",
23
+ "@storybook/builder-vite": "^10.0.0",
24
+ "@storybook/builder-webpack5": "^10.0.0",
25
+ "aurelia": "^2.0.0-beta.25",
26
+ "storybook": "^10.0.0"
24
27
  },
25
28
  "devDependencies": {
26
- "@aurelia/webpack-loader": "^2.0.0-beta.24",
29
+ "@aurelia/webpack-loader": "^2.0.0-beta.25",
27
30
  "@rollup/plugin-commonjs": "^28.0.6",
28
31
  "@rollup/plugin-node-resolve": "^16.0.1",
29
32
  "@rollup/plugin-typescript": "^12.1.3",
30
- "@storybook/builder-vite": "^9.0.12",
31
- "storybook": "^9.0.12",
33
+ "@storybook/builder-vite": "^10.0.5",
32
34
  "@types/jest": "^30.0.0",
33
35
  "glob": "^11.0.3",
34
36
  "jest": "^30.0.2",
35
37
  "jest-environment-jsdom": "^30.0.2",
36
38
  "rollup": "^4.44.0",
39
+ "storybook": "^10.0.0",
37
40
  "ts-jest": "^29.4.0",
38
41
  "ts-loader": "^9.5.2",
39
42
  "typescript": "^5.8.3"
40
43
  },
41
44
  "exports": {
42
- ".": {
43
- "require": "./dist/index.js",
44
- "import": "./dist/index.mjs"
45
- },
46
- "./preset": {
47
- "require": "./dist/preset.js",
48
- "import": "./dist/preset.mjs"
49
- }
45
+ ".": "./dist/index.js",
46
+ "./preset": "./dist/preset.js"
50
47
  }
51
48
  }
package/rollup.config.mjs CHANGED
@@ -7,7 +7,12 @@ const external = [
7
7
  '@aurelia/runtime-html',
8
8
  '@aurelia/vite-plugin',
9
9
  '@storybook/builder-vite',
10
- 'aurelia'
10
+ 'aurelia',
11
+ 'react',
12
+ 'react-dom',
13
+ 'storybook/internal/core-events',
14
+ 'storybook/internal/types',
15
+ 'storybook/theming'
11
16
  ];
12
17
 
13
18
  // Get all TypeScript files from src directory
@@ -21,7 +26,7 @@ const createConfig = (input, output) => ({
21
26
  input,
22
27
  output: {
23
28
  file: output,
24
- format: output.endsWith('.mjs') ? 'esm' : 'cjs',
29
+ format: 'esm',
25
30
  sourcemap: true,
26
31
  exports: 'named'
27
32
  },
@@ -37,12 +42,9 @@ const createConfig = (input, output) => ({
37
42
  external
38
43
  });
39
44
 
40
- // Create configs for all source files
41
- const configs = Object.entries(srcFiles).flatMap(([name, input]) => [
42
- // ESM build
43
- createConfig(input, `dist/${name}.mjs`),
44
- // CommonJS build
45
+ // Create configs for all source files - ESM only for Storybook v10
46
+ const configs = Object.entries(srcFiles).map(([name, input]) =>
45
47
  createConfig(input, `dist/${name}.js`)
46
- ]);
48
+ );
47
49
 
48
50
  export default configs;
package/src/index.ts CHANGED
@@ -1,4 +1,32 @@
1
+ import type { StorybookConfig } from 'storybook/internal/types';
1
2
  import { renderToCanvas } from './preview/render';
2
3
 
3
4
  export { renderToCanvas };
4
5
  export const render = renderToCanvas;
6
+
7
+ // Define the framework
8
+ export const framework = {
9
+ name: '@aurelia/storybook',
10
+ options: {}
11
+ };
12
+
13
+ // Framework configuration for Storybook
14
+ export const frameworkOptions = {
15
+ builder: {
16
+ name: '@storybook/builder-vite',
17
+ options: {}
18
+ }
19
+ };
20
+
21
+ // Export a complete framework configuration
22
+ export const aureliaFramework = {
23
+ name: '@aurelia/storybook',
24
+ options: {},
25
+ builder: '@storybook/builder-vite'
26
+ };
27
+
28
+ // Provide external dependencies configuration
29
+ export const externals = {
30
+ 'react': 'React',
31
+ 'react-dom': 'ReactDOM'
32
+ };
package/src/preset.ts CHANGED
@@ -7,7 +7,25 @@ import { getRules } from './webpack';
7
7
  * Optionally adjust the Vite configuration.
8
8
  */
9
9
  export async function viteFinal(config: any): Promise<any> {
10
- // For now, return the config unchanged.
10
+ // Configure Vite to properly handle dependencies
11
+ config.define = config.define || {};
12
+ config.define['process.env.NODE_ENV'] = JSON.stringify(process.env.NODE_ENV || 'development');
13
+
14
+ // Configure optimization deps
15
+ config.optimizeDeps = config.optimizeDeps || {};
16
+ config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
17
+
18
+ // Only exclude Aurelia-specific dependencies that cause issues
19
+ const excludeList = [
20
+ '@aurelia/runtime-html'
21
+ ];
22
+
23
+ excludeList.forEach(dep => {
24
+ if (!config.optimizeDeps.exclude.includes(dep)) {
25
+ config.optimizeDeps.exclude.push(dep);
26
+ }
27
+ });
28
+
11
29
  return config;
12
30
  }
13
31
 
@@ -28,4 +46,4 @@ export async function webpackFinal(config: any): Promise<any> {
28
46
  // Export a default for compatibility.
29
47
  export default { viteFinal, webpackFinal };
30
48
 
31
- export const previewAnnotations = [require.resolve('./preview')];
49
+ export const previewAnnotations = ['./preview.js'];
@@ -13,18 +13,8 @@ interface AureliaStoryResult {
13
13
  props?: Record<string, any>;
14
14
  }
15
15
 
16
- /**
17
- * Merges multiple sources into a single object.
18
- * Sources can be story parameters, args, or story.props.
19
- */
20
- function mergeStoryProps(
21
- ...sources: Array<Record<string, any> | undefined>
22
- ): Record<string, any> {
23
- return Object.assign({}, ...sources);
24
- }
25
-
26
16
  // Track Aurelia apps for cleanup
27
- const appMap = new Map<HTMLElement, Aurelia>();
17
+ const appMap = new Map<HTMLElement, any>();
28
18
 
29
19
  async function teardown(element: HTMLElement) {
30
20
  if (appMap.has(element)) {
@@ -36,7 +26,9 @@ async function teardown(element: HTMLElement) {
36
26
  }
37
27
  }
38
28
 
39
- export const render: ArgsStoryFn<AureliaRenderer> = (args, { id, component: Component }) => {
29
+ export const render: ArgsStoryFn<AureliaRenderer> = (args, context) => {
30
+ const { id, component: Component } = context;
31
+
40
32
  if (!Component) {
41
33
  throw new Error(
42
34
  `Unable to render story ${id} as the component annotation is missing from the default export`
@@ -56,14 +48,34 @@ export async function renderToCanvas(
56
48
  forceRemount,
57
49
  }: RenderContext<AureliaRenderer>,
58
50
  canvasElement: HTMLElement,
59
- bootstrapAppFn?: typeof bootstrapAureliaApp
51
+ bootstrapAppFn?: typeof createAureliaApp
60
52
  ) {
61
- const appBootstrapFn = bootstrapAppFn || bootstrapAureliaApp;
53
+ // Store reference to the original storybook root element
54
+ const rootElement = canvasElement;
55
+
56
+ // Ensure we have (or create) a single container inside the root where the Aurelia app actually renders
57
+ let hostElement: HTMLElement;
58
+ if (rootElement.id === 'storybook-root') {
59
+ hostElement = rootElement.querySelector('.aurelia-story-container') as HTMLElement;
60
+ if (!hostElement) {
61
+ hostElement = document.createElement('div');
62
+ hostElement.className = 'aurelia-story-container';
63
+ hostElement.style.height = '100%';
64
+ rootElement.appendChild(hostElement);
65
+ }
66
+ } else {
67
+ hostElement = rootElement;
68
+ }
62
69
 
70
+ // All app instances are now tracked by the *root* element, ensuring we only ever have one per story iframe
71
+ const appBootstrapFn = bootstrapAppFn ?? createAureliaApp;
63
72
  const { parameters, component, args } = storyContext;
64
- let app = appMap.get(canvasElement);
65
-
73
+
74
+ let app = appMap.get(rootElement);
66
75
  const story = storyFn() as AureliaStoryResult;
76
+
77
+ // Temporary debug logging
78
+ console.log(`[DEBUG] Story: ${name}, forceRemount: ${forceRemount}, hasExistingApp: ${!!app}, canvasId: ${canvasElement.className}`);
67
79
 
68
80
  if (!story) {
69
81
  showError({
@@ -78,50 +90,40 @@ export async function renderToCanvas(
78
90
 
79
91
  showMain();
80
92
 
81
- let mergedProps;
82
- // Use full merge (including story.props) when bootstrapping a new app or force remounting.
83
93
  if (!app || forceRemount) {
84
- mergedProps = mergeStoryProps(parameters?.args, args, story.props);
85
- if (app) {
86
- await teardown(canvasElement);
94
+ if (forceRemount && app) {
95
+ await teardown(rootElement);
96
+ app = undefined;
87
97
  }
88
- app = appBootstrapFn(
98
+ // Clear container before mounting new app
99
+ hostElement.innerHTML = '';
100
+
101
+ const mergedProps = { ...parameters?.args, ...args, ...story.props };
102
+
103
+ const aureliaApp = appBootstrapFn(
89
104
  story,
90
105
  mergedProps,
91
- canvasElement,
106
+ hostElement,
92
107
  component as Constructable
93
- ) as Aurelia;
94
- await app.start();
95
- appMap.set(canvasElement, app);
108
+ );
109
+ await aureliaApp.start();
110
+ appMap.set(rootElement, aureliaApp);
111
+ app = aureliaApp;
96
112
  } else {
97
- // Update the existing app viewModel only with parameters and args (exclude story.props).
98
- mergedProps = mergeStoryProps(parameters?.args, args);
99
- if (app.root?.controller?.viewModel) {
113
+ // update existing app props
114
+ const mergedProps = { ...parameters?.args, ...args, ...story.props };
115
+ if (app?.root?.controller?.viewModel) {
100
116
  Object.assign(app.root.controller.viewModel, mergedProps);
101
117
  }
102
118
  }
103
119
 
104
- // Set up story change listener for cleanup
105
- const channel = storyContext.viewMode === 'story' ? storyContext.channel : null;
106
- let onStoryChange: () => void;
107
- if (channel) {
108
- onStoryChange = () => {
109
- // When the story changes, clean up the Aurelia app
110
- teardown(canvasElement);
111
- };
112
- channel.on(STORY_CHANGED, onStoryChange);
113
- }
114
-
115
- // Return teardown function that also unsubscribes from STORY_CHANGED
120
+ // Return cleanup fn
116
121
  return async () => {
117
- if (channel && onStoryChange) {
118
- channel.off(STORY_CHANGED, onStoryChange);
119
- }
120
- await teardown(canvasElement);
122
+ await teardown(rootElement);
121
123
  };
122
124
  }
123
125
 
124
- export function bootstrapAureliaApp(
126
+ export function createAureliaApp(
125
127
  story: AureliaStoryResult,
126
128
  args: Record<string, any>,
127
129
  domElement: HTMLElement,
@@ -146,7 +148,7 @@ export function bootstrapAureliaApp(
146
148
 
147
149
  const App = CustomElement.define(
148
150
  {
149
- name: 'au-storybook',
151
+ name: 'sb-app',
150
152
  template,
151
153
  containerless: true,
152
154
  },
package/src/preview.ts CHANGED
@@ -1,50 +1 @@
1
- import { renderToCanvas, bootstrapAureliaApp } from './preview/render';
2
- import Aurelia from 'aurelia';
3
-
4
- // Track the current story's cleanup function
5
- let currentCleanup: (() => void) | null = null;
6
-
7
- export const render = (args: any, context: any) => {
8
- // Clean up previous story if exists
9
- if (currentCleanup) {
10
- currentCleanup();
11
- currentCleanup = null;
12
- }
13
-
14
- // Create a container element
15
- const container = document.createElement('div');
16
-
17
- // Get the story function result
18
- const story = context.storyFn();
19
-
20
- // Bootstrap Aurelia app immediately
21
- if (story && (story.Component || story.template)) {
22
- const app = bootstrapAureliaApp(
23
- story,
24
- args,
25
- container,
26
- story.Component || context.component
27
- ) as Aurelia;
28
-
29
- // Start the app asynchronously
30
- const startPromise = app.start();
31
- if (startPromise && typeof startPromise.catch === 'function') {
32
- startPromise.catch((error: any) => {
33
- console.error('Failed to start Aurelia app:', error);
34
- });
35
- }
36
-
37
- // Set cleanup function
38
- currentCleanup = () => {
39
- const stopPromise = app.stop();
40
- if (stopPromise && typeof stopPromise.catch === 'function') {
41
- stopPromise.catch((error: any) => {
42
- console.error('Failed to stop Aurelia app:', error);
43
- });
44
- }
45
- };
46
- }
47
-
48
- // Return the container element immediately
49
- return container;
50
- };
1
+ export { renderToCanvas, render } from './preview/render';
package/tsconfig.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "outDir": "dist",
7
7
  "rootDir": "src",
8
8
  "strict": true,
9
- "moduleResolution": "node",
9
+ "moduleResolution": "bundler",
10
10
  "esModuleInterop": true,
11
11
  "skipLibCheck": true
12
12
  },