@aurelia/storybook 2.1.0 → 2.2.1
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/.github/workflows/ci.yml +61 -0
- package/.github/workflows/publish.yml +82 -0
- package/.github/workflows/storybook-preview.yml +62 -0
- package/CHANGELOG.md +5 -0
- package/README.md +180 -1
- package/__tests__/create-aurelia-app.test.ts +94 -0
- package/__tests__/preset.test.ts +32 -3
- package/__tests__/preview.test.ts +9 -131
- package/__tests__/render.test.ts +15 -26
- package/apps/hello-world/package-lock.json +404 -287
- package/apps/hello-world/package.json +10 -10
- package/apps/hello-world/src/components/notification-center.ts +2 -2
- package/apps/hello-world/src/components/stat-card.ts +12 -4
- package/apps/hello-world/src/components/weather-widget.ts +2 -1
- package/apps/hello-world/src/stories/feedback-form.stories.ts +15 -9
- package/apps/hello-world/src/stories/hello-world.stories.ts +20 -9
- package/apps/hello-world/src/stories/notification-center.stories.ts +17 -10
- package/apps/hello-world/src/stories/stat-card.stories.ts +23 -13
- package/apps/hello-world/src/stories/weather-widget.stories.ts +18 -13
- package/apps/hello-world-rsbuild/.storybook/main.ts +16 -0
- package/apps/hello-world-rsbuild/.storybook/preview.ts +1 -0
- package/apps/hello-world-rsbuild/.stylelintrc.json +5 -0
- package/apps/hello-world-rsbuild/README.md +28 -0
- package/apps/hello-world-rsbuild/eslint.config.mjs +25 -0
- package/apps/hello-world-rsbuild/favicon.ico +0 -0
- package/apps/hello-world-rsbuild/index.html +17 -0
- package/apps/hello-world-rsbuild/package-lock.json +11131 -0
- package/apps/hello-world-rsbuild/package.json +56 -0
- package/apps/hello-world-rsbuild/src/components/feedback-form.html +111 -0
- package/apps/hello-world-rsbuild/src/components/feedback-form.ts +45 -0
- package/apps/hello-world-rsbuild/src/components/notification-center.html +119 -0
- package/apps/hello-world-rsbuild/src/components/notification-center.ts +27 -0
- package/apps/hello-world-rsbuild/src/components/stat-card.html +107 -0
- package/apps/hello-world-rsbuild/src/components/stat-card.ts +41 -0
- package/apps/hello-world-rsbuild/src/components/weather-widget.html +89 -0
- package/apps/hello-world-rsbuild/src/components/weather-widget.ts +31 -0
- package/apps/hello-world-rsbuild/src/hello-world.html +48 -0
- package/apps/hello-world-rsbuild/src/hello-world.ts +17 -0
- package/apps/hello-world-rsbuild/src/main.ts +6 -0
- package/apps/hello-world-rsbuild/src/my-app.html +1 -0
- package/apps/hello-world-rsbuild/src/my-app.ts +3 -0
- package/apps/hello-world-rsbuild/src/resource.d.ts +15 -0
- package/apps/hello-world-rsbuild/src/services/weather-service.ts +15 -0
- package/apps/hello-world-rsbuild/src/stories/feedback-form.stories.ts +58 -0
- package/apps/hello-world-rsbuild/src/stories/hello-world.stories.ts +64 -0
- package/apps/hello-world-rsbuild/src/stories/notification-center.stories.ts +88 -0
- package/apps/hello-world-rsbuild/src/stories/stat-card.stories.ts +75 -0
- package/apps/hello-world-rsbuild/src/stories/weather-widget.stories.ts +62 -0
- package/apps/hello-world-rsbuild/test/my-app.spec.ts +15 -0
- package/apps/hello-world-rsbuild/test/setup.ts +29 -0
- package/apps/hello-world-rsbuild/tsconfig.json +19 -0
- package/apps/hello-world-rsbuild/tsconfig.vitest.json +11 -0
- package/apps/hello-world-rsbuild/vite.config.ts +17 -0
- package/apps/hello-world-rsbuild/vitest.config.ts +15 -0
- package/apps/hello-world-webpack/package-lock.json +239 -264
- package/apps/hello-world-webpack/package.json +8 -7
- package/apps/hello-world-webpack/src/components/notification-center.ts +2 -2
- package/apps/hello-world-webpack/src/components/stat-card.ts +12 -4
- package/apps/hello-world-webpack/src/components/weather-widget.ts +2 -1
- package/apps/hello-world-webpack/src/my-app.stories.ts +6 -4
- package/apps/hello-world-webpack/src/stories/feedback-form.stories.ts +15 -9
- package/apps/hello-world-webpack/src/stories/hello-world.stories.ts +20 -9
- package/apps/hello-world-webpack/src/stories/notification-center.stories.ts +17 -10
- package/apps/hello-world-webpack/src/stories/stat-card.stories.ts +23 -13
- package/apps/hello-world-webpack/src/stories/weather-widget.stories.ts +18 -13
- package/dist/index.d.ts +25 -0
- package/dist/index.js +68 -14
- package/dist/index.js.map +1 -1
- package/dist/preset.d.ts +21 -0
- package/dist/preset.js +46 -2
- package/dist/preset.js.map +1 -1
- package/dist/preview/helpers.d.ts +2 -0
- package/dist/preview/helpers.js +6 -0
- package/dist/preview/helpers.js.map +1 -0
- package/dist/preview/render.d.ts +7 -0
- package/dist/preview/render.js +66 -15
- package/dist/preview/render.js.map +1 -1
- package/dist/preview/storybook-types-runtime.d.ts +1 -0
- package/dist/preview/storybook-types-runtime.js +5 -0
- package/dist/preview/storybook-types-runtime.js.map +1 -0
- package/dist/preview/storybook-types.d.ts +27 -0
- package/dist/preview/types-runtime.d.ts +1 -0
- package/dist/preview/types-runtime.js +5 -0
- package/dist/preview/types-runtime.js.map +1 -0
- package/dist/preview/types.d.ts +44 -0
- package/dist/preview.d.ts +3 -0
- package/dist/preview.js +71 -16
- package/dist/preview.js.map +1 -1
- package/dist/webpack.d.ts +10 -0
- package/dist/webpack.js +19 -1
- package/dist/webpack.js.map +1 -1
- package/package.json +54 -9
- package/rollup.config.mjs +5 -3
- package/scripts/sync-versions.cjs +55 -0
- package/src/index.ts +11 -1
- package/src/preset.ts +32 -2
- package/src/preview/helpers.ts +7 -0
- package/src/preview/render.ts +98 -30
- package/src/preview/storybook-types-runtime.ts +2 -0
- package/src/preview/storybook-types.ts +34 -0
- package/src/preview/types-runtime.ts +2 -0
- package/src/preview/types.ts +57 -2
- package/src/preview.ts +11 -1
- package/src/webpack.ts +19 -0
- package/CONTINUITY.md +0 -22
- package/dist/preview/types.js +0 -2
- package/dist/preview/types.js.map +0 -1
- /package/{jest.config.js → jest.config.cjs} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout
|
|
13
|
+
uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Setup Node
|
|
16
|
+
uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 20.19.0
|
|
19
|
+
cache: npm
|
|
20
|
+
|
|
21
|
+
- name: Install root deps
|
|
22
|
+
run: npm install
|
|
23
|
+
|
|
24
|
+
- name: Verify example versions are aligned
|
|
25
|
+
run: npm run sync:versions:check
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: npm run build
|
|
29
|
+
|
|
30
|
+
- name: Build types
|
|
31
|
+
run: npm run build:types
|
|
32
|
+
|
|
33
|
+
- name: Test package
|
|
34
|
+
run: npm test
|
|
35
|
+
|
|
36
|
+
- name: Build hello-world (Vite)
|
|
37
|
+
working-directory: apps/hello-world
|
|
38
|
+
run: |
|
|
39
|
+
npm pkg set "devDependencies.@aurelia/storybook=file:../.."
|
|
40
|
+
npm install
|
|
41
|
+
npx tsc --noEmit -p tsconfig.json
|
|
42
|
+
npm run build
|
|
43
|
+
npm run build-storybook
|
|
44
|
+
|
|
45
|
+
- name: Build hello-world-webpack
|
|
46
|
+
working-directory: apps/hello-world-webpack
|
|
47
|
+
run: |
|
|
48
|
+
npm pkg set "devDependencies.@aurelia/storybook=file:../.."
|
|
49
|
+
npm install
|
|
50
|
+
npx tsc --noEmit -p tsconfig.json
|
|
51
|
+
npm run build
|
|
52
|
+
npm run build-storybook
|
|
53
|
+
|
|
54
|
+
- name: Build hello-world-rsbuild
|
|
55
|
+
working-directory: apps/hello-world-rsbuild
|
|
56
|
+
run: |
|
|
57
|
+
npm pkg set "devDependencies.@aurelia/storybook=file:../.."
|
|
58
|
+
npm install
|
|
59
|
+
npx tsc --noEmit -p tsconfig.json
|
|
60
|
+
npm run build
|
|
61
|
+
npm run build-storybook
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
description: 'Tag to publish (e.g., v2.2.1)'
|
|
11
|
+
required: true
|
|
12
|
+
type: string
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
publish:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
id-token: write
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
ref: ${{ inputs.tag || github.ref }}
|
|
26
|
+
|
|
27
|
+
- name: Setup Node
|
|
28
|
+
uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: 20.19.0
|
|
31
|
+
registry-url: https://registry.npmjs.org
|
|
32
|
+
cache: npm
|
|
33
|
+
|
|
34
|
+
- name: Install deps
|
|
35
|
+
run: npm install
|
|
36
|
+
|
|
37
|
+
- name: Verify versions aligned
|
|
38
|
+
run: npm run sync:versions:check
|
|
39
|
+
|
|
40
|
+
- name: Verify tag matches package version
|
|
41
|
+
run: |
|
|
42
|
+
TAG_INPUT="${{ inputs.tag }}"
|
|
43
|
+
if [ -n "$TAG_INPUT" ]; then
|
|
44
|
+
TAG="${TAG_INPUT#v}"
|
|
45
|
+
else
|
|
46
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
47
|
+
fi
|
|
48
|
+
VERSION="$(node -p "require('./package.json').version")"
|
|
49
|
+
if [ "$TAG" != "$VERSION" ]; then
|
|
50
|
+
echo "Tag ($TAG) does not match package.json version ($VERSION)"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Build package
|
|
55
|
+
run: npm run build
|
|
56
|
+
|
|
57
|
+
- name: Build types
|
|
58
|
+
run: npm run build:types
|
|
59
|
+
|
|
60
|
+
- name: Test package
|
|
61
|
+
run: npm test
|
|
62
|
+
|
|
63
|
+
- name: Verify changelog exists
|
|
64
|
+
run: |
|
|
65
|
+
if [ ! -s CHANGELOG.md ]; then
|
|
66
|
+
echo "CHANGELOG.md is empty. Run npm run changelog before tagging."
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
- name: Verify changelog version matches package
|
|
71
|
+
run: |
|
|
72
|
+
VERSION="$(node -p "require('./package.json').version")"
|
|
73
|
+
CHANGELOG_VERSION="$(node -e "const fs=require('fs');const m=fs.readFileSync('CHANGELOG.md','utf8').match(/## \\[(\\d+\\.\\d+\\.\\d+(?:-[^\\]]+)?)\\]/);console.log(m?m[1]:'')")"
|
|
74
|
+
if [ "$VERSION" != "$CHANGELOG_VERSION" ]; then
|
|
75
|
+
echo "CHANGELOG.md latest version ($CHANGELOG_VERSION) does not match package.json ($VERSION)"
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
- name: Publish to npm
|
|
80
|
+
run: npm publish --access public
|
|
81
|
+
env:
|
|
82
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Storybook Preview
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pages: write
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: pages
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Setup Node
|
|
27
|
+
uses: actions/setup-node@v4
|
|
28
|
+
with:
|
|
29
|
+
node-version: 20.19.0
|
|
30
|
+
cache: npm
|
|
31
|
+
|
|
32
|
+
- name: Install root deps
|
|
33
|
+
run: npm install
|
|
34
|
+
|
|
35
|
+
- name: Build package
|
|
36
|
+
run: npm run build
|
|
37
|
+
|
|
38
|
+
- name: Build Storybook (hello-world)
|
|
39
|
+
working-directory: apps/hello-world
|
|
40
|
+
run: |
|
|
41
|
+
npm pkg set "devDependencies.@aurelia/storybook=file:../.."
|
|
42
|
+
npm install
|
|
43
|
+
npm run build-storybook
|
|
44
|
+
|
|
45
|
+
- name: Configure Pages
|
|
46
|
+
uses: actions/configure-pages@v5
|
|
47
|
+
|
|
48
|
+
- name: Upload Pages artifact
|
|
49
|
+
uses: actions/upload-pages-artifact@v3
|
|
50
|
+
with:
|
|
51
|
+
path: apps/hello-world/storybook-static
|
|
52
|
+
|
|
53
|
+
deploy:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
needs: build
|
|
56
|
+
environment:
|
|
57
|
+
name: github-pages
|
|
58
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
59
|
+
steps:
|
|
60
|
+
- name: Deploy to GitHub Pages
|
|
61
|
+
id: deployment
|
|
62
|
+
uses: actions/deploy-pages@v4
|
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| Storybook | 10.x (ESM) | Tested with 10.0.5+; works with `storybook dev`/`storybook build` commands. |
|
|
12
12
|
| Aurelia | 2.0.0-beta.25+ | Uses Aurelia's `enhance()` APIs under the hood. |
|
|
13
|
-
| Bundlers | `@storybook/builder-vite` (Vite 5) · `@storybook/builder-webpack5` | Pick whichever matches your app;
|
|
13
|
+
| Bundlers | `@storybook/builder-vite` (Vite 5) · `@storybook/builder-webpack5` · `storybook-builder-rsbuild` (Rsbuild/Rspack) | Pick whichever matches your app; they share the same Aurelia preview runtime. |
|
|
14
14
|
| Node.js | ≥ 20.19.0 or ≥ 22.12.0 | Matches the engines field in `package.json` and Storybook 10's baseline.
|
|
15
15
|
|
|
16
16
|
## Requirements
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
npm install --save-dev @aurelia/storybook storybook @storybook/builder-vite
|
|
26
26
|
# or, for Webpack builds:
|
|
27
27
|
npm install --save-dev @aurelia/storybook storybook @storybook/builder-webpack5
|
|
28
|
+
# or, for Rsbuild/Rspack builds:
|
|
29
|
+
npm install --save-dev @aurelia/storybook storybook storybook-builder-rsbuild @rsbuild/core
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
Add whichever addons you need (`@storybook/addon-links`, `@storybook/addon-actions`, etc.). Essentials functionality now ships with Storybook 10 core, so most projects only add optional extras.
|
|
@@ -119,6 +121,37 @@ Add whichever addons you need (`@storybook/addon-links`, `@storybook/addon-actio
|
|
|
119
121
|
|
|
120
122
|
---
|
|
121
123
|
|
|
124
|
+
## Quick Start (Rsbuild/Rspack Builder)
|
|
125
|
+
|
|
126
|
+
1. Install `storybook-builder-rsbuild` and `@rsbuild/core`.
|
|
127
|
+
2. Create `.storybook/main.ts`:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import type { StorybookConfig } from 'storybook/internal/types';
|
|
131
|
+
|
|
132
|
+
const config: StorybookConfig = {
|
|
133
|
+
stories: ['../src/**/*.stories.@(ts|tsx|js|jsx|mdx)'],
|
|
134
|
+
addons: ['@storybook/addon-links'],
|
|
135
|
+
framework: {
|
|
136
|
+
name: '@aurelia/storybook',
|
|
137
|
+
options: {},
|
|
138
|
+
},
|
|
139
|
+
core: {
|
|
140
|
+
builder: 'storybook-builder-rsbuild',
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default config;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The Aurelia preset injects the `ts-loader` + `@aurelia/webpack-loader` rules via `rsbuildFinal`,
|
|
148
|
+
so most projects do not need extra Rsbuild configuration. If you do, add your own `rsbuildFinal`
|
|
149
|
+
and merge with `@rsbuild/core`'s `mergeRsbuildConfig`.
|
|
150
|
+
|
|
151
|
+
3. Reuse the same `.storybook/preview.ts` and `package.json` scripts as in the Vite quick start.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
122
155
|
## Writing Aurelia Stories
|
|
123
156
|
|
|
124
157
|
Story files look exactly like standard Storybook CSF stories. The framework export automatically:
|
|
@@ -178,6 +211,22 @@ export const WithCustomTemplate = {
|
|
|
178
211
|
};
|
|
179
212
|
```
|
|
180
213
|
|
|
214
|
+
### Helper for Typed Story Results
|
|
215
|
+
|
|
216
|
+
If you want stronger typing (especially for `props`), you can use the helper and types exported by the package:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { defineAureliaStory, type AureliaStoryResult } from '@aurelia/storybook';
|
|
220
|
+
|
|
221
|
+
const render = (args: { title: string }): AureliaStoryResult<{ title: string }> =>
|
|
222
|
+
defineAureliaStory({
|
|
223
|
+
template: `<my-card title.bind="title"></my-card>`,
|
|
224
|
+
props: args,
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
You can also import directly from `@aurelia/storybook/preview` or `@aurelia/storybook/preview/types` if you prefer.
|
|
229
|
+
|
|
181
230
|
### Story Result Contract
|
|
182
231
|
|
|
183
232
|
When you provide a custom `render` function, return an object with any of the following fields. The Aurelia runtime consumes them while creating the preview app:
|
|
@@ -220,6 +269,117 @@ export const WithServices = {
|
|
|
220
269
|
|
|
221
270
|
Because the Aurelia app lives for the lifetime of the story iframe, DI registrations persist until the story is torn down or Storybook forces a remount. If you need a clean state between stories, set `parameters: { forceRemount: true }` on the story or click the *Remount component* toolbar button in Storybook.
|
|
222
271
|
|
|
272
|
+
### Global Aurelia Configuration (Preview + Story Parameters)
|
|
273
|
+
|
|
274
|
+
You can register global resources/plugins and customize the DI container via Storybook parameters. The framework reads `parameters.aurelia` from the merged Storybook context (preview + component + story):
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
// .storybook/preview.ts
|
|
278
|
+
import { Registration } from 'aurelia';
|
|
279
|
+
import { CurrencyValueConverter } from '../src/resources/currency';
|
|
280
|
+
import { FeatureFlags } from '../src/services/feature-flags';
|
|
281
|
+
|
|
282
|
+
export const parameters = {
|
|
283
|
+
aurelia: {
|
|
284
|
+
register: [CurrencyValueConverter],
|
|
285
|
+
configureContainer: (container) => {
|
|
286
|
+
container.register(Registration.instance(FeatureFlags, { beta: true }));
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
You can also override or extend per story:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
export const WithOverrides = {
|
|
296
|
+
parameters: {
|
|
297
|
+
aurelia: {
|
|
298
|
+
configureContainer: (container) => {
|
|
299
|
+
container.register(Registration.instance('apiBaseUrl', 'https://staging.example.com'));
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
These hooks run when the Aurelia app is created. If you rely on different container setups per story, use `parameters: { forceRemount: true }` to ensure a fresh app instance.
|
|
307
|
+
|
|
308
|
+
#### Parameters API (Quick Reference)
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
export const parameters = {
|
|
312
|
+
aurelia: {
|
|
313
|
+
// Register global resources/plugins
|
|
314
|
+
register: [MyElement, MyValueConverter],
|
|
315
|
+
// Optional aliases for parity with story results
|
|
316
|
+
components: [MyElement],
|
|
317
|
+
items: [Registration.instance(MyService, new MyService())],
|
|
318
|
+
// Configure the DI container
|
|
319
|
+
configureContainer: (container, context) => {
|
|
320
|
+
// ...
|
|
321
|
+
},
|
|
322
|
+
// Configure the Aurelia instance
|
|
323
|
+
configure: (aurelia, context) => {
|
|
324
|
+
// ...
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Cookbook
|
|
331
|
+
|
|
332
|
+
### 1) Register global resources once
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
// .storybook/preview.ts
|
|
336
|
+
import { Registration } from 'aurelia';
|
|
337
|
+
import { CurrencyValueConverter } from '../src/resources/currency';
|
|
338
|
+
import { FeatureFlags } from '../src/services/feature-flags';
|
|
339
|
+
|
|
340
|
+
export const parameters = {
|
|
341
|
+
aurelia: {
|
|
342
|
+
register: [CurrencyValueConverter],
|
|
343
|
+
configureContainer: (container) => {
|
|
344
|
+
container.register(Registration.instance(FeatureFlags, { beta: true }));
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 2) Mock a service per story
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
import { Registration } from 'aurelia';
|
|
354
|
+
import { IWeatherService } from '../src/services/weather-service';
|
|
355
|
+
|
|
356
|
+
export const WithMockedService = {
|
|
357
|
+
render: (args) =>
|
|
358
|
+
defineAureliaStory({
|
|
359
|
+
template: `<weather-widget location.bind="location"></weather-widget>`,
|
|
360
|
+
props: args,
|
|
361
|
+
items: [
|
|
362
|
+
Registration.instance(IWeatherService, {
|
|
363
|
+
getWeather: async () => ({ location: 'Seattle', condition: 'Sunny' }),
|
|
364
|
+
}),
|
|
365
|
+
],
|
|
366
|
+
}),
|
|
367
|
+
};
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### 3) Force a clean DI container per story
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
export const CleanState = {
|
|
374
|
+
parameters: { forceRemount: true },
|
|
375
|
+
render: (args) =>
|
|
376
|
+
defineAureliaStory({
|
|
377
|
+
template: `<my-component value.bind="value"></my-component>`,
|
|
378
|
+
props: args,
|
|
379
|
+
}),
|
|
380
|
+
};
|
|
381
|
+
```
|
|
382
|
+
|
|
223
383
|
## Example Apps Inside This Repo
|
|
224
384
|
|
|
225
385
|
- `apps/hello-world` – Vite-based Aurelia starter that consumes `@aurelia/storybook`.
|
|
@@ -265,6 +425,25 @@ This repository publishes the Storybook framework itself. Helpful scripts:
|
|
|
265
425
|
|
|
266
426
|
While developing, you can link the package into one of the sample apps in `apps/` to manual-test Storybook changes end to end.
|
|
267
427
|
|
|
428
|
+
## Releases & Changelog
|
|
429
|
+
|
|
430
|
+
- Keep `CHANGELOG.md` updated for each release (use the **Unreleased** section while working).
|
|
431
|
+
- Align example app versions with the root package before tagging:
|
|
432
|
+
- `npm run sync:versions`
|
|
433
|
+
- Tag releases as `vX.Y.Z` so the publish workflow can run.
|
|
434
|
+
|
|
435
|
+
Publish flow (automated via GitHub Actions):
|
|
436
|
+
1. Update `package.json` version.
|
|
437
|
+
2. Generate `CHANGELOG.md` from conventional commits: `npm run changelog`.
|
|
438
|
+
3. Run `npm run sync:versions` and commit changes.
|
|
439
|
+
4. Create tag `vX.Y.Z` and push it.
|
|
440
|
+
|
|
441
|
+
## Troubleshooting
|
|
442
|
+
|
|
443
|
+
- **AUR0153 duplicate element registration**: ensure the same component isn't registered multiple times within the same story/container.
|
|
444
|
+
- **Args undefined during first render**: defensively handle optional args in components (e.g., fallbacks for arrays/strings).
|
|
445
|
+
- **Rsbuild `loader.loadModule is not a function`**: avoid `ts-loader` in Rsbuild/Rspack builds; use the built-in Rsbuild TS handling.
|
|
446
|
+
|
|
268
447
|
## Contributing
|
|
269
448
|
|
|
270
449
|
Bug reports, docs tweaks, and feature PRs are all welcome. Please open an issue to discuss significant changes, and spin up one of the example apps to verify the behavior you are touching.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createAureliaApp } from '../src/preview/render';
|
|
2
|
+
|
|
3
|
+
jest.mock('aurelia', () => {
|
|
4
|
+
let lastInstance: any;
|
|
5
|
+
|
|
6
|
+
class Aurelia {
|
|
7
|
+
public container: { has: jest.Mock };
|
|
8
|
+
public register = jest.fn();
|
|
9
|
+
public app = jest.fn(() => ({}));
|
|
10
|
+
|
|
11
|
+
constructor(container?: unknown) {
|
|
12
|
+
this.container = (container as any) ?? { has: jest.fn(() => false) };
|
|
13
|
+
lastInstance = this;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CustomElement = {
|
|
18
|
+
define: jest.fn((definition: unknown, Type: new () => unknown) => Type),
|
|
19
|
+
getDefinition: jest.fn(() => ({ name: 'dummy', bindables: {}, key: 'au:ce:dummy' })),
|
|
20
|
+
isType: jest.fn(() => true),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
__esModule: true,
|
|
25
|
+
default: Aurelia,
|
|
26
|
+
CustomElement,
|
|
27
|
+
__getLastInstance: () => lastInstance,
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('createAureliaApp', () => {
|
|
32
|
+
it('does not double-register the component when included in components', () => {
|
|
33
|
+
const Component = class {};
|
|
34
|
+
const host = document.createElement('div');
|
|
35
|
+
|
|
36
|
+
createAureliaApp(
|
|
37
|
+
{ template: '<dummy></dummy>', components: [Component] } as any,
|
|
38
|
+
{},
|
|
39
|
+
host,
|
|
40
|
+
Component as any
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const aurelia = (jest.requireMock('aurelia') as any).__getLastInstance();
|
|
44
|
+
const registerArgs = aurelia.register.mock.calls.flat();
|
|
45
|
+
const registrations = registerArgs.filter((entry: unknown) => entry === Component);
|
|
46
|
+
expect(registrations).toHaveLength(1);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('skips registration when the container already has the component key', () => {
|
|
50
|
+
const Component = class {};
|
|
51
|
+
const host = document.createElement('div');
|
|
52
|
+
const container = { has: jest.fn(() => true) };
|
|
53
|
+
|
|
54
|
+
createAureliaApp(
|
|
55
|
+
{ template: '<dummy></dummy>', components: [] as any, container } as any,
|
|
56
|
+
{},
|
|
57
|
+
host,
|
|
58
|
+
Component as any
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const aurelia = (jest.requireMock('aurelia') as any).__getLastInstance();
|
|
62
|
+
expect(container.has).toHaveBeenCalled();
|
|
63
|
+
expect(aurelia.register).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('applies parameters.aurelia registrations and hooks', () => {
|
|
67
|
+
const GlobalComponent = class {};
|
|
68
|
+
const host = document.createElement('div');
|
|
69
|
+
const configureContainer = jest.fn();
|
|
70
|
+
const configure = jest.fn();
|
|
71
|
+
const storyContext = {
|
|
72
|
+
parameters: {
|
|
73
|
+
aurelia: {
|
|
74
|
+
register: [GlobalComponent],
|
|
75
|
+
configureContainer,
|
|
76
|
+
configure,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
} as any;
|
|
80
|
+
|
|
81
|
+
createAureliaApp(
|
|
82
|
+
{ template: '<dummy></dummy>' } as any,
|
|
83
|
+
{},
|
|
84
|
+
host,
|
|
85
|
+
undefined,
|
|
86
|
+
storyContext
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const aurelia = (jest.requireMock('aurelia') as any).__getLastInstance();
|
|
90
|
+
expect(configureContainer).toHaveBeenCalledWith(aurelia.container, storyContext);
|
|
91
|
+
expect(aurelia.register).toHaveBeenCalledWith(GlobalComponent);
|
|
92
|
+
expect(configure).toHaveBeenCalledWith(aurelia, storyContext);
|
|
93
|
+
});
|
|
94
|
+
});
|
package/__tests__/preset.test.ts
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
import { webpackFinal, viteFinal } from '../src/preset';
|
|
2
|
-
import { getRules } from '../src/webpack';
|
|
1
|
+
import { rsbuildFinal, webpackFinal, viteFinal } from '../src/preset';
|
|
2
|
+
import { getRsbuildRules, getRules } from '../src/webpack';
|
|
3
3
|
|
|
4
4
|
jest.mock('../src/webpack', () => ({
|
|
5
5
|
getRules: jest.fn(() => [
|
|
6
6
|
{ test: /\.ts$/, use: 'ts-loader' },
|
|
7
7
|
{ test: /\.html$/, use: 'html-loader' },
|
|
8
8
|
]),
|
|
9
|
+
getRsbuildRules: jest.fn(() => [
|
|
10
|
+
{ test: /\.ts$/, use: '@aurelia/webpack-loader' },
|
|
11
|
+
{ test: /\.html$/, use: '@aurelia/webpack-loader' },
|
|
12
|
+
]),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
const mergeRsbuildConfig = jest.fn((base, extra) => ({
|
|
16
|
+
...base,
|
|
17
|
+
...extra,
|
|
18
|
+
tools: {
|
|
19
|
+
...base?.tools,
|
|
20
|
+
...extra?.tools,
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
jest.mock('@rsbuild/core', () => ({
|
|
25
|
+
mergeRsbuildConfig,
|
|
9
26
|
}));
|
|
10
27
|
|
|
11
28
|
describe('preset', () => {
|
|
@@ -46,4 +63,16 @@ describe('preset', () => {
|
|
|
46
63
|
expect(result).toBe(config);
|
|
47
64
|
});
|
|
48
65
|
});
|
|
49
|
-
|
|
66
|
+
|
|
67
|
+
describe('rsbuildFinal', () => {
|
|
68
|
+
it('should merge rsbuild config and add Aurelia rules', async () => {
|
|
69
|
+
const config = { tools: {} };
|
|
70
|
+
const result = await rsbuildFinal(config);
|
|
71
|
+
expect(mergeRsbuildConfig).toHaveBeenCalledWith(config, expect.any(Object));
|
|
72
|
+
|
|
73
|
+
const rspackConfig = { module: { rules: [] as any[] } };
|
|
74
|
+
result.tools.rspack(rspackConfig);
|
|
75
|
+
expect(rspackConfig.module.rules).toEqual(getRsbuildRules());
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|