@pyreon/storybook 0.2.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"e27e4752-1","name":"render.ts"},{"uid":"e27e4752-3","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"e27e4752-1":{"renderedLength":1288,"gzipLength":673,"brotliLength":0,"metaUid":"e27e4752-0"},"e27e4752-3":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"e27e4752-2"}},"nodeMetas":{"e27e4752-0":{"id":"/src/render.ts","moduleParts":{"index.js":"e27e4752-1"},"imported":[{"uid":"e27e4752-4"},{"uid":"e27e4752-6"}],"importedBy":[{"uid":"e27e4752-2"}]},"e27e4752-2":{"id":"/src/index.ts","moduleParts":{"index.js":"e27e4752-3"},"imported":[{"uid":"e27e4752-0"},{"uid":"e27e4752-4"},{"uid":"e27e4752-5"},{"uid":"e27e4752-6"}],"importedBy":[],"isEntry":true},"e27e4752-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"e27e4752-2"},{"uid":"e27e4752-0"}]},"e27e4752-5":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"e27e4752-2"}]},"e27e4752-6":{"id":"@pyreon/runtime-dom","moduleParts":{},"imported":[],"importedBy":[{"uid":"e27e4752-2"},{"uid":"e27e4752-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"home/runner/work/fundamentals/fundamentals/node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","uid":"a15c263f-1"},{"name":"src","children":[{"uid":"a15c263f-3","name":"render-impl.tsx"},{"uid":"a15c263f-5","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"a15c263f-1":{"renderedLength":1640,"gzipLength":827,"brotliLength":0,"metaUid":"a15c263f-0"},"a15c263f-3":{"renderedLength":1280,"gzipLength":673,"brotliLength":0,"metaUid":"a15c263f-2"},"a15c263f-5":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"a15c263f-4"}},"nodeMetas":{"a15c263f-0":{"id":"/home/runner/work/fundamentals/fundamentals/node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","moduleParts":{"index.js":"a15c263f-1"},"imported":[],"importedBy":[{"uid":"a15c263f-2"}]},"a15c263f-2":{"id":"/src/render-impl.tsx","moduleParts":{"index.js":"a15c263f-3"},"imported":[{"uid":"a15c263f-9"},{"uid":"a15c263f-0"}],"importedBy":[{"uid":"a15c263f-6"}]},"a15c263f-4":{"id":"/src/index.ts","moduleParts":{"index.js":"a15c263f-5"},"imported":[{"uid":"a15c263f-6"},{"uid":"a15c263f-7"},{"uid":"a15c263f-8"},{"uid":"a15c263f-9"}],"importedBy":[],"isEntry":true},"a15c263f-6":{"id":"/src/render.ts","moduleParts":{},"imported":[{"uid":"a15c263f-2"}],"importedBy":[{"uid":"a15c263f-4"}]},"a15c263f-7":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"a15c263f-4"}]},"a15c263f-8":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"a15c263f-4"}]},"a15c263f-9":{"id":"@pyreon/runtime-dom","moduleParts":{},"imported":[],"importedBy":[{"uid":"a15c263f-4"},{"uid":"a15c263f-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"preview.js","children":[{"name":"src","children":[{"uid":"4ccb792b-1","name":"render.ts"},{"uid":"4ccb792b-3","name":"preview.ts"}]}]}],"isRoot":true},"nodeParts":{"4ccb792b-1":{"renderedLength":1094,"gzipLength":589,"brotliLength":0,"metaUid":"4ccb792b-0"},"4ccb792b-3":{"renderedLength":421,"gzipLength":284,"brotliLength":0,"metaUid":"4ccb792b-2"}},"nodeMetas":{"4ccb792b-0":{"id":"/src/render.ts","moduleParts":{"preview.js":"4ccb792b-1"},"imported":[{"uid":"4ccb792b-4"},{"uid":"4ccb792b-5"}],"importedBy":[{"uid":"4ccb792b-2"}]},"4ccb792b-2":{"id":"/src/preview.ts","moduleParts":{"preview.js":"4ccb792b-3"},"imported":[{"uid":"4ccb792b-4"},{"uid":"4ccb792b-0"}],"importedBy":[],"isEntry":true},"4ccb792b-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"4ccb792b-2"},{"uid":"4ccb792b-0"}]},"4ccb792b-5":{"id":"@pyreon/runtime-dom","moduleParts":{},"imported":[],"importedBy":[{"uid":"4ccb792b-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"preview.js","children":[{"name":"home/runner/work/fundamentals/fundamentals/node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","uid":"3cdd8ae0-1"},{"name":"src","children":[{"uid":"3cdd8ae0-3","name":"render-impl.tsx"},{"uid":"3cdd8ae0-5","name":"preview-impl.tsx"},{"uid":"3cdd8ae0-7","name":"preview.ts"}]}]}],"isRoot":true},"nodeParts":{"3cdd8ae0-1":{"renderedLength":1634,"gzipLength":823,"brotliLength":0,"metaUid":"3cdd8ae0-0"},"3cdd8ae0-3":{"renderedLength":1100,"gzipLength":595,"brotliLength":0,"metaUid":"3cdd8ae0-2"},"3cdd8ae0-5":{"renderedLength":452,"gzipLength":313,"brotliLength":0,"metaUid":"3cdd8ae0-4"},"3cdd8ae0-7":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"3cdd8ae0-6"}},"nodeMetas":{"3cdd8ae0-0":{"id":"/home/runner/work/fundamentals/fundamentals/node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","moduleParts":{"preview.js":"3cdd8ae0-1"},"imported":[],"importedBy":[{"uid":"3cdd8ae0-4"},{"uid":"3cdd8ae0-2"}]},"3cdd8ae0-2":{"id":"/src/render-impl.tsx","moduleParts":{"preview.js":"3cdd8ae0-3"},"imported":[{"uid":"3cdd8ae0-8"},{"uid":"3cdd8ae0-0"}],"importedBy":[{"uid":"3cdd8ae0-4"}]},"3cdd8ae0-4":{"id":"/src/preview-impl.tsx","moduleParts":{"preview.js":"3cdd8ae0-5"},"imported":[{"uid":"3cdd8ae0-2"},{"uid":"3cdd8ae0-0"}],"importedBy":[{"uid":"3cdd8ae0-6"}]},"3cdd8ae0-6":{"id":"/src/preview.ts","moduleParts":{"preview.js":"3cdd8ae0-7"},"imported":[{"uid":"3cdd8ae0-4"}],"importedBy":[],"isEntry":true},"3cdd8ae0-8":{"id":"@pyreon/runtime-dom","moduleParts":{},"imported":[],"importedBy":[{"uid":"3cdd8ae0-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/index.js CHANGED
@@ -1,8 +1,57 @@
1
- import { Fragment, h, h as h$1 } from "@pyreon/core";
2
1
  import { mount, mount as mount$1 } from "@pyreon/runtime-dom";
2
+ import { Fragment, h } from "@pyreon/core";
3
3
  import { computed, effect, signal } from "@pyreon/reactivity";
4
4
 
5
- //#region src/render.ts
5
+ //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
6
+ /**
7
+ * Hyperscript function — the compiled output of JSX.
8
+ * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
9
+ *
10
+ * Generic on P so TypeScript validates props match the component's signature
11
+ * at the call site, then stores the result in the loosely-typed VNode.
12
+ */
13
+ /** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
14
+ const EMPTY_PROPS = {};
15
+ function h$1(type, props, ...children) {
16
+ return {
17
+ type,
18
+ props: props ?? EMPTY_PROPS,
19
+ children: normalizeChildren(children),
20
+ key: props?.key ?? null
21
+ };
22
+ }
23
+ function normalizeChildren(children) {
24
+ for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
25
+ return children;
26
+ }
27
+ function flattenChildren(children) {
28
+ const result = [];
29
+ for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));
30
+ else result.push(child);
31
+ return result;
32
+ }
33
+ /**
34
+ * JSX automatic runtime.
35
+ *
36
+ * When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
37
+ * rewrites JSX to imports from this file automatically:
38
+ * <div class="x" /> → jsx("div", { class: "x" })
39
+ */
40
+ function jsx(type, props, key) {
41
+ const { children, ...rest } = props;
42
+ const propsWithKey = key != null ? {
43
+ ...rest,
44
+ key
45
+ } : rest;
46
+ if (typeof type === "function") return h$1(type, children !== void 0 ? {
47
+ ...propsWithKey,
48
+ children
49
+ } : propsWithKey);
50
+ return h$1(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
51
+ }
52
+
53
+ //#endregion
54
+ //#region src/render-impl.tsx
6
55
  /**
7
56
  * State tracked per canvas element so we can clean up between renders.
8
57
  */
@@ -38,10 +87,9 @@ function renderToCanvas({ storyFn, showMain, showError }, canvasElement) {
38
87
  }
39
88
  /**
40
89
  * Default render implementation used when no custom `render` is provided.
41
- * Simply calls `h(component, args)`.
42
90
  */
43
91
  function defaultRender(component, args) {
44
- return h$1(component, args);
92
+ return /* @__PURE__ */ jsx(component, { ...args });
45
93
  }
46
94
 
47
95
  //#endregion
package/lib/index.js.map CHANGED
@@ -1 +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"}
1
+ {"version":3,"file":"index.js","names":["h","mount"],"sources":["../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/render-impl.tsx"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import 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 const element = storyFn()\n const unmount = mount(element, canvasElement)\n canvasState.set(canvasElement, unmount)\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 */\nexport function defaultRender(\n component: ComponentFn<any>,\n args: Record<string, unknown>,\n): VNodeChild {\n const Component = component\n return <Component {...args} />\n}\n"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;;;AAWA,MAAM,cAAc,EAAE;AACtB,SAASA,IAAE,MAAM,OAAO,GAAG,UAAU;AACpC,QAAO;EACN;EACA,OAAO,SAAS;EAChB,UAAU,kBAAkB,SAAS;EACrC,KAAK,OAAO,OAAO;EACnB;;AAEF,SAAS,kBAAkB,UAAU;AACpC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAK,KAAI,MAAM,QAAQ,SAAS,GAAG,CAAE,QAAO,gBAAgB,SAAS;AAC1G,QAAO;;AAER,SAAS,gBAAgB,UAAU;CAClC,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,SAAS,SAAU,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,GAAG,gBAAgB,MAAM,CAAC;KACzF,QAAO,KAAK,MAAM;AACvB,QAAO;;;;;;;;;AAYR,SAAS,IAAI,MAAM,OAAO,KAAK;CAC9B,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,eAAe,OAAO,OAAO;EAClC,GAAG;EACH;EACA,GAAG;AACJ,KAAI,OAAO,SAAS,WAAY,QAAOA,IAAE,MAAM,aAAa,KAAK,IAAI;EACpE,GAAG;EACH;EACA,GAAG,aAAa;AACjB,QAAOA,IAAE,MAAM,cAAc,GAAG,aAAa,KAAK,IAAI,EAAE,GAAG,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;;;;;;;;AC5C5G,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;EAEF,MAAM,UAAUC,QADA,SAAS,EACM,cAAc;AAC7C,cAAY,IAAI,eAAe,QAAQ;AACvC,YAAU;UACH,KAAK;AAEZ,YAAU;GACR,OAAO;GACP,cAHY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAG5C;GACpB,CAAC;;;;;;AAON,SAAgB,cACd,WACA,MACY;AAEZ,QAAO,oBADW,WACX,EAAW,GAAI,MAAQ"}
package/lib/preview.js CHANGED
@@ -1,7 +1,55 @@
1
- import { h } from "@pyreon/core";
2
1
  import { mount } from "@pyreon/runtime-dom";
3
2
 
4
- //#region src/render.ts
3
+ //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
4
+ /**
5
+ * Hyperscript function — the compiled output of JSX.
6
+ * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
7
+ *
8
+ * Generic on P so TypeScript validates props match the component's signature
9
+ * at the call site, then stores the result in the loosely-typed VNode.
10
+ */
11
+ /** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
12
+ const EMPTY_PROPS = {};
13
+ function h(type, props, ...children) {
14
+ return {
15
+ type,
16
+ props: props ?? EMPTY_PROPS,
17
+ children: normalizeChildren(children),
18
+ key: props?.key ?? null
19
+ };
20
+ }
21
+ function normalizeChildren(children) {
22
+ for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
23
+ return children;
24
+ }
25
+ function flattenChildren(children) {
26
+ const result = [];
27
+ for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));
28
+ else result.push(child);
29
+ return result;
30
+ }
31
+ /**
32
+ * JSX automatic runtime.
33
+ *
34
+ * When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
35
+ * rewrites JSX to imports from this file automatically:
36
+ * <div class="x" /> → jsx("div", { class: "x" })
37
+ */
38
+ function jsx(type, props, key) {
39
+ const { children, ...rest } = props;
40
+ const propsWithKey = key != null ? {
41
+ ...rest,
42
+ key
43
+ } : rest;
44
+ if (typeof type === "function") return h(type, children !== void 0 ? {
45
+ ...propsWithKey,
46
+ children
47
+ } : propsWithKey);
48
+ return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
49
+ }
50
+
51
+ //#endregion
52
+ //#region src/render-impl.tsx
5
53
  /**
6
54
  * State tracked per canvas element so we can clean up between renders.
7
55
  */
@@ -37,7 +85,7 @@ function renderToCanvas({ storyFn, showMain, showError }, canvasElement) {
37
85
  }
38
86
 
39
87
  //#endregion
40
- //#region src/preview.ts
88
+ //#region src/preview-impl.tsx
41
89
  /**
42
90
  * Default render function — if the story CSF has a `component` but no
43
91
  * explicit `render`, this is used to create the VNode.
@@ -45,7 +93,7 @@ function renderToCanvas({ storyFn, showMain, showError }, canvasElement) {
45
93
  function render(args, context) {
46
94
  const Component = context.component;
47
95
  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);
96
+ return /* @__PURE__ */ jsx(Component, { ...args });
49
97
  }
50
98
 
51
99
  //#endregion
@@ -1 +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"}
1
+ {"version":3,"file":"preview.js","names":[],"sources":["../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/render-impl.tsx","../src/preview-impl.tsx"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import 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 const element = storyFn()\n const unmount = mount(element, canvasElement)\n canvasState.set(canvasElement, unmount)\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 */\nexport function defaultRender(\n component: ComponentFn<any>,\n args: Record<string, unknown>,\n): VNodeChild {\n const Component = component\n return <Component {...args} />\n}\n","import type { ComponentFn, VNodeChild } from '@pyreon/core'\nimport { renderToCanvas } from './render-impl'\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 <Component {...args} />\n}\n"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;AAWA,MAAM,cAAc,EAAE;AACtB,SAAS,EAAE,MAAM,OAAO,GAAG,UAAU;AACpC,QAAO;EACN;EACA,OAAO,SAAS;EAChB,UAAU,kBAAkB,SAAS;EACrC,KAAK,OAAO,OAAO;EACnB;;AAEF,SAAS,kBAAkB,UAAU;AACpC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAK,KAAI,MAAM,QAAQ,SAAS,GAAG,CAAE,QAAO,gBAAgB,SAAS;AAC1G,QAAO;;AAER,SAAS,gBAAgB,UAAU;CAClC,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,SAAS,SAAU,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,GAAG,gBAAgB,MAAM,CAAC;KACzF,QAAO,KAAK,MAAM;AACvB,QAAO;;;;;;;;;AAYR,SAAS,IAAI,MAAM,OAAO,KAAK;CAC9B,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,eAAe,OAAO,OAAO;EAClC,GAAG;EACH;EACA,GAAG;AACJ,KAAI,OAAO,SAAS,WAAY,QAAO,EAAE,MAAM,aAAa,KAAK,IAAI;EACpE,GAAG;EACH;EACA,GAAG,aAAa;AACjB,QAAO,EAAE,MAAM,cAAc,GAAG,aAAa,KAAK,IAAI,EAAE,GAAG,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;;;;;;;;AC5C5G,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;EAEF,MAAM,UAAU,MADA,SAAS,EACM,cAAc;AAC7C,cAAY,IAAI,eAAe,QAAQ;AACvC,YAAU;UACH,KAAK;AAEZ,YAAU;GACR,OAAO;GACP,cAHY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAG5C;GACpB,CAAC;;;;;;;;;;ACvCN,SAAgB,OACd,MACA,SACY;CACZ,MAAM,YAAY,QAAQ;AAC1B,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iHACD;AAEH,QAAO,oBAAC,WAAD,EAAW,GAAI,MAAQ"}
@@ -1,5 +1,5 @@
1
- import { ComponentFn, ComponentFn as ComponentFn$1, Fragment, Props, Props as Props$1, VNode, VNodeChild, VNodeChild as VNodeChild$1, h } from "@pyreon/core";
2
1
  import { mount } from "@pyreon/runtime-dom";
2
+ import { ComponentFn, ComponentFn as ComponentFn$1, Fragment, Props, Props as Props$1, VNode, VNodeChild, VNodeChild as VNodeChild$1, h } from "@pyreon/core";
3
3
  import { computed, effect, signal } from "@pyreon/reactivity";
4
4
 
5
5
  //#region src/types.d.ts
@@ -75,7 +75,7 @@ interface StoryObj<TMeta extends Meta<any> = Meta> {
75
75
  /** Extract the args type from a Meta definition. */
76
76
  type MetaArgs<TMeta> = TMeta extends Meta<infer C> ? InferProps<C> : Props$1;
77
77
  //#endregion
78
- //#region src/render.d.ts
78
+ //#region src/render-impl.d.ts
79
79
  /**
80
80
  * Render a Pyreon story into a Storybook canvas element.
81
81
  *
@@ -108,7 +108,6 @@ declare function renderToCanvas({
108
108
  }, canvasElement: HTMLElement): void;
109
109
  /**
110
110
  * Default render implementation used when no custom `render` is provided.
111
- * Simply calls `h(component, args)`.
112
111
  */
113
112
  declare function defaultRender(component: ComponentFn$1<any>, args: Record<string, unknown>): VNodeChild$1;
114
113
  //#endregion
@@ -1 +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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/render-impl.tsx"],"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;;;;;;;;iBCYgB,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;;;;iBA0BD,aAAA,CACd,SAAA,EAAW,aAAA,OACX,IAAA,EAAM,MAAA,oBACL,YAAA"}
@@ -1,7 +1,57 @@
1
- import { h } from "@pyreon/core";
2
1
  import { mount } from "@pyreon/runtime-dom";
3
2
 
4
- //#region src/render.ts
3
+ //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
4
+ /**
5
+ * Hyperscript function — the compiled output of JSX.
6
+ * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
7
+ *
8
+ * Generic on P so TypeScript validates props match the component's signature
9
+ * at the call site, then stores the result in the loosely-typed VNode.
10
+ */
11
+ /** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
12
+
13
+ function h(type, props, ...children) {
14
+ return {
15
+ type,
16
+ props: props ?? EMPTY_PROPS,
17
+ children: normalizeChildren(children),
18
+ key: props?.key ?? null
19
+ };
20
+ }
21
+ function normalizeChildren(children) {
22
+ for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
23
+ return children;
24
+ }
25
+ function flattenChildren(children) {
26
+ const result = [];
27
+ for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));else result.push(child);
28
+ return result;
29
+ }
30
+ /**
31
+ * JSX automatic runtime.
32
+ *
33
+ * When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
34
+ * rewrites JSX to imports from this file automatically:
35
+ * <div class="x" /> → jsx("div", { class: "x" })
36
+ */
37
+ function jsx(type, props, key) {
38
+ const {
39
+ children,
40
+ ...rest
41
+ } = props;
42
+ const propsWithKey = key != null ? {
43
+ ...rest,
44
+ key
45
+ } : rest;
46
+ if (typeof type === "function") return h(type, children !== void 0 ? {
47
+ ...propsWithKey,
48
+ children
49
+ } : propsWithKey);
50
+ return h(type, propsWithKey, ...(children === void 0 ? [] : Array.isArray(children) ? children : [children]));
51
+ }
52
+
53
+ //#endregion
54
+ //#region src/render-impl.tsx
5
55
  /**
6
56
  * State tracked per canvas element so we can clean up between renders.
7
57
  */
@@ -41,7 +91,7 @@ function renderToCanvas({
41
91
  }
42
92
 
43
93
  //#endregion
44
- //#region src/preview.ts
94
+ //#region src/preview-impl.tsx
45
95
  /**
46
96
  * Default render function — if the story CSF has a `component` but no
47
97
  * explicit `render`, this is used to create the VNode.
@@ -49,7 +99,9 @@ function renderToCanvas({
49
99
  function render(args, context) {
50
100
  const Component = context.component;
51
101
  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);
102
+ return /* @__PURE__ */jsx(Component, {
103
+ ...args
104
+ });
53
105
  }
54
106
 
55
107
  //#endregion
@@ -1 +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"}
1
+ {"version":3,"file":"preview.d.ts","names":[],"sources":["../../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../../src/render-impl.tsx","../../src/preview-impl.tsx"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;;AAYA,SAAS,CAAA,CAAE,IAAA,EAAM,KAAA,EAAO,GAAG,QAAA,EAAU;EACpC,OAAO;IACN,IAAA;IACA,KAAA,EAAO,KAAA,IAAS,WAAA;IAChB,QAAA,EAAU,iBAAA,CAAkB,QAAA,CAAS;IACrC,GAAA,EAAK,KAAA,EAAO,GAAA,IAAO;GACnB;;AAEF,SAAS,iBAAA,CAAkB,QAAA,EAAU;EACpC,KAAK,IAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,MAAA,EAAQ,CAAA,EAAA,EAAK,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,CAAA,CAAA,CAAG,EAAE,OAAO,eAAA,CAAgB,QAAA,CAAS;EAC1G,OAAO,QAAA;;AAER,SAAS,eAAA,CAAgB,QAAA,EAAU;EAClC,MAAM,MAAA,GAAS,EAAE;EACjB,KAAK,MAAM,KAAA,IAAS,QAAA,EAAU,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,EAAE,MAAA,CAAO,IAAA,CAAK,GAAG,eAAA,CAAgB,KAAA,CAAM,CAAC,CAAA,KACzF,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM;EACvB,OAAO,MAAA;;;;;;;;;AAYR,SAAS,GAAA,CAAI,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK;EAC9B,MAAM;IAAE,QAAA;IAAU,GAAG;EAAA,CAAA,GAAS,KAAA;EAC9B,MAAM,YAAA,GAAe,GAAA,IAAO,IAAA,GAAO;IAClC,GAAG,IAAA;IACH;GACA,GAAG,IAAA;EACJ,IAAI,OAAO,IAAA,KAAS,UAAA,EAAY,OAAO,CAAA,CAAE,IAAA,EAAM,QAAA,KAAa,KAAK,CAAA,GAAI;IACpE,GAAG,YAAA;IACH;GACA,GAAG,YAAA,CAAa;EACjB,OAAO,CAAA,CAAE,IAAA,EAAM,YAAA,EAAc,IAAG,QAAA,KAAa,KAAK,CAAA,GAAI,EAAE,GAAG,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,GAAG,QAAA,GAAW,CAAC,QAAA,CAAS,EAAC;;;;;;;;;;;;;;;;;;;;;AC9B5G,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;IAEF,MAAM,OAAA,GAAU,KAAA,CADA,OAAA,CAAA,CAAS,EACM,aAAA,CAAc;IAC7C,WAAA,CAAY,GAAA,CAAI,aAAA,EAAe,OAAA,CAAQ;IACvC,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;;;;;;;;;;ACvCN,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,eAAA,GAAA,CAAC,SAAA,EAAD;IAAW,GAAI;EAAA,CAAQ,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { ComponentFn, VNodeChild } from "@pyreon/core";
2
2
 
3
- //#region src/render.d.ts
3
+ //#region src/render-impl.d.ts
4
4
  /**
5
5
  * Render a Pyreon story into a Storybook canvas element.
6
6
  *
@@ -32,7 +32,7 @@ declare function renderToCanvas({
32
32
  forceRemount: boolean;
33
33
  }, canvasElement: HTMLElement): void;
34
34
  //#endregion
35
- //#region src/preview.d.ts
35
+ //#region src/preview-impl.d.ts
36
36
  /**
37
37
  * Default render function — if the story CSF has a `component` but no
38
38
  * explicit `render`, this is used to create the VNode.
@@ -1 +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"}
1
+ {"version":3,"file":"preview2.d.ts","names":[],"sources":["../../src/render-impl.tsx","../../src/preview-impl.tsx"],"mappings":";;;;;AAoBA;;;;;;;;;;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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/storybook",
3
- "version": "0.2.0",
3
+ "version": "0.6.0",
4
4
  "description": "Storybook renderer for Pyreon — mount, render, and interact with Pyreon components in Storybook",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -51,9 +51,9 @@
51
51
  "typecheck": "tsc --noEmit"
52
52
  },
53
53
  "peerDependencies": {
54
- "@pyreon/core": "^0.3.1",
55
- "@pyreon/reactivity": "^0.3.1",
56
- "@pyreon/runtime-dom": "^0.3.1",
54
+ "@pyreon/core": ">=0.5.0 <1.0.0",
55
+ "@pyreon/reactivity": ">=0.5.0 <1.0.0",
56
+ "@pyreon/runtime-dom": ">=0.5.0 <1.0.0",
57
57
  "storybook": ">=8.0.0"
58
58
  }
59
59
  }
package/src/index.ts CHANGED
@@ -35,11 +35,11 @@ export type {
35
35
 
36
36
  // ─── Renderer ────────────────────────────────────────────────────────────────
37
37
 
38
- export { renderToCanvas, defaultRender } from './render'
38
+ export { defaultRender, renderToCanvas } from './render'
39
39
 
40
40
  // ─── Pyreon re-exports for convenience ───────────────────────────────────────
41
41
 
42
- export { h, Fragment } from '@pyreon/core'
43
42
  export type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'
44
- export { signal, computed, effect } from '@pyreon/reactivity'
43
+ export { Fragment, h } from '@pyreon/core'
44
+ export { computed, effect, signal } from '@pyreon/reactivity'
45
45
  export { mount } from '@pyreon/runtime-dom'
@@ -0,0 +1,28 @@
1
+ import type { ComponentFn, VNodeChild } from '@pyreon/core'
2
+ import { renderToCanvas } from './render-impl'
3
+
4
+ /**
5
+ * Preview entry — Storybook loads this in the preview iframe.
6
+ *
7
+ * Exports the render function and default decorators/parameters
8
+ * that apply to all stories using this renderer.
9
+ */
10
+
11
+ export { renderToCanvas }
12
+
13
+ /**
14
+ * Default render function — if the story CSF has a `component` but no
15
+ * explicit `render`, this is used to create the VNode.
16
+ */
17
+ export function render<TArgs extends Record<string, unknown>>(
18
+ args: TArgs,
19
+ context: { component?: ComponentFn<any> },
20
+ ): VNodeChild {
21
+ const Component = context.component
22
+ if (!Component) {
23
+ throw new Error(
24
+ '[@pyreon/storybook] No component provided. Either set `component` in your meta or provide a `render` function.',
25
+ )
26
+ }
27
+ return <Component {...args} />
28
+ }
package/src/preview.ts CHANGED
@@ -1,29 +1 @@
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
- }
1
+ export { render, renderToCanvas } from './preview-impl'
@@ -0,0 +1,69 @@
1
+ import type { ComponentFn, VNodeChild } from '@pyreon/core'
2
+ import { mount } from '@pyreon/runtime-dom'
3
+
4
+ /**
5
+ * State tracked per canvas element so we can clean up between renders.
6
+ */
7
+ const canvasState = new WeakMap<HTMLElement, () => void>()
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
+ export function renderToCanvas(
22
+ {
23
+ storyFn,
24
+ showMain,
25
+ showError,
26
+ }: {
27
+ storyFn: () => VNodeChild
28
+ storyContext: {
29
+ component?: ComponentFn<any>
30
+ args: Record<string, unknown>
31
+ [key: string]: unknown
32
+ }
33
+ showMain: () => void
34
+ showError: (error: { title: string; description: string }) => void
35
+ forceRemount: boolean
36
+ },
37
+ canvasElement: HTMLElement,
38
+ ): void {
39
+ // Always clean up the previous render
40
+ const prevUnmount = canvasState.get(canvasElement)
41
+ if (prevUnmount) {
42
+ prevUnmount()
43
+ canvasState.delete(canvasElement)
44
+ }
45
+
46
+ try {
47
+ const element = storyFn()
48
+ const unmount = mount(element, canvasElement)
49
+ canvasState.set(canvasElement, unmount)
50
+ showMain()
51
+ } catch (err) {
52
+ const error = err instanceof Error ? err : new Error(String(err))
53
+ showError({
54
+ title: `Error rendering story`,
55
+ description: error.message,
56
+ })
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Default render implementation used when no custom `render` is provided.
62
+ */
63
+ export function defaultRender(
64
+ component: ComponentFn<any>,
65
+ args: Record<string, unknown>,
66
+ ): VNodeChild {
67
+ const Component = component
68
+ return <Component {...args} />
69
+ }
package/src/render.ts CHANGED
@@ -1,75 +1 @@
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
- }
1
+ export { defaultRender, renderToCanvas } from './render-impl'
@@ -1,15 +1,14 @@
1
- import { h, Fragment } from '@pyreon/core'
2
1
  import type { ComponentFn, VNodeChild } from '@pyreon/core'
3
- import { signal, effect } from '@pyreon/reactivity'
2
+ import { effect, signal } from '@pyreon/reactivity'
4
3
  import { mount } from '@pyreon/runtime-dom'
5
- import { renderToCanvas, defaultRender } from '../render'
6
4
  import { render as previewRender } from '../preview'
5
+ import { defaultRender, renderToCanvas } from '../render'
7
6
  import type {
8
- Meta,
9
- StoryObj,
10
7
  DecoratorFn,
11
- StoryFn,
8
+ Meta,
12
9
  StoryContext,
10
+ StoryFn,
11
+ StoryObj,
13
12
  } from '../types'
14
13
 
15
14
  // ─── Helpers ──────────────────────────────────────────────────────────────────
@@ -26,7 +25,7 @@ function makeRenderContext(overrides: {
26
25
  args?: Record<string, unknown>
27
26
  }) {
28
27
  return {
29
- storyFn: overrides.storyFn ?? (() => h('div', null, 'default')),
28
+ storyFn: overrides.storyFn ?? (() => <div>default</div>),
30
29
  storyContext: {
31
30
  component: overrides.component,
32
31
  args: overrides.args ?? {},
@@ -47,7 +46,7 @@ describe('renderToCanvas', () => {
47
46
  it('mounts a simple VNode into the canvas', () => {
48
47
  const canvas = createCanvas()
49
48
  const ctx = makeRenderContext({
50
- storyFn: () => h('button', null, 'Click me'),
49
+ storyFn: () => <button>Click me</button>,
51
50
  })
52
51
 
53
52
  renderToCanvas(ctx, canvas)
@@ -59,12 +58,12 @@ describe('renderToCanvas', () => {
59
58
 
60
59
  it('mounts a Pyreon component with props', () => {
61
60
  function Button(props: { label: string; disabled?: boolean }) {
62
- return h('button', { disabled: props.disabled ?? false }, props.label)
61
+ return <button disabled={props.disabled ?? false}>{props.label}</button>
63
62
  }
64
63
 
65
64
  const canvas = createCanvas()
66
65
  const ctx = makeRenderContext({
67
- storyFn: () => h(Button, { label: 'Submit', disabled: true }),
66
+ storyFn: () => <Button label="Submit" disabled={true} />,
68
67
  })
69
68
 
70
69
  renderToCanvas(ctx, canvas)
@@ -80,13 +79,13 @@ describe('renderToCanvas', () => {
80
79
  const canvas = createCanvas()
81
80
 
82
81
  renderToCanvas(
83
- makeRenderContext({ storyFn: () => h('div', null, 'First') }),
82
+ makeRenderContext({ storyFn: () => <div>First</div> }),
84
83
  canvas,
85
84
  )
86
85
  expect(canvas.textContent).toBe('First')
87
86
 
88
87
  renderToCanvas(
89
- makeRenderContext({ storyFn: () => h('div', null, 'Second') }),
88
+ makeRenderContext({ storyFn: () => <div>Second</div> }),
90
89
  canvas,
91
90
  )
92
91
  expect(canvas.textContent).toBe('Second')
@@ -105,13 +104,10 @@ describe('renderToCanvas', () => {
105
104
  count()
106
105
  effectRunCount++
107
106
  })
108
- return h('span', null, () => `${count()}`)
107
+ return <span>{() => `${count()}`}</span>
109
108
  }
110
109
 
111
- renderToCanvas(
112
- makeRenderContext({ storyFn: () => h(Counter, null) }),
113
- canvas,
114
- )
110
+ renderToCanvas(makeRenderContext({ storyFn: () => <Counter /> }), canvas)
115
111
 
116
112
  const initialCount = effectRunCount
117
113
  count.set(1)
@@ -119,7 +115,7 @@ describe('renderToCanvas', () => {
119
115
 
120
116
  // Re-render with a different story — should dispose previous effects
121
117
  renderToCanvas(
122
- makeRenderContext({ storyFn: () => h('div', null, 'New story') }),
118
+ makeRenderContext({ storyFn: () => <div>New story</div> }),
123
119
  canvas,
124
120
  )
125
121
 
@@ -186,13 +182,10 @@ describe('renderToCanvas', () => {
186
182
  const count = signal(0)
187
183
 
188
184
  function Counter() {
189
- return h('span', { 'data-testid': 'count' }, () => `Count: ${count()}`)
185
+ return <span data-testid="count">{() => `Count: ${count()}`}</span>
190
186
  }
191
187
 
192
- renderToCanvas(
193
- makeRenderContext({ storyFn: () => h(Counter, null) }),
194
- canvas,
195
- )
188
+ renderToCanvas(makeRenderContext({ storyFn: () => <Counter /> }), canvas)
196
189
 
197
190
  expect(canvas.textContent).toBe('Count: 0')
198
191
 
@@ -207,7 +200,7 @@ describe('renderToCanvas', () => {
207
200
  describe('defaultRender', () => {
208
201
  it('creates a VNode from component + args', () => {
209
202
  function Greeting(props: { name: string }) {
210
- return h('p', null, `Hello, ${props.name}!`)
203
+ return <p>Hello, {props.name}!</p>
211
204
  }
212
205
 
213
206
  const canvas = createCanvas()
@@ -228,7 +221,7 @@ describe('Meta and StoryObj types', () => {
228
221
  label: string
229
222
  variant?: 'primary' | 'secondary'
230
223
  }) {
231
- return h('button', { class: props.variant }, props.label)
224
+ return <button class={props.variant}>{props.label}</button>
232
225
  }
233
226
 
234
227
  const meta = {
@@ -244,10 +237,7 @@ describe('Meta and StoryObj types', () => {
244
237
 
245
238
  it('StoryObj inherits args from Meta', () => {
246
239
  function Input(props: { placeholder: string; disabled?: boolean }) {
247
- return h('input', {
248
- placeholder: props.placeholder,
249
- disabled: props.disabled,
250
- })
240
+ return <input placeholder={props.placeholder} disabled={props.disabled} />
251
241
  }
252
242
 
253
243
  const _meta = {
@@ -266,7 +256,11 @@ describe('Meta and StoryObj types', () => {
266
256
 
267
257
  it('StoryObj supports custom render function', () => {
268
258
  function Card(props: { title: string }) {
269
- return h('div', { class: 'card' }, h('h2', null, props.title))
259
+ return (
260
+ <div class="card">
261
+ <h2>{props.title}</h2>
262
+ </div>
263
+ )
270
264
  }
271
265
 
272
266
  const _meta = {
@@ -277,7 +271,11 @@ describe('Meta and StoryObj types', () => {
277
271
  type Story = StoryObj<typeof _meta>
278
272
 
279
273
  const withWrapper: Story = {
280
- render: (args) => h('div', { class: 'wrapper' }, h(Card, args)),
274
+ render: (args) => (
275
+ <div class="wrapper">
276
+ <Card {...args} />
277
+ </div>
278
+ ),
281
279
  }
282
280
 
283
281
  const canvas = createCanvas()
@@ -297,19 +295,15 @@ describe('Meta and StoryObj types', () => {
297
295
  describe('Decorators', () => {
298
296
  it('decorator wraps a story', () => {
299
297
  function Button(props: { label: string }) {
300
- return h('button', null, props.label)
298
+ return <button>{props.label}</button>
301
299
  }
302
300
 
303
301
  const withPadding: DecoratorFn<{ label: string }> = (storyFn, context) => {
304
- return h(
305
- 'div',
306
- { style: 'padding: 1rem' },
307
- storyFn(context.args, context),
308
- )
302
+ return <div style="padding: 1rem">{storyFn(context.args, context)}</div>
309
303
  }
310
304
 
311
305
  const canvas = createCanvas()
312
- const storyResult = withPadding((args) => h(Button, args), {
306
+ const storyResult = withPadding((args) => <Button {...args} />, {
313
307
  args: { label: 'Wrapped' },
314
308
  argTypes: {},
315
309
  globals: {},
@@ -328,14 +322,16 @@ describe('Decorators', () => {
328
322
 
329
323
  it('multiple decorators compose correctly', () => {
330
324
  function Text(props: { content: string }) {
331
- return h('span', null, props.content)
325
+ return <span>{props.content}</span>
332
326
  }
333
327
 
334
- const withBorder: DecoratorFn<{ content: string }> = (storyFn, ctx) =>
335
- h('div', { class: 'border' }, storyFn(ctx.args, ctx))
328
+ const withBorder: DecoratorFn<{ content: string }> = (storyFn, ctx) => (
329
+ <div class="border">{storyFn(ctx.args, ctx)}</div>
330
+ )
336
331
 
337
- const withTheme: DecoratorFn<{ content: string }> = (storyFn, ctx) =>
338
- h('div', { class: 'theme-dark' }, storyFn(ctx.args, ctx))
332
+ const withTheme: DecoratorFn<{ content: string }> = (storyFn, ctx) => (
333
+ <div class="theme-dark">{storyFn(ctx.args, ctx)}</div>
334
+ )
339
335
 
340
336
  const context: StoryContext<{ content: string }> = {
341
337
  args: { content: 'Hello' },
@@ -348,7 +344,7 @@ describe('Decorators', () => {
348
344
  }
349
345
 
350
346
  // Compose: withTheme(withBorder(story))
351
- const story: StoryFn<{ content: string }> = (args) => h(Text, args)
347
+ const story: StoryFn<{ content: string }> = (args) => <Text {...args} />
352
348
  const decorated = withTheme((_args, ctx) => withBorder(story, ctx), context)
353
349
 
354
350
  const canvas = createCanvas()
@@ -368,8 +364,12 @@ describe('Fragment stories', () => {
368
364
  const canvas = createCanvas()
369
365
  renderToCanvas(
370
366
  makeRenderContext({
371
- storyFn: () =>
372
- h(Fragment, null, h('p', null, 'Line 1'), h('p', null, 'Line 2')),
367
+ storyFn: () => (
368
+ <>
369
+ <p>Line 1</p>
370
+ <p>Line 2</p>
371
+ </>
372
+ ),
373
373
  }),
374
374
  canvas,
375
375
  )
@@ -387,7 +387,7 @@ describe('Fragment stories', () => {
387
387
  describe('preview render', () => {
388
388
  it('renders a component with args', () => {
389
389
  function Badge(props: { text: string }) {
390
- return h('span', { class: 'badge' }, props.text)
390
+ return <span class="badge">{props.text}</span>
391
391
  }
392
392
 
393
393
  const canvas = createCanvas()