From 65dbb3892672447af726b5875dc1e529a8b9ccc1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 01:20:56 -0400 Subject: [PATCH] `color_scheme` -> `theme` --- docs/zed/syntax-highlighting.md | 2 +- styles/src/build_themes.ts | 16 ++-- styles/src/build_tokens.ts | 17 ++-- styles/src/component/icon_button.ts | 14 +-- styles/src/component/text_button.ts | 14 +-- styles/src/style_tree/components.ts | 2 +- styles/src/style_tree/editor.ts | 4 +- .../{color_scheme.ts => create_theme.ts} | 4 +- styles/src/theme/index.ts | 10 +-- styles/src/theme/ramps.ts | 2 +- styles/src/theme/syntax.ts | 86 +++++++++---------- styles/src/theme/theme_config.ts | 67 --------------- styles/src/theme/tokens/layer.ts | 2 +- styles/src/theme/tokens/players.ts | 4 +- .../tokens/{color_scheme.ts => theme.ts} | 11 ++- 15 files changed, 93 insertions(+), 162 deletions(-) rename styles/src/theme/{color_scheme.ts => create_theme.ts} (98%) rename styles/src/theme/tokens/{color_scheme.ts => theme.ts} (93%) diff --git a/docs/zed/syntax-highlighting.md b/docs/zed/syntax-highlighting.md index 3878fcc6e9..d4331ee367 100644 --- a/docs/zed/syntax-highlighting.md +++ b/docs/zed/syntax-highlighting.md @@ -35,7 +35,7 @@ Match a property identifier and highlight it using the identifier `@property`. I ``` ```ts -function buildDefaultSyntax(colorScheme: ColorScheme): Partial { +function buildDefaultSyntax(colorScheme: Theme): Partial { // ... } ``` diff --git a/styles/src/build_themes.ts b/styles/src/build_themes.ts index a9cbad94e7..17575663a1 100644 --- a/styles/src/build_themes.ts +++ b/styles/src/build_themes.ts @@ -2,7 +2,7 @@ import * as fs from "fs" import { tmpdir } from "os" import * as path from "path" import app from "./style_tree/app" -import { ColorScheme, create_color_scheme } from "./theme/color_scheme" +import { Theme, create_theme } from "./theme/create_theme" import { themes } from "./themes" import { useThemeStore } from "./theme" @@ -21,22 +21,22 @@ function clear_themes(theme_directory: string) { } } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) +const all_themes: Theme[] = themes.map((theme) => + create_theme(theme) ) -function write_themes(themes: ColorScheme[], output_directory: string) { +function write_themes(themes: Theme[], output_directory: string) { clear_themes(output_directory) - for (const color_scheme of themes) { + for (const theme of themes) { const { setTheme } = useThemeStore.getState() - setTheme(color_scheme) + setTheme(theme) const style_tree = app() const style_tree_json = JSON.stringify(style_tree, null, 2) - const temp_path = path.join(temp_directory, `${color_scheme.name}.json`) + const temp_path = path.join(temp_directory, `${theme.name}.json`) const out_path = path.join( output_directory, - `${color_scheme.name}.json` + `${theme.name}.json` ) fs.writeFileSync(temp_path, style_tree_json) fs.renameSync(temp_path, out_path) diff --git a/styles/src/build_tokens.ts b/styles/src/build_tokens.ts index f51e5eb6cf..fd6aa18ced 100644 --- a/styles/src/build_tokens.ts +++ b/styles/src/build_tokens.ts @@ -1,9 +1,9 @@ import * as fs from "fs" import * as path from "path" -import { ColorScheme, create_color_scheme } from "./common" +import { Theme, create_theme, useThemeStore } from "./common" import { themes } from "./themes" import { slugify } from "./utils/slugify" -import { theme_tokens } from "./theme/tokens/color_scheme" +import { theme_tokens } from "./theme/tokens/theme" const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens") const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json") @@ -27,7 +27,7 @@ type TokenSet = { selected_token_sets: { [key: string]: "enabled" } } -function build_token_set_order(theme: ColorScheme[]): { +function build_token_set_order(theme: Theme[]): { token_set_order: string[] } { const token_set_order: string[] = theme.map((scheme) => @@ -36,7 +36,7 @@ function build_token_set_order(theme: ColorScheme[]): { return { token_set_order } } -function build_themes_index(theme: ColorScheme[]): TokenSet[] { +function build_themes_index(theme: Theme[]): TokenSet[] { const themes_index: TokenSet[] = theme.map((scheme, index) => { const id = `${scheme.is_light ? "light" : "dark"}_${scheme.name .toLowerCase() @@ -55,10 +55,13 @@ function build_themes_index(theme: ColorScheme[]): TokenSet[] { return themes_index } -function write_tokens(themes: ColorScheme[], tokens_directory: string) { +function write_tokens(themes: Theme[], tokens_directory: string) { clear_tokens(tokens_directory) for (const theme of themes) { + const { setTheme } = useThemeStore.getState() + setTheme(theme) + const file_name = slugify(theme.name) + ".json" const tokens = theme_tokens() const tokens_json = JSON.stringify(tokens, null, 2) @@ -80,8 +83,8 @@ function write_tokens(themes: ColorScheme[], tokens_directory: string) { console.log(`- ${METADATA_FILE} created`) } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) +const all_themes: Theme[] = themes.map((theme) => + create_theme(theme) ) write_tokens(all_themes, TOKENS_DIRECTORY) diff --git a/styles/src/component/icon_button.ts b/styles/src/component/icon_button.ts index 18b900e833..6887fc7c30 100644 --- a/styles/src/component/icon_button.ts +++ b/styles/src/component/icon_button.ts @@ -1,6 +1,6 @@ import { interactive, toggleable } from "../element" import { background, foreground } from "../style_tree/components" -import { useTheme, ColorScheme } from "../theme" +import { useTheme, Theme } from "../theme" export type Margin = { top: number @@ -11,15 +11,15 @@ export type Margin = { interface IconButtonOptions { layer?: - | ColorScheme["lowest"] - | ColorScheme["middle"] - | ColorScheme["highest"] - color?: keyof ColorScheme["lowest"] + | Theme["lowest"] + | Theme["middle"] + | Theme["highest"] + color?: keyof Theme["lowest"] margin?: Partial } type ToggleableIconButtonOptions = IconButtonOptions & { - active_color?: keyof ColorScheme["lowest"] + active_color?: keyof Theme["lowest"] } export function icon_button({ color, margin, layer }: IconButtonOptions) { @@ -67,7 +67,7 @@ export function icon_button({ color, margin, layer }: IconButtonOptions) { } export function toggleable_icon_button( - theme: ColorScheme, + theme: Theme, { color, active_color, margin }: ToggleableIconButtonOptions ) { if (!color) color = "base" diff --git a/styles/src/component/text_button.ts b/styles/src/component/text_button.ts index 50737f9766..58b2a1cbf2 100644 --- a/styles/src/component/text_button.ts +++ b/styles/src/component/text_button.ts @@ -5,21 +5,21 @@ import { foreground, text, } from "../style_tree/components" -import { useTheme, ColorScheme } from "../theme" +import { useTheme, Theme } from "../theme" import { Margin } from "./icon_button" interface TextButtonOptions { layer?: - | ColorScheme["lowest"] - | ColorScheme["middle"] - | ColorScheme["highest"] - color?: keyof ColorScheme["lowest"] + | Theme["lowest"] + | Theme["middle"] + | Theme["highest"] + color?: keyof Theme["lowest"] margin?: Partial text_properties?: TextProperties } type ToggleableTextButtonOptions = TextButtonOptions & { - active_color?: keyof ColorScheme["lowest"] + active_color?: keyof Theme["lowest"] } export function text_button({ @@ -75,7 +75,7 @@ export function text_button({ } export function toggleable_text_button( - theme: ColorScheme, + theme: Theme, { color, active_color, margin }: ToggleableTextButtonOptions ) { if (!color) color = "base" diff --git a/styles/src/style_tree/components.ts b/styles/src/style_tree/components.ts index db32712f41..43a5fa9d28 100644 --- a/styles/src/style_tree/components.ts +++ b/styles/src/style_tree/components.ts @@ -1,5 +1,5 @@ import { font_families, font_sizes, FontWeight } from "../common" -import { Layer, Styles, StyleSets, Style } from "../theme/color_scheme" +import { Layer, Styles, StyleSets, Style } from "../theme/create_theme" function is_style_set(key: any): key is StyleSets { return [ diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index 31fa86110d..a2fec11642 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -1,5 +1,5 @@ import { with_opacity } from "../theme/color" -import { Layer, StyleSets } from "../theme/color_scheme" +import { Layer, StyleSets } from "../theme/create_theme" import { background, border, @@ -48,7 +48,7 @@ export default function editor(): any { } } - const syntax = build_syntax(theme) + const syntax = build_syntax() return { text_color: syntax.primary.color, diff --git a/styles/src/theme/color_scheme.ts b/styles/src/theme/create_theme.ts similarity index 98% rename from styles/src/theme/color_scheme.ts rename to styles/src/theme/create_theme.ts index 933c616053..dff4c3dbc4 100644 --- a/styles/src/theme/color_scheme.ts +++ b/styles/src/theme/create_theme.ts @@ -8,7 +8,7 @@ import { } from "./theme_config" import { get_ramps } from "./ramps" -export interface ColorScheme { +export interface Theme { name: string is_light: boolean @@ -105,7 +105,7 @@ export interface Style { foreground: string } -export function create_color_scheme(theme: ThemeConfig): ColorScheme { +export function create_theme(theme: ThemeConfig): Theme { const { name, appearance, diff --git a/styles/src/theme/index.ts b/styles/src/theme/index.ts index 100248b1a8..ca8aaa461f 100644 --- a/styles/src/theme/index.ts +++ b/styles/src/theme/index.ts @@ -1,9 +1,9 @@ import { create } from "zustand" -import { ColorScheme } from "./color_scheme" +import { Theme } from "./create_theme" type ThemeState = { - theme: ColorScheme | undefined - setTheme: (theme: ColorScheme) => void + theme: Theme | undefined + setTheme: (theme: Theme) => void } export const useThemeStore = create((set) => ({ @@ -11,7 +11,7 @@ export const useThemeStore = create((set) => ({ setTheme: (theme) => set(() => ({ theme })), })) -export const useTheme = (): ColorScheme => { +export const useTheme = (): Theme => { const { theme } = useThemeStore.getState() if (!theme) throw new Error("Tried to use theme before it was loaded") @@ -19,7 +19,7 @@ export const useTheme = (): ColorScheme => { return theme } -export * from "./color_scheme" +export * from "./create_theme" export * from "./ramps" export * from "./syntax" export * from "./theme_config" diff --git a/styles/src/theme/ramps.ts b/styles/src/theme/ramps.ts index 118d0c7274..c5b915a8c5 100644 --- a/styles/src/theme/ramps.ts +++ b/styles/src/theme/ramps.ts @@ -1,5 +1,5 @@ import chroma, { Color, Scale } from "chroma-js" -import { RampSet } from "./color_scheme" +import { RampSet } from "./create_theme" import { ThemeConfigInputColors, ThemeConfigInputColorsKeys, diff --git a/styles/src/theme/syntax.ts b/styles/src/theme/syntax.ts index c0d68e418e..540a1d0ff9 100644 --- a/styles/src/theme/syntax.ts +++ b/styles/src/theme/syntax.ts @@ -1,6 +1,5 @@ import deepmerge from "deepmerge" -import { FontWeight, font_weights } from "../common" -import { ColorScheme } from "./color_scheme" +import { FontWeight, font_weights, useTheme } from "../common" import chroma from "chroma-js" export interface SyntaxHighlightStyle { @@ -123,7 +122,9 @@ const default_syntax_highlight_style: Omit = { italic: false, } -function build_default_syntax(color_scheme: ColorScheme): Syntax { +function build_default_syntax(): Syntax { + const theme = useTheme() + // Make a temporary object that is allowed to be missing // the "color" property for each style const syntax: { @@ -141,8 +142,8 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { // predictive color distinct from any other color in the theme const predictive = chroma .mix( - color_scheme.ramps.neutral(0.4).hex(), - color_scheme.ramps.blue(0.4).hex(), + theme.ramps.neutral(0.4).hex(), + theme.ramps.blue(0.4).hex(), 0.45, "lch" ) @@ -151,32 +152,32 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { // hint color distinct from any other color in the theme const hint = chroma .mix( - color_scheme.ramps.neutral(0.6).hex(), - color_scheme.ramps.blue(0.4).hex(), + theme.ramps.neutral(0.6).hex(), + theme.ramps.blue(0.4).hex(), 0.45, "lch" ) .hex() const color = { - primary: color_scheme.ramps.neutral(1).hex(), - comment: color_scheme.ramps.neutral(0.71).hex(), - punctuation: color_scheme.ramps.neutral(0.86).hex(), + primary: theme.ramps.neutral(1).hex(), + comment: theme.ramps.neutral(0.71).hex(), + punctuation: theme.ramps.neutral(0.86).hex(), predictive: predictive, hint: hint, - emphasis: color_scheme.ramps.blue(0.5).hex(), - string: color_scheme.ramps.orange(0.5).hex(), - function: color_scheme.ramps.yellow(0.5).hex(), - type: color_scheme.ramps.cyan(0.5).hex(), - constructor: color_scheme.ramps.blue(0.5).hex(), - variant: color_scheme.ramps.blue(0.5).hex(), - property: color_scheme.ramps.blue(0.5).hex(), - enum: color_scheme.ramps.orange(0.5).hex(), - operator: color_scheme.ramps.orange(0.5).hex(), - number: color_scheme.ramps.green(0.5).hex(), - boolean: color_scheme.ramps.green(0.5).hex(), - constant: color_scheme.ramps.green(0.5).hex(), - keyword: color_scheme.ramps.blue(0.5).hex(), + emphasis: theme.ramps.blue(0.5).hex(), + string: theme.ramps.orange(0.5).hex(), + function: theme.ramps.yellow(0.5).hex(), + type: theme.ramps.cyan(0.5).hex(), + constructor: theme.ramps.blue(0.5).hex(), + variant: theme.ramps.blue(0.5).hex(), + property: theme.ramps.blue(0.5).hex(), + enum: theme.ramps.orange(0.5).hex(), + operator: theme.ramps.orange(0.5).hex(), + number: theme.ramps.green(0.5).hex(), + boolean: theme.ramps.green(0.5).hex(), + constant: theme.ramps.green(0.5).hex(), + keyword: theme.ramps.blue(0.5).hex(), } // Then assign colors and use Syntax to enforce each style getting it's own color @@ -211,11 +212,11 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { weight: font_weights.bold, }, link_uri: { - color: color_scheme.ramps.green(0.5).hex(), + color: theme.ramps.green(0.5).hex(), underline: true, }, link_text: { - color: color_scheme.ramps.orange(0.5).hex(), + color: theme.ramps.orange(0.5).hex(), italic: true, }, "text.literal": { @@ -231,7 +232,7 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.punctuation, }, "punctuation.special": { - color: color_scheme.ramps.neutral(0.86).hex(), + color: theme.ramps.neutral(0.86).hex(), }, "punctuation.list_marker": { color: color.punctuation, @@ -252,10 +253,10 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.string, }, constructor: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, variant: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, type: { color: color.type, @@ -264,16 +265,16 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.primary, }, label: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, tag: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, attribute: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, property: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, constant: { color: color.constant, @@ -307,17 +308,18 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { return default_syntax } -function merge_syntax( - default_syntax: Syntax, - color_scheme: ColorScheme -): Syntax { - if (!color_scheme.syntax) { +export function build_syntax(): Syntax { + const theme = useTheme() + + const default_syntax: Syntax = build_default_syntax() + + if (!theme.syntax) { return default_syntax } - return deepmerge>( + const syntax = deepmerge>( default_syntax, - color_scheme.syntax, + theme.syntax, { arrayMerge: (destinationArray, sourceArray) => [ ...destinationArray, @@ -325,12 +327,6 @@ function merge_syntax( ], } ) -} - -export function build_syntax(color_scheme: ColorScheme): Syntax { - const default_syntax: Syntax = build_default_syntax(color_scheme) - - const syntax = merge_syntax(default_syntax, color_scheme) return syntax } diff --git a/styles/src/theme/theme_config.ts b/styles/src/theme/theme_config.ts index 26462bee6d..bc8f07425f 100644 --- a/styles/src/theme/theme_config.ts +++ b/styles/src/theme/theme_config.ts @@ -66,35 +66,10 @@ type ThemeConfigProperties = ThemeMeta & { override: ThemeConfigOverrides } -// This should be the format a theme is defined as export type ThemeConfig = { [K in keyof ThemeConfigProperties]: ThemeConfigProperties[K] } -interface ThemeColors { - neutral: string[] - red: string[] - orange: string[] - yellow: string[] - green: string[] - cyan: string[] - blue: string[] - violet: string[] - magenta: string[] -} - -type ThemeSyntax = Required - -export type ThemeProperties = ThemeMeta & { - color: ThemeColors - syntax: ThemeSyntax -} - -// This should be a theme after all its properties have been resolved -export type Theme = { - [K in keyof ThemeProperties]: ThemeProperties[K] -} - export enum ThemeAppearance { Light = "light", Dark = "dark", @@ -104,45 +79,3 @@ export enum ThemeLicenseType { MIT = "MIT", Apache2 = "Apache License 2.0", } - -export type ThemeFamilyItem = - | ThemeConfig - | { light: ThemeConfig; dark: ThemeConfig } - -type ThemeFamilyProperties = Partial> & { - name: string - default: ThemeFamilyItem - variants: { - [key: string]: ThemeFamilyItem - } -} - -// Idea: A theme family is a collection of themes that share the same name -// For example, a theme family could be `One Dark` and have a `light` and `dark` variant -// The Ayu family could have `light`, `mirage`, and `dark` variants - -type ThemeFamily = { - [K in keyof ThemeFamilyProperties]: ThemeFamilyProperties[K] -} - -/** The collection of all themes - * - * Example: - * ```ts - * { - * one_dark, - * one_light, - * ayu: { - * name: 'Ayu', - * default: 'ayu_mirage', - * variants: { - * light: 'ayu_light', - * mirage: 'ayu_mirage', - * dark: 'ayu_dark', - * }, - * }, - * ... - * } - * ``` - */ -export type ThemeIndex = Record diff --git a/styles/src/theme/tokens/layer.ts b/styles/src/theme/tokens/layer.ts index a2e539092e..6b4e1d79f7 100644 --- a/styles/src/theme/tokens/layer.ts +++ b/styles/src/theme/tokens/layer.ts @@ -1,5 +1,5 @@ import { SingleColorToken } from "@tokens-studio/types" -import { Layer, Style, StyleSet } from "../color_scheme" +import { Layer, Style, StyleSet } from "../create_theme" import { color_token } from "./token" interface StyleToken { diff --git a/styles/src/theme/tokens/players.ts b/styles/src/theme/tokens/players.ts index 85573a1a8f..4bf605aa93 100644 --- a/styles/src/theme/tokens/players.ts +++ b/styles/src/theme/tokens/players.ts @@ -1,7 +1,7 @@ import { SingleColorToken } from "@tokens-studio/types" import { color_token } from "./token" -import { Players } from "../color_scheme" -import { useTheme } from "@/src/common" +import { Players } from "../create_theme" +import { useTheme } from "../../../src/common" export type PlayerToken = Record<"selection" | "cursor", SingleColorToken> diff --git a/styles/src/theme/tokens/color_scheme.ts b/styles/src/theme/tokens/theme.ts similarity index 93% rename from styles/src/theme/tokens/color_scheme.ts rename to styles/src/theme/tokens/theme.ts index efbeaaa901..f759bc8139 100644 --- a/styles/src/theme/tokens/color_scheme.ts +++ b/styles/src/theme/tokens/theme.ts @@ -5,19 +5,18 @@ import { TokenTypes, } from "@tokens-studio/types" import { - ColorScheme, Shadow, SyntaxHighlightStyle, ThemeSyntax, -} from "../color_scheme" +} from "../create_theme" import { LayerToken, layer_token } from "./layer" import { PlayersToken, players_token } from "./players" import { color_token } from "./token" import { Syntax } from "../syntax" import editor from "../../style_tree/editor" -import { useTheme } from "@/src/common" +import { useTheme } from "../../../src/common" -interface ColorSchemeTokens { +interface ThemeTokens { name: SingleOtherToken appearance: SingleOtherToken lowest: LayerToken @@ -71,13 +70,13 @@ function syntax_highlight_style_color_tokens( }, {} as ThemeSyntaxColorTokens) } -const syntax_tokens = (): ColorSchemeTokens["syntax"] => { +const syntax_tokens = (): ThemeTokens["syntax"] => { const syntax = editor().syntax return syntax_highlight_style_color_tokens(syntax) } -export function theme_tokens(): ColorSchemeTokens { +export function theme_tokens(): ThemeTokens { const theme = useTheme() return {