1import {
2 SingleBoxShadowToken,
3 SingleColorToken,
4 SingleOtherToken,
5 TokenTypes,
6} from "@tokens-studio/types"
7import {
8 Shadow,
9 SyntaxHighlightStyle,
10 ThemeSyntax,
11} from "../create_theme"
12import { LayerToken, layer_token } from "./layer"
13import { PlayersToken, players_token } from "./players"
14import { color_token } from "./token"
15import { Syntax } from "../syntax"
16import editor from "../../style_tree/editor"
17import { useTheme } from "../../../src/common"
18
19interface ThemeTokens {
20 name: SingleOtherToken
21 appearance: SingleOtherToken
22 lowest: LayerToken
23 middle: LayerToken
24 highest: LayerToken
25 players: PlayersToken
26 popover_shadow: SingleBoxShadowToken
27 modal_shadow: SingleBoxShadowToken
28 syntax?: Partial<ThemeSyntaxColorTokens>
29}
30
31const create_shadow_token = (
32 shadow: Shadow,
33 token_name: string
34): SingleBoxShadowToken => {
35 return {
36 name: token_name,
37 type: TokenTypes.BOX_SHADOW,
38 value: `${shadow.offset[0]}px ${shadow.offset[1]}px ${shadow.blur}px 0px ${shadow.color}`,
39 }
40}
41
42const popover_shadow_token = (): SingleBoxShadowToken => {
43 const theme = useTheme()
44 const shadow = theme.popover_shadow
45 return create_shadow_token(shadow, "popover_shadow")
46}
47
48const modal_shadow_token = (): SingleBoxShadowToken => {
49 const theme = useTheme()
50 const shadow = theme.modal_shadow
51 return create_shadow_token(shadow, "modal_shadow")
52}
53
54type ThemeSyntaxColorTokens = Record<keyof ThemeSyntax, SingleColorToken>
55
56function syntax_highlight_style_color_tokens(
57 syntax: Syntax
58): ThemeSyntaxColorTokens {
59 const style_keys = Object.keys(syntax) as (keyof Syntax)[]
60
61 return style_keys.reduce((acc, style_key) => {
62 // Hack: The type of a style could be "Function"
63 // This can happen because we have a "constructor" property on the syntax object
64 // and a "constructor" property on the prototype of the syntax object
65 // To work around this just assert that the type of the style is not a function
66 if (!syntax[style_key] || typeof syntax[style_key] === "function")
67 return acc
68 const { color } = syntax[style_key] as Required<SyntaxHighlightStyle>
69 return { ...acc, [style_key]: color_token(style_key, color) }
70 }, {} as ThemeSyntaxColorTokens)
71}
72
73const syntax_tokens = (): ThemeTokens["syntax"] => {
74 const syntax = editor().syntax
75
76 return syntax_highlight_style_color_tokens(syntax)
77}
78
79export function theme_tokens(): ThemeTokens {
80 const theme = useTheme()
81
82 return {
83 name: {
84 name: "themeName",
85 value: theme.name,
86 type: TokenTypes.OTHER,
87 },
88 appearance: {
89 name: "themeAppearance",
90 value: theme.is_light ? "light" : "dark",
91 type: TokenTypes.OTHER,
92 },
93 lowest: layer_token(theme.lowest, "lowest"),
94 middle: layer_token(theme.middle, "middle"),
95 highest: layer_token(theme.highest, "highest"),
96 popover_shadow: popover_shadow_token(),
97 modal_shadow: modal_shadow_token(),
98 players: players_token(),
99 syntax: syntax_tokens(),
100 }
101}