/** * SUMI Design System — Style Dictionary configuration * * Source : tokens/primitive/*.json + tokens/semantic/*.json (W3C tokens spec) * Outputs : * - dist/tokens.css (concat of primitive + dark + light themes) * - dist/tokens-primitive.css * - dist/tokens-dark.css (selector :root, [data-theme="dark"]) * - dist/tokens-light.css (selector [data-theme="light"]) * - dist/tokens.ts (TS exports — values resolved against dark theme) * * SOURCE OF TRUTH = tokens/*.json * Do NOT edit dist/* manually — they are generated. Edit tokens/* and run `npm run build:tokens`. * * Charte : ../../../Documents/TG__Talas_Group/05_EXPERIENCE_UTILISATEUR/CHARTE_GRAPHIQUE_TALAS.md */ import StyleDictionary from 'style-dictionary'; import { readFileSync, writeFileSync } from 'node:fs'; const PRIMITIVE_GLOB = 'tokens/primitive/**/*.json'; const SEMANTIC_DARK = 'tokens/semantic/dark.json'; const SEMANTIC_LIGHT = 'tokens/semantic/light.json'; /** Filter that keeps only tokens whose path starts with one of `prefixes`. */ const filterByPathPrefix = (prefixes) => (token) => prefixes.includes(token.path[0]); /** Build primitive tokens — :root only (raw values shared by all themes). */ const buildPrimitive = async () => { const sd = new StyleDictionary({ source: [PRIMITIVE_GLOB], platforms: { css: { transformGroup: 'css', buildPath: 'dist/', files: [ { destination: 'tokens-primitive.css', format: 'css/variables', options: { selector: ':root', outputReferences: false }, }, ], }, }, }); await sd.buildAllPlatforms(); }; /** Build a theme — semantic tokens with theme selector. */ const buildTheme = async (themeName, semanticFile, selector) => { const sd = new StyleDictionary({ source: [PRIMITIVE_GLOB, semanticFile], platforms: { css: { transformGroup: 'css', buildPath: 'dist/', files: [ { destination: `tokens-${themeName}.css`, format: 'css/variables', filter: filterByPathPrefix(['sumi']), options: { selector, outputReferences: true }, }, ], }, }, }); await sd.buildAllPlatforms(); }; /** Build TS exports — values resolved against dark theme (default). */ const buildTypeScript = async () => { const sd = new StyleDictionary({ source: [PRIMITIVE_GLOB, SEMANTIC_DARK], platforms: { ts: { transformGroup: 'js', buildPath: 'dist/', files: [ { destination: 'tokens.ts', format: 'javascript/es6', }, { destination: 'tokens.d.ts', format: 'typescript/es6-declarations', }, ], }, }, }); await sd.buildAllPlatforms(); }; await buildPrimitive(); await buildTheme('dark', SEMANTIC_DARK, ':root, [data-theme="dark"]'); await buildTheme('light', SEMANTIC_LIGHT, '[data-theme="light"]'); await buildTypeScript(); // Concatenate the three CSS files into a single tokens.css const header = `/** * SUMI tokens — generated by style-dictionary.config.mjs * Source: packages/design-system/tokens/ * Do NOT edit this file. Edit tokens/*.json and run \`npm run build:tokens\`. */ `; const primitive = readFileSync('dist/tokens-primitive.css', 'utf8'); const dark = readFileSync('dist/tokens-dark.css', 'utf8'); const light = readFileSync('dist/tokens-light.css', 'utf8'); const stripGenerated = (s) => s.replace(/^\/\*\*\n \* Do not edit directly[\s\S]*?\*\/\n\n?/m, ''); writeFileSync( 'dist/tokens.css', header + stripGenerated(primitive) + '\n' + stripGenerated(dark) + '\n' + stripGenerated(light), ); console.log('\n✓ Style Dictionary build complete.'); console.log(' Output: packages/design-system/dist/'); console.log(' - tokens.css (unified)'); console.log(' - tokens-primitive.css, tokens-dark.css, tokens-light.css'); console.log(' - tokens.ts, tokens.d.ts');