@aurelia/storybook 2.1.0 → 2.3.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 (116) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +195 -12
  3. package/dist/index.d.ts +25 -0
  4. package/dist/index.js +101 -27
  5. package/dist/index.js.map +1 -1
  6. package/dist/preset.d.ts +21 -0
  7. package/dist/preset.js +74 -20
  8. package/dist/preset.js.map +1 -1
  9. package/dist/preview/helpers.d.ts +2 -0
  10. package/dist/preview/helpers.js +6 -0
  11. package/dist/preview/helpers.js.map +1 -0
  12. package/dist/preview/render.d.ts +7 -0
  13. package/dist/preview/render.js +99 -28
  14. package/dist/preview/render.js.map +1 -1
  15. package/dist/preview/storybook-types-runtime.d.ts +1 -0
  16. package/dist/preview/storybook-types-runtime.js +5 -0
  17. package/dist/preview/storybook-types-runtime.js.map +1 -0
  18. package/dist/preview/storybook-types.d.ts +27 -0
  19. package/dist/preview/types-runtime.d.ts +1 -0
  20. package/dist/preview/types-runtime.js +5 -0
  21. package/dist/preview/types-runtime.js.map +1 -0
  22. package/dist/preview/types.d.ts +44 -0
  23. package/dist/preview.d.ts +3 -0
  24. package/dist/preview.js +104 -29
  25. package/dist/preview.js.map +1 -1
  26. package/dist/webpack.d.ts +10 -0
  27. package/dist/webpack.js +19 -1
  28. package/dist/webpack.js.map +1 -1
  29. package/package.json +75 -15
  30. package/preset.js +2 -1
  31. package/CONTINUITY.md +0 -22
  32. package/__tests__/preset.test.ts +0 -49
  33. package/__tests__/preview.test.ts +0 -139
  34. package/__tests__/render.test.ts +0 -187
  35. package/__tests__/webpack.test.ts +0 -21
  36. package/apps/hello-world/.storybook/main.ts +0 -49
  37. package/apps/hello-world/.storybook/preview.ts +0 -1
  38. package/apps/hello-world/.stylelintrc.json +0 -5
  39. package/apps/hello-world/README.md +0 -28
  40. package/apps/hello-world/eslint.config.mjs +0 -25
  41. package/apps/hello-world/favicon.ico +0 -0
  42. package/apps/hello-world/index.html +0 -17
  43. package/apps/hello-world/package-lock.json +0 -9307
  44. package/apps/hello-world/package.json +0 -55
  45. package/apps/hello-world/src/components/feedback-form.html +0 -111
  46. package/apps/hello-world/src/components/feedback-form.ts +0 -45
  47. package/apps/hello-world/src/components/notification-center.html +0 -119
  48. package/apps/hello-world/src/components/notification-center.ts +0 -27
  49. package/apps/hello-world/src/components/stat-card.html +0 -107
  50. package/apps/hello-world/src/components/stat-card.ts +0 -33
  51. package/apps/hello-world/src/components/weather-widget.html +0 -89
  52. package/apps/hello-world/src/components/weather-widget.ts +0 -30
  53. package/apps/hello-world/src/hello-world.html +0 -48
  54. package/apps/hello-world/src/hello-world.ts +0 -17
  55. package/apps/hello-world/src/main.ts +0 -6
  56. package/apps/hello-world/src/my-app.html +0 -1
  57. package/apps/hello-world/src/my-app.ts +0 -3
  58. package/apps/hello-world/src/resource.d.ts +0 -15
  59. package/apps/hello-world/src/services/weather-service.ts +0 -15
  60. package/apps/hello-world/src/stories/feedback-form.stories.ts +0 -52
  61. package/apps/hello-world/src/stories/hello-world.stories.ts +0 -53
  62. package/apps/hello-world/src/stories/notification-center.stories.ts +0 -81
  63. package/apps/hello-world/src/stories/stat-card.stories.ts +0 -65
  64. package/apps/hello-world/src/stories/weather-widget.stories.ts +0 -57
  65. package/apps/hello-world/test/my-app.spec.ts +0 -15
  66. package/apps/hello-world/test/setup.ts +0 -29
  67. package/apps/hello-world/tsconfig.json +0 -19
  68. package/apps/hello-world/tsconfig.vitest.json +0 -11
  69. package/apps/hello-world/vite.config.ts +0 -17
  70. package/apps/hello-world/vitest.config.ts +0 -15
  71. package/apps/hello-world-webpack/.env.development +0 -0
  72. package/apps/hello-world-webpack/.storybook/main.ts +0 -14
  73. package/apps/hello-world-webpack/.storybook/preview.ts +0 -3
  74. package/apps/hello-world-webpack/.stylelintrc.json +0 -5
  75. package/apps/hello-world-webpack/README.md +0 -29
  76. package/apps/hello-world-webpack/eslint.config.mjs +0 -25
  77. package/apps/hello-world-webpack/favicon.ico +0 -0
  78. package/apps/hello-world-webpack/index.html +0 -15
  79. package/apps/hello-world-webpack/package-lock.json +0 -9853
  80. package/apps/hello-world-webpack/package.json +0 -51
  81. package/apps/hello-world-webpack/src/components/feedback-form.html +0 -111
  82. package/apps/hello-world-webpack/src/components/feedback-form.ts +0 -45
  83. package/apps/hello-world-webpack/src/components/notification-center.html +0 -119
  84. package/apps/hello-world-webpack/src/components/notification-center.ts +0 -27
  85. package/apps/hello-world-webpack/src/components/stat-card.html +0 -107
  86. package/apps/hello-world-webpack/src/components/stat-card.ts +0 -33
  87. package/apps/hello-world-webpack/src/components/weather-widget.html +0 -89
  88. package/apps/hello-world-webpack/src/components/weather-widget.ts +0 -30
  89. package/apps/hello-world-webpack/src/hello-world.html +0 -48
  90. package/apps/hello-world-webpack/src/hello-world.ts +0 -17
  91. package/apps/hello-world-webpack/src/main.ts +0 -6
  92. package/apps/hello-world-webpack/src/my-app.css +0 -3
  93. package/apps/hello-world-webpack/src/my-app.html +0 -1
  94. package/apps/hello-world-webpack/src/my-app.stories.ts +0 -15
  95. package/apps/hello-world-webpack/src/my-app.ts +0 -3
  96. package/apps/hello-world-webpack/src/resource.d.ts +0 -13
  97. package/apps/hello-world-webpack/src/services/weather-service.ts +0 -15
  98. package/apps/hello-world-webpack/src/stories/feedback-form.stories.ts +0 -52
  99. package/apps/hello-world-webpack/src/stories/hello-world.stories.ts +0 -53
  100. package/apps/hello-world-webpack/src/stories/notification-center.stories.ts +0 -81
  101. package/apps/hello-world-webpack/src/stories/stat-card.stories.ts +0 -65
  102. package/apps/hello-world-webpack/src/stories/weather-widget.stories.ts +0 -57
  103. package/apps/hello-world-webpack/tsconfig.json +0 -18
  104. package/apps/hello-world-webpack/webpack.config.js +0 -111
  105. package/dist/preview/types.js +0 -2
  106. package/dist/preview/types.js.map +0 -1
  107. package/jest.config.js +0 -9
  108. package/rollup.config.mjs +0 -50
  109. package/src/index.ts +0 -32
  110. package/src/preset.ts +0 -49
  111. package/src/preview/render.ts +0 -175
  112. package/src/preview/types.ts +0 -7
  113. package/src/preview.ts +0 -1
  114. package/src/webpack.ts +0 -21
  115. package/tsconfig.build.json +0 -5
  116. package/tsconfig.json +0 -15
package/dist/preview.js CHANGED
@@ -1,22 +1,45 @@
1
1
  import Aurelia, { CustomElement } from 'aurelia';
2
2
 
3
- // Track Aurelia apps for cleanup
4
3
  const appMap = new Map();
5
- async function teardown(element) {
6
- if (appMap.has(element)) {
7
- const app = appMap.get(element);
8
- if (app) {
9
- await app.stop();
10
- appMap.delete(element);
11
- }
4
+ function mergeStoryProps(parameters, storyArgs, storyProps) {
5
+ return { ...parameters?.args, ...storyArgs, ...storyProps };
6
+ }
7
+ function getAureliaParameters(storyContext) {
8
+ const parameters = storyContext?.parameters?.aurelia;
9
+ if (!parameters || typeof parameters !== 'object') {
10
+ return undefined;
11
+ }
12
+ return parameters;
13
+ }
14
+ function normalizeRegistrations(parameters) {
15
+ if (!parameters) {
16
+ return [];
17
+ }
18
+ const register = Array.isArray(parameters.register) ? parameters.register : [];
19
+ const components = Array.isArray(parameters.components) ? parameters.components : [];
20
+ const items = Array.isArray(parameters.items) ? parameters.items : [];
21
+ return [...register, ...components, ...items].filter(Boolean);
22
+ }
23
+ async function teardown(element, expectedApp) {
24
+ const mounted = appMap.get(element);
25
+ if (!mounted) {
26
+ return;
27
+ }
28
+ if (expectedApp && mounted.app !== expectedApp) {
29
+ return;
30
+ }
31
+ appMap.delete(element);
32
+ if (typeof mounted.app?.stop === 'function') {
33
+ await mounted.app.stop();
12
34
  }
13
35
  }
14
36
  const render = (args, context) => {
15
37
  const { id, component: Component } = context;
16
38
  if (!Component) {
17
- throw new Error(`Unable to render story ${id} as the component annotation is missing from the default export`);
39
+ const label = context.title && context.name ? `${context.title} / ${context.name}` : id;
40
+ throw new Error(`Unable to render story ${label} as the component annotation is missing from the default export`);
18
41
  }
19
- return { Component, props: args, template: '' };
42
+ return { Component, props: args };
20
43
  };
21
44
  async function renderToCanvas({ storyFn, title, name, showMain, showError, storyContext, forceRemount, }, canvasElement, bootstrapAppFn) {
22
45
  // Store reference to the original storybook root element
@@ -38,10 +61,10 @@ async function renderToCanvas({ storyFn, title, name, showMain, showError, story
38
61
  // All app instances are now tracked by the *root* element, ensuring we only ever have one per story iframe
39
62
  const appBootstrapFn = bootstrapAppFn ?? createAureliaApp;
40
63
  const { parameters, component, args } = storyContext;
41
- let app = appMap.get(rootElement);
64
+ const storyId = storyContext.id ?? `${title}--${name}`;
65
+ const mounted = appMap.get(rootElement);
66
+ let app = mounted?.app;
42
67
  const story = storyFn();
43
- // Temporary debug logging
44
- console.log(`[DEBUG] Story: ${name}, forceRemount: ${forceRemount}, hasExistingApp: ${!!app}, canvasId: ${canvasElement.className}`);
45
68
  if (!story) {
46
69
  showError({
47
70
  title: `Expecting an Aurelia component from the story: "${name}" of "${title}".`,
@@ -52,44 +75,87 @@ async function renderToCanvas({ storyFn, title, name, showMain, showError, story
52
75
  });
53
76
  return () => { };
54
77
  }
78
+ if (!component && !story.template) {
79
+ showError({
80
+ title: `Expecting a template or component from the story: "${name}" of "${title}".`,
81
+ description: `
82
+ Provide a component on the default export or return "{ template: '<custom-component></custom-component>' }" from the story.
83
+ `,
84
+ });
85
+ return () => { };
86
+ }
55
87
  showMain();
56
- if (!app || forceRemount) {
88
+ const shouldRemount = !app || forceRemount || mounted?.id !== storyId;
89
+ if (shouldRemount) {
57
90
  if (forceRemount && app) {
58
- await teardown(rootElement);
91
+ await teardown(rootElement, app);
92
+ app = undefined;
93
+ }
94
+ if (mounted?.id !== storyId && app) {
95
+ await teardown(rootElement, app);
59
96
  app = undefined;
60
97
  }
61
98
  // Clear container before mounting new app
62
99
  hostElement.innerHTML = '';
63
- const mergedProps = { ...parameters?.args, ...args, ...story.props };
64
- const aureliaApp = appBootstrapFn(story, mergedProps, hostElement, component);
100
+ const mergedProps = mergeStoryProps(parameters, args, story.props);
101
+ const aureliaApp = appBootstrapFn(story, mergedProps, hostElement, component, storyContext);
65
102
  await aureliaApp.start();
66
- appMap.set(rootElement, aureliaApp);
103
+ appMap.set(rootElement, { id: storyId, app: aureliaApp });
67
104
  app = aureliaApp;
68
105
  }
69
106
  else {
70
107
  // update existing app props
71
- const mergedProps = { ...parameters?.args, ...args, ...story.props };
108
+ const mergedProps = mergeStoryProps(parameters, args, story.props);
72
109
  if (app?.root?.controller?.viewModel) {
73
110
  Object.assign(app.root.controller.viewModel, mergedProps);
74
111
  }
75
112
  }
76
113
  // Return cleanup fn
114
+ const appForCleanup = app;
77
115
  return async () => {
78
- await teardown(rootElement);
116
+ await teardown(rootElement, appForCleanup);
79
117
  };
80
118
  }
81
- function createAureliaApp(story, args, domElement, component) {
119
+ function createAureliaApp(story, args, domElement, component, storyContext) {
82
120
  const aurelia = new Aurelia(story.container);
83
- if (story.items?.length) {
84
- aurelia.register(...story.items);
121
+ const { container } = aurelia;
122
+ const aureliaParameters = getAureliaParameters(storyContext);
123
+ const registerIfNeeded = (resource) => {
124
+ if (!resource) {
125
+ return;
126
+ }
127
+ if (CustomElement.isType(resource)) {
128
+ const definition = CustomElement.getDefinition(resource);
129
+ if (container.has(definition.key, false)) {
130
+ return;
131
+ }
132
+ }
133
+ aurelia.register(resource);
134
+ };
135
+ const registerAll = (resources) => {
136
+ if (!resources?.length) {
137
+ return;
138
+ }
139
+ for (const resource of resources) {
140
+ registerIfNeeded(resource);
141
+ }
142
+ };
143
+ if (aureliaParameters?.configureContainer && storyContext) {
144
+ aureliaParameters.configureContainer(container, storyContext);
85
145
  }
86
- if (story.components?.length) {
87
- aurelia.register(...story.components);
146
+ registerAll(normalizeRegistrations(aureliaParameters));
147
+ registerAll(story.items);
148
+ const storyComponents = (story.components ?? []).filter(Boolean);
149
+ const dedupedComponents = component
150
+ ? storyComponents.filter((entry) => entry !== component)
151
+ : storyComponents;
152
+ for (const entry of dedupedComponents) {
153
+ registerIfNeeded(entry);
88
154
  }
89
155
  let { template } = story;
90
156
  if (component) {
91
157
  template = template ?? createComponentTemplate(component, story.innerHtml);
92
- aurelia.register(component);
158
+ registerIfNeeded(component);
93
159
  }
94
160
  const App = CustomElement.define({
95
161
  name: 'sb-app',
@@ -98,6 +164,9 @@ function createAureliaApp(story, args, domElement, component) {
98
164
  }, class {
99
165
  });
100
166
  const app = Object.assign(new App(), args);
167
+ if (aureliaParameters?.configure && storyContext) {
168
+ aureliaParameters.configure(aurelia, storyContext);
169
+ }
101
170
  return aurelia.app({
102
171
  host: domElement,
103
172
  component: app,
@@ -105,10 +174,16 @@ function createAureliaApp(story, args, domElement, component) {
105
174
  }
106
175
  function createComponentTemplate(component, innerHtml) {
107
176
  const def = CustomElement.getDefinition(component);
108
- return `<${def.name} ${Object.values(def.bindables)
177
+ const bindings = Object.values(def.bindables ?? {})
109
178
  .map((bindable) => `${bindable.attribute}.bind="${bindable.name}"`)
110
- .join(' ')}>${innerHtml ?? ''}</${def.name}>`;
179
+ .join(' ');
180
+ const bindingAttributes = bindings ? ` ${bindings}` : '';
181
+ return `<${def.name}${bindingAttributes}>${innerHtml ?? ''}</${def.name}>`;
182
+ }
183
+
184
+ function defineAureliaStory(story) {
185
+ return story;
111
186
  }
112
187
 
113
- export { render, renderToCanvas };
188
+ export { defineAureliaStory, render, renderToCanvas };
114
189
  //# sourceMappingURL=preview.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview.js","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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"}
1
+ {"version":3,"file":"preview.js","sources":["../src/preview/render.ts","../src/preview/helpers.ts"],"sourcesContent":["import type { RenderContext, ArgsStoryFn } from './storybook-types';\nimport type {\n AureliaRenderer,\n AureliaStoryResult,\n AureliaParameters,\n AureliaStoryContext,\n} from './types';\nimport Aurelia, { Constructable, CustomElement } from 'aurelia';\n\ninterface MountedAureliaApp {\n id?: string;\n app: any;\n}\n\nconst appMap = new Map<HTMLElement, MountedAureliaApp>();\n\nfunction mergeStoryProps(\n parameters: { args?: Record<string, any> } | undefined,\n storyArgs: Record<string, any> | undefined,\n storyProps: Record<string, any> | undefined\n) {\n return { ...parameters?.args, ...storyArgs, ...storyProps };\n}\n\nfunction getAureliaParameters(\n storyContext?: AureliaStoryContext\n): AureliaParameters | undefined {\n const parameters = storyContext?.parameters?.aurelia;\n if (!parameters || typeof parameters !== 'object') {\n return undefined;\n }\n return parameters as AureliaParameters;\n}\n\nfunction normalizeRegistrations(\n parameters: AureliaParameters | undefined\n): unknown[] {\n if (!parameters) {\n return [];\n }\n\n const register = Array.isArray(parameters.register) ? parameters.register : [];\n const components = Array.isArray(parameters.components) ? parameters.components : [];\n const items = Array.isArray(parameters.items) ? parameters.items : [];\n\n return [...register, ...components, ...items].filter(Boolean);\n}\n\nasync function teardown(element: HTMLElement, expectedApp?: any) {\n const mounted = appMap.get(element);\n if (!mounted) {\n return;\n }\n\n if (expectedApp && mounted.app !== expectedApp) {\n return;\n }\n\n appMap.delete(element);\n\n if (typeof mounted.app?.stop === 'function') {\n await mounted.app.stop();\n }\n}\n\nexport const render: ArgsStoryFn<AureliaRenderer> = (args, context) => {\n const { id, component: Component } = context;\n \n if (!Component) {\n const label = context.title && context.name ? `${context.title} / ${context.name}` : id;\n throw new Error(\n `Unable to render story ${label} as the component annotation is missing from the default export`\n );\n }\n return { Component, props: args };\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 const storyId = storyContext.id ?? `${title}--${name}`;\n \n const mounted = appMap.get(rootElement);\n let app = mounted?.app;\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 if (!component && !story.template) {\n showError({\n title: `Expecting a template or component from the story: \"${name}\" of \"${title}\".`,\n description: `\n Provide a component on the default export or return \"{ template: '<custom-component></custom-component>' }\" from the story.\n `,\n });\n return () => {};\n }\n\n showMain();\n\n const shouldRemount = !app || forceRemount || mounted?.id !== storyId;\n\n if (shouldRemount) {\n if (forceRemount && app) {\n await teardown(rootElement, app);\n app = undefined;\n }\n if (mounted?.id !== storyId && app) {\n await teardown(rootElement, app);\n app = undefined;\n }\n\n // Clear container before mounting new app\n hostElement.innerHTML = '';\n\n const mergedProps = mergeStoryProps(parameters, args, story.props);\n\n const aureliaApp = appBootstrapFn(\n story,\n mergedProps,\n hostElement,\n component as Constructable,\n storyContext\n );\n await aureliaApp.start();\n appMap.set(rootElement, { id: storyId, app: aureliaApp });\n app = aureliaApp;\n } else {\n // update existing app props\n const mergedProps = mergeStoryProps(parameters, 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 const appForCleanup = app;\n return async () => {\n await teardown(rootElement, appForCleanup);\n };\n}\n\nexport function createAureliaApp(\n story: AureliaStoryResult,\n args: Record<string, any>,\n domElement: HTMLElement,\n component?: Constructable,\n storyContext?: AureliaStoryContext\n) {\n const aurelia = new Aurelia(story.container);\n const { container } = aurelia;\n const aureliaParameters = getAureliaParameters(storyContext);\n\n const registerIfNeeded = (resource: unknown) => {\n if (!resource) {\n return;\n }\n\n if (CustomElement.isType(resource)) {\n const definition = CustomElement.getDefinition(resource);\n if (container.has(definition.key, false)) {\n return;\n }\n }\n\n aurelia.register(resource);\n };\n\n const registerAll = (resources?: unknown[]) => {\n if (!resources?.length) {\n return;\n }\n\n for (const resource of resources) {\n registerIfNeeded(resource);\n }\n };\n\n if (aureliaParameters?.configureContainer && storyContext) {\n aureliaParameters.configureContainer(container, storyContext);\n }\n\n registerAll(normalizeRegistrations(aureliaParameters));\n registerAll(story.items);\n\n const storyComponents = (story.components ?? []).filter(Boolean);\n const dedupedComponents = component\n ? storyComponents.filter((entry) => entry !== component)\n : storyComponents;\n\n for (const entry of dedupedComponents) {\n registerIfNeeded(entry);\n }\n\n let { template } = story;\n\n if (component) {\n template = template ?? createComponentTemplate(component, story.innerHtml);\n registerIfNeeded(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 if (aureliaParameters?.configure && storyContext) {\n aureliaParameters.configure(aurelia, storyContext);\n }\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 const bindings = Object.values(def.bindables ?? {})\n .map((bindable) => `${bindable.attribute}.bind=\"${bindable.name}\"`)\n .join(' ');\n const bindingAttributes = bindings ? ` ${bindings}` : '';\n\n return `<${def.name}${bindingAttributes}>${innerHtml ?? ''}</${def.name}>`;\n}\n","import type { AureliaStoryResult } from './types';\n\nexport function defineAureliaStory<TArgs = Record<string, unknown>>(\n story: AureliaStoryResult<TArgs>\n): AureliaStoryResult<TArgs> {\n return story;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { RuleSetRule } from 'webpack';
2
+ /**
3
+ * A set of rules to be added to the webpack configuration.
4
+ * @returns
5
+ */
6
+ export declare function getRules(): RuleSetRule[];
7
+ /**
8
+ * Rsbuild/Rspack rules (avoid ts-loader; Rsbuild handles TS transpilation).
9
+ */
10
+ export declare function getRsbuildRules(): RuleSetRule[];
package/dist/webpack.js CHANGED
@@ -16,6 +16,24 @@ function getRules() {
16
16
  },
17
17
  ];
18
18
  }
19
+ /**
20
+ * Rsbuild/Rspack rules (avoid ts-loader; Rsbuild handles TS transpilation).
21
+ */
22
+ function getRsbuildRules() {
23
+ return [
24
+ {
25
+ test: /\.ts$/i,
26
+ enforce: 'pre',
27
+ use: ['@aurelia/webpack-loader'],
28
+ exclude: /node_modules/,
29
+ },
30
+ {
31
+ test: /\.html$/i,
32
+ use: '@aurelia/webpack-loader',
33
+ exclude: /node_modules/,
34
+ },
35
+ ];
36
+ }
19
37
 
20
- export { getRules };
38
+ export { getRsbuildRules, getRules };
21
39
  //# 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\n/**\n * Rsbuild/Rspack rules (avoid ts-loader; Rsbuild handles TS transpilation).\n */\nexport function getRsbuildRules(): RuleSetRule[] {\n return [\n {\n test: /\\.ts$/i,\n enforce: 'pre',\n use: ['@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;AAEA;;AAEG;SACa,eAAe,GAAA;IAC7B,OAAO;AACL,QAAA;AACE,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,CAAC,yBAAyB,CAAC;AAChC,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,10 +1,18 @@
1
1
  {
2
2
  "name": "@aurelia/storybook",
3
- "version": "2.1.0",
4
- "description": "A Storybook plugin to render Aurelia 2 components using Vite or Webpack",
3
+ "version": "2.3.0",
4
+ "description": "A Storybook plugin to render Aurelia 2 components using Vite, Webpack, or Rsbuild/Rspack",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "files": [
10
+ "dist",
11
+ "preset.js",
12
+ "README.md",
13
+ "CHANGELOG.md",
14
+ "LICENSE"
15
+ ],
8
16
  "publishConfig": {
9
17
  "access": "public"
10
18
  },
@@ -14,35 +22,87 @@
14
22
  "scripts": {
15
23
  "build": "rollup -c",
16
24
  "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly",
25
+ "changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s -r 0",
26
+ "sync:versions": "node scripts/sync-versions.cjs",
27
+ "sync:versions:check": "node scripts/sync-versions.cjs --check",
17
28
  "watch": "rollup -c -w",
18
29
  "test": "NODE_OPTIONS=--no-deprecation jest"
19
30
  },
20
31
  "peerDependencies": {
21
- "@aurelia/runtime-html": "^2.0.0-rc.0",
22
- "@aurelia/vite-plugin": "^2.0.0-rc.0",
23
- "@storybook/builder-vite": "^10.0.0",
24
- "@storybook/builder-webpack5": "^10.0.0",
25
- "aurelia": "^2.0.0-rc.0",
26
- "storybook": "^10.0.0"
32
+ "@aurelia/runtime-html": "^2.0.0-rc.1",
33
+ "@aurelia/vite-plugin": "^2.0.0-rc.1",
34
+ "@rsbuild/core": "^1.7.2 || ^2.0.0",
35
+ "@storybook/builder-vite": "^10.4.1",
36
+ "@storybook/builder-webpack5": "^10.4.1",
37
+ "aurelia": "^2.0.0-rc.1",
38
+ "storybook": "^10.4.1",
39
+ "storybook-builder-rsbuild": "^3.3.4"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "@rsbuild/core": {
43
+ "optional": true
44
+ },
45
+ "@storybook/builder-vite": {
46
+ "optional": true
47
+ },
48
+ "@storybook/builder-webpack5": {
49
+ "optional": true
50
+ },
51
+ "storybook-builder-rsbuild": {
52
+ "optional": true
53
+ }
27
54
  },
28
55
  "devDependencies": {
29
- "@aurelia/webpack-loader": "^2.0.0-rc.0",
56
+ "@aurelia/webpack-loader": "^2.0.0-rc.1",
30
57
  "@rollup/plugin-commonjs": "^28.0.6",
31
58
  "@rollup/plugin-node-resolve": "^16.0.1",
32
59
  "@rollup/plugin-typescript": "^12.1.3",
33
- "@storybook/builder-vite": "^10.0.5",
60
+ "@rsbuild/core": "^2.0.9",
61
+ "@storybook/builder-vite": "^10.4.1",
34
62
  "@types/jest": "^30.0.0",
63
+ "conventional-changelog-cli": "^5.0.0",
64
+ "conventional-changelog-conventionalcommits": "^8.0.0",
35
65
  "glob": "^11.0.3",
36
66
  "jest": "^30.0.2",
37
67
  "jest-environment-jsdom": "^30.0.2",
38
- "rollup": "^4.44.0",
39
- "storybook": "^10.0.0",
68
+ "postcss": "^8.5.15",
69
+ "rollup": "^4.61.0",
70
+ "storybook": "^10.4.1",
40
71
  "ts-jest": "^29.4.0",
41
72
  "ts-loader": "^9.5.2",
42
- "typescript": "^5.8.3"
73
+ "typescript": "^5.8.3",
74
+ "vite": "^7.3.5"
75
+ },
76
+ "overrides": {
77
+ "picomatch": "^4.0.4",
78
+ "postcss": "^8.5.15",
79
+ "rollup": "^4.61.0",
80
+ "vite": "^7.3.5"
43
81
  },
44
82
  "exports": {
45
- ".": "./dist/index.js",
46
- "./preset": "./dist/preset.js"
83
+ ".": {
84
+ "types": "./dist/index.d.ts",
85
+ "default": "./dist/index.js"
86
+ },
87
+ "./preset": {
88
+ "types": "./dist/preset.d.ts",
89
+ "default": "./dist/preset.js"
90
+ },
91
+ "./preview": {
92
+ "types": "./dist/preview.d.ts",
93
+ "default": "./dist/preview.js"
94
+ },
95
+ "./preview/types": {
96
+ "types": "./dist/preview/types.d.ts",
97
+ "default": "./dist/preview/types-runtime.js"
98
+ },
99
+ "./preview/storybook-types": {
100
+ "types": "./dist/preview/storybook-types.d.ts",
101
+ "default": "./dist/preview/storybook-types-runtime.js"
102
+ },
103
+ "./preview/helpers": {
104
+ "types": "./dist/preview/helpers.d.ts",
105
+ "default": "./dist/preview/helpers.js"
106
+ }
47
107
  }
48
108
  }
package/preset.js CHANGED
@@ -1 +1,2 @@
1
- module.exports = require('./dist/preset');
1
+ export * from './dist/preset.js';
2
+ export { default } from './dist/preset.js';
package/CONTINUITY.md DELETED
@@ -1,22 +0,0 @@
1
- Goal (incl. success criteria):
2
- - Address question about empty chunk generation during build; explain whether outputs are unnecessary and options.
3
- Constraints/Assumptions:
4
- - Use repo instructions in AGENTS.md; maintain this ledger.
5
- - Build uses Rollup per-file entries from globbed src/**/*.ts.
6
- Key decisions:
7
- - None yet for empty chunk handling.
8
- State:
9
- - Identified empty chunk comes from type-only file src/preview/types.ts.
10
- Done:
11
- - Inspected rollup config and types file to confirm empty output cause.
12
- Now:
13
- - Provide explanation and possible ways to avoid generating empty JS file.
14
- Next:
15
- - If requested, change rollup config or file layout to suppress empty chunk.
16
- Open questions (UNCONFIRMED if needed):
17
- - Should we change build config to avoid empty chunk? UNCONFIRMED.
18
- - Remove the untracked .DS_Store file? UNCONFIRMED.
19
- Working set (files/ids/commands):
20
- - CONTINUITY.md
21
- - /Users/dwayne/Code/aurelia2-storybook/rollup.config.mjs
22
- - /Users/dwayne/Code/aurelia2-storybook/src/preview/types.ts
@@ -1,49 +0,0 @@
1
- import { webpackFinal, viteFinal } from '../src/preset';
2
- import { getRules } from '../src/webpack';
3
-
4
- jest.mock('../src/webpack', () => ({
5
- getRules: jest.fn(() => [
6
- { test: /\.ts$/, use: 'ts-loader' },
7
- { test: /\.html$/, use: 'html-loader' },
8
- ]),
9
- }));
10
-
11
- describe('preset', () => {
12
- describe('webpackFinal', () => {
13
- it('should add rules to the webpack config', async () => {
14
- const config = {
15
- module: {
16
- rules: [],
17
- },
18
- };
19
- const result = await webpackFinal(config);
20
- expect(result.module.rules).toEqual(getRules());
21
- expect(getRules).toHaveBeenCalled();
22
- });
23
-
24
- it('should handle a config with no module.rules', async () => {
25
- const config = {};
26
- const result = await webpackFinal(config);
27
- expect(result).toEqual(config);
28
- });
29
-
30
- it('should handle a config with existing rules', async () => {
31
- const existingRule = { test: /\.js$/, use: 'babel-loader' };
32
- const config = {
33
- module: {
34
- rules: [existingRule],
35
- },
36
- };
37
- const result = await webpackFinal(config);
38
- expect(result.module.rules).toEqual([existingRule, ...getRules()]);
39
- });
40
- });
41
-
42
- describe('viteFinal', () => {
43
- it('should return the config unchanged', async () => {
44
- const config = { some: 'property' };
45
- const result = await viteFinal(config);
46
- expect(result).toBe(config);
47
- });
48
- });
49
- });
@@ -1,139 +0,0 @@
1
- import { render } from '../src/preview';
2
- import * as renderUtils from '../src/preview/render';
3
-
4
- jest.mock('../src/preview/render', () => ({
5
- ...jest.requireActual('../src/preview/render'),
6
- bootstrapAureliaApp: jest.fn(),
7
- }));
8
-
9
- describe('preview', () => {
10
- let bootstrapAureliaAppSpy: jest.SpyInstance;
11
- let fakeAureliaApp: { start: jest.Mock; stop: jest.Mock };
12
-
13
- beforeEach(() => {
14
- bootstrapAureliaAppSpy = jest.spyOn(renderUtils, 'bootstrapAureliaApp');
15
- fakeAureliaApp = {
16
- start: jest.fn().mockResolvedValue(undefined),
17
- stop: jest.fn().mockResolvedValue(undefined),
18
- };
19
- bootstrapAureliaAppSpy.mockReturnValue(fakeAureliaApp);
20
- document.body.innerHTML = '';
21
- });
22
-
23
- afterEach(() => {
24
- jest.clearAllMocks();
25
- });
26
-
27
- it('should return a container element', () => {
28
- const context = {
29
- storyFn: () => ({ Component: class {} }),
30
- component: class {},
31
- };
32
- const container = render({}, context);
33
- expect(container).toBeInstanceOf(HTMLElement);
34
- expect(container.tagName).toBe('DIV');
35
- });
36
-
37
- it('should call storyFn', () => {
38
- const storyFn = jest.fn(() => ({ Component: class {} }));
39
- const context = {
40
- storyFn,
41
- component: class {},
42
- };
43
- render({}, context);
44
- expect(storyFn).toHaveBeenCalledTimes(1);
45
- });
46
-
47
- it('should not bootstrap Aurelia if story has no Component or template', () => {
48
- const context = {
49
- storyFn: () => ({}),
50
- component: class {},
51
- };
52
- render({}, context);
53
- expect(bootstrapAureliaAppSpy).not.toHaveBeenCalled();
54
- });
55
-
56
- it('should bootstrap Aurelia if story has a Component', () => {
57
- const DummyComponent = class {};
58
- const context = {
59
- storyFn: () => ({ Component: DummyComponent }),
60
- component: class {},
61
- };
62
- const args = { a: 1 };
63
- const container = render(args, context);
64
- expect(bootstrapAureliaAppSpy).toHaveBeenCalledWith(
65
- { Component: DummyComponent },
66
- args,
67
- container,
68
- DummyComponent
69
- );
70
- expect(fakeAureliaApp.start).toHaveBeenCalled();
71
- });
72
-
73
- it('should bootstrap Aurelia if story has a template', () => {
74
- const template = '<div></div>';
75
- const context = {
76
- storyFn: () => ({ template }),
77
- component: class {},
78
- };
79
- const args = { a: 1 };
80
- const container = render(args, context);
81
- expect(bootstrapAureliaAppSpy).toHaveBeenCalledWith(
82
- { template },
83
- args,
84
- container,
85
- context.component
86
- );
87
- expect(fakeAureliaApp.start).toHaveBeenCalled();
88
- });
89
-
90
- it('should call cleanup for the previous story', () => {
91
- const storyFn1 = () => ({ Component: class {} });
92
- const storyFn2 = () => ({ template: 'hello' });
93
-
94
- // First render
95
- render({}, { storyFn: storyFn1, component: class {} });
96
-
97
- // Second render
98
- render({}, { storyFn: storyFn2, component: class {} });
99
-
100
- expect(fakeAureliaApp.stop).toHaveBeenCalledTimes(1);
101
- });
102
-
103
- it('should handle Aurelia start failure', async () => {
104
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
105
- const error = new Error('Failed to start');
106
- fakeAureliaApp.start.mockRejectedValue(error);
107
-
108
- const context = {
109
- storyFn: () => ({ Component: class {} }),
110
- component: class {},
111
- };
112
-
113
- render({}, context);
114
-
115
- // allow microtasks to run
116
- await new Promise(resolve => setTimeout(resolve, 0));
117
-
118
- expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to start Aurelia app:', error);
119
- consoleErrorSpy.mockRestore();
120
- });
121
-
122
- it('should handle Aurelia stop failure', async () => {
123
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
124
- const error = new Error('Failed to stop');
125
- fakeAureliaApp.stop.mockRejectedValue(error);
126
-
127
- // First render
128
- render({}, { storyFn: () => ({ Component: class {} }), component: class {} });
129
-
130
- // Second render to trigger cleanup
131
- render({}, { storyFn: () => ({ Component: class {} }), component: class {} });
132
-
133
- // allow microtasks to run
134
- await new Promise(resolve => setTimeout(resolve, 0));
135
-
136
- expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to stop Aurelia app:', error);
137
- consoleErrorSpy.mockRestore();
138
- });
139
- });