ember-storybook 0.4.0 → 0.4.2
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/README.md +112 -41
- package/declarations/client/render.d.ts.map +1 -1
- package/dist/client/config.mjs +1 -1
- package/dist/client/index.mjs +2 -2
- package/dist/{client-DMDzc8eL.mjs → client-DdSMlQeh.mjs} +2 -2
- package/dist/{client-DMDzc8eL.mjs.map → client-DdSMlQeh.mjs.map} +1 -1
- package/dist/{config-DBYXYt5d.mjs → config-DGk6BP_3.mjs} +13 -1
- package/dist/{config-DBYXYt5d.mjs.map → config-DGk6BP_3.mjs.map} +1 -1
- package/dist/index.mjs +2 -2
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,67 +1,138 @@
|
|
|
1
1
|
# Storybook for Ember
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
With it, you can visualize different states of your UI components and develop them interactively.
|
|
3
|
+
Develop, document, and test your UI components in isolation. A workshop for your components.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
`ember-storybook` is a [Storybook](https://storybook.js.org) framework for modern Ember apps.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
- **Controls from your signatures.** Controls and Signature are generated from the component itself.
|
|
8
|
+
- **Stories, tests, docs — one source.** The same story feeds the docs page, the play function, and Vitest
|
|
9
|
+
browser tests.
|
|
10
|
+
- **Route stories included.** Templates with `{{outlet}}` are a first-class story type.
|
|
10
11
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
For more information visit: [storybook.js.org](https://storybook.js.org?ref=readme)
|
|
12
|
+
## Requirements
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
- ember v6.8
|
|
15
|
+
- storybook v10
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
You can also build a [static version](https://storybook.js.org/docs/sharing/publish-storybook?renderer=ember&ref=readme) of your Storybook and deploy it anywhere you want.
|
|
17
|
+
## Installation
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
```sh
|
|
20
|
+
pnpm add -D storybook ember-storybook
|
|
21
|
+
```
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
- [Configurations](https://storybook.js.org/docs/configure?renderer=ember&ref=readme)
|
|
24
|
-
- [Addons](https://storybook.js.org/docs/configure/user-interface/storybook-addons?renderer=ember&ref=readme)
|
|
23
|
+
## Getting Started
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
Add the two config files, then write a story next to your component.
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
alongside classic CSF. Wire up `defineMain` and `definePreview`, then build
|
|
30
|
-
stories from `preview.meta()` — story `args` are inferred from the component's
|
|
31
|
-
Ember signature:
|
|
27
|
+
**`.storybook/main.ts`**
|
|
32
28
|
|
|
33
29
|
```ts
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
import type { StorybookConfig } from 'ember-storybook';
|
|
31
|
+
|
|
32
|
+
const config: StorybookConfig = {
|
|
33
|
+
stories: ['../app/**/*.stories.g(j|t)s'],
|
|
34
|
+
framework: 'ember-storybook',
|
|
35
|
+
};
|
|
36
36
|
|
|
37
|
-
export default
|
|
38
|
-
stories: ['../**/*.stories.g(j|t)s'],
|
|
39
|
-
addons: ['@storybook/addon-docs']
|
|
40
|
-
});
|
|
37
|
+
export default config;
|
|
41
38
|
```
|
|
42
39
|
|
|
40
|
+
**`.storybook/preview.ts`**
|
|
41
|
+
|
|
43
42
|
```ts
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
import
|
|
43
|
+
import { createApp } from '../app/app';
|
|
44
|
+
|
|
45
|
+
import type { Preview } from 'ember-storybook';
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
addons: [addonDocs()],
|
|
47
|
+
const preview: Preview = {
|
|
50
48
|
parameters: {
|
|
51
|
-
ember: {
|
|
52
|
-
|
|
53
|
-
}
|
|
49
|
+
ember: {
|
|
50
|
+
app: createApp,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default preview;
|
|
54
56
|
```
|
|
55
57
|
|
|
58
|
+
An empty App is booted by default, but you can set it yourself — pass an `Application`, an
|
|
59
|
+
`ApplicationInstance`, or a factory function returning one.
|
|
60
|
+
|
|
61
|
+
**`app/components/button.stories.gts`**
|
|
62
|
+
|
|
56
63
|
```gts
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
import {
|
|
64
|
+
import Button from './button.gts';
|
|
65
|
+
|
|
66
|
+
import type { Meta, StoryObj } from 'ember-storybook';
|
|
67
|
+
|
|
68
|
+
export default {
|
|
69
|
+
title: 'Example/Button',
|
|
70
|
+
component: Button,
|
|
71
|
+
} satisfies Meta;
|
|
60
72
|
|
|
61
|
-
const
|
|
73
|
+
export const Basic: StoryObj = {
|
|
74
|
+
args: {
|
|
75
|
+
intent: 'action',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The component is rendered with every arg passed down as a named argument (`@intent`) — no render function
|
|
81
|
+
needed.
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
Add the scripts and run it:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"scripts": {
|
|
88
|
+
"storybook": "storybook dev -p 6006",
|
|
89
|
+
"build-storybook": "storybook build"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
65
92
|
```
|
|
66
93
|
|
|
67
|
-
|
|
94
|
+
```sh
|
|
95
|
+
pnpm storybook
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
Full documentation lives at **[ember-integrations.github.io/ember-storybook](https://ember-integrations.github.io/ember-storybook/)**.
|
|
101
|
+
|
|
102
|
+
Getting Started
|
|
103
|
+
|
|
104
|
+
- **[Install & First Story](https://ember-integrations.github.io/ember-storybook/getting-started)** — requirements, install, and the two config files
|
|
105
|
+
|
|
106
|
+
Guide
|
|
107
|
+
|
|
108
|
+
- **[Writing Stories](https://ember-integrations.github.io/ember-storybook/guide/writing-stories)** — args, controls, and both CSF dialects (CSF v3 and CSF Next)
|
|
109
|
+
- **[Decorators](https://ember-integrations.github.io/ember-storybook/guide/decorators)** — wrap stories with context and layout
|
|
110
|
+
- **[Route Stories](https://ember-integrations.github.io/ember-storybook/guide/route-stories)** — stories for route templates and `{{outlet}}`
|
|
111
|
+
- **[App Context & Globals](https://ember-integrations.github.io/ember-storybook/guide/context-and-globals)** — `app`, `owner`, `configure`, and `updateGlobals`
|
|
112
|
+
- **[Auto-Docs](https://ember-integrations.github.io/ember-storybook/guide/auto-docs)** — docs pages generated from your component signatures
|
|
113
|
+
- **[Testing](https://ember-integrations.github.io/ember-storybook/guide/testing)** — turn stories into Vitest browser tests and play functions
|
|
114
|
+
- **[Sharing & Deploying](https://ember-integrations.github.io/ember-storybook/guide/sharing)** — build a static Storybook and ship it anywhere
|
|
115
|
+
- **[Migrating](https://ember-integrations.github.io/ember-storybook/configuration/migration)** — moving from `@storybook/ember` to `ember-storybook`
|
|
116
|
+
|
|
117
|
+
Config
|
|
118
|
+
|
|
119
|
+
- **[`main.ts`](https://ember-integrations.github.io/ember-storybook/configuration/main-ts)** — build configuration and available addons
|
|
120
|
+
- **[Ember Parameters](https://ember-integrations.github.io/ember-storybook/configuration/ember-parameters)** — every option under `parameters.ember`
|
|
121
|
+
|
|
122
|
+
## References
|
|
123
|
+
|
|
124
|
+
### Ember
|
|
125
|
+
|
|
126
|
+
- [Ember Guides](https://guides.emberjs.com/) — the official guides
|
|
127
|
+
- [Ember API](https://api.emberjs.com/) — `Application`, `ApplicationInstance`, and the rest of the API
|
|
128
|
+
- [Glimmer components](https://guides.emberjs.com/release/components/built-in-components/)
|
|
129
|
+
|
|
130
|
+
### Storybook
|
|
131
|
+
|
|
132
|
+
- [Storybook](https://storybook.js.org) — homepage
|
|
133
|
+
- [Write stories](https://storybook.js.org/docs/writing-stories) — CSF, args, decorators
|
|
134
|
+
- [Write tests](https://storybook.js.org/docs/writing-tests) — play functions and `@storybook/addon-vitest`
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
[MIT](https://github.com/ember-integrations/ember-storybook/blob/main/LICENSE)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/client/render.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAGV,aAAa,EAGb,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAiB3E,eAAO,MAAM,MAAM,EAAE,WAAW,CAAC,aAAa,CAgB7C,CAAC;AA8MF,wBAAsB,cAAc,CAClC,EACE,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACb,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG;IAAE,YAAY,EAAE,YAAY,CAAA;CAAE,EAChE,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/client/render.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAGV,aAAa,EAGb,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAiB3E,eAAO,MAAM,MAAM,EAAE,WAAW,CAAC,aAAa,CAgB7C,CAAC;AA8MF,wBAAsB,cAAc,CAClC,EACE,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACb,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG;IAAE,YAAY,EAAE,YAAY,CAAA;CAAE,EAChE,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,uBAuL9C"}
|
package/dist/client/config.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as render, i as parameters, o as renderToCanvas, r as globalTypes, t as argTypesEnhancers } from "../config-
|
|
1
|
+
import { a as render, i as parameters, o as renderToCanvas, r as globalTypes, t as argTypesEnhancers } from "../config-DGk6BP_3.mjs";
|
|
2
2
|
export { argTypesEnhancers, globalTypes, parameters, render, renderToCanvas };
|
package/dist/client/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as setProjectAnnotations, r as definePreview, t as RenderStory } from "../client-
|
|
2
|
-
import { o as renderToCanvas } from "../config-
|
|
1
|
+
import { n as setProjectAnnotations, r as definePreview, t as RenderStory } from "../client-DdSMlQeh.mjs";
|
|
2
|
+
import { o as renderToCanvas } from "../config-DGk6BP_3.mjs";
|
|
3
3
|
import { t as OutletPlaceholder } from "../outlet-placeholder-CgO7fIDo.mjs";
|
|
4
4
|
export { OutletPlaceholder, RenderStory, definePreview, renderToCanvas, setProjectAnnotations };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as normalizeStoryResult } from "./story-result-Ds8Z5TZx.mjs";
|
|
2
|
-
import { c as templateUsesOutlet, n as config_exports, s as render_exports } from "./config-
|
|
2
|
+
import { c as templateUsesOutlet, n as config_exports, s as render_exports } from "./config-DGk6BP_3.mjs";
|
|
3
3
|
import { t as annotations_exports } from "./annotations-DRGjlECb.mjs";
|
|
4
4
|
import "./outlet-placeholder-CgO7fIDo.mjs";
|
|
5
5
|
import { definePreview } from "storybook/internal/csf";
|
|
@@ -125,4 +125,4 @@ var RenderStory = class extends Component {
|
|
|
125
125
|
//#endregion
|
|
126
126
|
export { setProjectAnnotations$1 as n, definePreview$1 as r, RenderStory as t };
|
|
127
127
|
|
|
128
|
-
//# sourceMappingURL=client-
|
|
128
|
+
//# sourceMappingURL=client-DdSMlQeh.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-
|
|
1
|
+
{"version":3,"file":"client-DdSMlQeh.mjs","names":["globalThis","STORYBOOK_ENV","definePreview","definePreviewBase","frameworkAnnotations","docsAnnotations","internalAnnotations","input","addons","setDefaultProjectAnnotations","setProjectAnnotations","originalSetProjectAnnotations","INTERNAL_DEFAULT_PROJECT_ANNOTATIONS","projectAnnotations"],"sources":["../src/client/globals.ts","../src/client/define-preview.ts","../src/client/portable-stories.ts","../src/client/render-story.gts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line unicorn/no-global-object-property-assignment\nglobalThis.STORYBOOK_ENV = 'ember';\n","import { definePreview as definePreviewBase } from 'storybook/internal/csf';\n\nimport * as frameworkAnnotations from './config';\nimport * as docsAnnotations from './docs/annotations';\n\nimport type { EmberRenderer } from './types';\nimport type { TOC } from '@ember/component/template-only';\nimport type { AddonTypes, InferTypes, Meta, Preview, PreviewAddon } from 'storybook/internal/csf';\nimport type {\n Args,\n ArgsStoryFn,\n ComponentAnnotations,\n ProjectAnnotations\n} from 'storybook/internal/types';\n\n/**\n * The component shapes whose args `preview.meta()` infers from:\n *\n * - template-only components (`TOC<S>` / `TemplateOnlyComponent<S>`)\n * - class components (`Component<S>` — matched through the instance `args`)\n *\n * Anything else (untyped components, plain templates) falls back to loose\n * args; `preview.type<{ args: … }>()` overrides the inference explicitly.\n */\ntype EmberComponent<TArgs extends Args> =\n TOC<{ Args: TArgs }> | (abstract new (...args: never[]) => { args: Readonly<TArgs> });\n\ntype Simplify<T> = { [K in keyof T]: T[K] };\n\n/**\n * The framework's own preview annotations.\n *\n * In CSF Next mode Storybook bypasses the preset `previewAnnotations` entirely\n * (the generated iframe entry uses `preview.composed` alone), so `definePreview`\n * must inject them here — the same way `@storybook/react` folds its\n * `entry-preview` modules into the base factory.\n *\n * `./config` carries the renderer (`render`, `renderToCanvas`), the `renderer:\n * 'ember'` parameter and the outlet global; `./docs/annotations` carries the\n * docgen argTypes enhancers and the source decorator. The addon-docs-dependent\n * pieces (the autodocs `Page`, the patched `DocsRenderer`) are NOT imported\n * here: they arrive through the user's own `addonDocs()` registration, which\n * the preset redirects to `./docs/addon-preview` — keeping `@storybook/addon-docs`\n * out of this module's static import graph.\n */\nconst internalAnnotations = [frameworkAnnotations, docsAnnotations];\n\n/**\n * The renderer type parameter all `definePreview` factories carry: the Ember\n * renderer merged with whatever types the registered addons contribute.\n *\n * `InferTypes` collapses to `never` when no addons are registered (the empty\n * array case poisons the whole intersection), so it is neutralized here.\n */\nexport type EmberTypes<Addons extends AddonTypes = AddonTypes> = EmberRenderer & Addons;\n\ntype InferAddonTypes<Addons extends PreviewAddon<never>[]> = [InferTypes<Addons>] extends [never]\n ? AddonTypes\n : InferTypes<Addons>;\n\n/**\n * Type-safe preview configuration for Ember (the CSF Next entry point).\n *\n * ```ts\n * // .storybook/preview.ts\n * import { definePreview } from 'ember-storybook';\n * import addonDocs from '@storybook/addon-docs';\n *\n * export default definePreview({\n * addons: [addonDocs()],\n * parameters: {\n * ember: { app: createApp },\n * },\n * });\n * ```\n */\nexport function definePreview<Addons extends PreviewAddon<never>[]>(\n input: ProjectAnnotations<EmberTypes<InferAddonTypes<Addons>>> & { addons?: Addons }\n): EmberPreview<EmberTypes<InferAddonTypes<Addons>>> {\n return definePreviewBase<EmberTypes<InferAddonTypes<Addons>>, Addons>({\n ...input,\n // After the user's addons so framework values (argTypes enhancers, the\n // source decorator, the renderer itself) win the merge — mirroring the\n // CSF3 order, where the preset appends them last.\n addons: [...(input.addons ?? []), ...internalAnnotations] as unknown as Addons\n }) as unknown as EmberPreview<EmberTypes<InferAddonTypes<Addons>>>;\n}\n\n/**\n * The CSF Next `Preview` specialized for Ember: `preview.meta()` infers story\n * args from the component's signature.\n */\nexport interface EmberPreview<TRenderer extends EmberRenderer> extends Omit<\n Preview<TRenderer>,\n 'meta' | 'type'\n> {\n /**\n * Narrows or extends the inferred annotation types, e.g. to add args that\n * the component signature cannot provide:\n *\n * ```ts\n * const meta = preview.type<{ args: { theme: 'light' | 'dark' } }>().meta({\n * component: Button,\n * });\n * ```\n */\n type<R>(): EmberPreview<TRenderer & R>;\n\n /**\n * Creates the component meta for a story file; `meta.story()` then requires\n * exactly the component's args.\n *\n * ```ts\n * const meta = preview.meta({ component: Button });\n * export const Primary = meta.story({ args: { label: 'Click me' } });\n * ```\n */\n meta<TArgs extends Args, TInput extends ComponentAnnotations<TRenderer & { args: TArgs }, TArgs>>(\n input: TInput & {\n component?: EmberComponent<TArgs>;\n render?: ArgsStoryFn<TRenderer & { args: TArgs }, TArgs>;\n }\n ): Meta<TRenderer & { args: Simplify<TArgs & NonNullable<TInput['args']>> }, TInput>;\n\n meta<TInput extends ComponentAnnotations<TRenderer, TRenderer['args']>>(\n input: TInput\n ): Meta<TRenderer, TInput>;\n}\n","import {\n setDefaultProjectAnnotations,\n setProjectAnnotations as originalSetProjectAnnotations\n} from 'storybook/preview-api';\n\nimport * as INTERNAL_DEFAULT_PROJECT_ANNOTATIONS from './render';\n\nimport type { EmberRenderer } from './types';\nimport type {\n NamedOrDefaultProjectAnnotations,\n NormalizedProjectAnnotations\n} from 'storybook/internal/types';\n\n/**\n * Function that sets the globalConfig of your storybook. The global config is the preview module of\n * your .storybook folder.\n *\n * It should be run a single time, so that your global config (e.g. decorators) is applied to your\n * stories when using `composeStories` or `composeStory`.\n *\n * Example:\n *\n * ```jsx\n * // setup-file.js\n * import { setProjectAnnotations } from '@storybook/preact';\n * import projectAnnotations from './.storybook/preview';\n *\n * setProjectAnnotations(projectAnnotations);\n * ```\n *\n * @param projectAnnotations - E.g. (import projectAnnotations from '../.storybook/preview')\n */\nexport function setProjectAnnotations(\n projectAnnotations:\n | NamedOrDefaultProjectAnnotations<EmberRenderer>\n | NamedOrDefaultProjectAnnotations<EmberRenderer>[]\n): NormalizedProjectAnnotations<EmberRenderer> {\n setDefaultProjectAnnotations(INTERNAL_DEFAULT_PROJECT_ANNOTATIONS);\n\n return originalSetProjectAnnotations(projectAnnotations);\n}\n","import Component from '@glimmer/component';\nimport { getOwner } from '@ember/owner';\nimport { renderComponent } from '@ember/renderer';\n\nimport { modifier } from 'ember-modifier';\n\nimport { templateUsesOutlet } from './outlet';\nimport { normalizeStoryResult } from './story-result';\n\ninterface RenderStorySignature {\n Args: {\n story: () => object;\n args: Record<string, unknown>;\n };\n Element: HTMLDivElement;\n}\n\nexport class RenderStory extends Component<RenderStorySignature> {\n render = modifier((element: HTMLDivElement) => {\n const story = this.args.story();\n const { component, args, route } = normalizeStoryResult(story, this.args.args);\n const owner = getOwner(this);\n\n if (route || templateUsesOutlet(component)) {\n // `{{outlet}}` is resolved from Glimmer's dynamic scope, which only a root\n // render can seed. Rendering it in here would nest a second outlet root\n // inside an already-rendering tree, so route stories are canvas-only.\n throw new Error(\n 'ember-storybook: this story renders a route template (it uses `{{outlet}}`), ' +\n 'but route stories can only be rendered by `renderToCanvas`, not through ' +\n '<RenderStory> (portable stories).'\n );\n }\n\n const result = renderComponent(component, {\n args,\n into: element,\n owner\n });\n\n return () => {\n result.destroy();\n };\n });\n\n <template>\n <div {{this.render}}></div>\n </template>\n}\n"],"mappings":";;;;;;;;;;;;AAGAA,WAAWC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC0C3B,MAAMK,sBAAsB,CAACF,gBAAsBC,mBAAe;;;;;;;;;;;;;;;;;;;;;;;;AA+BlE,SAAgBH,gBACdK,OACmD;CACnD,OAAOJ,cAA+D;EACpE,GAAGI;EAIHC,QAAQ,CAAC,GAAID,MAAMC,UAAU,CAAA,GAAK,GAAGF,mBAAmB;CAC1D,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;ACtDA,SAAgBI,wBACdG,oBAG6C;CAC7CJ,6BAA6BG,cAAoC;CAEjE,OAAOD,sBAA8BE,kBAAkB;AACzD;;;ACvBA,IAAa,cAAb,cAAiC,UAAU;CACzC,SAAS,UAAU,YAAS;EAE1B,MAAM,EAAE,WAAW,MAAM,UAAU,qBADrB,KAAK,KAAK,MACgC,GAAO,KAAK,KAAK,IAAI;EAC7E,MAAM,QAAQ,SAAS,IAAI;EAE3B,IAAI,SAAS,mBAAmB,SAAA,GAI9B,MAAM,IAAI,MACR,wLAEE;EAIN,MAAM,SAAS,gBAAgB,WAAW;GACxC;GACA,MAAM;GACN;EACF,CAAA;EAEA,aAAO;GACL,OAAO,QAAO;EAChB;CACF,CAAA;CAEA;EAAA,SAAU,+BAEV;GAAA,WAAA;GAAA,OAAA;IAAA,OAAA,KAAA,UAAA,EAAW;GAAD;EAAA,CAAA;CAAA;AACZ"}
|
|
@@ -326,6 +326,18 @@ async function renderToCanvas({ storyFn, showMain, storyContext, forceRemount },
|
|
|
326
326
|
unregister(canvasElement);
|
|
327
327
|
};
|
|
328
328
|
}
|
|
329
|
+
if (existing && !forceRemount && !route && shallowEqual(existing.args, args)) {
|
|
330
|
+
if (globalsChanged) storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);
|
|
331
|
+
contexts.set(canvasElement, {
|
|
332
|
+
...existing,
|
|
333
|
+
args,
|
|
334
|
+
globals: { ...storyContext.globals }
|
|
335
|
+
});
|
|
336
|
+
showMain();
|
|
337
|
+
return () => {
|
|
338
|
+
unregister(canvasElement);
|
|
339
|
+
};
|
|
340
|
+
}
|
|
329
341
|
const canReuseApp = existing !== void 0 && !forceRemount && Boolean(existing.outletView) === Boolean(route);
|
|
330
342
|
if (isEmberBelow(6, 12)) {
|
|
331
343
|
if (existing) unregister(canvasElement);
|
|
@@ -401,4 +413,4 @@ const argTypesEnhancers = [enhanceArgTypes];
|
|
|
401
413
|
//#endregion
|
|
402
414
|
export { render as a, templateUsesOutlet as c, parameters as i, config_exports as n, renderToCanvas as o, globalTypes as r, render_exports as s, argTypesEnhancers as t };
|
|
403
415
|
|
|
404
|
-
//# sourceMappingURL=config-
|
|
416
|
+
//# sourceMappingURL=config-DGk6BP_3.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-DBYXYt5d.mjs","names":["getComponentTemplate","renderSettled","run","DEFAULT_OUTLET_NAME","resolveOutletStub","route","mode","placeholder","outlet","template","undefined","OUTLET_KEYWORD","asTemplateFactory","component","templateUsesOutlet","factory","block","parsedLayout","Array","isArray","includes","mainOutlet","child","main","buildChildRenderState","stub","owner","render","name","model","controller","outlets","buildRouteOutletState","args","storyName","createOutletView","container","state","element","factoryFor","Error","view","create","environment","lookup","application","setOutletState","appendTo","mountOutletView","updateOutletView","Application","ApplicationInstance","destroy","renderComponent","VERSION","OUTLET_GLOBAL_KEY","buildRouteOutletState","mountOutletView","resolveOutletStub","templateUsesOutlet","updateOutletView","createAppResolver","normalizeStoryResult","isEmberBelow","major","minor","maj","min","split","map","Number","render","args","context","id","component","ember","parameters","route","Error","shallowEqual","a","b","aKeys","Object","keys","bKeys","length","every","key","hasOwn","is","withoutOutletGlobal","globals","fromEntries","entries","filter","relevantGlobals","contexts","Map","DEFAULT_ROUTE","freeze","teardownMount","renderer","mount","remove","loadPlaceholderStub","OutletPlaceholder","name","template","routeOutletState","storyName","application","outlet","mode","placeholder","owner","mountStory","into","outletView","resolveAppOption","applicationInstance","initApp","appOption","opts","bootApp","storyContext","canvasElement","app","options","toLowerCase","includes","join","rootElement","obj","unregister","register","configure","boot","updateGlobals","error","renderToCanvas","storyFn","showMain","forceRemount","element","get","delete","storyResult","routeFromStory","undefined","existing","previousGlobals","currentGlobals","globalsChanged","set","canReuseApp","Boolean","document","createElement","append","mounted","has","enhanceArgTypes","OUTLET_GLOBAL_KEY","render","renderToCanvas","parameters","renderer","docs","story","inline","globalTypes","description","defaultValue","argTypesEnhancers"],"sources":["../src/client/outlet.ts","../src/client/render.ts","../src/client/config.ts"],"sourcesContent":["import { getComponentTemplate } from '@ember/component';\nimport { renderSettled } from '@ember/renderer';\nimport { run } from '@ember/runloop';\n\nimport type { OutletMode, OutletStub, RouteParameters } from './types';\nimport type ApplicationInstance from '@ember/application/instance';\n\n/**\n * What Ember's outlet hands a route template. A route template is *not* a\n * component story: it receives exactly `@model` and `@controller`, because that\n * is all `{{outlet}}` passes down (`OUTLET_COMPONENT_TEMPLATE` in ember-source).\n */\nexport interface OutletRenderState {\n owner: object;\n name: string;\n controller: unknown;\n model: unknown;\n template: object;\n}\n\n/**\n * Mirrors ember-source's internal `OutletState`. The shape is structural, not\n * nominal, so a plain object is accepted by `setOutletState`; the leaf's\n * `outlets.main` is what a nested `{{outlet}}` reads.\n */\nexport interface OutletState {\n render: OutletRenderState;\n outlets: { main: OutletState | undefined };\n}\n\nexport interface RouteStoryInput {\n /** The route template — the story's `component`. */\n template: object;\n /** `parameters.ember.route`. */\n route: RouteParameters;\n /**\n * The resolved stub for `{{outlet}}` — see {@link resolveOutletStub}.\n * `undefined` leaves the outlet as a hole.\n */\n outlet?: OutletStub;\n /** Final (decorated) story args; `model`/`controller` feed the route. */\n args: Record<string, unknown>;\n /** Story name, used when `route.name` is not given. */\n storyName: string;\n /** The booted app instance the route renders under. */\n owner: object;\n}\n\nconst DEFAULT_OUTLET_NAME = 'outlet';\n\nexport interface OutletResolveInput {\n /** `parameters.ember.route` of the story being rendered. */\n route: RouteParameters;\n /** Value of the `outlet` global (see `src/outlet-key.ts`), if any. */\n mode?: OutletMode;\n /**\n * Produces the stub rendered when the global asks for a visible placeholder.\n * Called lazily (and so may be an async chunk load) and only when needed;\n * injected so this module stays free of Ember-owned template components.\n */\n placeholder: () => OutletStub | Promise<OutletStub>;\n}\n\n/**\n * Decides what `{{outlet}}` renders.\n *\n * An explicit `route.outlet` is author intent and always wins, so a story stays\n * deterministic no matter how the toolbar is set. Otherwise the global decides:\n * `placeholder` renders the injected marker, anything else leaves a hole.\n */\nexport async function resolveOutletStub({\n route,\n mode,\n placeholder\n}: OutletResolveInput): Promise<OutletStub | undefined> {\n if (route.outlet?.template) {\n return route.outlet;\n }\n\n return mode === 'placeholder' ? await placeholder() : undefined;\n}\n\n/**\n * The name `{{outlet}}` compiles to: the built-in keyword helper\n * `{{component (-outlet)}}` (see ember-source's `transform-wrap-mount-and-outlet`).\n */\nconst OUTLET_KEYWORD = '-outlet';\n\n/**\n * The ownerless template a template factory hands out, reduced to the one\n * intimate API we read. `parsedLayout` is deliberately absent from Ember's\n * public types (ember-source keeps it \"because some addons use these intimate\n * APIs\"), so the shape is declared here rather than imported.\n */\ninterface ParsedTemplate {\n parsedLayout?: { block?: unknown };\n}\n\n/**\n * Story components are normally classes or template-only components (both\n * reachable via `getComponentTemplate`); a raw `createTemplateFactory` result\n * used directly as the component is only recognizable by its `__meta` marker.\n */\nfunction asTemplateFactory(\n component: object\n): ((owner?: unknown) => ParsedTemplate | undefined) | undefined {\n return typeof component === 'function' && '__meta' in component\n ? (component as unknown as (owner?: unknown) => ParsedTemplate | undefined)\n : undefined;\n}\n\n/**\n * Whether the component's *own* template references `{{outlet}}` — i.e. it is a\n * route template, which is how an unannotated route-story is recognized (#62).\n *\n * A template factory caches a per-owner (plus ownerless) `TemplateImpl`; its\n * `parsedLayout.block` is the parsed wire-format tuple\n * `[statements, locals, upvars]`. Free names — every helper/keyword the\n * template resolves, from the whole template including nested blocks — live\n * exactly once in `upvars`, so checking that slot cannot mistake a string\n * literal `\"-outlet\"` used as an argument for a real outlet.\n */\nexport function templateUsesOutlet(component: object): boolean {\n const factory = getComponentTemplate(component) ?? asTemplateFactory(component);\n\n if (!factory) {\n return false;\n }\n\n // Calling the factory with no owner returns the memoized ownerless template —\n // pure data: no owner, no compilation, no side effects on later owner renders.\n const template = (factory as unknown as (owner?: unknown) => ParsedTemplate | undefined)(\n undefined\n );\n const block = template?.parsedLayout?.block;\n\n return (\n Array.isArray(block) &&\n Array.isArray(block[2]) &&\n (block[2] as unknown[]).includes(OUTLET_KEYWORD)\n );\n}\n\n// Ember has no named outlets any more: every `{{outlet}}` is the \"main\" one.\nfunction mainOutlet(child: OutletState | undefined): OutletState['outlets'] {\n return { main: child };\n}\n\nfunction buildChildRenderState(stub: OutletStub, owner: object): OutletState {\n return {\n render: {\n owner,\n name: stub.name ?? DEFAULT_OUTLET_NAME,\n template: stub.template as object,\n model: stub.model,\n controller: stub.controller\n },\n // One level only: a stubbed child route is a leaf, so a `{{outlet}}` inside\n // it renders a hole as well.\n outlets: mainOutlet(undefined)\n };\n}\n\n/**\n * Builds the `OutletState` for a route story.\n *\n * `{{outlet}}` reads its child from Glimmer's *dynamic scope*, which\n * `renderComponent` never populates — so route templates are rendered through\n * Ember's own outlet root instead, and this is the state handed to it. Leaving\n * `outlets.main` undefined is what makes `{{outlet}}` render a hole.\n */\nexport function buildRouteOutletState({\n template,\n route,\n outlet,\n args,\n storyName,\n owner\n}: RouteStoryInput): OutletState {\n const child = outlet?.template ? buildChildRenderState(outlet, owner) : undefined;\n\n return {\n render: {\n owner,\n name: route.name ?? storyName,\n template,\n model: route.model ?? args.model,\n controller: route.controller ?? args.controller\n },\n outlets: mainOutlet(child)\n };\n}\n\n/**\n * Ember's `OutletView` (the router's top-level view), reduced to the surface\n * this module drives. It is only reachable through the container, so the type is\n * declared here rather than imported from `@ember/-internals`.\n */\nexport interface OutletView {\n appendTo(target: HTMLElement): void;\n setOutletState(state: OutletState): void;\n}\n\ninterface OutletViewFactory {\n create(options: Record<string, unknown>): OutletView;\n}\n\n/**\n * The private container entries backing Ember's outlet root — the very full\n * names `Router._setOutlets()` uses. Casting through this interface keeps the\n * unsound lookups in one place instead of spread across the renderer.\n */\ninterface OutletContainer {\n factoryFor(fullName: string): OutletViewFactory | undefined;\n lookup(fullName: string): unknown;\n}\n\n/**\n * `{{outlet}}` compiles to Ember's built-in `-outlet` keyword helper, which reads\n * its child from Glimmer's *dynamic scope*. `renderComponent` starts that scope\n * empty, so a route template rendered as a plain component crashes. Route stories\n * are therefore rendered through the same outlet root `Router._setOutlets()` uses\n * — reached by container name, never imported.\n */\nfunction createOutletView(\n container: OutletContainer,\n state: OutletState,\n element: HTMLElement\n): OutletView {\n const factory = container.factoryFor('view:-outlet');\n\n if (!factory) {\n throw new Error(\n 'ember-storybook: this story sets `parameters.ember.route`, but `view:-outlet` ' +\n 'is not registered on this Ember build, so {{outlet}} cannot be rendered. ' +\n \"Route stories render through Ember's own outlet root, which the router \" +\n '(`Router._setOutlets()`) uses as well.'\n );\n }\n\n const view = factory.create({\n environment: container.lookup('-environment:main'),\n application: container.lookup('application:main'),\n // The outlet root renders `{{outlet}}` itself; the story's route template\n // arrives through the state below, as `outlets.main`.\n template: container.lookup('template:-outlet')\n });\n\n view.setOutletState(state);\n\n // `appendTo` schedules on the `render` queue, so flush the run loop to render.\n run(() => {\n view.appendTo(element);\n });\n\n return view;\n}\n\n/**\n * Renders `state` into `element` through Ember's outlet root and waits for the\n * render to settle.\n */\nexport async function mountOutletView(\n application: ApplicationInstance,\n state: OutletState,\n element: HTMLElement\n): Promise<OutletView> {\n const view = createOutletView(application as unknown as OutletContainer, state, element);\n\n await renderSettled();\n\n return view;\n}\n\n/**\n * Swaps what the outlet renders, in place. This is how the router updates a live\n * route tree, so arg changes do not tear the route's components down.\n */\nexport async function updateOutletView(view: OutletView, state: OutletState): Promise<void> {\n view.setOutletState(state);\n await renderSettled();\n}\n","import Application from '@ember/application';\nimport ApplicationInstance from '@ember/application/instance';\nimport { destroy } from '@ember/destroyable';\nimport { renderComponent } from '@ember/renderer';\nimport { VERSION } from '@ember/version';\n\nimport { OUTLET_GLOBAL_KEY } from '../outlet-key';\nimport {\n buildRouteOutletState,\n mountOutletView,\n resolveOutletStub,\n templateUsesOutlet,\n updateOutletView\n} from './outlet';\nimport { createAppResolver, type EmberStoryResult, normalizeStoryResult } from './story-result';\n\nimport type { OutletView } from './outlet';\nimport type {\n AppParamater,\n EmberGlobals,\n EmberRenderer,\n OutletStub,\n RouteParameters,\n StoryContext\n} from './types';\nimport type { RenderResult } from '@ember/-internals/glimmer/lib/renderer';\nimport type { ArgsStoryFn, RenderContext } from 'storybook/internal/types';\n\ntype Args = Record<string, unknown>;\n\n// ember-source < 6.12 built a brand-new `BaseRenderer` (EvaluationContext) on\n// every `renderComponent` call and had no per-owner renderer cache. Re-rendering\n// an already-rendered owner therefore produced multiple live EvaluationContexts\n// that corrupted glimmer's shared opcode table, crashing with\n// \"Cannot read properties of null (reading 'syscall')\". 6.12+ added that cache\n// (`RENDERER_CACHE` keyed by owner), so reusing an app across renders is only\n// safe from 6.12 onward.\nfunction isEmberBelow(major: number, minor: number): boolean {\n const [maj, min] = VERSION.split('.').map(Number);\n\n return maj < major || (maj === major && min < minor);\n}\n\nexport const render: ArgsStoryFn<EmberRenderer> = (args, context): EmberStoryResult => {\n const { id, component } = context;\n // `ArgsStoryFn`'s context types `parameters` loosely; the framework's own\n // `StoryContext` carries the typed `ember` bag.\n const { ember } = context.parameters as StoryContext['parameters'];\n const route = ember?.route;\n\n if (typeof component === 'function' || typeof component === 'object') {\n // `route` is reported back like `args` are: `<RenderStory>` gets nothing but\n // the story result, and it needs to know a story is a route story.\n return { component, args, route };\n }\n\n throw new Error(\n `Unable to render story ${id} as the component annotation is missing from the default export`\n );\n};\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n return (\n aKeys.length === bKeys.length &&\n aKeys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]))\n );\n}\n\nconst withoutOutletGlobal = (globals: Record<string, unknown>) =>\n Object.fromEntries(Object.entries(globals).filter(([key]) => key !== OUTLET_GLOBAL_KEY));\n\n/**\n * Globals the renderer actually reacts to.\n *\n * The outlet menu only concerns route stories, so for a plain component story its\n * value is stripped: toggling \"Ember\" would otherwise count as a globals change\n * and needlessly remount (throwing away the component's state).\n */\nfunction relevantGlobals(\n route: RouteParameters | undefined,\n globals: Record<string, unknown>\n): Record<string, unknown> {\n return route ? globals : withoutOutletGlobal(globals);\n}\n\ntype RenderContextCache = {\n application: ApplicationInstance;\n mount: HTMLElement;\n args: Args;\n globals: Record<string, unknown>;\n // A story is mounted either as a plain component (`renderer`) or, for route\n // templates, through Ember's outlet root (`outletView`) — never both.\n renderer?: RenderResult;\n outletView?: OutletView;\n};\n\nconst contexts = new Map<EmberRenderer['canvasElement'], RenderContextCache>();\n\n/**\n * Route parameters assumed for a story whose template references `{{outlet}}`\n * but that never set `parameters.ember.route` (#62). Frozen and module-level so\n * the identity is stable across renders of the same story.\n */\nconst DEFAULT_ROUTE: RouteParameters = Object.freeze({});\n\n/**\n * Tears the mounted story down, leaving the booted app alone so it can be\n * reused.\n *\n * Route stories are deliberately not cleaned up here: the outlet root is dropped\n * by destroying the app (which clears *and deregisters* its roots), and\n * `Renderer.cleanupRootFor()` would empty the root list without deregistering —\n * leaving the renderer in the global set so the next append would assert \"Cannot\n * register the same renderer twice\".\n */\nfunction teardownMount(context: RenderContextCache) {\n context.renderer?.destroy();\n context.mount.remove();\n}\n\n/**\n * The stub rendered when the toolbar asks for a visible placeholder.\n *\n * Loaded on demand rather than imported: folding the compiled template into the\n * boot chunk makes the bundler emit a `node:module` `createRequire` shim into it,\n * which throws in the browser and takes `renderToCanvas` — and with it every\n * story — down with it.\n */\nasync function loadPlaceholderStub(): Promise<OutletStub> {\n // Typed explicitly: the `.gts` module has no declaration reachable from here.\n const { OutletPlaceholder } = (await import('./outlet-placeholder.gts')) as {\n OutletPlaceholder: object;\n };\n\n // A route template receives only @model/@controller, so the marker renders its\n // own \"outlet\" label when the author did not supply one.\n return { name: 'outlet', template: OutletPlaceholder };\n}\n\nasync function routeOutletState({\n component,\n args,\n route,\n globals,\n storyName,\n application\n}: {\n component: object;\n args: Args;\n route: RouteParameters;\n globals: EmberGlobals;\n storyName: string;\n application: ApplicationInstance;\n}) {\n return buildRouteOutletState({\n template: component,\n route,\n outlet: await resolveOutletStub({\n route,\n mode: globals[OUTLET_GLOBAL_KEY],\n placeholder: loadPlaceholderStub\n }),\n args,\n storyName,\n owner: application\n });\n}\n\nasync function mountStory({\n application,\n component,\n args,\n route,\n globals,\n storyName,\n mount\n}: {\n application: ApplicationInstance;\n component: object;\n args: Args;\n route?: RouteParameters;\n globals: EmberGlobals;\n storyName: string;\n mount: HTMLElement;\n}): Promise<Pick<RenderContextCache, 'renderer' | 'outletView'>> {\n if (!route) {\n return {\n renderer: renderComponent(component, { args, into: mount, owner: application })\n };\n }\n\n // `{{outlet}}` reads its child from Glimmer's dynamic scope, which\n // `renderComponent` never populates — so a route template rendered as a plain\n // component throws instead of rendering. Route stories (annotated, or detected\n // by their template's `{{outlet}}`, see `renderToCanvas`) go through Ember's\n // own outlet root; the toolbar global decides whether `{{outlet}}` is a hole\n // or a placeholder (an explicit `route.outlet` overrides it).\n const outletView = await mountOutletView(\n application,\n await routeOutletState({ component, args, route, globals, storyName, application }),\n mount\n );\n\n return { outletView };\n}\n\nconst resolveAppOption = createAppResolver({\n application: Application,\n applicationInstance: ApplicationInstance\n});\n\nfunction initApp(appOption: AppParamater, opts: { rootElement: HTMLElement }) {\n return resolveAppOption(appOption, opts) as ApplicationInstance;\n}\n\nasync function bootApp(\n storyContext: StoryContext,\n canvasElement: EmberRenderer['canvasElement']\n): Promise<ApplicationInstance> {\n const ember = storyContext.parameters.ember;\n\n if (!ember?.app) {\n const options = Object.keys(storyContext.parameters)\n .filter((key) => key.toLowerCase().includes('ember'))\n .join(', ');\n\n throw new Error(\n [\n 'ember-storybook: no Ember application configured for this story.',\n 'Set `parameters.ember.app` in your preview (e.g. `.storybook/preview.ts`) to a function',\n 'returning an Application or ApplicationInstance. When not provided, every render would',\n `boot a bare Application without any resolver, failing with an obscure error. Found \\`parameters\\` keys: ${options || '(none)'}.`\n ].join(' ')\n );\n }\n\n const application: ApplicationInstance = initApp(ember.app, { rootElement: canvasElement });\n\n // modify the owner for the story\n if (ember.owner) {\n for (const [key, obj] of Object.entries(ember.owner) as [`${string}:${string}`, object][]) {\n application.unregister(key);\n application.register(key, obj);\n }\n }\n\n // configure and boot the instance so ember registers necessary environments\n try {\n ember.configure?.(application);\n await application.boot();\n ember.updateGlobals?.(storyContext.globals, application);\n } catch (error) {\n // A half-booted app may not survive the failed render: the next render\n // would boot a second app onto the same root element, which Ember asserts\n // against (\"You cannot use the same root element ... multiple times\").\n destroy(application);\n throw error;\n }\n\n return application;\n}\n\nexport async function renderToCanvas(\n {\n storyFn,\n showMain,\n storyContext,\n forceRemount\n }: RenderContext<EmberRenderer> & { storyContext: StoryContext },\n canvasElement: EmberRenderer['canvasElement']\n) {\n function unregister(element: EmberRenderer['canvasElement']) {\n const context = contexts.get(element);\n\n if (!context) {\n return;\n }\n\n contexts.delete(element);\n teardownMount(context);\n destroy(context.application);\n }\n\n // The story function carries the decorator pipeline; the framework's `render`\n // reports the final (possibly decorator-transformed) args back in its result.\n const storyResult = storyFn();\n const {\n component,\n args,\n route: routeFromStory\n } = normalizeStoryResult(storyResult, storyContext.args);\n // Stories that define their own `render` never report a route back, so the\n // parameter is the fallback. A story whose template contains `{{outlet}}` but\n // that was never annotated is a route story too: rendering it as a plain\n // component crashes on the outlet keyword (#62), so it is mounted through the\n // outlet root with empty route parameters — hole/placeholder per the toolbar.\n const route =\n routeFromStory ??\n storyContext.parameters.ember?.route ??\n (templateUsesOutlet(component) ? DEFAULT_ROUTE : undefined);\n\n const existing = contexts.get(canvasElement);\n const previousGlobals = relevantGlobals(route, existing?.globals ?? {});\n const currentGlobals = relevantGlobals(route, storyContext.globals);\n const globalsChanged =\n existing !== undefined && !forceRemount && !shallowEqual(previousGlobals, currentGlobals);\n\n // Nothing to do: a globals-only change (or a no-op call) must not tear down the\n // mounted component.\n if (existing && !forceRemount && !globalsChanged && shallowEqual(existing.args, args)) {\n return () => {\n unregister(canvasElement);\n };\n }\n\n // An outlet root is not tracked by the mount cache that broke component re-renders\n // (#27, #33), so it can be updated in place exactly the way the router swaps route\n // state. That preserves the route tree's component state and avoids re-appending.\n //\n // The whole update-or-mount section is guarded: a booted app must never survive\n // a failed render, or the retry boots a second app onto the same `canvasElement`\n // and Ember's EventDispatcher assert masks the real error (#62).\n let application: ApplicationInstance | undefined;\n let mount: HTMLElement | undefined;\n\n try {\n if (route && existing?.outletView && !forceRemount) {\n if (globalsChanged) {\n storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);\n }\n\n await updateOutletView(\n existing.outletView,\n await routeOutletState({\n component,\n args,\n route,\n globals: storyContext.globals,\n storyName: storyContext.name,\n application: existing.application\n })\n );\n\n contexts.set(canvasElement, { ...existing, args, globals: { ...storyContext.globals } });\n\n showMain();\n\n return () => {\n unregister(canvasElement);\n };\n }\n\n // Reuse the booted app across arg/globals updates, but always render into a\n // fresh mount: reusing the same mount makes Ember's render cache serve a stale\n // entry, which destroyed renders with obscure node errors (#27, #33).\n //\n // A route story and a component story cannot share an app: the outlet root can\n // only be dropped by destroying the app, so switching modes remounts.\n const canReuseApp =\n existing !== undefined && !forceRemount && Boolean(existing.outletView) === Boolean(route);\n\n if (isEmberBelow(6, 12)) {\n // Exception: ember-source < 6.12 has no per-owner renderer cache, so every\n // `renderComponent` call builds a new renderer (EvaluationContext) and\n // re-rendering an already-rendered owner corrupts the shared opcode table,\n // crashing with \"reading 'syscall'\". Boot a fresh app on every render instead,\n // so each owner is only ever rendered once (at the cost of app state + perf).\n if (existing) {\n unregister(canvasElement);\n }\n\n application = await bootApp(storyContext, canvasElement);\n } else if (canReuseApp) {\n // ember-source >= 6.12 caches one renderer per owner, so we can keep the same\n // app instance across re-renders. This preserves component/app state (@tracked\n // fields, services) and avoids re-booting on every control/global change.\n if (globalsChanged) {\n storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);\n }\n\n application = existing.application;\n teardownMount(existing);\n } else {\n if (existing) {\n unregister(canvasElement);\n }\n\n application = await bootApp(storyContext, canvasElement);\n }\n\n mount = document.createElement('div');\n\n canvasElement.append(mount);\n\n const mounted = await mountStory({\n application,\n component,\n args,\n route,\n globals: storyContext.globals,\n storyName: storyContext.name,\n mount\n });\n\n contexts.set(canvasElement, {\n application,\n mount,\n args,\n globals: { ...storyContext.globals },\n ...mounted\n });\n\n showMain();\n\n return () => {\n unregister(canvasElement);\n };\n } catch (error) {\n // `unregister` covers the reuse paths (the still-registered context owns the\n // app); the fresh-boot paths have no context yet, so destroy their app here.\n if (contexts.has(canvasElement)) {\n unregister(canvasElement);\n } else {\n mount?.remove();\n\n if (application) {\n destroy(application);\n }\n }\n\n throw error;\n }\n}\n","import { enhanceArgTypes } from 'storybook/internal/docs-tools';\n\nimport { OUTLET_GLOBAL_KEY } from '../outlet-key';\n\nimport type { ArgTypesEnhancer, GlobalTypes, Parameters } from 'storybook/internal/types';\n\nexport { render, renderToCanvas } from './render';\n\nexport const parameters: Parameters = {\n renderer: 'ember',\n docs: {\n story: { inline: true }\n }\n};\n\n/**\n * The \"Ember\" toolbar menu: how a route story should render `{{outlet}}`.\n *\n * `defaultValue` seeds the global (Storybook merges global-type defaults under\n * any project `initialGlobals`), so a project can still change the starting\n * value with `initialGlobals: { outlet: 'placeholder' }`.\n *\n * No `toolbar` here: the menu UI (with the Ember brand icon) is a custom tool\n * in `src/manager`, because Storybook 10 only resolves toolbar icons against\n * its fixed built-in icon map.\n */\nexport const globalTypes: GlobalTypes = {\n [OUTLET_GLOBAL_KEY]: {\n description: 'How a route story renders {{outlet}}',\n defaultValue: 'hole'\n }\n};\n\nexport const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-DGk6BP_3.mjs","names":["getComponentTemplate","renderSettled","run","DEFAULT_OUTLET_NAME","resolveOutletStub","route","mode","placeholder","outlet","template","undefined","OUTLET_KEYWORD","asTemplateFactory","component","templateUsesOutlet","factory","block","parsedLayout","Array","isArray","includes","mainOutlet","child","main","buildChildRenderState","stub","owner","render","name","model","controller","outlets","buildRouteOutletState","args","storyName","createOutletView","container","state","element","factoryFor","Error","view","create","environment","lookup","application","setOutletState","appendTo","mountOutletView","updateOutletView","Application","ApplicationInstance","destroy","renderComponent","VERSION","OUTLET_GLOBAL_KEY","buildRouteOutletState","mountOutletView","resolveOutletStub","templateUsesOutlet","updateOutletView","createAppResolver","normalizeStoryResult","isEmberBelow","major","minor","maj","min","split","map","Number","render","args","context","id","component","ember","parameters","route","Error","shallowEqual","a","b","aKeys","Object","keys","bKeys","length","every","key","hasOwn","is","withoutOutletGlobal","globals","fromEntries","entries","filter","relevantGlobals","contexts","Map","DEFAULT_ROUTE","freeze","teardownMount","renderer","mount","remove","loadPlaceholderStub","OutletPlaceholder","name","template","routeOutletState","storyName","application","outlet","mode","placeholder","owner","mountStory","into","outletView","resolveAppOption","applicationInstance","initApp","appOption","opts","bootApp","storyContext","canvasElement","app","options","toLowerCase","includes","join","rootElement","obj","unregister","register","configure","boot","updateGlobals","error","renderToCanvas","storyFn","showMain","forceRemount","element","get","delete","storyResult","routeFromStory","undefined","existing","previousGlobals","currentGlobals","globalsChanged","set","canReuseApp","Boolean","document","createElement","append","mounted","has","enhanceArgTypes","OUTLET_GLOBAL_KEY","render","renderToCanvas","parameters","renderer","docs","story","inline","globalTypes","description","defaultValue","argTypesEnhancers"],"sources":["../src/client/outlet.ts","../src/client/render.ts","../src/client/config.ts"],"sourcesContent":["import { getComponentTemplate } from '@ember/component';\nimport { renderSettled } from '@ember/renderer';\nimport { run } from '@ember/runloop';\n\nimport type { OutletMode, OutletStub, RouteParameters } from './types';\nimport type ApplicationInstance from '@ember/application/instance';\n\n/**\n * What Ember's outlet hands a route template. A route template is *not* a\n * component story: it receives exactly `@model` and `@controller`, because that\n * is all `{{outlet}}` passes down (`OUTLET_COMPONENT_TEMPLATE` in ember-source).\n */\nexport interface OutletRenderState {\n owner: object;\n name: string;\n controller: unknown;\n model: unknown;\n template: object;\n}\n\n/**\n * Mirrors ember-source's internal `OutletState`. The shape is structural, not\n * nominal, so a plain object is accepted by `setOutletState`; the leaf's\n * `outlets.main` is what a nested `{{outlet}}` reads.\n */\nexport interface OutletState {\n render: OutletRenderState;\n outlets: { main: OutletState | undefined };\n}\n\nexport interface RouteStoryInput {\n /** The route template — the story's `component`. */\n template: object;\n /** `parameters.ember.route`. */\n route: RouteParameters;\n /**\n * The resolved stub for `{{outlet}}` — see {@link resolveOutletStub}.\n * `undefined` leaves the outlet as a hole.\n */\n outlet?: OutletStub;\n /** Final (decorated) story args; `model`/`controller` feed the route. */\n args: Record<string, unknown>;\n /** Story name, used when `route.name` is not given. */\n storyName: string;\n /** The booted app instance the route renders under. */\n owner: object;\n}\n\nconst DEFAULT_OUTLET_NAME = 'outlet';\n\nexport interface OutletResolveInput {\n /** `parameters.ember.route` of the story being rendered. */\n route: RouteParameters;\n /** Value of the `outlet` global (see `src/outlet-key.ts`), if any. */\n mode?: OutletMode;\n /**\n * Produces the stub rendered when the global asks for a visible placeholder.\n * Called lazily (and so may be an async chunk load) and only when needed;\n * injected so this module stays free of Ember-owned template components.\n */\n placeholder: () => OutletStub | Promise<OutletStub>;\n}\n\n/**\n * Decides what `{{outlet}}` renders.\n *\n * An explicit `route.outlet` is author intent and always wins, so a story stays\n * deterministic no matter how the toolbar is set. Otherwise the global decides:\n * `placeholder` renders the injected marker, anything else leaves a hole.\n */\nexport async function resolveOutletStub({\n route,\n mode,\n placeholder\n}: OutletResolveInput): Promise<OutletStub | undefined> {\n if (route.outlet?.template) {\n return route.outlet;\n }\n\n return mode === 'placeholder' ? await placeholder() : undefined;\n}\n\n/**\n * The name `{{outlet}}` compiles to: the built-in keyword helper\n * `{{component (-outlet)}}` (see ember-source's `transform-wrap-mount-and-outlet`).\n */\nconst OUTLET_KEYWORD = '-outlet';\n\n/**\n * The ownerless template a template factory hands out, reduced to the one\n * intimate API we read. `parsedLayout` is deliberately absent from Ember's\n * public types (ember-source keeps it \"because some addons use these intimate\n * APIs\"), so the shape is declared here rather than imported.\n */\ninterface ParsedTemplate {\n parsedLayout?: { block?: unknown };\n}\n\n/**\n * Story components are normally classes or template-only components (both\n * reachable via `getComponentTemplate`); a raw `createTemplateFactory` result\n * used directly as the component is only recognizable by its `__meta` marker.\n */\nfunction asTemplateFactory(\n component: object\n): ((owner?: unknown) => ParsedTemplate | undefined) | undefined {\n return typeof component === 'function' && '__meta' in component\n ? (component as unknown as (owner?: unknown) => ParsedTemplate | undefined)\n : undefined;\n}\n\n/**\n * Whether the component's *own* template references `{{outlet}}` — i.e. it is a\n * route template, which is how an unannotated route-story is recognized (#62).\n *\n * A template factory caches a per-owner (plus ownerless) `TemplateImpl`; its\n * `parsedLayout.block` is the parsed wire-format tuple\n * `[statements, locals, upvars]`. Free names — every helper/keyword the\n * template resolves, from the whole template including nested blocks — live\n * exactly once in `upvars`, so checking that slot cannot mistake a string\n * literal `\"-outlet\"` used as an argument for a real outlet.\n */\nexport function templateUsesOutlet(component: object): boolean {\n const factory = getComponentTemplate(component) ?? asTemplateFactory(component);\n\n if (!factory) {\n return false;\n }\n\n // Calling the factory with no owner returns the memoized ownerless template —\n // pure data: no owner, no compilation, no side effects on later owner renders.\n const template = (factory as unknown as (owner?: unknown) => ParsedTemplate | undefined)(\n undefined\n );\n const block = template?.parsedLayout?.block;\n\n return (\n Array.isArray(block) &&\n Array.isArray(block[2]) &&\n (block[2] as unknown[]).includes(OUTLET_KEYWORD)\n );\n}\n\n// Ember has no named outlets any more: every `{{outlet}}` is the \"main\" one.\nfunction mainOutlet(child: OutletState | undefined): OutletState['outlets'] {\n return { main: child };\n}\n\nfunction buildChildRenderState(stub: OutletStub, owner: object): OutletState {\n return {\n render: {\n owner,\n name: stub.name ?? DEFAULT_OUTLET_NAME,\n template: stub.template as object,\n model: stub.model,\n controller: stub.controller\n },\n // One level only: a stubbed child route is a leaf, so a `{{outlet}}` inside\n // it renders a hole as well.\n outlets: mainOutlet(undefined)\n };\n}\n\n/**\n * Builds the `OutletState` for a route story.\n *\n * `{{outlet}}` reads its child from Glimmer's *dynamic scope*, which\n * `renderComponent` never populates — so route templates are rendered through\n * Ember's own outlet root instead, and this is the state handed to it. Leaving\n * `outlets.main` undefined is what makes `{{outlet}}` render a hole.\n */\nexport function buildRouteOutletState({\n template,\n route,\n outlet,\n args,\n storyName,\n owner\n}: RouteStoryInput): OutletState {\n const child = outlet?.template ? buildChildRenderState(outlet, owner) : undefined;\n\n return {\n render: {\n owner,\n name: route.name ?? storyName,\n template,\n model: route.model ?? args.model,\n controller: route.controller ?? args.controller\n },\n outlets: mainOutlet(child)\n };\n}\n\n/**\n * Ember's `OutletView` (the router's top-level view), reduced to the surface\n * this module drives. It is only reachable through the container, so the type is\n * declared here rather than imported from `@ember/-internals`.\n */\nexport interface OutletView {\n appendTo(target: HTMLElement): void;\n setOutletState(state: OutletState): void;\n}\n\ninterface OutletViewFactory {\n create(options: Record<string, unknown>): OutletView;\n}\n\n/**\n * The private container entries backing Ember's outlet root — the very full\n * names `Router._setOutlets()` uses. Casting through this interface keeps the\n * unsound lookups in one place instead of spread across the renderer.\n */\ninterface OutletContainer {\n factoryFor(fullName: string): OutletViewFactory | undefined;\n lookup(fullName: string): unknown;\n}\n\n/**\n * `{{outlet}}` compiles to Ember's built-in `-outlet` keyword helper, which reads\n * its child from Glimmer's *dynamic scope*. `renderComponent` starts that scope\n * empty, so a route template rendered as a plain component crashes. Route stories\n * are therefore rendered through the same outlet root `Router._setOutlets()` uses\n * — reached by container name, never imported.\n */\nfunction createOutletView(\n container: OutletContainer,\n state: OutletState,\n element: HTMLElement\n): OutletView {\n const factory = container.factoryFor('view:-outlet');\n\n if (!factory) {\n throw new Error(\n 'ember-storybook: this story sets `parameters.ember.route`, but `view:-outlet` ' +\n 'is not registered on this Ember build, so {{outlet}} cannot be rendered. ' +\n \"Route stories render through Ember's own outlet root, which the router \" +\n '(`Router._setOutlets()`) uses as well.'\n );\n }\n\n const view = factory.create({\n environment: container.lookup('-environment:main'),\n application: container.lookup('application:main'),\n // The outlet root renders `{{outlet}}` itself; the story's route template\n // arrives through the state below, as `outlets.main`.\n template: container.lookup('template:-outlet')\n });\n\n view.setOutletState(state);\n\n // `appendTo` schedules on the `render` queue, so flush the run loop to render.\n run(() => {\n view.appendTo(element);\n });\n\n return view;\n}\n\n/**\n * Renders `state` into `element` through Ember's outlet root and waits for the\n * render to settle.\n */\nexport async function mountOutletView(\n application: ApplicationInstance,\n state: OutletState,\n element: HTMLElement\n): Promise<OutletView> {\n const view = createOutletView(application as unknown as OutletContainer, state, element);\n\n await renderSettled();\n\n return view;\n}\n\n/**\n * Swaps what the outlet renders, in place. This is how the router updates a live\n * route tree, so arg changes do not tear the route's components down.\n */\nexport async function updateOutletView(view: OutletView, state: OutletState): Promise<void> {\n view.setOutletState(state);\n await renderSettled();\n}\n","import Application from '@ember/application';\nimport ApplicationInstance from '@ember/application/instance';\nimport { destroy } from '@ember/destroyable';\nimport { renderComponent } from '@ember/renderer';\nimport { VERSION } from '@ember/version';\n\nimport { OUTLET_GLOBAL_KEY } from '../outlet-key';\nimport {\n buildRouteOutletState,\n mountOutletView,\n resolveOutletStub,\n templateUsesOutlet,\n updateOutletView\n} from './outlet';\nimport { createAppResolver, type EmberStoryResult, normalizeStoryResult } from './story-result';\n\nimport type { OutletView } from './outlet';\nimport type {\n AppParamater,\n EmberGlobals,\n EmberRenderer,\n OutletStub,\n RouteParameters,\n StoryContext\n} from './types';\nimport type { RenderResult } from '@ember/-internals/glimmer/lib/renderer';\nimport type { ArgsStoryFn, RenderContext } from 'storybook/internal/types';\n\ntype Args = Record<string, unknown>;\n\n// ember-source < 6.12 built a brand-new `BaseRenderer` (EvaluationContext) on\n// every `renderComponent` call and had no per-owner renderer cache. Re-rendering\n// an already-rendered owner therefore produced multiple live EvaluationContexts\n// that corrupted glimmer's shared opcode table, crashing with\n// \"Cannot read properties of null (reading 'syscall')\". 6.12+ added that cache\n// (`RENDERER_CACHE` keyed by owner), so reusing an app across renders is only\n// safe from 6.12 onward.\nfunction isEmberBelow(major: number, minor: number): boolean {\n const [maj, min] = VERSION.split('.').map(Number);\n\n return maj < major || (maj === major && min < minor);\n}\n\nexport const render: ArgsStoryFn<EmberRenderer> = (args, context): EmberStoryResult => {\n const { id, component } = context;\n // `ArgsStoryFn`'s context types `parameters` loosely; the framework's own\n // `StoryContext` carries the typed `ember` bag.\n const { ember } = context.parameters as StoryContext['parameters'];\n const route = ember?.route;\n\n if (typeof component === 'function' || typeof component === 'object') {\n // `route` is reported back like `args` are: `<RenderStory>` gets nothing but\n // the story result, and it needs to know a story is a route story.\n return { component, args, route };\n }\n\n throw new Error(\n `Unable to render story ${id} as the component annotation is missing from the default export`\n );\n};\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n return (\n aKeys.length === bKeys.length &&\n aKeys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]))\n );\n}\n\nconst withoutOutletGlobal = (globals: Record<string, unknown>) =>\n Object.fromEntries(Object.entries(globals).filter(([key]) => key !== OUTLET_GLOBAL_KEY));\n\n/**\n * Globals the renderer actually reacts to.\n *\n * The outlet menu only concerns route stories, so for a plain component story its\n * value is stripped: toggling \"Ember\" would otherwise count as a globals change\n * and needlessly remount (throwing away the component's state).\n */\nfunction relevantGlobals(\n route: RouteParameters | undefined,\n globals: Record<string, unknown>\n): Record<string, unknown> {\n return route ? globals : withoutOutletGlobal(globals);\n}\n\ntype RenderContextCache = {\n application: ApplicationInstance;\n mount: HTMLElement;\n args: Args;\n globals: Record<string, unknown>;\n // A story is mounted either as a plain component (`renderer`) or, for route\n // templates, through Ember's outlet root (`outletView`) — never both.\n renderer?: RenderResult;\n outletView?: OutletView;\n};\n\nconst contexts = new Map<EmberRenderer['canvasElement'], RenderContextCache>();\n\n/**\n * Route parameters assumed for a story whose template references `{{outlet}}`\n * but that never set `parameters.ember.route` (#62). Frozen and module-level so\n * the identity is stable across renders of the same story.\n */\nconst DEFAULT_ROUTE: RouteParameters = Object.freeze({});\n\n/**\n * Tears the mounted story down, leaving the booted app alone so it can be\n * reused.\n *\n * Route stories are deliberately not cleaned up here: the outlet root is dropped\n * by destroying the app (which clears *and deregisters* its roots), and\n * `Renderer.cleanupRootFor()` would empty the root list without deregistering —\n * leaving the renderer in the global set so the next append would assert \"Cannot\n * register the same renderer twice\".\n */\nfunction teardownMount(context: RenderContextCache) {\n context.renderer?.destroy();\n context.mount.remove();\n}\n\n/**\n * The stub rendered when the toolbar asks for a visible placeholder.\n *\n * Loaded on demand rather than imported: folding the compiled template into the\n * boot chunk makes the bundler emit a `node:module` `createRequire` shim into it,\n * which throws in the browser and takes `renderToCanvas` — and with it every\n * story — down with it.\n */\nasync function loadPlaceholderStub(): Promise<OutletStub> {\n // Typed explicitly: the `.gts` module has no declaration reachable from here.\n const { OutletPlaceholder } = (await import('./outlet-placeholder.gts')) as {\n OutletPlaceholder: object;\n };\n\n // A route template receives only @model/@controller, so the marker renders its\n // own \"outlet\" label when the author did not supply one.\n return { name: 'outlet', template: OutletPlaceholder };\n}\n\nasync function routeOutletState({\n component,\n args,\n route,\n globals,\n storyName,\n application\n}: {\n component: object;\n args: Args;\n route: RouteParameters;\n globals: EmberGlobals;\n storyName: string;\n application: ApplicationInstance;\n}) {\n return buildRouteOutletState({\n template: component,\n route,\n outlet: await resolveOutletStub({\n route,\n mode: globals[OUTLET_GLOBAL_KEY],\n placeholder: loadPlaceholderStub\n }),\n args,\n storyName,\n owner: application\n });\n}\n\nasync function mountStory({\n application,\n component,\n args,\n route,\n globals,\n storyName,\n mount\n}: {\n application: ApplicationInstance;\n component: object;\n args: Args;\n route?: RouteParameters;\n globals: EmberGlobals;\n storyName: string;\n mount: HTMLElement;\n}): Promise<Pick<RenderContextCache, 'renderer' | 'outletView'>> {\n if (!route) {\n return {\n renderer: renderComponent(component, { args, into: mount, owner: application })\n };\n }\n\n // `{{outlet}}` reads its child from Glimmer's dynamic scope, which\n // `renderComponent` never populates — so a route template rendered as a plain\n // component throws instead of rendering. Route stories (annotated, or detected\n // by their template's `{{outlet}}`, see `renderToCanvas`) go through Ember's\n // own outlet root; the toolbar global decides whether `{{outlet}}` is a hole\n // or a placeholder (an explicit `route.outlet` overrides it).\n const outletView = await mountOutletView(\n application,\n await routeOutletState({ component, args, route, globals, storyName, application }),\n mount\n );\n\n return { outletView };\n}\n\nconst resolveAppOption = createAppResolver({\n application: Application,\n applicationInstance: ApplicationInstance\n});\n\nfunction initApp(appOption: AppParamater, opts: { rootElement: HTMLElement }) {\n return resolveAppOption(appOption, opts) as ApplicationInstance;\n}\n\nasync function bootApp(\n storyContext: StoryContext,\n canvasElement: EmberRenderer['canvasElement']\n): Promise<ApplicationInstance> {\n const ember = storyContext.parameters.ember;\n\n if (!ember?.app) {\n const options = Object.keys(storyContext.parameters)\n .filter((key) => key.toLowerCase().includes('ember'))\n .join(', ');\n\n throw new Error(\n [\n 'ember-storybook: no Ember application configured for this story.',\n 'Set `parameters.ember.app` in your preview (e.g. `.storybook/preview.ts`) to a function',\n 'returning an Application or ApplicationInstance. When not provided, every render would',\n `boot a bare Application without any resolver, failing with an obscure error. Found \\`parameters\\` keys: ${options || '(none)'}.`\n ].join(' ')\n );\n }\n\n const application: ApplicationInstance = initApp(ember.app, { rootElement: canvasElement });\n\n // modify the owner for the story\n if (ember.owner) {\n for (const [key, obj] of Object.entries(ember.owner) as [`${string}:${string}`, object][]) {\n application.unregister(key);\n application.register(key, obj);\n }\n }\n\n // configure and boot the instance so ember registers necessary environments\n try {\n ember.configure?.(application);\n await application.boot();\n ember.updateGlobals?.(storyContext.globals, application);\n } catch (error) {\n // A half-booted app may not survive the failed render: the next render\n // would boot a second app onto the same root element, which Ember asserts\n // against (\"You cannot use the same root element ... multiple times\").\n destroy(application);\n throw error;\n }\n\n return application;\n}\n\nexport async function renderToCanvas(\n {\n storyFn,\n showMain,\n storyContext,\n forceRemount\n }: RenderContext<EmberRenderer> & { storyContext: StoryContext },\n canvasElement: EmberRenderer['canvasElement']\n) {\n function unregister(element: EmberRenderer['canvasElement']) {\n const context = contexts.get(element);\n\n if (!context) {\n return;\n }\n\n contexts.delete(element);\n teardownMount(context);\n destroy(context.application);\n }\n\n // The story function carries the decorator pipeline; the framework's `render`\n // reports the final (possibly decorator-transformed) args back in its result.\n const storyResult = storyFn();\n const {\n component,\n args,\n route: routeFromStory\n } = normalizeStoryResult(storyResult, storyContext.args);\n // Stories that define their own `render` never report a route back, so the\n // parameter is the fallback. A story whose template contains `{{outlet}}` but\n // that was never annotated is a route story too: rendering it as a plain\n // component crashes on the outlet keyword (#62), so it is mounted through the\n // outlet root with empty route parameters — hole/placeholder per the toolbar.\n const route =\n routeFromStory ??\n storyContext.parameters.ember?.route ??\n (templateUsesOutlet(component) ? DEFAULT_ROUTE : undefined);\n\n const existing = contexts.get(canvasElement);\n const previousGlobals = relevantGlobals(route, existing?.globals ?? {});\n const currentGlobals = relevantGlobals(route, storyContext.globals);\n const globalsChanged =\n existing !== undefined && !forceRemount && !shallowEqual(previousGlobals, currentGlobals);\n\n // Nothing to do: neither args nor any relevant global changed, so the no-op\n // call (or an irrelevant-global change) must not tear down the mounted component.\n if (existing && !forceRemount && !globalsChanged && shallowEqual(existing.args, args)) {\n return () => {\n unregister(canvasElement);\n };\n }\n\n // An outlet root is not tracked by the mount cache that broke component re-renders\n // (#27, #33), so it can be updated in place exactly the way the router swaps route\n // state. That preserves the route tree's component state and avoids re-appending.\n //\n // The whole update-or-mount section is guarded: a booted app must never survive\n // a failed render, or the retry boots a second app onto the same `canvasElement`\n // and Ember's EventDispatcher assert masks the real error (#62).\n let application: ApplicationInstance | undefined;\n let mount: HTMLElement | undefined;\n\n try {\n if (route && existing?.outletView && !forceRemount) {\n if (globalsChanged) {\n storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);\n }\n\n await updateOutletView(\n existing.outletView,\n await routeOutletState({\n component,\n args,\n route,\n globals: storyContext.globals,\n storyName: storyContext.name,\n application: existing.application\n })\n );\n\n contexts.set(canvasElement, { ...existing, args, globals: { ...storyContext.globals } });\n\n showMain();\n\n return () => {\n unregister(canvasElement);\n };\n }\n\n // A globals-only change never recreates a component story: templates never\n // read globals, so `updateGlobals` — or a decorator's own reaction — is the\n // only channel through which a global can reach a mounted story. Remounting\n // here would throw away the component's `@tracked` state for nothing, which\n // is how the Interaction Recorder appeared to \"reset\" stories: its toolbar\n // toggles are pure globals changes.\n if (existing && !forceRemount && !route && shallowEqual(existing.args, args)) {\n if (globalsChanged) {\n storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);\n }\n\n contexts.set(canvasElement, { ...existing, args, globals: { ...storyContext.globals } });\n\n showMain();\n\n return () => {\n unregister(canvasElement);\n };\n }\n\n // Reuse the booted app across arg/globals updates, but always render into a\n // fresh mount: reusing the same mount makes Ember's render cache serve a stale\n // entry, which destroyed renders with obscure node errors (#27, #33).\n //\n // A route story and a component story cannot share an app: the outlet root can\n // only be dropped by destroying the app, so switching modes remounts.\n const canReuseApp =\n existing !== undefined && !forceRemount && Boolean(existing.outletView) === Boolean(route);\n\n if (isEmberBelow(6, 12)) {\n // Exception: ember-source < 6.12 has no per-owner renderer cache, so every\n // `renderComponent` call builds a new renderer (EvaluationContext) and\n // re-rendering an already-rendered owner corrupts the shared opcode table,\n // crashing with \"reading 'syscall'\". Boot a fresh app on every render instead,\n // so each owner is only ever rendered once (at the cost of app state + perf).\n if (existing) {\n unregister(canvasElement);\n }\n\n application = await bootApp(storyContext, canvasElement);\n } else if (canReuseApp) {\n // ember-source >= 6.12 caches one renderer per owner, so we can keep the same\n // app instance across re-renders. This preserves component/app state (@tracked\n // fields, services) and avoids re-booting on every control/global change.\n if (globalsChanged) {\n storyContext.parameters.ember?.updateGlobals?.(storyContext.globals, existing.application);\n }\n\n application = existing.application;\n teardownMount(existing);\n } else {\n if (existing) {\n unregister(canvasElement);\n }\n\n application = await bootApp(storyContext, canvasElement);\n }\n\n mount = document.createElement('div');\n\n canvasElement.append(mount);\n\n const mounted = await mountStory({\n application,\n component,\n args,\n route,\n globals: storyContext.globals,\n storyName: storyContext.name,\n mount\n });\n\n contexts.set(canvasElement, {\n application,\n mount,\n args,\n globals: { ...storyContext.globals },\n ...mounted\n });\n\n showMain();\n\n return () => {\n unregister(canvasElement);\n };\n } catch (error) {\n // `unregister` covers the reuse paths (the still-registered context owns the\n // app); the fresh-boot paths have no context yet, so destroy their app here.\n if (contexts.has(canvasElement)) {\n unregister(canvasElement);\n } else {\n mount?.remove();\n\n if (application) {\n destroy(application);\n }\n }\n\n throw error;\n }\n}\n","import { enhanceArgTypes } from 'storybook/internal/docs-tools';\n\nimport { OUTLET_GLOBAL_KEY } from '../outlet-key';\n\nimport type { ArgTypesEnhancer, GlobalTypes, Parameters } from 'storybook/internal/types';\n\nexport { render, renderToCanvas } from './render';\n\nexport const parameters: Parameters = {\n renderer: 'ember',\n docs: {\n story: { inline: true }\n }\n};\n\n/**\n * The \"Ember\" toolbar menu: how a route story should render `{{outlet}}`.\n *\n * `defaultValue` seeds the global (Storybook merges global-type defaults under\n * any project `initialGlobals`), so a project can still change the starting\n * value with `initialGlobals: { outlet: 'placeholder' }`.\n *\n * No `toolbar` here: the menu UI (with the Ember brand icon) is a custom tool\n * in `src/manager`, because Storybook 10 only resolves toolbar icons against\n * its fixed built-in icon map.\n */\nexport const globalTypes: GlobalTypes = {\n [OUTLET_GLOBAL_KEY]: {\n description: 'How a route story renders {{outlet}}',\n defaultValue: 'hole'\n }\n};\n\nexport const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as setProjectAnnotations, r as definePreview, t as RenderStory } from "./client-
|
|
2
|
-
import { o as renderToCanvas } from "./config-
|
|
1
|
+
import { n as setProjectAnnotations, r as definePreview, t as RenderStory } from "./client-DdSMlQeh.mjs";
|
|
2
|
+
import { o as renderToCanvas } from "./config-DGk6BP_3.mjs";
|
|
3
3
|
import { t as OutletPlaceholder } from "./outlet-placeholder-CgO7fIDo.mjs";
|
|
4
4
|
export { OutletPlaceholder, RenderStory, definePreview, renderToCanvas, setProjectAnnotations };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-storybook",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Storybook for Ember: Develop, document, and test UI components in isolation",
|
|
6
6
|
"keywords": [
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/ember-integrations/ember-storybook/issues"
|
|
15
15
|
},
|
|
16
|
+
"homepage": "https://ember-integrations.github.io/ember-storybook",
|
|
16
17
|
"repository": {
|
|
17
18
|
"type": "git",
|
|
18
19
|
"url": "https://github.com/ember-integrations/ember-storybook"
|
|
@@ -77,9 +78,7 @@
|
|
|
77
78
|
"typedoc-plugin-ember": "0.0.3"
|
|
78
79
|
},
|
|
79
80
|
"peerDependencies": {
|
|
80
|
-
"
|
|
81
|
-
"ember-source": ">=6.8.0",
|
|
82
|
-
"storybook": "^10.5.0",
|
|
81
|
+
"storybook": "^10.0.0",
|
|
83
82
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
84
83
|
},
|
|
85
84
|
"devDependencies": {
|