@pyreon/storybook 0.0.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/lib/index.js ADDED
@@ -0,0 +1,49 @@
1
+ import { Fragment, h, h as h$1 } from "@pyreon/core";
2
+ import { mount, mount as mount$1 } from "@pyreon/runtime-dom";
3
+ import { computed, effect, signal } from "@pyreon/reactivity";
4
+
5
+ //#region src/render.ts
6
+ /**
7
+ * State tracked per canvas element so we can clean up between renders.
8
+ */
9
+ const canvasState = /* @__PURE__ */ new WeakMap();
10
+ /**
11
+ * Render a Pyreon story into a Storybook canvas element.
12
+ *
13
+ * This is the core integration point — Storybook calls this function
14
+ * every time a story needs to be displayed or re-rendered (e.g. when
15
+ * the user changes args via the Controls panel).
16
+ *
17
+ * It handles:
18
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
19
+ * 2. Building the VNode from the story function or component + args
20
+ * 3. Mounting the new VNode into the canvas
21
+ */
22
+ function renderToCanvas({ storyFn, showMain, showError }, canvasElement) {
23
+ const prevUnmount = canvasState.get(canvasElement);
24
+ if (prevUnmount) {
25
+ prevUnmount();
26
+ canvasState.delete(canvasElement);
27
+ }
28
+ try {
29
+ const unmount = mount$1(storyFn(), canvasElement);
30
+ canvasState.set(canvasElement, unmount);
31
+ showMain();
32
+ } catch (err) {
33
+ showError({
34
+ title: `Error rendering story`,
35
+ description: (err instanceof Error ? err : new Error(String(err))).message
36
+ });
37
+ }
38
+ }
39
+ /**
40
+ * Default render implementation used when no custom `render` is provided.
41
+ * Simply calls `h(component, args)`.
42
+ */
43
+ function defaultRender(component, args) {
44
+ return h$1(component, args);
45
+ }
46
+
47
+ //#endregion
48
+ export { Fragment, computed, defaultRender, effect, h, mount, renderToCanvas, signal };
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["mount","h"],"sources":["../src/render.ts"],"sourcesContent":["import { h } from '@pyreon/core'\nimport type { ComponentFn, VNodeChild } from '@pyreon/core'\nimport { mount } from '@pyreon/runtime-dom'\n\n/**\n * State tracked per canvas element so we can clean up between renders.\n */\nconst canvasState = new WeakMap<HTMLElement, () => void>()\n\n/**\n * Render a Pyreon story into a Storybook canvas element.\n *\n * This is the core integration point — Storybook calls this function\n * every time a story needs to be displayed or re-rendered (e.g. when\n * the user changes args via the Controls panel).\n *\n * It handles:\n * 1. Cleaning up the previous mount (disposing effects, removing DOM)\n * 2. Building the VNode from the story function or component + args\n * 3. Mounting the new VNode into the canvas\n */\nexport function renderToCanvas(\n {\n storyFn,\n showMain,\n showError,\n }: {\n storyFn: () => VNodeChild\n storyContext: {\n component?: ComponentFn<any>\n args: Record<string, unknown>\n [key: string]: unknown\n }\n showMain: () => void\n showError: (error: { title: string; description: string }) => void\n forceRemount: boolean\n },\n canvasElement: HTMLElement,\n): void {\n // Always clean up the previous render\n const prevUnmount = canvasState.get(canvasElement)\n if (prevUnmount) {\n prevUnmount()\n canvasState.delete(canvasElement)\n }\n\n try {\n // Get the story result — either from a custom render function\n // or by calling the component with args\n const element = storyFn()\n\n // Mount the Pyreon VNode tree into the canvas\n const unmount = mount(element, canvasElement)\n canvasState.set(canvasElement, unmount)\n\n showMain()\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n showError({\n title: `Error rendering story`,\n description: error.message,\n })\n }\n}\n\n/**\n * Default render implementation used when no custom `render` is provided.\n * Simply calls `h(component, args)`.\n */\nexport function defaultRender(\n component: ComponentFn<any>,\n args: Record<string, unknown>,\n): VNodeChild {\n return h(component, args)\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,8BAAc,IAAI,SAAkC;;;;;;;;;;;;;AAc1D,SAAgB,eACd,EACE,SACA,UACA,aAYF,eACM;CAEN,MAAM,cAAc,YAAY,IAAI,cAAc;AAClD,KAAI,aAAa;AACf,eAAa;AACb,cAAY,OAAO,cAAc;;AAGnC,KAAI;EAMF,MAAM,UAAUA,QAHA,SAAS,EAGM,cAAc;AAC7C,cAAY,IAAI,eAAe,QAAQ;AAEvC,YAAU;UACH,KAAK;AAEZ,YAAU;GACR,OAAO;GACP,cAHY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAG5C;GACpB,CAAC;;;;;;;AAQN,SAAgB,cACd,WACA,MACY;AACZ,QAAOC,IAAE,WAAW,KAAK"}
package/lib/preset.js ADDED
@@ -0,0 +1,20 @@
1
+ import { join } from "node:path";
2
+
3
+ //#region src/preset.ts
4
+ /**
5
+ * Storybook preset for @pyreon/storybook.
6
+ *
7
+ * This file is loaded by Storybook's server when the user sets
8
+ * `framework: "@pyreon/storybook"` in their `.storybook/main.ts`.
9
+ *
10
+ * It tells Storybook:
11
+ * - Which renderer to use (via the preview entry)
12
+ * - What framework name to report
13
+ */
14
+ const addons = [];
15
+ const previewAnnotations = [join(__dirname, "preview")];
16
+ const core = { renderer: "@pyreon/storybook" };
17
+
18
+ //#endregion
19
+ export { addons, core, previewAnnotations };
20
+ //# sourceMappingURL=preset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset.js","names":[],"sources":["../src/preset.ts"],"sourcesContent":["/**\n * Storybook preset for @pyreon/storybook.\n *\n * This file is loaded by Storybook's server when the user sets\n * `framework: \"@pyreon/storybook\"` in their `.storybook/main.ts`.\n *\n * It tells Storybook:\n * - Which renderer to use (via the preview entry)\n * - What framework name to report\n */\n\nimport { dirname, join } from 'node:path'\n\nfunction _getAbsolutePath(value: string): string {\n return dirname(require.resolve(join(value, 'package.json')))\n}\n\nexport const addons: string[] = []\n\nexport const previewAnnotations: string[] = [join(__dirname, 'preview')]\n\nexport const core = {\n renderer: '@pyreon/storybook',\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAa,SAAmB,EAAE;AAElC,MAAa,qBAA+B,CAAC,KAAK,WAAW,UAAU,CAAC;AAExE,MAAa,OAAO,EAClB,UAAU,qBACX"}
package/lib/preview.js ADDED
@@ -0,0 +1,53 @@
1
+ import { h } from "@pyreon/core";
2
+ import { mount } from "@pyreon/runtime-dom";
3
+
4
+ //#region src/render.ts
5
+ /**
6
+ * State tracked per canvas element so we can clean up between renders.
7
+ */
8
+ const canvasState = /* @__PURE__ */ new WeakMap();
9
+ /**
10
+ * Render a Pyreon story into a Storybook canvas element.
11
+ *
12
+ * This is the core integration point — Storybook calls this function
13
+ * every time a story needs to be displayed or re-rendered (e.g. when
14
+ * the user changes args via the Controls panel).
15
+ *
16
+ * It handles:
17
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
18
+ * 2. Building the VNode from the story function or component + args
19
+ * 3. Mounting the new VNode into the canvas
20
+ */
21
+ function renderToCanvas({ storyFn, showMain, showError }, canvasElement) {
22
+ const prevUnmount = canvasState.get(canvasElement);
23
+ if (prevUnmount) {
24
+ prevUnmount();
25
+ canvasState.delete(canvasElement);
26
+ }
27
+ try {
28
+ const unmount = mount(storyFn(), canvasElement);
29
+ canvasState.set(canvasElement, unmount);
30
+ showMain();
31
+ } catch (err) {
32
+ showError({
33
+ title: `Error rendering story`,
34
+ description: (err instanceof Error ? err : new Error(String(err))).message
35
+ });
36
+ }
37
+ }
38
+
39
+ //#endregion
40
+ //#region src/preview.ts
41
+ /**
42
+ * Default render function — if the story CSF has a `component` but no
43
+ * explicit `render`, this is used to create the VNode.
44
+ */
45
+ function render(args, context) {
46
+ const Component = context.component;
47
+ if (!Component) throw new Error("[@pyreon/storybook] No component provided. Either set `component` in your meta or provide a `render` function.");
48
+ return h(Component, args);
49
+ }
50
+
51
+ //#endregion
52
+ export { render, renderToCanvas };
53
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","names":[],"sources":["../src/render.ts","../src/preview.ts"],"sourcesContent":["import { h } from '@pyreon/core'\nimport type { ComponentFn, VNodeChild } from '@pyreon/core'\nimport { mount } from '@pyreon/runtime-dom'\n\n/**\n * State tracked per canvas element so we can clean up between renders.\n */\nconst canvasState = new WeakMap<HTMLElement, () => void>()\n\n/**\n * Render a Pyreon story into a Storybook canvas element.\n *\n * This is the core integration point — Storybook calls this function\n * every time a story needs to be displayed or re-rendered (e.g. when\n * the user changes args via the Controls panel).\n *\n * It handles:\n * 1. Cleaning up the previous mount (disposing effects, removing DOM)\n * 2. Building the VNode from the story function or component + args\n * 3. Mounting the new VNode into the canvas\n */\nexport function renderToCanvas(\n {\n storyFn,\n showMain,\n showError,\n }: {\n storyFn: () => VNodeChild\n storyContext: {\n component?: ComponentFn<any>\n args: Record<string, unknown>\n [key: string]: unknown\n }\n showMain: () => void\n showError: (error: { title: string; description: string }) => void\n forceRemount: boolean\n },\n canvasElement: HTMLElement,\n): void {\n // Always clean up the previous render\n const prevUnmount = canvasState.get(canvasElement)\n if (prevUnmount) {\n prevUnmount()\n canvasState.delete(canvasElement)\n }\n\n try {\n // Get the story result — either from a custom render function\n // or by calling the component with args\n const element = storyFn()\n\n // Mount the Pyreon VNode tree into the canvas\n const unmount = mount(element, canvasElement)\n canvasState.set(canvasElement, unmount)\n\n showMain()\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n showError({\n title: `Error rendering story`,\n description: error.message,\n })\n }\n}\n\n/**\n * Default render implementation used when no custom `render` is provided.\n * Simply calls `h(component, args)`.\n */\nexport function defaultRender(\n component: ComponentFn<any>,\n args: Record<string, unknown>,\n): VNodeChild {\n return h(component, args)\n}\n","import { h } from '@pyreon/core'\nimport type { ComponentFn, VNodeChild } from '@pyreon/core'\nimport { renderToCanvas } from './render'\n\n/**\n * Preview entry — Storybook loads this in the preview iframe.\n *\n * Exports the render function and default decorators/parameters\n * that apply to all stories using this renderer.\n */\n\nexport { renderToCanvas }\n\n/**\n * Default render function — if the story CSF has a `component` but no\n * explicit `render`, this is used to create the VNode.\n */\nexport function render<TArgs extends Record<string, unknown>>(\n args: TArgs,\n context: { component?: ComponentFn<any> },\n): VNodeChild {\n const Component = context.component\n if (!Component) {\n throw new Error(\n '[@pyreon/storybook] No component provided. Either set `component` in your meta or provide a `render` function.',\n )\n }\n return h(Component, args)\n}\n"],"mappings":";;;;;;;AAOA,MAAM,8BAAc,IAAI,SAAkC;;;;;;;;;;;;;AAc1D,SAAgB,eACd,EACE,SACA,UACA,aAYF,eACM;CAEN,MAAM,cAAc,YAAY,IAAI,cAAc;AAClD,KAAI,aAAa;AACf,eAAa;AACb,cAAY,OAAO,cAAc;;AAGnC,KAAI;EAMF,MAAM,UAAU,MAHA,SAAS,EAGM,cAAc;AAC7C,cAAY,IAAI,eAAe,QAAQ;AAEvC,YAAU;UACH,KAAK;AAEZ,YAAU;GACR,OAAO;GACP,cAHY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAG5C;GACpB,CAAC;;;;;;;;;;AC5CN,SAAgB,OACd,MACA,SACY;CACZ,MAAM,YAAY,QAAQ;AAC1B,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iHACD;AAEH,QAAO,EAAE,WAAW,KAAK"}
@@ -0,0 +1,116 @@
1
+ import { ComponentFn, ComponentFn as ComponentFn$1, Fragment, Props, Props as Props$1, VNode, VNodeChild, VNodeChild as VNodeChild$1, h } from "@pyreon/core";
2
+ import { mount } from "@pyreon/runtime-dom";
3
+ import { computed, effect, signal } from "@pyreon/reactivity";
4
+
5
+ //#region src/types.d.ts
6
+ /**
7
+ * The Pyreon renderer descriptor used by Storybook internally.
8
+ * This tells Storybook what our "component" and "storyResult" types are.
9
+ */
10
+ interface PyreonRenderer {
11
+ component: ComponentFn$1<any>;
12
+ storyResult: VNodeChild$1;
13
+ canvasElement: HTMLElement;
14
+ }
15
+ /** Extract props type from a Pyreon component function. */
16
+ type InferProps<T> = T extends ComponentFn$1<infer P> ? P : Props$1;
17
+ interface StoryContext<TArgs = Props$1> {
18
+ args: TArgs;
19
+ argTypes: Record<string, unknown>;
20
+ globals: Record<string, unknown>;
21
+ id: string;
22
+ kind: string;
23
+ name: string;
24
+ viewMode: 'story' | 'docs';
25
+ }
26
+ type StoryFn<TArgs = Props$1> = (args: TArgs, context: StoryContext<TArgs>) => VNodeChild$1;
27
+ type DecoratorFn<TArgs = Props$1> = (storyFn: StoryFn<TArgs>, context: StoryContext<TArgs>) => VNodeChild$1;
28
+ interface Meta<TComponent extends ComponentFn$1<any> = ComponentFn$1> {
29
+ /** The component to document. */
30
+ component?: TComponent;
31
+ /** Display title in the sidebar. */
32
+ title?: string;
33
+ /** Decorators applied to every story in this file. */
34
+ decorators?: DecoratorFn<InferProps<TComponent>>[];
35
+ /** Default args for all stories. */
36
+ args?: Partial<InferProps<TComponent>>;
37
+ /** Arg type definitions for Controls panel. */
38
+ argTypes?: Record<string, unknown>;
39
+ /** Story parameters (backgrounds, viewport, etc.). */
40
+ parameters?: Record<string, unknown>;
41
+ /** Tags for filtering (e.g. "autodocs"). */
42
+ tags?: string[];
43
+ /**
44
+ * Default render function. If omitted, the component is called
45
+ * with args as props: `h(component, args)`.
46
+ */
47
+ render?: (args: InferProps<TComponent>, context: StoryContext<InferProps<TComponent>>) => VNodeChild$1;
48
+ /** Exclude arg names from Controls. */
49
+ excludeStories?: string | string[] | RegExp;
50
+ /** Include only these story names. */
51
+ includeStories?: string | string[] | RegExp;
52
+ }
53
+ interface StoryObj<TMeta extends Meta<any> = Meta> {
54
+ /** Args for this specific story (merged with meta.args). */
55
+ args?: Partial<MetaArgs<TMeta>>;
56
+ /** Arg type overrides. */
57
+ argTypes?: Record<string, unknown>;
58
+ /** Decorators for this story only. */
59
+ decorators?: DecoratorFn<MetaArgs<TMeta>>[];
60
+ /** Parameters for this story. */
61
+ parameters?: Record<string, unknown>;
62
+ /** Tags for this story. */
63
+ tags?: string[];
64
+ /** Override the render function for this story. */
65
+ render?: (args: MetaArgs<TMeta>, context: StoryContext<MetaArgs<TMeta>>) => VNodeChild$1;
66
+ /** Story name override. */
67
+ name?: string;
68
+ /** Play function for interaction tests. */
69
+ play?: (context: {
70
+ canvasElement: HTMLElement;
71
+ args: MetaArgs<TMeta>;
72
+ step: (name: string, fn: () => Promise<void>) => Promise<void>;
73
+ }) => Promise<void> | void;
74
+ }
75
+ /** Extract the args type from a Meta definition. */
76
+ type MetaArgs<TMeta> = TMeta extends Meta<infer C> ? InferProps<C> : Props$1;
77
+ //#endregion
78
+ //#region src/render.d.ts
79
+ /**
80
+ * Render a Pyreon story into a Storybook canvas element.
81
+ *
82
+ * This is the core integration point — Storybook calls this function
83
+ * every time a story needs to be displayed or re-rendered (e.g. when
84
+ * the user changes args via the Controls panel).
85
+ *
86
+ * It handles:
87
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
88
+ * 2. Building the VNode from the story function or component + args
89
+ * 3. Mounting the new VNode into the canvas
90
+ */
91
+ declare function renderToCanvas({
92
+ storyFn,
93
+ showMain,
94
+ showError
95
+ }: {
96
+ storyFn: () => VNodeChild$1;
97
+ storyContext: {
98
+ component?: ComponentFn$1<any>;
99
+ args: Record<string, unknown>;
100
+ [key: string]: unknown;
101
+ };
102
+ showMain: () => void;
103
+ showError: (error: {
104
+ title: string;
105
+ description: string;
106
+ }) => void;
107
+ forceRemount: boolean;
108
+ }, canvasElement: HTMLElement): void;
109
+ /**
110
+ * Default render implementation used when no custom `render` is provided.
111
+ * Simply calls `h(component, args)`.
112
+ */
113
+ declare function defaultRender(component: ComponentFn$1<any>, args: Record<string, unknown>): VNodeChild$1;
114
+ //#endregion
115
+ export { type ComponentFn, type DecoratorFn, Fragment, type InferProps, type Meta, type Props, type PyreonRenderer, type StoryContext, type StoryFn, type StoryObj, type VNode, type VNodeChild, computed, defaultRender, effect, h, mount, renderToCanvas, signal };
116
+ //# sourceMappingURL=index2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/render.ts"],"mappings":";;;;;;;;;UAQiB,cAAA;EACf,SAAA,EAAW,aAAA;EACX,WAAA,EAAa,YAAA;EACb,aAAA,EAAe,WAAA;AAAA;;KAML,UAAA,MAAgB,CAAA,SAAU,aAAA,YAAuB,CAAA,GAAI,OAAA;AAAA,UAIhD,YAAA,SAAqB,OAAA;EACpC,IAAA,EAAM,KAAA;EACN,QAAA,EAAU,MAAA;EACV,OAAA,EAAS,MAAA;EACT,EAAA;EACA,IAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,KAGU,OAAA,SAAgB,OAAA,KAC1B,IAAA,EAAM,KAAA,EACN,OAAA,EAAS,YAAA,CAAa,KAAA,MACnB,YAAA;AAAA,KAEO,WAAA,SAAoB,OAAA,KAC9B,OAAA,EAAS,OAAA,CAAQ,KAAA,GACjB,OAAA,EAAS,YAAA,CAAa,KAAA,MACnB,YAAA;AAAA,UAIY,IAAA,oBAAwB,aAAA,QAAmB,aAAA;EA1BhC;EA4B1B,SAAA,GAAY,UAAA;EA5BmD;EA8B/D,KAAA;EA9BoE;EAgCpE,UAAA,GAAa,WAAA,CAAY,UAAA,CAAW,UAAA;EAhCV;EAkC1B,IAAA,GAAO,OAAA,CAAQ,UAAA,CAAW,UAAA;EAlC4B;EAoCtD,QAAA,GAAW,MAAA;EApCoD;EAsC/D,UAAA,GAAa,MAAA;EAtCuD;EAwCpE,IAAA;EApC2B;;;;EAyC3B,MAAA,IACE,IAAA,EAAM,UAAA,CAAW,UAAA,GACjB,OAAA,EAAS,YAAA,CAAa,UAAA,CAAW,UAAA,OAC9B,YAAA;EAzCI;EA2CT,cAAA,uBAAqC,MAAA;EA3CtB;EA6Cf,cAAA,uBAAqC,MAAA;AAAA;AAAA,UAKtB,QAAA,eAAuB,IAAA,QAAY,IAAA;EApD5C;EAsDN,IAAA,GAAO,OAAA,CAAQ,QAAA,CAAS,KAAA;EArDd;EAuDV,QAAA,GAAW,MAAA;EAtDF;EAwDT,UAAA,GAAa,WAAA,CAAY,QAAA,CAAS,KAAA;EAtDlC;EAwDA,UAAA,GAAa,MAAA;EAtDb;EAwDA,IAAA;EAxDQ;EA0DR,MAAA,IACE,IAAA,EAAM,QAAA,CAAS,KAAA,GACf,OAAA,EAAS,YAAA,CAAa,QAAA,CAAS,KAAA,OAC5B,YAAA;EA1DY;EA4DjB,IAAA;EA5D0B;EA8D1B,IAAA,IAAQ,OAAA;IACN,aAAA,EAAe,WAAA;IACf,IAAA,EAAM,QAAA,CAAS,KAAA;IACf,IAAA,GAAO,IAAA,UAAc,EAAA,QAAU,OAAA,WAAkB,OAAA;EAAA,MAC7C,OAAA;AAAA;;KAIH,QAAA,UAAkB,KAAA,SAAc,IAAA,YAAgB,UAAA,CAAW,CAAA,IAAK,OAAA;;;;;;;AA7FrE;;;;;;;;iBCagB,cAAA,CAAA;EAEZ,OAAA;EACA,QAAA;EACA;AAAA;EAEA,OAAA,QAAe,YAAA;EACf,YAAA;IACE,SAAA,GAAY,aAAA;IACZ,IAAA,EAAM,MAAA;IAAA,CACL,GAAA;EAAA;EAEH,QAAA;EACA,SAAA,GAAY,KAAA;IAAS,KAAA;IAAe,WAAA;EAAA;EACpC,YAAA;AAAA,GAEF,aAAA,EAAe,WAAA;;;;;iBAgCD,aAAA,CACd,SAAA,EAAW,aAAA,OACX,IAAA,EAAM,MAAA,oBACL,YAAA"}
@@ -0,0 +1,17 @@
1
+ import { join } from "node:path";
2
+
3
+ //#region src/preset.ts
4
+ /**
5
+ * Storybook preset for @pyreon/storybook.
6
+ *
7
+ * This file is loaded by Storybook's server when the user sets
8
+ * `framework: "@pyreon/storybook"` in their `.storybook/main.ts`.
9
+ *
10
+ * It tells Storybook:
11
+ * - Which renderer to use (via the preview entry)
12
+ * - What framework name to report
13
+ */
14
+
15
+ //#endregion
16
+ export { addons, core, previewAnnotations };
17
+ //# sourceMappingURL=preset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset.d.ts","names":[],"sources":["../../src/preset.ts"],"mappings":""}
@@ -0,0 +1,19 @@
1
+ //#region src/preset.d.ts
2
+ /**
3
+ * Storybook preset for @pyreon/storybook.
4
+ *
5
+ * This file is loaded by Storybook's server when the user sets
6
+ * `framework: "@pyreon/storybook"` in their `.storybook/main.ts`.
7
+ *
8
+ * It tells Storybook:
9
+ * - Which renderer to use (via the preview entry)
10
+ * - What framework name to report
11
+ */
12
+ declare const addons: string[];
13
+ declare const previewAnnotations: string[];
14
+ declare const core: {
15
+ renderer: string;
16
+ };
17
+ //#endregion
18
+ export { addons, core, previewAnnotations };
19
+ //# sourceMappingURL=preset2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset2.d.ts","names":[],"sources":["../../src/preset.ts"],"mappings":";;AAiBA;;;;;AAEA;;;;cAFa,MAAA;AAAA,cAEA,kBAAA;AAAA,cAEA,IAAA;EAEZ,QAAA;AAAA"}
@@ -0,0 +1,57 @@
1
+ import { h } from "@pyreon/core";
2
+ import { mount } from "@pyreon/runtime-dom";
3
+
4
+ //#region src/render.ts
5
+ /**
6
+ * State tracked per canvas element so we can clean up between renders.
7
+ */
8
+
9
+ /**
10
+ * Render a Pyreon story into a Storybook canvas element.
11
+ *
12
+ * This is the core integration point — Storybook calls this function
13
+ * every time a story needs to be displayed or re-rendered (e.g. when
14
+ * the user changes args via the Controls panel).
15
+ *
16
+ * It handles:
17
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
18
+ * 2. Building the VNode from the story function or component + args
19
+ * 3. Mounting the new VNode into the canvas
20
+ */
21
+ function renderToCanvas({
22
+ storyFn,
23
+ showMain,
24
+ showError
25
+ }, canvasElement) {
26
+ const prevUnmount = canvasState.get(canvasElement);
27
+ if (prevUnmount) {
28
+ prevUnmount();
29
+ canvasState.delete(canvasElement);
30
+ }
31
+ try {
32
+ const unmount = mount(storyFn(), canvasElement);
33
+ canvasState.set(canvasElement, unmount);
34
+ showMain();
35
+ } catch (err) {
36
+ showError({
37
+ title: `Error rendering story`,
38
+ description: (err instanceof Error ? err : new Error(String(err))).message
39
+ });
40
+ }
41
+ }
42
+
43
+ //#endregion
44
+ //#region src/preview.ts
45
+ /**
46
+ * Default render function — if the story CSF has a `component` but no
47
+ * explicit `render`, this is used to create the VNode.
48
+ */
49
+ function render(args, context) {
50
+ const Component = context.component;
51
+ if (!Component) throw new Error("[@pyreon/storybook] No component provided. Either set `component` in your meta or provide a `render` function.");
52
+ return h(Component, args);
53
+ }
54
+
55
+ //#endregion
56
+ export { render, renderToCanvas };
57
+ //# sourceMappingURL=preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.d.ts","names":[],"sources":["../../src/render.ts","../../src/preview.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cAAA,CACd;EACE,OAAA;EACA,QAAA;EACA;AAAA,CAAA,EAYF,aAAA,EACM;EAEN,MAAM,WAAA,GAAc,WAAA,CAAY,GAAA,CAAI,aAAA,CAAc;EAClD,IAAI,WAAA,EAAa;IACf,WAAA,CAAA,CAAa;IACb,WAAA,CAAY,MAAA,CAAO,aAAA,CAAc;;EAGnC,IAAI;IAMF,MAAM,OAAA,GAAU,KAAA,CAHA,OAAA,CAAA,CAAS,EAGM,aAAA,CAAc;IAC7C,WAAA,CAAY,GAAA,CAAI,aAAA,EAAe,OAAA,CAAQ;IAEvC,QAAA,CAAA,CAAU;WACH,GAAA,EAAK;IAEZ,SAAA,CAAU;MACR,KAAA,EAAO,uBAAA;MACP,WAAA,EAAA,CAHY,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,EAG5C;KACpB,CAAC;;;;;;;;;;AC5CN,SAAgB,MAAA,CACd,IAAA,EACA,OAAA,EACY;EACZ,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA;EAC1B,IAAI,CAAC,SAAA,EACH,MAAM,IAAI,KAAA,CACR,gHAAA,CACD;EAEH,OAAO,CAAA,CAAE,SAAA,EAAW,IAAA,CAAK"}
@@ -0,0 +1,45 @@
1
+ import { ComponentFn, VNodeChild } from "@pyreon/core";
2
+
3
+ //#region src/render.d.ts
4
+ /**
5
+ * Render a Pyreon story into a Storybook canvas element.
6
+ *
7
+ * This is the core integration point — Storybook calls this function
8
+ * every time a story needs to be displayed or re-rendered (e.g. when
9
+ * the user changes args via the Controls panel).
10
+ *
11
+ * It handles:
12
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
13
+ * 2. Building the VNode from the story function or component + args
14
+ * 3. Mounting the new VNode into the canvas
15
+ */
16
+ declare function renderToCanvas({
17
+ storyFn,
18
+ showMain,
19
+ showError
20
+ }: {
21
+ storyFn: () => VNodeChild;
22
+ storyContext: {
23
+ component?: ComponentFn<any>;
24
+ args: Record<string, unknown>;
25
+ [key: string]: unknown;
26
+ };
27
+ showMain: () => void;
28
+ showError: (error: {
29
+ title: string;
30
+ description: string;
31
+ }) => void;
32
+ forceRemount: boolean;
33
+ }, canvasElement: HTMLElement): void;
34
+ //#endregion
35
+ //#region src/preview.d.ts
36
+ /**
37
+ * Default render function — if the story CSF has a `component` but no
38
+ * explicit `render`, this is used to create the VNode.
39
+ */
40
+ declare function render<TArgs extends Record<string, unknown>>(args: TArgs, context: {
41
+ component?: ComponentFn<any>;
42
+ }): VNodeChild;
43
+ //#endregion
44
+ export { render, renderToCanvas };
45
+ //# sourceMappingURL=preview2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview2.d.ts","names":[],"sources":["../../src/render.ts","../../src/preview.ts"],"mappings":";;;;;AAqBA;;;;;;;;;;iBAAgB,cAAA,CAAA;EAEZ,OAAA;EACA,QAAA;EACA;AAAA;EAEA,OAAA,QAAe,UAAA;EACf,YAAA;IACE,SAAA,GAAY,WAAA;IACZ,IAAA,EAAM,MAAA;IAAA,CACL,GAAA;EAAA;EAEH,QAAA;EACA,SAAA,GAAY,KAAA;IAAS,KAAA;IAAe,WAAA;EAAA;EACpC,YAAA;AAAA,GAEF,aAAA,EAAe,WAAA;;;;;;;iBCpBD,MAAA,eAAqB,MAAA,kBAAA,CACnC,IAAA,EAAM,KAAA,EACN,OAAA;EAAW,SAAA,GAAY,WAAA;AAAA,IACtB,UAAA"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@pyreon/storybook",
3
+ "version": "0.0.1",
4
+ "description": "Storybook renderer for Pyreon — mount, render, and interact with Pyreon components in Storybook",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/pyreon/fundamentals.git",
9
+ "directory": "packages/storybook"
10
+ },
11
+ "homepage": "https://github.com/pyreon/fundamentals/tree/main/packages/storybook#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/pyreon/fundamentals/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "files": [
19
+ "lib",
20
+ "src",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "main": "./lib/index.js",
27
+ "module": "./lib/index.js",
28
+ "types": "./lib/types/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "bun": "./src/index.ts",
32
+ "import": "./lib/index.js",
33
+ "types": "./lib/types/index.d.ts"
34
+ },
35
+ "./preset": {
36
+ "bun": "./src/preset.ts",
37
+ "import": "./lib/preset.js",
38
+ "types": "./lib/types/preset.d.ts"
39
+ },
40
+ "./preview": {
41
+ "bun": "./src/preview.ts",
42
+ "import": "./lib/preview.js",
43
+ "types": "./lib/types/preview.d.ts"
44
+ },
45
+ "./package.json": "./package.json"
46
+ },
47
+ "scripts": {
48
+ "build": "vl_rolldown_build",
49
+ "dev": "vl_rolldown_build-watch",
50
+ "test": "vitest run",
51
+ "typecheck": "tsc --noEmit"
52
+ },
53
+ "peerDependencies": {
54
+ "@pyreon/core": "^0.2.1",
55
+ "@pyreon/reactivity": "^0.2.1",
56
+ "@pyreon/runtime-dom": "^0.2.1",
57
+ "storybook": ">=8.0.0"
58
+ }
59
+ }
package/src/index.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @pyreon/storybook — Storybook renderer for Pyreon components.
3
+ *
4
+ * Usage in .storybook/main.ts:
5
+ * framework: "@pyreon/storybook"
6
+ *
7
+ * Usage in stories:
8
+ * import type { Meta, StoryObj } from "@pyreon/storybook"
9
+ * import { Button } from "./Button"
10
+ *
11
+ * const meta = {
12
+ * component: Button,
13
+ * args: { label: "Click me" },
14
+ * } satisfies Meta<typeof Button>
15
+ *
16
+ * export default meta
17
+ * type Story = StoryObj<typeof meta>
18
+ *
19
+ * export const Primary: Story = {
20
+ * args: { variant: "primary" },
21
+ * }
22
+ */
23
+
24
+ // ─── Types ───────────────────────────────────────────────────────────────────
25
+
26
+ export type {
27
+ DecoratorFn,
28
+ InferProps,
29
+ Meta,
30
+ PyreonRenderer,
31
+ StoryContext,
32
+ StoryFn,
33
+ StoryObj,
34
+ } from './types'
35
+
36
+ // ─── Renderer ────────────────────────────────────────────────────────────────
37
+
38
+ export { renderToCanvas, defaultRender } from './render'
39
+
40
+ // ─── Pyreon re-exports for convenience ───────────────────────────────────────
41
+
42
+ export { h, Fragment } from '@pyreon/core'
43
+ export type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'
44
+ export { signal, computed, effect } from '@pyreon/reactivity'
45
+ export { mount } from '@pyreon/runtime-dom'
package/src/preset.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Storybook preset for @pyreon/storybook.
3
+ *
4
+ * This file is loaded by Storybook's server when the user sets
5
+ * `framework: "@pyreon/storybook"` in their `.storybook/main.ts`.
6
+ *
7
+ * It tells Storybook:
8
+ * - Which renderer to use (via the preview entry)
9
+ * - What framework name to report
10
+ */
11
+
12
+ import { dirname, join } from 'node:path'
13
+
14
+ function _getAbsolutePath(value: string): string {
15
+ return dirname(require.resolve(join(value, 'package.json')))
16
+ }
17
+
18
+ export const addons: string[] = []
19
+
20
+ export const previewAnnotations: string[] = [join(__dirname, 'preview')]
21
+
22
+ export const core = {
23
+ renderer: '@pyreon/storybook',
24
+ }
package/src/preview.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { h } from '@pyreon/core'
2
+ import type { ComponentFn, VNodeChild } from '@pyreon/core'
3
+ import { renderToCanvas } from './render'
4
+
5
+ /**
6
+ * Preview entry — Storybook loads this in the preview iframe.
7
+ *
8
+ * Exports the render function and default decorators/parameters
9
+ * that apply to all stories using this renderer.
10
+ */
11
+
12
+ export { renderToCanvas }
13
+
14
+ /**
15
+ * Default render function — if the story CSF has a `component` but no
16
+ * explicit `render`, this is used to create the VNode.
17
+ */
18
+ export function render<TArgs extends Record<string, unknown>>(
19
+ args: TArgs,
20
+ context: { component?: ComponentFn<any> },
21
+ ): VNodeChild {
22
+ const Component = context.component
23
+ if (!Component) {
24
+ throw new Error(
25
+ '[@pyreon/storybook] No component provided. Either set `component` in your meta or provide a `render` function.',
26
+ )
27
+ }
28
+ return h(Component, args)
29
+ }
package/src/render.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { h } from '@pyreon/core'
2
+ import type { ComponentFn, VNodeChild } from '@pyreon/core'
3
+ import { mount } from '@pyreon/runtime-dom'
4
+
5
+ /**
6
+ * State tracked per canvas element so we can clean up between renders.
7
+ */
8
+ const canvasState = new WeakMap<HTMLElement, () => void>()
9
+
10
+ /**
11
+ * Render a Pyreon story into a Storybook canvas element.
12
+ *
13
+ * This is the core integration point — Storybook calls this function
14
+ * every time a story needs to be displayed or re-rendered (e.g. when
15
+ * the user changes args via the Controls panel).
16
+ *
17
+ * It handles:
18
+ * 1. Cleaning up the previous mount (disposing effects, removing DOM)
19
+ * 2. Building the VNode from the story function or component + args
20
+ * 3. Mounting the new VNode into the canvas
21
+ */
22
+ export function renderToCanvas(
23
+ {
24
+ storyFn,
25
+ showMain,
26
+ showError,
27
+ }: {
28
+ storyFn: () => VNodeChild
29
+ storyContext: {
30
+ component?: ComponentFn<any>
31
+ args: Record<string, unknown>
32
+ [key: string]: unknown
33
+ }
34
+ showMain: () => void
35
+ showError: (error: { title: string; description: string }) => void
36
+ forceRemount: boolean
37
+ },
38
+ canvasElement: HTMLElement,
39
+ ): void {
40
+ // Always clean up the previous render
41
+ const prevUnmount = canvasState.get(canvasElement)
42
+ if (prevUnmount) {
43
+ prevUnmount()
44
+ canvasState.delete(canvasElement)
45
+ }
46
+
47
+ try {
48
+ // Get the story result — either from a custom render function
49
+ // or by calling the component with args
50
+ const element = storyFn()
51
+
52
+ // Mount the Pyreon VNode tree into the canvas
53
+ const unmount = mount(element, canvasElement)
54
+ canvasState.set(canvasElement, unmount)
55
+
56
+ showMain()
57
+ } catch (err) {
58
+ const error = err instanceof Error ? err : new Error(String(err))
59
+ showError({
60
+ title: `Error rendering story`,
61
+ description: error.message,
62
+ })
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Default render implementation used when no custom `render` is provided.
68
+ * Simply calls `h(component, args)`.
69
+ */
70
+ export function defaultRender(
71
+ component: ComponentFn<any>,
72
+ args: Record<string, unknown>,
73
+ ): VNodeChild {
74
+ return h(component, args)
75
+ }