Merge pull request #747 from zed-industries/styles-in-typescript

Nathan Sobo created

Style the Zed app using Typescript styleTrees and Design Tokens

Change summary

.gitignore                            |    1 
.zed.toml                             |    2 
crates/editor/src/context_menu.rs     |  272 +++
crates/theme/src/resolution.rs        |  497 -----
crates/theme/src/theme.rs             |    3 
crates/theme/src/theme_registry.rs    |  234 --
crates/zed/assets/themes/_base.toml   |  411 ----
crates/zed/assets/themes/black.toml   |   67 
crates/zed/assets/themes/dark.json    | 1285 +++++++++++++++
crates/zed/assets/themes/dark.toml    |   67 
crates/zed/assets/themes/light.json   | 1285 +++++++++++++++
crates/zed/assets/themes/light.toml   |   67 
crates/zed/src/zed.rs                 |    3 
script/build-themes                   |    7 
styles/.gitignore                     |    1 
styles/dist/core.json                 | 1155 +++++++++++++
styles/dist/dark.json                 |  637 +++++++
styles/dist/light.json                |  637 +++++++
styles/dist/tokens.json               | 2431 +++++++++++++++++++++++++++++
styles/nodemon.json                   |    8 
styles/package-lock.json              | 2321 +++++++++++++++++++++++++++
styles/package.json                   |   22 
styles/src/buildThemes.ts             |   17 
styles/src/buildTokens.ts             |  110 +
styles/src/styleTree/app.ts           |   43 
styles/src/styleTree/chatPanel.ts     |  108 +
styles/src/styleTree/components.ts    |   93 +
styles/src/styleTree/contactsPanel.ts |   62 
styles/src/styleTree/editor.ts        |  146 +
styles/src/styleTree/projectPanel.ts  |   37 
styles/src/styleTree/search.ts        |   79 
styles/src/styleTree/selectorModal.ts |   59 
styles/src/styleTree/workspace.ts     |  150 +
styles/src/themes/dark.ts             |  229 ++
styles/src/themes/light.ts            |  227 ++
styles/src/themes/theme.ts            |  145 +
styles/src/tokens.ts                  |  102 +
styles/src/utils/color.ts             |   52 
styles/src/utils/snakeCase.ts         |   35 
styles/tsconfig.json                  |   14 
40 files changed, 11,785 insertions(+), 1,336 deletions(-)

Detailed changes

.gitignore 🔗

@@ -2,6 +2,7 @@
 /zed.xcworkspace
 .DS_Store
 /script/node_modules
+/styles/node_modules
 /crates/server/.env.toml
 /crates/server/static/styles.css
 /vendor/bin

.zed.toml 🔗

@@ -1 +1 @@
-collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "Kethku"]
+collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "gibusu", "Kethku"]

crates/editor/src/context_menu.rs 🔗

@@ -0,0 +1,272 @@
+pub enum ContextMenu {
+    Completions(CompletionsMenu),
+    CodeActions(CodeActionsMenu),
+}
+
+impl ContextMenu {
+    pub fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
+        if self.visible() {
+            match self {
+                ContextMenu::Completions(menu) => menu.select_prev(cx),
+                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
+            }
+            true
+        } else {
+            false
+        }
+    }
+
+    pub fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
+        if self.visible() {
+            match self {
+                ContextMenu::Completions(menu) => menu.select_next(cx),
+                ContextMenu::CodeActions(menu) => menu.select_next(cx),
+            }
+            true
+        } else {
+            false
+        }
+    }
+
+    pub fn visible(&self) -> bool {
+        match self {
+            ContextMenu::Completions(menu) => menu.visible(),
+            ContextMenu::CodeActions(menu) => menu.visible(),
+        }
+    }
+
+    pub fn render(
+        &self,
+        cursor_position: DisplayPoint,
+        style: EditorStyle,
+        cx: &AppContext,
+    ) -> (DisplayPoint, ElementBox) {
+        match self {
+            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
+            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style),
+        }
+    }
+}
+
+struct CompletionsMenu {
+    id: CompletionId,
+    initial_position: Anchor,
+    buffer: ModelHandle<Buffer>,
+    completions: Arc<[Completion]>,
+    match_candidates: Vec<StringMatchCandidate>,
+    matches: Arc<[StringMatch]>,
+    selected_item: usize,
+    list: UniformListState,
+}
+
+impl CompletionsMenu {
+    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item > 0 {
+            self.selected_item -= 1;
+            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        }
+        cx.notify();
+    }
+
+    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item + 1 < self.matches.len() {
+            self.selected_item += 1;
+            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        }
+        cx.notify();
+    }
+
+    fn visible(&self) -> bool {
+        !self.matches.is_empty()
+    }
+
+    fn render(&self, style: EditorStyle, _: &AppContext) -> ElementBox {
+        enum CompletionTag {}
+
+        let completions = self.completions.clone();
+        let matches = self.matches.clone();
+        let selected_item = self.selected_item;
+        let container_style = style.autocomplete.container;
+        UniformList::new(self.list.clone(), matches.len(), move |range, items, cx| {
+            let start_ix = range.start;
+            for (ix, mat) in matches[range].iter().enumerate() {
+                let completion = &completions[mat.candidate_id];
+                let item_ix = start_ix + ix;
+                items.push(
+                    MouseEventHandler::new::<CompletionTag, _, _>(
+                        mat.candidate_id,
+                        cx,
+                        |state, _| {
+                            let item_style = if item_ix == selected_item {
+                                style.autocomplete.selected_item
+                            } else if state.hovered {
+                                style.autocomplete.hovered_item
+                            } else {
+                                style.autocomplete.item
+                            };
+
+                            Text::new(completion.label.text.clone(), style.text.clone())
+                                .with_soft_wrap(false)
+                                .with_highlights(combine_syntax_and_fuzzy_match_highlights(
+                                    &completion.label.text,
+                                    style.text.color.into(),
+                                    styled_runs_for_code_label(&completion.label, &style.syntax),
+                                    &mat.positions,
+                                ))
+                                .contained()
+                                .with_style(item_style)
+                                .boxed()
+                        },
+                    )
+                    .with_cursor_style(CursorStyle::PointingHand)
+                    .on_mouse_down(move |cx| {
+                        cx.dispatch_action(ConfirmCompletion(Some(item_ix)));
+                    })
+                    .boxed(),
+                );
+            }
+        })
+        .with_width_from_item(
+            self.matches
+                .iter()
+                .enumerate()
+                .max_by_key(|(_, mat)| {
+                    self.completions[mat.candidate_id]
+                        .label
+                        .text
+                        .chars()
+                        .count()
+                })
+                .map(|(ix, _)| ix),
+        )
+        .contained()
+        .with_style(container_style)
+        .boxed()
+    }
+
+    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
+        let mut matches = if let Some(query) = query {
+            fuzzy::match_strings(
+                &self.match_candidates,
+                query,
+                false,
+                100,
+                &Default::default(),
+                executor,
+            )
+            .await
+        } else {
+            self.match_candidates
+                .iter()
+                .enumerate()
+                .map(|(candidate_id, candidate)| StringMatch {
+                    candidate_id,
+                    score: Default::default(),
+                    positions: Default::default(),
+                    string: candidate.string.clone(),
+                })
+                .collect()
+        };
+        matches.sort_unstable_by_key(|mat| {
+            (
+                Reverse(OrderedFloat(mat.score)),
+                self.completions[mat.candidate_id].sort_key(),
+            )
+        });
+
+        for mat in &mut matches {
+            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
+            for position in &mut mat.positions {
+                *position += filter_start;
+            }
+        }
+
+        self.matches = matches.into();
+    }
+}
+
+#[derive(Clone)]
+struct CodeActionsMenu {
+    actions: Arc<[CodeAction]>,
+    buffer: ModelHandle<Buffer>,
+    selected_item: usize,
+    list: UniformListState,
+    deployed_from_indicator: bool,
+}
+
+impl CodeActionsMenu {
+    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item > 0 {
+            self.selected_item -= 1;
+            cx.notify()
+        }
+    }
+
+    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item + 1 < self.actions.len() {
+            self.selected_item += 1;
+            cx.notify()
+        }
+    }
+
+    fn visible(&self) -> bool {
+        !self.actions.is_empty()
+    }
+
+    fn render(
+        &self,
+        mut cursor_position: DisplayPoint,
+        style: EditorStyle,
+    ) -> (DisplayPoint, ElementBox) {
+        enum ActionTag {}
+
+        let container_style = style.autocomplete.container;
+        let actions = self.actions.clone();
+        let selected_item = self.selected_item;
+        let element =
+            UniformList::new(self.list.clone(), actions.len(), move |range, items, cx| {
+                let start_ix = range.start;
+                for (ix, action) in actions[range].iter().enumerate() {
+                    let item_ix = start_ix + ix;
+                    items.push(
+                        MouseEventHandler::new::<ActionTag, _, _>(item_ix, cx, |state, _| {
+                            let item_style = if item_ix == selected_item {
+                                style.autocomplete.selected_item
+                            } else if state.hovered {
+                                style.autocomplete.hovered_item
+                            } else {
+                                style.autocomplete.item
+                            };
+
+                            Text::new(action.lsp_action.title.clone(), style.text.clone())
+                                .with_soft_wrap(false)
+                                .contained()
+                                .with_style(item_style)
+                                .boxed()
+                        })
+                        .with_cursor_style(CursorStyle::PointingHand)
+                        .on_mouse_down(move |cx| {
+                            cx.dispatch_action(ConfirmCodeAction(Some(item_ix)));
+                        })
+                        .boxed(),
+                    );
+                }
+            })
+            .with_width_from_item(
+                self.actions
+                    .iter()
+                    .enumerate()
+                    .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
+                    .map(|(ix, _)| ix),
+            )
+            .contained()
+            .with_style(container_style)
+            .boxed();
+
+        if self.deployed_from_indicator {
+            *cursor_position.column_mut() = 0;
+        }
+
+        (cursor_position, element)
+    }
+}

crates/theme/src/resolution.rs 🔗

@@ -1,497 +0,0 @@
-use anyhow::{anyhow, Result};
-use indexmap::IndexMap;
-use serde_json::Value;
-use std::{
-    cell::RefCell,
-    mem,
-    rc::{Rc, Weak},
-};
-
-pub fn resolve_references(value: Value) -> Result<Value> {
-    let tree = Tree::from_json(value)?;
-    tree.resolve()?;
-    tree.to_json()
-}
-
-#[derive(Clone)]
-enum Node {
-    Reference {
-        path: String,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Object {
-        base: Option<String>,
-        children: IndexMap<String, Tree>,
-        resolved: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Array {
-        children: Vec<Tree>,
-        resolved: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    String {
-        value: String,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Number {
-        value: serde_json::Number,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Bool {
-        value: bool,
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-    Null {
-        parent: Option<Weak<RefCell<Node>>>,
-    },
-}
-
-#[derive(Clone)]
-struct Tree(Rc<RefCell<Node>>);
-
-impl Tree {
-    pub fn new(node: Node) -> Self {
-        Self(Rc::new(RefCell::new(node)))
-    }
-
-    fn from_json(value: Value) -> Result<Self> {
-        match value {
-            Value::String(value) => {
-                if let Some(path) = value.strip_prefix("$") {
-                    Ok(Self::new(Node::Reference {
-                        path: path.to_string(),
-                        parent: None,
-                    }))
-                } else {
-                    Ok(Self::new(Node::String {
-                        value,
-                        parent: None,
-                    }))
-                }
-            }
-            Value::Number(value) => Ok(Self::new(Node::Number {
-                value,
-                parent: None,
-            })),
-            Value::Bool(value) => Ok(Self::new(Node::Bool {
-                value,
-                parent: None,
-            })),
-            Value::Null => Ok(Self::new(Node::Null { parent: None })),
-            Value::Object(object) => {
-                let tree = Self::new(Node::Object {
-                    base: Default::default(),
-                    children: Default::default(),
-                    resolved: false,
-                    parent: None,
-                });
-                let mut children = IndexMap::new();
-                let mut resolved = true;
-                let mut base = None;
-                for (key, value) in object.into_iter() {
-                    let value = if key == "extends" {
-                        if value.is_string() {
-                            if let Value::String(value) = value {
-                                base = value.strip_prefix("$").map(str::to_string);
-                                resolved = false;
-                                Self::new(Node::String {
-                                    value,
-                                    parent: None,
-                                })
-                            } else {
-                                unreachable!()
-                            }
-                        } else {
-                            Tree::from_json(value)?
-                        }
-                    } else {
-                        Tree::from_json(value)?
-                    };
-                    value
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&tree.0)));
-                    resolved &= value.is_resolved();
-                    children.insert(key.clone(), value);
-                }
-
-                *tree.0.borrow_mut() = Node::Object {
-                    base,
-                    children,
-                    resolved,
-                    parent: None,
-                };
-                Ok(tree)
-            }
-            Value::Array(elements) => {
-                let tree = Self::new(Node::Array {
-                    children: Default::default(),
-                    resolved: false,
-                    parent: None,
-                });
-
-                let mut children = Vec::new();
-                let mut resolved = true;
-                for element in elements {
-                    let child = Tree::from_json(element)?;
-                    child
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&tree.0)));
-                    resolved &= child.is_resolved();
-                    children.push(child);
-                }
-
-                *tree.0.borrow_mut() = Node::Array {
-                    children,
-                    resolved,
-                    parent: None,
-                };
-                Ok(tree)
-            }
-        }
-    }
-
-    fn to_json(&self) -> Result<Value> {
-        match &*self.0.borrow() {
-            Node::Reference { .. } => Err(anyhow!("unresolved tree")),
-            Node::String { value, .. } => Ok(Value::String(value.clone())),
-            Node::Number { value, .. } => Ok(Value::Number(value.clone())),
-            Node::Bool { value, .. } => Ok(Value::Bool(*value)),
-            Node::Null { .. } => Ok(Value::Null),
-            Node::Object { children, .. } => {
-                let mut json_children = serde_json::Map::new();
-                for (key, value) in children {
-                    json_children.insert(key.clone(), value.to_json()?);
-                }
-                Ok(Value::Object(json_children))
-            }
-            Node::Array { children, .. } => {
-                let mut json_children = Vec::new();
-                for child in children {
-                    json_children.push(child.to_json()?);
-                }
-                Ok(Value::Array(json_children))
-            }
-        }
-    }
-
-    fn parent(&self) -> Option<Tree> {
-        match &*self.0.borrow() {
-            Node::Reference { parent, .. }
-            | Node::Object { parent, .. }
-            | Node::Array { parent, .. }
-            | Node::String { parent, .. }
-            | Node::Number { parent, .. }
-            | Node::Bool { parent, .. }
-            | Node::Null { parent } => parent.as_ref().and_then(|p| p.upgrade()).map(Tree),
-        }
-    }
-
-    fn get(&self, path: &str) -> Result<Option<Tree>> {
-        let mut tree = self.clone();
-        for component in path.split('.') {
-            let node = tree.0.borrow();
-            match &*node {
-                Node::Object { children, .. } => {
-                    if let Some(subtree) = children.get(component).cloned() {
-                        drop(node);
-                        tree = subtree;
-                    } else {
-                        return Err(anyhow!(
-                            "key \"{}\" does not exist in path \"{}\"",
-                            component,
-                            path
-                        ));
-                    }
-                }
-                Node::Reference { .. } => return Ok(None),
-                Node::Array { .. }
-                | Node::String { .. }
-                | Node::Number { .. }
-                | Node::Bool { .. }
-                | Node::Null { .. } => {
-                    return Err(anyhow!(
-                        "key \"{}\" in path \"{}\" is not an object",
-                        component,
-                        path
-                    ))
-                }
-            }
-        }
-
-        Ok(Some(tree))
-    }
-
-    fn is_resolved(&self) -> bool {
-        match &*self.0.borrow() {
-            Node::Reference { .. } => false,
-            Node::Object { resolved, .. } | Node::Array { resolved, .. } => *resolved,
-            Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => {
-                true
-            }
-        }
-    }
-
-    fn update_resolved(&self) {
-        match &mut *self.0.borrow_mut() {
-            Node::Object {
-                resolved,
-                base,
-                children,
-                ..
-            } => {
-                *resolved = base.is_none() && children.values().all(|c| c.is_resolved());
-            }
-            Node::Array {
-                resolved, children, ..
-            } => {
-                *resolved = children.iter().all(|c| c.is_resolved());
-            }
-            _ => {}
-        }
-    }
-
-    pub fn resolve(&self) -> Result<()> {
-        let mut unresolved = vec![self.clone()];
-        let mut made_progress = true;
-
-        while made_progress && !unresolved.is_empty() {
-            made_progress = false;
-            for mut tree in mem::take(&mut unresolved) {
-                made_progress |= tree.resolve_subtree(self, &mut unresolved)?;
-                if tree.is_resolved() {
-                    while let Some(parent) = tree.parent() {
-                        parent.update_resolved();
-                        if !parent.is_resolved() {
-                            break;
-                        }
-                        tree = parent;
-                    }
-                }
-            }
-        }
-
-        if unresolved.is_empty() {
-            Ok(())
-        } else {
-            Err(anyhow!("tree contains cycles"))
-        }
-    }
-
-    fn resolve_subtree(&self, root: &Tree, unresolved: &mut Vec<Tree>) -> Result<bool> {
-        let node = self.0.borrow();
-        match &*node {
-            Node::Reference { path, parent } => {
-                if let Some(subtree) = root.get(&path)? {
-                    if subtree.is_resolved() {
-                        let parent = parent.clone();
-                        drop(node);
-                        let mut new_node = subtree.0.borrow().clone();
-                        new_node.set_parent(parent);
-                        *self.0.borrow_mut() = new_node;
-                        Ok(true)
-                    } else {
-                        unresolved.push(self.clone());
-                        Ok(false)
-                    }
-                } else {
-                    unresolved.push(self.clone());
-                    Ok(false)
-                }
-            }
-            Node::Object {
-                base,
-                children,
-                resolved,
-                ..
-            } => {
-                if *resolved {
-                    Ok(false)
-                } else {
-                    let mut made_progress = false;
-                    let mut children_resolved = true;
-                    for child in children.values() {
-                        made_progress |= child.resolve_subtree(root, unresolved)?;
-                        children_resolved &= child.is_resolved();
-                    }
-
-                    if children_resolved {
-                        let mut has_base = false;
-                        let mut resolved_base = None;
-                        if let Some(base) = base {
-                            has_base = true;
-                            if let Some(base) = root.get(base)? {
-                                if base.is_resolved() {
-                                    resolved_base = Some(base);
-                                }
-                            }
-                        }
-
-                        drop(node);
-
-                        if let Some(base) = resolved_base.as_ref() {
-                            self.extend_from(&base);
-                            made_progress = true;
-                        }
-
-                        if let Node::Object { resolved, base, .. } = &mut *self.0.borrow_mut() {
-                            if has_base {
-                                if resolved_base.is_some() {
-                                    base.take();
-                                    *resolved = true;
-                                } else {
-                                    unresolved.push(self.clone());
-                                }
-                            } else {
-                                *resolved = true;
-                            }
-                        }
-                    } else if base.is_some() {
-                        unresolved.push(self.clone());
-                    }
-
-                    Ok(made_progress)
-                }
-            }
-            Node::Array {
-                children, resolved, ..
-            } => {
-                if *resolved {
-                    Ok(false)
-                } else {
-                    let mut made_progress = false;
-                    let mut children_resolved = true;
-                    for child in children.iter() {
-                        made_progress |= child.resolve_subtree(root, unresolved)?;
-                        children_resolved &= child.is_resolved();
-                    }
-
-                    if children_resolved {
-                        drop(node);
-
-                        if let Node::Array { resolved, .. } = &mut *self.0.borrow_mut() {
-                            *resolved = true;
-                        }
-                    }
-
-                    Ok(made_progress)
-                }
-            }
-            Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => {
-                Ok(false)
-            }
-        }
-    }
-
-    fn extend_from(&self, base: &Tree) {
-        if Rc::ptr_eq(&self.0, &base.0) {
-            return;
-        }
-
-        if let (
-            Node::Object { children, .. },
-            Node::Object {
-                children: base_children,
-                ..
-            },
-        ) = (&mut *self.0.borrow_mut(), &*base.0.borrow())
-        {
-            for (key, base_value) in base_children {
-                if let Some(value) = children.get(key) {
-                    value.extend_from(base_value);
-                } else {
-                    let base_value = base_value.clone();
-                    base_value
-                        .0
-                        .borrow_mut()
-                        .set_parent(Some(Rc::downgrade(&self.0)));
-                    children.insert(key.clone(), base_value);
-                }
-            }
-        }
-    }
-}
-
-impl Node {
-    fn set_parent(&mut self, new_parent: Option<Weak<RefCell<Node>>>) {
-        match self {
-            Node::Reference { parent, .. }
-            | Node::Object { parent, .. }
-            | Node::Array { parent, .. }
-            | Node::String { parent, .. }
-            | Node::Number { parent, .. }
-            | Node::Bool { parent, .. }
-            | Node::Null { parent } => *parent = new_parent,
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_references() {
-        let json = serde_json::json!({
-            "a": {
-                "extends": "$g",
-                "x": "$b.d"
-            },
-            "b": {
-                "c": "$a",
-                "d": "$e.f"
-            },
-            "e": {
-                "extends": "$a",
-                "f": "1"
-            },
-            "g": {
-                "h": 2
-            }
-        });
-
-        assert_eq!(
-            resolve_references(json).unwrap(),
-            serde_json::json!({
-                "a": {
-                    "extends": "$g",
-                    "x": "1",
-                    "h": 2
-                },
-                "b": {
-                    "c": {
-                        "extends": "$g",
-                        "x": "1",
-                        "h": 2
-                    },
-                    "d": "1"
-                },
-                "e": {
-                    "extends": "$a",
-                    "f": "1",
-                    "x": "1",
-                    "h": 2
-                },
-                "g": {
-                    "h": 2
-                }
-            })
-        )
-    }
-
-    #[test]
-    fn test_cycles() {
-        let json = serde_json::json!({
-            "a": {
-                "b": "$c.d"
-            },
-            "c": {
-                "d": "$a.b",
-            },
-        });
-
-        assert!(resolve_references(json).is_err());
-    }
-}

crates/theme/src/theme.rs 🔗

@@ -1,4 +1,3 @@
-mod resolution;
 mod theme_registry;
 
 use gpui::{
@@ -12,7 +11,7 @@ use std::{collections::HashMap, sync::Arc};
 
 pub use theme_registry::*;
 
-pub const DEFAULT_THEME_NAME: &'static str = "black";
+pub const DEFAULT_THEME_NAME: &'static str = "dark";
 
 #[derive(Deserialize, Default)]
 pub struct Theme {

crates/theme/src/theme_registry.rs 🔗

@@ -1,8 +1,8 @@
-use crate::{resolution::resolve_references, Theme};
+use crate::Theme;
 use anyhow::{Context, Result};
 use gpui::{fonts, AssetSource, FontCache};
 use parking_lot::Mutex;
-use serde_json::{Map, Value};
+use serde_json::Value;
 use std::{collections::HashMap, sync::Arc};
 
 pub struct ThemeRegistry {
@@ -25,12 +25,8 @@ impl ThemeRegistry {
     pub fn list(&self) -> impl Iterator<Item = String> {
         self.assets.list("themes/").into_iter().filter_map(|path| {
             let filename = path.strip_prefix("themes/")?;
-            let theme_name = filename.strip_suffix(".toml")?;
-            if theme_name.starts_with('_') {
-                None
-            } else {
-                Some(theme_name.to_string())
-            }
+            let theme_name = filename.strip_suffix(".json")?;
+            Some(theme_name.to_string())
         })
     }
 
@@ -44,9 +40,14 @@ impl ThemeRegistry {
             return Ok(theme.clone());
         }
 
-        let theme_data = self.load(name, true)?;
+        let asset_path = format!("themes/{}.json", name);
+        let theme_json = self
+            .assets
+            .load(&asset_path)
+            .with_context(|| format!("failed to load theme file {}", asset_path))?;
+
         let mut theme: Theme = fonts::with_font_cache(self.font_cache.clone(), || {
-            serde_path_to_error::deserialize(theme_data.as_ref())
+            serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&theme_json))
         })?;
 
         theme.name = name.into();
@@ -54,217 +55,4 @@ impl ThemeRegistry {
         self.themes.lock().insert(name.to_string(), theme.clone());
         Ok(theme)
     }
-
-    fn load(&self, name: &str, evaluate_references: bool) -> Result<Arc<Value>> {
-        if let Some(data) = self.theme_data.lock().get(name) {
-            return Ok(data.clone());
-        }
-
-        let asset_path = format!("themes/{}.toml", name);
-        let source_code = self
-            .assets
-            .load(&asset_path)
-            .with_context(|| format!("failed to load theme file {}", asset_path))?;
-
-        let mut theme_data: Map<String, Value> = toml::from_slice(source_code.as_ref())
-            .with_context(|| format!("failed to parse {}.toml", name))?;
-
-        // If this theme extends another base theme, deeply merge it into the base theme's data
-        if let Some(base_name) = theme_data
-            .get("extends")
-            .and_then(|name| name.as_str())
-            .map(str::to_string)
-        {
-            let base_theme_data = self
-                .load(&base_name, false)
-                .with_context(|| format!("failed to load base theme {}", base_name))?
-                .as_ref()
-                .clone();
-            if let Value::Object(mut base_theme_object) = base_theme_data {
-                deep_merge_json(&mut base_theme_object, theme_data);
-                theme_data = base_theme_object;
-            }
-        }
-
-        let mut theme_data = Value::Object(theme_data);
-
-        // Find all of the key path references in the object, and then sort them according
-        // to their dependencies.
-        if evaluate_references {
-            theme_data = resolve_references(theme_data)?;
-        }
-
-        let result = Arc::new(theme_data);
-        self.theme_data
-            .lock()
-            .insert(name.to_string(), result.clone());
-
-        Ok(result)
-    }
-}
-
-fn deep_merge_json(base: &mut Map<String, Value>, extension: Map<String, Value>) {
-    for (key, extension_value) in extension {
-        if let Value::Object(extension_object) = extension_value {
-            if let Some(base_object) = base.get_mut(&key).and_then(|value| value.as_object_mut()) {
-                deep_merge_json(base_object, extension_object);
-            } else {
-                base.insert(key, Value::Object(extension_object));
-            }
-        } else {
-            base.insert(key, extension_value);
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use anyhow::anyhow;
-    use gpui::MutableAppContext;
-
-    #[gpui::test]
-    fn test_theme_extension(cx: &mut MutableAppContext) {
-        let assets = TestAssets(&[
-            (
-                "themes/_base.toml",
-                r##"
-                [ui.active_tab]
-                extends = "$ui.tab"
-                border.color = "#666666"
-                text = "$text_colors.bright"
-
-                [ui.tab]
-                extends = "$ui.element"
-                text = "$text_colors.dull"
-
-                [ui.element]
-                background = "#111111"
-                border = {width = 2.0, color = "#00000000"}
-
-                [editor]
-                background = "#222222"
-                default_text = "$text_colors.regular"
-                "##,
-            ),
-            (
-                "themes/light.toml",
-                r##"
-                extends = "_base"
-
-                [text_colors]
-                bright = "#ffffff"
-                regular = "#eeeeee"
-                dull = "#dddddd"
-
-                [editor]
-                background = "#232323"
-                "##,
-            ),
-        ]);
-
-        let registry = ThemeRegistry::new(assets, cx.font_cache().clone());
-        let theme_data = registry.load("light", true).unwrap();
-
-        assert_eq!(
-            theme_data.as_ref(),
-            &serde_json::json!({
-              "ui": {
-                "active_tab": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#666666"
-                  },
-                  "extends": "$ui.tab",
-                  "text": "#ffffff"
-                },
-                "tab": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#00000000"
-                  },
-                  "extends": "$ui.element",
-                  "text": "#dddddd"
-                },
-                "element": {
-                  "background": "#111111",
-                  "border": {
-                    "width": 2.0,
-                    "color": "#00000000"
-                  }
-                }
-              },
-              "editor": {
-                "background": "#232323",
-                "default_text": "#eeeeee"
-              },
-              "extends": "_base",
-              "text_colors": {
-                "bright": "#ffffff",
-                "regular": "#eeeeee",
-                "dull": "#dddddd"
-              }
-            })
-        );
-    }
-
-    #[gpui::test]
-    fn test_nested_extension(cx: &mut MutableAppContext) {
-        let assets = TestAssets(&[(
-            "themes/theme.toml",
-            r##"
-                [a]
-                text = { extends = "$text.0" }
-
-                [b]
-                extends = "$a"
-                text = { extends = "$text.1" }
-
-                [text]
-                0 = { color = "red" }
-                1 = { color = "blue" }
-            "##,
-        )]);
-
-        let registry = ThemeRegistry::new(assets, cx.font_cache().clone());
-        let theme_data = registry.load("theme", true).unwrap();
-        assert_eq!(
-            theme_data
-                .get("b")
-                .unwrap()
-                .get("text")
-                .unwrap()
-                .get("color")
-                .unwrap(),
-            "blue"
-        );
-    }
-
-    struct TestAssets(&'static [(&'static str, &'static str)]);
-
-    impl AssetSource for TestAssets {
-        fn load(&self, path: &str) -> Result<std::borrow::Cow<[u8]>> {
-            if let Some(row) = self.0.iter().find(|e| e.0 == path) {
-                Ok(row.1.as_bytes().into())
-            } else {
-                Err(anyhow!("no such path {}", path))
-            }
-        }
-
-        fn list(&self, prefix: &str) -> Vec<std::borrow::Cow<'static, str>> {
-            self.0
-                .iter()
-                .copied()
-                .filter_map(|(path, _)| {
-                    if path.starts_with(prefix) {
-                        Some(path.into())
-                    } else {
-                        None
-                    }
-                })
-                .collect()
-        }
-    }
 }

crates/zed/assets/themes/_base.toml 🔗

@@ -1,411 +0,0 @@
-[text]
-base = { family = "Zed Sans", size = 14 }
-
-[workspace]
-background = "$surface.0"
-pane_divider = { width = 1, color = "$border.0" }
-leader_border_opacity = 0.7
-leader_border_width = 2.0
-
-[workspace.titlebar]
-height = 32
-border = { width = 1, bottom = true, color = "$border.0" }
-title = "$text.0"
-avatar_width = 18
-avatar = { corner_radius = 10, border = { width = 1, color = "#00000088" } }
-avatar_ribbon = { background = "#ff0000", height = 3, width = 12 }
-outdated_warning = { extends = "$text.2", size = 13 }
-share_icon_color = "$text.2.color"
-share_icon_active_color = "$text.0.color"
-
-[workspace.titlebar.sign_in_prompt]
-extends = "$text.2"
-size = 13
-underline = true
-padding = { right = 8 }
-
-[workspace.titlebar.hovered_sign_in_prompt]
-extends = "$workspace.titlebar.sign_in_prompt"
-color = "$text.1.color"
-
-[workspace.titlebar.offline_icon]
-padding = { right = 4 }
-width = 16
-color = "$text.2.color"
-
-[workspace.tab]
-height = 34
-text = "$text.2"
-padding = { left = 12, right = 12 }
-icon_width = 8
-spacing = 10
-icon_close = "$text.2.color"
-icon_close_active = "$text.0.color"
-icon_dirty = "$status.info"
-icon_conflict = "$status.warn"
-border = { left = true, bottom = true, width = 1, color = "$border.0", overlay = true }
-
-[workspace.active_tab]
-extends = "$workspace.tab"
-border.bottom = false
-background = "$surface.1"
-text = "$text.0"
-
-[workspace.sidebar]
-width = 30
-border = { right = true, width = 1, color = "$border.0" }
-
-[workspace.sidebar.resize_handle]
-padding = { left = 1 }
-background = "$border.0"
-
-[workspace.sidebar.item]
-icon_color = "$text.2.color"
-icon_size = 18
-height = "$workspace.tab.height"
-
-[workspace.sidebar.active_item]
-extends = "$workspace.sidebar.item"
-icon_color = "$text.0.color"
-
-[workspace.left_sidebar]
-extends = "$workspace.sidebar"
-border = { width = 1, color = "$border.0", right = true }
-
-[workspace.right_sidebar]
-extends = "$workspace.sidebar"
-border = { width = 1, color = "$border.0", left = true }
-
-[workspace.status_bar]
-padding = { left = 6, right = 6 }
-height = 24
-item_spacing = 8
-cursor_position = "$text.2"
-diagnostic_message = "$text.2"
-lsp_message = "$text.2"
-
-[workspace.toolbar]
-background = "$surface.1"
-border = { color = "$border.0", width = 1, left = false, right = false, bottom = true, top = false }
-height = 34
-item_spacing = 8
-padding = { left = 16, right = 8, top = 4, bottom = 4 }
-
-[breadcrumbs]
-extends = "$text.1"
-padding = { left = 6 }
-
-[panel]
-padding = { top = 12, left = 12, bottom = 12, right = 12 }
-
-[chat_panel]
-extends = "$panel"
-channel_name = { extends = "$text.0", weight = "bold" }
-channel_name_hash = { text = "$text.2", padding.right = 8 }
-
-[chat_panel.message]
-body = "$text.1"
-sender = { extends = "$text.0", weight = "bold", margin.right = 8 }
-timestamp = "$text.2"
-padding.bottom = 6
-
-[chat_panel.pending_message]
-extends = "$chat_panel.message"
-body = { color = "$text.3.color" }
-sender = { color = "$text.3.color" }
-timestamp = { color = "$text.3.color" }
-
-[chat_panel.channel_select.item]
-padding = 4
-name = "$text.1"
-hash = { extends = "$text.2", margin.right = 8 }
-
-[chat_panel.channel_select.hovered_item]
-extends = "$chat_panel.channel_select.item"
-background = "$state.hover"
-corner_radius = 6
-
-[chat_panel.channel_select.active_item]
-extends = "$chat_panel.channel_select.item"
-name = "$text.0"
-
-[chat_panel.channel_select.hovered_active_item]
-extends = "$chat_panel.channel_select.hovered_item"
-name = "$text.0"
-
-[chat_panel.channel_select.header]
-extends = "$chat_panel.channel_select.active_item"
-padding.bottom = 4
-padding.left = 0
-
-[chat_panel.channel_select.menu]
-padding = 4
-corner_radius = 6
-border = { color = "$border.0", width = 1 }
-background = "$surface.0"
-shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" }
-
-[chat_panel.input_editor]
-background = "$surface.1"
-corner_radius = 6
-padding = { left = 8, right = 8, top = 7, bottom = 7 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[chat_panel.sign_in_prompt]
-extends = "$text.0"
-underline = true
-
-[chat_panel.hovered_sign_in_prompt]
-extends = "$chat_panel.sign_in_prompt"
-color = "$text.1.color"
-
-[contacts_panel]
-extends = "$panel"
-host_row_height = 28
-host_avatar = { corner_radius = 10, width = 18 }
-host_username = { extends = "$text.0", padding.left = 8 }
-tree_branch_width = 1
-tree_branch_color = "$surface.2"
-
-[contacts_panel.project]
-height = 24
-padding = { left = 8 }
-guest_avatar = { corner_radius = 8, width = 14 }
-guest_avatar_spacing = 4
-
-[contacts_panel.project.name]
-extends = "$text.1"
-margin = { right = 6 }
-
-[contacts_panel.unshared_project]
-extends = "$contacts_panel.project"
-
-[contacts_panel.hovered_unshared_project]
-extends = "$contacts_panel.unshared_project"
-background = "$state.hover"
-corner_radius = 6
-
-[contacts_panel.shared_project]
-extends = "$contacts_panel.project"
-name.color = "$text.0.color"
-
-[contacts_panel.hovered_shared_project]
-extends = "$contacts_panel.shared_project"
-background = "$state.hover"
-corner_radius = 6
-
-[project_panel]
-extends = "$panel"
-padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
-
-[project_panel.entry]
-text = "$text.1"
-height = 22
-icon_color = "$text.3.color"
-icon_size = 8
-icon_spacing = 8
-
-[project_panel.hovered_entry]
-extends = "$project_panel.entry"
-background = "$state.hover"
-
-[project_panel.selected_entry]
-extends = "$project_panel.entry"
-text = { extends = "$text.0" }
-
-[project_panel.hovered_selected_entry]
-extends = "$project_panel.hovered_entry"
-text = { extends = "$text.0" }
-
-[selector]
-background = "$surface.0"
-padding = 8
-margin = { top = 52, bottom = 52 }
-corner_radius = 6
-shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" }
-border = { width = 1, color = "$border.0" }
-
-[selector.input_editor]
-background = "$surface.1"
-corner_radius = 6
-padding = { left = 16, right = 16, top = 7, bottom = 7 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[selector.empty]
-text = "$text.2"
-padding = { left = 16, right = 16, top = 8, bottom = 4 }
-
-[selector.item]
-text = "$text.1"
-highlight_text = { extends = "$text.base", color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" }
-padding = { left = 16, right = 16, top = 4, bottom = 4 }
-corner_radius = 6
-
-[selector.active_item]
-extends = "$selector.item"
-background = "$state.hover"
-text = "$text.0"
-
-[editor]
-text_color = "$text.1.color"
-background = "$surface.1"
-gutter_background = "$surface.1"
-gutter_padding_factor = 2.5
-active_line_background = "$state.active_line"
-highlighted_line_background = "$state.highlighted_line"
-rename_fade = 0.6
-unnecessary_code_fade = 0.5
-document_highlight_read_background = "#99999920"
-document_highlight_write_background = "#99999916"
-diff_background_deleted = "$state.deleted_line"
-diff_background_inserted = "$state.inserted_line"
-line_number = "$text.2.color"
-line_number_active = "$text.0.color"
-selection = "$selection.host"
-guest_selections = "$selection.guests"
-error_color = "$status.bad"
-code_actions_indicator = "$text.3.color"
-
-[editor.diagnostic_path_header]
-background = "$state.active_line"
-filename = { extends = "$text.0", size = 14 }
-path = { extends = "$text.2", size = 14, margin.left = 12 }
-text_scale_factor = 0.857
-
-[editor.diagnostic_header]
-background = "$editor.background"
-border = { width = 1, top = true, bottom = true, color = "$border.1" }
-code = { extends = "$text.2", size = 14, margin.left = 10 }
-icon_width_factor = 1.5
-text_scale_factor = 0.857
-
-[editor.diagnostic_header.message]
-text = { extends = "$text.1", size = 14 }
-highlight_text = { extends = "$text.0", size = 14, weight = "bold" }
-
-[editor.error_diagnostic]
-header.border = { width = 1, top = true, color = "$border.0" }
-text_scale_factor = 0.857
-
-[editor.error_diagnostic.message]
-text = { extends = "$text.1", size = 14, color = "$status.bad" }
-highlight_text = { extends = "$text.1", size = 14, color = "$status.bad", weight = "bold" }
-
-[editor.warning_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.warn"
-message.highlight_text.color = "$status.warn"
-
-[editor.information_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.info"
-message.highlight_text.color = "$status.info"
-
-[editor.hint_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$status.info"
-message.highlight_text.color = "$status.info"
-
-[editor.invalid_error_diagnostic]
-extends = "$editor.error_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_warning_diagnostic]
-extends = "$editor.warning_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_information_diagnostic]
-extends = "$editor.information_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.invalid_hint_diagnostic]
-extends = "$editor.hint_diagnostic"
-message.text.color = "$text.3.color"
-message.highlight_text.color = "$text.3.color"
-
-[editor.autocomplete]
-background = "$surface.2"
-border = { width = 2, color = "$border.1" }
-corner_radius = 6
-padding = 6
-match_highlight = { color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" }
-margin.left = -14
-
-[editor.autocomplete.item]
-padding = { left = 6, right = 6, top = 2, bottom = 2 }
-corner_radius = 6
-
-[editor.autocomplete.selected_item]
-extends = "$editor.autocomplete.item"
-background = "$state.selected"
-
-[editor.autocomplete.hovered_item]
-extends = "$editor.autocomplete.item"
-background = "$state.hover"
-
-[project_diagnostics]
-background = "$surface.1"
-empty_message = { extends = "$text.0", size = 18 }
-status_bar_item = { extends = "$text.2", margin.right = 10 }
-tab_icon_width = 13
-tab_icon_spacing = 4
-tab_summary_spacing = 10
-
-[search]
-match_background = "$state.highlighted_line"
-results_status = { extends = "$text.0", size = 18 }
-tab_icon_width = 14
-tab_icon_spacing = 4
-
-[search.option_button]
-extends = "$text.1"
-padding = { left = 6, right = 6, top = 1, bottom = 1 }
-corner_radius = 6
-background = "$surface.1"
-border = { width = 1, color = "$border.0" }
-margin.left = 1
-margin.right = 1
-
-[search.option_button_group]
-padding = { left = 2, right = 2 }
-
-[search.active_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.hovered_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.active_hovered_option_button]
-extends = "$search.option_button"
-background = "$surface.2"
-
-[search.match_index]
-extends = "$text.2"
-padding = 6
-
-[search.editor]
-min_width = 200
-max_width = 500
-background = "$surface.0"
-corner_radius = 6
-padding = { left = 14, right = 14, top = 3, bottom = 3 }
-margin = { right = 5 }
-text = "$text.0"
-placeholder_text = "$text.2"
-selection = "$selection.host"
-border = { width = 1, color = "$border.0" }
-
-[search.invalid_editor]
-extends = "$search.editor"
-border = { width = 1, color = "$status.bad" }

crates/zed/assets/themes/black.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#222222"
-1 = "#0f0b0c"
-2 = "#131415"
-
-[border]
-0 = "#000000B2"
-1 = "#FFFFFF20"
-
-[text]
-0 = { extends = "$text.base", color = "#ffffff" }
-1 = { extends = "$text.base", color = "#b3b3b3" }
-2 = { extends = "$text.base", color = "#7b7d80" }
-3 = { extends = "$text.base", color = "#66686A" }
-
-[shadow]
-0 = "#00000052"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#161313"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#00000033"
-selected = "#00000088"
-
-[editor.syntax]
-keyword = { color = "#0086c0", weight = "bold" }
-function = "#dcdcaa"
-string = "#cb8f77"
-type = "#4ec9b0"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#9cdcfe"
-title = { color = "#9cdcfe", weight = "bold" }
-emphasis = "#4ec9b0"
-"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#cb8f77", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000aa"

crates/zed/assets/themes/dark.json 🔗

@@ -0,0 +1,1285 @@
+{
+  "selector": {
+    "background": "#1c1c1c",
+    "corner_radius": 6,
+    "padding": 8,
+    "item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#9c9c9c",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#1096d3",
+        "weight": "bold",
+        "size": 14
+      }
+    },
+    "active_item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#1096d3",
+        "weight": "bold",
+        "size": 14
+      },
+      "background": "#2b2b2b"
+    },
+    "border": {
+      "color": "#070707",
+      "width": 1
+    },
+    "empty": {
+      "text": {
+        "family": "Zed Sans",
+        "color": "#474747",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 8
+      }
+    },
+    "input_editor": {
+      "background": "#000000",
+      "corner_radius": 6,
+      "placeholder_text": {
+        "family": "Zed Sans",
+        "color": "#474747",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "border": {
+        "color": "#232323",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 16,
+        "right": 16,
+        "top": 7
+      }
+    },
+    "margin": {
+      "bottom": 52,
+      "top": 52
+    },
+    "shadow": {
+      "blur": 16,
+      "color": "#00000052",
+      "offset": [
+        0,
+        2
+      ]
+    }
+  },
+  "workspace": {
+    "background": "#1c1c1c",
+    "leader_border_opacity": 0.7,
+    "leader_border_width": 2,
+    "tab": {
+      "height": 32,
+      "background": "#1c1c1c",
+      "icon_close": "#555555",
+      "icon_close_active": "#ffffff",
+      "icon_conflict": "#f6a724",
+      "icon_dirty": "#135acd",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#9c9c9c",
+        "size": 14
+      },
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "left": true,
+        "bottom": true,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "active_tab": {
+      "height": 32,
+      "background": "#000000",
+      "icon_close": "#555555",
+      "icon_close_active": "#ffffff",
+      "icon_conflict": "#f6a724",
+      "icon_dirty": "#135acd",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#ffffff",
+        "size": 14
+      },
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "left": true,
+        "bottom": false,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "left_sidebar": {
+      "width": 30,
+      "background": "#1c1c1c",
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "right": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#9c9c9c",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#ffffff",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#070707",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "right_sidebar": {
+      "width": 30,
+      "background": "#1c1c1c",
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "left": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#9c9c9c",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#ffffff",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#070707",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "pane_divider": {
+      "color": "#232323",
+      "width": 1
+    },
+    "status_bar": {
+      "height": 24,
+      "item_spacing": 8,
+      "padding": {
+        "left": 6,
+        "right": 6
+      },
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "top": true,
+        "overlay": true
+      },
+      "cursor_position": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "diagnostic_message": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "lsp_message": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      }
+    },
+    "titlebar": {
+      "avatar_width": 18,
+      "height": 32,
+      "background": "#2b2b2b",
+      "share_icon_color": "#9c9c9c",
+      "share_icon_active_color": "#2472f2",
+      "title": {
+        "family": "Zed Sans",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "avatar": {
+        "corner_radius": 10,
+        "border": {
+          "color": "#00000088",
+          "width": 1
+        }
+      },
+      "avatar_ribbon": {
+        "height": 3,
+        "width": 12
+      },
+      "border": {
+        "color": "#070707",
+        "width": 1,
+        "bottom": true
+      },
+      "sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#9c9c9c",
+        "size": 12,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "hovered_sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#ffffff",
+        "size": 12,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "offline_icon": {
+        "color": "#9c9c9c",
+        "width": 16,
+        "padding": {
+          "right": 4
+        }
+      },
+      "outdated_warning": {
+        "family": "Zed Sans",
+        "color": "#f7bb57",
+        "size": 13
+      }
+    },
+    "toolbar": {
+      "height": 34,
+      "background": "#000000",
+      "border": {
+        "color": "#232323",
+        "width": 1,
+        "bottom": true
+      },
+      "item_spacing": 8,
+      "padding": {
+        "left": 16,
+        "right": 8,
+        "top": 4,
+        "bottom": 4
+      }
+    },
+    "breadcrumbs": {
+      "family": "Zed Mono",
+      "color": "#9c9c9c",
+      "size": 14,
+      "padding": {
+        "left": 6
+      }
+    },
+    "disconnected_overlay": {
+      "family": "Zed Sans",
+      "color": "#ffffff",
+      "size": 14,
+      "background": "#000000aa"
+    }
+  },
+  "editor": {
+    "text_color": "#d5d5d5",
+    "background": "#000000",
+    "active_line_background": "#ffffff12",
+    "code_actions_indicator": "#555555",
+    "diff_background_deleted": "#f15656",
+    "diff_background_inserted": "#1b9447",
+    "document_highlight_read_background": "#ffffff1f",
+    "document_highlight_write_background": "#ffffff29",
+    "error_color": "#f15656",
+    "gutter_background": "#000000",
+    "gutter_padding_factor": 3.5,
+    "highlighted_line_background": "#ffffff1f",
+    "line_number": "#474747",
+    "line_number_active": "#ffffff",
+    "rename_fade": 0.6,
+    "unnecessary_code_fade": 0.5,
+    "selection": {
+      "cursor": "#2472f2",
+      "selection": "#2472f23d"
+    },
+    "guest_selections": [
+      {
+        "cursor": "#79ba16",
+        "selection": "#79ba163d"
+      },
+      {
+        "cursor": "#d430e0",
+        "selection": "#d430e03d"
+      },
+      {
+        "cursor": "#ee670a",
+        "selection": "#ee670a3d"
+      },
+      {
+        "cursor": "#993bf3",
+        "selection": "#993bf33d"
+      },
+      {
+        "cursor": "#16d6c1",
+        "selection": "#16d6c13d"
+      },
+      {
+        "cursor": "#ef59a3",
+        "selection": "#ef59a33d"
+      },
+      {
+        "cursor": "#f7bf17",
+        "selection": "#f7bf173d"
+      }
+    ],
+    "autocomplete": {
+      "background": "#000000",
+      "corner_radius": 6,
+      "padding": 6,
+      "border": {
+        "color": "#232323",
+        "width": 1
+      },
+      "item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        }
+      },
+      "hovered_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#ffffff14"
+      },
+      "margin": {
+        "left": -14
+      },
+      "match_highlight": {
+        "family": "Zed Mono",
+        "color": "#1096d3",
+        "size": 14
+      },
+      "selected_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#ffffff1f"
+      }
+    },
+    "diagnostic_header": {
+      "background": "#1c1c1c",
+      "icon_width_factor": 1.5,
+      "text_scale_factor": 0.857,
+      "border": {
+        "color": "#232323",
+        "width": 1,
+        "bottom": true,
+        "top": true
+      },
+      "code": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14,
+        "margin": {
+          "left": 10
+        }
+      },
+      "message": {
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f1f1f1",
+          "size": 14,
+          "weight": "bold"
+        },
+        "text": {
+          "family": "Zed Sans",
+          "color": "#9c9c9c",
+          "size": 14
+        }
+      }
+    },
+    "diagnostic_path_header": {
+      "background": "#ffffff12",
+      "text_scale_factor": 0.857,
+      "filename": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "path": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14,
+        "margin": {
+          "left": 12
+        }
+      }
+    },
+    "error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f15656",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f15656",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#f7bb57",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#f7bb57",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#070707",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "syntax": {
+      "keyword": "#4f8ff7",
+      "function": "#f9da82",
+      "string": "#f99d5f",
+      "type": "#3eeeda",
+      "number": "#aeef4b",
+      "comment": "#aaaaaa",
+      "property": "#4f8ff7",
+      "variant": "#53c1f5",
+      "constant": "#d5d5d5",
+      "title": {
+        "color": "#de900c",
+        "weight": "bold"
+      },
+      "emphasis": "#1096d3",
+      "emphasis_strong": {
+        "color": "#1096d3",
+        "weight": "bold"
+      },
+      "link_uri": {
+        "color": "#79ba16",
+        "underline": true
+      },
+      "link_text": {
+        "color": "#ee670a",
+        "italic": true
+      },
+      "list_marker": "#c6c6c6"
+    }
+  },
+  "project_diagnostics": {
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 13,
+    "tab_summary_spacing": 10,
+    "empty_message": {
+      "family": "Zed Sans",
+      "color": "#f1f1f1",
+      "size": 18
+    },
+    "status_bar_item": {
+      "family": "Zed Sans",
+      "color": "#808080",
+      "size": 14,
+      "margin": {
+        "right": 10
+      }
+    }
+  },
+  "project_panel": {
+    "padding": {
+      "top": 6,
+      "left": 12
+    },
+    "entry": {
+      "height": 22,
+      "icon_color": "#555555",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#9c9c9c",
+        "size": 14
+      }
+    },
+    "hovered_entry": {
+      "height": 22,
+      "background": "#232323",
+      "icon_color": "#555555",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#9c9c9c",
+        "size": 14
+      }
+    },
+    "selected_entry": {
+      "height": 22,
+      "icon_color": "#555555",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      }
+    },
+    "hovered_selected_entry": {
+      "height": 22,
+      "background": "#232323",
+      "icon_color": "#555555",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      }
+    }
+  },
+  "chat_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "channel_name": {
+      "family": "Zed Sans",
+      "color": "#f1f1f1",
+      "weight": "bold",
+      "size": 14
+    },
+    "channel_name_hash": {
+      "family": "Zed Sans",
+      "color": "#808080",
+      "size": 14,
+      "padding": {
+        "right": 8
+      }
+    },
+    "channel_select": {
+      "header": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#f1f1f1",
+          "size": 14
+        },
+        "padding": {
+          "bottom": 4,
+          "left": 0
+        },
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#9c9c9c",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#9c9c9c",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#232323",
+        "corner_radius": 6
+      },
+      "active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#f1f1f1",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#f1f1f1",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#808080",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#232323",
+        "corner_radius": 6
+      },
+      "menu": {
+        "background": "#000000",
+        "corner_radius": 6,
+        "padding": 4,
+        "border": {
+          "color": "#070707",
+          "width": 1
+        },
+        "shadow": {
+          "blur": 16,
+          "color": "#00000052",
+          "offset": [
+            0,
+            2
+          ]
+        }
+      }
+    },
+    "sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#9c9c9c",
+      "underline": true,
+      "size": 14
+    },
+    "hovered_sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#f1f1f1",
+      "underline": true,
+      "size": 14
+    },
+    "message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#9c9c9c",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#f1f1f1",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "pending_message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "input_editor": {
+      "background": "#000000",
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "border": {
+        "color": "#232323",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 8,
+        "right": 8,
+        "top": 7
+      }
+    }
+  },
+  "contacts_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "host_row_height": 28,
+    "tree_branch_color": "#404040",
+    "tree_branch_width": 1,
+    "host_avatar": {
+      "corner_radius": 10,
+      "width": 18
+    },
+    "host_username": {
+      "family": "Zed Mono",
+      "color": "#f1f1f1",
+      "size": 14,
+      "padding": {
+        "left": 8
+      }
+    },
+    "project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#9c9c9c",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#1c1c1c",
+      "corner_radius": 6
+    },
+    "hovered_shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#9c9c9c",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#232323",
+      "corner_radius": 6
+    },
+    "unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "corner_radius": 6
+    }
+  },
+  "search": {
+    "match_background": "#1096d329",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 14,
+    "active_hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#9c9c9c",
+      "size": 14,
+      "background": "#2b2b2b",
+      "corner_radius": 6,
+      "border": {
+        "color": "#070707",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "active_option_button": {
+      "family": "Zed Mono",
+      "color": "#9c9c9c",
+      "size": 14,
+      "background": "#2b2b2b",
+      "corner_radius": 6,
+      "border": {
+        "color": "#070707",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "editor": {
+      "background": "#000000",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "border": {
+        "color": "#232323",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#9c9c9c",
+      "size": 14,
+      "background": "#2b2b2b",
+      "corner_radius": 6,
+      "border": {
+        "color": "#070707",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "invalid_editor": {
+      "background": "#000000",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#f1f1f1",
+        "size": 14
+      },
+      "border": {
+        "color": "#eb2d2d",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "match_index": {
+      "family": "Zed Mono",
+      "color": "#808080",
+      "size": 14,
+      "padding": 6
+    },
+    "option_button": {
+      "family": "Zed Mono",
+      "color": "#9c9c9c",
+      "size": 14,
+      "background": "#1c1c1c",
+      "corner_radius": 6,
+      "border": {
+        "color": "#070707",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "option_button_group": {
+      "padding": {
+        "left": 2,
+        "right": 2
+      }
+    },
+    "results_status": {
+      "family": "Zed Mono",
+      "color": "#f1f1f1",
+      "size": 18
+    }
+  },
+  "breadcrumbs": {
+    "family": "Zed Sans",
+    "color": "#f1f1f1",
+    "size": 14,
+    "padding": {
+      "left": 6
+    }
+  }
+}

crates/zed/assets/themes/dark.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#283340"
-1 = "#1C2733"
-2 = "#1C2733"
-
-[border]
-0 = "#1B222B"
-1 = "#FFFFFF20"
-
-[text]
-0 = { extends = "$text.base", color = "#FFFFFF" }
-1 = { extends = "$text.base", color = "#CDD1E2" }
-2 = { extends = "$text.base", color = "#9BA8BE" }
-3 = { extends = "$text.base", color = "#6E7483" }
-
-[shadow]
-0 = "#00000052"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#00000022"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#00000033"
-selected = "#00000088"
-
-[editor.syntax]
-keyword = { color = "#0086c0", weight = "bold" }
-function = "#dcdcaa"
-string = "#cb8f77"
-type = "#4ec9b0"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#9cdcfe"
-title = { color = "#9cdcfe", weight = "bold" }
-emphasis = "#4ec9b0"
-"emphasis.strong" = { color = "#4ec9b0", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#cb8f77", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000aa"

crates/zed/assets/themes/light.json 🔗

@@ -0,0 +1,1285 @@
+{
+  "selector": {
+    "background": "#f8f8f8",
+    "corner_radius": 6,
+    "padding": 8,
+    "item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#474747",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#1b1edc",
+        "weight": "bold",
+        "size": 14
+      }
+    },
+    "active_item": {
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 4
+      },
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Sans",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "highlight_text": {
+        "family": "Zed Sans",
+        "color": "#1b1edc",
+        "weight": "bold",
+        "size": 14
+      },
+      "background": "#dcdcdc"
+    },
+    "border": {
+      "color": "#d5d5d5",
+      "width": 1
+    },
+    "empty": {
+      "text": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 4,
+        "left": 16,
+        "right": 16,
+        "top": 8
+      }
+    },
+    "input_editor": {
+      "background": "#ffffff",
+      "corner_radius": 6,
+      "placeholder_text": {
+        "family": "Zed Sans",
+        "color": "#808080",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 16,
+        "right": 16,
+        "top": 7
+      }
+    },
+    "margin": {
+      "bottom": 52,
+      "top": 52
+    },
+    "shadow": {
+      "blur": 16,
+      "color": "#0000001f",
+      "offset": [
+        0,
+        2
+      ]
+    }
+  },
+  "workspace": {
+    "background": "#f8f8f8",
+    "leader_border_opacity": 0.7,
+    "leader_border_width": 2,
+    "tab": {
+      "height": 32,
+      "background": "#f8f8f8",
+      "icon_close": "#9c9c9c",
+      "icon_close_active": "#000000",
+      "icon_conflict": "#f7bf17",
+      "icon_dirty": "#135acd",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "left": true,
+        "bottom": true,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "active_tab": {
+      "height": 32,
+      "background": "#ffffff",
+      "icon_close": "#9c9c9c",
+      "icon_close_active": "#000000",
+      "icon_conflict": "#f7bf17",
+      "icon_dirty": "#135acd",
+      "icon_width": 8,
+      "spacing": 10,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#000000",
+        "size": 14
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "left": true,
+        "bottom": false,
+        "overlay": true
+      },
+      "padding": {
+        "left": 12,
+        "right": 12
+      }
+    },
+    "left_sidebar": {
+      "width": 30,
+      "background": "#f8f8f8",
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "right": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#717171",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#000000",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d5d5d5",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "right_sidebar": {
+      "width": 30,
+      "background": "#f8f8f8",
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "left": true
+      },
+      "item": {
+        "height": 32,
+        "icon_color": "#717171",
+        "icon_size": 18
+      },
+      "active_item": {
+        "height": 32,
+        "icon_color": "#000000",
+        "icon_size": 18
+      },
+      "resize_handle": {
+        "background": "#d5d5d5",
+        "padding": {
+          "left": 1
+        }
+      }
+    },
+    "pane_divider": {
+      "color": "#d5d5d5",
+      "width": 1
+    },
+    "status_bar": {
+      "height": 24,
+      "item_spacing": 8,
+      "padding": {
+        "left": 6,
+        "right": 6
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "top": true,
+        "overlay": true
+      },
+      "cursor_position": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      },
+      "diagnostic_message": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      },
+      "lsp_message": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      }
+    },
+    "titlebar": {
+      "avatar_width": 18,
+      "height": 32,
+      "background": "#eaeaea",
+      "share_icon_color": "#717171",
+      "share_icon_active_color": "#484bed",
+      "title": {
+        "family": "Zed Sans",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "avatar": {
+        "corner_radius": 10,
+        "border": {
+          "color": "#00000088",
+          "width": 1
+        }
+      },
+      "avatar_ribbon": {
+        "height": 3,
+        "width": 12
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "bottom": true
+      },
+      "sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#474747",
+        "size": 12,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "hovered_sign_in_prompt": {
+        "family": "Zed Sans",
+        "color": "#000000",
+        "size": 12,
+        "underline": true,
+        "padding": {
+          "right": 8
+        }
+      },
+      "offline_icon": {
+        "color": "#717171",
+        "width": 16,
+        "padding": {
+          "right": 4
+        }
+      },
+      "outdated_warning": {
+        "family": "Zed Sans",
+        "color": "#d3a20b",
+        "size": 13
+      }
+    },
+    "toolbar": {
+      "height": 34,
+      "background": "#ffffff",
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "bottom": true
+      },
+      "item_spacing": 8,
+      "padding": {
+        "left": 16,
+        "right": 8,
+        "top": 4,
+        "bottom": 4
+      }
+    },
+    "breadcrumbs": {
+      "family": "Zed Mono",
+      "color": "#474747",
+      "size": 14,
+      "padding": {
+        "left": 6
+      }
+    },
+    "disconnected_overlay": {
+      "family": "Zed Sans",
+      "color": "#000000",
+      "size": 14,
+      "background": "#000000aa"
+    }
+  },
+  "editor": {
+    "text_color": "#1c1c1c",
+    "background": "#ffffff",
+    "active_line_background": "#0000000f",
+    "code_actions_indicator": "#9c9c9c",
+    "diff_background_deleted": "#fcc6c6",
+    "diff_background_inserted": "#b7f9ce",
+    "document_highlight_read_background": "#0000000f",
+    "document_highlight_write_background": "#00000029",
+    "error_color": "#eb2d2d",
+    "gutter_background": "#ffffff",
+    "gutter_padding_factor": 3.5,
+    "highlighted_line_background": "#0000001f",
+    "line_number": "#aaaaaa",
+    "line_number_active": "#000000",
+    "rename_fade": 0.6,
+    "unnecessary_code_fade": 0.5,
+    "selection": {
+      "cursor": "#2472f2",
+      "selection": "#2472f23d"
+    },
+    "guest_selections": [
+      {
+        "cursor": "#12d796",
+        "selection": "#12d7963d"
+      },
+      {
+        "cursor": "#de57e8",
+        "selection": "#de57e83d"
+      },
+      {
+        "cursor": "#f9812e",
+        "selection": "#f9812e3d"
+      },
+      {
+        "cursor": "#b066f8",
+        "selection": "#b066f83d"
+      },
+      {
+        "cursor": "#16d6c1",
+        "selection": "#16d6c13d"
+      },
+      {
+        "cursor": "#ef59a3",
+        "selection": "#ef59a33d"
+      },
+      {
+        "cursor": "#f7bf17",
+        "selection": "#f7bf173d"
+      }
+    ],
+    "autocomplete": {
+      "background": "#ffffff",
+      "corner_radius": 6,
+      "padding": 6,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        }
+      },
+      "hovered_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#00000008"
+      },
+      "margin": {
+        "left": -14
+      },
+      "match_highlight": {
+        "family": "Zed Mono",
+        "color": "#1b1edc",
+        "size": 14
+      },
+      "selected_item": {
+        "corner_radius": 6,
+        "padding": {
+          "bottom": 2,
+          "left": 6,
+          "right": 6,
+          "top": 2
+        },
+        "background": "#0000000f"
+      }
+    },
+    "diagnostic_header": {
+      "background": "#f8f8f8",
+      "icon_width_factor": 1.5,
+      "text_scale_factor": 0.857,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1,
+        "bottom": true,
+        "top": true
+      },
+      "code": {
+        "family": "Zed Mono",
+        "color": "#636363",
+        "size": 14,
+        "margin": {
+          "left": 10
+        }
+      },
+      "message": {
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#2b2b2b",
+          "size": 14,
+          "weight": "bold"
+        },
+        "text": {
+          "family": "Zed Sans",
+          "color": "#474747",
+          "size": 14
+        }
+      }
+    },
+    "diagnostic_path_header": {
+      "background": "#0000000f",
+      "text_scale_factor": 0.857,
+      "filename": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "path": {
+        "family": "Zed Mono",
+        "color": "#636363",
+        "size": 14,
+        "margin": {
+          "left": 12
+        }
+      }
+    },
+    "error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#eb2d2d",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#eb2d2d",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#d3a20b",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#d3a20b",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#2472f2",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_error_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_hint_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_information_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "invalid_warning_diagnostic": {
+      "text_scale_factor": 0.857,
+      "header": {
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1,
+          "top": true
+        }
+      },
+      "message": {
+        "text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14
+        },
+        "highlight_text": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "weight": "bold"
+        }
+      }
+    },
+    "syntax": {
+      "keyword": "#1819a1",
+      "function": "#bb550e",
+      "string": "#eb2d2d",
+      "type": "#a8820e",
+      "number": "#484bed",
+      "comment": "#717171",
+      "property": "#106c4e",
+      "variant": "#97142a",
+      "constant": "#1c1c1c",
+      "title": {
+        "color": "#1096d3",
+        "weight": "bold"
+      },
+      "emphasis": "#1b1edc",
+      "emphasis_strong": {
+        "color": "#1b1edc",
+        "weight": "bold"
+      },
+      "link_uri": {
+        "color": "#79ba16",
+        "underline": true
+      },
+      "link_text": {
+        "color": "#eb2d2d",
+        "italic": true
+      },
+      "list_marker": "#555555"
+    }
+  },
+  "project_diagnostics": {
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 13,
+    "tab_summary_spacing": 10,
+    "empty_message": {
+      "family": "Zed Sans",
+      "color": "#2b2b2b",
+      "size": 18
+    },
+    "status_bar_item": {
+      "family": "Zed Sans",
+      "color": "#636363",
+      "size": 14,
+      "margin": {
+        "right": 10
+      }
+    }
+  },
+  "project_panel": {
+    "padding": {
+      "top": 6,
+      "left": 12
+    },
+    "entry": {
+      "height": 22,
+      "icon_color": "#9c9c9c",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      }
+    },
+    "hovered_entry": {
+      "height": 22,
+      "background": "#eaeaea",
+      "icon_color": "#9c9c9c",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14
+      }
+    },
+    "selected_entry": {
+      "height": 22,
+      "icon_color": "#9c9c9c",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      }
+    },
+    "hovered_selected_entry": {
+      "height": 22,
+      "background": "#eaeaea",
+      "icon_color": "#9c9c9c",
+      "icon_size": 8,
+      "icon_spacing": 8,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      }
+    }
+  },
+  "chat_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "channel_name": {
+      "family": "Zed Sans",
+      "color": "#2b2b2b",
+      "weight": "bold",
+      "size": 14
+    },
+    "channel_name_hash": {
+      "family": "Zed Sans",
+      "color": "#636363",
+      "size": 14,
+      "padding": {
+        "right": 8
+      }
+    },
+    "channel_select": {
+      "header": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#2b2b2b",
+          "size": 14
+        },
+        "padding": {
+          "bottom": 4,
+          "left": 0
+        },
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#474747",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#474747",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#eaeaea",
+        "corner_radius": 6
+      },
+      "active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#2b2b2b",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "corner_radius": 0
+      },
+      "hovered_active_item": {
+        "name": {
+          "family": "Zed Sans",
+          "color": "#2b2b2b",
+          "size": 14
+        },
+        "padding": 4,
+        "hash": {
+          "family": "Zed Sans",
+          "color": "#636363",
+          "size": 14,
+          "margin": {
+            "right": 8
+          }
+        },
+        "background": "#eaeaea",
+        "corner_radius": 6
+      },
+      "menu": {
+        "background": "#ffffff",
+        "corner_radius": 6,
+        "padding": 4,
+        "border": {
+          "color": "#d5d5d5",
+          "width": 1
+        },
+        "shadow": {
+          "blur": 16,
+          "color": "#0000001f",
+          "offset": [
+            0,
+            2
+          ]
+        }
+      }
+    },
+    "sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#474747",
+      "underline": true,
+      "size": 14
+    },
+    "hovered_sign_in_prompt": {
+      "family": "Zed Sans",
+      "color": "#2b2b2b",
+      "underline": true,
+      "size": 14
+    },
+    "message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#474747",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#2b2b2b",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "pending_message": {
+      "body": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      },
+      "timestamp": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "size": 14
+      },
+      "padding": {
+        "bottom": 6
+      },
+      "sender": {
+        "family": "Zed Sans",
+        "color": "#636363",
+        "weight": "bold",
+        "size": 14,
+        "margin": {
+          "right": 8
+        }
+      }
+    },
+    "input_editor": {
+      "background": "#ffffff",
+      "corner_radius": 6,
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "padding": {
+        "bottom": 7,
+        "left": 8,
+        "right": 8,
+        "top": 7
+      }
+    }
+  },
+  "contacts_panel": {
+    "padding": {
+      "top": 12,
+      "left": 12,
+      "bottom": 12,
+      "right": 12
+    },
+    "host_row_height": 28,
+    "tree_branch_color": "#e3e3e3",
+    "tree_branch_width": 1,
+    "host_avatar": {
+      "corner_radius": 10,
+      "width": 18
+    },
+    "host_username": {
+      "family": "Zed Mono",
+      "color": "#2b2b2b",
+      "size": 14,
+      "padding": {
+        "left": 8
+      }
+    },
+    "project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#f8f8f8",
+      "corner_radius": 6
+    },
+    "hovered_shared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#474747",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "background": "#eaeaea",
+      "corner_radius": 6
+    },
+    "unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      }
+    },
+    "hovered_unshared_project": {
+      "guest_avatar_spacing": 4,
+      "height": 24,
+      "guest_avatar": {
+        "corner_radius": 8,
+        "width": 14
+      },
+      "name": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14,
+        "margin": {
+          "right": 6
+        }
+      },
+      "padding": {
+        "left": 8
+      },
+      "corner_radius": 6
+    }
+  },
+  "search": {
+    "match_background": "#eb2d2d33",
+    "tab_icon_spacing": 4,
+    "tab_icon_width": 14,
+    "active_hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#474747",
+      "size": 14,
+      "background": "#eaeaea",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "active_option_button": {
+      "family": "Zed Mono",
+      "color": "#474747",
+      "size": 14,
+      "background": "#eaeaea",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "editor": {
+      "background": "#ffffff",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "hovered_option_button": {
+      "family": "Zed Mono",
+      "color": "#474747",
+      "size": 14,
+      "background": "#eaeaea",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "invalid_editor": {
+      "background": "#ffffff",
+      "corner_radius": 6,
+      "min_width": 200,
+      "max_width": 500,
+      "placeholder_text": {
+        "family": "Zed Mono",
+        "color": "#808080",
+        "size": 14
+      },
+      "selection": {
+        "cursor": "#2472f2",
+        "selection": "#2472f23d"
+      },
+      "text": {
+        "family": "Zed Mono",
+        "color": "#2b2b2b",
+        "size": 14
+      },
+      "border": {
+        "color": "#f9a0a0",
+        "width": 1
+      },
+      "margin": {
+        "right": 5
+      },
+      "padding": {
+        "top": 3,
+        "bottom": 3,
+        "left": 14,
+        "right": 14
+      }
+    },
+    "match_index": {
+      "family": "Zed Mono",
+      "color": "#636363",
+      "size": 14,
+      "padding": 6
+    },
+    "option_button": {
+      "family": "Zed Mono",
+      "color": "#474747",
+      "size": 14,
+      "background": "#f8f8f8",
+      "corner_radius": 6,
+      "border": {
+        "color": "#d5d5d5",
+        "width": 1
+      },
+      "margin": {
+        "left": 1,
+        "right": 1
+      },
+      "padding": {
+        "bottom": 1,
+        "left": 6,
+        "right": 6,
+        "top": 1
+      }
+    },
+    "option_button_group": {
+      "padding": {
+        "left": 2,
+        "right": 2
+      }
+    },
+    "results_status": {
+      "family": "Zed Mono",
+      "color": "#2b2b2b",
+      "size": 18
+    }
+  },
+  "breadcrumbs": {
+    "family": "Zed Sans",
+    "color": "#2b2b2b",
+    "size": 14,
+    "padding": {
+      "left": 6
+    }
+  }
+}

crates/zed/assets/themes/light.toml 🔗

@@ -1,67 +0,0 @@
-extends = "_base"
-
-[surface]
-0 = "#EAEAEB"
-1 = "#FAFAFA"
-2 = "#FFFFFF"
-
-[border]
-0 = "#DDDDDC"
-1 = "#0000000F"
-
-[text]
-0 = { extends = "$text.base", color = "#000000" }
-1 = { extends = "$text.base", color = "#29292B" }
-2 = { extends = "$text.base", color = "#7E7E83" }
-3 = { extends = "$text.base", color = "#939393" }
-
-[shadow]
-0 = "#0000000D"
-
-[selection]
-host = { selection = "#3B57BC55", cursor = "$text.0.color" }
-guests = [
-  { selection = "#D0453B33", cursor = "#D0453B" },
-  { selection = "#3B874B33", cursor = "#3B874B" },
-  { selection = "#BD7CB433", cursor = "#BD7CB4" },
-  { selection = "#EE823133", cursor = "#EE8231" },
-  { selection = "#5A2B9233", cursor = "#5A2B92" },
-  { selection = "#FDF35133", cursor = "#FDF351" },
-  { selection = "#4EACAD33", cursor = "#4EACAD" },
-]
-
-[status]
-good = "#4fac63"
-info = "#3c5dd4"
-warn = "#faca50"
-bad = "#b7372e"
-
-[state]
-active_line = "#00000008"
-highlighted_line = "#faca5033"
-deleted_line = "#dd000036"
-inserted_line = "#00dd0036"
-hover = "#0000000D"
-selected = "#0000001c"
-
-[editor.syntax]
-keyword = { color = "#0000fa", weight = "bold" }
-function = "#795e26"
-string = "#a82121"
-type = "#267f29"
-number = "#b5cea8"
-comment = "#6a9955"
-property = "#4e94ce"
-variant = "#4fc1ff"
-constant = "#5a9ccc"
-title = { color = "#5a9ccc", weight = "bold" }
-emphasis = "#267f29"
-"emphasis.strong" = { color = "#267f29", weight = "bold" }
-link_uri = { color = "#6a9955", underline = true }
-link_text = { color = "#a82121", italic = true }
-list_marker = "#4e94ce"
-
-[workspace.disconnected_overlay]
-extends = "$text.base"
-color = "#ffffff"
-background = "#000000cc"

crates/zed/src/zed.rs 🔗

@@ -1001,7 +1001,8 @@ mod tests {
         lazy_static::lazy_static! {
             static ref DEFAULT_THEME: parking_lot::Mutex<Option<Arc<Theme>>> = Default::default();
             static ref FONTS: Vec<Arc<Vec<u8>>> = vec![
-                Assets.load("fonts/zed-sans/zed-sans-extended.ttf").unwrap().to_vec().into()
+                Assets.load("fonts/zed-sans/zed-sans-extended.ttf").unwrap().to_vec().into(),
+                Assets.load("fonts/zed-mono/zed-mono-extended.ttf").unwrap().to_vec().into(),
             ];
         }
 

styles/dist/core.json 🔗

@@ -0,0 +1,1155 @@
+{
+  "color": {
+    "neutral": {
+      "0": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "25": {
+        "value": "#f8f8f8",
+        "step": 25,
+        "type": "color"
+      },
+      "50": {
+        "value": "#f1f1f1",
+        "step": 50,
+        "type": "color"
+      },
+      "75": {
+        "value": "#eaeaea",
+        "step": 75,
+        "type": "color"
+      },
+      "100": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      },
+      "125": {
+        "value": "#dcdcdc",
+        "step": 125,
+        "type": "color"
+      },
+      "150": {
+        "value": "#d5d5d5",
+        "step": 150,
+        "type": "color"
+      },
+      "175": {
+        "value": "#cdcdcd",
+        "step": 175,
+        "type": "color"
+      },
+      "200": {
+        "value": "#c6c6c6",
+        "step": 200,
+        "type": "color"
+      },
+      "225": {
+        "value": "#bfbfbf",
+        "step": 225,
+        "type": "color"
+      },
+      "250": {
+        "value": "#b8b8b8",
+        "step": 250,
+        "type": "color"
+      },
+      "275": {
+        "value": "#b1b1b1",
+        "step": 275,
+        "type": "color"
+      },
+      "300": {
+        "value": "#aaaaaa",
+        "step": 300,
+        "type": "color"
+      },
+      "325": {
+        "value": "#a3a3a3",
+        "step": 325,
+        "type": "color"
+      },
+      "350": {
+        "value": "#9c9c9c",
+        "step": 350,
+        "type": "color"
+      },
+      "375": {
+        "value": "#959595",
+        "step": 375,
+        "type": "color"
+      },
+      "400": {
+        "value": "#8e8e8e",
+        "step": 400,
+        "type": "color"
+      },
+      "425": {
+        "value": "#878787",
+        "step": 425,
+        "type": "color"
+      },
+      "450": {
+        "value": "#808080",
+        "step": 450,
+        "type": "color"
+      },
+      "475": {
+        "value": "#787878",
+        "step": 475,
+        "type": "color"
+      },
+      "500": {
+        "value": "#717171",
+        "step": 500,
+        "type": "color"
+      },
+      "525": {
+        "value": "#6a6a6a",
+        "step": 525,
+        "type": "color"
+      },
+      "550": {
+        "value": "#636363",
+        "step": 550,
+        "type": "color"
+      },
+      "575": {
+        "value": "#5c5c5c",
+        "step": 575,
+        "type": "color"
+      },
+      "600": {
+        "value": "#555555",
+        "step": 600,
+        "type": "color"
+      },
+      "625": {
+        "value": "#4e4e4e",
+        "step": 625,
+        "type": "color"
+      },
+      "650": {
+        "value": "#474747",
+        "step": 650,
+        "type": "color"
+      },
+      "675": {
+        "value": "#404040",
+        "step": 675,
+        "type": "color"
+      },
+      "700": {
+        "value": "#393939",
+        "step": 700,
+        "type": "color"
+      },
+      "725": {
+        "value": "#323232",
+        "step": 725,
+        "type": "color"
+      },
+      "750": {
+        "value": "#2b2b2b",
+        "step": 750,
+        "type": "color"
+      },
+      "775": {
+        "value": "#232323",
+        "step": 775,
+        "type": "color"
+      },
+      "800": {
+        "value": "#1c1c1c",
+        "step": 800,
+        "type": "color"
+      },
+      "825": {
+        "value": "#151515",
+        "step": 825,
+        "type": "color"
+      },
+      "850": {
+        "value": "#0e0e0e",
+        "step": 850,
+        "type": "color"
+      },
+      "875": {
+        "value": "#070707",
+        "step": 875,
+        "type": "color"
+      },
+      "900": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "rose": {
+      "0": {
+        "value": "#feecef",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fcc5cf",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#fa9fae",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f8788e",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#f5526e",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#f0284a",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#cd1434",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#97142a",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#64101e",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#330a11",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "red": {
+      "0": {
+        "value": "#feecec",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#f9a0a0",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f57b7b",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#eb2d2d",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#c91818",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#951515",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#631111",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#330a0a",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "orange": {
+      "0": {
+        "value": "#fef3ec",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fcd6bd",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#fab98e",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f99d5f",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#f9812e",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#ee670a",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#bb550e",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#8b4210",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#5d2f0e",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#331b0a",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "amber": {
+      "0": {
+        "value": "#fef7ec",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fce2ba",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#f9ce89",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#f6a724",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#de900c",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#b0740f",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#845910",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#5a3e0e",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#33240a",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "yellow": {
+      "0": {
+        "value": "#fef9ec",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fce9b7",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#f9da82",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f8cc4d",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#d3a20b",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#a8820e",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#7e630f",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#58460e",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#33290a",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "lime": {
+      "0": {
+        "value": "#f7feec",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#dffab5",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#c7f57f",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#aeef4b",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#96e818",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#79ba16",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#639714",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#4e7412",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#38530f",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#23330a",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "green": {
+      "0": {
+        "value": "#ecfef2",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#84f2ab",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#54e989",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#27dd69",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#20b456",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#157338",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#105328",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a3319",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "emerald": {
+      "0": {
+        "value": "#ecfef8",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#b0fae1",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#74f6cb",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#39f0b3",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#12d796",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#10a977",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#118a62",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#106c4e",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#0d4f3a",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a3326",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "teal": {
+      "0": {
+        "value": "#ecfefc",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#b1faf2",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#76f5e7",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#3eeeda",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#16d6c1",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#14a898",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#138a7d",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#116c62",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#0e4f48",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a332f",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "cyan": {
+      "0": {
+        "value": "#ecfcfe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#b2f3fb",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#78eaf9",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#3de2f8",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#07d5f1",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#09aac0",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#0c8a9a",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#0e6a75",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#0d4c53",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a2f33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "sky": {
+      "0": {
+        "value": "#ecf8fe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#b9e5fb",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#86d3f8",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#53c1f5",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#20b0f2",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#1096d3",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#1179a8",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#115c7f",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#0e4158",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a2633",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "blue": {
+      "0": {
+        "value": "#ecf3fe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#9ec1fa",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#76a8f8",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#4f8ff7",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#135acd",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#134697",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#103063",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a1a33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "indigo": {
+      "0": {
+        "value": "#ececfe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#cdcdfc",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#aeaff9",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#9091f6",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#7274f3",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#484bed",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#1b1edc",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#1819a1",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#121269",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#0a0a33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "violet": {
+      "0": {
+        "value": "#f1ecfe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#daccfc",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#c3acfb",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#ac8cf9",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#966cf7",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#7741f2",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#5316e0",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#3f15a3",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#2b116a",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#160a33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "purple": {
+      "0": {
+        "value": "#f5ecfe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#e4cbfc",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#d2a9fb",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#c188f9",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#b066f8",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#993bf3",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#7b14dd",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#5c14a1",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#3e1169",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#1f0a33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "fuschia": {
+      "0": {
+        "value": "#fdecfe",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#f8c5fb",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#f19ff6",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#e87af0",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#de57e8",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#d430e0",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#b31fbc",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#87198e",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#5c1260",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#310a33",
+        "step": 900,
+        "type": "color"
+      }
+    },
+    "pink": {
+      "0": {
+        "value": "#feecf5",
+        "step": 0,
+        "type": "color"
+      },
+      "100": {
+        "value": "#fbc6e1",
+        "step": 100,
+        "type": "color"
+      },
+      "200": {
+        "value": "#f8a1cc",
+        "step": 200,
+        "type": "color"
+      },
+      "300": {
+        "value": "#f47db8",
+        "step": 300,
+        "type": "color"
+      },
+      "400": {
+        "value": "#ef59a3",
+        "step": 400,
+        "type": "color"
+      },
+      "500": {
+        "value": "#e8318c",
+        "step": 500,
+        "type": "color"
+      },
+      "600": {
+        "value": "#c71a71",
+        "step": 600,
+        "type": "color"
+      },
+      "700": {
+        "value": "#941756",
+        "step": 700,
+        "type": "color"
+      },
+      "800": {
+        "value": "#63113b",
+        "step": 800,
+        "type": "color"
+      },
+      "900": {
+        "value": "#330a1f",
+        "step": 900,
+        "type": "color"
+      }
+    }
+  },
+  "text": {
+    "family": {
+      "sans": {
+        "value": "Zed Sans",
+        "type": "fontFamily"
+      },
+      "mono": {
+        "value": "Zed Mono",
+        "type": "fontFamily"
+      }
+    },
+    "weight": {
+      "thin": {
+        "value": "thin",
+        "type": "fontWeight"
+      },
+      "extra_light": {
+        "value": "extra_light",
+        "type": "fontWeight"
+      },
+      "light": {
+        "value": "light",
+        "type": "fontWeight"
+      },
+      "normal": {
+        "value": "normal",
+        "type": "fontWeight"
+      },
+      "medium": {
+        "value": "medium",
+        "type": "fontWeight"
+      },
+      "semibold": {
+        "value": "semibold",
+        "type": "fontWeight"
+      },
+      "bold": {
+        "value": "bold",
+        "type": "fontWeight"
+      },
+      "extra_bold": {
+        "value": "extra_bold",
+        "type": "fontWeight"
+      },
+      "black": {
+        "value": "black",
+        "type": "fontWeight"
+      }
+    }
+  },
+  "size": {
+    "3xs": {
+      "value": 8,
+      "type": "fontSize"
+    },
+    "2xs": {
+      "value": 10,
+      "type": "fontSize"
+    },
+    "xs": {
+      "value": 12,
+      "type": "fontSize"
+    },
+    "sm": {
+      "value": 14,
+      "type": "fontSize"
+    },
+    "md": {
+      "value": 16,
+      "type": "fontSize"
+    },
+    "lg": {
+      "value": 18,
+      "type": "fontSize"
+    },
+    "xl": {
+      "value": 20,
+      "type": "fontSize"
+    }
+  }
+}

styles/dist/dark.json 🔗

@@ -0,0 +1,637 @@
+{
+  "meta": {
+    "themeName": "dark"
+  },
+  "text": {
+    "primary": {
+      "value": "#f1f1f1",
+      "step": 50,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#9c9c9c",
+      "step": 350,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#808080",
+      "step": 450,
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#474747",
+      "step": 650,
+      "type": "color"
+    },
+    "active": {
+      "value": "#ffffff",
+      "step": 0,
+      "type": "color"
+    },
+    "feature": {
+      "value": "#1096d3",
+      "step": 500,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#1b9447",
+      "step": 600,
+      "type": "color"
+    },
+    "error": {
+      "value": "#f15656",
+      "step": 400,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#f7bb57",
+      "step": 300,
+      "type": "color"
+    },
+    "info": {
+      "value": "#2472f2",
+      "step": 500,
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#c6c6c6",
+      "step": 200,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#9c9c9c",
+      "step": 350,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#555555",
+      "step": 600,
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#393939",
+      "step": 700,
+      "type": "color"
+    },
+    "active": {
+      "value": "#ffffff",
+      "step": 0,
+      "type": "color"
+    },
+    "feature": {
+      "value": "#2472f2",
+      "step": 500,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#1b9447",
+      "step": 600,
+      "type": "color"
+    },
+    "error": {
+      "value": "#eb2d2d",
+      "step": 500,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#f6a724",
+      "step": 400,
+      "type": "color"
+    },
+    "info": {
+      "value": "#135acd",
+      "step": 600,
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#2b2b2b",
+        "step": 750,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#323232",
+        "step": 725,
+        "type": "color"
+      },
+      "active": {
+        "value": "#1c1c1c",
+        "step": 800,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#404040",
+        "step": 675,
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#1c1c1c",
+        "step": 800,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#232323",
+        "step": 775,
+        "type": "color"
+      },
+      "active": {
+        "value": "#2b2b2b",
+        "step": 750,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#232323",
+        "step": 775,
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#ffffff14",
+        "step": 0,
+        "type": "color"
+      },
+      "active": {
+        "value": "#ffffff1f",
+        "step": 0,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#151515",
+        "step": 825,
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "active": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "active": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      },
+      "active": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "active": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#070707",
+      "step": 875,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#232323",
+      "step": 775,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#404040",
+      "step": 675,
+      "type": "color"
+    },
+    "focused": {
+      "value": "#717171",
+      "step": 500,
+      "type": "color"
+    },
+    "active": {
+      "value": "#000000",
+      "step": 900,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#20b456",
+      "step": 500,
+      "type": "color"
+    },
+    "error": {
+      "value": "#eb2d2d",
+      "step": 500,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#de900c",
+      "step": 500,
+      "type": "color"
+    },
+    "info": {
+      "value": "#2472f2",
+      "step": 500,
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#000000",
+      "step": 900,
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#404040",
+      "step": 675,
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#232323",
+      "step": 775,
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#ffffff12",
+        "step": 0,
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#ffffff1f",
+        "step": 0,
+        "type": "color"
+      },
+      "inserted": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "deleted": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "modified": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#2472f23d",
+        "step": 500,
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#ffffff1f",
+        "step": 0,
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#ffffff29",
+        "step": 0,
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#ffffff1f",
+        "step": 0,
+        "type": "color"
+      },
+      "match": {
+        "value": "#1096d329",
+        "step": 500,
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#0e415852",
+        "step": 800,
+        "type": "color"
+      },
+      "related": {
+        "value": "#151515",
+        "step": 825,
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#474747",
+        "step": 650,
+        "type": "color"
+      },
+      "active": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#d5d5d5",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#aaaaaa",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#4f8ff7",
+      "type": "color"
+    },
+    "function": {
+      "value": "#f9da82",
+      "type": "color"
+    },
+    "type": {
+      "value": "#3eeeda",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#53c1f5",
+      "type": "color"
+    },
+    "property": {
+      "value": "#4f8ff7",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#ee670a",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#ee670a",
+      "type": "color"
+    },
+    "string": {
+      "value": "#f99d5f",
+      "type": "color"
+    },
+    "number": {
+      "value": "#aeef4b",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#aeef4b",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#2472f23d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#2472f2cc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#79ba16",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#79ba16",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#79ba163d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#79ba16cc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#d430e0",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#d430e0",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#d430e03d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#d430e0cc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#ee670a",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#ee670a",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#ee670a3d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#ee670acc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#993bf3",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#993bf3",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#993bf33d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#993bf3cc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#16d6c1",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#16d6c1",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#16d6c13d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#16d6c1cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#ef59a3",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#ef59a3",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#ef59a33d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#ef59a3cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#f7bf173d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#f7bf17cc",
+        "step": 400,
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.32,
+    "type": "number"
+  }
+}

styles/dist/light.json 🔗

@@ -0,0 +1,637 @@
+{
+  "meta": {
+    "themeName": "light"
+  },
+  "text": {
+    "primary": {
+      "value": "#2b2b2b",
+      "step": 750,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#474747",
+      "step": 650,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#636363",
+      "step": 550,
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#808080",
+      "step": 450,
+      "type": "color"
+    },
+    "active": {
+      "value": "#000000",
+      "step": 900,
+      "type": "color"
+    },
+    "feature": {
+      "value": "#484bed",
+      "step": 500,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#20b456",
+      "step": 500,
+      "type": "color"
+    },
+    "error": {
+      "value": "#eb2d2d",
+      "step": 500,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#d3a20b",
+      "step": 500,
+      "type": "color"
+    },
+    "info": {
+      "value": "#2472f2",
+      "step": 500,
+      "type": "color"
+    }
+  },
+  "icon": {
+    "primary": {
+      "value": "#393939",
+      "step": 700,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#717171",
+      "step": 500,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#9c9c9c",
+      "step": 350,
+      "type": "color"
+    },
+    "placeholder": {
+      "value": "#aaaaaa",
+      "step": 300,
+      "type": "color"
+    },
+    "active": {
+      "value": "#000000",
+      "step": 900,
+      "type": "color"
+    },
+    "feature": {
+      "value": "#484bed",
+      "step": 500,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#1b9447",
+      "step": 600,
+      "type": "color"
+    },
+    "error": {
+      "value": "#c91818",
+      "step": 600,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#f7bf17",
+      "step": 400,
+      "type": "color"
+    },
+    "info": {
+      "value": "#135acd",
+      "step": 600,
+      "type": "color"
+    }
+  },
+  "background": {
+    "100": {
+      "base": {
+        "value": "#eaeaea",
+        "step": 75,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#d5d5d5",
+        "step": 150,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      }
+    },
+    "300": {
+      "base": {
+        "value": "#f8f8f8",
+        "step": 25,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#eaeaea",
+        "step": 75,
+        "type": "color"
+      },
+      "active": {
+        "value": "#dcdcdc",
+        "step": 125,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#eaeaea",
+        "step": 75,
+        "type": "color"
+      }
+    },
+    "500": {
+      "base": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#00000008",
+        "step": 900,
+        "type": "color"
+      },
+      "active": {
+        "value": "#0000000f",
+        "step": 900,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#f1f1f1",
+        "step": 50,
+        "type": "color"
+      }
+    },
+    "ok": {
+      "base": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      }
+    },
+    "error": {
+      "base": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      }
+    },
+    "warning": {
+      "base": {
+        "value": "#fce9b7",
+        "step": 100,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#fce9b7",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#fce9b7",
+        "step": 100,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#fce9b7",
+        "step": 100,
+        "type": "color"
+      }
+    },
+    "info": {
+      "base": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      },
+      "hovered": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      }
+    }
+  },
+  "border": {
+    "primary": {
+      "value": "#d5d5d5",
+      "step": 150,
+      "type": "color"
+    },
+    "secondary": {
+      "value": "#d5d5d5",
+      "step": 150,
+      "type": "color"
+    },
+    "muted": {
+      "value": "#e3e3e3",
+      "step": 100,
+      "type": "color"
+    },
+    "focused": {
+      "value": "#e3e3e3",
+      "step": 100,
+      "type": "color"
+    },
+    "active": {
+      "value": "#b8b8b8",
+      "step": 250,
+      "type": "color"
+    },
+    "ok": {
+      "value": "#84f2ab",
+      "step": 200,
+      "type": "color"
+    },
+    "error": {
+      "value": "#f9a0a0",
+      "step": 200,
+      "type": "color"
+    },
+    "warning": {
+      "value": "#f9da82",
+      "step": 200,
+      "type": "color"
+    },
+    "info": {
+      "value": "#9ec1fa",
+      "step": 200,
+      "type": "color"
+    }
+  },
+  "editor": {
+    "background": {
+      "value": "#ffffff",
+      "step": 0,
+      "type": "color"
+    },
+    "indent_guide": {
+      "value": "#e3e3e3",
+      "step": 100,
+      "type": "color"
+    },
+    "indent_guide_active": {
+      "value": "#d5d5d5",
+      "step": 150,
+      "type": "color"
+    },
+    "line": {
+      "active": {
+        "value": "#0000000f",
+        "step": 900,
+        "type": "color"
+      },
+      "highlighted": {
+        "value": "#0000001f",
+        "step": 900,
+        "type": "color"
+      },
+      "inserted": {
+        "value": "#b7f9ce",
+        "step": 100,
+        "type": "color"
+      },
+      "deleted": {
+        "value": "#fcc6c6",
+        "step": 100,
+        "type": "color"
+      },
+      "modified": {
+        "value": "#c5dafc",
+        "step": 100,
+        "type": "color"
+      }
+    },
+    "highlight": {
+      "selection": {
+        "value": "#2472f23d",
+        "step": 500,
+        "type": "color"
+      },
+      "occurrence": {
+        "value": "#0000000f",
+        "step": 900,
+        "type": "color"
+      },
+      "activeOccurrence": {
+        "value": "#00000029",
+        "step": 900,
+        "type": "color"
+      },
+      "matchingBracket": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "match": {
+        "value": "#eb2d2d33",
+        "step": 500,
+        "type": "color"
+      },
+      "activeMatch": {
+        "value": "#7274f35c",
+        "step": 400,
+        "type": "color"
+      },
+      "related": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      }
+    },
+    "gutter": {
+      "primary": {
+        "value": "#aaaaaa",
+        "step": 300,
+        "type": "color"
+      },
+      "active": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      }
+    }
+  },
+  "syntax": {
+    "primary": {
+      "value": "#1c1c1c",
+      "type": "color"
+    },
+    "comment": {
+      "value": "#717171",
+      "type": "color"
+    },
+    "keyword": {
+      "value": "#1819a1",
+      "type": "color"
+    },
+    "function": {
+      "value": "#f9812e",
+      "type": "color"
+    },
+    "type": {
+      "value": "#de900c",
+      "type": "color"
+    },
+    "variant": {
+      "value": "#1096d3",
+      "type": "color"
+    },
+    "property": {
+      "value": "#118a62",
+      "type": "color"
+    },
+    "enum": {
+      "value": "#eb2d2d",
+      "type": "color"
+    },
+    "operator": {
+      "value": "#eb2d2d",
+      "type": "color"
+    },
+    "string": {
+      "value": "#eb2d2d",
+      "type": "color"
+    },
+    "number": {
+      "value": "#484bed",
+      "type": "color"
+    },
+    "boolean": {
+      "value": "#eb2d2d",
+      "type": "color"
+    }
+  },
+  "player": {
+    "1": {
+      "baseColor": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#2472f23d",
+        "step": 500,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#2472f2cc",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "2": {
+      "baseColor": {
+        "value": "#12d796",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#12d796",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#12d7963d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#12d796cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "3": {
+      "baseColor": {
+        "value": "#de57e8",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#de57e8",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#de57e83d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#de57e8cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "4": {
+      "baseColor": {
+        "value": "#f9812e",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#f9812e",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#f9812e3d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#f9812ecc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "5": {
+      "baseColor": {
+        "value": "#b066f8",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#b066f8",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#b066f83d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#b066f8cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "6": {
+      "baseColor": {
+        "value": "#16d6c1",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#16d6c1",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#16d6c13d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#16d6c1cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "7": {
+      "baseColor": {
+        "value": "#ef59a3",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#ef59a3",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#ef59a33d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#ef59a3cc",
+        "step": 400,
+        "type": "color"
+      }
+    },
+    "8": {
+      "baseColor": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "cursorColor": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "selectionColor": {
+        "value": "#f7bf173d",
+        "step": 400,
+        "type": "color"
+      },
+      "borderColor": {
+        "value": "#f7bf17cc",
+        "step": 400,
+        "type": "color"
+      }
+    }
+  },
+  "shadowAlpha": {
+    "value": 0.12,
+    "type": "number"
+  }
+}

styles/dist/tokens.json 🔗

@@ -0,0 +1,2431 @@
+{
+  "core": {
+    "color": {
+      "neutral": {
+        "0": {
+          "value": "#ffffff",
+          "step": 0,
+          "type": "color"
+        },
+        "25": {
+          "value": "#f8f8f8",
+          "step": 25,
+          "type": "color"
+        },
+        "50": {
+          "value": "#f1f1f1",
+          "step": 50,
+          "type": "color"
+        },
+        "75": {
+          "value": "#eaeaea",
+          "step": 75,
+          "type": "color"
+        },
+        "100": {
+          "value": "#e3e3e3",
+          "step": 100,
+          "type": "color"
+        },
+        "125": {
+          "value": "#dcdcdc",
+          "step": 125,
+          "type": "color"
+        },
+        "150": {
+          "value": "#d5d5d5",
+          "step": 150,
+          "type": "color"
+        },
+        "175": {
+          "value": "#cdcdcd",
+          "step": 175,
+          "type": "color"
+        },
+        "200": {
+          "value": "#c6c6c6",
+          "step": 200,
+          "type": "color"
+        },
+        "225": {
+          "value": "#bfbfbf",
+          "step": 225,
+          "type": "color"
+        },
+        "250": {
+          "value": "#b8b8b8",
+          "step": 250,
+          "type": "color"
+        },
+        "275": {
+          "value": "#b1b1b1",
+          "step": 275,
+          "type": "color"
+        },
+        "300": {
+          "value": "#aaaaaa",
+          "step": 300,
+          "type": "color"
+        },
+        "325": {
+          "value": "#a3a3a3",
+          "step": 325,
+          "type": "color"
+        },
+        "350": {
+          "value": "#9c9c9c",
+          "step": 350,
+          "type": "color"
+        },
+        "375": {
+          "value": "#959595",
+          "step": 375,
+          "type": "color"
+        },
+        "400": {
+          "value": "#8e8e8e",
+          "step": 400,
+          "type": "color"
+        },
+        "425": {
+          "value": "#878787",
+          "step": 425,
+          "type": "color"
+        },
+        "450": {
+          "value": "#808080",
+          "step": 450,
+          "type": "color"
+        },
+        "475": {
+          "value": "#787878",
+          "step": 475,
+          "type": "color"
+        },
+        "500": {
+          "value": "#717171",
+          "step": 500,
+          "type": "color"
+        },
+        "525": {
+          "value": "#6a6a6a",
+          "step": 525,
+          "type": "color"
+        },
+        "550": {
+          "value": "#636363",
+          "step": 550,
+          "type": "color"
+        },
+        "575": {
+          "value": "#5c5c5c",
+          "step": 575,
+          "type": "color"
+        },
+        "600": {
+          "value": "#555555",
+          "step": 600,
+          "type": "color"
+        },
+        "625": {
+          "value": "#4e4e4e",
+          "step": 625,
+          "type": "color"
+        },
+        "650": {
+          "value": "#474747",
+          "step": 650,
+          "type": "color"
+        },
+        "675": {
+          "value": "#404040",
+          "step": 675,
+          "type": "color"
+        },
+        "700": {
+          "value": "#393939",
+          "step": 700,
+          "type": "color"
+        },
+        "725": {
+          "value": "#323232",
+          "step": 725,
+          "type": "color"
+        },
+        "750": {
+          "value": "#2b2b2b",
+          "step": 750,
+          "type": "color"
+        },
+        "775": {
+          "value": "#232323",
+          "step": 775,
+          "type": "color"
+        },
+        "800": {
+          "value": "#1c1c1c",
+          "step": 800,
+          "type": "color"
+        },
+        "825": {
+          "value": "#151515",
+          "step": 825,
+          "type": "color"
+        },
+        "850": {
+          "value": "#0e0e0e",
+          "step": 850,
+          "type": "color"
+        },
+        "875": {
+          "value": "#070707",
+          "step": 875,
+          "type": "color"
+        },
+        "900": {
+          "value": "#000000",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "rose": {
+        "0": {
+          "value": "#feecef",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fcc5cf",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#fa9fae",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f8788e",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#f5526e",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#f0284a",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#cd1434",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#97142a",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#64101e",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#330a11",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "red": {
+        "0": {
+          "value": "#feecec",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#f9a0a0",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f57b7b",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#eb2d2d",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#c91818",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#951515",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#631111",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#330a0a",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "orange": {
+        "0": {
+          "value": "#fef3ec",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fcd6bd",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#fab98e",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f99d5f",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#f9812e",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#ee670a",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#bb550e",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#8b4210",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#5d2f0e",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#331b0a",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "amber": {
+        "0": {
+          "value": "#fef7ec",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fce2ba",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#f9ce89",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f7bb57",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#f6a724",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#de900c",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#b0740f",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#845910",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#5a3e0e",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#33240a",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "yellow": {
+        "0": {
+          "value": "#fef9ec",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fce9b7",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#f9da82",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f8cc4d",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#f7bf17",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#d3a20b",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#a8820e",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#7e630f",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#58460e",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#33290a",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "lime": {
+        "0": {
+          "value": "#f7feec",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#dffab5",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#c7f57f",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#aeef4b",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#96e818",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#79ba16",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#639714",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#4e7412",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#38530f",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#23330a",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "green": {
+        "0": {
+          "value": "#ecfef2",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#84f2ab",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#54e989",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#27dd69",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#20b456",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#157338",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#105328",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a3319",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "emerald": {
+        "0": {
+          "value": "#ecfef8",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#b0fae1",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#74f6cb",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#39f0b3",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#12d796",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#10a977",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#118a62",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#106c4e",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#0d4f3a",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a3326",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "teal": {
+        "0": {
+          "value": "#ecfefc",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#b1faf2",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#76f5e7",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#3eeeda",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#16d6c1",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#14a898",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#138a7d",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#116c62",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#0e4f48",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a332f",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "cyan": {
+        "0": {
+          "value": "#ecfcfe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#b2f3fb",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#78eaf9",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#3de2f8",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#07d5f1",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#09aac0",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#0c8a9a",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#0e6a75",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#0d4c53",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a2f33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "sky": {
+        "0": {
+          "value": "#ecf8fe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#b9e5fb",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#86d3f8",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#53c1f5",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#20b0f2",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#1096d3",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#1179a8",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#115c7f",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#0e4158",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a2633",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "blue": {
+        "0": {
+          "value": "#ecf3fe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#9ec1fa",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#76a8f8",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#4f8ff7",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#135acd",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#134697",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#103063",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a1a33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "indigo": {
+        "0": {
+          "value": "#ececfe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#cdcdfc",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#aeaff9",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#9091f6",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#7274f3",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#484bed",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#1b1edc",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#1819a1",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#121269",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#0a0a33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "violet": {
+        "0": {
+          "value": "#f1ecfe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#daccfc",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#c3acfb",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#ac8cf9",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#966cf7",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#7741f2",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#5316e0",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#3f15a3",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#2b116a",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#160a33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "purple": {
+        "0": {
+          "value": "#f5ecfe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#e4cbfc",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#d2a9fb",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#c188f9",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#b066f8",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#993bf3",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#7b14dd",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#5c14a1",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#3e1169",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#1f0a33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "fuschia": {
+        "0": {
+          "value": "#fdecfe",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#f8c5fb",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#f19ff6",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#e87af0",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#de57e8",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#d430e0",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#b31fbc",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#87198e",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#5c1260",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#310a33",
+          "step": 900,
+          "type": "color"
+        }
+      },
+      "pink": {
+        "0": {
+          "value": "#feecf5",
+          "step": 0,
+          "type": "color"
+        },
+        "100": {
+          "value": "#fbc6e1",
+          "step": 100,
+          "type": "color"
+        },
+        "200": {
+          "value": "#f8a1cc",
+          "step": 200,
+          "type": "color"
+        },
+        "300": {
+          "value": "#f47db8",
+          "step": 300,
+          "type": "color"
+        },
+        "400": {
+          "value": "#ef59a3",
+          "step": 400,
+          "type": "color"
+        },
+        "500": {
+          "value": "#e8318c",
+          "step": 500,
+          "type": "color"
+        },
+        "600": {
+          "value": "#c71a71",
+          "step": 600,
+          "type": "color"
+        },
+        "700": {
+          "value": "#941756",
+          "step": 700,
+          "type": "color"
+        },
+        "800": {
+          "value": "#63113b",
+          "step": 800,
+          "type": "color"
+        },
+        "900": {
+          "value": "#330a1f",
+          "step": 900,
+          "type": "color"
+        }
+      }
+    },
+    "text": {
+      "family": {
+        "sans": {
+          "value": "Zed Sans",
+          "type": "fontFamily"
+        },
+        "mono": {
+          "value": "Zed Mono",
+          "type": "fontFamily"
+        }
+      },
+      "weight": {
+        "thin": {
+          "value": "thin",
+          "type": "fontWeight"
+        },
+        "extra_light": {
+          "value": "extra_light",
+          "type": "fontWeight"
+        },
+        "light": {
+          "value": "light",
+          "type": "fontWeight"
+        },
+        "normal": {
+          "value": "normal",
+          "type": "fontWeight"
+        },
+        "medium": {
+          "value": "medium",
+          "type": "fontWeight"
+        },
+        "semibold": {
+          "value": "semibold",
+          "type": "fontWeight"
+        },
+        "bold": {
+          "value": "bold",
+          "type": "fontWeight"
+        },
+        "extra_bold": {
+          "value": "extra_bold",
+          "type": "fontWeight"
+        },
+        "black": {
+          "value": "black",
+          "type": "fontWeight"
+        }
+      }
+    },
+    "size": {
+      "3xs": {
+        "value": 8,
+        "type": "fontSize"
+      },
+      "2xs": {
+        "value": 10,
+        "type": "fontSize"
+      },
+      "xs": {
+        "value": 12,
+        "type": "fontSize"
+      },
+      "sm": {
+        "value": 14,
+        "type": "fontSize"
+      },
+      "md": {
+        "value": 16,
+        "type": "fontSize"
+      },
+      "lg": {
+        "value": 18,
+        "type": "fontSize"
+      },
+      "xl": {
+        "value": 20,
+        "type": "fontSize"
+      }
+    }
+  },
+  "dark": {
+    "meta": {
+      "themeName": "dark"
+    },
+    "text": {
+      "primary": {
+        "value": "#f1f1f1",
+        "step": 50,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#9c9c9c",
+        "step": 350,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#808080",
+        "step": 450,
+        "type": "color"
+      },
+      "placeholder": {
+        "value": "#474747",
+        "step": 650,
+        "type": "color"
+      },
+      "active": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "feature": {
+        "value": "#1096d3",
+        "step": 500,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "error": {
+        "value": "#f15656",
+        "step": 400,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#f7bb57",
+        "step": 300,
+        "type": "color"
+      },
+      "info": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "icon": {
+      "primary": {
+        "value": "#c6c6c6",
+        "step": 200,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#9c9c9c",
+        "step": 350,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#555555",
+        "step": 600,
+        "type": "color"
+      },
+      "placeholder": {
+        "value": "#393939",
+        "step": 700,
+        "type": "color"
+      },
+      "active": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "feature": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "error": {
+        "value": "#eb2d2d",
+        "step": 500,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#f6a724",
+        "step": 400,
+        "type": "color"
+      },
+      "info": {
+        "value": "#135acd",
+        "step": 600,
+        "type": "color"
+      }
+    },
+    "background": {
+      "100": {
+        "base": {
+          "value": "#2b2b2b",
+          "step": 750,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#323232",
+          "step": 725,
+          "type": "color"
+        },
+        "active": {
+          "value": "#1c1c1c",
+          "step": 800,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#404040",
+          "step": 675,
+          "type": "color"
+        }
+      },
+      "300": {
+        "base": {
+          "value": "#1c1c1c",
+          "step": 800,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#232323",
+          "step": 775,
+          "type": "color"
+        },
+        "active": {
+          "value": "#2b2b2b",
+          "step": 750,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#232323",
+          "step": 775,
+          "type": "color"
+        }
+      },
+      "500": {
+        "base": {
+          "value": "#000000",
+          "step": 900,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#ffffff14",
+          "step": 0,
+          "type": "color"
+        },
+        "active": {
+          "value": "#ffffff1f",
+          "step": 0,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#151515",
+          "step": 825,
+          "type": "color"
+        }
+      },
+      "ok": {
+        "base": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        },
+        "active": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        }
+      },
+      "error": {
+        "base": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        },
+        "active": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "warning": {
+        "base": {
+          "value": "#f7bb57",
+          "step": 300,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#f7bb57",
+          "step": 300,
+          "type": "color"
+        },
+        "active": {
+          "value": "#f7bb57",
+          "step": 300,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#f7bb57",
+          "step": 300,
+          "type": "color"
+        }
+      },
+      "info": {
+        "base": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "active": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        }
+      }
+    },
+    "border": {
+      "primary": {
+        "value": "#070707",
+        "step": 875,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#232323",
+        "step": 775,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#404040",
+        "step": 675,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#717171",
+        "step": 500,
+        "type": "color"
+      },
+      "active": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#20b456",
+        "step": 500,
+        "type": "color"
+      },
+      "error": {
+        "value": "#eb2d2d",
+        "step": 500,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#de900c",
+        "step": 500,
+        "type": "color"
+      },
+      "info": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "editor": {
+      "background": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      },
+      "indent_guide": {
+        "value": "#404040",
+        "step": 675,
+        "type": "color"
+      },
+      "indent_guide_active": {
+        "value": "#232323",
+        "step": 775,
+        "type": "color"
+      },
+      "line": {
+        "active": {
+          "value": "#ffffff12",
+          "step": 0,
+          "type": "color"
+        },
+        "highlighted": {
+          "value": "#ffffff1f",
+          "step": 0,
+          "type": "color"
+        },
+        "inserted": {
+          "value": "#1b9447",
+          "step": 600,
+          "type": "color"
+        },
+        "deleted": {
+          "value": "#f15656",
+          "step": 400,
+          "type": "color"
+        },
+        "modified": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "highlight": {
+        "selection": {
+          "value": "#2472f23d",
+          "step": 500,
+          "type": "color"
+        },
+        "occurrence": {
+          "value": "#ffffff1f",
+          "step": 0,
+          "type": "color"
+        },
+        "activeOccurrence": {
+          "value": "#ffffff29",
+          "step": 0,
+          "type": "color"
+        },
+        "matchingBracket": {
+          "value": "#ffffff1f",
+          "step": 0,
+          "type": "color"
+        },
+        "match": {
+          "value": "#1096d329",
+          "step": 500,
+          "type": "color"
+        },
+        "activeMatch": {
+          "value": "#0e415852",
+          "step": 800,
+          "type": "color"
+        },
+        "related": {
+          "value": "#151515",
+          "step": 825,
+          "type": "color"
+        }
+      },
+      "gutter": {
+        "primary": {
+          "value": "#474747",
+          "step": 650,
+          "type": "color"
+        },
+        "active": {
+          "value": "#ffffff",
+          "step": 0,
+          "type": "color"
+        }
+      }
+    },
+    "syntax": {
+      "primary": {
+        "value": "#d5d5d5",
+        "type": "color"
+      },
+      "comment": {
+        "value": "#aaaaaa",
+        "type": "color"
+      },
+      "keyword": {
+        "value": "#4f8ff7",
+        "type": "color"
+      },
+      "function": {
+        "value": "#f9da82",
+        "type": "color"
+      },
+      "type": {
+        "value": "#3eeeda",
+        "type": "color"
+      },
+      "variant": {
+        "value": "#53c1f5",
+        "type": "color"
+      },
+      "property": {
+        "value": "#4f8ff7",
+        "type": "color"
+      },
+      "enum": {
+        "value": "#ee670a",
+        "type": "color"
+      },
+      "operator": {
+        "value": "#ee670a",
+        "type": "color"
+      },
+      "string": {
+        "value": "#f99d5f",
+        "type": "color"
+      },
+      "number": {
+        "value": "#aeef4b",
+        "type": "color"
+      },
+      "boolean": {
+        "value": "#aeef4b",
+        "type": "color"
+      }
+    },
+    "player": {
+      "1": {
+        "baseColor": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#2472f23d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#2472f2cc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "2": {
+        "baseColor": {
+          "value": "#79ba16",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#79ba16",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#79ba163d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#79ba16cc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "3": {
+        "baseColor": {
+          "value": "#d430e0",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#d430e0",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#d430e03d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#d430e0cc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "4": {
+        "baseColor": {
+          "value": "#ee670a",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#ee670a",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#ee670a3d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#ee670acc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "5": {
+        "baseColor": {
+          "value": "#993bf3",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#993bf3",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#993bf33d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#993bf3cc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "6": {
+        "baseColor": {
+          "value": "#16d6c1",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#16d6c1",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#16d6c13d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#16d6c1cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "7": {
+        "baseColor": {
+          "value": "#ef59a3",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#ef59a3",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#ef59a33d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#ef59a3cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "8": {
+        "baseColor": {
+          "value": "#f7bf17",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#f7bf17",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#f7bf173d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#f7bf17cc",
+          "step": 400,
+          "type": "color"
+        }
+      }
+    },
+    "shadowAlpha": {
+      "value": 0.32,
+      "type": "number"
+    }
+  },
+  "light": {
+    "meta": {
+      "themeName": "light"
+    },
+    "text": {
+      "primary": {
+        "value": "#2b2b2b",
+        "step": 750,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#474747",
+        "step": 650,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#636363",
+        "step": 550,
+        "type": "color"
+      },
+      "placeholder": {
+        "value": "#808080",
+        "step": 450,
+        "type": "color"
+      },
+      "active": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      },
+      "feature": {
+        "value": "#484bed",
+        "step": 500,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#20b456",
+        "step": 500,
+        "type": "color"
+      },
+      "error": {
+        "value": "#eb2d2d",
+        "step": 500,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#d3a20b",
+        "step": 500,
+        "type": "color"
+      },
+      "info": {
+        "value": "#2472f2",
+        "step": 500,
+        "type": "color"
+      }
+    },
+    "icon": {
+      "primary": {
+        "value": "#393939",
+        "step": 700,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#717171",
+        "step": 500,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#9c9c9c",
+        "step": 350,
+        "type": "color"
+      },
+      "placeholder": {
+        "value": "#aaaaaa",
+        "step": 300,
+        "type": "color"
+      },
+      "active": {
+        "value": "#000000",
+        "step": 900,
+        "type": "color"
+      },
+      "feature": {
+        "value": "#484bed",
+        "step": 500,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#1b9447",
+        "step": 600,
+        "type": "color"
+      },
+      "error": {
+        "value": "#c91818",
+        "step": 600,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#f7bf17",
+        "step": 400,
+        "type": "color"
+      },
+      "info": {
+        "value": "#135acd",
+        "step": 600,
+        "type": "color"
+      }
+    },
+    "background": {
+      "100": {
+        "base": {
+          "value": "#eaeaea",
+          "step": 75,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#e3e3e3",
+          "step": 100,
+          "type": "color"
+        },
+        "active": {
+          "value": "#d5d5d5",
+          "step": 150,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#e3e3e3",
+          "step": 100,
+          "type": "color"
+        }
+      },
+      "300": {
+        "base": {
+          "value": "#f8f8f8",
+          "step": 25,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#eaeaea",
+          "step": 75,
+          "type": "color"
+        },
+        "active": {
+          "value": "#dcdcdc",
+          "step": 125,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#eaeaea",
+          "step": 75,
+          "type": "color"
+        }
+      },
+      "500": {
+        "base": {
+          "value": "#ffffff",
+          "step": 0,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#00000008",
+          "step": 900,
+          "type": "color"
+        },
+        "active": {
+          "value": "#0000000f",
+          "step": 900,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#f1f1f1",
+          "step": 50,
+          "type": "color"
+        }
+      },
+      "ok": {
+        "base": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        },
+        "active": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        }
+      },
+      "error": {
+        "base": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        },
+        "active": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        }
+      },
+      "warning": {
+        "base": {
+          "value": "#fce9b7",
+          "step": 100,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#fce9b7",
+          "step": 100,
+          "type": "color"
+        },
+        "active": {
+          "value": "#fce9b7",
+          "step": 100,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#fce9b7",
+          "step": 100,
+          "type": "color"
+        }
+      },
+      "info": {
+        "base": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        },
+        "hovered": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        },
+        "active": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        },
+        "focused": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        }
+      }
+    },
+    "border": {
+      "primary": {
+        "value": "#d5d5d5",
+        "step": 150,
+        "type": "color"
+      },
+      "secondary": {
+        "value": "#d5d5d5",
+        "step": 150,
+        "type": "color"
+      },
+      "muted": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      },
+      "focused": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      },
+      "active": {
+        "value": "#b8b8b8",
+        "step": 250,
+        "type": "color"
+      },
+      "ok": {
+        "value": "#84f2ab",
+        "step": 200,
+        "type": "color"
+      },
+      "error": {
+        "value": "#f9a0a0",
+        "step": 200,
+        "type": "color"
+      },
+      "warning": {
+        "value": "#f9da82",
+        "step": 200,
+        "type": "color"
+      },
+      "info": {
+        "value": "#9ec1fa",
+        "step": 200,
+        "type": "color"
+      }
+    },
+    "editor": {
+      "background": {
+        "value": "#ffffff",
+        "step": 0,
+        "type": "color"
+      },
+      "indent_guide": {
+        "value": "#e3e3e3",
+        "step": 100,
+        "type": "color"
+      },
+      "indent_guide_active": {
+        "value": "#d5d5d5",
+        "step": 150,
+        "type": "color"
+      },
+      "line": {
+        "active": {
+          "value": "#0000000f",
+          "step": 900,
+          "type": "color"
+        },
+        "highlighted": {
+          "value": "#0000001f",
+          "step": 900,
+          "type": "color"
+        },
+        "inserted": {
+          "value": "#b7f9ce",
+          "step": 100,
+          "type": "color"
+        },
+        "deleted": {
+          "value": "#fcc6c6",
+          "step": 100,
+          "type": "color"
+        },
+        "modified": {
+          "value": "#c5dafc",
+          "step": 100,
+          "type": "color"
+        }
+      },
+      "highlight": {
+        "selection": {
+          "value": "#2472f23d",
+          "step": 500,
+          "type": "color"
+        },
+        "occurrence": {
+          "value": "#0000000f",
+          "step": 900,
+          "type": "color"
+        },
+        "activeOccurrence": {
+          "value": "#00000029",
+          "step": 900,
+          "type": "color"
+        },
+        "matchingBracket": {
+          "value": "#ffffff",
+          "step": 0,
+          "type": "color"
+        },
+        "match": {
+          "value": "#eb2d2d33",
+          "step": 500,
+          "type": "color"
+        },
+        "activeMatch": {
+          "value": "#7274f35c",
+          "step": 400,
+          "type": "color"
+        },
+        "related": {
+          "value": "#ffffff",
+          "step": 0,
+          "type": "color"
+        }
+      },
+      "gutter": {
+        "primary": {
+          "value": "#aaaaaa",
+          "step": 300,
+          "type": "color"
+        },
+        "active": {
+          "value": "#000000",
+          "step": 900,
+          "type": "color"
+        }
+      }
+    },
+    "syntax": {
+      "primary": {
+        "value": "#1c1c1c",
+        "type": "color"
+      },
+      "comment": {
+        "value": "#717171",
+        "type": "color"
+      },
+      "keyword": {
+        "value": "#1819a1",
+        "type": "color"
+      },
+      "function": {
+        "value": "#f9812e",
+        "type": "color"
+      },
+      "type": {
+        "value": "#de900c",
+        "type": "color"
+      },
+      "variant": {
+        "value": "#1096d3",
+        "type": "color"
+      },
+      "property": {
+        "value": "#118a62",
+        "type": "color"
+      },
+      "enum": {
+        "value": "#eb2d2d",
+        "type": "color"
+      },
+      "operator": {
+        "value": "#eb2d2d",
+        "type": "color"
+      },
+      "string": {
+        "value": "#eb2d2d",
+        "type": "color"
+      },
+      "number": {
+        "value": "#484bed",
+        "type": "color"
+      },
+      "boolean": {
+        "value": "#eb2d2d",
+        "type": "color"
+      }
+    },
+    "player": {
+      "1": {
+        "baseColor": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#2472f2",
+          "step": 500,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#2472f23d",
+          "step": 500,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#2472f2cc",
+          "step": 500,
+          "type": "color"
+        }
+      },
+      "2": {
+        "baseColor": {
+          "value": "#12d796",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#12d796",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#12d7963d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#12d796cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "3": {
+        "baseColor": {
+          "value": "#de57e8",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#de57e8",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#de57e83d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#de57e8cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "4": {
+        "baseColor": {
+          "value": "#f9812e",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#f9812e",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#f9812e3d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#f9812ecc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "5": {
+        "baseColor": {
+          "value": "#b066f8",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#b066f8",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#b066f83d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#b066f8cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "6": {
+        "baseColor": {
+          "value": "#16d6c1",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#16d6c1",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#16d6c13d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#16d6c1cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "7": {
+        "baseColor": {
+          "value": "#ef59a3",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#ef59a3",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#ef59a33d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#ef59a3cc",
+          "step": 400,
+          "type": "color"
+        }
+      },
+      "8": {
+        "baseColor": {
+          "value": "#f7bf17",
+          "step": 400,
+          "type": "color"
+        },
+        "cursorColor": {
+          "value": "#f7bf17",
+          "step": 400,
+          "type": "color"
+        },
+        "selectionColor": {
+          "value": "#f7bf173d",
+          "step": 400,
+          "type": "color"
+        },
+        "borderColor": {
+          "value": "#f7bf17cc",
+          "step": 400,
+          "type": "color"
+        }
+      }
+    },
+    "shadowAlpha": {
+      "value": 0.12,
+      "type": "number"
+    }
+  }
+}

styles/nodemon.json 🔗

@@ -0,0 +1,8 @@
+{
+    "watch": [
+        "./**/*"
+    ],
+    "ext": "ts",
+    "ignore": [],
+    "exec": "ts-node src/buildThemes.ts"
+}

styles/package-lock.json 🔗

@@ -0,0 +1,2321 @@
+{
+    "name": "styles",
+    "version": "1.0.0",
+    "lockfileVersion": 2,
+    "requires": true,
+    "packages": {
+        "": {
+            "name": "styles",
+            "version": "1.0.0",
+            "license": "ISC",
+            "dependencies": {
+                "@types/chroma-js": "^2.1.3",
+                "@types/node": "^17.0.23",
+                "case-anything": "^2.1.10",
+                "chroma-js": "^2.4.2",
+                "nodemon": "^2.0.15",
+                "ts-node": "^10.7.0"
+            }
+        },
+        "node_modules/@cspotcode/source-map-consumer": {
+            "version": "0.8.0",
+            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
+            "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
+            "engines": {
+                "node": ">= 12"
+            }
+        },
+        "node_modules/@cspotcode/source-map-support": {
+            "version": "0.7.0",
+            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
+            "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+            "dependencies": {
+                "@cspotcode/source-map-consumer": "0.8.0"
+            },
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@sindresorhus/is": {
+            "version": "0.14.0",
+            "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+            "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/@szmarczak/http-timer": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+            "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+            "dependencies": {
+                "defer-to-connect": "^1.0.1"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/@tsconfig/node10": {
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
+            "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
+        },
+        "node_modules/@tsconfig/node12": {
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
+            "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
+        },
+        "node_modules/@tsconfig/node14": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
+            "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
+        },
+        "node_modules/@tsconfig/node16": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
+            "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
+        },
+        "node_modules/@types/chroma-js": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
+            "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
+        },
+        "node_modules/@types/node": {
+            "version": "17.0.23",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
+            "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+        },
+        "node_modules/abbrev": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+            "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+        },
+        "node_modules/acorn": {
+            "version": "8.7.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+            "bin": {
+                "acorn": "bin/acorn"
+            },
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
+        "node_modules/acorn-walk": {
+            "version": "8.2.0",
+            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
+        "node_modules/ansi-align": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+            "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+            "dependencies": {
+                "string-width": "^4.1.0"
+            }
+        },
+        "node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "dependencies": {
+                "color-convert": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/anymatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+            "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+            "dependencies": {
+                "normalize-path": "^3.0.0",
+                "picomatch": "^2.0.4"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
+        "node_modules/arg": {
+            "version": "4.1.3",
+            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+        },
+        "node_modules/balanced-match": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+        },
+        "node_modules/binary-extensions": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+            "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/boxen": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+            "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+            "dependencies": {
+                "ansi-align": "^3.0.0",
+                "camelcase": "^6.2.0",
+                "chalk": "^4.1.0",
+                "cli-boxes": "^2.2.1",
+                "string-width": "^4.2.2",
+                "type-fest": "^0.20.2",
+                "widest-line": "^3.1.0",
+                "wrap-ansi": "^7.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/braces": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+            "dependencies": {
+                "fill-range": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/cacheable-request": {
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+            "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+            "dependencies": {
+                "clone-response": "^1.0.2",
+                "get-stream": "^5.1.0",
+                "http-cache-semantics": "^4.0.0",
+                "keyv": "^3.0.0",
+                "lowercase-keys": "^2.0.0",
+                "normalize-url": "^4.1.0",
+                "responselike": "^1.0.2"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/cacheable-request/node_modules/get-stream": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+            "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+            "dependencies": {
+                "pump": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/cacheable-request/node_modules/lowercase-keys": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+            "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/camelcase": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+            "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/case-anything": {
+            "version": "2.1.10",
+            "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
+            "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==",
+            "engines": {
+                "node": ">=12.13"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/mesqueeb"
+            }
+        },
+        "node_modules/chalk": {
+            "version": "4.1.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+            "dependencies": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
+            }
+        },
+        "node_modules/chalk/node_modules/has-flag": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/chalk/node_modules/supports-color": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+            "dependencies": {
+                "has-flag": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/chokidar": {
+            "version": "3.5.3",
+            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+            "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+            "funding": [
+                {
+                    "type": "individual",
+                    "url": "https://paulmillr.com/funding/"
+                }
+            ],
+            "dependencies": {
+                "anymatch": "~3.1.2",
+                "braces": "~3.0.2",
+                "glob-parent": "~5.1.2",
+                "is-binary-path": "~2.1.0",
+                "is-glob": "~4.0.1",
+                "normalize-path": "~3.0.0",
+                "readdirp": "~3.6.0"
+            },
+            "engines": {
+                "node": ">= 8.10.0"
+            },
+            "optionalDependencies": {
+                "fsevents": "~2.3.2"
+            }
+        },
+        "node_modules/chroma-js": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
+            "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
+        },
+        "node_modules/ci-info": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+            "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
+        },
+        "node_modules/cli-boxes": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+            "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/clone-response": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+            "dependencies": {
+                "mimic-response": "^1.0.0"
+            }
+        },
+        "node_modules/color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "dependencies": {
+                "color-name": "~1.1.4"
+            },
+            "engines": {
+                "node": ">=7.0.0"
+            }
+        },
+        "node_modules/color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "node_modules/concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+        },
+        "node_modules/configstore": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
+            "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
+            "dependencies": {
+                "dot-prop": "^5.2.0",
+                "graceful-fs": "^4.1.2",
+                "make-dir": "^3.0.0",
+                "unique-string": "^2.0.0",
+                "write-file-atomic": "^3.0.0",
+                "xdg-basedir": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/create-require": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+        },
+        "node_modules/crypto-random-string": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+            "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/debug": {
+            "version": "3.2.7",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+            "dependencies": {
+                "ms": "^2.1.1"
+            }
+        },
+        "node_modules/decompress-response": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+            "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+            "dependencies": {
+                "mimic-response": "^1.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/deep-extend": {
+            "version": "0.6.0",
+            "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+            "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+            "engines": {
+                "node": ">=4.0.0"
+            }
+        },
+        "node_modules/defer-to-connect": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+            "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
+        },
+        "node_modules/diff": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+            "engines": {
+                "node": ">=0.3.1"
+            }
+        },
+        "node_modules/dot-prop": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+            "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+            "dependencies": {
+                "is-obj": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/duplexer3": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+        },
+        "node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "node_modules/end-of-stream": {
+            "version": "1.4.4",
+            "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+            "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+            "dependencies": {
+                "once": "^1.4.0"
+            }
+        },
+        "node_modules/escape-goat": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
+            "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/fill-range": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+            "dependencies": {
+                "to-regex-range": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/fsevents": {
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+            "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+            "hasInstallScript": true,
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+            }
+        },
+        "node_modules/get-stream": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+            "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+            "dependencies": {
+                "pump": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/glob-parent": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+            "dependencies": {
+                "is-glob": "^4.0.1"
+            },
+            "engines": {
+                "node": ">= 6"
+            }
+        },
+        "node_modules/global-dirs": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+            "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+            "dependencies": {
+                "ini": "2.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/got": {
+            "version": "9.6.0",
+            "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+            "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+            "dependencies": {
+                "@sindresorhus/is": "^0.14.0",
+                "@szmarczak/http-timer": "^1.1.2",
+                "cacheable-request": "^6.0.0",
+                "decompress-response": "^3.3.0",
+                "duplexer3": "^0.1.4",
+                "get-stream": "^4.1.0",
+                "lowercase-keys": "^1.0.1",
+                "mimic-response": "^1.0.1",
+                "p-cancelable": "^1.0.0",
+                "to-readable-stream": "^1.0.0",
+                "url-parse-lax": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8.6"
+            }
+        },
+        "node_modules/graceful-fs": {
+            "version": "4.2.9",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+            "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
+        },
+        "node_modules/has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/has-yarn": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+            "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/http-cache-semantics": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+            "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
+        },
+        "node_modules/ignore-by-default": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+        },
+        "node_modules/import-lazy": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "engines": {
+                "node": ">=0.8.19"
+            }
+        },
+        "node_modules/ini": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+            "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/is-binary-path": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+            "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+            "dependencies": {
+                "binary-extensions": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/is-ci": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+            "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+            "dependencies": {
+                "ci-info": "^2.0.0"
+            },
+            "bin": {
+                "is-ci": "bin.js"
+            }
+        },
+        "node_modules/is-extglob": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/is-fullwidth-code-point": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/is-glob": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+            "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+            "dependencies": {
+                "is-extglob": "^2.1.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/is-installed-globally": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+            "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+            "dependencies": {
+                "global-dirs": "^3.0.0",
+                "is-path-inside": "^3.0.2"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/is-npm": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz",
+            "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/is-number": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+            "engines": {
+                "node": ">=0.12.0"
+            }
+        },
+        "node_modules/is-obj": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+            "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/is-path-inside": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+            "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/is-typedarray": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+        },
+        "node_modules/is-yarn-global": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+            "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw=="
+        },
+        "node_modules/json-buffer": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+            "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
+        },
+        "node_modules/keyv": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+            "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+            "dependencies": {
+                "json-buffer": "3.0.0"
+            }
+        },
+        "node_modules/latest-version": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+            "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+            "dependencies": {
+                "package-json": "^6.3.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/lowercase-keys": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+            "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/lru-cache": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+            "dependencies": {
+                "yallist": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/make-dir": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+            "dependencies": {
+                "semver": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/make-dir/node_modules/semver": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+            "bin": {
+                "semver": "bin/semver.js"
+            }
+        },
+        "node_modules/make-error": {
+            "version": "1.3.6",
+            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+        },
+        "node_modules/mimic-response": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+            "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/minimist": {
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
+        },
+        "node_modules/ms": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+            "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+        },
+        "node_modules/nodemon": {
+            "version": "2.0.15",
+            "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz",
+            "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==",
+            "hasInstallScript": true,
+            "dependencies": {
+                "chokidar": "^3.5.2",
+                "debug": "^3.2.7",
+                "ignore-by-default": "^1.0.1",
+                "minimatch": "^3.0.4",
+                "pstree.remy": "^1.1.8",
+                "semver": "^5.7.1",
+                "supports-color": "^5.5.0",
+                "touch": "^3.1.0",
+                "undefsafe": "^2.0.5",
+                "update-notifier": "^5.1.0"
+            },
+            "bin": {
+                "nodemon": "bin/nodemon.js"
+            },
+            "engines": {
+                "node": ">=8.10.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/nodemon"
+            }
+        },
+        "node_modules/nopt": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+            "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+            "dependencies": {
+                "abbrev": "1"
+            },
+            "bin": {
+                "nopt": "bin/nopt.js"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/normalize-path": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+            "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/normalize-url": {
+            "version": "4.5.1",
+            "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+            "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "dependencies": {
+                "wrappy": "1"
+            }
+        },
+        "node_modules/p-cancelable": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+            "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/package-json": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+            "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+            "dependencies": {
+                "got": "^9.6.0",
+                "registry-auth-token": "^4.0.0",
+                "registry-url": "^5.0.0",
+                "semver": "^6.2.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/package-json/node_modules/semver": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+            "bin": {
+                "semver": "bin/semver.js"
+            }
+        },
+        "node_modules/picomatch": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+            "engines": {
+                "node": ">=8.6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/jonschlinkert"
+            }
+        },
+        "node_modules/prepend-http": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+            "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/pstree.remy": {
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+            "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
+        },
+        "node_modules/pump": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+            "dependencies": {
+                "end-of-stream": "^1.1.0",
+                "once": "^1.3.1"
+            }
+        },
+        "node_modules/pupa": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
+            "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
+            "dependencies": {
+                "escape-goat": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/rc": {
+            "version": "1.2.8",
+            "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+            "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+            "dependencies": {
+                "deep-extend": "^0.6.0",
+                "ini": "~1.3.0",
+                "minimist": "^1.2.0",
+                "strip-json-comments": "~2.0.1"
+            },
+            "bin": {
+                "rc": "cli.js"
+            }
+        },
+        "node_modules/rc/node_modules/ini": {
+            "version": "1.3.8",
+            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+            "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+        },
+        "node_modules/readdirp": {
+            "version": "3.6.0",
+            "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+            "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+            "dependencies": {
+                "picomatch": "^2.2.1"
+            },
+            "engines": {
+                "node": ">=8.10.0"
+            }
+        },
+        "node_modules/registry-auth-token": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
+            "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
+            "dependencies": {
+                "rc": "^1.2.8"
+            },
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
+        "node_modules/registry-url": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+            "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+            "dependencies": {
+                "rc": "^1.2.8"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/responselike": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+            "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+            "dependencies": {
+                "lowercase-keys": "^1.0.0"
+            }
+        },
+        "node_modules/semver": {
+            "version": "5.7.1",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+            "bin": {
+                "semver": "bin/semver"
+            }
+        },
+        "node_modules/semver-diff": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+            "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+            "dependencies": {
+                "semver": "^6.3.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/semver-diff/node_modules/semver": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+            "bin": {
+                "semver": "bin/semver.js"
+            }
+        },
+        "node_modules/signal-exit": {
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+        },
+        "node_modules/string-width": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/strip-json-comments": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/supports-color": {
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "dependencies": {
+                "has-flag": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/to-readable-stream": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+            "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/to-regex-range": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+            "dependencies": {
+                "is-number": "^7.0.0"
+            },
+            "engines": {
+                "node": ">=8.0"
+            }
+        },
+        "node_modules/touch": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+            "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+            "dependencies": {
+                "nopt": "~1.0.10"
+            },
+            "bin": {
+                "nodetouch": "bin/nodetouch.js"
+            }
+        },
+        "node_modules/ts-node": {
+            "version": "10.7.0",
+            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
+            "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+            "dependencies": {
+                "@cspotcode/source-map-support": "0.7.0",
+                "@tsconfig/node10": "^1.0.7",
+                "@tsconfig/node12": "^1.0.7",
+                "@tsconfig/node14": "^1.0.0",
+                "@tsconfig/node16": "^1.0.2",
+                "acorn": "^8.4.1",
+                "acorn-walk": "^8.1.1",
+                "arg": "^4.1.0",
+                "create-require": "^1.1.0",
+                "diff": "^4.0.1",
+                "make-error": "^1.1.1",
+                "v8-compile-cache-lib": "^3.0.0",
+                "yn": "3.1.1"
+            },
+            "bin": {
+                "ts-node": "dist/bin.js",
+                "ts-node-cwd": "dist/bin-cwd.js",
+                "ts-node-esm": "dist/bin-esm.js",
+                "ts-node-script": "dist/bin-script.js",
+                "ts-node-transpile-only": "dist/bin-transpile.js",
+                "ts-script": "dist/bin-script-deprecated.js"
+            },
+            "peerDependencies": {
+                "@swc/core": ">=1.2.50",
+                "@swc/wasm": ">=1.2.50",
+                "@types/node": "*",
+                "typescript": ">=2.7"
+            },
+            "peerDependenciesMeta": {
+                "@swc/core": {
+                    "optional": true
+                },
+                "@swc/wasm": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/type-fest": {
+            "version": "0.20.2",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/typedarray-to-buffer": {
+            "version": "3.1.5",
+            "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+            "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+            "dependencies": {
+                "is-typedarray": "^1.0.0"
+            }
+        },
+        "node_modules/typescript": {
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+            "peer": true,
+            "bin": {
+                "tsc": "bin/tsc",
+                "tsserver": "bin/tsserver"
+            },
+            "engines": {
+                "node": ">=4.2.0"
+            }
+        },
+        "node_modules/undefsafe": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+            "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
+        },
+        "node_modules/unique-string": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+            "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+            "dependencies": {
+                "crypto-random-string": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/update-notifier": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz",
+            "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==",
+            "dependencies": {
+                "boxen": "^5.0.0",
+                "chalk": "^4.1.0",
+                "configstore": "^5.0.1",
+                "has-yarn": "^2.1.0",
+                "import-lazy": "^2.1.0",
+                "is-ci": "^2.0.0",
+                "is-installed-globally": "^0.4.0",
+                "is-npm": "^5.0.0",
+                "is-yarn-global": "^0.3.0",
+                "latest-version": "^5.1.0",
+                "pupa": "^2.1.1",
+                "semver": "^7.3.4",
+                "semver-diff": "^3.1.1",
+                "xdg-basedir": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/yeoman/update-notifier?sponsor=1"
+            }
+        },
+        "node_modules/update-notifier/node_modules/semver": {
+            "version": "7.3.5",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+            "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+            "dependencies": {
+                "lru-cache": "^6.0.0"
+            },
+            "bin": {
+                "semver": "bin/semver.js"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/url-parse-lax": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+            "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+            "dependencies": {
+                "prepend-http": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/v8-compile-cache-lib": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
+            "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
+        },
+        "node_modules/widest-line": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+            "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+            "dependencies": {
+                "string-width": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/wrap-ansi": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
+        "node_modules/wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+        },
+        "node_modules/write-file-atomic": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+            "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+            "dependencies": {
+                "imurmurhash": "^0.1.4",
+                "is-typedarray": "^1.0.0",
+                "signal-exit": "^3.0.2",
+                "typedarray-to-buffer": "^3.1.5"
+            }
+        },
+        "node_modules/xdg-basedir": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
+            "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/yallist": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+        },
+        "node_modules/yn": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+            "engines": {
+                "node": ">=6"
+            }
+        }
+    },
+    "dependencies": {
+        "@cspotcode/source-map-consumer": {
+            "version": "0.8.0",
+            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
+            "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg=="
+        },
+        "@cspotcode/source-map-support": {
+            "version": "0.7.0",
+            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
+            "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+            "requires": {
+                "@cspotcode/source-map-consumer": "0.8.0"
+            }
+        },
+        "@sindresorhus/is": {
+            "version": "0.14.0",
+            "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+            "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ=="
+        },
+        "@szmarczak/http-timer": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+            "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+            "requires": {
+                "defer-to-connect": "^1.0.1"
+            }
+        },
+        "@tsconfig/node10": {
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
+            "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
+        },
+        "@tsconfig/node12": {
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
+            "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
+        },
+        "@tsconfig/node14": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
+            "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
+        },
+        "@tsconfig/node16": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
+            "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
+        },
+        "@types/chroma-js": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
+            "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
+        },
+        "@types/node": {
+            "version": "17.0.23",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
+            "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+        },
+        "abbrev": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+            "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+        },
+        "acorn": {
+            "version": "8.7.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
+        },
+        "acorn-walk": {
+            "version": "8.2.0",
+            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
+        },
+        "ansi-align": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+            "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+            "requires": {
+                "string-width": "^4.1.0"
+            }
+        },
+        "ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+        },
+        "ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "requires": {
+                "color-convert": "^2.0.1"
+            }
+        },
+        "anymatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+            "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+            "requires": {
+                "normalize-path": "^3.0.0",
+                "picomatch": "^2.0.4"
+            }
+        },
+        "arg": {
+            "version": "4.1.3",
+            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+        },
+        "balanced-match": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+        },
+        "binary-extensions": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+            "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+        },
+        "boxen": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+            "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+            "requires": {
+                "ansi-align": "^3.0.0",
+                "camelcase": "^6.2.0",
+                "chalk": "^4.1.0",
+                "cli-boxes": "^2.2.1",
+                "string-width": "^4.2.2",
+                "type-fest": "^0.20.2",
+                "widest-line": "^3.1.0",
+                "wrap-ansi": "^7.0.0"
+            }
+        },
+        "brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "braces": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+            "requires": {
+                "fill-range": "^7.0.1"
+            }
+        },
+        "cacheable-request": {
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+            "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+            "requires": {
+                "clone-response": "^1.0.2",
+                "get-stream": "^5.1.0",
+                "http-cache-semantics": "^4.0.0",
+                "keyv": "^3.0.0",
+                "lowercase-keys": "^2.0.0",
+                "normalize-url": "^4.1.0",
+                "responselike": "^1.0.2"
+            },
+            "dependencies": {
+                "get-stream": {
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+                    "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+                    "requires": {
+                        "pump": "^3.0.0"
+                    }
+                },
+                "lowercase-keys": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+                    "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
+                }
+            }
+        },
+        "camelcase": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+            "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="
+        },
+        "case-anything": {
+            "version": "2.1.10",
+            "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
+            "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ=="
+        },
+        "chalk": {
+            "version": "4.1.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+            "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
+            "dependencies": {
+                "has-flag": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+                },
+                "supports-color": {
+                    "version": "7.2.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+                    "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+                    "requires": {
+                        "has-flag": "^4.0.0"
+                    }
+                }
+            }
+        },
+        "chokidar": {
+            "version": "3.5.3",
+            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+            "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+            "requires": {
+                "anymatch": "~3.1.2",
+                "braces": "~3.0.2",
+                "fsevents": "~2.3.2",
+                "glob-parent": "~5.1.2",
+                "is-binary-path": "~2.1.0",
+                "is-glob": "~4.0.1",
+                "normalize-path": "~3.0.0",
+                "readdirp": "~3.6.0"
+            }
+        },
+        "chroma-js": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
+            "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
+        },
+        "ci-info": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+            "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
+        },
+        "cli-boxes": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+            "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw=="
+        },
+        "clone-response": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+            "requires": {
+                "mimic-response": "^1.0.0"
+            }
+        },
+        "color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "requires": {
+                "color-name": "~1.1.4"
+            }
+        },
+        "color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+        },
+        "configstore": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
+            "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
+            "requires": {
+                "dot-prop": "^5.2.0",
+                "graceful-fs": "^4.1.2",
+                "make-dir": "^3.0.0",
+                "unique-string": "^2.0.0",
+                "write-file-atomic": "^3.0.0",
+                "xdg-basedir": "^4.0.0"
+            }
+        },
+        "create-require": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+        },
+        "crypto-random-string": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+            "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="
+        },
+        "debug": {
+            "version": "3.2.7",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+            "requires": {
+                "ms": "^2.1.1"
+            }
+        },
+        "decompress-response": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+            "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+            "requires": {
+                "mimic-response": "^1.0.0"
+            }
+        },
+        "deep-extend": {
+            "version": "0.6.0",
+            "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+            "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+        },
+        "defer-to-connect": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+            "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
+        },
+        "diff": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+        },
+        "dot-prop": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+            "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+            "requires": {
+                "is-obj": "^2.0.0"
+            }
+        },
+        "duplexer3": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+        },
+        "emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "end-of-stream": {
+            "version": "1.4.4",
+            "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+            "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+            "requires": {
+                "once": "^1.4.0"
+            }
+        },
+        "escape-goat": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
+            "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q=="
+        },
+        "fill-range": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+            "requires": {
+                "to-regex-range": "^5.0.1"
+            }
+        },
+        "fsevents": {
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+            "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+            "optional": true
+        },
+        "get-stream": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+            "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+            "requires": {
+                "pump": "^3.0.0"
+            }
+        },
+        "glob-parent": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+            "requires": {
+                "is-glob": "^4.0.1"
+            }
+        },
+        "global-dirs": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+            "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+            "requires": {
+                "ini": "2.0.0"
+            }
+        },
+        "got": {
+            "version": "9.6.0",
+            "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+            "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+            "requires": {
+                "@sindresorhus/is": "^0.14.0",
+                "@szmarczak/http-timer": "^1.1.2",
+                "cacheable-request": "^6.0.0",
+                "decompress-response": "^3.3.0",
+                "duplexer3": "^0.1.4",
+                "get-stream": "^4.1.0",
+                "lowercase-keys": "^1.0.1",
+                "mimic-response": "^1.0.1",
+                "p-cancelable": "^1.0.0",
+                "to-readable-stream": "^1.0.0",
+                "url-parse-lax": "^3.0.0"
+            }
+        },
+        "graceful-fs": {
+            "version": "4.2.9",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+            "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
+        },
+        "has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+        },
+        "has-yarn": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+            "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw=="
+        },
+        "http-cache-semantics": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+            "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
+        },
+        "ignore-by-default": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+        },
+        "import-lazy": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
+        },
+        "imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+        },
+        "ini": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+            "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="
+        },
+        "is-binary-path": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+            "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+            "requires": {
+                "binary-extensions": "^2.0.0"
+            }
+        },
+        "is-ci": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+            "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+            "requires": {
+                "ci-info": "^2.0.0"
+            }
+        },
+        "is-extglob": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+        },
+        "is-fullwidth-code-point": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "is-glob": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+            "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+            "requires": {
+                "is-extglob": "^2.1.1"
+            }
+        },
+        "is-installed-globally": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+            "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+            "requires": {
+                "global-dirs": "^3.0.0",
+                "is-path-inside": "^3.0.2"
+            }
+        },
+        "is-npm": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz",
+            "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA=="
+        },
+        "is-number": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+        },
+        "is-obj": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+            "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
+        },
+        "is-path-inside": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+            "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
+        },
+        "is-typedarray": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+        },
+        "is-yarn-global": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+            "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw=="
+        },
+        "json-buffer": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+            "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
+        },
+        "keyv": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+            "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+            "requires": {
+                "json-buffer": "3.0.0"
+            }
+        },
+        "latest-version": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+            "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+            "requires": {
+                "package-json": "^6.3.0"
+            }
+        },
+        "lowercase-keys": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+            "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
+        },
+        "lru-cache": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+            "requires": {
+                "yallist": "^4.0.0"
+            }
+        },
+        "make-dir": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+            "requires": {
+                "semver": "^6.0.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+                }
+            }
+        },
+        "make-error": {
+            "version": "1.3.6",
+            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+        },
+        "mimic-response": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+            "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
+        },
+        "minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "requires": {
+                "brace-expansion": "^1.1.7"
+            }
+        },
+        "minimist": {
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
+        },
+        "ms": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+            "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+        },
+        "nodemon": {
+            "version": "2.0.15",
+            "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz",
+            "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==",
+            "requires": {
+                "chokidar": "^3.5.2",
+                "debug": "^3.2.7",
+                "ignore-by-default": "^1.0.1",
+                "minimatch": "^3.0.4",
+                "pstree.remy": "^1.1.8",
+                "semver": "^5.7.1",
+                "supports-color": "^5.5.0",
+                "touch": "^3.1.0",
+                "undefsafe": "^2.0.5",
+                "update-notifier": "^5.1.0"
+            }
+        },
+        "nopt": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+            "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+            "requires": {
+                "abbrev": "1"
+            }
+        },
+        "normalize-path": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+            "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+        },
+        "normalize-url": {
+            "version": "4.5.1",
+            "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+            "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA=="
+        },
+        "once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "requires": {
+                "wrappy": "1"
+            }
+        },
+        "p-cancelable": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+            "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw=="
+        },
+        "package-json": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+            "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+            "requires": {
+                "got": "^9.6.0",
+                "registry-auth-token": "^4.0.0",
+                "registry-url": "^5.0.0",
+                "semver": "^6.2.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+                }
+            }
+        },
+        "picomatch": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+        },
+        "prepend-http": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+            "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
+        },
+        "pstree.remy": {
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+            "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
+        },
+        "pump": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+            "requires": {
+                "end-of-stream": "^1.1.0",
+                "once": "^1.3.1"
+            }
+        },
+        "pupa": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
+            "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
+            "requires": {
+                "escape-goat": "^2.0.0"
+            }
+        },
+        "rc": {
+            "version": "1.2.8",
+            "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+            "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+            "requires": {
+                "deep-extend": "^0.6.0",
+                "ini": "~1.3.0",
+                "minimist": "^1.2.0",
+                "strip-json-comments": "~2.0.1"
+            },
+            "dependencies": {
+                "ini": {
+                    "version": "1.3.8",
+                    "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+                    "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+                }
+            }
+        },
+        "readdirp": {
+            "version": "3.6.0",
+            "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+            "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+            "requires": {
+                "picomatch": "^2.2.1"
+            }
+        },
+        "registry-auth-token": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
+            "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
+            "requires": {
+                "rc": "^1.2.8"
+            }
+        },
+        "registry-url": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+            "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+            "requires": {
+                "rc": "^1.2.8"
+            }
+        },
+        "responselike": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+            "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+            "requires": {
+                "lowercase-keys": "^1.0.0"
+            }
+        },
+        "semver": {
+            "version": "5.7.1",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+        },
+        "semver-diff": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+            "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+            "requires": {
+                "semver": "^6.3.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+                }
+            }
+        },
+        "signal-exit": {
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+        },
+        "string-width": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "requires": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            }
+        },
+        "strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "requires": {
+                "ansi-regex": "^5.0.1"
+            }
+        },
+        "strip-json-comments": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+        },
+        "supports-color": {
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "requires": {
+                "has-flag": "^3.0.0"
+            }
+        },
+        "to-readable-stream": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+            "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q=="
+        },
+        "to-regex-range": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+            "requires": {
+                "is-number": "^7.0.0"
+            }
+        },
+        "touch": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+            "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+            "requires": {
+                "nopt": "~1.0.10"
+            }
+        },
+        "ts-node": {
+            "version": "10.7.0",
+            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
+            "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+            "requires": {
+                "@cspotcode/source-map-support": "0.7.0",
+                "@tsconfig/node10": "^1.0.7",
+                "@tsconfig/node12": "^1.0.7",
+                "@tsconfig/node14": "^1.0.0",
+                "@tsconfig/node16": "^1.0.2",
+                "acorn": "^8.4.1",
+                "acorn-walk": "^8.1.1",
+                "arg": "^4.1.0",
+                "create-require": "^1.1.0",
+                "diff": "^4.0.1",
+                "make-error": "^1.1.1",
+                "v8-compile-cache-lib": "^3.0.0",
+                "yn": "3.1.1"
+            }
+        },
+        "type-fest": {
+            "version": "0.20.2",
+            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
+        },
+        "typedarray-to-buffer": {
+            "version": "3.1.5",
+            "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+            "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+            "requires": {
+                "is-typedarray": "^1.0.0"
+            }
+        },
+        "typescript": {
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+            "peer": true
+        },
+        "undefsafe": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+            "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
+        },
+        "unique-string": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+            "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+            "requires": {
+                "crypto-random-string": "^2.0.0"
+            }
+        },
+        "update-notifier": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz",
+            "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==",
+            "requires": {
+                "boxen": "^5.0.0",
+                "chalk": "^4.1.0",
+                "configstore": "^5.0.1",
+                "has-yarn": "^2.1.0",
+                "import-lazy": "^2.1.0",
+                "is-ci": "^2.0.0",
+                "is-installed-globally": "^0.4.0",
+                "is-npm": "^5.0.0",
+                "is-yarn-global": "^0.3.0",
+                "latest-version": "^5.1.0",
+                "pupa": "^2.1.1",
+                "semver": "^7.3.4",
+                "semver-diff": "^3.1.1",
+                "xdg-basedir": "^4.0.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "7.3.5",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+                    "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+                    "requires": {
+                        "lru-cache": "^6.0.0"
+                    }
+                }
+            }
+        },
+        "url-parse-lax": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+            "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+            "requires": {
+                "prepend-http": "^2.0.0"
+            }
+        },
+        "v8-compile-cache-lib": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
+            "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
+        },
+        "widest-line": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+            "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+            "requires": {
+                "string-width": "^4.0.0"
+            }
+        },
+        "wrap-ansi": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "requires": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            }
+        },
+        "wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+        },
+        "write-file-atomic": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+            "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+            "requires": {
+                "imurmurhash": "^0.1.4",
+                "is-typedarray": "^1.0.0",
+                "signal-exit": "^3.0.2",
+                "typedarray-to-buffer": "^3.1.5"
+            }
+        },
+        "xdg-basedir": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
+            "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="
+        },
+        "yallist": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+        },
+        "yn": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
+        }
+    }
+}

styles/package.json 🔗

@@ -0,0 +1,22 @@
+{
+    "name": "styles",
+    "version": "1.0.0",
+    "description": "",
+    "main": "index.js",
+    "scripts": {
+        "build": "npm run build-themes && npm run build-tokens",
+        "build-themes": "ts-node ./src/buildThemes.ts",
+        "build-tokens": "ts-node ./src/buildTokens.ts",
+        "watch": "nodemon"
+    },
+    "author": "",
+    "license": "ISC",
+    "dependencies": {
+        "@types/chroma-js": "^2.1.3",
+        "@types/node": "^17.0.23",
+        "case-anything": "^2.1.10",
+        "chroma-js": "^2.4.2",
+        "ts-node": "^10.7.0",
+        "nodemon": "^2.0.15"
+    }
+}

styles/src/buildThemes.ts 🔗

@@ -0,0 +1,17 @@
+import * as fs from "fs";
+import * as path from "path";
+import app from "./styleTree/app";
+import dark from "./themes/dark";
+import light from "./themes/light";
+import snakeCase from "./utils/snakeCase";
+
+const themes = [dark, light];
+for (let theme of themes) {
+    let styleTree = snakeCase(app(theme));
+    let styleTreeJSON = JSON.stringify(styleTree, null, 2);
+    let outPath = path.resolve(
+        `${__dirname}/../../crates/zed/assets/themes/${theme.name}.json`
+    );
+    fs.writeFileSync(outPath, styleTreeJSON);
+    console.log(`- ${outPath} created`);
+}

styles/src/buildTokens.ts 🔗

@@ -0,0 +1,110 @@
+import * as fs from "fs";
+import * as path from "path";
+import dark from "./themes/dark";
+import light from "./themes/light";
+import Theme from "./themes/theme";
+import { colors, fontFamilies, fontSizes, fontWeights } from "./tokens";
+
+// Organize theme tokens
+function themeTokens(theme: Theme) {
+    return {
+        meta: {
+            themeName: theme.name,
+        },
+        text: theme.textColor,
+        icon: theme.iconColor,
+        background: theme.backgroundColor,
+        border: theme.borderColor,
+        editor: theme.editor,
+        syntax: {
+            primary: {
+                value: theme.syntax.primary.color.value,
+                type: "color",
+            },
+            comment: {
+                value: theme.syntax.comment.color.value,
+                type: "color",
+            },
+            keyword: {
+                value: theme.syntax.keyword.color.value,
+                type: "color",
+            },
+            function: {
+                value: theme.syntax.function.color.value,
+                type: "color",
+            },
+            type: {
+                value: theme.syntax.type.color.value,
+                type: "color",
+            },
+            variant: {
+                value: theme.syntax.variant.color.value,
+                type: "color",
+            },
+            property: {
+                value: theme.syntax.property.color.value,
+                type: "color",
+            },
+            enum: {
+                value: theme.syntax.enum.color.value,
+                type: "color",
+            },
+            operator: {
+                value: theme.syntax.operator.color.value,
+                type: "color",
+            },
+            string: {
+                value: theme.syntax.string.color.value,
+                type: "color",
+            },
+            number: {
+                value: theme.syntax.number.color.value,
+                type: "color",
+            },
+            boolean: {
+                value: theme.syntax.boolean.color.value,
+                type: "color",
+            },
+        },
+        player: theme.player,
+        shadowAlpha: theme.shadowAlpha,
+    };
+}
+
+// Organize core tokens
+const coreTokens = {
+    color: {
+        ...colors,
+    },
+    text: {
+        family: fontFamilies,
+        weight: fontWeights,
+    },
+    size: fontSizes,
+};
+
+const combinedTokens: any = {};
+
+const distPath = path.resolve(`${__dirname}/../dist`);
+
+// Add core tokens to the combined tokens and write `core.json`.
+// We write `core.json` as a separate file for the design team's convenience, but it isn't consumed by Figma Tokens directly.
+const corePath = path.join(distPath, "core.json");
+fs.writeFileSync(corePath, JSON.stringify(coreTokens, null, 2));
+console.log(`- ${corePath} created`);
+combinedTokens.core = coreTokens;
+
+// Add each theme to the combined tokens and write ${theme}.json.
+// We write `${theme}.json` as a separate file for the design team's convenience, but it isn't consumed by Figma Tokens directly.
+let themes = [dark, light];
+themes.forEach((theme) => {
+    const themePath = `${distPath}/${theme.name}.json`
+    fs.writeFileSync(themePath, JSON.stringify(themeTokens(theme), null, 2));
+    console.log(`- ${themePath} created`);
+    combinedTokens[theme.name] = themeTokens(theme);
+});
+
+// Write combined tokens to `tokens.json`. This file is consumed by the Figma Tokens plugin to keep our designs consistent with the app.
+const combinedPath = path.resolve(`${distPath}/tokens.json`);
+fs.writeFileSync(combinedPath, JSON.stringify(combinedTokens, null, 2));
+console.log(`- ${combinedPath} created`);

styles/src/styleTree/app.ts 🔗

@@ -0,0 +1,43 @@
+import Theme from "../themes/theme";
+import chatPanel from "./chatPanel";
+import { text } from "./components";
+import contactsPanel from "./contactsPanel";
+import editor from "./editor";
+import projectPanel from "./projectPanel";
+import search from "./search";
+import selectorModal from "./selectorModal";
+import workspace from "./workspace";
+
+export const panel = {
+    padding: { top: 12, left: 12, bottom: 12, right: 12 },
+};
+
+export default function app(theme: Theme): Object {
+    return {
+        selector: selectorModal(theme),
+        workspace: workspace(theme),
+        editor: editor(theme),
+        projectDiagnostics: {
+            tabIconSpacing: 4,
+            tabIconWidth: 13,
+            tabSummarySpacing: 10,
+            emptyMessage: text(theme, "sans", "primary", { size: "lg" }),
+            statusBarItem: {
+                ...text(theme, "sans", "muted"),
+                margin: {
+                    right: 10,
+                },
+            },
+        },
+        projectPanel: projectPanel(theme),
+        chatPanel: chatPanel(theme),
+        contactsPanel: contactsPanel(theme),
+        search: search(theme),
+        breadcrumbs: {
+            ...text(theme, "sans", "primary"),
+            padding: {
+                left: 6,
+            },
+        }
+    };
+}

styles/src/styleTree/chatPanel.ts 🔗

@@ -0,0 +1,108 @@
+import Theme from "../themes/theme";
+import { panel } from "./app";
+import {
+    backgroundColor,
+    border,
+    player,
+    shadow,
+    text,
+    TextColor
+} from "./components";
+
+export default function chatPanel(theme: Theme) {
+    function channelSelectItem(
+        theme: Theme,
+        textColor: TextColor,
+        hovered: boolean
+    ) {
+        return {
+            name: text(theme, "sans", textColor),
+            padding: 4,
+            hash: {
+                ...text(theme, "sans", "muted"),
+                margin: {
+                    right: 8,
+                },
+            },
+            background: hovered ? backgroundColor(theme, 300, "hovered") : undefined,
+            cornerRadius: hovered ? 6 : 0,
+        };
+    }
+
+    const message = {
+        body: text(theme, "sans", "secondary"),
+        timestamp: text(theme, "sans", "muted", { size: "sm" }),
+        padding: {
+            bottom: 6,
+        },
+        sender: {
+            ...text(theme, "sans", "primary", { weight: "bold" }),
+            margin: {
+                right: 8,
+            },
+        },
+    };
+
+    return {
+        ...panel,
+        channelName: text(theme, "sans", "primary", { weight: "bold" }),
+        channelNameHash: {
+            ...text(theme, "sans", "muted"),
+            padding: {
+                right: 8,
+            },
+        },
+        channelSelect: {
+            header: {
+                ...channelSelectItem(theme, "primary", false),
+                padding: {
+                    bottom: 4,
+                    left: 0,
+                },
+            },
+            item: channelSelectItem(theme, "secondary", false),
+            hoveredItem: channelSelectItem(theme, "secondary", true),
+            activeItem: channelSelectItem(theme, "primary", false),
+            hoveredActiveItem: channelSelectItem(theme, "primary", true),
+            menu: {
+                background: backgroundColor(theme, 500),
+                cornerRadius: 6,
+                padding: 4,
+                border: border(theme, "primary"),
+                shadow: shadow(theme),
+            },
+        },
+        signInPrompt: text(theme, "sans", "secondary", { underline: true }),
+        hoveredSignInPrompt: text(theme, "sans", "primary", { underline: true }),
+        message,
+        pendingMessage: {
+            ...message,
+            body: {
+                ...message.body,
+                color: theme.textColor.muted.value,
+            },
+            sender: {
+                ...message.sender,
+                color: theme.textColor.muted.value,
+            },
+            timestamp: {
+                ...message.timestamp,
+                color: theme.textColor.muted.value,
+            },
+        },
+        inputEditor: {
+            background: backgroundColor(theme, 500),
+            cornerRadius: 6,
+            text: text(theme, "mono", "primary"),
+            placeholderText: text(theme, "mono", "placeholder", { size: "sm" }),
+            selection: player(theme, 1).selection,
+            border: border(theme, "secondary"),
+            padding: {
+                bottom: 7,
+                left: 8,
+                right: 8,
+                top: 7,
+            },
+        },
+    };
+}

styles/src/styleTree/components.ts 🔗

@@ -0,0 +1,93 @@
+import chroma from "chroma-js";
+import Theme, { BackgroundColorSet } from "../themes/theme";
+import { fontFamilies, fontSizes, FontWeight } from "../tokens";
+import { Color } from "../utils/color";
+
+export type TextColor = keyof Theme["textColor"];
+export function text(
+    theme: Theme,
+    fontFamily: keyof typeof fontFamilies,
+    color: TextColor,
+    properties?: {
+        size?: keyof typeof fontSizes;
+        weight?: FontWeight;
+        underline?: boolean;
+    }
+) {
+    let size = fontSizes[properties?.size || "sm"].value;
+    return {
+        family: fontFamilies[fontFamily].value,
+        color: theme.textColor[color].value,
+        ...properties,
+        size,
+    };
+}
+export function textColor(theme: Theme, color: TextColor) {
+    return theme.textColor[color].value;
+}
+
+export type BorderColor = keyof Theme["borderColor"];
+export interface BorderOptions {
+    width?: number;
+    top?: boolean;
+    bottom?: boolean;
+    left?: boolean;
+    right?: boolean;
+    overlay?: boolean;
+}
+export function border(
+    theme: Theme,
+    color: BorderColor,
+    options?: BorderOptions
+) {
+    return {
+        color: borderColor(theme, color),
+        width: 1,
+        ...options,
+    };
+}
+export function borderColor(theme: Theme, color: BorderColor) {
+    return theme.borderColor[color].value;
+}
+
+export type IconColor = keyof Theme["iconColor"];
+export function iconColor(theme: Theme, color: IconColor) {
+    return theme.iconColor[color].value;
+}
+
+export type PlayerIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
+export interface Player {
+    selection: {
+        cursor: Color;
+        selection: Color;
+    };
+}
+export function player(
+    theme: Theme,
+    playerNumber: PlayerIndex,
+): Player {
+    return {
+        selection: {
+            cursor: theme.player[playerNumber].cursorColor.value,
+            selection: theme.player[playerNumber].selectionColor.value,
+        },
+    };
+}
+
+export type BackgroundColor = keyof Theme["backgroundColor"];
+export type BackgroundState = keyof BackgroundColorSet;
+export function backgroundColor(
+    theme: Theme,
+    name: BackgroundColor,
+    state?: BackgroundState,
+): Color {
+    return theme.backgroundColor[name][state || "base"].value;
+}
+
+export function shadow(theme: Theme) {
+    return {
+        blur: 16,
+        color: chroma("black").alpha(theme.shadowAlpha.value).hex(),
+        offset: [0, 2],
+    };
+}

styles/src/styleTree/contactsPanel.ts 🔗

@@ -0,0 +1,62 @@
+import Theme from "../themes/theme";
+import { panel } from "./app";
+import { backgroundColor, borderColor, text } from "./components";
+
+export default function(theme: Theme) {
+    const project = {
+        guestAvatarSpacing: 4,
+        height: 24,
+        guestAvatar: {
+            cornerRadius: 8,
+            width: 14,
+        },
+        name: {
+            ...text(theme, "mono", "placeholder", { size: "sm" }),
+            margin: {
+                right: 6,
+            },
+        },
+        padding: {
+            left: 8,
+        },
+    };
+
+    const sharedProject = {
+        ...project,
+        background: backgroundColor(theme, 300),
+        cornerRadius: 6,
+        name: {
+            ...project.name,
+            ...text(theme, "mono", "secondary", { size: "sm" }),
+        },
+    };
+
+    return {
+        ...panel,
+        hostRowHeight: 28,
+        treeBranchColor: borderColor(theme, "muted"),
+        treeBranchWidth: 1,
+        hostAvatar: {
+            cornerRadius: 10,
+            width: 18,
+        },
+        hostUsername: {
+            ...text(theme, "mono", "primary", { size: "sm" }),
+            padding: {
+                left: 8,
+            },
+        },
+        project,
+        sharedProject,
+        hoveredSharedProject: {
+            ...sharedProject,
+            background: backgroundColor(theme, 300, "hovered"),
+            cornerRadius: 6,
+        },
+        unsharedProject: project,
+        hoveredUnsharedProject: {
+            ...project,
+            cornerRadius: 6,
+        },
+    }
+}

styles/src/styleTree/editor.ts 🔗

@@ -0,0 +1,146 @@
+import Theme from "../themes/theme";
+import {
+    backgroundColor,
+    border,
+    iconColor,
+    player,
+    text,
+    TextColor
+} from "./components";
+
+export default function editor(theme: Theme) {
+    const autocompleteItem = {
+        cornerRadius: 6,
+        padding: {
+            bottom: 2,
+            left: 6,
+            right: 6,
+            top: 2,
+        },
+    };
+
+    function diagnostic(theme: Theme, color: TextColor) {
+        return {
+            textScaleFactor: 0.857,
+            header: {
+                border: border(theme, "primary", {
+                    top: true,
+                }),
+            },
+            message: {
+                text: text(theme, "sans", color, { size: "sm" }),
+                highlightText: text(theme, "sans", color, {
+                    size: "sm",
+                    weight: "bold",
+                }),
+            },
+        };
+    }
+
+    return {
+        // textColor: theme.syntax.primary.color,
+        textColor: theme.syntax.primary.color.value,
+        background: backgroundColor(theme, 500),
+        activeLineBackground: theme.editor.line.active.value,
+        codeActionsIndicator: iconColor(theme, "muted"),
+        diffBackgroundDeleted: backgroundColor(theme, "error"),
+        diffBackgroundInserted: backgroundColor(theme, "ok"),
+        documentHighlightReadBackground: theme.editor.highlight.occurrence.value,
+        documentHighlightWriteBackground: theme.editor.highlight.activeOccurrence.value,
+        errorColor: theme.textColor.error.value,
+        gutterBackground: backgroundColor(theme, 500),
+        gutterPaddingFactor: 3.5,
+        highlightedLineBackground: theme.editor.line.highlighted.value,
+        lineNumber: theme.editor.gutter.primary.value,
+        lineNumberActive: theme.editor.gutter.active.value,
+        renameFade: 0.6,
+        unnecessaryCodeFade: 0.5,
+        selection: player(theme, 1).selection,
+        guestSelections: [
+            player(theme, 2).selection,
+            player(theme, 3).selection,
+            player(theme, 4).selection,
+            player(theme, 5).selection,
+            player(theme, 6).selection,
+            player(theme, 7).selection,
+            player(theme, 8).selection,
+        ],
+        autocomplete: {
+            background: backgroundColor(theme, 500),
+            cornerRadius: 6,
+            padding: 6,
+            border: border(theme, "secondary"),
+            item: autocompleteItem,
+            hoveredItem: {
+                ...autocompleteItem,
+                background: backgroundColor(theme, 500, "hovered"),
+            },
+            margin: {
+                left: -14,
+            },
+            matchHighlight: text(theme, "mono", "feature"),
+            selectedItem: {
+                ...autocompleteItem,
+                background: backgroundColor(theme, 500, "active"),
+            },
+        },
+        diagnosticHeader: {
+            background: backgroundColor(theme, 300),
+            iconWidthFactor: 1.5,
+            textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
+            border: border(theme, "secondary", {
+                bottom: true,
+                top: true,
+            }),
+            code: {
+                ...text(theme, "mono", "muted", { size: "sm" }),
+                margin: {
+                    left: 10,
+                },
+            },
+            message: {
+                highlightText: text(theme, "sans", "primary", {
+                    size: "sm",
+                    weight: "bold",
+                }),
+                text: text(theme, "sans", "secondary", { size: "sm" }),
+            },
+        },
+        diagnosticPathHeader: {
+            background: theme.editor.line.active.value,
+            textScaleFactor: 0.857,
+            filename: text(theme, "mono", "primary", { size: "sm" }),
+            path: {
+                ...text(theme, "mono", "muted", { size: "sm" }),
+                margin: {
+                    left: 12,
+                },
+            },
+        },
+        errorDiagnostic: diagnostic(theme, "error"),
+        warningDiagnostic: diagnostic(theme, "warning"),
+        informationDiagnostic: diagnostic(theme, "info"),
+        hintDiagnostic: diagnostic(theme, "info"),
+        invalidErrorDiagnostic: diagnostic(theme, "muted"),
+        invalidHintDiagnostic: diagnostic(theme, "muted"),
+        invalidInformationDiagnostic: diagnostic(theme, "muted"),
+        invalidWarningDiagnostic: diagnostic(theme, "muted"),
+        syntax: {
+            keyword: theme.syntax.keyword.color.value,
+            function: theme.syntax.function.color.value,
+            string: theme.syntax.string.color.value,
+            type: theme.syntax.type.color.value,
+            number: theme.syntax.number.color.value,
+            comment: theme.syntax.comment.color.value,
+            property: theme.syntax.property.color.value,
+            variant: theme.syntax.variant.color.value,
+            constant: theme.syntax.constant.color.value,
+            title: { color: theme.syntax.title.color.value, weight: "bold" },
+            emphasis: theme.textColor.feature.value,
+            "emphasis.strong": { color: theme.textColor.feature.value, weight: "bold" },
+            link_uri: { color: theme.syntax.linkUrl.color.value, underline: true },
+            link_text: { color: theme.syntax.linkText.color.value, italic: true },
+            list_marker: theme.syntax.punctuation.color.value,
+        },
+    };
+}

styles/src/styleTree/projectPanel.ts 🔗

@@ -0,0 +1,37 @@
+import Theme from "../themes/theme";
+import { Color } from "../utils/color";
+import { panel } from "./app";
+import { backgroundColor, iconColor, text, TextColor } from "./components";
+
+export default function projectPanel(theme: Theme) {
+    function entry(theme: Theme, textColor: TextColor, background?: Color) {
+        return {
+            height: 22,
+            background,
+            iconColor: iconColor(theme, "muted"),
+            iconSize: 8,
+            iconSpacing: 8,
+            text: text(theme, "mono", textColor, { size: "sm" }),
+        };
+    }
+
+    return {
+        ...panel,
+        entry: entry(theme, "secondary"),
+        hoveredEntry: entry(
+            theme,
+            "secondary",
+            backgroundColor(theme, 300, "hovered")
+        ),
+        selectedEntry: entry(theme, "primary"),
+        hoveredSelectedEntry: entry(
+            theme,
+            "primary",
+            backgroundColor(theme, 300, "hovered")
+        ),
+        padding: {
+            top: 6,
+            left: 12,
+        },
+    };
+}

styles/src/styleTree/search.ts 🔗

@@ -0,0 +1,79 @@
+import Theme from "../themes/theme";
+import { backgroundColor, border, player, text } from "./components";
+
+export default function search(theme: Theme) {
+    const optionButton = {
+        ...text(theme, "mono", "secondary"),
+        background: backgroundColor(theme, 300),
+        cornerRadius: 6,
+        border: border(theme, "primary"),
+        margin: {
+            left: 1,
+            right: 1,
+        },
+        padding: {
+            bottom: 1,
+            left: 6,
+            right: 6,
+            top: 1,
+        },
+    };
+
+    const editor = {
+        background: backgroundColor(theme, 500),
+        cornerRadius: 6,
+        minWidth: 200,
+        maxWidth: 500,
+        placeholderText: text(theme, "mono", "placeholder"),
+        selection: player(theme, 1).selection,
+        text: text(theme, "mono", "primary"),
+        border: border(theme, "secondary"),
+        margin: {
+            right: 5,
+        },
+        padding: {
+            top: 3,
+            bottom: 3,
+            left: 14,
+            right: 14,
+        },
+    };
+
+    return {
+        matchBackground: theme.editor.highlight.match.value,
+        tabIconSpacing: 4,
+        tabIconWidth: 14,
+        activeHoveredOptionButton: {
+            ...optionButton,
+            background: backgroundColor(theme, 100),
+        },
+        activeOptionButton: {
+            ...optionButton,
+            background: backgroundColor(theme, 100),
+        },
+        editor,
+        hoveredOptionButton: {
+            ...optionButton,
+            background: backgroundColor(theme, 100),
+        },
+        invalidEditor: {
+            ...editor,
+            border: border(theme, "error"),
+        },
+        matchIndex: {
+            ...text(theme, "mono", "muted"),
+            padding: 6,
+        },
+        optionButton,
+        optionButtonGroup: {
+            padding: {
+                left: 2,
+                right: 2,
+            },
+        },
+        resultsStatus: {
+            ...text(theme, "mono", "primary"),
+            size: 18,
+        },
+    };
+}

styles/src/styleTree/selectorModal.ts 🔗

@@ -0,0 +1,59 @@
+import Theme from "../themes/theme";
+import { backgroundColor, border, player, shadow, text } from "./components";
+
+export default function selectorModal(theme: Theme): Object {
+    const item = {
+        padding: {
+            bottom: 4,
+            left: 16,
+            right: 16,
+            top: 4,
+        },
+        cornerRadius: 6,
+        text: text(theme, "sans", "secondary"),
+        highlightText: text(theme, "sans", "feature", { weight: "bold" }),
+    };
+
+    const activeItem = {
+        ...item,
+        background: backgroundColor(theme, 300, "active"),
+        text: text(theme, "sans", "primary"),
+    };
+
+    return {
+        background: backgroundColor(theme, 300),
+        cornerRadius: 6,
+        padding: 8,
+        item,
+        activeItem,
+        border: border(theme, "primary"),
+        empty: {
+            text: text(theme, "sans", "placeholder"),
+            padding: {
+                bottom: 4,
+                left: 16,
+                right: 16,
+                top: 8,
+            },
+        },
+        inputEditor: {
+            background: backgroundColor(theme, 500),
+            corner_radius: 6,
+            placeholderText: text(theme, "sans", "placeholder"),
+            selection: player(theme, 1).selection,
+            text: text(theme, "mono", "primary"),
+            border: border(theme, "secondary"),
+            padding: {
+                bottom: 7,
+                left: 16,
+                right: 16,
+                top: 7,
+            },
+        },
+        margin: {
+            bottom: 52,
+            top: 52,
+        },
+        shadow: shadow(theme),
+    };
+}

styles/src/styleTree/workspace.ts 🔗

@@ -0,0 +1,150 @@
+import Theme from "../themes/theme";
+import { backgroundColor, border, borderColor, iconColor, text } from "./components";
+
+export default function workspace(theme: Theme) {
+    const signInPrompt = {
+        ...text(theme, "sans", "secondary", { size: "xs" }),
+        underline: true,
+        padding: {
+            right: 8,
+        },
+    };
+
+    const tab = {
+        height: 32,
+        background: backgroundColor(theme, 300),
+        iconClose: iconColor(theme, "muted"),
+        iconCloseActive: iconColor(theme, "active"),
+        iconConflict: iconColor(theme, "warning"),
+        iconDirty: iconColor(theme, "info"),
+        iconWidth: 8,
+        spacing: 10,
+        text: text(theme, "mono", "secondary", { size: "sm" }),
+        border: border(theme, "primary", {
+            left: true,
+            bottom: true,
+            overlay: true,
+        }),
+        padding: {
+            left: 12,
+            right: 12,
+        },
+    };
+
+    const activeTab = {
+        ...tab,
+        background: backgroundColor(theme, 500),
+        text: text(theme, "mono", "active", { size: "sm" }),
+        border: {
+            ...tab.border,
+            bottom: false,
+        },
+    };
+
+    const sidebarItem = {
+        height: 32,
+        iconColor: iconColor(theme, "secondary"),
+        iconSize: 18,
+    };
+    const sidebar = {
+        width: 30,
+        background: backgroundColor(theme, 300),
+        border: border(theme, "primary", { right: true }),
+        item: sidebarItem,
+        activeItem: {
+            ...sidebarItem,
+            iconColor: iconColor(theme, "active"),
+        },
+        resizeHandle: {
+            background: border(theme, "primary").color,
+            padding: {
+                left: 1,
+            },
+        },
+    };
+
+    return {
+        background: backgroundColor(theme, 300),
+        leaderBorderOpacity: 0.7,
+        leaderBorderWidth: 2.0,
+        tab,
+        activeTab,
+        leftSidebar: {
+            ...sidebar,
+            border: border(theme, "primary", { right: true }),
+        },
+        rightSidebar: {
+            ...sidebar,
+            border: border(theme, "primary", { left: true }),
+        },
+        paneDivider: {
+            color: border(theme, "secondary").color,
+            width: 1,
+        },
+        status_bar: {
+            height: 24,
+            itemSpacing: 8,
+            padding: {
+                left: 6,
+                right: 6,
+            },
+            border: border(theme, "primary", { top: true, overlay: true }),
+            cursorPosition: text(theme, "sans", "muted"),
+            diagnosticMessage: text(theme, "sans", "muted"),
+            lspMessage: text(theme, "sans", "muted"),
+        },
+        titlebar: {
+            avatarWidth: 18,
+            height: 32,
+            background: backgroundColor(theme, 100),
+            shareIconColor: iconColor(theme, "secondary"),
+            shareIconActiveColor: iconColor(theme, "feature"),
+            title: text(theme, "sans", "primary"),
+            avatar: {
+                cornerRadius: 10,
+                border: {
+                    color: "#00000088",
+                    width: 1,
+                },
+            },
+            avatarRibbon: {
+                height: 3,
+                width: 12,
+                // TODO: The background for this ideally should be 
+                // set with a token, not hardcoded in rust
+            },
+            border: border(theme, "primary", { bottom: true }),
+            signInPrompt,
+            hoveredSignInPrompt: {
+                ...signInPrompt,
+                ...text(theme, "sans", "active", { size: "xs" }),
+            },
+            offlineIcon: {
+                color: iconColor(theme, "secondary"),
+                width: 16,
+                padding: {
+                    right: 4,
+                },
+            },
+            outdatedWarning: {
+                ...text(theme, "sans", "warning"),
+                size: 13,
+            },
+        },
+        toolbar: {
+            height: 34,
+            background: backgroundColor(theme, 500),
+            border: border(theme, "secondary", { bottom: true }),
+            itemSpacing: 8,
+            padding: { left: 16, right: 8, top: 4, bottom: 4 },
+        },
+        breadcrumbs: {
+            ...text(theme, "mono", "secondary"),
+            padding: { left: 6 },
+        },
+        disconnectedOverlay: {
+            ...text(theme, "sans", "active"),
+            background: "#000000aa",
+        },
+    };
+}

styles/src/themes/dark.ts 🔗

@@ -0,0 +1,229 @@
+import { colors, fontWeights, NumberToken } from "../tokens";
+import { withOpacity } from "../utils/color";
+import Theme, { buildPlayer, Syntax } from "./theme";
+
+const backgroundColor = {
+    100: {
+        base: colors.neutral[750],
+        hovered: colors.neutral[725],
+        active: colors.neutral[800],
+        focused: colors.neutral[675],
+    },
+    300: {
+        base: colors.neutral[800],
+        hovered: colors.neutral[775],
+        active: colors.neutral[750],
+        focused: colors.neutral[775],
+    },
+    500: {
+        base: colors.neutral[900],
+        hovered: withOpacity(colors.neutral[0], 0.08),
+        active: withOpacity(colors.neutral[0], 0.12),
+        focused: colors.neutral[825],
+    },
+    ok: {
+        base: colors.green[600],
+        hovered: colors.green[600],
+        active: colors.green[600],
+        focused: colors.green[600],
+    },
+    error: {
+        base: colors.red[400],
+        hovered: colors.red[400],
+        active: colors.red[400],
+        focused: colors.red[400],
+    },
+    warning: {
+        base: colors.amber[300],
+        hovered: colors.amber[300],
+        active: colors.amber[300],
+        focused: colors.amber[300],
+    },
+    info: {
+        base: colors.blue[500],
+        hovered: colors.blue[500],
+        active: colors.blue[500],
+        focused: colors.blue[500],
+    },
+};
+
+const borderColor = {
+    primary: colors.neutral[875],
+    secondary: colors.neutral[775],
+    muted: colors.neutral[675],
+    focused: colors.neutral[500],
+    active: colors.neutral[900],
+    ok: colors.green[500],
+    error: colors.red[500],
+    warning: colors.amber[500],
+    info: colors.blue[500],
+};
+
+const textColor = {
+    primary: colors.neutral[50],
+    secondary: colors.neutral[350],
+    muted: colors.neutral[450],
+    placeholder: colors.neutral[650],
+    active: colors.neutral[0],
+    //TODO: (design) define feature and it's correct value
+    feature: colors.sky[500],
+    ok: colors.green[600],
+    error: colors.red[400],
+    warning: colors.amber[300],
+    info: colors.blue[500],
+};
+
+const iconColor = {
+    primary: colors.neutral[200],
+    secondary: colors.neutral[350],
+    muted: colors.neutral[600],
+    placeholder: colors.neutral[700],
+    active: colors.neutral[0],
+    //TODO: (design) define feature and it's correct value
+    feature: colors.blue[500],
+    ok: colors.green[600],
+    error: colors.red[500],
+    warning: colors.amber[400],
+    info: colors.blue[600],
+};
+
+const player = {
+    1: buildPlayer(colors.blue[500]),
+    2: buildPlayer(colors.lime[500]),
+    3: buildPlayer(colors.fuschia[500]),
+    4: buildPlayer(colors.orange[500]),
+    5: buildPlayer(colors.purple[500]),
+    6: buildPlayer(colors.teal[400]),
+    7: buildPlayer(colors.pink[400]),
+    8: buildPlayer(colors.yellow[400]),
+};
+
+const editor = {
+    background: backgroundColor[500].base,
+    indent_guide: borderColor.muted,
+    indent_guide_active: borderColor.secondary,
+    line: {
+        active: withOpacity(colors.neutral[0], 0.07),
+        highlighted: withOpacity(colors.neutral[0], 0.12),
+        inserted: backgroundColor.ok.active,
+        deleted: backgroundColor.error.active,
+        modified: backgroundColor.info.active,
+    },
+    highlight: {
+        selection: player[1].selectionColor,
+        occurrence: withOpacity(colors.neutral[0], 0.12),
+        activeOccurrence: withOpacity(colors.neutral[0], 0.16), // TODO: This is not correctly hooked up to occurences on the rust side
+        matchingBracket: backgroundColor[500].active,
+        match: withOpacity(colors.sky[500], 0.16),
+        activeMatch: withOpacity(colors.sky[800], 0.32),
+        related: backgroundColor[500].focused,
+    },
+    gutter: {
+        primary: textColor.placeholder,
+        active: textColor.active,
+    },
+};
+
+const syntax: Syntax = {
+    primary: {
+        color: colors.neutral[150],
+        weight: fontWeights.normal,
+    },
+    comment: {
+        color: colors.neutral[300],
+        weight: fontWeights.normal,
+    },
+    punctuation: {
+        color: colors.neutral[200],
+        weight: fontWeights.normal,
+    },
+    constant: {
+        color: colors.neutral[150],
+        weight: fontWeights.normal,
+    },
+    keyword: {
+        color: colors.blue[400],
+        weight: fontWeights.normal,
+    },
+    function: {
+        color: colors.yellow[200],
+        weight: fontWeights.normal,
+    },
+    type: {
+        color: colors.teal[300],
+        weight: fontWeights.normal,
+    },
+    variant: {
+        color: colors.sky[300],
+        weight: fontWeights.normal,
+    },
+    property: {
+        color: colors.blue[400],
+        weight: fontWeights.normal,
+    },
+    enum: {
+        color: colors.orange[500],
+        weight: fontWeights.normal,
+    },
+    operator: {
+        color: colors.orange[500],
+        weight: fontWeights.normal,
+    },
+    string: {
+        color: colors.orange[300],
+        weight: fontWeights.normal,
+    },
+    number: {
+        color: colors.lime[300],
+        weight: fontWeights.normal,
+    },
+    boolean: {
+        color: colors.lime[300],
+        weight: fontWeights.normal,
+    },
+    predictive: {
+        color: textColor.muted,
+        weight: fontWeights.normal,
+    },
+    title: {
+        color: colors.amber[500],
+        weight: fontWeights.bold,
+    },
+    emphasis: {
+        color: textColor.active,
+        weight: fontWeights.normal,
+    },
+    emphasisStrong: {
+        color: textColor.active,
+        weight: fontWeights.bold,
+    },
+    linkUrl: {
+        color: colors.lime[500],
+        weight: fontWeights.normal,
+        // TODO: add underline
+    },
+    linkText: {
+        color: colors.orange[500],
+        weight: fontWeights.normal,
+        // TODO: add italic
+    },
+};
+
+const shadowAlpha: NumberToken = {
+    value: 0.32,
+    type: "number",
+};
+
+const theme: Theme = {
+    name: "dark",
+    backgroundColor,
+    borderColor,
+    textColor,
+    iconColor,
+    editor,
+    syntax,
+    player,
+    shadowAlpha,
+};
+
+export default theme;

styles/src/themes/light.ts 🔗

@@ -0,0 +1,227 @@
+import { colors, fontWeights, NumberToken } from "../tokens";
+import { withOpacity } from "../utils/color";
+import Theme, { buildPlayer, Syntax } from "./theme";
+
+const backgroundColor = {
+    100: {
+        base: colors.neutral[75],
+        hovered: colors.neutral[100],
+        active: colors.neutral[150],
+        focused: colors.neutral[100],
+    },
+    300: {
+        base: colors.neutral[25],
+        hovered: colors.neutral[75],
+        active: colors.neutral[125],
+        focused: colors.neutral[75],
+    },
+    500: {
+        base: colors.neutral[0],
+        hovered: withOpacity(colors.neutral[900], 0.03),
+        active: withOpacity(colors.neutral[900], 0.06),
+        focused: colors.neutral[50],
+    },
+    ok: {
+        base: colors.green[100],
+        hovered: colors.green[100],
+        active: colors.green[100],
+        focused: colors.green[100],
+    },
+    error: {
+        base: colors.red[100],
+        hovered: colors.red[100],
+        active: colors.red[100],
+        focused: colors.red[100],
+    },
+    warning: {
+        base: colors.yellow[100],
+        hovered: colors.yellow[100],
+        active: colors.yellow[100],
+        focused: colors.yellow[100],
+    },
+    info: {
+        base: colors.blue[100],
+        hovered: colors.blue[100],
+        active: colors.blue[100],
+        focused: colors.blue[100],
+    },
+};
+
+const borderColor = {
+    primary: colors.neutral[150],
+    secondary: colors.neutral[150],
+    muted: colors.neutral[100],
+    focused: colors.neutral[100],
+    active: colors.neutral[250],
+    ok: colors.green[200],
+    error: colors.red[200],
+    warning: colors.yellow[200],
+    info: colors.blue[200],
+};
+
+const textColor = {
+    primary: colors.neutral[750],
+    secondary: colors.neutral[650],
+    muted: colors.neutral[550],
+    placeholder: colors.neutral[450],
+    active: colors.neutral[900],
+    feature: colors.indigo[600],
+    ok: colors.green[500],
+    error: colors.red[500],
+    warning: colors.yellow[500],
+    info: colors.blue[500],
+};
+
+const iconColor = {
+    primary: colors.neutral[700],
+    secondary: colors.neutral[500],
+    muted: colors.neutral[350],
+    placeholder: colors.neutral[300],
+    active: colors.neutral[900],
+    feature: colors.indigo[500],
+    ok: colors.green[600],
+    error: colors.red[600],
+    warning: colors.yellow[400],
+    info: colors.blue[600],
+};
+
+const player = {
+    1: buildPlayer(colors.blue[500]),
+    2: buildPlayer(colors.emerald[400]),
+    3: buildPlayer(colors.fuschia[400]),
+    4: buildPlayer(colors.orange[400]),
+    5: buildPlayer(colors.purple[400]),
+    6: buildPlayer(colors.teal[400]),
+    7: buildPlayer(colors.pink[400]),
+    8: buildPlayer(colors.yellow[400]),
+};
+
+const editor = {
+    background: backgroundColor[500].base,
+    indent_guide: borderColor.muted,
+    indent_guide_active: borderColor.secondary,
+    line: {
+        active: withOpacity(colors.neutral[900], 0.06),
+        highlighted: withOpacity(colors.neutral[900], 0.12),
+        inserted: backgroundColor.ok.active,
+        deleted: backgroundColor.error.active,
+        modified: backgroundColor.info.active,
+    },
+    highlight: {
+        selection: player[1].selectionColor,
+        occurrence: withOpacity(colors.neutral[900], 0.06),
+        activeOccurrence: withOpacity(colors.neutral[900], 0.16), // TODO: This is not hooked up to occurences on the rust side
+        matchingBracket: colors.neutral[0],
+        match: withOpacity(colors.red[500], 0.2),
+        activeMatch: withOpacity(colors.indigo[400], 0.36), // TODO: This is not hooked up to occurences on the rust side
+        related: colors.neutral[0],
+    },
+    gutter: {
+        primary: colors.neutral[300],
+        active: textColor.active,
+    },
+};
+
+const syntax: Syntax = {
+    primary: {
+        color: colors.neutral[800],
+        weight: fontWeights.normal,
+    },
+    comment: {
+        color: colors.neutral[500],
+        weight: fontWeights.normal,
+    },
+    punctuation: {
+        color: colors.neutral[600],
+        weight: fontWeights.normal,
+    },
+    constant: {
+        color: colors.neutral[800],
+        weight: fontWeights.normal,
+    },
+    keyword: {
+        color: colors.indigo[700],
+        weight: fontWeights.normal,
+    },
+    function: {
+        color: colors.orange[600],
+        weight: fontWeights.normal,
+    },
+    type: {
+        color: colors.yellow[600],
+        weight: fontWeights.normal,
+    },
+    variant: {
+        color: colors.rose[700],
+        weight: fontWeights.normal,
+    },
+    property: {
+        color: colors.emerald[700],
+        weight: fontWeights.normal,
+    },
+    enum: {
+        color: colors.red[500],
+        weight: fontWeights.normal,
+    },
+    operator: {
+        color: colors.red[500],
+        weight: fontWeights.normal,
+    },
+    string: {
+        color: colors.red[500],
+        weight: fontWeights.normal,
+    },
+    number: {
+        color: colors.indigo[500],
+        weight: fontWeights.normal,
+    },
+    boolean: {
+        color: colors.red[500],
+        weight: fontWeights.normal,
+    },
+    predictive: {
+        color: textColor.placeholder,
+        weight: fontWeights.normal,
+    },
+    title: {
+        color: colors.sky[500],
+        weight: fontWeights.bold,
+    },
+    emphasis: {
+        color: textColor.active,
+        weight: fontWeights.normal,
+    },
+    emphasisStrong: {
+        color: textColor.active,
+        weight: fontWeights.bold,
+    },
+    linkUrl: {
+        color: colors.lime[500],
+        weight: fontWeights.normal,
+        // TODO: add underline
+    },
+    linkText: {
+        color: colors.red[500],
+        weight: fontWeights.normal,
+        // TODO: add italic
+    },
+};
+
+const shadowAlpha: NumberToken = {
+    value: 0.12,
+    type: "number",
+};
+
+const theme: Theme = {
+    name: "light",
+    backgroundColor,
+    borderColor,
+    textColor,
+    iconColor,
+    editor,
+    syntax,
+    player,
+    shadowAlpha,
+};
+
+export default theme;

styles/src/themes/theme.ts 🔗

@@ -0,0 +1,145 @@
+import { ColorToken, FontWeightToken, NumberToken } from "../tokens";
+import { withOpacity } from "../utils/color";
+
+export interface SyntaxHighlightStyle {
+    color: ColorToken;
+    weight: FontWeightToken;
+}
+
+export interface Player {
+    baseColor: ColorToken;
+    cursorColor: ColorToken;
+    selectionColor: ColorToken;
+    borderColor: ColorToken;
+}
+export function buildPlayer(
+    color: ColorToken,
+    cursorOpacity?: number,
+    selectionOpacity?: number,
+    borderOpacity?: number
+) {
+    return {
+        baseColor: color,
+        cursorColor: withOpacity(color, cursorOpacity || 1.0),
+        selectionColor: withOpacity(color, selectionOpacity || 0.24),
+        borderColor: withOpacity(color, borderOpacity || 0.8),
+    }
+}
+
+export interface BackgroundColorSet {
+    base: ColorToken;
+    hovered: ColorToken;
+    active: ColorToken;
+    focused: ColorToken;
+}
+
+export interface Syntax {
+    primary: SyntaxHighlightStyle;
+    comment: SyntaxHighlightStyle;
+    punctuation: SyntaxHighlightStyle;
+    constant: SyntaxHighlightStyle;
+    keyword: SyntaxHighlightStyle;
+    function: SyntaxHighlightStyle;
+    type: SyntaxHighlightStyle;
+    variant: SyntaxHighlightStyle;
+    property: SyntaxHighlightStyle;
+    enum: SyntaxHighlightStyle;
+    operator: SyntaxHighlightStyle;
+    string: SyntaxHighlightStyle;
+    number: SyntaxHighlightStyle;
+    boolean: SyntaxHighlightStyle;
+    predictive: SyntaxHighlightStyle;
+    // TODO: Either move the following or rename
+    title: SyntaxHighlightStyle;
+    emphasis: SyntaxHighlightStyle;
+    emphasisStrong: SyntaxHighlightStyle;
+    linkUrl: SyntaxHighlightStyle;
+    linkText: SyntaxHighlightStyle;
+};
+
+export default interface Theme {
+    name: string;
+    backgroundColor: {
+        100: BackgroundColorSet;
+        300: BackgroundColorSet;
+        500: BackgroundColorSet;
+        ok: BackgroundColorSet;
+        error: BackgroundColorSet;
+        warning: BackgroundColorSet;
+        info: BackgroundColorSet;
+    };
+    borderColor: {
+        primary: ColorToken;
+        secondary: ColorToken;
+        muted: ColorToken;
+        focused: ColorToken;
+        active: ColorToken;
+        ok: ColorToken;
+        error: ColorToken;
+        warning: ColorToken;
+        info: ColorToken;
+    };
+    textColor: {
+        primary: ColorToken;
+        secondary: ColorToken;
+        muted: ColorToken;
+        placeholder: ColorToken;
+        active: ColorToken;
+        feature: ColorToken;
+        ok: ColorToken;
+        error: ColorToken;
+        warning: ColorToken;
+        info: ColorToken;
+    };
+    iconColor: {
+        primary: ColorToken;
+        secondary: ColorToken;
+        muted: ColorToken;
+        placeholder: ColorToken;
+        active: ColorToken;
+        feature: ColorToken;
+        ok: ColorToken;
+        error: ColorToken;
+        warning: ColorToken;
+        info: ColorToken;
+    };
+    editor: {
+        background: ColorToken;
+        indent_guide: ColorToken;
+        indent_guide_active: ColorToken;
+        line: {
+            active: ColorToken;
+            highlighted: ColorToken;
+            inserted: ColorToken;
+            deleted: ColorToken;
+            modified: ColorToken;
+        };
+        highlight: {
+            selection: ColorToken;
+            occurrence: ColorToken;
+            activeOccurrence: ColorToken;
+            matchingBracket: ColorToken;
+            match: ColorToken;
+            activeMatch: ColorToken;
+            related: ColorToken;
+        };
+        gutter: {
+            primary: ColorToken;
+            active: ColorToken;
+        };
+    };
+
+    syntax: Syntax,
+
+    player: {
+        1: Player;
+        2: Player;
+        3: Player;
+        4: Player;
+        5: Player;
+        6: Player;
+        7: Player;
+        8: Player;
+    };
+    shadowAlpha: NumberToken;
+}

styles/src/tokens.ts 🔗

@@ -0,0 +1,102 @@
+import { colorRamp } from "./utils/color";
+
+interface Token<V, T> {
+  value: V,
+  type: T
+}
+
+export type FontFamily = string;
+export type FontFamilyToken = Token<FontFamily, "fontFamily">;
+function fontFamily(value: FontFamily): FontFamilyToken {
+  return {
+    value,
+    type: "fontFamily"
+  }
+}
+export const fontFamilies = {
+  sans: fontFamily("Zed Sans"),
+  mono: fontFamily("Zed Mono"),
+}
+
+export type FontSize = number;
+export type FontSizeToken = Token<FontSize, "fontSize">;
+function fontSize(value: FontSize) {
+  return {
+    value,
+    type: "fontSize"
+  };
+}
+export const fontSizes = {
+  "3xs": fontSize(8),
+  "2xs": fontSize(10),
+  xs: fontSize(12),
+  sm: fontSize(14),
+  md: fontSize(16),
+  lg: fontSize(18),
+  xl: fontSize(20),
+};
+
+export type FontWeight = 
+  | "thin"
+  | "extra_light"
+  | "light"
+  | "normal"
+  | "medium"
+  | "semibold"
+  | "bold"
+  | "extra_bold"
+  | "black";
+export type FontWeightToken = Token<FontWeight, "fontWeight">;
+function fontWeight(value: FontWeight): FontWeightToken {
+  return {
+    value,
+    type: "fontWeight"
+  };
+}
+export const fontWeights = {
+  "thin": fontWeight("thin"),
+  "extra_light": fontWeight("extra_light"),
+  "light": fontWeight("light"),
+  "normal": fontWeight("normal"),
+  "medium": fontWeight("medium"),
+  "semibold": fontWeight("semibold"),
+  "bold": fontWeight("bold"),
+  "extra_bold": fontWeight("extra_bold"),
+  "black": fontWeight("black"),
+}
+
+export type Color = string;
+export interface ColorToken {
+  value: Color,
+  type: "color",
+  step?: number,
+}
+export const colors = {
+  neutral: colorRamp(["white", "black"], { steps: 37, increment: 25 }), // (900/25) + 1
+  rose: colorRamp("#F43F5EFF"),
+  red: colorRamp("#EF4444FF"),
+  orange: colorRamp("#F97316FF"),
+  amber: colorRamp("#F59E0BFF"),
+  yellow: colorRamp("#EAB308FF"),
+  lime: colorRamp("#84CC16FF"),
+  green: colorRamp("#22C55EFF"),
+  emerald: colorRamp("#10B981FF"),
+  teal: colorRamp("#14B8A6FF"),
+  cyan: colorRamp("#06BBD4FF"),
+  sky: colorRamp("#0EA5E9FF"),
+  blue: colorRamp("#3B82F6FF"),
+  indigo: colorRamp("#6366F1FF"),
+  violet: colorRamp("#8B5CF6FF"),
+  purple: colorRamp("#A855F7FF"),
+  fuschia: colorRamp("#D946E4FF"),
+  pink: colorRamp("#EC4899FF"),
+}
+
+export type NumberToken = Token<number, "number">;
+
+export default {
+  fontFamilies,
+  fontSizes,
+  fontWeights,
+  colors,
+};

styles/src/utils/color.ts 🔗

@@ -0,0 +1,52 @@
+import chroma, { Scale } from "chroma-js";
+import { ColorToken } from "../tokens";
+
+export type Color = string;
+export type ColorRampStep = { value: Color; type: "color"; step: number };
+export type ColorRamp = {
+    [index: number]: ColorRampStep;
+};
+
+export function colorRamp(
+    color: Color | [Color, Color],
+    options?: { steps?: number; increment?: number; }
+): ColorRamp {
+    let scale: Scale;
+    if (Array.isArray(color)) {
+        const [startColor, endColor] = color;
+        scale = chroma.scale([startColor, endColor]);
+    } else {
+        let hue = Math.round(chroma(color).hsl()[0]);
+        let startColor = chroma.hsl(hue, 0.88, 0.96);
+        let endColor = chroma.hsl(hue, 0.68, 0.12);
+        scale = chroma
+            .scale([startColor, color, endColor])
+            .domain([0, 0.5, 1])
+            .mode("hsl")
+            .gamma(1)
+            // .correctLightness(true)
+            .padding([0, 0]);
+    }
+
+    const ramp: ColorRamp = {};
+    const steps = options?.steps || 10;
+    const increment = options?.increment || 100;
+
+    scale.colors(steps, "hex").forEach((color, ix) => {
+        const step = ix * increment;
+        ramp[step] = {
+            value: color,
+            step,
+            type: "color",
+        };
+    });
+
+    return ramp;
+}
+
+export function withOpacity(color: ColorToken, opacity: number): ColorToken {
+    return {
+        ...color,
+        value: chroma(color.value).alpha(opacity).hex()
+    };
+}

styles/src/utils/snakeCase.ts 🔗

@@ -0,0 +1,35 @@
+import { snakeCase } from "case-anything";
+
+// https://stackoverflow.com/questions/60269936/typescript-convert-generic-object-from-snake-to-camel-case
+
+// Typescript magic to convert any string from camelCase to snake_case at compile time
+type SnakeCase<S> =
+    S extends string ?
+    S extends `${infer T}${infer U}` ?
+    `${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${SnakeCase<U>}` :
+    S :
+    S;
+
+type SnakeCased<Type> = {
+    [Property in keyof Type as SnakeCase<Property>]: SnakeCased<Type[Property]>
+}
+
+export default function snakeCaseTree<T>(object: T): SnakeCased<T> {
+    const snakeObject: any = {};
+    for (const key in object) {
+        snakeObject[snakeCase(key)] = snakeCaseValue(object[key]);
+    }
+    return snakeObject;
+}
+
+function snakeCaseValue(value: any): any {
+    if (typeof value === "object") {
+        if (Array.isArray(value)) {
+            return value.map(snakeCaseValue);
+        } else {
+            return snakeCaseTree(value);
+        }
+    } else {
+        return value;
+    }
+}

styles/tsconfig.json 🔗

@@ -0,0 +1,14 @@
+{
+    "compilerOptions": {
+        "target": "es2015",
+        "module": "commonjs",
+        "esModuleInterop": true,
+        "noImplicitAny": true,
+        "removeComments": true,
+        "preserveConstEnums": true,
+        "sourceMap": true
+    },
+    "exclude": [
+        "node_modules"
+    ]
+}