@unpunnyfuns/swatchbook-integrations 0.53.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css-in-js.mjs +1 -1
- package/dist/css-in-js.mjs.map +1 -1
- package/package.json +2 -2
package/dist/css-in-js.mjs
CHANGED
|
@@ -74,7 +74,7 @@ function renderTheme(project) {
|
|
|
74
74
|
function collectPaths(project) {
|
|
75
75
|
const all = /* @__PURE__ */ new Set();
|
|
76
76
|
for (const theme of project.permutations) {
|
|
77
|
-
const tokens = project.
|
|
77
|
+
const tokens = project.resolveAt(theme.input);
|
|
78
78
|
for (const path of Object.keys(tokens)) all.add(path);
|
|
79
79
|
}
|
|
80
80
|
return [...all].toSorted();
|
package/dist/css-in-js.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-in-js.mjs","names":[],"sources":["../src/css-in-js.ts"],"sourcesContent":["import type { Project, SwatchbookIntegration } from '@unpunnyfuns/swatchbook-core';\n\nexport interface CssInJsIntegrationOptions {\n /**\n * Virtual module ID the addon serves. Default:\n * `'virtual:swatchbook/theme'`. Consumers import this string from\n * their preview (or stories) to receive a typed accessor object whose\n * leaves are `var(--<cssVarPrefix>-*)` references.\n */\n virtualId?: string;\n}\n\n/**\n * Preview-only CSS-in-JS integration for swatchbook's Storybook addon.\n * Contributes a virtual JS module that exports a nested accessor\n * mirroring the project's token tree — every leaf is a `var(...)`\n * reference carrying the project's `cssVarPrefix`. Lets stories import\n * `{ theme }` the same way their production components do, but backed\n * by swatchbook's runtime-switchable cascade rather than a concrete\n * theme object. Not a replacement for the consumer's production\n * CSS-in-JS emit step.\n *\n * Swatchbook's toolbar still does the flipping via compound `data-*`\n * attributes; the accessor's values don't change across tuples because\n * the cascade resolves the var.\n *\n * ```ts\n * // .storybook/main.ts\n * import cssInJsIntegration from '@unpunnyfuns/swatchbook-integrations/css-in-js';\n *\n * export default defineMain({\n * addons: [\n * {\n * name: '@unpunnyfuns/swatchbook-addon',\n * options: {\n * configPath: '../swatchbook.config.ts',\n * integrations: [cssInJsIntegration()],\n * },\n * },\n * ],\n * });\n *\n * // Any story / component\n * import { theme, color, space } from 'virtual:swatchbook/theme';\n *\n * // styled-components / emotion\n * <ThemeProvider theme={theme}>...</ThemeProvider>\n *\n * // direct ref\n * const bg = color.surface.default; // -> \"var(--sb-color-surface-default)\"\n * ```\n *\n * The theme object is stable across tuples — consumers wire it into a\n * provider *once*; runtime switching happens entirely through CSS cascade\n * when swatchbook's toolbar toggles `data-<prefix>-<axis>` on `<html>`.\n * Consumers who need resolved-value permutations (MUI `createTheme`, Vuetify\n * factories) are not covered — that's a different emission story.\n */\nexport default function cssInJsIntegration(\n options: CssInJsIntegrationOptions = {},\n): SwatchbookIntegration {\n const virtualId = options.virtualId ?? 'virtual:swatchbook/theme';\n return {\n name: 'css-in-js',\n virtualModule: {\n virtualId,\n render: renderTheme,\n },\n };\n}\n\nfunction renderTheme(project: Project): string {\n const prefix = project.config.cssVarPrefix ?? '';\n const varPrefix = prefix ? `${prefix}-` : '';\n const paths = collectPaths(project);\n const tree = buildTree(paths, (path) => `var(--${varPrefix}${path.replaceAll('.', '-')})`);\n\n const groupNames = Object.keys(tree).toSorted();\n const groupExports = groupNames.map(\n (name) => `export const ${safeIdent(name)} = ${renderNode(tree[name]!, 1)};`,\n );\n const aggregate = `export const theme = { ${groupNames.map(safeIdent).join(', ')} };`;\n\n return [\n '/* Synthesized by @unpunnyfuns/swatchbook-integrations/css-in-js for preview.',\n ' * Served via `virtual:swatchbook/theme` — rebuilt on token changes. */',\n '',\n ...groupExports,\n '',\n aggregate,\n '',\n ].join('\\n');\n}\n\nfunction collectPaths(project: Project): string[] {\n const all = new Set<string>();\n for (const theme of project.permutations) {\n const tokens = project.
|
|
1
|
+
{"version":3,"file":"css-in-js.mjs","names":[],"sources":["../src/css-in-js.ts"],"sourcesContent":["import type { Project, SwatchbookIntegration } from '@unpunnyfuns/swatchbook-core';\n\nexport interface CssInJsIntegrationOptions {\n /**\n * Virtual module ID the addon serves. Default:\n * `'virtual:swatchbook/theme'`. Consumers import this string from\n * their preview (or stories) to receive a typed accessor object whose\n * leaves are `var(--<cssVarPrefix>-*)` references.\n */\n virtualId?: string;\n}\n\n/**\n * Preview-only CSS-in-JS integration for swatchbook's Storybook addon.\n * Contributes a virtual JS module that exports a nested accessor\n * mirroring the project's token tree — every leaf is a `var(...)`\n * reference carrying the project's `cssVarPrefix`. Lets stories import\n * `{ theme }` the same way their production components do, but backed\n * by swatchbook's runtime-switchable cascade rather than a concrete\n * theme object. Not a replacement for the consumer's production\n * CSS-in-JS emit step.\n *\n * Swatchbook's toolbar still does the flipping via compound `data-*`\n * attributes; the accessor's values don't change across tuples because\n * the cascade resolves the var.\n *\n * ```ts\n * // .storybook/main.ts\n * import cssInJsIntegration from '@unpunnyfuns/swatchbook-integrations/css-in-js';\n *\n * export default defineMain({\n * addons: [\n * {\n * name: '@unpunnyfuns/swatchbook-addon',\n * options: {\n * configPath: '../swatchbook.config.ts',\n * integrations: [cssInJsIntegration()],\n * },\n * },\n * ],\n * });\n *\n * // Any story / component\n * import { theme, color, space } from 'virtual:swatchbook/theme';\n *\n * // styled-components / emotion\n * <ThemeProvider theme={theme}>...</ThemeProvider>\n *\n * // direct ref\n * const bg = color.surface.default; // -> \"var(--sb-color-surface-default)\"\n * ```\n *\n * The theme object is stable across tuples — consumers wire it into a\n * provider *once*; runtime switching happens entirely through CSS cascade\n * when swatchbook's toolbar toggles `data-<prefix>-<axis>` on `<html>`.\n * Consumers who need resolved-value permutations (MUI `createTheme`, Vuetify\n * factories) are not covered — that's a different emission story.\n */\nexport default function cssInJsIntegration(\n options: CssInJsIntegrationOptions = {},\n): SwatchbookIntegration {\n const virtualId = options.virtualId ?? 'virtual:swatchbook/theme';\n return {\n name: 'css-in-js',\n virtualModule: {\n virtualId,\n render: renderTheme,\n },\n };\n}\n\nfunction renderTheme(project: Project): string {\n const prefix = project.config.cssVarPrefix ?? '';\n const varPrefix = prefix ? `${prefix}-` : '';\n const paths = collectPaths(project);\n const tree = buildTree(paths, (path) => `var(--${varPrefix}${path.replaceAll('.', '-')})`);\n\n const groupNames = Object.keys(tree).toSorted();\n const groupExports = groupNames.map(\n (name) => `export const ${safeIdent(name)} = ${renderNode(tree[name]!, 1)};`,\n );\n const aggregate = `export const theme = { ${groupNames.map(safeIdent).join(', ')} };`;\n\n return [\n '/* Synthesized by @unpunnyfuns/swatchbook-integrations/css-in-js for preview.',\n ' * Served via `virtual:swatchbook/theme` — rebuilt on token changes. */',\n '',\n ...groupExports,\n '',\n aggregate,\n '',\n ].join('\\n');\n}\n\nfunction collectPaths(project: Project): string[] {\n const all = new Set<string>();\n for (const theme of project.permutations) {\n const tokens = project.resolveAt(theme.input as Record<string, string>);\n for (const path of Object.keys(tokens)) all.add(path);\n }\n return [...all].toSorted();\n}\n\ntype TreeNode = { [key: string]: TreeNode | string };\n\n/**\n * Build a nested object tree from a sorted path list. Leaves hold the\n * emitted value from `leafFor(path)`. Leaf/branch collisions (a shorter\n * path emits a leaf while a longer path wants to nest under the same\n * key) are resolved by keeping the leaf — realistic DTCG trees don't\n * hit this, but the explicit behaviour beats silent UB.\n */\nfunction buildTree(sortedPaths: readonly string[], leafFor: (path: string) => string): TreeNode {\n const root: TreeNode = {};\n for (const path of sortedPaths) {\n const segments = path.split('.');\n let node = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i]!;\n const existing = node[seg];\n if (typeof existing === 'string') break;\n if (existing === undefined) {\n const next: TreeNode = {};\n node[seg] = next;\n node = next;\n } else {\n node = existing;\n }\n }\n const leafKey = segments.at(-1)!;\n if (node[leafKey] === undefined) node[leafKey] = leafFor(path);\n }\n return root;\n}\n\nfunction renderNode(node: TreeNode | string, depth: number): string {\n if (typeof node === 'string') return JSON.stringify(node);\n const indent = ' '.repeat(depth);\n const closing = ' '.repeat(depth - 1);\n const entries = Object.keys(node)\n .toSorted()\n .map((key) => `${indent}${safeKey(key)}: ${renderNode(node[key]!, depth + 1)}`);\n return `{\\n${entries.join(',\\n')},\\n${closing}}`;\n}\n\n/**\n * Bare identifier (or canonical non-leading-zero integer literal) if\n * safe; quoted string otherwise. Leading-zero numerics like `\"050\"`\n * stay quoted because bare `050` is an octal under strict mode.\n */\nfunction safeKey(key: string): string {\n if (/^[A-Za-z_$][\\w$]*$/.test(key)) return key;\n if (/^(0|[1-9]\\d*)$/.test(key)) return key;\n return JSON.stringify(key);\n}\n\n/** Top-level exports must be valid JS identifiers. */\nfunction safeIdent(key: string): string {\n return /^[A-Za-z_$][\\w$]*$/.test(key) ? key : `_${key.replaceAll(/[^\\w$]/g, '_')}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAwB,mBACtB,UAAqC,EAAE,EAChB;AAEvB,QAAO;EACL,MAAM;EACN,eAAe;GACb,WAJc,QAAQ,aAAa;GAKnC,QAAQ;GACT;EACF;;AAGH,SAAS,YAAY,SAA0B;CAC7C,MAAM,SAAS,QAAQ,OAAO,gBAAgB;CAC9C,MAAM,YAAY,SAAS,GAAG,OAAO,KAAK;CAE1C,MAAM,OAAO,UADC,aAAa,QAAQ,GACJ,SAAS,SAAS,YAAY,KAAK,WAAW,KAAK,IAAI,CAAC,GAAG;CAE1F,MAAM,aAAa,OAAO,KAAK,KAAK,CAAC,UAAU;CAC/C,MAAM,eAAe,WAAW,KAC7B,SAAS,gBAAgB,UAAU,KAAK,CAAC,KAAK,WAAW,KAAK,OAAQ,EAAE,CAAC,GAC3E;CACD,MAAM,YAAY,0BAA0B,WAAW,IAAI,UAAU,CAAC,KAAK,KAAK,CAAC;AAEjF,QAAO;EACL;EACA;EACA;EACA,GAAG;EACH;EACA;EACA;EACD,CAAC,KAAK,KAAK;;AAGd,SAAS,aAAa,SAA4B;CAChD,MAAM,sBAAM,IAAI,KAAa;AAC7B,MAAK,MAAM,SAAS,QAAQ,cAAc;EACxC,MAAM,SAAS,QAAQ,UAAU,MAAM,MAAgC;AACvE,OAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,CAAE,KAAI,IAAI,KAAK;;AAEvD,QAAO,CAAC,GAAG,IAAI,CAAC,UAAU;;;;;;;;;AAY5B,SAAS,UAAU,aAAgC,SAA6C;CAC9F,MAAM,OAAiB,EAAE;AACzB,MAAK,MAAM,QAAQ,aAAa;EAC9B,MAAM,WAAW,KAAK,MAAM,IAAI;EAChC,IAAI,OAAO;AACX,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,KAAK;GAC5C,MAAM,MAAM,SAAS;GACrB,MAAM,WAAW,KAAK;AACtB,OAAI,OAAO,aAAa,SAAU;AAClC,OAAI,aAAa,KAAA,GAAW;IAC1B,MAAM,OAAiB,EAAE;AACzB,SAAK,OAAO;AACZ,WAAO;SAEP,QAAO;;EAGX,MAAM,UAAU,SAAS,GAAG,GAAG;AAC/B,MAAI,KAAK,aAAa,KAAA,EAAW,MAAK,WAAW,QAAQ,KAAK;;AAEhE,QAAO;;AAGT,SAAS,WAAW,MAAyB,OAAuB;AAClE,KAAI,OAAO,SAAS,SAAU,QAAO,KAAK,UAAU,KAAK;CACzD,MAAM,SAAS,KAAK,OAAO,MAAM;CACjC,MAAM,UAAU,KAAK,OAAO,QAAQ,EAAE;AAItC,QAAO,MAHS,OAAO,KAAK,KAAK,CAC9B,UAAU,CACV,KAAK,QAAQ,GAAG,SAAS,QAAQ,IAAI,CAAC,IAAI,WAAW,KAAK,MAAO,QAAQ,EAAE,GAAG,CAC5D,KAAK,MAAM,CAAC,KAAK,QAAQ;;;;;;;AAQhD,SAAS,QAAQ,KAAqB;AACpC,KAAI,qBAAqB,KAAK,IAAI,CAAE,QAAO;AAC3C,KAAI,iBAAiB,KAAK,IAAI,CAAE,QAAO;AACvC,QAAO,KAAK,UAAU,IAAI;;;AAI5B,SAAS,UAAU,KAAqB;AACtC,QAAO,qBAAqB,KAAK,IAAI,GAAG,MAAM,IAAI,IAAI,WAAW,WAAW,IAAI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unpunnyfuns/swatchbook-integrations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"description": "Display-side integrations for the swatchbook Storybook addon. Each subpath (./tailwind, …) exports a factory that plugs into the addon's options as a SwatchbookIntegration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "unpunnyfuns <unpunnyfuns@gmail.com>",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@unpunnyfuns/swatchbook-core": "0.
|
|
47
|
+
"@unpunnyfuns/swatchbook-core": "0.55.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^25.6.0",
|