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}