@aurelia/storybook 2.0.0 → 2.1.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.
- package/CONTINUITY.md +22 -0
- package/README.md +210 -156
- package/apps/hello-world/.storybook/main.ts +0 -1
- package/apps/hello-world/package-lock.json +4485 -2626
- package/apps/hello-world/package.json +6 -16
- package/apps/hello-world/src/components/feedback-form.html +111 -0
- package/apps/hello-world/src/components/feedback-form.ts +45 -0
- package/apps/hello-world/src/components/notification-center.html +119 -0
- package/apps/hello-world/src/components/notification-center.ts +27 -0
- package/apps/hello-world/src/components/stat-card.html +107 -0
- package/apps/hello-world/src/components/stat-card.ts +33 -0
- package/apps/hello-world/src/components/weather-widget.html +89 -0
- package/apps/hello-world/src/components/weather-widget.ts +30 -0
- package/apps/hello-world/src/hello-world.html +44 -2
- package/apps/hello-world/src/services/weather-service.ts +15 -0
- package/apps/hello-world/src/stories/feedback-form.stories.ts +52 -0
- package/apps/hello-world/src/stories/hello-world.stories.ts +4 -5
- package/apps/hello-world/src/stories/notification-center.stories.ts +81 -0
- package/apps/hello-world/src/stories/stat-card.stories.ts +65 -0
- package/apps/hello-world/src/stories/weather-widget.stories.ts +57 -0
- package/apps/hello-world/tsconfig.json +4 -3
- package/apps/hello-world/vite.config.ts +0 -2
- package/apps/hello-world-webpack/.storybook/main.ts +0 -1
- package/apps/hello-world-webpack/package-lock.json +3646 -836
- package/apps/hello-world-webpack/package.json +2 -5
- package/apps/hello-world-webpack/src/components/feedback-form.html +111 -0
- package/apps/hello-world-webpack/src/components/feedback-form.ts +45 -0
- package/apps/hello-world-webpack/src/components/notification-center.html +119 -0
- package/apps/hello-world-webpack/src/components/notification-center.ts +27 -0
- package/apps/hello-world-webpack/src/components/stat-card.html +107 -0
- package/apps/hello-world-webpack/src/components/stat-card.ts +33 -0
- package/apps/hello-world-webpack/src/components/weather-widget.html +89 -0
- package/apps/hello-world-webpack/src/components/weather-widget.ts +30 -0
- package/apps/hello-world-webpack/src/hello-world.html +44 -2
- package/apps/hello-world-webpack/src/services/weather-service.ts +15 -0
- package/apps/hello-world-webpack/src/stories/feedback-form.stories.ts +52 -0
- package/apps/hello-world-webpack/src/stories/hello-world.stories.ts +5 -6
- package/apps/hello-world-webpack/src/stories/notification-center.stories.ts +81 -0
- package/apps/hello-world-webpack/src/stories/stat-card.stories.ts +65 -0
- package/apps/hello-world-webpack/src/stories/weather-widget.stories.ts +57 -0
- package/apps/hello-world-webpack/tsconfig.json +1 -1
- package/package.json +5 -5
- package/apps/hello-world/.yarnrc.yml +0 -2
- package/apps/hello-world-webpack/.yarnrc.yml +0 -2
- package/dist/index.mjs +0 -132
- package/dist/index.mjs.map +0 -1
- package/dist/preset.mjs +0 -60
- package/dist/preset.mjs.map +0 -1
- package/dist/preview/render.mjs +0 -114
- package/dist/preview/render.mjs.map +0 -1
- package/dist/preview/types.mjs +0 -2
- package/dist/preview/types.mjs.map +0 -1
- package/dist/preview.mjs +0 -114
- package/dist/preview.mjs.map +0 -1
- package/dist/webpack.mjs +0 -21
- package/dist/webpack.mjs.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { fn, userEvent, within } from 'storybook/test';
|
|
2
|
+
import { FeedbackForm } from '../components/feedback-form';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Dashboard/FeedbackForm',
|
|
6
|
+
component: FeedbackForm,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
render: (args) => ({
|
|
11
|
+
template: `<feedback-form topics.bind="topics"
|
|
12
|
+
submitting.bind="submitting"
|
|
13
|
+
on-submit.bind="onSubmit"></feedback-form>`,
|
|
14
|
+
props: args,
|
|
15
|
+
components: [FeedbackForm],
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
|
|
21
|
+
type Story = typeof meta;
|
|
22
|
+
|
|
23
|
+
export const DefaultForm = {
|
|
24
|
+
args: {
|
|
25
|
+
topics: ['Bug report', 'Feature request', 'General question'],
|
|
26
|
+
onSubmit: fn(),
|
|
27
|
+
submitting: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const SubmittingState = {
|
|
32
|
+
args: {
|
|
33
|
+
topics: ['Design review', 'Accessibility', 'Performance'],
|
|
34
|
+
submitting: true,
|
|
35
|
+
onSubmit: fn(),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const FillAndSubmit = {
|
|
40
|
+
args: {
|
|
41
|
+
topics: ['Beta feedback', 'Success story'],
|
|
42
|
+
onSubmit: fn(),
|
|
43
|
+
},
|
|
44
|
+
play: async ({ canvasElement }) => {
|
|
45
|
+
const canvas = within(canvasElement);
|
|
46
|
+
await userEvent.type(canvas.getByLabelText('Name'), 'Jordan');
|
|
47
|
+
await userEvent.type(canvas.getByLabelText('Email'), 'jordan@example.com');
|
|
48
|
+
await userEvent.selectOptions(canvas.getByLabelText('Topic'), 'Success story');
|
|
49
|
+
await userEvent.type(canvas.getByLabelText('Message'), 'The new timeline view is great');
|
|
50
|
+
await userEvent.click(canvas.getByRole('button', { name: /send feedback/i }));
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { HelloWorld } from '../hello-world';
|
|
2
|
-
import { fn } from '
|
|
3
|
-
import { userEvent, within } from '@storybook/test';
|
|
2
|
+
import { fn, userEvent, within } from 'storybook/test';
|
|
4
3
|
|
|
5
4
|
const meta = {
|
|
6
5
|
title: 'Example/HelloWorld',
|
|
@@ -18,14 +17,14 @@ export default meta;
|
|
|
18
17
|
|
|
19
18
|
export const DefaultHelloWorld = {
|
|
20
19
|
args: {
|
|
21
|
-
message:
|
|
20
|
+
message: 'Hello from Aurelia Storybook',
|
|
22
21
|
onIncrement: fn()
|
|
23
22
|
}
|
|
24
23
|
};
|
|
25
24
|
|
|
26
25
|
export const InteractiveHelloWorld = {
|
|
27
26
|
args: {
|
|
28
|
-
message:
|
|
27
|
+
message: 'Try clicking the button!',
|
|
29
28
|
onIncrement: fn()
|
|
30
29
|
},
|
|
31
30
|
play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
|
|
@@ -49,6 +48,6 @@ export const WithCustomTemplate = {
|
|
|
49
48
|
template: `<hello-world message.bind="message">Click me!</hello-world>`
|
|
50
49
|
}),
|
|
51
50
|
args: {
|
|
52
|
-
message:
|
|
51
|
+
message: 'This is a custom message'
|
|
53
52
|
}
|
|
54
|
-
};
|
|
53
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { fn, userEvent, within } from 'storybook/test';
|
|
2
|
+
import { NotificationCenter, NotificationItem } from '../components/notification-center';
|
|
3
|
+
|
|
4
|
+
const baseNotifications: NotificationItem[] = [
|
|
5
|
+
{
|
|
6
|
+
id: 1,
|
|
7
|
+
title: 'Build succeeded',
|
|
8
|
+
message: 'Main pipeline finished in 4m 12s.',
|
|
9
|
+
level: 'success',
|
|
10
|
+
timestamp: 'Today - 09:24',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: 2,
|
|
14
|
+
title: 'New comment',
|
|
15
|
+
message: 'Samira replied to your review on PR #512.',
|
|
16
|
+
level: 'info',
|
|
17
|
+
timestamp: 'Today - 08:51',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 3,
|
|
21
|
+
title: 'Usage warning',
|
|
22
|
+
message: 'API quota is at 85% of the monthly allocation.',
|
|
23
|
+
level: 'warning',
|
|
24
|
+
timestamp: 'Yesterday - 17:05',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 4,
|
|
28
|
+
title: 'Error spike',
|
|
29
|
+
message: 'Synthetic tests detected an uptick in 500s.',
|
|
30
|
+
level: 'error',
|
|
31
|
+
timestamp: 'Yesterday - 15:33',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const meta = {
|
|
36
|
+
title: 'Dashboard/NotificationCenter',
|
|
37
|
+
component: NotificationCenter,
|
|
38
|
+
render: (args) => ({
|
|
39
|
+
template: `<notification-center notifications.bind="notifications"
|
|
40
|
+
max-visible.bind="maxVisible"
|
|
41
|
+
on-dismiss.bind="onDismiss"
|
|
42
|
+
show-timestamp.bind="showTimestamp"></notification-center>`,
|
|
43
|
+
props: args,
|
|
44
|
+
components: [NotificationCenter],
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default meta;
|
|
49
|
+
|
|
50
|
+
type Story = typeof meta;
|
|
51
|
+
|
|
52
|
+
export const DefaultNotifications = {
|
|
53
|
+
args: {
|
|
54
|
+
notifications: baseNotifications,
|
|
55
|
+
maxVisible: 3,
|
|
56
|
+
showTimestamp: true,
|
|
57
|
+
onDismiss: fn(),
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const CompactList = {
|
|
62
|
+
args: {
|
|
63
|
+
notifications: baseNotifications.slice(0, 2),
|
|
64
|
+
maxVisible: 2,
|
|
65
|
+
onDismiss: fn(),
|
|
66
|
+
showTimestamp: false,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Interactions = {
|
|
71
|
+
args: {
|
|
72
|
+
notifications: baseNotifications,
|
|
73
|
+
maxVisible: 4,
|
|
74
|
+
onDismiss: fn(),
|
|
75
|
+
},
|
|
76
|
+
play: async ({ canvasElement }) => {
|
|
77
|
+
const canvas = within(canvasElement);
|
|
78
|
+
const dismissButtons = await canvas.findAllByRole('button', { name: /dismiss/i });
|
|
79
|
+
await userEvent.click(dismissButtons[0]);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { fn, userEvent, within } from 'storybook/test';
|
|
2
|
+
import { StatCard } from '../components/stat-card';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Dashboard/StatCard',
|
|
6
|
+
component: StatCard,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
render: (args) => ({
|
|
11
|
+
components: [StatCard],
|
|
12
|
+
template: `<stat-card title.bind="title"
|
|
13
|
+
value.bind="value"
|
|
14
|
+
unit.bind="unit"
|
|
15
|
+
change.bind="change"
|
|
16
|
+
change-copy.bind="changeCopy"
|
|
17
|
+
description.bind="description"
|
|
18
|
+
on-refresh.bind="onRefresh"></stat-card>`,
|
|
19
|
+
props: args,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
type Story = typeof meta;
|
|
26
|
+
|
|
27
|
+
export const DefaultCard = {
|
|
28
|
+
args: {
|
|
29
|
+
title: 'Active users',
|
|
30
|
+
value: 1284,
|
|
31
|
+
unit: '',
|
|
32
|
+
change: 12.5,
|
|
33
|
+
changeCopy: 'vs last week',
|
|
34
|
+
description: 'Rolling 7-day average of unique user sessions.',
|
|
35
|
+
onRefresh: fn(),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const NegativeTrend = {
|
|
40
|
+
args: {
|
|
41
|
+
title: 'NPS score',
|
|
42
|
+
value: 42,
|
|
43
|
+
change: -6.3,
|
|
44
|
+
changeCopy: 'vs previous survey',
|
|
45
|
+
description: 'Direct feedback collected from in-app survey responses.',
|
|
46
|
+
onRefresh: fn(),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const ManualRefreshDemo = {
|
|
51
|
+
args: {
|
|
52
|
+
title: 'Deploy success rate',
|
|
53
|
+
value: '99.2',
|
|
54
|
+
unit: '%',
|
|
55
|
+
change: 1.1,
|
|
56
|
+
changeCopy: 'vs last 24h',
|
|
57
|
+
description: 'Completed deploys without rollbacks.',
|
|
58
|
+
onRefresh: fn(),
|
|
59
|
+
},
|
|
60
|
+
play: async ({ canvasElement }) => {
|
|
61
|
+
const canvas = within(canvasElement);
|
|
62
|
+
const refreshButton = await canvas.findByRole('button', { name: /refresh metric/i });
|
|
63
|
+
await userEvent.click(refreshButton);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Registration } from 'aurelia';
|
|
2
|
+
import { fn, userEvent, within } from 'storybook/test';
|
|
3
|
+
import { WeatherWidget } from '../components/weather-widget';
|
|
4
|
+
import { IWeatherService, WeatherService, WeatherSummary } from '../services/weather-service';
|
|
5
|
+
|
|
6
|
+
const mockService: WeatherService = {
|
|
7
|
+
async getWeather(location: string): Promise<WeatherSummary> {
|
|
8
|
+
return {
|
|
9
|
+
location,
|
|
10
|
+
condition: location.includes('Berlin') ? 'Cloudy' : 'Sunny',
|
|
11
|
+
temperature: location.includes('Berlin') ? 16 : 24,
|
|
12
|
+
high: location.includes('Berlin') ? 18 : 27,
|
|
13
|
+
low: location.includes('Berlin') ? 11 : 19,
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const meta = {
|
|
19
|
+
title: 'Dashboard/WeatherWidget',
|
|
20
|
+
component: WeatherWidget,
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: 'centered',
|
|
23
|
+
},
|
|
24
|
+
render: (args) => ({
|
|
25
|
+
template: `<weather-widget location.bind="location"></weather-widget>`,
|
|
26
|
+
props: args,
|
|
27
|
+
components: [WeatherWidget],
|
|
28
|
+
items: [Registration.instance(IWeatherService, mockService)],
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
|
|
34
|
+
type Story = typeof meta;
|
|
35
|
+
|
|
36
|
+
export const DefaultWeather = {
|
|
37
|
+
args: {
|
|
38
|
+
location: 'Seattle, WA',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const EuropeanCity = {
|
|
43
|
+
args: {
|
|
44
|
+
location: 'Berlin, Germany',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const RefreshInteraction = {
|
|
49
|
+
args: {
|
|
50
|
+
location: 'Lisbon, Portugal',
|
|
51
|
+
},
|
|
52
|
+
play: async ({ canvasElement }) => {
|
|
53
|
+
const canvas = within(canvasElement);
|
|
54
|
+
const refreshButton = await canvas.findByRole('button', { name: /refresh/i });
|
|
55
|
+
await userEvent.click(refreshButton);
|
|
56
|
+
},
|
|
57
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurelia/storybook",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A Storybook plugin to render Aurelia 2 components using Vite or Webpack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"test": "NODE_OPTIONS=--no-deprecation jest"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
|
-
"@aurelia/runtime-html": "^2.0.0-
|
|
22
|
-
"@aurelia/vite-plugin": "^2.0.0-
|
|
21
|
+
"@aurelia/runtime-html": "^2.0.0-rc.0",
|
|
22
|
+
"@aurelia/vite-plugin": "^2.0.0-rc.0",
|
|
23
23
|
"@storybook/builder-vite": "^10.0.0",
|
|
24
24
|
"@storybook/builder-webpack5": "^10.0.0",
|
|
25
|
-
"aurelia": "^2.0.0-
|
|
25
|
+
"aurelia": "^2.0.0-rc.0",
|
|
26
26
|
"storybook": "^10.0.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@aurelia/webpack-loader": "^2.0.0-
|
|
29
|
+
"@aurelia/webpack-loader": "^2.0.0-rc.0",
|
|
30
30
|
"@rollup/plugin-commonjs": "^28.0.6",
|
|
31
31
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
32
32
|
"@rollup/plugin-typescript": "^12.1.3",
|
package/dist/index.mjs
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import Aurelia, { CustomElement } from 'aurelia';
|
|
2
|
-
|
|
3
|
-
// Track Aurelia apps for cleanup
|
|
4
|
-
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
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
async function renderToCanvas({ storyFn, title, name, showMain, showError, storyContext, forceRemount, }, canvasElement, bootstrapAppFn) {
|
|
15
|
-
// Store reference to the original storybook root element
|
|
16
|
-
const rootElement = canvasElement;
|
|
17
|
-
// Ensure we have (or create) a single container inside the root where the Aurelia app actually renders
|
|
18
|
-
let hostElement;
|
|
19
|
-
if (rootElement.id === 'storybook-root') {
|
|
20
|
-
hostElement = rootElement.querySelector('.aurelia-story-container');
|
|
21
|
-
if (!hostElement) {
|
|
22
|
-
hostElement = document.createElement('div');
|
|
23
|
-
hostElement.className = 'aurelia-story-container';
|
|
24
|
-
hostElement.style.height = '100%';
|
|
25
|
-
rootElement.appendChild(hostElement);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
hostElement = rootElement;
|
|
30
|
-
}
|
|
31
|
-
// All app instances are now tracked by the *root* element, ensuring we only ever have one per story iframe
|
|
32
|
-
const appBootstrapFn = bootstrapAppFn ?? createAureliaApp;
|
|
33
|
-
const { parameters, component, args } = storyContext;
|
|
34
|
-
let app = appMap.get(rootElement);
|
|
35
|
-
const story = storyFn();
|
|
36
|
-
// Temporary debug logging
|
|
37
|
-
console.log(`[DEBUG] Story: ${name}, forceRemount: ${forceRemount}, hasExistingApp: ${!!app}, canvasId: ${canvasElement.className}`);
|
|
38
|
-
if (!story) {
|
|
39
|
-
showError({
|
|
40
|
-
title: `Expecting an Aurelia component from the story: "${name}" of "${title}".`,
|
|
41
|
-
description: `
|
|
42
|
-
Did you forget to return the Aurelia component from the story?
|
|
43
|
-
Use "() => ({ template: '<custom-component></custom-component>' })" when defining the story.
|
|
44
|
-
`,
|
|
45
|
-
});
|
|
46
|
-
return () => { };
|
|
47
|
-
}
|
|
48
|
-
showMain();
|
|
49
|
-
if (!app || forceRemount) {
|
|
50
|
-
if (forceRemount && app) {
|
|
51
|
-
await teardown(rootElement);
|
|
52
|
-
app = undefined;
|
|
53
|
-
}
|
|
54
|
-
// Clear container before mounting new app
|
|
55
|
-
hostElement.innerHTML = '';
|
|
56
|
-
const mergedProps = { ...parameters?.args, ...args, ...story.props };
|
|
57
|
-
const aureliaApp = appBootstrapFn(story, mergedProps, hostElement, component);
|
|
58
|
-
await aureliaApp.start();
|
|
59
|
-
appMap.set(rootElement, aureliaApp);
|
|
60
|
-
app = aureliaApp;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
// update existing app props
|
|
64
|
-
const mergedProps = { ...parameters?.args, ...args, ...story.props };
|
|
65
|
-
if (app?.root?.controller?.viewModel) {
|
|
66
|
-
Object.assign(app.root.controller.viewModel, mergedProps);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// Return cleanup fn
|
|
70
|
-
return async () => {
|
|
71
|
-
await teardown(rootElement);
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function createAureliaApp(story, args, domElement, component) {
|
|
75
|
-
const aurelia = new Aurelia(story.container);
|
|
76
|
-
if (story.items?.length) {
|
|
77
|
-
aurelia.register(...story.items);
|
|
78
|
-
}
|
|
79
|
-
if (story.components?.length) {
|
|
80
|
-
aurelia.register(...story.components);
|
|
81
|
-
}
|
|
82
|
-
let { template } = story;
|
|
83
|
-
if (component) {
|
|
84
|
-
template = template ?? createComponentTemplate(component, story.innerHtml);
|
|
85
|
-
aurelia.register(component);
|
|
86
|
-
}
|
|
87
|
-
const App = CustomElement.define({
|
|
88
|
-
name: 'sb-app',
|
|
89
|
-
template,
|
|
90
|
-
containerless: true,
|
|
91
|
-
}, class {
|
|
92
|
-
});
|
|
93
|
-
const app = Object.assign(new App(), args);
|
|
94
|
-
return aurelia.app({
|
|
95
|
-
host: domElement,
|
|
96
|
-
component: app,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
function createComponentTemplate(component, innerHtml) {
|
|
100
|
-
const def = CustomElement.getDefinition(component);
|
|
101
|
-
return `<${def.name} ${Object.values(def.bindables)
|
|
102
|
-
.map((bindable) => `${bindable.attribute}.bind="${bindable.name}"`)
|
|
103
|
-
.join(' ')}>${innerHtml ?? ''}</${def.name}>`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const render = renderToCanvas;
|
|
107
|
-
// Define the framework
|
|
108
|
-
const framework = {
|
|
109
|
-
name: '@aurelia/storybook',
|
|
110
|
-
options: {}
|
|
111
|
-
};
|
|
112
|
-
// Framework configuration for Storybook
|
|
113
|
-
const frameworkOptions = {
|
|
114
|
-
builder: {
|
|
115
|
-
name: '@storybook/builder-vite',
|
|
116
|
-
options: {}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
// Export a complete framework configuration
|
|
120
|
-
const aureliaFramework = {
|
|
121
|
-
name: '@aurelia/storybook',
|
|
122
|
-
options: {},
|
|
123
|
-
builder: '@storybook/builder-vite'
|
|
124
|
-
};
|
|
125
|
-
// Provide external dependencies configuration
|
|
126
|
-
const externals = {
|
|
127
|
-
'react': 'React',
|
|
128
|
-
'react-dom': 'ReactDOM'
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export { aureliaFramework, externals, framework, frameworkOptions, render, renderToCanvas };
|
|
132
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/preview/render.ts","../src/index.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}","import type { StorybookConfig } from 'storybook/internal/types';\nimport { renderToCanvas } from './preview/render';\n\nexport { renderToCanvas };\nexport const render = renderToCanvas;\n\n// Define the framework\nexport const framework = {\n name: '@aurelia/storybook',\n options: {}\n};\n\n// Framework configuration for Storybook\nexport const frameworkOptions = {\n builder: {\n name: '@storybook/builder-vite',\n options: {}\n }\n};\n\n// Export a complete framework configuration\nexport const aureliaFramework = {\n name: '@aurelia/storybook',\n options: {},\n builder: '@storybook/builder-vite'\n};\n\n// Provide external dependencies configuration\nexport const externals = {\n 'react': 'React',\n 'react-dom': 'ReactDOM'\n};\n"],"names":[],"mappings":";;AAeA;AACA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB;AAE1C,eAAe,QAAQ,CAAC,OAAoB,EAAA;AAC1C,IAAA,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QACvB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC/B,IAAI,GAAG,EAAE;AACP,YAAA,MAAM,GAAG,CAAC,IAAI,EAAE;AAChB,YAAA,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;AAG5B;AAaO,eAAe,cAAc,CAClC,EACE,OAAO,EACP,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAY,GACmB,EACjC,aAA0B,EAC1B,cAAwC,EAAA;;IAGxC,MAAM,WAAW,GAAG,aAAa;;AAGjC,IAAA,IAAI,WAAwB;AAC5B,IAAA,IAAI,WAAW,CAAC,EAAE,KAAK,gBAAgB,EAAE;AACvC,QAAA,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC,0BAA0B,CAAgB;QAClF,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;AAC3C,YAAA,WAAW,CAAC,SAAS,GAAG,yBAAyB;AACjD,YAAA,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;AACjC,YAAA,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;;;SAEjC;QACL,WAAW,GAAG,WAAW;;;AAI3B,IAAA,MAAM,cAAc,GAAG,cAAc,IAAI,gBAAgB;IACzD,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,YAAY;IAEpD,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;AACjC,IAAA,MAAM,KAAK,GAAG,OAAO,EAAwB;;AAG7C,IAAA,OAAO,CAAC,GAAG,CAAC,CAAA,eAAA,EAAkB,IAAI,mBAAmB,YAAY,CAAA,kBAAA,EAAqB,CAAC,CAAC,GAAG,CAAA,YAAA,EAAe,aAAa,CAAC,SAAS,CAAA,CAAE,CAAC;IAEpI,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,SAAS,CAAC;AACR,YAAA,KAAK,EAAE,CAAA,gDAAA,EAAmD,IAAI,CAAA,MAAA,EAAS,KAAK,CAAA,EAAA,CAAI;AAChF,YAAA,WAAW,EAAE;;;AAGZ,MAAA,CAAA;AACF,SAAA,CAAC;AACF,QAAA,OAAO,MAAK,GAAG;;AAGjB,IAAA,QAAQ,EAAE;AAEV,IAAA,IAAI,CAAC,GAAG,IAAI,YAAY,EAAE;AACxB,QAAA,IAAI,YAAY,IAAI,GAAG,EAAE;AACvB,YAAA,MAAM,QAAQ,CAAC,WAAW,CAAC;YAC3B,GAAG,GAAG,SAAS;;;AAGjB,QAAA,WAAW,CAAC,SAAS,GAAG,EAAE;AAE1B,QAAA,MAAM,WAAW,GAAG,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE;AAEpE,QAAA,MAAM,UAAU,GAAG,cAAc,CAC/B,KAAK,EACL,WAAW,EACX,WAAW,EACX,SAA0B,CAC3B;AACD,QAAA,MAAM,UAAU,CAAC,KAAK,EAAE;AACxB,QAAA,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC;QACnC,GAAG,GAAG,UAAU;;SACX;;AAEL,QAAA,MAAM,WAAW,GAAG,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE;QACpE,IAAI,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE;AACpC,YAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,WAAW,CAAC;;;;IAK7D,OAAO,YAAW;AAChB,QAAA,MAAM,QAAQ,CAAC,WAAW,CAAC;AAC7B,KAAC;AACH;AAEM,SAAU,gBAAgB,CAC9B,KAAyB,EACzB,IAAyB,EACzB,UAAuB,EACvB,SAAyB,EAAA;IAEzB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;AAE5C,IAAA,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE;QACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;;AAGlC,IAAA,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE;QAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC;;AAGvC,IAAA,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK;IAExB,IAAI,SAAS,EAAE;QACb,QAAQ,GAAG,QAAQ,IAAI,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;AAC1E,QAAA,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;;AAG7B,IAAA,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAC9B;AACE,QAAA,IAAI,EAAE,QAAQ;QACd,QAAQ;AACR,QAAA,aAAa,EAAE,IAAI;KACpB,EACD,MAAA;AAAQ,KAAA,CACT;AAED,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC;IAE1C,OAAO,OAAO,CAAC,GAAG,CAAC;AACjB,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,SAAS,EAAE,GAAG;AACf,KAAA,CAAC;AACJ;AAEM,SAAU,uBAAuB,CACrC,SAAwB,EACxB,SAAkB,EAAA;IAElB,MAAM,GAAG,GAAG,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC;AAElD,IAAA,OAAO,CAAA,CAAA,EAAI,GAAG,CAAC,IAAI,CAAA,CAAA,EAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS;AAC/C,SAAA,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAA,EAAG,QAAQ,CAAC,SAAS,CAAA,OAAA,EAAU,QAAQ,CAAC,IAAI,GAAG;AACjE,SAAA,IAAI,CAAC,GAAG,CAAC,CAAA,CAAA,EAAI,SAAS,IAAI,EAAE,CAAA,EAAA,EAAK,GAAG,CAAC,IAAI,CAAA,CAAA,CAAG;AACjD;;AC1KO,MAAM,MAAM,GAAG;AAEtB;AACO,MAAM,SAAS,GAAG;AACvB,IAAA,IAAI,EAAE,oBAAoB;AAC1B,IAAA,OAAO,EAAE;;AAGX;AACO,MAAM,gBAAgB,GAAG;AAC9B,IAAA,OAAO,EAAE;AACP,QAAA,IAAI,EAAE,yBAAyB;AAC/B,QAAA,OAAO,EAAE;AACV;;AAGH;AACO,MAAM,gBAAgB,GAAG;AAC9B,IAAA,IAAI,EAAE,oBAAoB;AAC1B,IAAA,OAAO,EAAE,EAAE;AACX,IAAA,OAAO,EAAE;;AAGX;AACO,MAAM,SAAS,GAAG;AACvB,IAAA,OAAO,EAAE,OAAO;AAChB,IAAA,WAAW,EAAE;;;;;"}
|
package/dist/preset.mjs
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A set of rules to be added to the webpack configuration.
|
|
3
|
-
* @returns
|
|
4
|
-
*/
|
|
5
|
-
function getRules() {
|
|
6
|
-
return [
|
|
7
|
-
{
|
|
8
|
-
test: /\.ts$/i,
|
|
9
|
-
use: ['ts-loader', '@aurelia/webpack-loader'],
|
|
10
|
-
exclude: /node_modules/,
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
test: /\.html$/i,
|
|
14
|
-
use: '@aurelia/webpack-loader',
|
|
15
|
-
exclude: /node_modules/,
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// src/preset.ts
|
|
21
|
-
// Minimal preset for Storybook-Aurelia2
|
|
22
|
-
/**
|
|
23
|
-
* Optionally adjust the Vite configuration.
|
|
24
|
-
*/
|
|
25
|
-
async function viteFinal(config) {
|
|
26
|
-
// Configure Vite to properly handle dependencies
|
|
27
|
-
config.define = config.define || {};
|
|
28
|
-
config.define['process.env.NODE_ENV'] = JSON.stringify(process.env.NODE_ENV || 'development');
|
|
29
|
-
// Configure optimization deps
|
|
30
|
-
config.optimizeDeps = config.optimizeDeps || {};
|
|
31
|
-
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
|
|
32
|
-
// Only exclude Aurelia-specific dependencies that cause issues
|
|
33
|
-
const excludeList = [
|
|
34
|
-
'@aurelia/runtime-html'
|
|
35
|
-
];
|
|
36
|
-
excludeList.forEach(dep => {
|
|
37
|
-
if (!config.optimizeDeps.exclude.includes(dep)) {
|
|
38
|
-
config.optimizeDeps.exclude.push(dep);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
return config;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* A function to configure webpack.
|
|
45
|
-
* @param config
|
|
46
|
-
* @returns
|
|
47
|
-
*/
|
|
48
|
-
async function webpackFinal(config) {
|
|
49
|
-
const rules = config.module?.rules;
|
|
50
|
-
if (rules) {
|
|
51
|
-
rules.push(...getRules());
|
|
52
|
-
}
|
|
53
|
-
return config;
|
|
54
|
-
}
|
|
55
|
-
// Export a default for compatibility.
|
|
56
|
-
var preset = { viteFinal, webpackFinal };
|
|
57
|
-
const previewAnnotations = [require.resolve('./preview')];
|
|
58
|
-
|
|
59
|
-
export { preset as default, previewAnnotations, viteFinal, webpackFinal };
|
|
60
|
-
//# sourceMappingURL=preset.mjs.map
|
package/dist/preset.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preset.mjs","sources":["../src/webpack.ts","../src/preset.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","// src/preset.ts\n// Minimal preset for Storybook-Aurelia2\n\nimport { getRules } from './webpack';\n\n/**\n * Optionally adjust the Vite configuration.\n */\nexport async function viteFinal(config: any): Promise<any> {\n // Configure Vite to properly handle dependencies\n config.define = config.define || {};\n config.define['process.env.NODE_ENV'] = JSON.stringify(process.env.NODE_ENV || 'development');\n \n // Configure optimization deps\n config.optimizeDeps = config.optimizeDeps || {};\n config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];\n \n // Only exclude Aurelia-specific dependencies that cause issues\n const excludeList = [\n '@aurelia/runtime-html'\n ];\n \n excludeList.forEach(dep => {\n if (!config.optimizeDeps.exclude.includes(dep)) {\n config.optimizeDeps.exclude.push(dep);\n }\n });\n \n return config;\n}\n\n/**\n * A function to configure webpack.\n * @param config\n * @returns\n */\nexport async function webpackFinal(config: any): Promise<any> {\n const rules = config.module?.rules;\n if (rules) {\n rules.push(...getRules());\n }\n\n return config;\n}\n\n// Export a default for compatibility.\nexport default { viteFinal, webpackFinal };\n\nexport const previewAnnotations = [require.resolve('./preview')];\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;;ACpBA;AACA;AAIA;;AAEG;AACI,eAAe,SAAS,CAAC,MAAW,EAAA;;IAEvC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE;AACnC,IAAA,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;;IAG7F,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE;AAC/C,IAAA,MAAM,CAAC,YAAY,CAAC,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,IAAI,EAAE;;AAG/D,IAAA,MAAM,WAAW,GAAG;QAChB;KACH;AAED,IAAA,WAAW,CAAC,OAAO,CAAC,GAAG,IAAG;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC5C,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;;AAE7C,KAAC,CAAC;AAEF,IAAA,OAAO,MAAM;AACjB;AAEA;;;;AAIG;AACI,eAAe,YAAY,CAAC,MAAW,EAAA;AAC1C,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK;IAClC,IAAI,KAAK,EAAE;AACP,QAAA,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;;AAG7B,IAAA,OAAO,MAAM;AACjB;AAEA;AACA,aAAe,EAAE,SAAS,EAAE,YAAY,EAAE;AAEnC,MAAM,kBAAkB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;;;;"}
|
package/dist/preview/render.mjs
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import Aurelia, { CustomElement } from 'aurelia';
|
|
2
|
-
|
|
3
|
-
// Track Aurelia apps for cleanup
|
|
4
|
-
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
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
const render = (args, context) => {
|
|
15
|
-
const { id, component: Component } = context;
|
|
16
|
-
if (!Component) {
|
|
17
|
-
throw new Error(`Unable to render story ${id} as the component annotation is missing from the default export`);
|
|
18
|
-
}
|
|
19
|
-
return { Component, props: args, template: '' };
|
|
20
|
-
};
|
|
21
|
-
async function renderToCanvas({ storyFn, title, name, showMain, showError, storyContext, forceRemount, }, canvasElement, bootstrapAppFn) {
|
|
22
|
-
// Store reference to the original storybook root element
|
|
23
|
-
const rootElement = canvasElement;
|
|
24
|
-
// Ensure we have (or create) a single container inside the root where the Aurelia app actually renders
|
|
25
|
-
let hostElement;
|
|
26
|
-
if (rootElement.id === 'storybook-root') {
|
|
27
|
-
hostElement = rootElement.querySelector('.aurelia-story-container');
|
|
28
|
-
if (!hostElement) {
|
|
29
|
-
hostElement = document.createElement('div');
|
|
30
|
-
hostElement.className = 'aurelia-story-container';
|
|
31
|
-
hostElement.style.height = '100%';
|
|
32
|
-
rootElement.appendChild(hostElement);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
hostElement = rootElement;
|
|
37
|
-
}
|
|
38
|
-
// All app instances are now tracked by the *root* element, ensuring we only ever have one per story iframe
|
|
39
|
-
const appBootstrapFn = bootstrapAppFn ?? createAureliaApp;
|
|
40
|
-
const { parameters, component, args } = storyContext;
|
|
41
|
-
let app = appMap.get(rootElement);
|
|
42
|
-
const story = storyFn();
|
|
43
|
-
// Temporary debug logging
|
|
44
|
-
console.log(`[DEBUG] Story: ${name}, forceRemount: ${forceRemount}, hasExistingApp: ${!!app}, canvasId: ${canvasElement.className}`);
|
|
45
|
-
if (!story) {
|
|
46
|
-
showError({
|
|
47
|
-
title: `Expecting an Aurelia component from the story: "${name}" of "${title}".`,
|
|
48
|
-
description: `
|
|
49
|
-
Did you forget to return the Aurelia component from the story?
|
|
50
|
-
Use "() => ({ template: '<custom-component></custom-component>' })" when defining the story.
|
|
51
|
-
`,
|
|
52
|
-
});
|
|
53
|
-
return () => { };
|
|
54
|
-
}
|
|
55
|
-
showMain();
|
|
56
|
-
if (!app || forceRemount) {
|
|
57
|
-
if (forceRemount && app) {
|
|
58
|
-
await teardown(rootElement);
|
|
59
|
-
app = undefined;
|
|
60
|
-
}
|
|
61
|
-
// Clear container before mounting new app
|
|
62
|
-
hostElement.innerHTML = '';
|
|
63
|
-
const mergedProps = { ...parameters?.args, ...args, ...story.props };
|
|
64
|
-
const aureliaApp = appBootstrapFn(story, mergedProps, hostElement, component);
|
|
65
|
-
await aureliaApp.start();
|
|
66
|
-
appMap.set(rootElement, aureliaApp);
|
|
67
|
-
app = aureliaApp;
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// update existing app props
|
|
71
|
-
const mergedProps = { ...parameters?.args, ...args, ...story.props };
|
|
72
|
-
if (app?.root?.controller?.viewModel) {
|
|
73
|
-
Object.assign(app.root.controller.viewModel, mergedProps);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// Return cleanup fn
|
|
77
|
-
return async () => {
|
|
78
|
-
await teardown(rootElement);
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function createAureliaApp(story, args, domElement, component) {
|
|
82
|
-
const aurelia = new Aurelia(story.container);
|
|
83
|
-
if (story.items?.length) {
|
|
84
|
-
aurelia.register(...story.items);
|
|
85
|
-
}
|
|
86
|
-
if (story.components?.length) {
|
|
87
|
-
aurelia.register(...story.components);
|
|
88
|
-
}
|
|
89
|
-
let { template } = story;
|
|
90
|
-
if (component) {
|
|
91
|
-
template = template ?? createComponentTemplate(component, story.innerHtml);
|
|
92
|
-
aurelia.register(component);
|
|
93
|
-
}
|
|
94
|
-
const App = CustomElement.define({
|
|
95
|
-
name: 'sb-app',
|
|
96
|
-
template,
|
|
97
|
-
containerless: true,
|
|
98
|
-
}, class {
|
|
99
|
-
});
|
|
100
|
-
const app = Object.assign(new App(), args);
|
|
101
|
-
return aurelia.app({
|
|
102
|
-
host: domElement,
|
|
103
|
-
component: app,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
function createComponentTemplate(component, innerHtml) {
|
|
107
|
-
const def = CustomElement.getDefinition(component);
|
|
108
|
-
return `<${def.name} ${Object.values(def.bindables)
|
|
109
|
-
.map((bindable) => `${bindable.attribute}.bind="${bindable.name}"`)
|
|
110
|
-
.join(' ')}>${innerHtml ?? ''}</${def.name}>`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export { createAureliaApp, createComponentTemplate, render, renderToCanvas };
|
|
114
|
-
//# sourceMappingURL=render.mjs.map
|