colorScheme.ts

 1import { SingleBoxShadowToken, SingleColorToken, SingleOtherToken, TokenTypes } from "@tokens-studio/types"
 2import { ColorScheme, Shadow, SyntaxHighlightStyle, ThemeSyntax } from "../colorScheme"
 3import { LayerToken, layerToken } from "./layer"
 4import { PlayersToken, playersToken } from "./players"
 5import { colorToken } from "./token"
 6import { Syntax } from "../syntax";
 7import editor from "../../styleTree/editor"
 8
 9interface ColorSchemeTokens {
10    name: SingleOtherToken
11    appearance: SingleOtherToken
12    lowest: LayerToken
13    middle: LayerToken
14    highest: LayerToken
15    players: PlayersToken
16    popoverShadow: SingleBoxShadowToken
17    modalShadow: SingleBoxShadowToken
18    syntax?: Partial<ThemeSyntaxColorTokens>
19}
20
21const createShadowToken = (shadow: Shadow, tokenName: string): SingleBoxShadowToken => {
22    return {
23        name: tokenName,
24        type: TokenTypes.BOX_SHADOW,
25        value: `${shadow.offset[0]}px ${shadow.offset[1]}px ${shadow.blur}px 0px ${shadow.color}`
26    };
27};
28
29const popoverShadowToken = (colorScheme: ColorScheme): SingleBoxShadowToken => {
30    const shadow = colorScheme.popoverShadow;
31    return createShadowToken(shadow, "popoverShadow");
32};
33
34const modalShadowToken = (colorScheme: ColorScheme): SingleBoxShadowToken => {
35    const shadow = colorScheme.modalShadow;
36    return createShadowToken(shadow, "modalShadow");
37};
38
39type ThemeSyntaxColorTokens = Record<keyof ThemeSyntax, SingleColorToken>
40
41function syntaxHighlightStyleColorTokens(syntax: Syntax): ThemeSyntaxColorTokens {
42    const styleKeys = Object.keys(syntax) as (keyof Syntax)[]
43
44    return styleKeys.reduce((acc, styleKey) => {
45        // Hack: The type of a style could be "Function"
46        // This can happen because we have a "constructor" property on the syntax object
47        // and a "constructor" property on the prototype of the syntax object
48        // To work around this just assert that the type of the style is not a function
49        if (!syntax[styleKey] || typeof syntax[styleKey] === 'function') return acc;
50        const { color } = syntax[styleKey] as Required<SyntaxHighlightStyle>;
51        return { ...acc, [styleKey]: colorToken(styleKey, color) };
52    }, {} as ThemeSyntaxColorTokens);
53}
54
55const syntaxTokens = (colorScheme: ColorScheme): ColorSchemeTokens['syntax'] => {
56    const syntax = editor(colorScheme).syntax
57
58    return syntaxHighlightStyleColorTokens(syntax)
59}
60
61export function colorSchemeTokens(colorScheme: ColorScheme): ColorSchemeTokens {
62    return {
63        name: {
64            name: "themeName",
65            value: colorScheme.name,
66            type: TokenTypes.OTHER,
67        },
68        appearance: {
69            name: "themeAppearance",
70            value: colorScheme.isLight ? "light" : "dark",
71            type: TokenTypes.OTHER,
72        },
73        lowest: layerToken(colorScheme.lowest, "lowest"),
74        middle: layerToken(colorScheme.middle, "middle"),
75        highest: layerToken(colorScheme.highest, "highest"),
76        popoverShadow: popoverShadowToken(colorScheme),
77        modalShadow: modalShadowToken(colorScheme),
78        players: playersToken(colorScheme),
79        syntax: syntaxTokens(colorScheme),
80    }
81}