/** * Complete set of Figma token names (slash-separated format). * Source: design-system discussion #1689 */ const FIGMA_TOKENS: string[] = [ // Primitive colors 'color/grey/0', 'color/grey/50', 'color/grey/100', 'color/grey/200', 'color/grey/300', 'color/grey/400', 'color/grey/500', 'color/grey/600', 'color/grey/700', 'color/grey/800', 'color/grey/900', 'color/opacity/grey/018', 'color/pink/50', 'color/pink/100', 'color/pink/200', 'color/pink/300', 'color/pink/400', 'color/pink/500', 'color/pink/600', 'color/pink/700', 'color/pink/800', 'color/yellow/50', 'color/yellow/100', 'color/yellow/200', 'color/yellow/300', 'color/yellow/400', 'color/yellow/500', 'color/yellow/600', 'color/yellow/700', 'color/yellow/800', 'color/blue/50', 'color/blue/100', 'color/blue/200', 'color/blue/300', 'color/blue/400', 'color/blue/500', 'color/blue/600', 'color/blue/700', 'color/blue/800', 'color/teal/50', 'color/teal/100', 'color/teal/200', 'color/teal/300', 'color/teal/400', 'color/teal/500', 'color/teal/600', 'color/teal/700', 'color/teal/800', 'color/red/50', 'color/red/100', 'color/red/200', 'color/red/300', 'color/red/400', 'color/red/500', 'color/red/600', 'color/red/700', 'color/red/800', // Primitive spacing/sizing/radius 'spacing/0', 'spacing/1', 'spacing/2', 'spacing/4', 'spacing/6', 'spacing/8', 'spacing/12', 'spacing/16', 'spacing/20', 'spacing/24', 'spacing/32', 'spacing/48', 'spacing/64', 'spacing/96', 'spacing/160', 'sizing/0', 'sizing/1', 'sizing/2', 'sizing/4', 'sizing/8', 'sizing/12', 'sizing/16', 'sizing/20', 'sizing/24', 'sizing/32', 'sizing/40', 'sizing/48', 'sizing/64', 'sizing/96', 'sizing/160', 'radius/0', 'radius/2', 'radius/4', 'radius/8', 'radius/16', 'radius/300', // Semantic color/text 'color/text/primary', 'color/text/secondary', 'color/text/tertiary', 'color/text/accentDark', 'color/text/placeholder', 'color/text/inverted', 'color/text/feedback/positive', 'color/text/feedback/info', 'color/text/feedback/warning', 'color/text/feedback/critical', // Semantic color/icon 'color/icon/primary', 'color/icon/secondary', 'color/icon/tertiary', 'color/icon/inverted', 'color/icon/accentDark', 'color/icon/disabled', 'color/icon/feedback/positive', 'color/icon/feedback/info', 'color/icon/feedback/warning', 'color/icon/feedback/critical', // Semantic color/border 'color/border/primary', 'color/border/secondary', 'color/border/secondaryopacity', 'color/border/tertiary', 'color/border/brand', 'color/border/feedback/focus', 'color/border/feedback/critical', 'color/border/feedback/disabled', 'color/border/feedback/status', // Semantic sizing/icon 'sizing/icon/16', 'sizing/icon/24', 'sizing/icon/32', 'sizing/icon/48', // Semantic borderwidth 'borderwidth/1', 'borderwidth/2', // Semantic color/background 'color/background/primary', 'color/background/secondary', 'color/background/tertiary', 'color/background/brand/brand', 'color/background/brand/accentLight', 'color/background/inverted/primary', 'color/background/inverted/secondary', 'color/background/inverted/tertiary', // Semantic color/foreground 'color/foreground/primary', 'color/foreground/secondary', 'color/foreground/tertiary', 'color/foreground/overlay', 'color/foreground/disabled', 'color/foreground/brand/brand', 'color/foreground/brand/accentLight', 'color/foreground/brand/accentDark', 'color/foreground/inverted/primary', 'color/foreground/inverted/secondary', 'color/foreground/inverted/tertiary', 'color/foreground/feedback/positiveDark', 'color/foreground/feedback/positiveLight', 'color/foreground/feedback/infoDark', 'color/foreground/feedback/infoLight', 'color/foreground/feedback/warningDark', 'color/foreground/feedback/warningLight', 'color/foreground/feedback/criticalDark', 'color/foreground/feedback/criticalLight', 'color/foreground/feedback/statusOnline', 'color/foreground/feedback/statusOffline', // Component button 'button/background/primary/B2C/rest', 'button/background/primary/B2C/hover', 'button/background/primary/B2C/active', 'button/background/primary/B2C/busy', 'button/background/secondary/hover', 'button/background/secondary/active', 'button/background/tertiary/hover', 'button/background/tertiary/active', 'button/background/critical/rest', 'button/background/critical/hover', 'button/background/critical/active', 'button/background/critical/busy', 'button/background/disabled/inactive', 'button/background/ghost/hover', 'button/background/ghost/active', 'button/background/classroom/rest', 'button/background/classroom/hover', 'button/background/classroom/active', 'button/background/classroom/selected', 'button/background/classroom/busy', 'button/background/onColor/rest', 'button/background/onColor/hover', 'button/background/onColor/active', 'button/background/onColor/busy', 'button/background/inverted/hover', 'button/background/inverted/active', 'button/border/primary/rest', 'button/border/primary/hover', 'button/border/primary/active', 'button/border/primary/busy', 'button/border/tertiary/rest', 'button/border/tertiary/hover', 'button/border/tertiary/active', 'button/border/tertiary/busy', 'button/border/critical/rest', 'button/border/critical/hover', 'button/border/critical/active', 'button/border/critical/busy', 'button/border/disabled/default', 'button/border/secondary/rest', 'button/border/secondary/hover', 'button/border/secondary/active', 'button/border/secondary/busy', 'button/border/inverted/rest', 'button/border/inverted/hover', 'button/border/inverted/active', 'button/border/inverted/busy', 'button/border/focus/default', 'button/text/inverted', 'button/text/default', 'button/text/disabled', 'button/radius/8', // Component action 'action/background/hover', 'action/background/active', 'action/border/tertiary', ]; const FIGMA_TOKEN_SET = new Set(FIGMA_TOKENS); /** * Returns the Figma token name for a code token, or undefined if * there's no matching Figma token. * * Mapping rules: * - exp.color.X → color/X (exp prefix stripped) * - color.background.X → also checked as color/foreground/X * - direct dot→slash conversion */ export function getFigmaTokenName(codeTokenName: string): string | undefined { const direct = codeTokenName.replace(/\./g, '/'); if (FIGMA_TOKEN_SET.has(direct)) return direct; // exp.color.* → color/* in Figma if (codeTokenName.startsWith('exp.')) { const stripped = codeTokenName.slice(4).replace(/\./g, '/'); if (FIGMA_TOKEN_SET.has(stripped)) return stripped; } // color.background.* → color/foreground/* in Figma if (codeTokenName.startsWith('color.background.')) { const asForeground = codeTokenName .replace('color.background.', 'color.foreground.') .replace(/\./g, '/'); if (FIGMA_TOKEN_SET.has(asForeground)) return asForeground; } return undefined; } export function isFigmaToken(codeTokenName: string): boolean { return getFigmaTokenName(codeTokenName) !== undefined; }