diff --git a/apps/web/src/components/analytics/TrackAnalyticsView.tsx b/apps/web/src/components/analytics/TrackAnalyticsView.tsx index 366a9c2a4..08bc5ef14 100644 --- a/apps/web/src/components/analytics/TrackAnalyticsView.tsx +++ b/apps/web/src/components/analytics/TrackAnalyticsView.tsx @@ -155,10 +155,10 @@ export const TrackAnalyticsView: React.FC = ({ width: `${val}%`, backgroundColor: range === '18-24' - ? '#7c9dd6' + ? 'var(--sumi-viz-indigo)' : range === '25-34' - ? '#7a9e6c' - : '#2a2a31', + ? 'var(--sumi-viz-sage)' + : 'var(--sumi-bg-hover)', }} >
diff --git a/apps/web/src/components/charts/BarChart.tsx b/apps/web/src/components/charts/BarChart.tsx index ebf2dcd8c..f9dff72ae 100644 --- a/apps/web/src/components/charts/BarChart.tsx +++ b/apps/web/src/components/charts/BarChart.tsx @@ -22,7 +22,7 @@ export function BarChart({ data, xAxisLabel, yAxisLabel, - color = '#7c9dd6', + color = 'var(--sumi-viz-indigo)', showGrid = true, showValues = false, height = 300, diff --git a/apps/web/src/components/charts/LineChart.tsx b/apps/web/src/components/charts/LineChart.tsx index f9b3e0285..0733c8c9f 100644 --- a/apps/web/src/components/charts/LineChart.tsx +++ b/apps/web/src/components/charts/LineChart.tsx @@ -22,7 +22,7 @@ export function LineChart({ data, xAxisLabel, yAxisLabel, - color = '#7c9dd6', + color = 'var(--sumi-viz-indigo)', showGrid = true, showDots = true, height = 300, diff --git a/apps/web/src/components/charts/PieChart.tsx b/apps/web/src/components/charts/PieChart.tsx index b11d6d9ff..3dc23705f 100644 --- a/apps/web/src/components/charts/PieChart.tsx +++ b/apps/web/src/components/charts/PieChart.tsx @@ -15,15 +15,18 @@ export interface PieChartProps extends Omit { colors?: string[]; } +// Data viz pigments — see CHARTE_GRAPHIQUE_TALAS §4.5 (data viz only). +// First 5 are canonical; sakura/terminal/magenta are app-specific extras pending +// canonical definition in tokens (follow-up Sprint 2). const DEFAULT_COLORS = [ - '#7c9dd6', // indigo - '#d4634a', // vermillion - '#7a9e6c', // sage - '#c9a84c', // gold - '#a8a4a0', // text-secondary - '#e0a0b8', // sakura - '#3eaa5e', // terminal-green - '#c840a0', // graffiti-magenta + 'var(--sumi-viz-indigo)', + 'var(--sumi-viz-vermillion)', + 'var(--sumi-viz-sage)', + 'var(--sumi-viz-gold)', + 'var(--sumi-viz-neutral)', + '#e0a0b8', // sakura — TODO: canonize in tokens/primitive/color.json viz palette + '#3eaa5e', // terminal-green — TODO: canonize + '#c840a0', // graffiti-magenta — TODO: canonize ]; /** diff --git a/apps/web/src/components/developer/SwaggerUI.tsx b/apps/web/src/components/developer/SwaggerUI.tsx index e0736a239..6bdf698ca 100644 --- a/apps/web/src/components/developer/SwaggerUI.tsx +++ b/apps/web/src/components/developer/SwaggerUI.tsx @@ -240,7 +240,7 @@ export function SwaggerUIDoc({ specUrl, spec, useIframe = false }: SwaggerUIProp color: rgba(255, 255, 255, 0.8); } .swagger-ui-container .swagger-ui .parameter__name { - color: #7c9dd6; + color: var(--sumi-viz-indigo); } .swagger-ui-container .swagger-ui .response-col_status { color: #fff; @@ -256,7 +256,7 @@ export function SwaggerUIDoc({ specUrl, spec, useIframe = false }: SwaggerUIProp color: #fff; } .swagger-ui-container .swagger-ui .btn { - background: #7c9dd6; + background: var(--sumi-viz-indigo); color: #000; border: none; } @@ -264,7 +264,7 @@ export function SwaggerUIDoc({ specUrl, spec, useIframe = false }: SwaggerUIProp background: #93afe0; } .swagger-ui-container .swagger-ui .btn.execute { - background: #7c9dd6; + background: var(--sumi-viz-indigo); color: #000; } .swagger-ui-container .swagger-ui .btn.cancel { diff --git a/apps/web/src/components/ui/WaveformVisualizer.tsx b/apps/web/src/components/ui/WaveformVisualizer.tsx index 90025ddf5..36d688306 100644 --- a/apps/web/src/components/ui/WaveformVisualizer.tsx +++ b/apps/web/src/components/ui/WaveformVisualizer.tsx @@ -91,8 +91,8 @@ export const WaveformVisualizer: React.FC = ({ progress, onSeek, height = 64, - color = '#2a2a31', // sumi-bg-hover - playedColor = '#7c9dd6', // sumi-accent + color = 'var(--sumi-bg-hover)', + playedColor = 'var(--sumi-viz-indigo)', }) => { const canvasRef = useRef(null); const [data, setData] = useState([]); @@ -133,6 +133,15 @@ export const WaveformVisualizer: React.FC = ({ const gap = 1; const effectiveBarWidth = Math.max(1, barWidth - gap); + // Resolve CSS vars to hex values (canvas can't resolve var() directly) + const styles = getComputedStyle(canvas); + const resolve = (c: string) => + c.startsWith('var(') + ? styles.getPropertyValue(c.slice(4, -1).trim()).trim() || c + : c; + const resolvedColor = resolve(color); + const resolvedPlayed = resolve(playedColor); + data.forEach((val, i) => { const x = i * barWidth; const barHeight = val * drawHeight; @@ -140,7 +149,7 @@ export const WaveformVisualizer: React.FC = ({ // Determine color based on progress const isPlayed = (i / data.length) * 100 <= progress; - ctx.fillStyle = isPlayed ? playedColor : color; + ctx.fillStyle = isPlayed ? resolvedPlayed : resolvedColor; // Draw rounded rect equivalent ctx.fillRect(x, y, effectiveBarWidth, barHeight); diff --git a/apps/web/src/components/upload/metadata/MetadataEditor.tsx b/apps/web/src/components/upload/metadata/MetadataEditor.tsx index 15fc43967..86ee9ae4e 100644 --- a/apps/web/src/components/upload/metadata/MetadataEditor.tsx +++ b/apps/web/src/components/upload/metadata/MetadataEditor.tsx @@ -175,8 +175,8 @@ export const MetadataEditor: React.FC = ({ progress={progress} onSeek={setProgress} height={48} - color="#2a2a31" - playedColor="#7c9dd6" + color="var(--sumi-bg-hover)" + playedColor="var(--sumi-viz-indigo)" />
diff --git a/apps/web/src/features/player/components/AudioVisualizer.tsx b/apps/web/src/features/player/components/AudioVisualizer.tsx index 1dc5fe661..0458ea35f 100644 --- a/apps/web/src/features/player/components/AudioVisualizer.tsx +++ b/apps/web/src/features/player/components/AudioVisualizer.tsx @@ -13,6 +13,13 @@ import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { BarChart3, Activity, Radio } from 'lucide-react'; import type { VisualizerMode } from '../hooks/useSpectrumAnalyser'; +import { + ColorVizIndigo, + ColorVizVermillion, + ColorVizSage, + ColorVizGold, + ColorVoidBase, +} from '@veza/design-system/tokens-generated'; interface AudioVisualizerProps { /** Normalized frequency bands [0-1] */ @@ -31,11 +38,24 @@ const MODES: { mode: VisualizerMode; icon: typeof BarChart3; label: string }[] = { mode: 'spectrogram', icon: Radio, label: 'Spectrogram' }, ]; -// SUMI colors -const ACCENT_COLOR = '#7c9dd6'; // --sumi-accent -const SAGE = '#7a9e6c'; // --sumi-sage -const GOLD = '#c9a84c'; // --sumi-gold -const BG_VOID = '#0c0c0f'; // --sumi-bg-void +// SUMI colors — resolved hex values from generated tokens (source of truth: packages/design-system/tokens/). +// Canvas can't resolve var(--sumi-*) directly, so we use the imported hex strings to enable +// gradient interpolation and string concatenation (alpha suffix) below. +const ACCENT_COLOR = ColorVizIndigo; +const VERMILLION = ColorVizVermillion; +const SAGE = ColorVizSage; +const GOLD = ColorVizGold; +const BG_VOID = ColorVoidBase; + +// Decompose hex colors to RGB byte tuples for spectrogram interpolation. +const hexToRgb = (hex: string): [number, number, number] => { + const m = hex.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); + if (!m || !m[1] || !m[2] || !m[3]) return [0, 0, 0]; + return [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)]; +}; +const [I_R, I_G, I_B] = hexToRgb(ACCENT_COLOR); +const [V_R, V_G, V_B] = hexToRgb(VERMILLION); +const [GOLD_R, GOLD_G, GOLD_B] = hexToRgb(GOLD); export function AudioVisualizer({ bands, @@ -75,11 +95,11 @@ export function AudioVisualizer({ const x = i * (barWidth + gap); const y = H - barH; - // Gradient from accent to vermillion based on frequency + // Gradient from accent (indigo) to vermillion based on frequency const t = i / barCount; - const r = lerp(0x7c, 0xd4, t); - const g = lerp(0x9d, 0x63, t); - const b = lerp(0xd6, 0x4a, t); + const r = lerp(I_R, V_R, t); + const g = lerp(I_G, V_G, t); + const b = lerp(I_B, V_B, t); ctx.fillStyle = `rgb(${r}, ${g}, ${b})`; // Rounded top rect @@ -276,21 +296,19 @@ function lerp(a: number, b: number, t: number): number { } function spectrogramColor(intensity: number): [number, number, number] { - // 0..0.25: black → deep blue - // 0.25..0.5: deep blue → accent - // 0.5..0.75: accent → vermillion - // 0.75..1: vermillion → gold + // Heat map: black → deep blue → indigo → vermillion → gold + // Bytes derived from token-imported hex via hexToRgb (above). if (intensity < 0.25) { const t = intensity / 0.25; return [lerp(12, 40, t), lerp(12, 50, t), lerp(15, 100, t)]; } else if (intensity < 0.5) { const t = (intensity - 0.25) / 0.25; - return [lerp(40, 0x7c, t), lerp(50, 0x9d, t), lerp(100, 0xd6, t)]; + return [lerp(40, I_R, t), lerp(50, I_G, t), lerp(100, I_B, t)]; } else if (intensity < 0.75) { const t = (intensity - 0.5) / 0.25; - return [lerp(0x7c, 0xd4, t), lerp(0x9d, 0x63, t), lerp(0xd6, 0x4a, t)]; + return [lerp(I_R, V_R, t), lerp(I_G, V_G, t), lerp(I_B, V_B, t)]; } else { const t = (intensity - 0.75) / 0.25; - return [lerp(0xd4, 0xc9, t), lerp(0x63, 0xa8, t), lerp(0x4a, 0x4c, t)]; + return [lerp(V_R, GOLD_R, t), lerp(V_G, GOLD_G, t), lerp(V_B, GOLD_B, t)]; } } diff --git a/apps/web/src/features/streaming/components/playback-dashboard/PlaybackDashboardCharts.tsx b/apps/web/src/features/streaming/components/playback-dashboard/PlaybackDashboardCharts.tsx index 8319445c6..b7e64417e 100644 --- a/apps/web/src/features/streaming/components/playback-dashboard/PlaybackDashboardCharts.tsx +++ b/apps/web/src/features/streaming/components/playback-dashboard/PlaybackDashboardCharts.tsx @@ -34,7 +34,7 @@ export function PlaybackDashboardCharts({ data={sessionsChartData} xAxisLabel="Date" yAxisLabel="Nombre de sessions" - color="#7c9dd6" + color="var(--sumi-viz-indigo)" height={300} showGrid showDots @@ -56,7 +56,7 @@ export function PlaybackDashboardCharts({ data={playTimeChartData} xAxisLabel="Date" yAxisLabel="Temps moyen (secondes)" - color="#7a9e6c" + color="var(--sumi-viz-sage)" height={300} showGrid showDots @@ -78,7 +78,7 @@ export function PlaybackDashboardCharts({ data={completionChartData} xAxisLabel="Date" yAxisLabel="Taux de complétion (%)" - color="#c9a84c" + color="var(--sumi-viz-gold)" height={300} showGrid showDots diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 86526dc01..a58c3e2bd 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -1,6 +1,12 @@ @import 'tailwindcss'; @import 'tw-animate-css'; +/* SUMI generated tokens — Single source of truth. See packages/design-system/tokens/. + This adds --color-* primitives and --sumi-* semantics (bg/text/accent/viz/feedback). + The legacy :root block below still defines additional --sumi-* vars (typography, motion, + z-index, glass…) pending migration to tokens.json (Sprint 2 follow-up). */ +@import '@veza/design-system/tokens.css'; + @custom-variant dark (&:is([data-theme="dark"] *)); /* ╔══════════════════════════════════════════════════════════════════════════╗ diff --git a/package-lock.json b/package-lock.json index d61fe3c57..68571749b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1109,6 +1109,202 @@ "node": ">=18" } }, + "node_modules/@bundled-es-modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-Rk453EklPUPC3NRWc3VUNI/SSUjdBaFoaQvFRmNBNtMHVtOFD5AntiWg5kEE1hqcPqedYFDzxE3ZcMYPcA195w==", + "dev": true, + "license": "ISC", + "dependencies": { + "deepmerge": "^4.3.1" + } + }, + "node_modules/@bundled-es-modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-740y5ofkzydsFao5EXJrGilcIL6EFEw/cmPf2uhTw9J6G1YOhiIFjNFCHdpgEiiH5VlU3G0SARSjlFlimRRSMA==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "buffer": "^6.0.3", + "events": "^3.3.0", + "glob": "^10.4.2", + "patch-package": "^8.0.0", + "path": "^0.12.7", + "stream": "^0.0.3", + "string_decoder": "^1.3.0", + "url": "^0.11.3" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@bundled-es-modules/glob/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/@bundled-es-modules/memfs": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/memfs/-/memfs-4.17.0.tgz", + "integrity": "sha512-ykdrkEmQr9BV804yd37ikXfNnvxrwYfY9Z2/EtMHFEFadEjsQXJ1zL9bVZrKNLDtm91UdUOEHso6Aweg93K6xQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "assert": "^2.1.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "memfs": "^4.17.0", + "path": "^0.12.7", + "stream": "^0.0.3", + "util": "^0.12.5" + } + }, + "node_modules/@bundled-es-modules/memfs/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@bundled-es-modules/memfs/node_modules/memfs": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@bundled-es-modules/memfs/node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/@chromatic-com/playwright": { "version": "0.12.8", "resolved": "https://registry.npmjs.org/@chromatic-com/playwright/-/playwright-0.12.8.tgz", @@ -2864,6 +3060,436 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.57.2", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@juspay-tech/hyper-js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@juspay-tech/hyper-js/-/hyper-js-2.1.0.tgz", @@ -7529,6 +8155,25 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@zip.js/zip.js": { + "version": "2.8.26", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.26.tgz", + "integrity": "sha512-RQ4h9F6DOiHxpdocUDrOl6xBM+yOtz+LkUol47AVWcfebGBDpZ7w7Xvz9PS24JgXvLGiXXzSAfdCdVy1tPlaFA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=18.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -7993,6 +8638,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/assert/node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -8883,6 +9556,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -9011,6 +9691,22 @@ "dev": true, "license": "MIT" }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", @@ -9242,6 +9938,19 @@ "dev": true, "license": "MIT" }, + "node_modules/component-emitter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-2.0.0.tgz", + "integrity": "sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -11504,6 +12213,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flairup": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz", @@ -12064,6 +12783,23 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -12595,6 +13331,16 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/i18next": { "version": "25.7.3", "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.3.tgz", @@ -13232,6 +13978,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -13813,6 +14576,26 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -13846,6 +14629,16 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jsonpointer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", @@ -13905,6 +14698,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -15910,6 +16713,91 @@ "tslib": "^2.0.3" } }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/patch-package/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/path": { "version": "0.12.7", "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", @@ -16006,6 +16894,13 @@ "node": ">=8" } }, + "node_modules/path-unified": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/path-unified/-/path-unified-0.2.0.tgz", + "integrity": "sha512-MNKqvrKbbbb5p7XHXV6ZAsf/1f/yJQa13S/fcX0uua8ew58Tgc6jXV+16JyAbnR/clgCH+euKDxrF2STxMHdrg==", + "dev": true, + "license": "MIT" + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -18487,6 +19382,16 @@ "memoizerific": "^1.11.3" } }, + "node_modules/stream": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.3.tgz", + "integrity": "sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^2.0.0" + } + }, "node_modules/streamx": { "version": "2.23.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", @@ -18812,6 +19717,58 @@ "dev": true, "license": "MIT" }, + "node_modules/style-dictionary": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-4.4.0.tgz", + "integrity": "sha512-+xU0IA1StzqAqFs/QtXkK+XJa7wpS4X5H+JQccRKsRCElgeLGocFU1U/UMvMUylKFw6vwGV+Y/a2wb2pm5rFFQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@bundled-es-modules/deepmerge": "^4.3.1", + "@bundled-es-modules/glob": "^10.4.2", + "@bundled-es-modules/memfs": "^4.9.4", + "@zip.js/zip.js": "^2.7.44", + "chalk": "^5.3.0", + "change-case": "^5.3.0", + "commander": "^12.1.0", + "is-plain-obj": "^4.1.0", + "json5": "^2.2.2", + "patch-package": "^8.0.0", + "path-unified": "^0.2.0", + "prettier": "^3.3.3", + "tinycolor2": "^1.6.0" + }, + "bin": { + "style-dictionary": "bin/style-dictionary.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/style-dictionary/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/style-dictionary/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -19303,6 +20260,23 @@ } } }, + "node_modules/thingies": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -19323,6 +20297,13 @@ "dev": true, "license": "MIT" }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyexec": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", @@ -19408,6 +20389,16 @@ "valibot": "^1.1.0" } }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-buffer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", @@ -19502,6 +20493,23 @@ "node": ">=18" } }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/tree-sitter-json": { "version": "0.24.8", "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.24.8.tgz", @@ -21513,6 +22521,7 @@ "tailwind-merge": "^3.0.0" }, "devDependencies": { + "style-dictionary": "^4.4.0", "typescript": "^5.9.0" }, "peerDependencies": { diff --git a/packages/design-system/README.md b/packages/design-system/README.md index c06befabe..a4f7eb77a 100644 --- a/packages/design-system/README.md +++ b/packages/design-system/README.md @@ -1,87 +1,106 @@ # @veza/design-system -**SUMI Design System v2.0** — "L'encre et la lumière" (Ink and Light) +**SUMI Design System v3.0** — "Lavis d'encre" (Ink wash) -The centralized design system for the Veza platform. Provides design tokens, component type registry, and utilities. +Token-only package for the Veza platform. Single source of truth for all design tokens (colors, typography, spacing, motion, elevation), authored as W3C-spec JSON tokens and compiled via Style Dictionary to CSS variables and TypeScript exports. ## Structure ``` packages/design-system/ -├── src/ -│ ├── index.ts # Barrel exports -│ ├── utils.ts # cn() utility -│ ├── tokens/ -│ │ ├── index.ts # All token exports -│ │ ├── colors.ts # Background, surface, text, pigment, semantic colors -│ │ ├── typography.ts # Font families, sizes, weights, line heights -│ │ ├── spacing.ts # Spacing scale, border radius, z-index, layout -│ │ └── motion.ts # Duration and easing tokens -│ └── components/ -│ └── index.ts # Component type registry +├── tokens/ # SOURCE OF TRUTH (edit these) +│ ├── primitive/ +│ │ ├── color.json # ink, washi, void, mizu, kin, viz, functional, alpha +│ │ ├── typography.json # Space Grotesk + Inter + JetBrains Mono scales +│ │ ├── spacing.json # 4px scale + radius + z-index +│ │ ├── motion.json # goutte/trait/lavis/vague/maree + easings +│ │ └── elevation.json # shadows + blur + opacity +│ └── semantic/ +│ ├── dark.json # default :root, [data-theme="dark"] +│ └── light.json # [data-theme="light"] (washi paper) +├── dist/ # GENERATED (do NOT edit, gitignored) +│ ├── tokens.css # Unified primitive + dark + light +│ ├── tokens-{primitive,dark,light}.css +│ └── tokens.{ts,d.ts} # TS exports of resolved hex values +├── style-dictionary.config.mjs # Build config └── package.json ``` ## Usage -### Design Tokens (TypeScript) +### CSS variables (recommended for UI) -```typescript -import { pigments, fontFamilies, spacing } from '@veza/design-system/tokens'; - -// Colors -pigments.accent.base // '#7c9dd6' -pigments.vermillion.base // '#d4634a' - -// Typography -fontFamilies.heading // "'Space Grotesk', 'Inter', sans-serif" - -// Spacing -spacing['4'] // '16px' -``` - -### Design Tokens (CSS) - -The CSS custom properties are the primary token interface, defined in `apps/web/src/index.css`: +`apps/web/src/index.css` imports the unified file: ```css -color: var(--sumi-accent); -padding: var(--sumi-space-4); -font-family: var(--sumi-font-heading); -border-radius: var(--sumi-radius-md); +@import '@veza/design-system/tokens.css'; ``` -### Components +Then components reference vars via Tailwind arbitrary values or inline styles: -Components are implemented in `apps/web/src/components/ui/` and imported via path alias: - -```typescript -import { Button } from '@/components/ui/button'; -import { Card } from '@/components/ui/card'; -import { Dialog } from '@/components/ui/dialog'; +```tsx +
...
+
...
``` -See `apps/web/.storybook/` for Storybook documentation of all components. +### TypeScript imports (for canvas / runtime needs) + +For contexts that can't resolve CSS vars (canvas drawing, programmatic gradients, byte interpolation): + +```ts +import { ColorVizIndigo, SumiAccentDefault } from '@veza/design-system/tokens-generated'; + +ctx.fillStyle = ColorVizIndigo; // resolved hex string '#7c9dd6' +const accent = SumiAccentDefault; // '#0098b5' +``` + +## Build + +```bash +npm run build:tokens --workspace=@veza/design-system +``` + +Triggered automatically via `turbo run build` (the apps/web build depends on this package). + +## Color system — Option B palette + +Per `CHARTE_GRAPHIQUE_TALAS.md` §4 (canonical brand source) + §4.5 (data viz): + +### UI palette (everywhere except data viz) + +The cyan **Mizu** (`#0098B5`) is the **sole** accent color. Functional colors (success/error/warning) are always diluted (max 60% opacity), never solid fills. + +| Token | Role | Value | +|-------|------|-------| +| `--sumi-accent-default` | Primary actions, links, focus | Mizu cyan `#0098B5` | +| `--sumi-feedback-success` | Success states (subtle) | Diluted sage | +| `--sumi-feedback-error` | Error states (subtle) | Diluted brick | +| `--sumi-feedback-warning` | Warning states (subtle) | Diluted amber | + +### Data viz palette (charts, waveforms, analytics ONLY) + +For graphs and visualizations needing distinguishable colors, the 4 viz pigments + neutral are authorized: + +| Pigment | Hex | Token | +|---------|-----|-------| +| Indigo | `#7c9dd6` | `--sumi-viz-indigo` | +| Vermillion | `#d4634a` | `--sumi-viz-vermillion` | +| Sage | `#7a9e6c` | `--sumi-viz-sage` | +| Gold | `#c9a84c` | `--sumi-viz-gold` | +| Neutral grey | `#a8a4a0` | `--sumi-viz-neutral` | + +**These are NEVER allowed in standard UI** (buttons, links, accents). The cyan rule above stays absolute. ## Themes - **Dark** (default) — Ink on void - **Light** — Washi paper aesthetic (`[data-theme="light"]`) -- **High Contrast** — WCAG AA 4.5:1+ (`[data-contrast="high"]`) -- **Compact Density** — Reduced spacing (`[data-density="compact"]`) +- **Circadian + patina + density + contrast** — Runtime modifiers handled by `apps/web/src/components/theme/ThemeProvider.tsx` -## Color System — The 4 Pigments +## See also -| Pigment | Hex | Usage | -|---------|-----|-------| -| **Accent** (Indigo) | `#7c9dd6` | Primary actions, links, focus | -| **Vermillion** | `#d4634a` | Errors, destructive, live | -| **Sage** | `#7a9e6c` | Success, online | -| **Gold** | `#c9a84c` | Warnings, achievements | - -## References - -- Design tokens source: `apps/web/src/index.css` -- Token documentation: `apps/web/docs/DESIGN_TOKENS.md` +- Brand source of truth: `~/Documents/TG__Talas_Group/05_EXPERIENCE_UTILISATEUR/CHARTE_GRAPHIQUE_TALAS.md` +- Brand decisions: `~/Documents/TG__Talas_Group/05_EXPERIENCE_UTILISATEUR/DECISIONS_IDENTITE.md` +- Veza UI/UX contract: `veza-docs/ORIGIN/ORIGIN_UI_UX_SYSTEM.md` - Storybook: `apps/web/.storybook/` - Component source: `apps/web/src/components/ui/` diff --git a/packages/design-system/package.json b/packages/design-system/package.json index a91e3a37b..a526b34dd 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -1,34 +1,26 @@ { "name": "@veza/design-system", - "version": "2.0.0", - "description": "SUMI Design System — Design tokens, utilities, and component re-exports for the Veza platform", + "version": "3.0.0", + "description": "SUMI Design System — Design tokens (single source of truth) for the Veza platform. Authored as W3C JSON tokens, compiled via Style Dictionary to CSS vars + TS exports.", "type": "module", - "main": "./src/index.ts", - "types": "./src/index.ts", "exports": { - ".": "./src/index.ts", - "./tokens": "./src/tokens/index.ts", - "./tokens/colors": "./src/tokens/colors.ts", - "./tokens/typography": "./src/tokens/typography.ts", - "./tokens/spacing": "./src/tokens/spacing.ts", - "./tokens/motion": "./src/tokens/motion.ts" + "./tokens.css": "./dist/tokens.css", + "./tokens-generated": { + "types": "./dist/tokens.d.ts", + "default": "./dist/tokens.ts" + } }, "files": [ - "src/" + "tokens/", + "dist/", + "style-dictionary.config.mjs" ], "scripts": { - "typecheck": "tsc --noEmit" - }, - "dependencies": { - "clsx": "^2.0.0", - "tailwind-merge": "^3.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" + "build": "node style-dictionary.config.mjs", + "build:tokens": "node style-dictionary.config.mjs" }, "devDependencies": { - "typescript": "^5.9.0" + "style-dictionary": "^4.4.0" }, "license": "UNLICENSED" } diff --git a/packages/design-system/src/components/index.ts b/packages/design-system/src/components/index.ts deleted file mode 100644 index fc1346d3a..000000000 --- a/packages/design-system/src/components/index.ts +++ /dev/null @@ -1,116 +0,0 @@ -/** - * SUMI Design System v2.0 — Component Registry - * - * This file documents the canonical component set of the SUMI design system. - * Components are implemented in apps/web/src/components/ui/ and imported - * from there using the @/components/ui/ path alias. - * - * To use in the web app: - * import { Button } from '@/components/ui/button'; - * import { Card } from '@/components/ui/card'; - * - * This registry exists for documentation and type-checking purposes. - */ - -/** - * SUMI Component Categories: - * - * ═══ PRIMITIVES ═══ - * Button — Primary action element (variants: default, destructive, outline, secondary, ghost, link) - * Input — Text input field - * Textarea — Multi-line text input - * Label — Form field label - * Checkbox — Binary selection - * RadioGroup — Single selection from options - * Switch — Toggle control - * Slider — Range input - * Select — Dropdown selection - * - * ═══ LAYOUT ═══ - * Card — Content container with border - * Accordion — Collapsible content sections - * Tabs — Tabbed content panels - * Sidebar — Navigation sidebar - * ScrollArea — Custom scrollable container - * Table — Data table - * - * ═══ FEEDBACK ═══ - * Alert — Informational message - * Badge — Status indicator - * Dialog — Modal dialog - * Toast — Temporary notification - * Tooltip — Hover information - * HoverCard — Rich hover popup - * Skeleton — Loading placeholder - * Progress — Progress indicator - * LoadingSpinner — Animated spinner - * - * ═══ NAVIGATION ═══ - * DropdownMenu — Contextual menu - * ContextMenu — Right-click menu - * NavigationProgress — Page transition indicator - * - * ═══ SPECIALIZED ═══ - * FileUpload — File upload with drag & drop - * AvatarUpload — Avatar image upload with cropper - * DatePicker — Date selection - * VirtualizedList — Virtualized scrolling for large lists - * OptimizedImage — Responsive image with blur placeholder - * AnimatedNumber — Animated numeric display - */ - -// Component type exports for type-safety when referencing SUMI components -export type SumiComponentName = - // Primitives - | 'Button' - | 'Input' - | 'Textarea' - | 'Label' - | 'Checkbox' - | 'RadioGroup' - | 'Switch' - | 'Slider' - | 'Select' - | 'FloatingInput' - // Layout - | 'Card' - | 'Accordion' - | 'Tabs' - | 'Sidebar' - | 'ScrollArea' - | 'Table' - | 'Collapsible' - // Feedback - | 'Alert' - | 'Badge' - | 'Dialog' - | 'ConfirmationDialog' - | 'Toast' - | 'Tooltip' - | 'HoverCard' - | 'Skeleton' - | 'Progress' - | 'LoadingSpinner' - | 'LoadingState' - | 'ErrorBoundary' - | 'ErrorDisplay' - // Navigation - | 'DropdownMenu' - | 'ContextMenu' - | 'NavigationProgress' - | 'ScrollToTop' - // Specialized - | 'Avatar' - | 'AvatarUpload' - | 'FileUpload' - | 'DatePicker' - | 'ImageCropper' - | 'VirtualizedList' - | 'OptimizedImage' - | 'AnimatedNumber' - | 'DataList' - | 'FormField' - | 'FAB' - | 'FocusTrap' - | 'KeyboardShortcutsPanel' - | 'WaveformVisualizer'; diff --git a/packages/design-system/src/index.ts b/packages/design-system/src/index.ts deleted file mode 100644 index a18ecde30..000000000 --- a/packages/design-system/src/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @veza/design-system — SUMI Design System v2.0 - * "L'encre et la lumière" — Ink and Light - * - * This package provides: - * - Design tokens (colors, typography, spacing, motion) as TypeScript objects - * - Component type registry for the SUMI component set - * - Utility functions (cn) - * - * Components are implemented in apps/web/src/components/ui/ and should be - * imported from there using the @/components/ui/ path alias. - * - * Usage: - * import { colors, typography } from '@veza/design-system/tokens'; - * import { pigments } from '@veza/design-system/tokens/colors'; - */ - -// ═══ Design Tokens ═══ -export { - colors, - backgrounds, - surfaces, - borders, - text, - pigments, - semantic, - glass, - shadows, - lightTheme, - typography, - fontFamilies, - fontSizes, - lineHeights, - letterSpacings, - fontWeights, - spacingTokens, - spacing, - radius, - zIndex, - layout, - motion, - durations, - easings, -} from './tokens'; - -export type { SumiColor } from './tokens'; - -// ═══ Component Registry ═══ -export type { SumiComponentName } from './components'; - -// ═══ Utilities ═══ -export { cn } from './utils'; diff --git a/packages/design-system/src/tokens/colors.ts b/packages/design-system/src/tokens/colors.ts deleted file mode 100644 index 5976b5076..000000000 --- a/packages/design-system/src/tokens/colors.ts +++ /dev/null @@ -1,191 +0,0 @@ -/** - * SUMI Design System v4.0 — Color Tokens - * "Lavis d'encre" — Ink Wash (墨の濃淡) - * - * Named after traditional Japanese ink tones: - * Kuro (黒), Sumi (墨), Usuzumi (薄墨), Hai (灰), Gin (銀), Kasumi (霞) - * Shiro (白), Kinari (生成), Kinu (絹), Torinoko (鳥の子), Cha (茶) - * - * Source of truth: apps/web/src/index.css - */ - -// ═══ DARK THEME (default) — Ink on void (墨の闇) ═══ - -export const backgrounds = { - void: '#0d0d0b', - base: '#13110f', - raised: '#1a1714', - overlay: '#242018', - hover: '#2e2a22', - active: '#383228', - wash: '#17140f', -} as const; - -export const surfaces = { - inset: '#0f0d0b', - subtle: '#1e1a15', - card: '#1a1714', - elevated: '#242018', -} as const; - -export const borders = { - faint: 'rgba(232,224,208, 0.03)', - default: 'rgba(232,224,208, 0.06)', - strong: 'rgba(232,224,208, 0.10)', - focus: 'rgba(184,58,30, 0.50)', - accent: 'rgba(184,58,30, 0.25)', -} as const; - -export const text = { - primary: '#e8e0d0', - secondary: '#9e9688', - tertiary: '#6b6560', - disabled: '#3d3930', - inverse: '#13110f', - link: '#b83a1e', -} as const; - -// ═══ PIGMENTS — Shu vermillion primary (朱) + Kin gold (金) ═══ - -export const pigments = { - accent: { - base: '#b83a1e', - hover: '#c84a2e', - active: '#8b2500', - muted: 'rgba(184,58,30, 0.18)', - subtle: 'rgba(184,58,30, 0.06)', - emphasis: '#8b2500', - }, - vermillion: { - base: '#a04050', - hover: '#b05060', - subtle: 'rgba(160,64,80, 0.10)', - }, - sage: { - base: '#4f6840', - hover: '#5f7850', - subtle: 'rgba(79,104,64, 0.10)', - }, - gold: { - base: '#b8860b', - hover: '#c8960b', - subtle: 'rgba(184,134,11, 0.10)', - }, - kin: { - base: '#b8860b', - glow: '0 0 8px rgba(184,134,11, 0.2)', - }, - patinaGreen: { - base: '#5A8A72', - }, -} as const; - -// ═══ SEMANTIC ═══ - -export const semantic = { - success: pigments.sage.base, - successSubtle: pigments.sage.subtle, - warning: pigments.gold.base, - warningSubtle: pigments.gold.subtle, - error: pigments.vermillion.base, - errorSubtle: pigments.vermillion.subtle, - info: pigments.accent.base, - live: '#a04050', - online: pigments.sage.base, -} as const; - -// ═══ GLASS — Shoji screen (障子) ═══ - -export const glass = { - bg: 'rgba(19,17,15, 0.80)', - border: 'rgba(232,224,208, 0.04)', - blur: '12px', -} as const; - -// ═══ SHADOWS — Ink diffusion (滲み) ═══ - -export const shadows = { - xs: '0 1px 3px rgba(13,13,11,0.20)', - sm: '0 2px 8px rgba(13,13,11,0.15), 0 1px 3px rgba(13,13,11,0.12)', - md: '0 4px 20px rgba(13,13,11,0.15), 0 2px 6px rgba(13,13,11,0.10)', - lg: '0 8px 35px rgba(13,13,11,0.18), 0 4px 12px rgba(13,13,11,0.10)', - xl: '0 16px 55px rgba(13,13,11,0.22), 0 8px 20px rgba(13,13,11,0.12)', - '2xl': '0 24px 75px rgba(13,13,11,0.30)', - glow: '0 0 0 3px rgba(184,58,30, 0.20)', - glowLg: '0 0 20px rgba(184,58,30, 0.10)', - kin: '0 0 16px rgba(184,134,11, 0.15)', -} as const; - -// ═══ LIGHT THEME — Washi paper (和紙) ═══ - -export const lightTheme = { - backgrounds: { - void: '#e8e0cf', - base: '#f0ebe0', - raised: '#f0ebe0', - overlay: '#f0ebe0', - hover: '#e4dccb', - active: '#ddd4c0', - wash: '#ece5d6', - }, - surfaces: { - inset: '#e0d8c8', - subtle: '#e8e0cf', - card: '#f0ebe0', - elevated: '#f5f0e5', - }, - borders: { - faint: 'rgba(26,23,20, 0.04)', - default: 'rgba(26,23,20, 0.06)', - strong: 'rgba(26,23,20, 0.12)', - focus: 'rgba(139,37,0, 0.45)', - accent: 'rgba(139,37,0, 0.20)', - }, - text: { - primary: '#1a1714', - secondary: '#3d3930', - tertiary: '#6b6560', - disabled: '#c4bba8', - inverse: '#e8e0d0', - link: '#8b2500', - }, -} as const; - -// ═══ INK TONES — 墨の六色 ═══ - -export const inkTones = { - kuro: '#0d0d0b', - sumi: '#1a1714', - usuzumi: '#3d3930', - hai: '#6b6560', - gin: '#9e9688', - kasumi: '#c4bba8', -} as const; - -// ═══ WASHI TONES — 和紙の色 ═══ - -export const washiTones = { - shiro: '#f0ebe0', - kinari: '#e8e0cf', - kinu: '#ddd4c0', - torinoko: '#d0c5ad', - cha: '#c4b698', -} as const; - -// ═══ ALL COLORS ═══ - -export const colors = { - backgrounds, - surfaces, - borders, - text, - pigments, - semantic, - glass, - shadows, - lightTheme, - inkTones, - washiTones, -} as const; - -export type SumiColor = typeof colors; diff --git a/packages/design-system/src/tokens/index.ts b/packages/design-system/src/tokens/index.ts deleted file mode 100644 index a66cb086e..000000000 --- a/packages/design-system/src/tokens/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * SUMI Design System v2.0 — Design Tokens - * - * Centralized design tokens extracted from CSS custom properties. - * Use these for TypeScript-level access to the design system values. - * - * For CSS usage, prefer the CSS custom properties directly: - * var(--sumi-accent), var(--sumi-space-4), etc. - * - * For JS/TS usage (e.g., inline styles, canvas, SVG): - * import { colors, typography, spacing, motion } from '@veza/design-system/tokens'; - */ - -export { colors, backgrounds, surfaces, borders, text, pigments, semantic, glass, shadows, lightTheme } from './colors'; -export type { SumiColor } from './colors'; - -export { typography, fontFamilies, fontSizes, lineHeights, letterSpacings, fontWeights } from './typography'; - -export { spacingTokens, spacing, radius, zIndex, layout } from './spacing'; - -export { motion, durations, easings } from './motion'; diff --git a/packages/design-system/src/tokens/motion.ts b/packages/design-system/src/tokens/motion.ts deleted file mode 100644 index 26f992c34..000000000 --- a/packages/design-system/src/tokens/motion.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * SUMI Design System v4.0 — Motion & Animation Tokens - * - * Source of truth: apps/web/src/index.css - */ - -export const durations = { - instant: '75ms', - fast: '150ms', - normal: '200ms', - slow: '300ms', - slower: '500ms', -} as const; - -export const easings = { - default: 'cubic-bezier(0.25, 0.1, 0.25, 1)', - out: 'cubic-bezier(0.33, 1, 0.68, 1)', - in: 'cubic-bezier(0.32, 0, 0.67, 0)', - inOut: 'cubic-bezier(0.65, 0, 0.35, 1)', - bounce: 'cubic-bezier(0.34, 1.56, 0.64, 1)', - spring: 'cubic-bezier(0.175, 0.885, 0.32, 1.1)', -} as const; - -export const motion = { - durations, - easings, -} as const; diff --git a/packages/design-system/src/tokens/spacing.ts b/packages/design-system/src/tokens/spacing.ts deleted file mode 100644 index 789585de8..000000000 --- a/packages/design-system/src/tokens/spacing.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * SUMI Design System v4.0 — Spacing & Layout Tokens - * - * Source of truth: apps/web/src/index.css - */ - -export const spacing = { - '0.5': '2px', - '1': '4px', - '1.5': '6px', - '2': '8px', - '2.5': '10px', - '3': '12px', - '4': '16px', - '5': '20px', - '6': '24px', - '8': '32px', - '10': '40px', - '12': '48px', - '16': '64px', - '20': '80px', -} as const; - -export const radius = { - xs: '2px', - sm: '4px', - md: '6px', - lg: '12px', - xl: '16px', - '2xl': '20px', - full: '9999px', -} as const; - -export const zIndex = { - base: 0, - raised: 10, - dropdown: 100, - sticky: 200, - overlay: 300, - modal: 400, - popover: 500, - toast: 600, - tooltip: 700, - max: 999, -} as const; - -export const layout = { - maxWidth: '1400px', - maxWidthContent: '1200px', -} as const; - -export const spacingTokens = { - spacing, - radius, - zIndex, - layout, -} as const; diff --git a/packages/design-system/src/tokens/typography.ts b/packages/design-system/src/tokens/typography.ts deleted file mode 100644 index 8c814a5e3..000000000 --- a/packages/design-system/src/tokens/typography.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * SUMI Design System v4.0 — Typography Tokens - * "Lavis d'encre" — Brush calligraphy meets clean sans - * - * Source of truth: apps/web/src/index.css - */ - -export const fontFamilies = { - body: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", - heading: "'Noto Serif JP', Georgia, serif", - mono: "'JetBrains Mono', 'SF Mono', 'Consolas', monospace", - serif: "'Noto Serif JP', Georgia, serif", -} as const; - -export const fontSizes = { - '4xl': '2.25rem', // 36px - '3xl': '1.875rem', // 30px - '2xl': '1.5rem', // 24px - xl: '1.25rem', // 20px - lg: '1.125rem', // 18px - md: '1rem', // 16px - base: '0.875rem', // 14px - sm: '0.8125rem', // 13px - xs: '0.75rem', // 12px -} as const; - -export const lineHeights = { - none: '1', - tight: '1.25', - snug: '1.375', - normal: '1.5', - relaxed: '1.625', - loose: '1.75', -} as const; - -export const letterSpacings = { - tighter: '-0.03em', - tight: '-0.015em', - normal: '0', - wide: '0.025em', - wider: '0.05em', - widest: '0.1em', -} as const; - -export const fontWeights = { - light: 300, - regular: 400, - medium: 500, - semibold: 600, - bold: 700, -} as const; - -export const typography = { - fontFamilies, - fontSizes, - lineHeights, - letterSpacings, - fontWeights, -} as const; diff --git a/packages/design-system/src/utils.ts b/packages/design-system/src/utils.ts deleted file mode 100644 index 96b19bd79..000000000 --- a/packages/design-system/src/utils.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * SUMI Design System — Utility Functions - * - * Canonical implementation of cn() for merging Tailwind classes. - * Also available at apps/web/src/lib/utils.ts. - */ - -import { type ClassValue, clsx } from 'clsx'; -import { twMerge } from 'tailwind-merge'; - -/** - * Merge Tailwind CSS classes with deduplication. - * Combines clsx (conditional classes) + tailwind-merge (conflict resolution). - * - * @example - * cn('px-4 py-2', isActive && 'bg-primary', className) - */ -export function cn(...inputs: ClassValue[]): string { - return twMerge(clsx(inputs)); -} diff --git a/packages/design-system/style-dictionary.config.mjs b/packages/design-system/style-dictionary.config.mjs new file mode 100644 index 000000000..21241e122 --- /dev/null +++ b/packages/design-system/style-dictionary.config.mjs @@ -0,0 +1,121 @@ +/** + * 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'); diff --git a/packages/design-system/tokens/primitive/color.json b/packages/design-system/tokens/primitive/color.json new file mode 100644 index 000000000..f000e6e80 --- /dev/null +++ b/packages/design-system/tokens/primitive/color.json @@ -0,0 +1,74 @@ +{ + "color": { + "ink": { + "kuro": { "$value": "#0A0A0C", "$type": "color", "$description": "黒 — pure black, deepest void" }, + "sumi": { "$value": "#1A1A1E", "$type": "color", "$description": "墨 — ink, dense black" }, + "usuzumi": { "$value": "#3D3A35", "$type": "color", "$description": "薄墨 — light ink" }, + "hai": { "$value": "#6B6660", "$type": "color", "$description": "灰 — ash" }, + "gin": { "$value": "#9A958D", "$type": "color", "$description": "銀 — silver" }, + "kasumi": { "$value": "#B5B0A8", "$type": "color", "$description": "霞 — mist" } + }, + "washi": { + "shiro": { "$value": "#F2EDE6", "$type": "color", "$description": "白 — washi paper, warm white (charte canonique)" }, + "kinari": { "$value": "#E8E3DB", "$type": "color", "$description": "生成 — undyed cream" }, + "kinu": { "$value": "#DDD4C0", "$type": "color", "$description": "絹 — silk" }, + "torinoko": { "$value": "#D0C5AD", "$type": "color", "$description": "鳥の子 — torinoko paper" }, + "cha": { "$value": "#C4B698", "$type": "color", "$description": "茶 — tea" } + }, + "void": { + "base": { "$value": "#0D0D0F", "$type": "color", "$description": "Dark theme paper — deep ink" }, + "raised": { "$value": "#141416", "$type": "color" }, + "overlay":{ "$value": "#1A1A1E", "$type": "color" }, + "hover": { "$value": "#222226", "$type": "color" }, + "active": { "$value": "#2A2A2F", "$type": "color" }, + "wash": { "$value": "#111113", "$type": "color" }, + "inset": { "$value": "#0B0B0D", "$type": "color" }, + "subtle": { "$value": "#161618", "$type": "color" } + }, + "mizu": { + "base": { "$value": "#0098B5", "$type": "color", "$description": "水 — mizu cyan, the SOLE accent (charte §4.1)" }, + "hover": { "$value": "#00B4D8", "$type": "color" }, + "active": { "$value": "#007A94", "$type": "color" }, + "deep": { "$value": "#006B7F", "$type": "color", "$description": "Cyan profond — for normal text WCAG AA" }, + "muted": { "$value": "rgba(0,152,181, 0.18)", "$type": "color" }, + "subtle": { "$value": "rgba(0,152,181, 0.06)", "$type": "color" }, + "focus": { "$value": "rgba(0,152,181, 0.50)", "$type": "color" }, + "border": { "$value": "rgba(0,152,181, 0.25)", "$type": "color" } + }, + "kin": { + "base": { "$value": "#b8860b", "$type": "color", "$description": "金 — gold leaf, decorative only" }, + "hover": { "$value": "#c8960b", "$type": "color" }, + "subtle": { "$value": "rgba(184,134,11, 0.08)", "$type": "color" } + }, + "viz": { + "_comment": "Data viz palette ONLY (charts, waveforms, analytics). Forbidden in standard UI per CHARTE_GRAPHIQUE_TALAS §4.5", + "indigo": { "$value": "#7c9dd6", "$type": "color", "$description": "Data viz pigment — indigo" }, + "vermillion": { "$value": "#d4634a", "$type": "color", "$description": "Data viz pigment — vermillion" }, + "sage": { "$value": "#7a9e6c", "$type": "color", "$description": "Data viz pigment — sage" }, + "gold": { "$value": "#c9a84c", "$type": "color", "$description": "Data viz pigment — gold" }, + "neutral": { "$value": "#a8a4a0", "$type": "color", "$description": "Data viz pigment — neutral grey" } + }, + "functional": { + "_comment": "Functional colors are ALWAYS diluted (max 60% opacity). Never as solid fill (charte §4.2)", + "sage-diluted": { "$value": "rgba(90,140,100, 0.60)", "$type": "color", "$description": "Success — vert sauge dilué" }, + "sage-hover": { "$value": "rgba(90,140,100, 0.70)", "$type": "color" }, + "sage-subtle": { "$value": "rgba(90,140,100, 0.10)", "$type": "color" }, + "brick-diluted": { "$value": "rgba(180,80,70, 0.55)", "$type": "color", "$description": "Error — rouge brique dilué" }, + "brick-hover": { "$value": "rgba(180,80,70, 0.65)", "$type": "color" }, + "brick-subtle": { "$value": "rgba(180,80,70, 0.10)", "$type": "color" }, + "amber-diluted": { "$value": "rgba(190,150,60, 0.55)", "$type": "color", "$description": "Warning — ambre dilué" }, + "amber-hover": { "$value": "rgba(190,150,60, 0.65)", "$type": "color" }, + "amber-subtle": { "$value": "rgba(190,150,60, 0.10)", "$type": "color" } + }, + "alpha": { + "ink-04": { "$value": "rgba(26,26,30, 0.04)", "$type": "color", "$description": "Ink wash — surface card" }, + "ink-06": { "$value": "rgba(26,26,30, 0.06)", "$type": "color" }, + "ink-08": { "$value": "rgba(26,26,30, 0.08)", "$type": "color" }, + "ink-12": { "$value": "rgba(26,26,30, 0.12)", "$type": "color" }, + "ink-20": { "$value": "rgba(26,26,30, 0.20)", "$type": "color" }, + "ivory-03":{ "$value": "rgba(232,227,219, 0.03)", "$type": "color", "$description": "Ivory border — faint" }, + "ivory-06":{ "$value": "rgba(232,227,219, 0.06)", "$type": "color" }, + "ivory-10":{ "$value": "rgba(232,227,219, 0.10)", "$type": "color" } + } + } +} diff --git a/packages/design-system/tokens/primitive/elevation.json b/packages/design-system/tokens/primitive/elevation.json new file mode 100644 index 000000000..e07928a7b --- /dev/null +++ b/packages/design-system/tokens/primitive/elevation.json @@ -0,0 +1,29 @@ +{ + "shadow": { + "_comment": "Diffusions d'encre (滲み) — JAMAIS de border 1px solid (charte §7.3)", + "xs": { "$value": "0 1px 3px rgba(13,13,11,0.20)", "$type": "shadow" }, + "sm": { "$value": "0 2px 8px rgba(13,13,11,0.15), 0 1px 3px rgba(13,13,11,0.12)", "$type": "shadow" }, + "md": { "$value": "0 4px 20px rgba(13,13,11,0.15), 0 2px 6px rgba(13,13,11,0.10)", "$type": "shadow" }, + "lg": { "$value": "0 8px 35px rgba(13,13,11,0.18), 0 4px 12px rgba(13,13,11,0.10)", "$type": "shadow" }, + "xl": { "$value": "0 16px 55px rgba(13,13,11,0.22), 0 8px 20px rgba(13,13,11,0.12)", "$type": "shadow" }, + "2xl": { "$value": "0 24px 75px rgba(13,13,11,0.30)", "$type": "shadow" }, + "ink": { "$value": "0 0 6px rgba(26,26,30, 0.06)", "$type": "shadow", "$description": "Diffusion d'encre — remplace border" }, + "glow": { "$value": "0 0 0 3px rgba(0,152,181, 0.20)", "$type": "shadow", "$description": "Focus ring cyan" }, + "kin": { "$value": "0 0 16px rgba(184,134,11, 0.15)", "$type": "shadow" } + }, + "blur": { + "_comment": "Couches d'encre (charte §7.2) — backdrop-filter croissant par élévation", + "surface": { "$value": "8px", "$type": "dimension", "$description": "Surface cards" }, + "overlay": { "$value": "16px", "$type": "dimension", "$description": "Dropdowns, menus" }, + "modal": { "$value": "24px", "$type": "dimension", "$description": "Modales" }, + "suzuri": { "$value": "32px", "$type": "dimension", "$description": "Player audio (硯 — pierre à encre)" } + }, + "opacity": { + "_comment": "Opacités d'encre par élévation", + "surface": { "$value": "0.06", "$type": "number" }, + "overlay": { "$value": "0.10", "$type": "number" }, + "modal": { "$value": "0.16", "$type": "number" }, + "suzuri": { "$value": "0.25", "$type": "number" }, + "grain": { "$value": "0.04", "$type": "number", "$description": "Grain washi standard" } + } +} diff --git a/packages/design-system/tokens/primitive/motion.json b/packages/design-system/tokens/primitive/motion.json new file mode 100644 index 000000000..995da2ef3 --- /dev/null +++ b/packages/design-system/tokens/primitive/motion.json @@ -0,0 +1,20 @@ +{ + "motion": { + "_comment": "Le poids de l'eau (charte §3) — 5 niveaux de masse, max 2 animations simultanées", + "duration": { + "goutte": { "$value": "100ms", "$type": "duration", "$description": "滴 — drop : tooltips, badges" }, + "trait": { "$value": "150ms", "$type": "duration", "$description": "筆 — stroke : boutons, icônes" }, + "lavis": { "$value": "250ms", "$type": "duration", "$description": "墨 — wash : cards, dropdowns" }, + "vague": { "$value": "350ms", "$type": "duration", "$description": "波 — wave : modales, sidebars" }, + "maree": { "$value": "450ms", "$type": "duration", "$description": "潮 — tide : navigation, player" } + }, + "ease": { + "goutte": { "$value": "cubic-bezier(0.25, 0.1, 0.25, 1)", "$type": "cubicBezier" }, + "trait": { "$value": "cubic-bezier(0.33, 1, 0.68, 1)", "$type": "cubicBezier", "$description": "Rebond léger" }, + "lavis": { "$value": "cubic-bezier(0.25, 0.8, 0.25, 1)", "$type": "cubicBezier" }, + "vague": { "$value": "cubic-bezier(0.16, 1, 0.3, 1)", "$type": "cubicBezier" }, + "maree": { "$value": "cubic-bezier(0.33, 1, 0.68, 1)", "$type": "cubicBezier" }, + "rebond": { "$value": "cubic-bezier(0.34, 1.56, 0.64, 1)", "$type": "cubicBezier", "$description": "Rebond marqué — accents" } + } + } +} diff --git a/packages/design-system/tokens/primitive/spacing.json b/packages/design-system/tokens/primitive/spacing.json new file mode 100644 index 000000000..d77cc9c8e --- /dev/null +++ b/packages/design-system/tokens/primitive/spacing.json @@ -0,0 +1,37 @@ +{ + "space": { + "_comment": "Échelle 4px stricte (charte §6 + ORIGIN règle 5). Aucune valeur arbitraire.", + "0": { "$value": "0", "$type": "dimension" }, + "1": { "$value": "0.25rem", "$type": "dimension", "$description": "4px" }, + "2": { "$value": "0.5rem", "$type": "dimension", "$description": "8px" }, + "3": { "$value": "0.75rem", "$type": "dimension", "$description": "12px" }, + "4": { "$value": "1rem", "$type": "dimension", "$description": "16px" }, + "5": { "$value": "1.25rem", "$type": "dimension", "$description": "20px" }, + "6": { "$value": "1.5rem", "$type": "dimension", "$description": "24px" }, + "8": { "$value": "2rem", "$type": "dimension", "$description": "32px" }, + "10": { "$value": "2.5rem", "$type": "dimension", "$description": "40px" }, + "12": { "$value": "3rem", "$type": "dimension", "$description": "48px" }, + "16": { "$value": "4rem", "$type": "dimension", "$description": "64px" }, + "20": { "$value": "5rem", "$type": "dimension", "$description": "80px" }, + "24": { "$value": "6rem", "$type": "dimension", "$description": "96px" } + }, + "radius": { + "none": { "$value": "0", "$type": "dimension" }, + "sm": { "$value": "0.25rem", "$type": "dimension" }, + "md": { "$value": "0.5rem", "$type": "dimension" }, + "lg": { "$value": "0.75rem", "$type": "dimension" }, + "xl": { "$value": "1rem", "$type": "dimension" }, + "full": { "$value": "9999px", "$type": "dimension" } + }, + "z": { + "base": { "$value": "0", "$type": "number" }, + "raised": { "$value": "10", "$type": "number" }, + "sticky": { "$value": "100", "$type": "number" }, + "header": { "$value": "200", "$type": "number" }, + "drawer": { "$value": "300", "$type": "number" }, + "modal": { "$value": "400", "$type": "number" }, + "popover": { "$value": "500", "$type": "number" }, + "toast": { "$value": "600", "$type": "number" }, + "tooltip": { "$value": "700", "$type": "number" } + } +} diff --git a/packages/design-system/tokens/primitive/typography.json b/packages/design-system/tokens/primitive/typography.json new file mode 100644 index 000000000..da1e1bc11 --- /dev/null +++ b/packages/design-system/tokens/primitive/typography.json @@ -0,0 +1,42 @@ +{ + "font": { + "family": { + "heading": { "$value": "'Space Grotesk', system-ui, sans-serif", "$type": "fontFamily", "$description": "Titres — MAJUSCULES, letter-spacing 0.10-0.15em" }, + "body": { "$value": "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", "$type": "fontFamily" }, + "mono": { "$value": "'JetBrains Mono', 'SF Mono', 'Consolas', monospace", "$type": "fontFamily", "$description": "Code et specs techniques uniquement" } + }, + "weight": { + "regular": { "$value": 400, "$type": "fontWeight" }, + "medium": { "$value": 500, "$type": "fontWeight" }, + "semibold": { "$value": 600, "$type": "fontWeight" }, + "bold": { "$value": 700, "$type": "fontWeight" } + }, + "size": { + "xs": { "$value": "0.75rem", "$type": "dimension" }, + "sm": { "$value": "0.8125rem", "$type": "dimension" }, + "base": { "$value": "0.875rem", "$type": "dimension" }, + "md": { "$value": "1rem", "$type": "dimension" }, + "lg": { "$value": "1.125rem", "$type": "dimension" }, + "xl": { "$value": "1.25rem", "$type": "dimension" }, + "2xl": { "$value": "1.5rem", "$type": "dimension" }, + "3xl": { "$value": "1.875rem", "$type": "dimension" }, + "4xl": { "$value": "2.25rem", "$type": "dimension" } + }, + "leading": { + "none": { "$value": "1", "$type": "number" }, + "tight": { "$value": "1.25", "$type": "number" }, + "snug": { "$value": "1.375", "$type": "number" }, + "normal": { "$value": "1.5", "$type": "number" }, + "relaxed": { "$value": "1.625", "$type": "number" }, + "loose": { "$value": "1.7", "$type": "number", "$description": "Corps de texte — interligne charte" } + }, + "tracking": { + "tight": { "$value": "-0.02em", "$type": "dimension" }, + "normal": { "$value": "0", "$type": "dimension" }, + "wide": { "$value": "0.08em", "$type": "dimension" }, + "wider": { "$value": "0.10em", "$type": "dimension", "$description": "H3 charte" }, + "widest": { "$value": "0.12em", "$type": "dimension", "$description": "H2 charte" }, + "huge": { "$value": "0.15em", "$type": "dimension", "$description": "H1 charte" } + } + } +} diff --git a/packages/design-system/tokens/semantic/dark.json b/packages/design-system/tokens/semantic/dark.json new file mode 100644 index 000000000..967f2ca78 --- /dev/null +++ b/packages/design-system/tokens/semantic/dark.json @@ -0,0 +1,69 @@ +{ + "sumi": { + "_comment": "Semantic tokens — dark theme (default :root). Tous les refs pointent vers tokens/primitive/.", + "bg": { + "void": { "$value": "{color.void.base}", "$type": "color" }, + "base": { "$value": "{color.void.base}", "$type": "color" }, + "raised": { "$value": "{color.void.raised}", "$type": "color" }, + "overlay": { "$value": "{color.void.overlay}", "$type": "color" }, + "hover": { "$value": "{color.void.hover}", "$type": "color" }, + "active": { "$value": "{color.void.active}", "$type": "color" }, + "wash": { "$value": "{color.void.wash}", "$type": "color" } + }, + "surface": { + "inset": { "$value": "{color.void.inset}", "$type": "color" }, + "subtle": { "$value": "{color.void.subtle}", "$type": "color" }, + "card": { "$value": "{color.void.raised}", "$type": "color" }, + "elevated": { "$value": "{color.void.overlay}", "$type": "color" } + }, + "border": { + "faint": { "$value": "{color.alpha.ivory-03}", "$type": "color" }, + "default": { "$value": "{color.alpha.ivory-06}", "$type": "color" }, + "strong": { "$value": "{color.alpha.ivory-10}", "$type": "color" }, + "focus": { "$value": "{color.mizu.focus}", "$type": "color" }, + "accent": { "$value": "{color.mizu.border}", "$type": "color" } + }, + "text": { + "primary": { "$value": "{color.washi.kinari}", "$type": "color" }, + "secondary": { "$value": "{color.ink.gin}", "$type": "color" }, + "tertiary": { "$value": "{color.ink.hai}", "$type": "color" }, + "disabled": { "$value": "{color.ink.usuzumi}", "$type": "color" }, + "inverse": { "$value": "{color.washi.shiro}", "$type": "color" }, + "link": { "$value": "{color.mizu.base}", "$type": "color" } + }, + "accent": { + "default": { "$value": "{color.mizu.base}", "$type": "color" }, + "hover": { "$value": "{color.mizu.hover}", "$type": "color" }, + "active": { "$value": "{color.mizu.active}", "$type": "color" }, + "muted": { "$value": "{color.mizu.muted}", "$type": "color" }, + "subtle": { "$value": "{color.mizu.subtle}", "$type": "color" }, + "emphasis": { "$value": "{color.mizu.deep}", "$type": "color", "$description": "Pour texte normal AA" } + }, + "viz": { + "_comment": "Data viz uniquement (charts, waveforms, analytics)", + "indigo": { "$value": "{color.viz.indigo}", "$type": "color" }, + "vermillion": { "$value": "{color.viz.vermillion}", "$type": "color" }, + "sage": { "$value": "{color.viz.sage}", "$type": "color" }, + "gold": { "$value": "{color.viz.gold}", "$type": "color" }, + "neutral": { "$value": "{color.viz.neutral}", "$type": "color" } + }, + "feedback": { + "success": { "$value": "{color.functional.sage-diluted}", "$type": "color" }, + "success-hover": { "$value": "{color.functional.sage-hover}", "$type": "color" }, + "success-subtle": { "$value": "{color.functional.sage-subtle}", "$type": "color" }, + "error": { "$value": "{color.functional.brick-diluted}", "$type": "color" }, + "error-hover": { "$value": "{color.functional.brick-hover}", "$type": "color" }, + "error-subtle": { "$value": "{color.functional.brick-subtle}", "$type": "color" }, + "warning": { "$value": "{color.functional.amber-diluted}", "$type": "color" }, + "warning-hover": { "$value": "{color.functional.amber-hover}", "$type": "color" }, + "warning-subtle": { "$value": "{color.functional.amber-subtle}", "$type": "color" }, + "info": { "$value": "{color.mizu.base}", "$type": "color" } + }, + "kin": { + "base": { "$value": "{color.kin.base}", "$type": "color" }, + "hover": { "$value": "{color.kin.hover}", "$type": "color" }, + "subtle": { "$value": "{color.kin.subtle}", "$type": "color" }, + "glow": { "$value": "{shadow.kin}", "$type": "shadow" } + } + } +} diff --git a/packages/design-system/tokens/semantic/light.json b/packages/design-system/tokens/semantic/light.json new file mode 100644 index 000000000..5e70c8e15 --- /dev/null +++ b/packages/design-system/tokens/semantic/light.json @@ -0,0 +1,68 @@ +{ + "sumi": { + "_comment": "Semantic tokens — light theme ([data-theme=\"light\"]). Washi paper aesthetic.", + "bg": { + "void": { "$value": "{color.washi.shiro}", "$type": "color" }, + "base": { "$value": "{color.washi.shiro}", "$type": "color" }, + "raised": { "$value": "{color.washi.shiro}", "$type": "color" }, + "overlay": { "$value": "{color.washi.kinari}", "$type": "color" }, + "hover": { "$value": "{color.washi.kinari}", "$type": "color" }, + "active": { "$value": "{color.washi.kinu}", "$type": "color" }, + "wash": { "$value": "{color.washi.kinari}", "$type": "color" } + }, + "surface": { + "inset": { "$value": "{color.washi.kinari}", "$type": "color" }, + "subtle": { "$value": "{color.washi.shiro}", "$type": "color" }, + "card": { "$value": "{color.washi.shiro}", "$type": "color" }, + "elevated": { "$value": "{color.washi.shiro}", "$type": "color" } + }, + "border": { + "faint": { "$value": "{color.alpha.ink-04}", "$type": "color" }, + "default": { "$value": "{color.alpha.ink-06}", "$type": "color" }, + "strong": { "$value": "{color.alpha.ink-12}", "$type": "color" }, + "focus": { "$value": "{color.mizu.focus}", "$type": "color" }, + "accent": { "$value": "{color.mizu.border}", "$type": "color" } + }, + "text": { + "primary": { "$value": "{color.ink.sumi}", "$type": "color" }, + "secondary": { "$value": "{color.ink.gin}", "$type": "color" }, + "tertiary": { "$value": "{color.ink.hai}", "$type": "color" }, + "disabled": { "$value": "{color.ink.kasumi}", "$type": "color" }, + "inverse": { "$value": "{color.washi.kinari}", "$type": "color" }, + "link": { "$value": "{color.mizu.deep}", "$type": "color", "$description": "Cyan profond pour AA en mode jour" } + }, + "accent": { + "default": { "$value": "{color.mizu.base}", "$type": "color" }, + "hover": { "$value": "{color.mizu.active}", "$type": "color" }, + "active": { "$value": "{color.mizu.deep}", "$type": "color" }, + "muted": { "$value": "{color.mizu.muted}", "$type": "color" }, + "subtle": { "$value": "{color.mizu.subtle}", "$type": "color" }, + "emphasis": { "$value": "{color.mizu.deep}", "$type": "color" } + }, + "viz": { + "indigo": { "$value": "{color.viz.indigo}", "$type": "color" }, + "vermillion": { "$value": "{color.viz.vermillion}", "$type": "color" }, + "sage": { "$value": "{color.viz.sage}", "$type": "color" }, + "gold": { "$value": "{color.viz.gold}", "$type": "color" }, + "neutral": { "$value": "{color.viz.neutral}", "$type": "color" } + }, + "feedback": { + "success": { "$value": "{color.functional.sage-diluted}", "$type": "color" }, + "success-hover": { "$value": "{color.functional.sage-hover}", "$type": "color" }, + "success-subtle": { "$value": "{color.functional.sage-subtle}", "$type": "color" }, + "error": { "$value": "{color.functional.brick-diluted}", "$type": "color" }, + "error-hover": { "$value": "{color.functional.brick-hover}", "$type": "color" }, + "error-subtle": { "$value": "{color.functional.brick-subtle}", "$type": "color" }, + "warning": { "$value": "{color.functional.amber-diluted}", "$type": "color" }, + "warning-hover": { "$value": "{color.functional.amber-hover}", "$type": "color" }, + "warning-subtle": { "$value": "{color.functional.amber-subtle}", "$type": "color" }, + "info": { "$value": "{color.mizu.base}", "$type": "color" } + }, + "kin": { + "base": { "$value": "{color.kin.base}", "$type": "color" }, + "hover": { "$value": "{color.kin.hover}", "$type": "color" }, + "subtle": { "$value": "{color.kin.subtle}", "$type": "color" }, + "glow": { "$value": "{shadow.kin}", "$type": "shadow" } + } + } +} diff --git a/turbo.json b/turbo.json index b339a06bd..9070a6587 100644 --- a/turbo.json +++ b/turbo.json @@ -3,7 +3,13 @@ "tasks": { "build": { "dependsOn": ["^build"], - "outputs": ["dist/**", ".next/**", "!.next/cache/**"] + "outputs": ["dist/**", ".next/**", "!.next/cache/**"], + "inputs": [ + "src/**", + "tokens/**", + "*.config.*", + "package.json" + ] }, "test": { "dependsOn": [],