@razorwind/storybook 0.0.60 → 0.0.62
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 +145 -56
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +150 -61
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
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){return e===!0||e===`true`||e===1}function a(e,t){return e?`${e}:${t}`:t}function o(e){let t=e.theme??e.$theme;return typeof t==`string`&&t.length>0?t:void 0}function s(e,t){return e===`palette`||e===`$palette`?typeof t==`boolean`||typeof t==`number`||typeof t==`string`:(e===`theme`||e===`$theme`)&&typeof t==`string`}function c(e){let t=new Map;function r(e,c,l,u,d){if(!(0,n.isObject)(e))return;let f=u||i(e.palette)||i(e.$palette),p=o(e)??d;if((0,n.isTokenLeaf)(e)){(f||p)&&t.set(a(l,c.join(`.`)),{...f&&{palette:!0},...p&&{childTheme:p}});return}for(let[t,n]of Object.entries(e))t.startsWith(`$`)&&t!==`$palette`&&t!==`$theme`||s(t,n)||r(n,[...c,t],l,f,p)}for(let t of(0,n.resolveTokenSets)(e)){let e=t.id==="default"?void 0:t.id;r(t.tokens,[],e,!1,void 0)}return t}function l(e,t={}){let r=t.cssVarPrefix??`rw`,i=c(e);return(0,n.flattenTokens)(e,{includeTypes:t.includeTypes,enrichToken:e=>{let t=i.get(a(e.theme,e.path));return{...e,cssVar:(0,n.toCssVar)(e.path,r),...e.type===`color`&&t}}})}function u(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
|
|
2
|
-
`,`\\n`).replaceAll(`\r`,`\\r`)}function d(e){return typeof e==`string`?`"${u(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function f(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles?.[0],r=e.themeNames??[],i=
|
|
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){return e===!0||e===`true`||e===1}function a(e,t){return e?`${e}:${t}`:t}function o(e){let t=e.theme??e.$theme;return typeof t==`string`&&t.length>0?t:void 0}function s(e,t){return e===`palette`||e===`$palette`?typeof t==`boolean`||typeof t==`number`||typeof t==`string`:(e===`theme`||e===`$theme`)&&typeof t==`string`}function c(e){let t=new Map;function r(e,c,l,u,d){if(!(0,n.isObject)(e))return;let f=u||i(e.palette)||i(e.$palette),p=o(e)??d;if((0,n.isTokenLeaf)(e)){(f||p)&&t.set(a(l,c.join(`.`)),{...f&&{palette:!0},...p&&{childTheme:p}});return}for(let[t,n]of Object.entries(e))t.startsWith(`$`)&&t!==`$palette`&&t!==`$theme`||s(t,n)||r(n,[...c,t],l,f,p)}for(let t of(0,n.resolveTokenSets)(e)){let e=t.id==="default"?void 0:t.id;r(t.tokens,[],e,!1,void 0)}return t}function l(e,t={}){let r=t.cssVarPrefix??`rw`,i=c(e);return(0,n.flattenTokens)(e,{includeTypes:t.includeTypes,shouldIncludeToken:e=>e.skipDocs!==!0,enrichToken:e=>{let t=i.get(a(e.theme,e.path));return{...e,cssVar:(0,n.toCssVar)(e.path,r),...e.type===`color`&&t}}})}function u(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
|
|
2
|
+
`,`\\n`).replaceAll(`\r`,`\\r`)}function d(e){return typeof e==`string`?`"${u(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function f(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles?.[0],r=e.themeNames??[],i=e.tokenThemeNames??[],a=i.length>1?`
|
|
3
|
+
## Token-doc variants
|
|
4
|
+
|
|
5
|
+
Generated token blocks follow Storybook's \`theme\` global when it matches one
|
|
6
|
+
of these token-set names: ${i.map(e=>`\`${e}\``).join(`, `)}.
|
|
7
|
+
Pass \`theme\` directly to a block to override that selection.
|
|
8
|
+
`:``,o=n?r.length>1?`
|
|
3
9
|
## Storybook UI theme
|
|
4
10
|
|
|
5
11
|
Generated theme module:
|
|
@@ -40,7 +46,7 @@ Generated by \`@razorwind/storybook\`.
|
|
|
40
46
|
- \`${e.outputPath}/Tokens.mdx\` — token overview (${t})
|
|
41
47
|
- \`${e.outputPath}/blocks/\` — React doc blocks (ColorPalette, Typeset, …)
|
|
42
48
|
- \`${e.outputPath}/tokens.json\` — flattened token manifest
|
|
43
|
-
${
|
|
49
|
+
${o}${a}
|
|
44
50
|
## Setup
|
|
45
51
|
|
|
46
52
|
1. Add the generated MDX pages to Storybook (paths depend on your \`stories\` config):
|
|
@@ -65,7 +71,28 @@ import { ColorPaletteBlock } from "./blocks";
|
|
|
65
71
|
## Regenerate
|
|
66
72
|
|
|
67
73
|
Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputPath}/\`.
|
|
68
|
-
`}
|
|
74
|
+
`}const p=new Set([`fontFamily`,`fontWeight`,`typography`]),m=/font|typography|type|text|line[-_.]?height|letter[-_.]?spacing/i;function h(e){return p.has(e.type??``)?!0:(e.type===`dimension`||e.type===`number`)&&m.test(e.path)}function g(e,t){return e.some(e=>t.some(t=>e.path===t||e.path.startsWith(`${t}.`)))}const _=/^\{([^{}]+)\}$/,v=/^var\((--[^),\s]+)(?:\s*,[^)]*)?\)$/;function y(e){if(typeof e==`string`)return _.exec(e.trim())?.[1]?.trim()}function b(e){if(typeof e==`string`)return v.exec(e.trim())?.[1]}function x(e){let t=new Map(e.map(e=>[e.path,e])),r=new Map(e.map(e=>[(0,n.toThemeCssVar)(e.path),e])),i=e=>{let n=e,i=new Set;for(let a=0;a<8;a++){if(i.has(n.path))return e.cssValue;i.add(n.path);let a=t.get(y(n.value)??``)??r.get(b(n.value)??b(n.cssValue)??``);if(!a||a.path===n.path)return n.cssValue;n=a}return e.cssValue};return e.map(e=>e.type===`color`?{...e,cssValue:i(e)}:e)}function S(e){return Object.keys(e).length>1}function ee(){return`import { useGlobals, useMemo } from "storybook/preview-api";
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Select a generated token variant. By default this follows Storybook's
|
|
78
|
+
* \`theme\` global; callers may pass \`theme\` to override it.
|
|
79
|
+
*/
|
|
80
|
+
export function useThemeVariant<T extends Record<string, unknown>>(
|
|
81
|
+
variants: T,
|
|
82
|
+
fallback: keyof T & string,
|
|
83
|
+
theme?: string
|
|
84
|
+
): keyof T & string {
|
|
85
|
+
const [globals] = useGlobals();
|
|
86
|
+
|
|
87
|
+
return useMemo(() => {
|
|
88
|
+
const candidate = theme ?? globals.theme;
|
|
89
|
+
|
|
90
|
+
return typeof candidate === "string" && candidate in variants
|
|
91
|
+
? (candidate as keyof T & string)
|
|
92
|
+
: fallback;
|
|
93
|
+
}, [fallback, globals.theme, theme, variants]);
|
|
94
|
+
}
|
|
95
|
+
`}function C(e,t){let r=(0,n.resolveTokenSets)(e),i=r.filter(e=>!(0,n.isSharedThemeId)(e.id));return i.length<=1?{default:x(l(e,t))}:Object.fromEntries(i.map(e=>[e.id,x(l(B(r,e),t))]))}function w(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 T(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function E(e,t={}){let n=t.colorGroupBy??2,r=Object.entries(e),i=r[0]?.[0]??`default`,a=S(e),o=(e,t=` `)=>[...w(e,n).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,n])=>{let r=n.map(n=>`${t} ${d(T(n.path,e))}: ${d(n.cssValue)}`).join(`,
|
|
69
96
|
`),i=n.find(e=>e.description)?.description??`${n.length} token${n.length===1?``:`s`}`;return`${t}<ColorItem
|
|
70
97
|
title={${d(e)}}
|
|
71
98
|
subtitle={${d(i)}}
|
|
@@ -73,46 +100,80 @@ Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputP
|
|
|
73
100
|
${r}
|
|
74
101
|
}}
|
|
75
102
|
/>`}).join(`
|
|
76
|
-
`),
|
|
103
|
+
`),s=e=>{let t=e.filter(e=>e.type===`color`),n=t.filter(e=>e.palette),r=t.filter(e=>!e.palette&&e.childTheme),i=t.filter(e=>!e.palette&&!e.childTheme),a=n.length>0||r.length>0,s=o(t),c=[[`Color palettes`,n],[`Semantic colors`,r],[`Colors`,i]].filter(e=>!!e[1]?.length).map(([e,t])=>` <section>
|
|
77
104
|
<h2>${e}</h2>
|
|
78
105
|
<ColorPalette>
|
|
79
|
-
${
|
|
106
|
+
${o(t,` `)}
|
|
80
107
|
</ColorPalette>
|
|
81
108
|
</section>`).join(`
|
|
109
|
+
`);return a?`<>\n${c}\n </>`:`<ColorPalette>\n${s||` {/* No color tokens */}`}\n </ColorPalette>`},c=r.map(([e,t])=>` ${d(e)}: (\n ${s(t)}\n )`).join(`,
|
|
82
110
|
`);return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
|
|
111
|
+
${a?`import { useThemeVariant } from "./ThemeVariant";
|
|
112
|
+
`:``}
|
|
83
113
|
|
|
84
114
|
/**
|
|
85
115
|
* Color tokens rendered with Storybook's ColorPalette doc block.
|
|
86
116
|
*
|
|
87
117
|
* @see https://storybook.js.org/docs/api/doc-blocks/doc-block-colorpalette
|
|
88
118
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
119
|
+
const COLOR_VARIANTS = {
|
|
120
|
+
${c}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export interface ColorPaletteBlockProps {
|
|
124
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
125
|
+
theme?: string;
|
|
97
126
|
}
|
|
98
|
-
|
|
127
|
+
|
|
128
|
+
export function ColorPaletteBlock({ theme }: ColorPaletteBlockProps = {}) {
|
|
129
|
+
const activeTheme = ${a?`useThemeVariant(COLOR_VARIANTS, ${d(i)}, theme)`:d(i)};
|
|
130
|
+
|
|
131
|
+
return COLOR_VARIANTS[activeTheme];
|
|
132
|
+
}
|
|
133
|
+
`}function D(e,n={}){let r=n.sampleText??`The quick brown fox jumps over the lazy dog`,i=S(e),a=Object.entries(e),o=a[0]?.[0]??`default`,s=e=>{let 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),s=(o?(0,t.cssFontFamily)(o):void 0)??e.find(e=>e.type===`fontFamily`)?.cssValue??`system-ui, sans-serif`,c=e.find(e=>e.type===`fontWeight`),l=c&&Number.parseFloat(c.cssValue)||400,u=a.length>0?`[${a.map(e=>d(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`<Typeset
|
|
134
|
+
fontFamily={${d(s)}}
|
|
135
|
+
fontSizes={${u}}
|
|
136
|
+
fontWeight={${d(l)}}
|
|
137
|
+
sampleText={${d(r)}}
|
|
138
|
+
/>`},c=a.map(([e,t])=>` ${d(e)}: (${s(t)})`).join(`,
|
|
139
|
+
`);return`import { Typeset } from "@storybook/addon-docs/blocks";
|
|
140
|
+
${i?`import { useThemeVariant } from "./ThemeVariant";
|
|
141
|
+
`:``}
|
|
99
142
|
|
|
100
143
|
/**
|
|
101
144
|
* Typography tokens rendered with Storybook's Typeset doc block.
|
|
102
145
|
*
|
|
103
146
|
* @see https://storybook.js.org/docs/api/doc-blocks/doc-block-typeset
|
|
104
147
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/>
|
|
113
|
-
);
|
|
148
|
+
const TYPESET_VARIANTS = {
|
|
149
|
+
${c}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export interface TypesetBlockProps {
|
|
153
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
154
|
+
theme?: string;
|
|
114
155
|
}
|
|
115
|
-
|
|
156
|
+
|
|
157
|
+
export function TypesetBlock({ theme }: TypesetBlockProps = {}) {
|
|
158
|
+
const activeTheme = ${i?`useThemeVariant(TYPESET_VARIANTS, ${d(o)}, theme)`:d(o)};
|
|
159
|
+
|
|
160
|
+
return TYPESET_VARIANTS[activeTheme];
|
|
161
|
+
}
|
|
162
|
+
`}function O(e){let t=S(e),n=Object.entries(e),r=n[0]?.[0]??`default`,i=e=>e.map(e=>{let t=e.theme?d(e.theme):`undefined`;return` {
|
|
163
|
+
path: ${d(e.path)},
|
|
164
|
+
type: ${e.type?d(e.type):`undefined`},
|
|
165
|
+
value: ${d(e.cssValue)},
|
|
166
|
+
cssVar: ${d(e.cssVar)},
|
|
167
|
+
description: ${e.description?d(e.description):`undefined`},
|
|
168
|
+
theme: ${t},
|
|
169
|
+
typography: ${h(e)}
|
|
170
|
+
}`}).join(`,
|
|
171
|
+
`),a=n.map(([e,t])=>` ${d(e)}: [
|
|
172
|
+
${i(t)}
|
|
173
|
+
]`).join(`,
|
|
174
|
+
`);return`import type { CSSProperties, ReactElement } from "react";
|
|
175
|
+
${t?`import { useThemeVariant } from "./ThemeVariant";
|
|
176
|
+
`:``}
|
|
116
177
|
|
|
117
178
|
export interface TokenTableRow {
|
|
118
179
|
path: string;
|
|
@@ -121,19 +182,12 @@ export interface TokenTableRow {
|
|
|
121
182
|
cssVar: string;
|
|
122
183
|
description?: string;
|
|
123
184
|
theme?: string;
|
|
185
|
+
typography: boolean;
|
|
124
186
|
}
|
|
125
187
|
|
|
126
|
-
const
|
|
127
|
-
${
|
|
128
|
-
|
|
129
|
-
type: ${e.type?d(e.type):`undefined`},
|
|
130
|
-
value: ${d(e.cssValue)},
|
|
131
|
-
cssVar: ${d(e.cssVar)},
|
|
132
|
-
description: ${e.description?d(e.description):`undefined`},
|
|
133
|
-
theme: ${t}
|
|
134
|
-
}`}).join(`,
|
|
135
|
-
`)||``}
|
|
136
|
-
];
|
|
188
|
+
const TOKEN_VARIANTS: Record<string, TokenTableRow[]> = {
|
|
189
|
+
${a}
|
|
190
|
+
};
|
|
137
191
|
|
|
138
192
|
const tableStyle: CSSProperties = {
|
|
139
193
|
width: "100%",
|
|
@@ -160,10 +214,14 @@ const swatchStyle = (value: string): CSSProperties => ({
|
|
|
160
214
|
});
|
|
161
215
|
|
|
162
216
|
export interface TokenTableBlockProps {
|
|
163
|
-
/** Optional path prefix filter (e.g. \`color\`). */
|
|
164
|
-
filter?: string;
|
|
217
|
+
/** Optional path prefix filter or filters (e.g. \`color\`). */
|
|
218
|
+
filter?: string | string[];
|
|
165
219
|
/** Optional DTCG \`$type\` filter. */
|
|
166
220
|
type?: string;
|
|
221
|
+
/** Restrict rows to tokens used to define typography. */
|
|
222
|
+
typography?: boolean;
|
|
223
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
224
|
+
theme?: string;
|
|
167
225
|
}
|
|
168
226
|
|
|
169
227
|
/**
|
|
@@ -171,15 +229,27 @@ export interface TokenTableBlockProps {
|
|
|
171
229
|
*/
|
|
172
230
|
export function TokenTableBlock({
|
|
173
231
|
filter,
|
|
174
|
-
type
|
|
232
|
+
type,
|
|
233
|
+
typography,
|
|
234
|
+
theme
|
|
175
235
|
}: TokenTableBlockProps = {}): ReactElement {
|
|
176
|
-
const
|
|
177
|
-
|
|
236
|
+
const activeTheme = ${t?`useThemeVariant(TOKEN_VARIANTS, ${d(r)}, theme)`:d(r)};
|
|
237
|
+
const rows = TOKEN_VARIANTS[activeTheme].filter(token => {
|
|
238
|
+
const filters = typeof filter === "string" ? [filter] : filter;
|
|
239
|
+
if (
|
|
240
|
+
filters &&
|
|
241
|
+
!filters.some(prefix =>
|
|
242
|
+
token.path === prefix || token.path.startsWith(\`\${prefix}.\`)
|
|
243
|
+
)
|
|
244
|
+
) {
|
|
178
245
|
return false;
|
|
179
246
|
}
|
|
180
247
|
if (type && token.type !== type) {
|
|
181
248
|
return false;
|
|
182
249
|
}
|
|
250
|
+
if (typography && !token.typography) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
183
253
|
return true;
|
|
184
254
|
});
|
|
185
255
|
|
|
@@ -216,7 +286,7 @@ export function TokenTableBlock({
|
|
|
216
286
|
</table>
|
|
217
287
|
);
|
|
218
288
|
}
|
|
219
|
-
`}function
|
|
289
|
+
`}function k(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
|
|
220
290
|
## Colors
|
|
221
291
|
|
|
222
292
|
<ColorPaletteBlock />
|
|
@@ -224,6 +294,17 @@ export function TokenTableBlock({
|
|
|
224
294
|
## Typography
|
|
225
295
|
|
|
226
296
|
<TypesetBlock />
|
|
297
|
+
`:``,i=e.hasSizes?`
|
|
298
|
+
## Size
|
|
299
|
+
|
|
300
|
+
<TokenTableBlock filter="size" />
|
|
301
|
+
`:``,a=e.hasSpaces?`
|
|
302
|
+
## Space
|
|
303
|
+
|
|
304
|
+
<TokenTableBlock filter={[
|
|
305
|
+
"space",
|
|
306
|
+
"spacing"
|
|
307
|
+
]} />
|
|
227
308
|
`:``;return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
228
309
|
import { ColorPaletteBlock } from "./blocks/ColorPalette";
|
|
229
310
|
import { TokenTableBlock } from "./blocks/TokenTable";
|
|
@@ -234,11 +315,11 @@ import { TypesetBlock } from "./blocks/Typeset";
|
|
|
234
315
|
# ${t}
|
|
235
316
|
|
|
236
317
|
Design tokens generated by \`@razorwind/storybook\` for Storybook MDX docs.
|
|
237
|
-
${n}${r}
|
|
318
|
+
${n}${r}${i}${a}
|
|
238
319
|
## All tokens
|
|
239
320
|
|
|
240
321
|
<TokenTableBlock />
|
|
241
|
-
`}function
|
|
322
|
+
`}function A(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
242
323
|
import { ColorPaletteBlock } from "./blocks/ColorPalette";
|
|
243
324
|
|
|
244
325
|
<Meta title="${u(e.titlePrefix??`Design Tokens`)}/Colors" />
|
|
@@ -246,15 +327,20 @@ import { ColorPaletteBlock } from "./blocks/ColorPalette";
|
|
|
246
327
|
# Colors
|
|
247
328
|
|
|
248
329
|
<ColorPaletteBlock />
|
|
249
|
-
`}function
|
|
330
|
+
`}function j(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
250
331
|
import { TypesetBlock } from "./blocks/Typeset";
|
|
332
|
+
import { TokenTableBlock } from "./blocks/TokenTable";
|
|
251
333
|
|
|
252
334
|
<Meta title="${u(e.titlePrefix??`Design Tokens`)}/Typography" />
|
|
253
335
|
|
|
254
336
|
# Typography
|
|
255
337
|
|
|
256
338
|
<TypesetBlock />
|
|
257
|
-
|
|
339
|
+
|
|
340
|
+
## Typography tokens
|
|
341
|
+
|
|
342
|
+
<TokenTableBlock typography />
|
|
343
|
+
`}function M(e,t){let n=e[t];return typeof n==`string`?n:void 0}function N(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function te(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
|
|
258
344
|
|
|
259
345
|
/**
|
|
260
346
|
* Icons rendered with Storybook's IconGallery doc block.
|
|
@@ -264,7 +350,7 @@ import { TypesetBlock } from "./blocks/Typeset";
|
|
|
264
350
|
export function IconGalleryBlock() {
|
|
265
351
|
return (
|
|
266
352
|
<IconGallery>
|
|
267
|
-
${(
|
|
353
|
+
${(N(e)?Object.values(e).filter(N).toSorted((e,t)=>(M(e,`name`)??``).localeCompare(M(t,`name`)??``)):[]).map(e=>{let t=M(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>N(e)&&M(e,`type`)===`svg`&&typeof e.content==`string`),r=N(n)&&typeof n.content==`string`?`<span
|
|
268
354
|
style={{ display: "inline-flex", width: 24, height: 24 }}
|
|
269
355
|
dangerouslySetInnerHTML={{ __html: ${d(n.content)} }}
|
|
270
356
|
/>`:`<code>${u(t)}</code>`;return` <IconItem name={${d(t)}}>
|
|
@@ -274,7 +360,7 @@ ${(S(e)?Object.values(e).filter(S).toSorted((e,t)=>(x(e,`name`)??``).localeCompa
|
|
|
274
360
|
</IconGallery>
|
|
275
361
|
);
|
|
276
362
|
}
|
|
277
|
-
`}function
|
|
363
|
+
`}function ne(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
278
364
|
import { IconGalleryBlock } from "./blocks/IconGallery";
|
|
279
365
|
|
|
280
366
|
<Meta title="${u(e.titlePrefix??`Design Tokens`)}/Icons" />
|
|
@@ -282,21 +368,24 @@ import { IconGalleryBlock } from "./blocks/IconGallery";
|
|
|
282
368
|
# Icons
|
|
283
369
|
|
|
284
370
|
<IconGalleryBlock />
|
|
285
|
-
`}function
|
|
286
|
-
export {
|
|
371
|
+
`}function re(e=!0){return`export { ColorPaletteBlock } from "./ColorPalette";
|
|
372
|
+
export type { ColorPaletteBlockProps } from "./ColorPalette";
|
|
373
|
+
${e?`export { IconGalleryBlock } from "./IconGallery";
|
|
374
|
+
`:``}
|
|
287
375
|
export { TokenTableBlock } from "./TokenTable";
|
|
288
376
|
export type { TokenTableBlockProps, TokenTableRow } from "./TokenTable";
|
|
289
377
|
export { TypesetBlock } from "./Typeset";
|
|
290
|
-
|
|
291
|
-
`)}
|
|
378
|
+
export type { TypesetBlockProps } from "./Typeset";
|
|
379
|
+
`}const P=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 F(e){return N(e)?e.base===`light`||e.base===`dark`:!1}function I(e){return N(e)?F(e)?!0:Object.keys(e).some(e=>P.has(e)):!1}function L(e){if(!N(e)||I(e))return!1;let t=Object.values(e);return t.length>0&&t.every(I)}function R(e,t,n){return t.base===`light`||t.base===`dark`?t.base:`${e} ${n??``}`.toLowerCase().includes(`light`)?`light`:`dark`}function z(e){return/^[a-z_$][\w$]*$/i.test(e)?e:d(e)}function B(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 V(e){return N(e)&&`$value`in e&&!(`colorSpace`in e)&&!(`hex`in e)?e.$value:e}function H(e,t){let n=V(e),r=new Set;for(let e=0;e<8;e++){let e=y(n);if(!e||r.has(e))break;r.add(e);let i=t.get(e);if(!i)break;n=i.value}return n}function U(e){return e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:(0,n.formatTokenValue)(e)}function W(e,t){let r=(0,n.resolveTokenSets)(e),i=r.find(e=>e.id===t)??(r.length===1?r[0]:void 0),a=i?B(r,i):e,o=new Map;for(let e of l(a))(!o.get(e.path)||e.theme===t)&&o.set(e.path,e);return o}function G(e,t){let n={...e};for(let[r,i]of Object.entries(e))r!==`base`&&i!==void 0&&(n[r]=U(H(i,t)));return n}function K(e,t,n,r,i){let a=G(t,W(i.tokens,e));return q(R(e,a,i.theme),a,n,r)}function q(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 J(e,t=``){return`create({\n${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>`${t} ${e}: ${d(n)}`).join(`,
|
|
380
|
+
`)}\n${t}})`}function Y(e){return`import { create } from "storybook/theming";
|
|
292
381
|
|
|
293
382
|
/**
|
|
294
383
|
* Storybook UI theme generated by \`@razorwind/storybook\`.
|
|
295
384
|
*
|
|
296
385
|
* @see https://storybook.js.org/docs/configure/user-interface/theming
|
|
297
386
|
*/
|
|
298
|
-
export default ${
|
|
299
|
-
`}function
|
|
387
|
+
export default ${J(e)};
|
|
388
|
+
`}function X(e){return`import { create } from "storybook/theming";
|
|
300
389
|
|
|
301
390
|
/**
|
|
302
391
|
* Storybook UI themes generated by \`@razorwind/storybook\`.
|
|
@@ -304,7 +393,7 @@ export default ${H(e)};
|
|
|
304
393
|
* @see https://storybook.js.org/docs/configure/user-interface/theming
|
|
305
394
|
*/
|
|
306
395
|
export default {
|
|
307
|
-
${Object.entries(e).map(([e,t])=>` ${
|
|
396
|
+
${Object.entries(e).map(([e,t])=>` ${z(e)}: ${J(t,` `)}`).join(`,
|
|
308
397
|
`)}
|
|
309
398
|
};
|
|
310
|
-
`}function
|
|
399
|
+
`}function Z(e){if(F(e))return Y(e);let t=Object.entries(e);if(t.length!==1)return X(e);let[,n]=t[0]??[];return n?Y(n):X(e)}function Q(e,t,r,i){let a=(e,n)=>K(e,n,r,t.fonts,t);if(L(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(B(o,t));if(L(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}I(n)&&(e[t.id]=a(t.id,n))}return e}if(I(e)){let n=s[0]&&s[0].id!=="default"?s[0].id:t.theme??`default`;return{[n]:a(n,e)}}return{}}const ie=e=>(t,i,a)=>(0,n.createDocument)((0,r.joinPaths)(e,t),i,{name:`razorwind-storybook`},!1,a);function $(e,t={}){let i=t.outputPath??`storybook/tokens`,a=(0,n.resolveSchemaIdentity)(e),o=t.titlePrefix??a.title??`Design Tokens`,s={...t,titlePrefix:o},c=l(e.tokens,t),u=C(e.tokens,t),d=c.some(e=>e.type===`color`),p=e.fonts&&Object.keys(e.fonts).length>0||c.some(h),m=g(c,[`size`]),_=g(c,[`space`,`spacing`]),v=!t.skipIcons&&N(e.icons)&&Object.keys(e.icons).length>0,y=ie(i),b={[(0,r.joinPaths)(i,`blocks/ColorPalette.tsx`)]:y(`blocks/ColorPalette.tsx`,E(u,s),`tsx`),[(0,r.joinPaths)(i,`blocks/Typeset.tsx`)]:y(`blocks/Typeset.tsx`,D(u,{...s,fonts:e.fonts}),`tsx`),[(0,r.joinPaths)(i,`blocks/TokenTable.tsx`)]:y(`blocks/TokenTable.tsx`,O(u),`tsx`),[(0,r.joinPaths)(i,`blocks/index.ts`)]:y(`blocks/index.ts`,re(v),`typescript`),[(0,r.joinPaths)(i,`Tokens.mdx`)]:y(`Tokens.mdx`,k({titlePrefix:o,hasColors:d,hasTypography:p,hasSizes:m,hasSpaces:_}),`mdx`)};v&&(b[(0,r.joinPaths)(i,`blocks/IconGallery.tsx`)]=y(`blocks/IconGallery.tsx`,te(e.icons),`tsx`)),S(u)&&(b[(0,r.joinPaths)(i,`blocks/ThemeVariant.ts`)]=y(`blocks/ThemeVariant.ts`,ee(),`typescript`)),d&&(b[(0,r.joinPaths)(i,`Colors.mdx`)]=y(`Colors.mdx`,A(s),`mdx`)),p&&(b[(0,r.joinPaths)(i,`Typography.mdx`)]=y(`Typography.mdx`,j(s),`mdx`)),v&&(b[(0,r.joinPaths)(i,`Icons.mdx`)]=y(`Icons.mdx`,ne(s),`mdx`)),b[(0,r.joinPaths)(i,`tokens.json`)]=y(`tokens.json`,`${JSON.stringify(c,null,2)}\n`,`json`);let x;if(t.mapTheme){let n=Q(t.mapTheme(e.tokens),e,a,t.mapTheme);Object.keys(n).length>0&&(x=Object.keys(n),b[(0,r.joinPaths)(i,`theme.ts`)]=y(`theme.ts`,Z(n),`typescript`))}let w=`INSTALL.md`;return b[(0,r.joinPaths)(i,w)]=y(w,t.installGuide??f({outputPath:i,titlePrefix:o,themeFiles:x?[`theme.ts`]:void 0,themeNames:x,tokenThemeNames:Object.keys(u)}),`markdown`),b}var ae=(0,e.definePlugin)(e=>({name:`storybook`,themeGeneration:`combined`,generate:async t=>$(t,e??{})}));exports.applyBrandDefaults=q,exports.default=ae,exports.flattenTokens=l,Object.defineProperty(exports,"formatTokenValue",{enumerable:!0,get:function(){return n.formatTokenValue}}),exports.generateTokenDocs=$,exports.normalizeThemes=Q,exports.renderInstallMd=f,exports.renderThemeFile=Z,exports.resolveTokenSets=n.resolveTokenSets,Object.defineProperty(exports,"toCssVar",{enumerable:!0,get:function(){return n.toCssVar}});
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.cts.map
CHANGED
|
@@ -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":";;;;;;;;;UAwBiB;;EAEf;;EAEA,OAAO;;EAEP;;EAEA;;EAEA;;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;;;;;;;;;;;;;;EAeA,WAAW;;;;;;EAOX;;;;;EAMA;;;;;;;iBC3Dc,cACd,QAAQ,WAAS,eAAe,WAChC,UAAS,KAAK,2DACb;;;;;;;;iBC3Fa,gBAAgB;EAC9B;EACA;EACA;EACA;;;;;;;
|
|
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;;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;;;;;;;;;;;;;;EAeA,WAAW;;;;;;EAOX;;;;;EAMA;;;;;;;iBC3Dc,cACd,QAAQ,WAAS,eAAe,WAChC,UAAS,KAAK,2DACb;;;;;;;;iBC3Fa,gBAAgB;EAC9B;EACA;EACA;EACA;EACA;;;;;;;iBCi7Bc,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
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
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,isObject as l,isSharedThemeId as u,isTokenLeaf as d,mergeTokenTrees as f,resolveSchemaIdentity as ee,resolveTokenSets as p,toCssVar as m,toCssVar as h}from"@razorwind/core/utils";import{joinPaths as
|
|
2
|
-
`,`\\n`).replaceAll(`\r`,`\\r`)}function
|
|
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,isObject as l,isSharedThemeId as u,isTokenLeaf as d,mergeTokenTrees as f,resolveSchemaIdentity as ee,resolveTokenSets as p,toCssVar as m,toCssVar as h,toThemeCssVar as g}from"@razorwind/core/utils";import{joinPaths as _}from"@stryke/path/join";function v(e){return e===!0||e===`true`||e===1}function y(e,t){return e?`${e}:${t}`:t}function te(e){let t=e.theme??e.$theme;return typeof t==`string`&&t.length>0?t:void 0}function b(e,t){return e===`palette`||e===`$palette`?typeof t==`boolean`||typeof t==`number`||typeof t==`string`:(e===`theme`||e===`$theme`)&&typeof t==`string`}function x(e){let t=new Map;function n(e,r,i,a,o){if(!l(e))return;let s=a||v(e.palette)||v(e.$palette),c=te(e)??o;if(d(e)){(s||c)&&t.set(y(i,r.join(`.`)),{...s&&{palette:!0},...c&&{childTheme:c}});return}for(let[t,a]of Object.entries(e))t.startsWith(`$`)&&t!==`$palette`&&t!==`$theme`||b(t,a)||n(a,[...r,t],i,s,c)}for(let t of p(e)){let e=t.id==="default"?void 0:t.id;n(t.tokens,[],e,!1,void 0)}return t}function S(e,t={}){let n=t.cssVarPrefix??`rw`,r=x(e);return s(e,{includeTypes:t.includeTypes,shouldIncludeToken:e=>e.skipDocs!==!0,enrichToken:e=>{let t=r.get(y(e.theme,e.path));return{...e,cssVar:h(e.path,n),...e.type===`color`&&t}}})}function C(e){return e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`
|
|
2
|
+
`,`\\n`).replaceAll(`\r`,`\\r`)}function w(e){return typeof e==`string`?`"${C(e)}"`:typeof e==`number`||typeof e==`boolean`?String(e):e==null?`undefined`:JSON.stringify(e)}function T(e){let t=e.titlePrefix??`Design Tokens`,n=e.themeFiles?.[0],r=e.themeNames??[],i=e.tokenThemeNames??[],a=i.length>1?`
|
|
3
|
+
## Token-doc variants
|
|
4
|
+
|
|
5
|
+
Generated token blocks follow Storybook's \`theme\` global when it matches one
|
|
6
|
+
of these token-set names: ${i.map(e=>`\`${e}\``).join(`, `)}.
|
|
7
|
+
Pass \`theme\` directly to a block to override that selection.
|
|
8
|
+
`:``,o=n?r.length>1?`
|
|
3
9
|
## Storybook UI theme
|
|
4
10
|
|
|
5
11
|
Generated theme module:
|
|
@@ -40,7 +46,7 @@ Generated by \`@razorwind/storybook\`.
|
|
|
40
46
|
- \`${e.outputPath}/Tokens.mdx\` — token overview (${t})
|
|
41
47
|
- \`${e.outputPath}/blocks/\` — React doc blocks (ColorPalette, Typeset, …)
|
|
42
48
|
- \`${e.outputPath}/tokens.json\` — flattened token manifest
|
|
43
|
-
${
|
|
49
|
+
${o}${a}
|
|
44
50
|
## Setup
|
|
45
51
|
|
|
46
52
|
1. Add the generated MDX pages to Storybook (paths depend on your \`stories\` config):
|
|
@@ -65,54 +71,109 @@ import { ColorPaletteBlock } from "./blocks";
|
|
|
65
71
|
## Regenerate
|
|
66
72
|
|
|
67
73
|
Re-run Razorwind generate when tokens change to refresh docs under \`${e.outputPath}/\`.
|
|
68
|
-
`}
|
|
74
|
+
`}const E=new Set([`fontFamily`,`fontWeight`,`typography`]),ne=/font|typography|type|text|line[-_.]?height|letter[-_.]?spacing/i;function D(e){return E.has(e.type??``)?!0:(e.type===`dimension`||e.type===`number`)&&ne.test(e.path)}function O(e,t){return e.some(e=>t.some(t=>e.path===t||e.path.startsWith(`${t}.`)))}const re=/^\{([^{}]+)\}$/,ie=/^var\((--[^),\s]+)(?:\s*,[^)]*)?\)$/;function k(e){if(typeof e==`string`)return re.exec(e.trim())?.[1]?.trim()}function A(e){if(typeof e==`string`)return ie.exec(e.trim())?.[1]}function j(e){let t=new Map(e.map(e=>[e.path,e])),n=new Map(e.map(e=>[g(e.path),e])),r=e=>{let r=e,i=new Set;for(let a=0;a<8;a++){if(i.has(r.path))return e.cssValue;i.add(r.path);let a=t.get(k(r.value)??``)??n.get(A(r.value)??A(r.cssValue)??``);if(!a||a.path===r.path)return r.cssValue;r=a}return e.cssValue};return e.map(e=>e.type===`color`?{...e,cssValue:r(e)}:e)}function M(e){return Object.keys(e).length>1}function ae(){return`import { useGlobals, useMemo } from "storybook/preview-api";
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Select a generated token variant. By default this follows Storybook's
|
|
78
|
+
* \`theme\` global; callers may pass \`theme\` to override it.
|
|
79
|
+
*/
|
|
80
|
+
export function useThemeVariant<T extends Record<string, unknown>>(
|
|
81
|
+
variants: T,
|
|
82
|
+
fallback: keyof T & string,
|
|
83
|
+
theme?: string
|
|
84
|
+
): keyof T & string {
|
|
85
|
+
const [globals] = useGlobals();
|
|
86
|
+
|
|
87
|
+
return useMemo(() => {
|
|
88
|
+
const candidate = theme ?? globals.theme;
|
|
89
|
+
|
|
90
|
+
return typeof candidate === "string" && candidate in variants
|
|
91
|
+
? (candidate as keyof T & string)
|
|
92
|
+
: fallback;
|
|
93
|
+
}, [fallback, globals.theme, theme, variants]);
|
|
94
|
+
}
|
|
95
|
+
`}function oe(e,t){let n=p(e),r=n.filter(e=>!u(e.id));return r.length<=1?{default:j(S(e,t))}:Object.fromEntries(r.map(e=>[e.id,j(S(K(n,e),t))]))}function se(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 ce(e,t){return e===t?e.split(`.`).at(-1)??e:e.startsWith(`${t}.`)?e.slice(t.length+1):e.split(`.`).at(-1)??e}function le(e,t={}){let n=t.colorGroupBy??2,r=Object.entries(e),i=r[0]?.[0]??`default`,a=M(e),o=(e,t=` `)=>[...se(e,n).entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,n])=>{let r=n.map(n=>`${t} ${w(ce(n.path,e))}: ${w(n.cssValue)}`).join(`,
|
|
69
96
|
`),i=n.find(e=>e.description)?.description??`${n.length} token${n.length===1?``:`s`}`;return`${t}<ColorItem
|
|
70
|
-
title={${
|
|
71
|
-
subtitle={${
|
|
97
|
+
title={${w(e)}}
|
|
98
|
+
subtitle={${w(i)}}
|
|
72
99
|
colors={{
|
|
73
100
|
${r}
|
|
74
101
|
}}
|
|
75
102
|
/>`}).join(`
|
|
76
|
-
`),
|
|
103
|
+
`),s=e=>{let t=e.filter(e=>e.type===`color`),n=t.filter(e=>e.palette),r=t.filter(e=>!e.palette&&e.childTheme),i=t.filter(e=>!e.palette&&!e.childTheme),a=n.length>0||r.length>0,s=o(t),c=[[`Color palettes`,n],[`Semantic colors`,r],[`Colors`,i]].filter(e=>!!e[1]?.length).map(([e,t])=>` <section>
|
|
77
104
|
<h2>${e}</h2>
|
|
78
105
|
<ColorPalette>
|
|
79
|
-
${
|
|
106
|
+
${o(t,` `)}
|
|
80
107
|
</ColorPalette>
|
|
81
108
|
</section>`).join(`
|
|
109
|
+
`);return a?`<>\n${c}\n </>`:`<ColorPalette>\n${s||` {/* No color tokens */}`}\n </ColorPalette>`},c=r.map(([e,t])=>` ${w(e)}: (\n ${s(t)}\n )`).join(`,
|
|
82
110
|
`);return`import { ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";
|
|
111
|
+
${a?`import { useThemeVariant } from "./ThemeVariant";
|
|
112
|
+
`:``}
|
|
83
113
|
|
|
84
114
|
/**
|
|
85
115
|
* Color tokens rendered with Storybook's ColorPalette doc block.
|
|
86
116
|
*
|
|
87
117
|
* @see https://storybook.js.org/docs/api/doc-blocks/doc-block-colorpalette
|
|
88
118
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
119
|
+
const COLOR_VARIANTS = {
|
|
120
|
+
${c}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export interface ColorPaletteBlockProps {
|
|
124
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
125
|
+
theme?: string;
|
|
97
126
|
}
|
|
98
|
-
|
|
127
|
+
|
|
128
|
+
export function ColorPaletteBlock({ theme }: ColorPaletteBlockProps = {}) {
|
|
129
|
+
const activeTheme = ${a?`useThemeVariant(COLOR_VARIANTS, ${w(i)}, theme)`:w(i)};
|
|
130
|
+
|
|
131
|
+
return COLOR_VARIANTS[activeTheme];
|
|
132
|
+
}
|
|
133
|
+
`}function ue(e,t={}){let a=t.sampleText??`The quick brown fox jumps over the lazy dog`,o=M(e),s=Object.entries(e),c=s[0]?.[0]??`default`,l=e=>{let 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=>w(e)).join(`, `)}]`:`[12, 14, 16, 20, 24, 32]`;return`<Typeset
|
|
134
|
+
fontFamily={${w(l)}}
|
|
135
|
+
fontSizes={${f}}
|
|
136
|
+
fontWeight={${w(d)}}
|
|
137
|
+
sampleText={${w(a)}}
|
|
138
|
+
/>`},u=s.map(([e,t])=>` ${w(e)}: (${l(t)})`).join(`,
|
|
139
|
+
`);return`import { Typeset } from "@storybook/addon-docs/blocks";
|
|
140
|
+
${o?`import { useThemeVariant } from "./ThemeVariant";
|
|
141
|
+
`:``}
|
|
99
142
|
|
|
100
143
|
/**
|
|
101
144
|
* Typography tokens rendered with Storybook's Typeset doc block.
|
|
102
145
|
*
|
|
103
146
|
* @see https://storybook.js.org/docs/api/doc-blocks/doc-block-typeset
|
|
104
147
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/>
|
|
113
|
-
);
|
|
148
|
+
const TYPESET_VARIANTS = {
|
|
149
|
+
${u}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export interface TypesetBlockProps {
|
|
153
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
154
|
+
theme?: string;
|
|
114
155
|
}
|
|
115
|
-
|
|
156
|
+
|
|
157
|
+
export function TypesetBlock({ theme }: TypesetBlockProps = {}) {
|
|
158
|
+
const activeTheme = ${o?`useThemeVariant(TYPESET_VARIANTS, ${w(c)}, theme)`:w(c)};
|
|
159
|
+
|
|
160
|
+
return TYPESET_VARIANTS[activeTheme];
|
|
161
|
+
}
|
|
162
|
+
`}function N(e){let t=M(e),n=Object.entries(e),r=n[0]?.[0]??`default`,i=e=>e.map(e=>{let t=e.theme?w(e.theme):`undefined`;return` {
|
|
163
|
+
path: ${w(e.path)},
|
|
164
|
+
type: ${e.type?w(e.type):`undefined`},
|
|
165
|
+
value: ${w(e.cssValue)},
|
|
166
|
+
cssVar: ${w(e.cssVar)},
|
|
167
|
+
description: ${e.description?w(e.description):`undefined`},
|
|
168
|
+
theme: ${t},
|
|
169
|
+
typography: ${D(e)}
|
|
170
|
+
}`}).join(`,
|
|
171
|
+
`),a=n.map(([e,t])=>` ${w(e)}: [
|
|
172
|
+
${i(t)}
|
|
173
|
+
]`).join(`,
|
|
174
|
+
`);return`import type { CSSProperties, ReactElement } from "react";
|
|
175
|
+
${t?`import { useThemeVariant } from "./ThemeVariant";
|
|
176
|
+
`:``}
|
|
116
177
|
|
|
117
178
|
export interface TokenTableRow {
|
|
118
179
|
path: string;
|
|
@@ -121,19 +182,12 @@ export interface TokenTableRow {
|
|
|
121
182
|
cssVar: string;
|
|
122
183
|
description?: string;
|
|
123
184
|
theme?: string;
|
|
185
|
+
typography: boolean;
|
|
124
186
|
}
|
|
125
187
|
|
|
126
|
-
const
|
|
127
|
-
${
|
|
128
|
-
|
|
129
|
-
type: ${e.type?C(e.type):`undefined`},
|
|
130
|
-
value: ${C(e.cssValue)},
|
|
131
|
-
cssVar: ${C(e.cssVar)},
|
|
132
|
-
description: ${e.description?C(e.description):`undefined`},
|
|
133
|
-
theme: ${t}
|
|
134
|
-
}`}).join(`,
|
|
135
|
-
`)||``}
|
|
136
|
-
];
|
|
188
|
+
const TOKEN_VARIANTS: Record<string, TokenTableRow[]> = {
|
|
189
|
+
${a}
|
|
190
|
+
};
|
|
137
191
|
|
|
138
192
|
const tableStyle: CSSProperties = {
|
|
139
193
|
width: "100%",
|
|
@@ -160,10 +214,14 @@ const swatchStyle = (value: string): CSSProperties => ({
|
|
|
160
214
|
});
|
|
161
215
|
|
|
162
216
|
export interface TokenTableBlockProps {
|
|
163
|
-
/** Optional path prefix filter (e.g. \`color\`). */
|
|
164
|
-
filter?: string;
|
|
217
|
+
/** Optional path prefix filter or filters (e.g. \`color\`). */
|
|
218
|
+
filter?: string | string[];
|
|
165
219
|
/** Optional DTCG \`$type\` filter. */
|
|
166
220
|
type?: string;
|
|
221
|
+
/** Restrict rows to tokens used to define typography. */
|
|
222
|
+
typography?: boolean;
|
|
223
|
+
/** Generated token-set name. Defaults to Storybook's \`theme\` global. */
|
|
224
|
+
theme?: string;
|
|
167
225
|
}
|
|
168
226
|
|
|
169
227
|
/**
|
|
@@ -171,15 +229,27 @@ export interface TokenTableBlockProps {
|
|
|
171
229
|
*/
|
|
172
230
|
export function TokenTableBlock({
|
|
173
231
|
filter,
|
|
174
|
-
type
|
|
232
|
+
type,
|
|
233
|
+
typography,
|
|
234
|
+
theme
|
|
175
235
|
}: TokenTableBlockProps = {}): ReactElement {
|
|
176
|
-
const
|
|
177
|
-
|
|
236
|
+
const activeTheme = ${t?`useThemeVariant(TOKEN_VARIANTS, ${w(r)}, theme)`:w(r)};
|
|
237
|
+
const rows = TOKEN_VARIANTS[activeTheme].filter(token => {
|
|
238
|
+
const filters = typeof filter === "string" ? [filter] : filter;
|
|
239
|
+
if (
|
|
240
|
+
filters &&
|
|
241
|
+
!filters.some(prefix =>
|
|
242
|
+
token.path === prefix || token.path.startsWith(\`\${prefix}.\`)
|
|
243
|
+
)
|
|
244
|
+
) {
|
|
178
245
|
return false;
|
|
179
246
|
}
|
|
180
247
|
if (type && token.type !== type) {
|
|
181
248
|
return false;
|
|
182
249
|
}
|
|
250
|
+
if (typography && !token.typography) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
183
253
|
return true;
|
|
184
254
|
});
|
|
185
255
|
|
|
@@ -216,7 +286,7 @@ export function TokenTableBlock({
|
|
|
216
286
|
</table>
|
|
217
287
|
);
|
|
218
288
|
}
|
|
219
|
-
`}function
|
|
289
|
+
`}function P(e){let t=e.titlePrefix??`Design Tokens`,n=e.hasColors?`
|
|
220
290
|
## Colors
|
|
221
291
|
|
|
222
292
|
<ColorPaletteBlock />
|
|
@@ -224,37 +294,53 @@ export function TokenTableBlock({
|
|
|
224
294
|
## Typography
|
|
225
295
|
|
|
226
296
|
<TypesetBlock />
|
|
297
|
+
`:``,i=e.hasSizes?`
|
|
298
|
+
## Size
|
|
299
|
+
|
|
300
|
+
<TokenTableBlock filter="size" />
|
|
301
|
+
`:``,a=e.hasSpaces?`
|
|
302
|
+
## Space
|
|
303
|
+
|
|
304
|
+
<TokenTableBlock filter={[
|
|
305
|
+
"space",
|
|
306
|
+
"spacing"
|
|
307
|
+
]} />
|
|
227
308
|
`:``;return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
228
309
|
import { ColorPaletteBlock } from "./blocks/ColorPalette";
|
|
229
310
|
import { TokenTableBlock } from "./blocks/TokenTable";
|
|
230
311
|
import { TypesetBlock } from "./blocks/Typeset";
|
|
231
312
|
|
|
232
|
-
<Meta title="${
|
|
313
|
+
<Meta title="${C(t)}/Overview" />
|
|
233
314
|
|
|
234
315
|
# ${t}
|
|
235
316
|
|
|
236
317
|
Design tokens generated by \`@razorwind/storybook\` for Storybook MDX docs.
|
|
237
|
-
${n}${r}
|
|
318
|
+
${n}${r}${i}${a}
|
|
238
319
|
## All tokens
|
|
239
320
|
|
|
240
321
|
<TokenTableBlock />
|
|
241
|
-
`}function
|
|
322
|
+
`}function F(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
242
323
|
import { ColorPaletteBlock } from "./blocks/ColorPalette";
|
|
243
324
|
|
|
244
|
-
<Meta title="${
|
|
325
|
+
<Meta title="${C(e.titlePrefix??`Design Tokens`)}/Colors" />
|
|
245
326
|
|
|
246
327
|
# Colors
|
|
247
328
|
|
|
248
329
|
<ColorPaletteBlock />
|
|
249
|
-
`}function
|
|
330
|
+
`}function I(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
250
331
|
import { TypesetBlock } from "./blocks/Typeset";
|
|
332
|
+
import { TokenTableBlock } from "./blocks/TokenTable";
|
|
251
333
|
|
|
252
|
-
<Meta title="${
|
|
334
|
+
<Meta title="${C(e.titlePrefix??`Design Tokens`)}/Typography" />
|
|
253
335
|
|
|
254
336
|
# Typography
|
|
255
337
|
|
|
256
338
|
<TypesetBlock />
|
|
257
|
-
|
|
339
|
+
|
|
340
|
+
## Typography tokens
|
|
341
|
+
|
|
342
|
+
<TokenTableBlock typography />
|
|
343
|
+
`}function L(e,t){let n=e[t];return typeof n==`string`?n:void 0}function R(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function z(e){return`import { IconGallery, IconItem } from "@storybook/addon-docs/blocks";
|
|
258
344
|
|
|
259
345
|
/**
|
|
260
346
|
* Icons rendered with Storybook's IconGallery doc block.
|
|
@@ -264,30 +350,33 @@ import { TypesetBlock } from "./blocks/Typeset";
|
|
|
264
350
|
export function IconGalleryBlock() {
|
|
265
351
|
return (
|
|
266
352
|
<IconGallery>
|
|
267
|
-
${(
|
|
353
|
+
${(R(e)?Object.values(e).filter(R).toSorted((e,t)=>(L(e,`name`)??``).localeCompare(L(t,`name`)??``)):[]).map(e=>{let t=L(e,`name`)??`unknown`,n=(Array.isArray(e.files)?e.files:[]).find(e=>R(e)&&L(e,`type`)===`svg`&&typeof e.content==`string`),r=R(n)&&typeof n.content==`string`?`<span
|
|
268
354
|
style={{ display: "inline-flex", width: 24, height: 24 }}
|
|
269
|
-
dangerouslySetInnerHTML={{ __html: ${
|
|
270
|
-
/>`:`<code>${
|
|
355
|
+
dangerouslySetInnerHTML={{ __html: ${w(n.content)} }}
|
|
356
|
+
/>`:`<code>${C(t)}</code>`;return` <IconItem name={${w(t)}}>
|
|
271
357
|
${r}
|
|
272
358
|
</IconItem>`}).join(`
|
|
273
359
|
`)||` {/* No icons */}`}
|
|
274
360
|
</IconGallery>
|
|
275
361
|
);
|
|
276
362
|
}
|
|
277
|
-
`}function
|
|
363
|
+
`}function B(e={}){return`import { Meta } from "@storybook/addon-docs/blocks";
|
|
278
364
|
import { IconGalleryBlock } from "./blocks/IconGallery";
|
|
279
365
|
|
|
280
|
-
<Meta title="${
|
|
366
|
+
<Meta title="${C(e.titlePrefix??`Design Tokens`)}/Icons" />
|
|
281
367
|
|
|
282
368
|
# Icons
|
|
283
369
|
|
|
284
370
|
<IconGalleryBlock />
|
|
285
|
-
`}function
|
|
286
|
-
export {
|
|
371
|
+
`}function V(e=!0){return`export { ColorPaletteBlock } from "./ColorPalette";
|
|
372
|
+
export type { ColorPaletteBlockProps } from "./ColorPalette";
|
|
373
|
+
${e?`export { IconGalleryBlock } from "./IconGallery";
|
|
374
|
+
`:``}
|
|
287
375
|
export { TokenTableBlock } from "./TokenTable";
|
|
288
376
|
export type { TokenTableBlockProps, TokenTableRow } from "./TokenTable";
|
|
289
377
|
export { TypesetBlock } from "./Typeset";
|
|
290
|
-
|
|
378
|
+
export type { TypesetBlockProps } from "./Typeset";
|
|
379
|
+
`}const H=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 U(e){return R(e)?e.base===`light`||e.base===`dark`:!1}function W(e){return R(e)?U(e)?!0:Object.keys(e).some(e=>H.has(e)):!1}function G(e){if(!R(e)||W(e))return!1;let t=Object.values(e);return t.length>0&&t.every(W)}function de(e,t,n){return t.base===`light`||t.base===`dark`?t.base:`${e} ${n??``}`.toLowerCase().includes(`light`)?`light`:`dark`}function fe(e){return/^[a-z_$][\w$]*$/i.test(e)?e:w(e)}function K(e,t){let n=e.find(e=>e.id===a);return!n||u(t.id)?t.tokens:f(t.tokens,n.tokens)}function pe(e){return R(e)&&`$value`in e&&!(`colorSpace`in e)&&!(`hex`in e)?e.$value:e}function me(e,t){let n=pe(e),r=new Set;for(let e=0;e<8;e++){let e=k(n);if(!e||r.has(e))break;r.add(e);let i=t.get(e);if(!i)break;n=i.value}return n}function he(e){return e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:c(e)}function ge(e,t){let n=p(e),r=n.find(e=>e.id===t)??(n.length===1?n[0]:void 0),i=r?K(n,r):e,a=new Map;for(let e of S(i))(!a.get(e.path)||e.theme===t)&&a.set(e.path,e);return a}function _e(e,t){let n={...e};for(let[r,i]of Object.entries(e))r!==`base`&&i!==void 0&&(n[r]=he(me(i,t)));return n}function ve(e,t,n,r,i){let a=_e(t,ge(i.tokens,e));return q(de(e,a,i.theme),a,n,r)}function q(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 J(e,t=``){return`create({\n${Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>`${t} ${e}: ${w(n)}`).join(`,
|
|
291
380
|
`)}\n${t}})`}function Y(e){return`import { create } from "storybook/theming";
|
|
292
381
|
|
|
293
382
|
/**
|
|
@@ -304,8 +393,8 @@ export default ${J(e)};
|
|
|
304
393
|
* @see https://storybook.js.org/docs/configure/user-interface/theming
|
|
305
394
|
*/
|
|
306
395
|
export default {
|
|
307
|
-
${Object.entries(e).map(([e,t])=>` ${
|
|
396
|
+
${Object.entries(e).map(([e,t])=>` ${fe(e)}: ${J(t,` `)}`).join(`,
|
|
308
397
|
`)}
|
|
309
398
|
};
|
|
310
|
-
`}function Z(e){if(
|
|
399
|
+
`}function Z(e){if(U(e))return Y(e);let t=Object.entries(e);if(t.length!==1)return X(e);let[,n]=t[0]??[];return n?Y(n):X(e)}function Q(e,t,n,r){let i=(e,r)=>ve(e,r,n,t.fonts,t);if(G(e))return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,i(e,t)]));let a=p(t.tokens),o=a.filter(e=>!u(e.id));if(o.length>1){let e={};for(let t of o){let n=r(K(a,t));if(G(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}W(n)&&(e[t.id]=i(t.id,n))}return e}if(W(e)){let n=o[0]&&o[0].id!=="default"?o[0].id:t.theme??`default`;return{[n]:i(n,e)}}return{}}const ye=e=>(t,n,r)=>o(_(e,t),n,{name:`razorwind-storybook`},!1,r);function $(e,t={}){let n=t.outputPath??`storybook/tokens`,r=ee(e),i=t.titlePrefix??r.title??`Design Tokens`,a={...t,titlePrefix:i},o=S(e.tokens,t),s=oe(e.tokens,t),c=o.some(e=>e.type===`color`),l=e.fonts&&Object.keys(e.fonts).length>0||o.some(D),u=O(o,[`size`]),d=O(o,[`space`,`spacing`]),f=!t.skipIcons&&R(e.icons)&&Object.keys(e.icons).length>0,p=ye(n),m={[_(n,`blocks/ColorPalette.tsx`)]:p(`blocks/ColorPalette.tsx`,le(s,a),`tsx`),[_(n,`blocks/Typeset.tsx`)]:p(`blocks/Typeset.tsx`,ue(s,{...a,fonts:e.fonts}),`tsx`),[_(n,`blocks/TokenTable.tsx`)]:p(`blocks/TokenTable.tsx`,N(s),`tsx`),[_(n,`blocks/index.ts`)]:p(`blocks/index.ts`,V(f),`typescript`),[_(n,`Tokens.mdx`)]:p(`Tokens.mdx`,P({titlePrefix:i,hasColors:c,hasTypography:l,hasSizes:u,hasSpaces:d}),`mdx`)};f&&(m[_(n,`blocks/IconGallery.tsx`)]=p(`blocks/IconGallery.tsx`,z(e.icons),`tsx`)),M(s)&&(m[_(n,`blocks/ThemeVariant.ts`)]=p(`blocks/ThemeVariant.ts`,ae(),`typescript`)),c&&(m[_(n,`Colors.mdx`)]=p(`Colors.mdx`,F(a),`mdx`)),l&&(m[_(n,`Typography.mdx`)]=p(`Typography.mdx`,I(a),`mdx`)),f&&(m[_(n,`Icons.mdx`)]=p(`Icons.mdx`,B(a),`mdx`)),m[_(n,`tokens.json`)]=p(`tokens.json`,`${JSON.stringify(o,null,2)}\n`,`json`);let h;if(t.mapTheme){let i=Q(t.mapTheme(e.tokens),e,r,t.mapTheme);Object.keys(i).length>0&&(h=Object.keys(i),m[_(n,`theme.ts`)]=p(`theme.ts`,Z(i),`typescript`))}let g=`INSTALL.md`;return m[_(n,g)]=p(g,t.installGuide??T({outputPath:n,titlePrefix:i,themeFiles:h?[`theme.ts`]:void 0,themeNames:h,tokenThemeNames:Object.keys(s)}),`markdown`),m}var be=e(e=>({name:`storybook`,themeGeneration:`combined`,generate:async t=>$(t,e??{})}));export{q as applyBrandDefaults,be as default,S as flattenTokens,c as formatTokenValue,$ as generateTokenDocs,Q as normalizeThemes,T as renderInstallMd,Z as renderThemeFile,p as resolveTokenSets,m as toCssVar};
|
|
311
400
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@razorwind/storybook",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.62",
|
|
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.92",
|
|
87
87
|
"@power-plant/dtcg-schema": "^0.0.1",
|
|
88
|
-
"@razorwind/core": "^0.0.
|
|
88
|
+
"@razorwind/core": "^0.0.64",
|
|
89
89
|
"@stryke/path": "^0.29.41",
|
|
90
90
|
"@stryke/type-checks": "^0.6.47"
|
|
91
91
|
},
|
|
@@ -106,5 +106,5 @@
|
|
|
106
106
|
"typescript": "^6.0.3"
|
|
107
107
|
},
|
|
108
108
|
"publishConfig": { "access": "public" },
|
|
109
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "c84f0264563cf2de9e59fef95d25924ebebe6f80"
|
|
110
110
|
}
|