@razorwind/storybook 0.0.47 → 0.0.49

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/dist/index.cjs CHANGED
@@ -1,16 +1,31 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("@razorwind/core/plugin"),t=require("@razorwind/core/lib/fonts"),n=require("@razorwind/core/utils"),r=require("@stryke/path/join"),i=require("node:path");function a(e,t={}){let r=t.cssVarPrefix??`rw`;return(0,n.flattenTokens)(e,{includeTypes:t.includeTypes,enrichToken:e=>({...e,cssVar:(0,n.toCssVar)(e.path,r)})})}function o(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
2
- `,`\\n`).replaceAll(`\r`,`\\r`)}function s(e){return typeof e==`string`?`"${o(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function c(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles&&e.themeFiles.length>0?`
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("@razorwind/core/plugin"),t=require("@razorwind/core/lib/fonts"),n=require("@razorwind/core/utils"),r=require("@stryke/path/join");function i(e,t={}){let r=t.cssVarPrefix??`rw`;return(0,n.flattenTokens)(e,{includeTypes:t.includeTypes,enrichToken:e=>({...e,cssVar:(0,n.toCssVar)(e.path,r)})})}function a(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
2
+ `,`\\n`).replaceAll(`\r`,`\\r`)}function o(e){return typeof e==`string`?`"${a(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function s(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles?.[0],r=e.themeNames??[],i=n?r.length>1?`
3
+ ## Storybook UI theme
4
+
5
+ Generated theme module:
6
+
7
+ - \`${n}\` — record of \`create()\` themes keyed by name (${r.map(e=>`\`${e}\``).join(`, `)})
8
+
9
+ Wire into \`.storybook/preview.ts\`:
10
+
11
+ \`\`\`ts
12
+ import themes from "../${n}";
13
+
14
+ export const parameters = {
15
+ docs: { theme: themes[${JSON.stringify(r[0])}] }
16
+ };
17
+ \`\`\`
18
+ `:`
3
19
  ## Storybook UI theme
4
20
 
5
21
  Generated theme module(s):
6
22
 
7
- ${e.themeFiles.map(e=>`- \`${e}\``).join(`
8
- `)}
23
+ - \`${n}\`
9
24
 
10
25
  Wire into \`.storybook/preview.ts\`:
11
26
 
12
27
  \`\`\`ts
13
- import theme from "../${e.themeFiles[0]}";
28
+ import theme from "../${n}";
14
29
 
15
30
  export const parameters = {
16
31
  docs: { theme }
@@ -25,7 +40,7 @@ Generated by \`@razorwind/storybook\`.
25
40
  - \`${e.outputPath}/Tokens.mdx\` — token overview (${t})
26
41
  - \`${e.outputPath}/blocks/\` — React doc blocks (ColorPalette, Typeset, …)
27
42
  - \`${e.outputPath}/tokens.json\` — flattened token manifest
28
- ${n}
43
+ ${i}
29
44
  ## Setup
30
45
 
31
46
  1. Add the generated MDX pages to Storybook (paths depend on your \`stories\` config):
@@ -50,7 +65,7 @@ import { ColorPaletteBlock } from "./blocks";
50
65
  ## Regenerate
51
66
 
52
67
  Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputPath}/\`.
53
- `}function l(e,t){let n=new Map;for(let r of e){let e=r.path.split(`.`).slice(0,Math.max(t,1)).join(`.`)||r.path,i=n.get(e)??[];i.push(r),n.set(e,i)}return n}function u(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function d(e,t={}){return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
68
+ `}function c(e,t){let n=new Map;for(let r of e){let e=r.path.split(`.`).slice(0,Math.max(t,1)).join(`.`)||r.path,i=n.get(e)??[];i.push(r),n.set(e,i)}return n}function l(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function u(e,t={}){return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
54
69
 
55
70
  /**
56
71
  * Color tokens rendered with Storybook's ColorPalette doc block.
@@ -60,10 +75,10 @@ Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputP
60
75
  export function ColorPaletteBlock() {
61
76
  return (
62
77
  <ColorPalette>
63
- ${[...l(e.filter(e=>e.type===`color`),t.colorGroupBy??2).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.map(t=>` ${s(u(t.path,e))}: ${s(t.cssValue)}`).join(`,
78
+ ${[...c(e.filter(e=>e.type===`color`),t.colorGroupBy??2).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.map(t=>` ${o(l(t.path,e))}: ${o(t.cssValue)}`).join(`,
64
79
  `),r=t.find(e=>e.description)?.description??`${t.length} token${t.length===1?``:`s`}`;return` <ColorItem
65
- title={${s(e)}}
66
- subtitle={${s(r)}}
80
+ title={${o(e)}}
81
+ subtitle={${o(r)}}
67
82
  colors={{
68
83
  ${n}
69
84
  }}
@@ -72,7 +87,7 @@ ${n}
72
87
  </ColorPalette>
73
88
  );
74
89
  }
75
- `}function f(e,n={}){let r=n.sampleText??`The quick brown fox jumps over the lazy dog`,i=e.filter(e=>e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)).map(e=>{let t=/^(\d+(?:\.\d+)?)/.exec(e.cssValue);return t?Number(t[1]):e.cssValue}),a=[...new Set(i)],o=(0,t.pickFontByRole)(n.fonts,t.SANS_ROLES),c=(o?(0,t.cssFontFamily)(o):void 0)??e.find(e=>e.type===`fontFamily`)?.cssValue??`system-ui, sans-serif`,l=e.find(e=>e.type===`fontWeight`),u=l&&Number.parseFloat(l.cssValue)||400,d=a.length>0?`[${a.map(e=>s(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`import { Typeset } from "@storybook/addon-docs/blocks";
90
+ `}function d(e,n={}){let r=n.sampleText??`The quick brown fox jumps over the lazy dog`,i=e.filter(e=>e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)).map(e=>{let t=/^(\d+(?:\.\d+)?)/.exec(e.cssValue);return t?Number(t[1]):e.cssValue}),a=[...new Set(i)],s=(0,t.pickFontByRole)(n.fonts,t.SANS_ROLES),c=(s?(0,t.cssFontFamily)(s):void 0)??e.find(e=>e.type===`fontFamily`)?.cssValue??`system-ui, sans-serif`,l=e.find(e=>e.type===`fontWeight`),u=l&&Number.parseFloat(l.cssValue)||400,d=a.length>0?`[${a.map(e=>o(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`import { Typeset } from "@storybook/addon-docs/blocks";
76
91
 
77
92
  /**
78
93
  * Typography tokens rendered with Storybook's Typeset doc block.
@@ -82,14 +97,14 @@ ${n}
82
97
  export function TypesetBlock() {
83
98
  return (
84
99
  <Typeset
85
- fontFamily={${s(c)}}
100
+ fontFamily={${o(c)}}
86
101
  fontSizes={${d}}
87
- fontWeight={${s(u)}}
88
- sampleText={${s(r)}}
102
+ fontWeight={${o(u)}}
103
+ sampleText={${o(r)}}
89
104
  />
90
105
  );
91
106
  }
92
- `}function p(e){return`import type { CSSProperties, ReactElement } from "react";
107
+ `}function f(e){return`import type { CSSProperties, ReactElement } from "react";
93
108
 
94
109
  export interface TokenTableRow {
95
110
  path: string;
@@ -101,12 +116,12 @@ export interface TokenTableRow {
101
116
  }
102
117
 
103
118
  const TOKENS: TokenTableRow[] = [
104
- ${e.map(e=>{let t=e.theme?s(e.theme):`undefined`;return` {
105
- path: ${s(e.path)},
106
- type: ${e.type?s(e.type):`undefined`},
107
- value: ${s(e.cssValue)},
108
- cssVar: ${s(e.cssVar)},
109
- description: ${e.description?s(e.description):`undefined`},
119
+ ${e.map(e=>{let t=e.theme?o(e.theme):`undefined`;return` {
120
+ path: ${o(e.path)},
121
+ type: ${e.type?o(e.type):`undefined`},
122
+ value: ${o(e.cssValue)},
123
+ cssVar: ${o(e.cssVar)},
124
+ description: ${e.description?o(e.description):`undefined`},
110
125
  theme: ${t}
111
126
  }`}).join(`,
112
127
  `)||``}
@@ -193,7 +208,7 @@ export function TokenTableBlock({
193
208
  </table>
194
209
  );
195
210
  }
196
- `}function m(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
211
+ `}function p(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
197
212
  ## Colors
198
213
 
199
214
  <ColorPaletteBlock />
@@ -206,7 +221,7 @@ import { ColorPaletteBlock } from "./blocks/ColorPalette";
206
221
  import { TokenTableBlock } from "./blocks/TokenTable";
207
222
  import { TypesetBlock } from "./blocks/Typeset";
208
223
 
209
- <Meta title="${o(t)}/Overview" />
224
+ <Meta title="${a(t)}/Overview" />
210
225
 
211
226
  # ${t}
212
227
 
@@ -215,23 +230,23 @@ ${n}${r}
215
230
  ## All tokens
216
231
 
217
232
  <TokenTableBlock />
218
- `}function h(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
233
+ `}function m(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
219
234
  import { ColorPaletteBlock } from "./blocks/ColorPalette";
220
235
 
221
- <Meta title="${o(e.titlePrefix??`Design Tokens`)}/Colors" />
236
+ <Meta title="${a(e.titlePrefix??`Design Tokens`)}/Colors" />
222
237
 
223
238
  # Colors
224
239
 
225
240
  <ColorPaletteBlock />
226
- `}function g(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
241
+ `}function h(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
227
242
  import { TypesetBlock } from "./blocks/Typeset";
228
243
 
229
- <Meta title="${o(e.titlePrefix??`Design Tokens`)}/Typography" />
244
+ <Meta title="${a(e.titlePrefix??`Design Tokens`)}/Typography" />
230
245
 
231
246
  # Typography
232
247
 
233
248
  <TypesetBlock />
234
- `}function _(e,t){let n=e[t];return typeof n==`string`?n:void 0}function v(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function y(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
249
+ `}function g(e,t){let n=e[t];return typeof n==`string`?n:void 0}function _(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function v(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
235
250
 
236
251
  /**
237
252
  * Icons rendered with Storybook's IconGallery doc block.
@@ -241,38 +256,47 @@ import { TypesetBlock } from "./blocks/Typeset";
241
256
  export function IconGalleryBlock() {
242
257
  return (
243
258
  <IconGallery>
244
- ${(v(e)?Object.values(e).filter(v).toSorted((e,t)=>(_(e,`name`)??``).localeCompare(_(t,`name`)??``)):[]).map(e=>{let t=_(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>v(e)&&_(e,`type`)===`svg`&&typeof e.content==`string`),r=v(n)&&typeof n.content==`string`?`<span
259
+ ${(_(e)?Object.values(e).filter(_).toSorted((e,t)=>(g(e,`name`)??``).localeCompare(g(t,`name`)??``)):[]).map(e=>{let t=g(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>_(e)&&g(e,`type`)===`svg`&&typeof e.content==`string`),r=_(n)&&typeof n.content==`string`?`<span
245
260
  style={{ display: "inline-flex", width: 24, height: 24 }}
246
- dangerouslySetInnerHTML={{ __html: ${s(n.content)} }}
247
- />`:`<code>${o(t)}</code>`;return` <IconItem name={${s(t)}}>
261
+ dangerouslySetInnerHTML={{ __html: ${o(n.content)} }}
262
+ />`:`<code>${a(t)}</code>`;return` <IconItem name={${o(t)}}>
248
263
  ${r}
249
264
  </IconItem>`}).join(`
250
265
  `)||` {/* No icons */}`}
251
266
  </IconGallery>
252
267
  );
253
268
  }
254
- `}function b(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
269
+ `}function y(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
255
270
  import { IconGalleryBlock } from "./blocks/IconGallery";
256
271
 
257
- <Meta title="${o(e.titlePrefix??`Design Tokens`)}/Icons" />
272
+ <Meta title="${a(e.titlePrefix??`Design Tokens`)}/Icons" />
258
273
 
259
274
  # Icons
260
275
 
261
276
  <IconGalleryBlock />
262
- `}function x(){return`export { ColorPaletteBlock } from "./ColorPalette";
277
+ `}function b(){return`export { ColorPaletteBlock } from "./ColorPalette";
263
278
  export { IconGalleryBlock } from "./IconGallery";
264
279
  export { TokenTableBlock } from "./TokenTable";
265
280
  export type { TokenTableBlockProps, TokenTableRow } from "./TokenTable";
266
281
  export { TypesetBlock } from "./Typeset";
267
- `}function S(e){return v(e)?e.base===`light`||e.base===`dark`:!1}function C(e,n,r){let i=(0,t.pickFontByRole)(r,t.SANS_ROLES),a=(0,t.pickFontByRole)(r,t.MONO_ROLES);return{brandTarget:`_blank`,...e,brandTitle:e.brandTitle??n.title,brandUrl:e.brandUrl??n.homepage,brandImage:e.brandImage??n.logo,fontBase:e.fontBase??(i?(0,t.cssFontFamily)(i):void 0),fontCode:e.fontCode??(a?(0,t.cssFontFamily)(a):void 0)}}function w(e){return`import { create } from "storybook/theming";
282
+ `}const x=new Set(`base.colorPrimary.colorSecondary.appBg.appContentBg.appHoverBg.appPreviewBg.appBorderColor.appBorderRadius.fontBase.fontCode.textColor.textInverseColor.textMutedColor.barTextColor.barHoverColor.barSelectedColor.barBg.buttonBg.buttonBorder.booleanBg.booleanSelectedBg.inputBg.inputBorder.inputTextColor.inputBorderRadius.brandTitle.brandUrl.brandImage.brandTarget.gridCellSize`.split(`.`));function S(e){return _(e)?e.base===`light`||e.base===`dark`:!1}function C(e){return _(e)?S(e)?!0:Object.keys(e).some(e=>x.has(e)):!1}function w(e){if(!_(e)||C(e))return!1;let t=Object.values(e);return t.length>0&&t.every(C)}function T(e,t,n){return t.base===`light`||t.base===`dark`?t.base:`${e} ${n??``}`.toLowerCase().includes(`light`)?`light`:`dark`}function E(e){return/^[a-z_$][\w$]*$/i.test(e)?e:o(e)}function D(e,t){let r=e.find(e=>e.id===n.SHARED_THEME_ID);return!r||(0,n.isSharedThemeId)(t.id)?t.tokens:(0,n.mergeTokenTrees)(t.tokens,r.tokens)}function O(e,t,n,r,i){return k(T(e,t,i),t,n,r)}function k(e,n,r,i){let a=(0,t.pickFontByRole)(i,t.SANS_ROLES),o=(0,t.pickFontByRole)(i,t.MONO_ROLES);return{brandTarget:`_blank`,base:e||`light`,...n,brandTitle:n.brandTitle??r.title,brandUrl:n.brandUrl??r.homepage,brandImage:n.brandImage??r.logo,fontBase:n.fontBase??(a?(0,t.cssFontFamily)(a):void 0),fontCode:n.fontCode??(o?(0,t.cssFontFamily)(o):void 0)}}function A(e,t=``){return`create({\n${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>`${t} ${e}: ${o(n)}`).join(`,
283
+ `)}\n${t}})`}function j(e){return`import { create } from "storybook/theming";
268
284
 
269
285
  /**
270
286
  * Storybook UI theme generated by \`@razorwind/storybook\`.
271
287
  *
272
288
  * @see https://storybook.js.org/docs/configure/user-interface/theming
273
289
  */
274
- export default create({
275
- ${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>` ${e}: ${s(t)}`).join(`,
290
+ export default ${A(e)};
291
+ `}function M(e){return`import { create } from "storybook/theming";
292
+
293
+ /**
294
+ * Storybook UI themes generated by \`@razorwind/storybook\`.
295
+ *
296
+ * @see https://storybook.js.org/docs/configure/user-interface/theming
297
+ */
298
+ export default {
299
+ ${Object.entries(e).map(([e,t])=>` ${E(e)}: ${A(t,` `)}`).join(`,
276
300
  `)}
277
- });
278
- `}const T=e=>(t,i,a)=>(0,n.createDocument)((0,r.joinPaths)(e,t),i,{name:`razorwind-storybook`},(i,a)=>(0,r.joinPaths)(e,(0,n.slugifyThemeName)(a),t),a);function E(e,t={}){let o=t.outputPath??`storybook/tokens`,s=(0,n.resolveSchemaIdentity)(e),l=t.titlePrefix??s.title??`Design Tokens`,u={...t,titlePrefix:l},_=a(e.tokens,t),E=_.some(e=>e.type===`color`),D=e.fonts&&Object.keys(e.fonts).length>0||_.some(e=>e.type===`fontFamily`||e.type===`fontWeight`||e.type===`typography`||e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)),O=!t.skipIcons&&v(e.icons)&&Object.keys(e.icons).length>0,k=T(o),A={[(0,r.joinPaths)(o,`blocks/ColorPalette.tsx`)]:k(`blocks/ColorPalette.tsx`,d(_,u),`tsx`),[(0,r.joinPaths)(o,`blocks/Typeset.tsx`)]:k(`blocks/Typeset.tsx`,f(_,{...u,fonts:e.fonts}),`tsx`),[(0,r.joinPaths)(o,`blocks/TokenTable.tsx`)]:k(`blocks/TokenTable.tsx`,p(_),`tsx`),[(0,r.joinPaths)(o,`blocks/IconGallery.tsx`)]:k(`blocks/IconGallery.tsx`,y(t.skipIcons?{}:e.icons),`tsx`),[(0,r.joinPaths)(o,`blocks/index.ts`)]:k(`blocks/index.ts`,x(),`typescript`),[(0,r.joinPaths)(o,`Tokens.mdx`)]:k(`Tokens.mdx`,m({titlePrefix:l,hasColors:E,hasTypography:D}),`mdx`)};if(E&&(A[(0,r.joinPaths)(o,`Colors.mdx`)]=k(`Colors.mdx`,h(u),`mdx`)),D&&(A[(0,r.joinPaths)(o,`Typography.mdx`)]=k(`Typography.mdx`,g(u),`mdx`)),O&&(A[(0,r.joinPaths)(o,`Icons.mdx`)]=k(`Icons.mdx`,b(u),`mdx`)),A[(0,r.joinPaths)(o,`tokens.json`)]=k(`tokens.json`,`${JSON.stringify(_,null,2)}\n`,`json`),t.mapTheme){let n=t.mapTheme(e.tokens);if(S(n))A[(0,r.joinPaths)(o,`theme.ts`)]=k(`theme.ts`,w(C(n,s,e.fonts)),`typescript`);else if(v(n))for(let[t,i]of Object.entries(n))S(i)&&(A[(0,r.joinPaths)(o,`theme-${t}.ts`)]=k(`theme-${t}.ts`,w(C(i,s,e.fonts)),`typescript`))}let j=Object.keys(A).filter(e=>e.startsWith((0,i.join)(o,`theme`))).map(e=>e.slice(o.length+1)),M=`INSTALL.md`;return A[(0,r.joinPaths)(o,M)]=k(M,t.installGuide??c({outputPath:o,titlePrefix:l,themeFiles:j.length>0?j:void 0}),`markdown`),A}var D=(0,e.definePlugin)(e=>({name:`storybook`,generate:async t=>E(t,e??{})}));exports.applyBrandDefaults=C,exports.default=D,exports.flattenTokens=a,Object.defineProperty(exports,"formatTokenValue",{enumerable:!0,get:function(){return n.formatTokenValue}}),exports.generateTokenDocs=E,exports.renderInstallMd=c,exports.renderThemeFile=w,exports.resolveTokenSets=n.resolveTokenSets,Object.defineProperty(exports,"toCssVar",{enumerable:!0,get:function(){return n.toCssVar}});
301
+ };
302
+ `}function N(e){if(S(e))return j(e);let t=Object.entries(e);if(t.length!==1)return M(e);let[,n]=t[0]??[];return n?j(n):M(e)}function P(e,t,r,i){let a=(e,n)=>O(e,n,r,t.fonts,t.theme);if(w(e))return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,a(e,t)]));let o=(0,n.resolveTokenSets)(t.tokens),s=o.filter(e=>!(0,n.isSharedThemeId)(e.id));if(s.length>1){let e={};for(let t of s){let n=i(D(o,t));if(w(n)){let r=n[t.id];if(r){e[t.id]=a(t.id,r);continue}for(let[t,r]of Object.entries(n))e[t]=a(t,r);continue}C(n)&&(e[t.id]=a(t.id,n))}return e}if(C(e)){let n=s[0]&&s[0].id!=="default"?s[0].id:t.theme??`default`;return{[n]:a(n,e)}}return{}}const F=e=>(t,i,a)=>(0,n.createDocument)((0,r.joinPaths)(e,t),i,{name:`razorwind-storybook`},!1,a);function I(e,t={}){let a=t.outputPath??`storybook/tokens`,o=(0,n.resolveSchemaIdentity)(e),c=t.titlePrefix??o.title??`Design Tokens`,l={...t,titlePrefix:c},g=i(e.tokens,t),x=g.some(e=>e.type===`color`),S=e.fonts&&Object.keys(e.fonts).length>0||g.some(e=>e.type===`fontFamily`||e.type===`fontWeight`||e.type===`typography`||e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)),C=!t.skipIcons&&_(e.icons)&&Object.keys(e.icons).length>0,w=F(a),T={[(0,r.joinPaths)(a,`blocks/ColorPalette.tsx`)]:w(`blocks/ColorPalette.tsx`,u(g,l),`tsx`),[(0,r.joinPaths)(a,`blocks/Typeset.tsx`)]:w(`blocks/Typeset.tsx`,d(g,{...l,fonts:e.fonts}),`tsx`),[(0,r.joinPaths)(a,`blocks/TokenTable.tsx`)]:w(`blocks/TokenTable.tsx`,f(g),`tsx`),[(0,r.joinPaths)(a,`blocks/IconGallery.tsx`)]:w(`blocks/IconGallery.tsx`,v(t.skipIcons?{}:e.icons),`tsx`),[(0,r.joinPaths)(a,`blocks/index.ts`)]:w(`blocks/index.ts`,b(),`typescript`),[(0,r.joinPaths)(a,`Tokens.mdx`)]:w(`Tokens.mdx`,p({titlePrefix:c,hasColors:x,hasTypography:S}),`mdx`)};x&&(T[(0,r.joinPaths)(a,`Colors.mdx`)]=w(`Colors.mdx`,m(l),`mdx`)),S&&(T[(0,r.joinPaths)(a,`Typography.mdx`)]=w(`Typography.mdx`,h(l),`mdx`)),C&&(T[(0,r.joinPaths)(a,`Icons.mdx`)]=w(`Icons.mdx`,y(l),`mdx`)),T[(0,r.joinPaths)(a,`tokens.json`)]=w(`tokens.json`,`${JSON.stringify(g,null,2)}\n`,`json`);let E;if(t.mapTheme){let n=P(t.mapTheme(e.tokens),e,o,t.mapTheme);Object.keys(n).length>0&&(E=Object.keys(n),T[(0,r.joinPaths)(a,`theme.ts`)]=w(`theme.ts`,N(n),`typescript`))}let D=`INSTALL.md`;return T[(0,r.joinPaths)(a,D)]=w(D,t.installGuide??s({outputPath:a,titlePrefix:c,themeFiles:E?[`theme.ts`]:void 0,themeNames:E}),`markdown`),T}var L=(0,e.definePlugin)(e=>({name:`storybook`,themeGeneration:`combined`,generate:async t=>I(t,e??{})}));exports.applyBrandDefaults=k,exports.default=L,exports.flattenTokens=i,Object.defineProperty(exports,"formatTokenValue",{enumerable:!0,get:function(){return n.formatTokenValue}}),exports.generateTokenDocs=I,exports.normalizeThemes=P,exports.renderInstallMd=s,exports.renderThemeFile=N,exports.resolveTokenSets=n.resolveTokenSets,Object.defineProperty(exports,"toCssVar",{enumerable:!0,get:function(){return n.toCssVar}});
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { TokenType, Tokens } from "@power-plant/dtcg-schema";
2
+ import { PartialKeys } from "@stryke/types/base";
2
3
  import { Fonts, Schema, Tokens as Tokens$1 } from "@razorwind/core/schema";
3
4
  import { formatTokenValue, resolveTokenSets, toCssVar } from "@razorwind/core/utils";
4
5
  import { GeneratorFunctionResult } from "@power-plant/core";
@@ -61,7 +62,8 @@ interface StorybookTheme {
61
62
  brandTarget?: string;
62
63
  gridCellSize?: number;
63
64
  }
64
- type StorybookThemeResult = StorybookTheme | Record<string, StorybookTheme>;
65
+ type StorybookThemePartial = PartialKeys<StorybookTheme, "base">;
66
+ type StorybookThemeResult = StorybookThemePartial | Record<string, StorybookThemePartial>;
65
67
  /**
66
68
  * Map flattened design tokens to a Storybook theme object.
67
69
  *
@@ -110,8 +112,10 @@ interface StorybookPluginOptions {
110
112
  /**
111
113
  * Map extracted token values to a Storybook UI theme.
112
114
  *
113
- * When provided, the result is written to `{outputPath}/theme.ts` as a
114
- * `create()` call from `storybook/theming`.
115
+ * When provided, all mapped themes are written to a single
116
+ * `{outputPath}/theme.ts`. One theme becomes `export default create({…})`;
117
+ * multiple themes become a record keyed by theme name
118
+ * (`{ light: create({…}), dark: create({…}) }`).
115
119
  *
116
120
  * @see https://storybook.js.org/docs/configure/user-interface/theming
117
121
  */
@@ -145,23 +149,37 @@ declare function renderInstallMd(options: {
145
149
  outputPath: string;
146
150
  titlePrefix?: string;
147
151
  themeFiles?: string[];
152
+ themeNames?: string[];
148
153
  }): string;
149
154
  //#endregion
150
155
  //#region src/generate.d.ts
151
156
  /**
152
157
  * Fill Storybook brand fields from Schema identity when the mapped theme omits them.
153
158
  */
154
- declare function applyBrandDefaults(theme: StorybookTheme, identity: {
159
+ declare function applyBrandDefaults(base: "light" | "dark", theme: PartialKeys<StorybookTheme, "base">, identity: {
155
160
  title?: string;
156
161
  homepage?: string;
157
162
  logo?: string;
158
163
  }, fonts?: Fonts): StorybookTheme;
159
164
  /**
160
- * Serialize a Storybook theme object as a `storybook/theming` `create()` module.
165
+ * Serialize Storybook theme(s) as a `storybook/theming` `create()` module.
166
+ *
167
+ * A single theme becomes `export default create({…})`. Multiple named themes
168
+ * become a record: `{ light: create({…}), dark: create({…}) }`.
161
169
  *
162
170
  * @see https://storybook.js.org/docs/configure/user-interface/theming
163
171
  */
164
- declare function renderThemeFile(theme: StorybookTheme): string;
172
+ declare function renderThemeFile(theme: StorybookTheme | Record<string, StorybookTheme>): string;
173
+ /**
174
+ * Normalize {@link StorybookPluginOptions.mapTheme} results into a named
175
+ * theme record. Multi-theme token sets are mapped per theme when `mapTheme`
176
+ * returns a single theme object.
177
+ */
178
+ declare function normalizeThemes(mapped: unknown, spec: Pick<Schema, "tokens" | "theme" | "fonts">, identity: {
179
+ title?: string;
180
+ homepage?: string;
181
+ logo?: string;
182
+ }, mapTheme: NonNullable<StorybookPluginOptions["mapTheme"]>): Record<string, StorybookTheme>;
165
183
  /**
166
184
  * Generate Storybook MDX / React token doc blocks from a Razorwind schema.
167
185
  */
@@ -172,6 +190,10 @@ declare function generateTokenDocs(spec: Schema, options?: StorybookPluginOption
172
190
  * Razorwind plugin that turns design tokens into Storybook MDX doc blocks
173
191
  * (`ColorPalette`, `Typeset`, `TokenTable`, `IconGallery`) and optional UI themes.
174
192
  *
193
+ * Light and dark token sets are emitted as a single `theme.ts`: one theme is
194
+ * `export default create({…})`; multiple themes are a record keyed by name
195
+ * (`{ light: create({…}), dark: create({…}) }`).
196
+ *
175
197
  * @see https://storybook.js.org/docs/writing-docs/doc-blocks
176
198
  * @see https://storybook.js.org/docs/configure/user-interface/theming
177
199
  * @see https://github.com/unpunnyfuns/swatchbook/tree/main/packages/addon
@@ -196,5 +218,5 @@ declare function generateTokenDocs(spec: Schema, options?: StorybookPluginOption
196
218
  */
197
219
  declare const _default: (options?: StorybookPluginOptions | undefined) => import("@razorwind/core/plugin").Plugin;
198
220
  //#endregion
199
- export { type FlatToken, type GenerateStorybookTheme, type StorybookPluginOptions, type StorybookTheme, applyBrandDefaults, _default as default, flattenTokens, formatTokenValue, generateTokenDocs, renderInstallMd, renderThemeFile, resolveTokenSets, toCssVar };
221
+ export { type FlatToken, type GenerateStorybookTheme, type StorybookPluginOptions, type StorybookTheme, type StorybookThemePartial, type StorybookThemeResult, applyBrandDefaults, _default as default, flattenTokens, formatTokenValue, generateTokenDocs, normalizeThemes, renderInstallMd, renderThemeFile, resolveTokenSets, toCssVar };
200
222
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/flatten.ts","../src/install.ts","../src/generate.ts","../src/index.ts"],"mappings":";;;;;;;;UAuBiB;;EAEf;;EAEA,OAAO;;EAEP;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;UAQe;;EAEf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU,uBACV,iBAAiB,eAAe;;;;;;KAOtB,0BACV,QAAQ,SAAS,eAAe,YAC7B;;;;UAKY;;;;;;EAMf;;;;;;EAOA;;;;;;EAOA;;;;;;EAOA;;;;;EAMA,eAAe;;;;;;EAOf;;;;;;;;;EAUA,WAAW;;;;;;EAOX;;;;;EAMA;;;;;;;iBC7Hc,cACd,QAAQ,WAAS,eAAe,WAChC,UAAS,KAAK,2DACb;;;;;;;;iBCba,gBAAgB;EAC9B;EACA;EACA;;;;;;;iBC8cc,mBACd,OAAO,gBACP;EAAY;EAAgB;EAAmB;GAC/C,QAAQ,QACP;;;;;;iBAoBa,gBAAgB,OAAO;;;;iBA0CvB,kBACd,MAAM,QACN,UAAS,yBACR,wBAAwB,QAAQ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/flatten.ts","../src/install.ts","../src/generate.ts","../src/index.ts"],"mappings":";;;;;;;;;UAwBiB;;EAEf;;EAEA,OAAO;;EAEP;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;UAQe;;EAEf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU,wBAAwB,YAAY;KAEpC,uBACV,wBAAwB,eAAe;;;;;;KAO7B,0BACV,QAAQ,SAAS,eAAe,YAC7B;;;;UAKY;;;;;;EAMf;;;;;;EAOA;;;;;;EAOA;;;;;;EAOA;;;;;EAMA,eAAe;;;;;;EAOf;;;;;;;;;;;EAYA,WAAW;;;;;;EAOX;;;;;EAMA;;;;;;;iBClIc,cACd,QAAQ,WAAS,eAAe,WAChC,UAAS,KAAK,2DACb;;;;;;;;iBCba,gBAAgB;EAC9B;EACA;EACA;EACA;;;;;;;iBCqjBc,mBACd,wBACA,OAAO,YAAY,yBACnB;EAAY;EAAgB;EAAmB;GAC/C,QAAQ,QACP;;;;;;;;;iBAkEa,gBACd,OAAO,iBAAiB,eAAe;;;;;;iBAwBzB,gBACd,iBACA,MAAM,KAAK,uCACX;EAAY;EAAgB;EAAmB;GAC/C,UAAU,YAAY,sCACrB,eAAe;;;;iBAwEF,kBACd,MAAM,QACN,UAAS,yBACR,wBAAwB,QAAQ"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { formatTokenValue, resolveTokenSets, toCssVar } from "@razorwind/core/utils";
2
2
  import { TokenType, Tokens } from "@power-plant/dtcg-schema";
3
+ import { PartialKeys } from "@stryke/types/base";
3
4
  import { Fonts, Schema, Tokens as Tokens$1 } from "@razorwind/core/schema";
4
5
  import { GeneratorFunctionResult } from "@power-plant/core";
5
6
  //#region src/types.d.ts
@@ -61,7 +62,8 @@ interface StorybookTheme {
61
62
  brandTarget?: string;
62
63
  gridCellSize?: number;
63
64
  }
64
- type StorybookThemeResult = StorybookTheme | Record<string, StorybookTheme>;
65
+ type StorybookThemePartial = PartialKeys<StorybookTheme, "base">;
66
+ type StorybookThemeResult = StorybookThemePartial | Record<string, StorybookThemePartial>;
65
67
  /**
66
68
  * Map flattened design tokens to a Storybook theme object.
67
69
  *
@@ -110,8 +112,10 @@ interface StorybookPluginOptions {
110
112
  /**
111
113
  * Map extracted token values to a Storybook UI theme.
112
114
  *
113
- * When provided, the result is written to `{outputPath}/theme.ts` as a
114
- * `create()` call from `storybook/theming`.
115
+ * When provided, all mapped themes are written to a single
116
+ * `{outputPath}/theme.ts`. One theme becomes `export default create({…})`;
117
+ * multiple themes become a record keyed by theme name
118
+ * (`{ light: create({…}), dark: create({…}) }`).
115
119
  *
116
120
  * @see https://storybook.js.org/docs/configure/user-interface/theming
117
121
  */
@@ -145,23 +149,37 @@ declare function renderInstallMd(options: {
145
149
  outputPath: string;
146
150
  titlePrefix?: string;
147
151
  themeFiles?: string[];
152
+ themeNames?: string[];
148
153
  }): string;
149
154
  //#endregion
150
155
  //#region src/generate.d.ts
151
156
  /**
152
157
  * Fill Storybook brand fields from Schema identity when the mapped theme omits them.
153
158
  */
154
- declare function applyBrandDefaults(theme: StorybookTheme, identity: {
159
+ declare function applyBrandDefaults(base: "light" | "dark", theme: PartialKeys<StorybookTheme, "base">, identity: {
155
160
  title?: string;
156
161
  homepage?: string;
157
162
  logo?: string;
158
163
  }, fonts?: Fonts): StorybookTheme;
159
164
  /**
160
- * Serialize a Storybook theme object as a `storybook/theming` `create()` module.
165
+ * Serialize Storybook theme(s) as a `storybook/theming` `create()` module.
166
+ *
167
+ * A single theme becomes `export default create({…})`. Multiple named themes
168
+ * become a record: `{ light: create({…}), dark: create({…}) }`.
161
169
  *
162
170
  * @see https://storybook.js.org/docs/configure/user-interface/theming
163
171
  */
164
- declare function renderThemeFile(theme: StorybookTheme): string;
172
+ declare function renderThemeFile(theme: StorybookTheme | Record<string, StorybookTheme>): string;
173
+ /**
174
+ * Normalize {@link StorybookPluginOptions.mapTheme} results into a named
175
+ * theme record. Multi-theme token sets are mapped per theme when `mapTheme`
176
+ * returns a single theme object.
177
+ */
178
+ declare function normalizeThemes(mapped: unknown, spec: Pick<Schema, "tokens" | "theme" | "fonts">, identity: {
179
+ title?: string;
180
+ homepage?: string;
181
+ logo?: string;
182
+ }, mapTheme: NonNullable<StorybookPluginOptions["mapTheme"]>): Record<string, StorybookTheme>;
165
183
  /**
166
184
  * Generate Storybook MDX / React token doc blocks from a Razorwind schema.
167
185
  */
@@ -172,6 +190,10 @@ declare function generateTokenDocs(spec: Schema, options?: StorybookPluginOption
172
190
  * Razorwind plugin that turns design tokens into Storybook MDX doc blocks
173
191
  * (`ColorPalette`, `Typeset`, `TokenTable`, `IconGallery`) and optional UI themes.
174
192
  *
193
+ * Light and dark token sets are emitted as a single `theme.ts`: one theme is
194
+ * `export default create({…})`; multiple themes are a record keyed by name
195
+ * (`{ light: create({…}), dark: create({…}) }`).
196
+ *
175
197
  * @see https://storybook.js.org/docs/writing-docs/doc-blocks
176
198
  * @see https://storybook.js.org/docs/configure/user-interface/theming
177
199
  * @see https://github.com/unpunnyfuns/swatchbook/tree/main/packages/addon
@@ -196,5 +218,5 @@ declare function generateTokenDocs(spec: Schema, options?: StorybookPluginOption
196
218
  */
197
219
  declare const _default: (options?: StorybookPluginOptions | undefined) => import("@razorwind/core/plugin").Plugin;
198
220
  //#endregion
199
- export { type FlatToken, type GenerateStorybookTheme, type StorybookPluginOptions, type StorybookTheme, applyBrandDefaults, _default as default, flattenTokens, formatTokenValue, generateTokenDocs, renderInstallMd, renderThemeFile, resolveTokenSets, toCssVar };
221
+ export { type FlatToken, type GenerateStorybookTheme, type StorybookPluginOptions, type StorybookTheme, type StorybookThemePartial, type StorybookThemeResult, applyBrandDefaults, _default as default, flattenTokens, formatTokenValue, generateTokenDocs, normalizeThemes, renderInstallMd, renderThemeFile, resolveTokenSets, toCssVar };
200
222
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,16 +1,31 @@
1
- import{definePlugin as e}from"@razorwind/core/plugin";import{MONO_ROLES as t,SANS_ROLES as n,cssFontFamily as r,pickFontByRole as i}from"@razorwind/core/lib/fonts";import{createDocument as a,flattenTokens as o,formatTokenValue as s,resolveSchemaIdentity as c,resolveTokenSets as l,slugifyThemeName as u,toCssVar as d,toCssVar as f}from"@razorwind/core/utils";import{joinPaths as p}from"@stryke/path/join";import{join as m}from"node:path";function h(e,t={}){let n=t.cssVarPrefix??`rw`;return o(e,{includeTypes:t.includeTypes,enrichToken:e=>({...e,cssVar:f(e.path,n)})})}function g(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
2
- `,`\\n`).replaceAll(`\r`,`\\r`)}function _(e){return typeof e==`string`?`"${g(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function v(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles&&e.themeFiles.length>0?`
1
+ import{definePlugin as e}from"@razorwind/core/plugin";import{MONO_ROLES as t,SANS_ROLES as n,cssFontFamily as r,pickFontByRole as i}from"@razorwind/core/lib/fonts";import{SHARED_THEME_ID as a,createDocument as o,flattenTokens as s,formatTokenValue as c,isSharedThemeId as l,mergeTokenTrees as u,resolveSchemaIdentity as d,resolveTokenSets as f,toCssVar as p,toCssVar as m}from"@razorwind/core/utils";import{joinPaths as h}from"@stryke/path/join";function g(e,t={}){let n=t.cssVarPrefix??`rw`;return s(e,{includeTypes:t.includeTypes,enrichToken:e=>({...e,cssVar:m(e.path,n)})})}function _(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
2
+ `,`\\n`).replaceAll(`\r`,`\\r`)}function v(e){return typeof e==`string`?`"${_(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function y(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles?.[0],r=e.themeNames??[],i=n?r.length>1?`
3
+ ## Storybook UI theme
4
+
5
+ Generated theme module:
6
+
7
+ - \`${n}\` — record of \`create()\` themes keyed by name (${r.map(e=>`\`${e}\``).join(`, `)})
8
+
9
+ Wire into \`.storybook/preview.ts\`:
10
+
11
+ \`\`\`ts
12
+ import themes from "../${n}";
13
+
14
+ export const parameters = {
15
+ docs: { theme: themes[${JSON.stringify(r[0])}] }
16
+ };
17
+ \`\`\`
18
+ `:`
3
19
  ## Storybook UI theme
4
20
 
5
21
  Generated theme module(s):
6
22
 
7
- ${e.themeFiles.map(e=>`- \`${e}\``).join(`
8
- `)}
23
+ - \`${n}\`
9
24
 
10
25
  Wire into \`.storybook/preview.ts\`:
11
26
 
12
27
  \`\`\`ts
13
- import theme from "../${e.themeFiles[0]}";
28
+ import theme from "../${n}";
14
29
 
15
30
  export const parameters = {
16
31
  docs: { theme }
@@ -25,7 +40,7 @@ Generated by \`@razorwind/storybook\`.
25
40
  - \`${e.outputPath}/Tokens.mdx\` — token overview (${t})
26
41
  - \`${e.outputPath}/blocks/\` — React doc blocks (ColorPalette, Typeset, …)
27
42
  - \`${e.outputPath}/tokens.json\` — flattened token manifest
28
- ${n}
43
+ ${i}
29
44
  ## Setup
30
45
 
31
46
  1. Add the generated MDX pages to Storybook (paths depend on your \`stories\` config):
@@ -50,7 +65,7 @@ import { ColorPaletteBlock } from "./blocks";
50
65
  ## Regenerate
51
66
 
52
67
  Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputPath}/\`.
53
- `}function y(e,t){let n=new Map;for(let r of e){let e=r.path.split(`.`).slice(0,Math.max(t,1)).join(`.`)||r.path,i=n.get(e)??[];i.push(r),n.set(e,i)}return n}function b(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function x(e,t={}){return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
68
+ `}function b(e,t){let n=new Map;for(let r of e){let e=r.path.split(`.`).slice(0,Math.max(t,1)).join(`.`)||r.path,i=n.get(e)??[];i.push(r),n.set(e,i)}return n}function x(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function S(e,t={}){return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
54
69
 
55
70
  /**
56
71
  * Color tokens rendered with Storybook's ColorPalette doc block.
@@ -60,10 +75,10 @@ Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputP
60
75
  export function ColorPaletteBlock() {
61
76
  return (
62
77
  <ColorPalette>
63
- ${[...y(e.filter(e=>e.type===`color`),t.colorGroupBy??2).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.map(t=>` ${_(b(t.path,e))}: ${_(t.cssValue)}`).join(`,
78
+ ${[...b(e.filter(e=>e.type===`color`),t.colorGroupBy??2).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.map(t=>` ${v(x(t.path,e))}: ${v(t.cssValue)}`).join(`,
64
79
  `),r=t.find(e=>e.description)?.description??`${t.length} token${t.length===1?``:`s`}`;return` <ColorItem
65
- title={${_(e)}}
66
- subtitle={${_(r)}}
80
+ title={${v(e)}}
81
+ subtitle={${v(r)}}
67
82
  colors={{
68
83
  ${n}
69
84
  }}
@@ -72,7 +87,7 @@ ${n}
72
87
  </ColorPalette>
73
88
  );
74
89
  }
75
- `}function S(e,t={}){let a=t.sampleText??`The quick brown fox jumps over the lazy dog`,o=e.filter(e=>e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)).map(e=>{let t=/^(\d+(?:\.\d+)?)/.exec(e.cssValue);return t?Number(t[1]):e.cssValue}),s=[...new Set(o)],c=i(t.fonts,n),l=(c?r(c):void 0)??e.find(e=>e.type===`fontFamily`)?.cssValue??`system-ui, sans-serif`,u=e.find(e=>e.type===`fontWeight`),d=u&&Number.parseFloat(u.cssValue)||400,f=s.length>0?`[${s.map(e=>_(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`import { Typeset } from "@storybook/addon-docs/blocks";
90
+ `}function C(e,t={}){let a=t.sampleText??`The quick brown fox jumps over the lazy dog`,o=e.filter(e=>e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)).map(e=>{let t=/^(\d+(?:\.\d+)?)/.exec(e.cssValue);return t?Number(t[1]):e.cssValue}),s=[...new Set(o)],c=i(t.fonts,n),l=(c?r(c):void 0)??e.find(e=>e.type===`fontFamily`)?.cssValue??`system-ui, sans-serif`,u=e.find(e=>e.type===`fontWeight`),d=u&&Number.parseFloat(u.cssValue)||400,f=s.length>0?`[${s.map(e=>v(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`import { Typeset } from "@storybook/addon-docs/blocks";
76
91
 
77
92
  /**
78
93
  * Typography tokens rendered with Storybook's Typeset doc block.
@@ -82,14 +97,14 @@ ${n}
82
97
  export function TypesetBlock() {
83
98
  return (
84
99
  <Typeset
85
- fontFamily={${_(l)}}
100
+ fontFamily={${v(l)}}
86
101
  fontSizes={${f}}
87
- fontWeight={${_(d)}}
88
- sampleText={${_(a)}}
102
+ fontWeight={${v(d)}}
103
+ sampleText={${v(a)}}
89
104
  />
90
105
  );
91
106
  }
92
- `}function C(e){return`import type { CSSProperties, ReactElement } from "react";
107
+ `}function w(e){return`import type { CSSProperties, ReactElement } from "react";
93
108
 
94
109
  export interface TokenTableRow {
95
110
  path: string;
@@ -101,12 +116,12 @@ export interface TokenTableRow {
101
116
  }
102
117
 
103
118
  const TOKENS: TokenTableRow[] = [
104
- ${e.map(e=>{let t=e.theme?_(e.theme):`undefined`;return` {
105
- path: ${_(e.path)},
106
- type: ${e.type?_(e.type):`undefined`},
107
- value: ${_(e.cssValue)},
108
- cssVar: ${_(e.cssVar)},
109
- description: ${e.description?_(e.description):`undefined`},
119
+ ${e.map(e=>{let t=e.theme?v(e.theme):`undefined`;return` {
120
+ path: ${v(e.path)},
121
+ type: ${e.type?v(e.type):`undefined`},
122
+ value: ${v(e.cssValue)},
123
+ cssVar: ${v(e.cssVar)},
124
+ description: ${e.description?v(e.description):`undefined`},
110
125
  theme: ${t}
111
126
  }`}).join(`,
112
127
  `)||``}
@@ -193,7 +208,7 @@ export function TokenTableBlock({
193
208
  </table>
194
209
  );
195
210
  }
196
- `}function w(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
211
+ `}function T(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
197
212
  ## Colors
198
213
 
199
214
  <ColorPaletteBlock />
@@ -206,7 +221,7 @@ import { ColorPaletteBlock } from "./blocks/ColorPalette";
206
221
  import { TokenTableBlock } from "./blocks/TokenTable";
207
222
  import { TypesetBlock } from "./blocks/Typeset";
208
223
 
209
- <Meta title="${g(t)}/Overview" />
224
+ <Meta title="${_(t)}/Overview" />
210
225
 
211
226
  # ${t}
212
227
 
@@ -215,23 +230,23 @@ ${n}${r}
215
230
  ## All tokens
216
231
 
217
232
  <TokenTableBlock />
218
- `}function T(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
233
+ `}function E(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
219
234
  import { ColorPaletteBlock } from "./blocks/ColorPalette";
220
235
 
221
- <Meta title="${g(e.titlePrefix??`Design Tokens`)}/Colors" />
236
+ <Meta title="${_(e.titlePrefix??`Design Tokens`)}/Colors" />
222
237
 
223
238
  # Colors
224
239
 
225
240
  <ColorPaletteBlock />
226
- `}function E(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
241
+ `}function D(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
227
242
  import { TypesetBlock } from "./blocks/Typeset";
228
243
 
229
- <Meta title="${g(e.titlePrefix??`Design Tokens`)}/Typography" />
244
+ <Meta title="${_(e.titlePrefix??`Design Tokens`)}/Typography" />
230
245
 
231
246
  # Typography
232
247
 
233
248
  <TypesetBlock />
234
- `}function D(e,t){let n=e[t];return typeof n==`string`?n:void 0}function O(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function k(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
249
+ `}function O(e,t){let n=e[t];return typeof n==`string`?n:void 0}function k(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function A(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
235
250
 
236
251
  /**
237
252
  * Icons rendered with Storybook's IconGallery doc block.
@@ -241,39 +256,48 @@ import { TypesetBlock } from "./blocks/Typeset";
241
256
  export function IconGalleryBlock() {
242
257
  return (
243
258
  <IconGallery>
244
- ${(O(e)?Object.values(e).filter(O).toSorted((e,t)=>(D(e,`name`)??``).localeCompare(D(t,`name`)??``)):[]).map(e=>{let t=D(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>O(e)&&D(e,`type`)===`svg`&&typeof e.content==`string`),r=O(n)&&typeof n.content==`string`?`<span
259
+ ${(k(e)?Object.values(e).filter(k).toSorted((e,t)=>(O(e,`name`)??``).localeCompare(O(t,`name`)??``)):[]).map(e=>{let t=O(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>k(e)&&O(e,`type`)===`svg`&&typeof e.content==`string`),r=k(n)&&typeof n.content==`string`?`<span
245
260
  style={{ display: "inline-flex", width: 24, height: 24 }}
246
- dangerouslySetInnerHTML={{ __html: ${_(n.content)} }}
247
- />`:`<code>${g(t)}</code>`;return` <IconItem name={${_(t)}}>
261
+ dangerouslySetInnerHTML={{ __html: ${v(n.content)} }}
262
+ />`:`<code>${_(t)}</code>`;return` <IconItem name={${v(t)}}>
248
263
  ${r}
249
264
  </IconItem>`}).join(`
250
265
  `)||` {/* No icons */}`}
251
266
  </IconGallery>
252
267
  );
253
268
  }
254
- `}function A(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
269
+ `}function j(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
255
270
  import { IconGalleryBlock } from "./blocks/IconGallery";
256
271
 
257
- <Meta title="${g(e.titlePrefix??`Design Tokens`)}/Icons" />
272
+ <Meta title="${_(e.titlePrefix??`Design Tokens`)}/Icons" />
258
273
 
259
274
  # Icons
260
275
 
261
276
  <IconGalleryBlock />
262
- `}function j(){return`export { ColorPaletteBlock } from "./ColorPalette";
277
+ `}function M(){return`export { ColorPaletteBlock } from "./ColorPalette";
263
278
  export { IconGalleryBlock } from "./IconGallery";
264
279
  export { TokenTableBlock } from "./TokenTable";
265
280
  export type { TokenTableBlockProps, TokenTableRow } from "./TokenTable";
266
281
  export { TypesetBlock } from "./Typeset";
267
- `}function M(e){return O(e)?e.base===`light`||e.base===`dark`:!1}function N(e,a,o){let s=i(o,n),c=i(o,t);return{brandTarget:`_blank`,...e,brandTitle:e.brandTitle??a.title,brandUrl:e.brandUrl??a.homepage,brandImage:e.brandImage??a.logo,fontBase:e.fontBase??(s?r(s):void 0),fontCode:e.fontCode??(c?r(c):void 0)}}function P(e){return`import { create } from "storybook/theming";
282
+ `}const N=new Set(`base.colorPrimary.colorSecondary.appBg.appContentBg.appHoverBg.appPreviewBg.appBorderColor.appBorderRadius.fontBase.fontCode.textColor.textInverseColor.textMutedColor.barTextColor.barHoverColor.barSelectedColor.barBg.buttonBg.buttonBorder.booleanBg.booleanSelectedBg.inputBg.inputBorder.inputTextColor.inputBorderRadius.brandTitle.brandUrl.brandImage.brandTarget.gridCellSize`.split(`.`));function P(e){return k(e)?e.base===`light`||e.base===`dark`:!1}function F(e){return k(e)?P(e)?!0:Object.keys(e).some(e=>N.has(e)):!1}function I(e){if(!k(e)||F(e))return!1;let t=Object.values(e);return t.length>0&&t.every(F)}function L(e,t,n){return t.base===`light`||t.base===`dark`?t.base:`${e} ${n??``}`.toLowerCase().includes(`light`)?`light`:`dark`}function R(e){return/^[a-z_$][\w$]*$/i.test(e)?e:v(e)}function z(e,t){let n=e.find(e=>e.id===a);return!n||l(t.id)?t.tokens:u(t.tokens,n.tokens)}function B(e,t,n,r,i){return V(L(e,t,i),t,n,r)}function V(e,a,o,s){let c=i(s,n),l=i(s,t);return{brandTarget:`_blank`,base:e||`light`,...a,brandTitle:a.brandTitle??o.title,brandUrl:a.brandUrl??o.homepage,brandImage:a.brandImage??o.logo,fontBase:a.fontBase??(c?r(c):void 0),fontCode:a.fontCode??(l?r(l):void 0)}}function H(e,t=``){return`create({\n${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>`${t} ${e}: ${v(n)}`).join(`,
283
+ `)}\n${t}})`}function U(e){return`import { create } from "storybook/theming";
268
284
 
269
285
  /**
270
286
  * Storybook UI theme generated by \`@razorwind/storybook\`.
271
287
  *
272
288
  * @see https://storybook.js.org/docs/configure/user-interface/theming
273
289
  */
274
- export default create({
275
- ${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>` ${e}: ${_(t)}`).join(`,
290
+ export default ${H(e)};
291
+ `}function W(e){return`import { create } from "storybook/theming";
292
+
293
+ /**
294
+ * Storybook UI themes generated by \`@razorwind/storybook\`.
295
+ *
296
+ * @see https://storybook.js.org/docs/configure/user-interface/theming
297
+ */
298
+ export default {
299
+ ${Object.entries(e).map(([e,t])=>` ${R(e)}: ${H(t,` `)}`).join(`,
276
300
  `)}
277
- });
278
- `}const F=e=>(t,n,r)=>a(p(e,t),n,{name:`razorwind-storybook`},(n,r)=>p(e,u(r),t),r);function I(e,t={}){let n=t.outputPath??`storybook/tokens`,r=c(e),i=t.titlePrefix??r.title??`Design Tokens`,a={...t,titlePrefix:i},o=h(e.tokens,t),s=o.some(e=>e.type===`color`),l=e.fonts&&Object.keys(e.fonts).length>0||o.some(e=>e.type===`fontFamily`||e.type===`fontWeight`||e.type===`typography`||e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)),u=!t.skipIcons&&O(e.icons)&&Object.keys(e.icons).length>0,d=F(n),f={[p(n,`blocks/ColorPalette.tsx`)]:d(`blocks/ColorPalette.tsx`,x(o,a),`tsx`),[p(n,`blocks/Typeset.tsx`)]:d(`blocks/Typeset.tsx`,S(o,{...a,fonts:e.fonts}),`tsx`),[p(n,`blocks/TokenTable.tsx`)]:d(`blocks/TokenTable.tsx`,C(o),`tsx`),[p(n,`blocks/IconGallery.tsx`)]:d(`blocks/IconGallery.tsx`,k(t.skipIcons?{}:e.icons),`tsx`),[p(n,`blocks/index.ts`)]:d(`blocks/index.ts`,j(),`typescript`),[p(n,`Tokens.mdx`)]:d(`Tokens.mdx`,w({titlePrefix:i,hasColors:s,hasTypography:l}),`mdx`)};if(s&&(f[p(n,`Colors.mdx`)]=d(`Colors.mdx`,T(a),`mdx`)),l&&(f[p(n,`Typography.mdx`)]=d(`Typography.mdx`,E(a),`mdx`)),u&&(f[p(n,`Icons.mdx`)]=d(`Icons.mdx`,A(a),`mdx`)),f[p(n,`tokens.json`)]=d(`tokens.json`,`${JSON.stringify(o,null,2)}\n`,`json`),t.mapTheme){let i=t.mapTheme(e.tokens);if(M(i))f[p(n,`theme.ts`)]=d(`theme.ts`,P(N(i,r,e.fonts)),`typescript`);else if(O(i))for(let[t,a]of Object.entries(i))M(a)&&(f[p(n,`theme-${t}.ts`)]=d(`theme-${t}.ts`,P(N(a,r,e.fonts)),`typescript`))}let g=Object.keys(f).filter(e=>e.startsWith(m(n,`theme`))).map(e=>e.slice(n.length+1)),_=`INSTALL.md`;return f[p(n,_)]=d(_,t.installGuide??v({outputPath:n,titlePrefix:i,themeFiles:g.length>0?g:void 0}),`markdown`),f}var L=e(e=>({name:`storybook`,generate:async t=>I(t,e??{})}));export{N as applyBrandDefaults,L as default,h as flattenTokens,s as formatTokenValue,I as generateTokenDocs,v as renderInstallMd,P as renderThemeFile,l as resolveTokenSets,d as toCssVar};
301
+ };
302
+ `}function G(e){if(P(e))return U(e);let t=Object.entries(e);if(t.length!==1)return W(e);let[,n]=t[0]??[];return n?U(n):W(e)}function K(e,t,n,r){let i=(e,r)=>B(e,r,n,t.fonts,t.theme);if(I(e))return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,i(e,t)]));let a=f(t.tokens),o=a.filter(e=>!l(e.id));if(o.length>1){let e={};for(let t of o){let n=r(z(a,t));if(I(n)){let r=n[t.id];if(r){e[t.id]=i(t.id,r);continue}for(let[t,r]of Object.entries(n))e[t]=i(t,r);continue}F(n)&&(e[t.id]=i(t.id,n))}return e}if(F(e)){let n=o[0]&&o[0].id!=="default"?o[0].id:t.theme??`default`;return{[n]:i(n,e)}}return{}}const q=e=>(t,n,r)=>o(h(e,t),n,{name:`razorwind-storybook`},!1,r);function J(e,t={}){let n=t.outputPath??`storybook/tokens`,r=d(e),i=t.titlePrefix??r.title??`Design Tokens`,a={...t,titlePrefix:i},o=g(e.tokens,t),s=o.some(e=>e.type===`color`),c=e.fonts&&Object.keys(e.fonts).length>0||o.some(e=>e.type===`fontFamily`||e.type===`fontWeight`||e.type===`typography`||e.type===`dimension`&&/(?:font|type|text).*size|size.*(?:font|type|text)/i.test(e.path)),l=!t.skipIcons&&k(e.icons)&&Object.keys(e.icons).length>0,u=q(n),f={[h(n,`blocks/ColorPalette.tsx`)]:u(`blocks/ColorPalette.tsx`,S(o,a),`tsx`),[h(n,`blocks/Typeset.tsx`)]:u(`blocks/Typeset.tsx`,C(o,{...a,fonts:e.fonts}),`tsx`),[h(n,`blocks/TokenTable.tsx`)]:u(`blocks/TokenTable.tsx`,w(o),`tsx`),[h(n,`blocks/IconGallery.tsx`)]:u(`blocks/IconGallery.tsx`,A(t.skipIcons?{}:e.icons),`tsx`),[h(n,`blocks/index.ts`)]:u(`blocks/index.ts`,M(),`typescript`),[h(n,`Tokens.mdx`)]:u(`Tokens.mdx`,T({titlePrefix:i,hasColors:s,hasTypography:c}),`mdx`)};s&&(f[h(n,`Colors.mdx`)]=u(`Colors.mdx`,E(a),`mdx`)),c&&(f[h(n,`Typography.mdx`)]=u(`Typography.mdx`,D(a),`mdx`)),l&&(f[h(n,`Icons.mdx`)]=u(`Icons.mdx`,j(a),`mdx`)),f[h(n,`tokens.json`)]=u(`tokens.json`,`${JSON.stringify(o,null,2)}\n`,`json`);let p;if(t.mapTheme){let i=K(t.mapTheme(e.tokens),e,r,t.mapTheme);Object.keys(i).length>0&&(p=Object.keys(i),f[h(n,`theme.ts`)]=u(`theme.ts`,G(i),`typescript`))}let m=`INSTALL.md`;return f[h(n,m)]=u(m,t.installGuide??y({outputPath:n,titlePrefix:i,themeFiles:p?[`theme.ts`]:void 0,themeNames:p}),`markdown`),f}var Y=e(e=>({name:`storybook`,themeGeneration:`combined`,generate:async t=>J(t,e??{})}));export{V as applyBrandDefaults,Y as default,g as flattenTokens,c as formatTokenValue,J as generateTokenDocs,K as normalizeThemes,y as renderInstallMd,G as renderThemeFile,f as resolveTokenSets,p as toCssVar};
279
303
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@razorwind/storybook",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "type": "module",
5
5
  "description": "Razorwind plugin that creates Storybook MDX token doc blocks from Razorwind design tokens.",
6
6
  "repository": {
@@ -85,7 +85,7 @@
85
85
  "dependencies": {
86
86
  "@power-plant/core": "^0.0.90",
87
87
  "@power-plant/dtcg-schema": "^0.0.1",
88
- "@razorwind/core": "^0.0.50",
88
+ "@razorwind/core": "^0.0.52",
89
89
  "@stryke/path": "^0.29.35",
90
90
  "@stryke/type-checks": "^0.6.41"
91
91
  },
@@ -101,9 +101,10 @@
101
101
  },
102
102
  "devDependencies": {
103
103
  "@powerlines/plugin-tsdown": "^0.1.612",
104
+ "@stryke/types": "^0.12.36",
104
105
  "@types/node": "^25.9.5",
105
106
  "typescript": "^6.0.3"
106
107
  },
107
108
  "publishConfig": { "access": "public" },
108
- "gitHead": "604b878d66c0cfab51c5c9497c5c9f7bf81ec688"
109
+ "gitHead": "a72e2fb9b29f96e4f2c2241f622e56e6929f6dc9"
109
110
  }