Merge branch 'main' into v0.119.x

Joseph T. Lyons created

Change summary

Cargo.lock                                                                |   20 
Cargo.toml                                                                |    8 
assets/keymaps/default.json                                               |    2 
crates/assistant/src/assistant_panel.rs                                   |   10 
crates/call/src/participant.rs                                            |    2 
crates/call/src/room.rs                                                   |   58 
crates/channel/src/channel_buffer.rs                                      |    7 
crates/channel/src/channel_store.rs                                       |    9 
crates/collab/Cargo.toml                                                  |    2 
crates/collab/k8s/collab.template.yml                                     |    1 
crates/collab/k8s/postgrest.template.yml                                  |    1 
crates/collab/migrations.sqlite/20221109000000_test_schema.sql            |    3 
crates/collab/migrations/20240103025509_add_role_to_room_participants.sql |    1 
crates/collab/src/db/ids.rs                                               |    8 
crates/collab/src/db/queries/channels.rs                                  |   57 
crates/collab/src/db/queries/projects.rs                                  |    7 
crates/collab/src/db/queries/rooms.rs                                     |   40 
crates/collab/src/db/tables/room_participant.rs                           |    3 
crates/collab/src/tests.rs                                                |    1 
crates/collab/src/tests/channel_guest_tests.rs                            |   86 
crates/collab/src/tests/editor_tests.rs                                   | 3773 
crates/collab/src/tests/integration_tests.rs                              |   26 
crates/collab/src/tests/random_project_collaboration_tests.rs             |    4 
crates/collab/src/tests/randomized_test_helpers.rs                        |    2 
crates/collab_ui/src/channel_view.rs                                      |   15 
crates/collab_ui/src/chat_panel.rs                                        |    8 
crates/collab_ui/src/collab_panel.rs                                      |  105 
crates/collab_ui/src/collab_panel/channel_modal.rs                        |   67 
crates/collab_ui/src/collab_titlebar_item.rs                              |  107 
crates/diagnostics/src/diagnostics.rs                                     |    8 
crates/editor/src/editor.rs                                               |   31 
crates/editor/src/editor_tests.rs                                         |   21 
crates/editor/src/element.rs                                              |    8 
crates/editor/src/git.rs                                                  |    3 
crates/editor/src/hover_popover.rs                                        |    8 
crates/editor/src/inlay_hint_cache.rs                                     |    7 
crates/editor/src/items.rs                                                |   36 
crates/editor/src/link_go_to_definition.rs                                |    5 
crates/editor/src/movement.rs                                             |    3 
crates/feedback/src/feedback_modal.rs                                     |   16 
crates/gpui/Cargo.toml                                                    |    3 
crates/gpui/src/app/entity_map.rs                                         |  125 
crates/gpui/src/app/test_context.rs                                       |  135 
crates/gpui/src/color.rs                                                  |    9 
crates/gpui/src/element.rs                                                |    5 
crates/gpui/src/geometry.rs                                               |   45 
crates/gpui/src/interactive.rs                                            |    6 
crates/gpui/src/platform.rs                                               |   73 
crates/gpui/src/platform/mac/dispatcher.rs                                |   10 
crates/gpui/src/platform/test/platform.rs                                 |   38 
crates/gpui/src/platform/test/window.rs                                   |  143 
crates/gpui/src/view.rs                                                   |    5 
crates/gpui/src/window.rs                                                 |   46 
crates/language/src/buffer.rs                                             |   28 
crates/language/src/buffer_tests.rs                                       |   14 
crates/language_tools/src/lsp_log.rs                                      |    6 
crates/live_kit_server/src/token.rs                                       |    1 
crates/multi_buffer/src/multi_buffer.rs                                   |   39 
crates/project/src/project.rs                                             |   45 
crates/project/src/worktree.rs                                            |   12 
crates/project_panel/src/project_panel.rs                                 |   35 
crates/project_symbols/src/project_symbols.rs                             |    1 
crates/rpc/proto/zed.proto                                                |    1 
crates/search/src/buffer_search.rs                                        |    3 
crates/search/src/project_search.rs                                       |  344 
crates/settings/Cargo.toml                                                |    1 
crates/terminal/src/terminal.rs                                           |   10 
crates/terminal_view/src/terminal_panel.rs                                |   11 
crates/terminal_view/src/terminal_view.rs                                 |    2 
crates/theme/src/styles/players.rs                                        |    9 
crates/theme/src/themes/LICENSES                                          | 1013 
crates/theme/src/themes/atelier.rs                                        |  652 
crates/theme/src/themes/gruvbox.rs                                        |  664 
crates/theme/src/themes/one.rs                                            |  630 
crates/theme/src/themes/rose_pine.rs                                      |  650 
crates/theme/src/themes/solarized.rs                                      |  614 
crates/theme_importer/Cargo.toml                                          |    1 
crates/theme_importer/src/main.rs                                         |   50 
crates/theme_importer/src/zed1.rs                                         |    2 
crates/theme_importer/src/zed1/licenses.rs                                | 1192 
crates/ui/src/components/button/button.rs                                 |    7 
crates/ui/src/components/button/button_icon.rs                            |   11 
crates/ui/src/components/button/button_like.rs                            |  116 
crates/ui/src/components/button/icon_button.rs                            |   11 
crates/ui/src/components/button/toggle_button.rs                          |    7 
crates/ui/src/components/checkbox.rs                                      |  179 
crates/ui/src/prelude.rs                                                  |    2 
crates/welcome/src/welcome.rs                                             |  292 
crates/workspace/Cargo.toml                                               |    1 
crates/workspace/src/dock.rs                                              |   10 
crates/workspace/src/pane_group.rs                                        |   10 
crates/workspace/src/persistence.rs                                       |  136 
crates/workspace/src/persistence/model.rs                                 |   23 
crates/workspace/src/workspace.rs                                         |   33 
docs/old/theme/generating-theme-types.md                                  |   29 
script/deploy-migration                                                   |    7 
script/generate-licenses                                                  |    5 
styles/.eslintrc.js                                                       |   34 
styles/.gitignore                                                         |    2 
styles/.prettierignore                                                    |    3 
styles/.prettierrc                                                        |    6 
styles/.zed/settings.json                                                 |   20 
styles/package-lock.json                                                  | 4372 
styles/package.json                                                       |   37 
styles/src/build_licenses.ts                                              |   50 
styles/src/build_themes.ts                                                |   45 
styles/src/build_tokens.ts                                                |   88 
styles/src/build_types.ts                                                 |   62 
styles/src/common.ts                                                      |   34 
styles/src/component/button.ts                                            |  127 
styles/src/component/icon_button.ts                                       |  111 
styles/src/component/index.ts                                             |    6 
styles/src/component/indicator.ts                                         |   15 
styles/src/component/input.ts                                             |   23 
styles/src/component/tab.ts                                               |   73 
styles/src/component/tab_bar_button.ts                                    |   58 
styles/src/component/text_button.ts                                       |  129 
styles/src/element/index.ts                                               |    6 
styles/src/element/interactive.test.ts                                    |   56 
styles/src/element/interactive.ts                                         |   97 
styles/src/element/margin.ts                                              |   41 
styles/src/element/padding.ts                                             |   41 
styles/src/element/toggle.test.ts                                         |   52 
styles/src/element/toggle.ts                                              |   47 
styles/src/style_tree/app.ts                                              |   65 
styles/src/style_tree/assistant.ts                                        |  398 
styles/src/style_tree/chat_panel.ts                                       |  160 
styles/src/style_tree/collab_modals.ts                                    |  176 
styles/src/style_tree/collab_panel.ts                                     |  427 
styles/src/style_tree/command_palette.ts                                  |   46 
styles/src/style_tree/component_test.ts                                   |   27 
styles/src/style_tree/components.ts                                       |  302 
styles/src/style_tree/contact_finder.ts                                   |   74 
styles/src/style_tree/contact_notification.ts                             |   55 
styles/src/style_tree/contacts_popover.ts                                 |    6 
styles/src/style_tree/context_menu.ts                                     |   60 
styles/src/style_tree/copilot.ts                                          |  293 
styles/src/style_tree/editor.ts                                           |  327 
styles/src/style_tree/feedback.ts                                         |   59 
styles/src/style_tree/hover_popover.ts                                    |   49 
styles/src/style_tree/incoming_call_notification.ts                       |   55 
styles/src/style_tree/notification_panel.ts                               |   75 
styles/src/style_tree/picker.ts                                           |  158 
styles/src/style_tree/project_diagnostics.ts                              |   14 
styles/src/style_tree/project_panel.ts                                    |  201 
styles/src/style_tree/project_shared_notification.ts                      |   55 
styles/src/style_tree/search.ts                                           |  437 
styles/src/style_tree/shared_screen.ts                                    |   10 
styles/src/style_tree/simple_message_notification.ts                      |   52 
styles/src/style_tree/status_bar.ts                                       |  161 
styles/src/style_tree/tab_bar.ts                                          |  167 
styles/src/style_tree/terminal.ts                                         |   54 
styles/src/style_tree/titlebar.ts                                         |  287 
styles/src/style_tree/toolbar.ts                                          |   58 
styles/src/style_tree/toolbar_dropdown_menu.ts                            |   66 
styles/src/style_tree/tooltip.ts                                          |   24 
styles/src/style_tree/update_notification.ts                              |   41 
styles/src/style_tree/welcome.ts                                          |  157 
styles/src/style_tree/workspace.ts                                        |  153 
styles/src/theme/color.ts                                                 |    5 
styles/src/theme/create_theme.ts                                          |  329 
styles/src/theme/index.ts                                                 |   26 
styles/src/theme/ramps.ts                                                 |   47 
styles/src/theme/syntax.ts                                                |  332 
styles/src/theme/theme_config.ts                                          |   81 
styles/src/theme/tokens/layer.ts                                          |   63 
styles/src/theme/tokens/players.ts                                        |   37 
styles/src/theme/tokens/theme.ts                                          |   97 
styles/src/theme/tokens/token.ts                                          |   19 
styles/src/themes/andromeda/LICENSE                                       |   21 
styles/src/themes/andromeda/andromeda.ts                                  |   39 
styles/src/themes/atelier/LICENSE                                         |   21 
styles/src/themes/atelier/atelier-cave-dark.ts                            |   61 
styles/src/themes/atelier/atelier-cave-light.ts                           |   63 
styles/src/themes/atelier/atelier-dune-dark.ts                            |   61 
styles/src/themes/atelier/atelier-dune-light.ts                           |   63 
styles/src/themes/atelier/atelier-estuary-dark.ts                         |   61 
styles/src/themes/atelier/atelier-estuary-light.ts                        |   63 
styles/src/themes/atelier/atelier-forest-dark.ts                          |   61 
styles/src/themes/atelier/atelier-forest-light.ts                         |   63 
styles/src/themes/atelier/atelier-heath-dark.ts                           |   61 
styles/src/themes/atelier/atelier-heath-light.ts                          |   63 
styles/src/themes/atelier/atelier-lakeside-dark.ts                        |   61 
styles/src/themes/atelier/atelier-lakeside-light.ts                       |   63 
styles/src/themes/atelier/atelier-plateau-dark.ts                         |   61 
styles/src/themes/atelier/atelier-plateau-light.ts                        |   63 
styles/src/themes/atelier/atelier-savanna-dark.ts                         |   61 
styles/src/themes/atelier/atelier-savanna-light.ts                        |   63 
styles/src/themes/atelier/atelier-seaside-dark.ts                         |   61 
styles/src/themes/atelier/atelier-seaside-light.ts                        |   63 
styles/src/themes/atelier/atelier-sulphurpool-dark.ts                     |   61 
styles/src/themes/atelier/atelier-sulphurpool-light.ts                    |   63 
styles/src/themes/atelier/common.ts                                       |   56 
styles/src/themes/ayu/LICENSE                                             |   21 
styles/src/themes/ayu/ayu-dark.ts                                         |   16 
styles/src/themes/ayu/ayu-light.ts                                        |   16 
styles/src/themes/ayu/ayu-mirage.ts                                       |   16 
styles/src/themes/ayu/common.ts                                           |   85 
styles/src/themes/gruvbox/LICENSE                                         |   21 
styles/src/themes/gruvbox/gruvbox-common.ts                               |  264 
styles/src/themes/gruvbox/gruvbox-dark-hard.ts                            |    1 
styles/src/themes/gruvbox/gruvbox-dark-soft.ts                            |    1 
styles/src/themes/gruvbox/gruvbox-dark.ts                                 |    1 
styles/src/themes/gruvbox/gruvbox-light-hard.ts                           |    1 
styles/src/themes/gruvbox/gruvbox-light-soft.ts                           |    1 
styles/src/themes/gruvbox/gruvbox-light.ts                                |    1 
styles/src/themes/index.ts                                                |   82 
styles/src/themes/one/LICENSE                                             |   21 
styles/src/themes/one/one-dark.ts                                         |   80 
styles/src/themes/one/one-light.ts                                        |   79 
styles/src/themes/rose-pine/LICENSE                                       |   21 
styles/src/themes/rose-pine/common.ts                                     |   75 
styles/src/themes/rose-pine/rose-pine-dawn.ts                             |   49 
styles/src/themes/rose-pine/rose-pine-moon.ts                             |   47 
styles/src/themes/rose-pine/rose-pine.ts                                  |   44 
styles/src/themes/sandcastle/LICENSE                                      |   21 
styles/src/themes/sandcastle/sandcastle.ts                                |   37 
styles/src/themes/solarized/LICENSE                                       |   21 
styles/src/themes/solarized/solarized.ts                                  |   52 
styles/src/themes/staff/.gitkeep                                          |    0 
styles/src/themes/summercamp/LICENSE                                      |   21 
styles/src/themes/summercamp/summercamp.ts                                |   39 
styles/src/utils/slugify.ts                                               |   10 
styles/tsconfig.json                                                      |   27 
styles/vitest.config.ts                                                   |    8 
225 files changed, 7,620 insertions(+), 18,487 deletions(-)

Detailed changes

Cargo.lock πŸ”—

@@ -576,8 +576,9 @@ dependencies = [
 
 [[package]]
 name = "async-task"
-version = "4.0.3"
-source = "git+https://github.com/zed-industries/async-task?rev=341b57d6de98cdfd7b418567b8de2022ca993a6e#341b57d6de98cdfd7b418567b8de2022ca993a6e"
+version = "4.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
 
 [[package]]
 name = "async-tls"
@@ -1440,7 +1441,7 @@ dependencies = [
 
 [[package]]
 name = "collab"
-version = "0.33.0"
+version = "0.34.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -1925,11 +1926,12 @@ dependencies = [
 
 [[package]]
 name = "ctor"
-version = "0.1.20"
-source = "git+https://github.com/zed-industries/rust-ctor?rev=7f824cf6a7943885a649b579f33f9ac53f0d1db6#7f824cf6a7943885a649b579f33f9ac53f0d1db6"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e"
 dependencies = [
  "quote",
- "syn 1.0.109",
+ "syn 2.0.37",
 ]
 
 [[package]]
@@ -3064,7 +3066,6 @@ dependencies = [
  "slotmap",
  "smallvec",
  "smol",
- "sqlez",
  "sum_tree",
  "taffy",
  "thiserror",
@@ -6845,7 +6846,6 @@ dependencies = [
  "serde_json",
  "serde_json_lenient",
  "smallvec",
- "sqlez",
  "toml 0.5.11",
  "tree-sitter",
  "tree-sitter-json 0.19.0",
@@ -7837,6 +7837,7 @@ dependencies = [
  "convert_case 0.6.0",
  "gpui",
  "indexmap 1.9.3",
+ "indoc",
  "json_comments",
  "log",
  "palette",
@@ -8488,7 +8489,7 @@ dependencies = [
 [[package]]
 name = "tree-sitter-nu"
 version = "0.0.1"
-source = "git+https://github.com/nushell/tree-sitter-nu?rev=a0b80b2e21e5e39571252dc799e19eb89f1fc912#a0b80b2e21e5e39571252dc799e19eb89f1fc912"
+source = "git+https://github.com/nushell/tree-sitter-nu?rev=26bbaecda0039df4067861ab38ea8ea169f7f5aa#26bbaecda0039df4067861ab38ea8ea169f7f5aa"
 dependencies = [
  "cc",
  "tree-sitter",
@@ -9438,6 +9439,7 @@ dependencies = [
  "serde_json",
  "settings",
  "smallvec",
+ "sqlez",
  "terminal",
  "theme",
  "ui",

Cargo.toml πŸ”—

@@ -92,10 +92,7 @@ resolver = "2"
 anyhow = { version = "1.0.57" }
 async-trait = { version = "0.1" }
 async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
-# TODO: Switch back to the published version of `ctor` once:
-#       1. A new version of `ctor` is published with this change: https://github.com/mmastrac/rust-ctor/pull/295
-#       2. We've confirmed it's fine to update to the latest version of `ctor` (we're currently on v0.1.20).
-ctor = { git = "https://github.com/zed-industries/rust-ctor", rev = "7f824cf6a7943885a649b579f33f9ac53f0d1db6" }
+ctor = "0.2.6"
 derive_more = { version = "0.99.17" }
 env_logger = { version = "0.9" }
 futures = { version = "0.3" }
@@ -158,13 +155,12 @@ tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-rack
 tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "f545a41f57502e1b5ddf2a6668896c1b0620f930"}
 tree-sitter-lua = "0.0.14"
 tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" }
-tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "a0b80b2e21e5e39571252dc799e19eb89f1fc912"}
+tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "26bbaecda0039df4067861ab38ea8ea169f7f5aa"}
 tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"}
 tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"}
 
 [patch.crates-io]
 tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "31c40449749c4263a91a43593831b82229049a4c" }
-async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" }
 # wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", rev = "v16.0.0" }
 
 # TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457

assets/keymaps/default.json πŸ”—

@@ -402,7 +402,7 @@
       "cmd-r": "workspace::ToggleRightDock",
       "cmd-j": "workspace::ToggleBottomDock",
       "alt-cmd-y": "workspace::CloseAllDocks",
-      "cmd-shift-f": "workspace::NewSearch",
+      "cmd-shift-f": "workspace::DeploySearch",
       "cmd-k cmd-t": "theme_selector::Toggle",
       "cmd-k cmd-s": "zed::OpenKeymap",
       "cmd-t": "project_symbols::Toggle",

crates/assistant/src/assistant_panel.rs πŸ”—

@@ -1286,8 +1286,8 @@ impl Panel for AssistantPanel {
         }
     }
 
-    fn icon(&self, _cx: &WindowContext) -> Option<Icon> {
-        Some(Icon::Ai)
+    fn icon(&self, cx: &WindowContext) -> Option<Icon> {
+        Some(Icon::Ai).filter(|_| AssistantSettings::get_global(cx).button)
     }
 
     fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
@@ -2827,8 +2827,8 @@ impl InlineAssistant {
 
     fn handle_codegen_changed(&mut self, _: Model<Codegen>, cx: &mut ViewContext<Self>) {
         let is_read_only = !self.codegen.read(cx).idle();
-        self.prompt_editor.update(cx, |editor, _cx| {
-            let was_read_only = editor.read_only();
+        self.prompt_editor.update(cx, |editor, cx| {
+            let was_read_only = editor.read_only(cx);
             if was_read_only != is_read_only {
                 if is_read_only {
                     editor.set_read_only(true);
@@ -3063,7 +3063,7 @@ impl InlineAssistant {
     fn render_prompt_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
         let settings = ThemeSettings::get_global(cx);
         let text_style = TextStyle {
-            color: if self.prompt_editor.read(cx).read_only() {
+            color: if self.prompt_editor.read(cx).read_only(cx) {
                 cx.theme().colors().text_disabled
             } else {
                 cx.theme().colors().text

crates/call/src/participant.rs πŸ”—

@@ -36,12 +36,14 @@ impl ParticipantLocation {
 pub struct LocalParticipant {
     pub projects: Vec<proto::ParticipantProject>,
     pub active_project: Option<WeakModel<Project>>,
+    pub role: proto::ChannelRole,
 }
 
 #[derive(Clone, Debug)]
 pub struct RemoteParticipant {
     pub user: Arc<User>,
     pub peer_id: proto::PeerId,
+    pub role: proto::ChannelRole,
     pub projects: Vec<proto::ParticipantProject>,
     pub location: ParticipantLocation,
     pub participant_index: ParticipantIndex,

crates/call/src/room.rs πŸ”—

@@ -247,14 +247,18 @@ impl Room {
             let response = client.request(proto::CreateRoom {}).await?;
             let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
             let room = cx.new_model(|cx| {
-                Self::new(
+                let mut room = Self::new(
                     room_proto.id,
                     None,
                     response.live_kit_connection_info,
                     client,
                     user_store,
                     cx,
-                )
+                );
+                if let Some(participant) = room_proto.participants.first() {
+                    room.local_participant.role = participant.role()
+                }
+                room
             })?;
 
             let initial_project_id = if let Some(initial_project) = initial_project {
@@ -606,6 +610,16 @@ impl Room {
             .find(|p| p.peer_id == peer_id)
     }
 
+    pub fn role_for_user(&self, user_id: u64) -> Option<proto::ChannelRole> {
+        self.remote_participants
+            .get(&user_id)
+            .map(|participant| participant.role)
+    }
+
+    pub fn local_participant_is_admin(&self) -> bool {
+        self.local_participant.role == proto::ChannelRole::Admin
+    }
+
     pub fn pending_participants(&self) -> &[Arc<User>] {
         &self.pending_participants
     }
@@ -710,7 +724,20 @@ impl Room {
                 this.participant_user_ids.clear();
 
                 if let Some(participant) = local_participant {
+                    let role = participant.role();
                     this.local_participant.projects = participant.projects;
+                    if this.local_participant.role != role {
+                        this.local_participant.role = role;
+
+                        this.joined_projects.retain(|project| {
+                            if let Some(project) = project.upgrade() {
+                                project.update(cx, |project, _| project.set_role(role));
+                                true
+                            } else {
+                                false
+                            }
+                        });
+                    }
                 } else {
                     this.local_participant.projects.clear();
                 }
@@ -766,6 +793,7 @@ impl Room {
                             });
                         }
 
+                        let role = participant.role();
                         let location = ParticipantLocation::from_proto(participant.location)
                             .unwrap_or(ParticipantLocation::External);
                         if let Some(remote_participant) =
@@ -774,8 +802,11 @@ impl Room {
                             remote_participant.peer_id = peer_id;
                             remote_participant.projects = participant.projects;
                             remote_participant.participant_index = participant_index;
-                            if location != remote_participant.location {
+                            if location != remote_participant.location
+                                || role != remote_participant.role
+                            {
                                 remote_participant.location = location;
+                                remote_participant.role = role;
                                 cx.emit(Event::ParticipantLocationChanged {
                                     participant_id: peer_id,
                                 });
@@ -789,6 +820,7 @@ impl Room {
                                     peer_id,
                                     projects: participant.projects,
                                     location,
+                                    role,
                                     muted: true,
                                     speaking: false,
                                     video_tracks: Default::default(),
@@ -1091,15 +1123,24 @@ impl Room {
     ) -> Task<Result<Model<Project>>> {
         let client = self.client.clone();
         let user_store = self.user_store.clone();
+        let role = self.local_participant.role;
         cx.emit(Event::RemoteProjectJoined { project_id: id });
         cx.spawn(move |this, mut cx| async move {
-            let project =
-                Project::remote(id, client, user_store, language_registry, fs, cx.clone()).await?;
+            let project = Project::remote(
+                id,
+                client,
+                user_store,
+                language_registry,
+                fs,
+                role,
+                cx.clone(),
+            )
+            .await?;
 
             this.update(&mut cx, |this, cx| {
                 this.joined_projects.retain(|project| {
                     if let Some(project) = project.upgrade() {
-                        !project.read(cx).is_read_only()
+                        !project.read(cx).is_disconnected()
                     } else {
                         false
                     }
@@ -1224,6 +1265,11 @@ impl Room {
             .unwrap_or(false)
     }
 
+    pub fn read_only(&self) -> bool {
+        !(self.local_participant().role == proto::ChannelRole::Member
+            || self.local_participant().role == proto::ChannelRole::Admin)
+    }
+
     pub fn is_speaking(&self) -> bool {
         self.live_kit
             .as_ref()

crates/channel/src/channel_buffer.rs πŸ”—

@@ -62,7 +62,12 @@ impl ChannelBuffer {
             .collect::<Result<Vec<_>, _>>()?;
 
         let buffer = cx.new_model(|_| {
-            language::Buffer::remote(response.buffer_id, response.replica_id as u16, base_text)
+            language::Buffer::remote(
+                response.buffer_id,
+                response.replica_id as u16,
+                channel.channel_buffer_capability(),
+                base_text,
+            )
         })?;
         buffer.update(&mut cx, |buffer, cx| buffer.apply_ops(operations, cx))??;
 

crates/channel/src/channel_store.rs πŸ”—

@@ -11,6 +11,7 @@ use gpui::{
     AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, SharedString, Task,
     WeakModel,
 };
+use language::Capability;
 use rpc::{
     proto::{self, ChannelVisibility},
     TypedEnvelope,
@@ -74,8 +75,12 @@ impl Channel {
         slug.trim_matches(|c| c == '-').to_string()
     }
 
-    pub fn can_edit_notes(&self) -> bool {
-        self.role == proto::ChannelRole::Member || self.role == proto::ChannelRole::Admin
+    pub fn channel_buffer_capability(&self) -> Capability {
+        if self.role == proto::ChannelRole::Member || self.role == proto::ChannelRole::Admin {
+            Capability::ReadWrite
+        } else {
+            Capability::ReadOnly
+        }
     }
 }
 

crates/collab/Cargo.toml πŸ”—

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathan@zed.dev>"]
 default-run = "collab"
 edition = "2021"
 name = "collab"
-version = "0.33.0"
+version = "0.34.0"
 publish = false
 
 [[bin]]

crates/collab/k8s/collab.template.yml πŸ”—

@@ -13,6 +13,7 @@ metadata:
   annotations:
     service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
     service.beta.kubernetes.io/do-loadbalancer-certificate-id: ${ZED_DO_CERTIFICATE_ID}
+    service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
 spec:
   type: LoadBalancer
   selector:

crates/collab/k8s/postgrest.template.yml πŸ”—

@@ -7,6 +7,7 @@ metadata:
   annotations:
     service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
     service.beta.kubernetes.io/do-loadbalancer-certificate-id: ${ZED_DO_CERTIFICATE_ID}
+    service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
 spec:
   type: LoadBalancer
   selector:

crates/collab/migrations.sqlite/20221109000000_test_schema.sql πŸ”—

@@ -161,7 +161,8 @@ CREATE TABLE "room_participants" (
     "calling_user_id" INTEGER NOT NULL REFERENCES users (id),
     "calling_connection_id" INTEGER NOT NULL,
     "calling_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE SET NULL,
-    "participant_index" INTEGER
+    "participant_index" INTEGER,
+    "role" TEXT
 );
 CREATE UNIQUE INDEX "index_room_participants_on_user_id" ON "room_participants" ("user_id");
 CREATE INDEX "index_room_participants_on_room_id" ON "room_participants" ("room_id");

crates/collab/src/db/ids.rs πŸ”—

@@ -132,6 +132,14 @@ impl ChannelRole {
             Admin | Member | Banned => false,
         }
     }
+
+    pub fn can_share_projects(&self) -> bool {
+        use ChannelRole::*;
+        match self {
+            Admin | Member => true,
+            Guest | Banned => false,
+        }
+    }
 }
 
 impl From<proto::ChannelRole> for ChannelRole {

crates/collab/src/db/queries/channels.rs πŸ”—

@@ -132,48 +132,49 @@ impl Database {
                     debug_assert!(
                         self.channel_role_for_user(&channel, user_id, &*tx).await? == role
                     );
-                }
-            }
-
-            if channel.visibility == ChannelVisibility::Public {
-                role = Some(ChannelRole::Guest);
-                let channel_to_join = self
-                    .public_ancestors_including_self(&channel, &*tx)
-                    .await?
-                    .first()
-                    .cloned()
-                    .unwrap_or(channel.clone());
-
-                channel_member::Entity::insert(channel_member::ActiveModel {
-                    id: ActiveValue::NotSet,
-                    channel_id: ActiveValue::Set(channel_to_join.id),
-                    user_id: ActiveValue::Set(user_id),
-                    accepted: ActiveValue::Set(true),
-                    role: ActiveValue::Set(ChannelRole::Guest),
-                })
-                .exec(&*tx)
-                .await?;
+                } else if channel.visibility == ChannelVisibility::Public {
+                    role = Some(ChannelRole::Guest);
+                    let channel_to_join = self
+                        .public_ancestors_including_self(&channel, &*tx)
+                        .await?
+                        .first()
+                        .cloned()
+                        .unwrap_or(channel.clone());
+
+                    channel_member::Entity::insert(channel_member::ActiveModel {
+                        id: ActiveValue::NotSet,
+                        channel_id: ActiveValue::Set(channel_to_join.id),
+                        user_id: ActiveValue::Set(user_id),
+                        accepted: ActiveValue::Set(true),
+                        role: ActiveValue::Set(ChannelRole::Guest),
+                    })
+                    .exec(&*tx)
+                    .await?;
 
-                accept_invite_result = Some(
-                    self.calculate_membership_updated(&channel_to_join, user_id, &*tx)
-                        .await?,
-                );
+                    accept_invite_result = Some(
+                        self.calculate_membership_updated(&channel_to_join, user_id, &*tx)
+                            .await?,
+                    );
 
-                debug_assert!(self.channel_role_for_user(&channel, user_id, &*tx).await? == role);
+                    debug_assert!(
+                        self.channel_role_for_user(&channel, user_id, &*tx).await? == role
+                    );
+                }
             }
 
             if role.is_none() || role == Some(ChannelRole::Banned) {
                 Err(anyhow!("not allowed"))?
             }
+            let role = role.unwrap();
 
             let live_kit_room = format!("channel-{}", nanoid::nanoid!(30));
             let room_id = self
                 .get_or_create_channel_room(channel_id, &live_kit_room, environment, &*tx)
                 .await?;
 
-            self.join_channel_room_internal(room_id, user_id, connection, &*tx)
+            self.join_channel_room_internal(room_id, user_id, connection, role, &*tx)
                 .await
-                .map(|jr| (jr, accept_invite_result, role.unwrap()))
+                .map(|jr| (jr, accept_invite_result, role))
         })
         .await
     }

crates/collab/src/db/queries/projects.rs πŸ”—

@@ -46,6 +46,13 @@ impl Database {
             if participant.room_id != room_id {
                 return Err(anyhow!("shared project on unexpected room"))?;
             }
+            if !participant
+                .role
+                .unwrap_or(ChannelRole::Member)
+                .can_share_projects()
+            {
+                return Err(anyhow!("guests cannot share projects"))?;
+            }
 
             let project = project::ActiveModel {
                 room_id: ActiveValue::set(participant.room_id),

crates/collab/src/db/queries/rooms.rs πŸ”—

@@ -131,7 +131,12 @@ impl Database {
                     connection.owner_id as i32,
                 ))),
                 participant_index: ActiveValue::set(Some(0)),
-                ..Default::default()
+                role: ActiveValue::set(Some(ChannelRole::Admin)),
+
+                id: ActiveValue::NotSet,
+                location_kind: ActiveValue::NotSet,
+                location_project_id: ActiveValue::NotSet,
+                initial_project_id: ActiveValue::NotSet,
             }
             .insert(&*tx)
             .await?;
@@ -151,6 +156,22 @@ impl Database {
         initial_project_id: Option<ProjectId>,
     ) -> Result<RoomGuard<(proto::Room, proto::IncomingCall)>> {
         self.room_transaction(room_id, |tx| async move {
+            let caller = room_participant::Entity::find()
+                .filter(
+                    room_participant::Column::UserId
+                        .eq(calling_user_id)
+                        .and(room_participant::Column::RoomId.eq(room_id)),
+                )
+                .one(&*tx)
+                .await?
+                .ok_or_else(|| anyhow!("user is not in the room"))?;
+
+            let called_user_role = match caller.role.unwrap_or(ChannelRole::Member) {
+                ChannelRole::Admin | ChannelRole::Member => ChannelRole::Member,
+                ChannelRole::Guest => ChannelRole::Guest,
+                ChannelRole::Banned => return Err(anyhow!("banned users cannot invite").into()),
+            };
+
             room_participant::ActiveModel {
                 room_id: ActiveValue::set(room_id),
                 user_id: ActiveValue::set(called_user_id),
@@ -162,7 +183,13 @@ impl Database {
                     calling_connection.owner_id as i32,
                 ))),
                 initial_project_id: ActiveValue::set(initial_project_id),
-                ..Default::default()
+                role: ActiveValue::set(Some(called_user_role)),
+
+                id: ActiveValue::NotSet,
+                answering_connection_id: ActiveValue::NotSet,
+                answering_connection_server_id: ActiveValue::NotSet,
+                location_kind: ActiveValue::NotSet,
+                location_project_id: ActiveValue::NotSet,
             }
             .insert(&*tx)
             .await?;
@@ -384,6 +411,7 @@ impl Database {
         room_id: RoomId,
         user_id: UserId,
         connection: ConnectionId,
+        role: ChannelRole,
         tx: &DatabaseTransaction,
     ) -> Result<JoinRoom> {
         let participant_index = self
@@ -404,7 +432,11 @@ impl Database {
                 connection.owner_id as i32,
             ))),
             participant_index: ActiveValue::Set(Some(participant_index)),
-            ..Default::default()
+            role: ActiveValue::set(Some(role)),
+            id: ActiveValue::NotSet,
+            location_kind: ActiveValue::NotSet,
+            location_project_id: ActiveValue::NotSet,
+            initial_project_id: ActiveValue::NotSet,
         }])
         .on_conflict(
             OnConflict::columns([room_participant::Column::UserId])
@@ -413,6 +445,7 @@ impl Database {
                     room_participant::Column::AnsweringConnectionServerId,
                     room_participant::Column::AnsweringConnectionLost,
                     room_participant::Column::ParticipantIndex,
+                    room_participant::Column::Role,
                 ])
                 .to_owned(),
         )
@@ -1126,6 +1159,7 @@ impl Database {
                         projects: Default::default(),
                         location: Some(proto::ParticipantLocation { variant: location }),
                         participant_index: participant_index as u32,
+                        role: db_participant.role.unwrap_or(ChannelRole::Member).into(),
                     },
                 );
             } else {

crates/collab/src/db/tables/room_participant.rs πŸ”—

@@ -1,4 +1,4 @@
-use crate::db::{ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
+use crate::db::{ChannelRole, ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
 use rpc::ConnectionId;
 use sea_orm::entity::prelude::*;
 
@@ -19,6 +19,7 @@ pub struct Model {
     pub calling_connection_id: i32,
     pub calling_connection_server_id: Option<ServerId>,
     pub participant_index: Option<i32>,
+    pub role: Option<ChannelRole>,
 }
 
 impl Model {

crates/collab/src/tests.rs πŸ”—

@@ -2,6 +2,7 @@ use call::Room;
 use gpui::{Model, TestAppContext};
 
 mod channel_buffer_tests;
+mod channel_guest_tests;
 mod channel_message_tests;
 mod channel_tests;
 mod editor_tests;

crates/collab/src/tests/channel_guest_tests.rs πŸ”—

@@ -0,0 +1,86 @@
+use crate::tests::TestServer;
+use call::ActiveCall;
+use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
+use rpc::proto;
+use workspace::Workspace;
+
+#[gpui::test]
+async fn test_channel_guests(
+    executor: BackgroundExecutor,
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(executor.clone()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+
+    let channel_id = server
+        .make_channel("the-channel", None, (&client_a, cx_a), &mut [])
+        .await;
+
+    client_a
+        .channel_store()
+        .update(cx_a, |channel_store, cx| {
+            channel_store.set_channel_visibility(channel_id, proto::ChannelVisibility::Public, cx)
+        })
+        .await
+        .unwrap();
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            serde_json::json!({
+                "a.txt": "a-contents",
+            }),
+        )
+        .await;
+
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    // Client A shares a project in the channel
+    active_call_a
+        .update(cx_a, |call, cx| call.join_channel(channel_id, cx))
+        .await
+        .unwrap();
+    let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    cx_a.executor().run_until_parked();
+
+    // Client B joins channel A as a guest
+    cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
+        .await
+        .unwrap();
+
+    // b should be following a in the shared project.
+    // B is a guest,
+    cx_a.executor().run_until_parked();
+
+    // todo!() the test window does not call activation handlers
+    // correctly yet, so this API does not work.
+    // let project_b = active_call_b.read_with(cx_b, |call, _| {
+    //     call.location()
+    //         .unwrap()
+    //         .upgrade()
+    //         .expect("should not be weak")
+    // });
+
+    let window_b = cx_b.update(|cx| cx.active_window().unwrap());
+    let cx_b = &mut VisualTestContext::from_window(window_b, cx_b);
+
+    let workspace_b = window_b
+        .downcast::<Workspace>()
+        .unwrap()
+        .root_view(cx_b)
+        .unwrap();
+    let project_b = workspace_b.update(cx_b, |workspace, _| workspace.project().clone());
+
+    assert_eq!(
+        project_b.read_with(cx_b, |project, _| project.remote_id()),
+        Some(project_id),
+    );
+    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()))
+}

crates/collab/src/tests/editor_tests.rs πŸ”—

@@ -1,1889 +1,1884 @@
-//todo(partially ported)
-// use std::{
-//     path::Path,
-//     sync::{
-//         atomic::{self, AtomicBool, AtomicUsize},
-//         Arc,
-//     },
-// };
-
-// use call::ActiveCall;
-// use editor::{
-//     test::editor_test_context::{AssertionContextManager, EditorTestContext},
-//     Anchor, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename,
-//     ToggleCodeActions, Undo,
-// };
-// use gpui::{BackgroundExecutor, TestAppContext, VisualContext, VisualTestContext};
-// use indoc::indoc;
-// use language::{
-//     language_settings::{AllLanguageSettings, InlayHintSettings},
-//     tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig,
-// };
-// use rpc::RECEIVE_TIMEOUT;
-// use serde_json::json;
-// use settings::SettingsStore;
-// use text::Point;
-// use workspace::Workspace;
-
-// use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
-
-// #[gpui::test(iterations = 10)]
-// async fn test_host_disconnect(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-//     cx_c: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     let client_c = server.create_client(cx_c, "user_c").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
-//         .await;
-
-//     cx_b.update(editor::init);
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             serde_json::json!({
-//                 "a.txt": "a-contents",
-//                 "b.txt": "b-contents",
-//             }),
-//         )
-//         .await;
-
-//     let active_call_a = cx_a.read(ActiveCall::global);
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-
-//     let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees().next().unwrap());
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-//     executor.run_until_parked();
-
-//     assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
-
-//     let workspace_b =
-//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
-//     let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
-
-//     let editor_b = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             workspace.open_path((worktree_id, "b.txt"), None, true, cx)
-//         })
-//         .unwrap()
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     //TODO: focus
-//     assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
-//     editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
-//     //todo(is_edited)
-//     // assert!(workspace_b.is_edited(cx_b));
-
-//     // Drop client A's connection. Collaborators should disappear and the project should not be shown as shared.
-//     server.forbid_connections();
-//     server.disconnect_client(client_a.peer_id().unwrap());
-//     executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
-
-//     project_a.read_with(cx_a, |project, _| project.collaborators().is_empty());
-
-//     project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
-
-//     project_b.read_with(cx_b, |project, _| project.is_read_only());
-
-//     assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
-
-//     // Ensure client B's edited state is reset and that the whole window is blurred.
-
-//     workspace_b.update(cx_b, |_, cx| {
-//         assert_eq!(cx.focused_view_id(), None);
-//     });
-//     // assert!(!workspace_b.is_edited(cx_b));
-
-//     // Ensure client B is not prompted to save edits when closing window after disconnecting.
-//     let can_close = workspace_b
-//         .update(cx_b, |workspace, cx| workspace.prepare_to_close(true, cx))
-//         .await
-//         .unwrap();
-//     assert!(can_close);
-
-//     // Allow client A to reconnect to the server.
-//     server.allow_connections();
-//     executor.advance_clock(RECEIVE_TIMEOUT);
-
-//     // Client B calls client A again after they reconnected.
-//     let active_call_b = cx_b.read(ActiveCall::global);
-//     active_call_b
-//         .update(cx_b, |call, cx| {
-//             call.invite(client_a.user_id().unwrap(), None, cx)
-//         })
-//         .await
-//         .unwrap();
-//     executor.run_until_parked();
-//     active_call_a
-//         .update(cx_a, |call, cx| call.accept_incoming(cx))
-//         .await
-//         .unwrap();
-
-//     active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     // Drop client A's connection again. We should still unshare it successfully.
-//     server.forbid_connections();
-//     server.disconnect_client(client_a.peer_id().unwrap());
-//     executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
-
-//     project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
-// }
-
-// #[gpui::test]
-// async fn test_newline_above_or_below_does_not_move_guest_cursor(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     client_a
-//         .fs()
-//         .insert_tree("/dir", json!({ "a.txt": "Some text\n" }))
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     // Open a buffer as client A
-//     let buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
-//         .await
-//         .unwrap();
-//     let window_a = cx_a.add_empty_window();
-//     let editor_a =
-//         window_a.build_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
-//     let mut editor_cx_a = EditorTestContext {
-//         cx: cx_a,
-//         window: window_a.into(),
-//         editor: editor_a,
-//         assertion_cx: AssertionContextManager::new(),
-//     };
-
-//     // Open a buffer as client B
-//     let buffer_b = project_b
-//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
-//         .await
-//         .unwrap();
-//     let window_b = cx_b.add_empty_window();
-//     let editor_b =
-//         window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
-//     let mut editor_cx_b = EditorTestContext {
-//         cx: cx_b,
-//         window: window_b.into(),
-//         editor: editor_b,
-//         assertion_cx: AssertionContextManager::new(),
-//     };
-
-//     // Test newline above
-//     editor_cx_a.set_selections_state(indoc! {"
-//         Some textˇ
-//     "});
-//     editor_cx_b.set_selections_state(indoc! {"
-//         Some textˇ
-//     "});
-//     editor_cx_a.update_editor(|editor, cx| editor.newline_above(&editor::NewlineAbove, cx));
-//     executor.run_until_parked();
-//     editor_cx_a.assert_editor_state(indoc! {"
-//         Λ‡
-//         Some text
-//     "});
-//     editor_cx_b.assert_editor_state(indoc! {"
-
-//         Some textˇ
-//     "});
-
-//     // Test newline below
-//     editor_cx_a.set_selections_state(indoc! {"
-
-//         Some textˇ
-//     "});
-//     editor_cx_b.set_selections_state(indoc! {"
-
-//         Some textˇ
-//     "});
-//     editor_cx_a.update_editor(|editor, cx| editor.newline_below(&editor::NewlineBelow, cx));
-//     executor.run_until_parked();
-//     editor_cx_a.assert_editor_state(indoc! {"
-
-//         Some text
-//         Λ‡
-//     "});
-//     editor_cx_b.assert_editor_state(indoc! {"
-
-//         Some textˇ
-
-//     "});
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_collaborating_with_completion(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 completion_provider: Some(lsp::CompletionOptions {
-//                     trigger_characters: Some(vec![".".to_string()]),
-//                     resolve_provider: Some(true),
-//                     ..Default::default()
-//                 }),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "fn main() { a }",
-//                 "other.rs": "",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     // Open a file in an editor as the guest.
-//     let buffer_b = project_b
-//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-//     let window_b = cx_b.add_empty_window();
-//     let editor_b = window_b.build_view(cx_b, |cx| {
-//         Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
-//     });
-
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     cx_a.foreground().run_until_parked();
-
-//     buffer_b.read_with(cx_b, |buffer, _| {
-//         assert!(!buffer.completion_triggers().is_empty())
-//     });
-
-//     // Type a completion trigger character as the guest.
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
-//         editor.handle_input(".", cx);
-//         cx.focus(&editor_b);
-//     });
-
-//     // Receive a completion request as the host's language server.
-//     // Return some completions from the host's language server.
-//     cx_a.foreground().start_waiting();
-//     fake_language_server
-//         .handle_request::<lsp::request::Completion, _, _>(|params, _| async move {
-//             assert_eq!(
-//                 params.text_document_position.text_document.uri,
-//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//             );
-//             assert_eq!(
-//                 params.text_document_position.position,
-//                 lsp::Position::new(0, 14),
-//             );
-
-//             Ok(Some(lsp::CompletionResponse::Array(vec![
-//                 lsp::CompletionItem {
-//                     label: "first_method(…)".into(),
-//                     detail: Some("fn(&mut self, B) -> C".into()),
-//                     text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-//                         new_text: "first_method($1)".to_string(),
-//                         range: lsp::Range::new(
-//                             lsp::Position::new(0, 14),
-//                             lsp::Position::new(0, 14),
-//                         ),
-//                     })),
-//                     insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
-//                     ..Default::default()
-//                 },
-//                 lsp::CompletionItem {
-//                     label: "second_method(…)".into(),
-//                     detail: Some("fn(&mut self, C) -> D<E>".into()),
-//                     text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-//                         new_text: "second_method()".to_string(),
-//                         range: lsp::Range::new(
-//                             lsp::Position::new(0, 14),
-//                             lsp::Position::new(0, 14),
-//                         ),
-//                     })),
-//                     insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
-//                     ..Default::default()
-//                 },
-//             ])))
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-//     cx_a.foreground().finish_waiting();
-
-//     // Open the buffer on the host.
-//     let buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-//     cx_a.foreground().run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a. }")
-//     });
-
-//     // Confirm a completion on the guest.
-
-//     editor_b.read_with(cx_b, |editor, _| assert!(editor.context_menu_visible()));
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
-//         assert_eq!(editor.text(cx), "fn main() { a.first_method() }");
-//     });
-
-//     // Return a resolved completion from the host's language server.
-//     // The resolved completion has an additional text edit.
-//     fake_language_server.handle_request::<lsp::request::ResolveCompletionItem, _, _>(
-//         |params, _| async move {
-//             assert_eq!(params.label, "first_method(…)");
-//             Ok(lsp::CompletionItem {
-//                 label: "first_method(…)".into(),
-//                 detail: Some("fn(&mut self, B) -> C".into()),
-//                 text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-//                     new_text: "first_method($1)".to_string(),
-//                     range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
-//                 })),
-//                 additional_text_edits: Some(vec![lsp::TextEdit {
-//                     new_text: "use d::SomeTrait;\n".to_string(),
-//                     range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)),
-//                 }]),
-//                 insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
-//                 ..Default::default()
-//             })
-//         },
-//     );
-
-//     // The additional edit is applied.
-//     cx_a.executor().run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(
-//             buffer.text(),
-//             "use d::SomeTrait;\nfn main() { a.first_method() }"
-//         );
-//     });
-
-//     buffer_b.read_with(cx_b, |buffer, _| {
-//         assert_eq!(
-//             buffer.text(),
-//             "use d::SomeTrait;\nfn main() { a.first_method() }"
-//         );
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_collaborating_with_code_actions(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     //
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     cx_b.update(editor::init);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "mod other;\nfn main() { let foo = other::foo(); }",
-//                 "other.rs": "pub fn foo() -> usize { 4 }",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     // Join the project as client B.
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-//     let window_b =
-//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
-//     let workspace_b = window_b.root(cx_b);
-//     let editor_b = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     let mut fake_language_server = fake_language_servers.next().await.unwrap();
-//     let mut requests = fake_language_server
-//         .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
-//             assert_eq!(
-//                 params.text_document.uri,
-//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//             );
-//             assert_eq!(params.range.start, lsp::Position::new(0, 0));
-//             assert_eq!(params.range.end, lsp::Position::new(0, 0));
-//             Ok(None)
-//         });
-//     executor.advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
-//     requests.next().await;
-
-//     // Move cursor to a location that contains code actions.
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.change_selections(None, cx, |s| {
-//             s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
-//         });
-//         cx.focus(&editor_b);
-//     });
-
-//     let mut requests = fake_language_server
-//         .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
-//             assert_eq!(
-//                 params.text_document.uri,
-//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//             );
-//             assert_eq!(params.range.start, lsp::Position::new(1, 31));
-//             assert_eq!(params.range.end, lsp::Position::new(1, 31));
-
-//             Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
-//                 lsp::CodeAction {
-//                     title: "Inline into all callers".to_string(),
-//                     edit: Some(lsp::WorkspaceEdit {
-//                         changes: Some(
-//                             [
-//                                 (
-//                                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//                                     vec![lsp::TextEdit::new(
-//                                         lsp::Range::new(
-//                                             lsp::Position::new(1, 22),
-//                                             lsp::Position::new(1, 34),
-//                                         ),
-//                                         "4".to_string(),
-//                                     )],
-//                                 ),
-//                                 (
-//                                     lsp::Url::from_file_path("/a/other.rs").unwrap(),
-//                                     vec![lsp::TextEdit::new(
-//                                         lsp::Range::new(
-//                                             lsp::Position::new(0, 0),
-//                                             lsp::Position::new(0, 27),
-//                                         ),
-//                                         "".to_string(),
-//                                     )],
-//                                 ),
-//                             ]
-//                             .into_iter()
-//                             .collect(),
-//                         ),
-//                         ..Default::default()
-//                     }),
-//                     data: Some(json!({
-//                         "codeActionParams": {
-//                             "range": {
-//                                 "start": {"line": 1, "column": 31},
-//                                 "end": {"line": 1, "column": 31},
-//                             }
-//                         }
-//                     })),
-//                     ..Default::default()
-//                 },
-//             )]))
-//         });
-//     executor.advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
-//     requests.next().await;
-
-//     // Toggle code actions and wait for them to display.
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.toggle_code_actions(
-//             &ToggleCodeActions {
-//                 deployed_from_indicator: false,
-//             },
-//             cx,
-//         );
-//     });
-//     cx_a.foreground().run_until_parked();
-
-//     editor_b.read_with(cx_b, |editor, _| assert!(editor.context_menu_visible()));
-
-//     fake_language_server.remove_request_handler::<lsp::request::CodeActionRequest>();
-
-//     // Confirming the code action will trigger a resolve request.
-//     let confirm_action = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             Editor::confirm_code_action(workspace, &ConfirmCodeAction { item_ix: Some(0) }, cx)
-//         })
-//         .unwrap();
-//     fake_language_server.handle_request::<lsp::request::CodeActionResolveRequest, _, _>(
-//         |_, _| async move {
-//             Ok(lsp::CodeAction {
-//                 title: "Inline into all callers".to_string(),
-//                 edit: Some(lsp::WorkspaceEdit {
-//                     changes: Some(
-//                         [
-//                             (
-//                                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//                                 vec![lsp::TextEdit::new(
-//                                     lsp::Range::new(
-//                                         lsp::Position::new(1, 22),
-//                                         lsp::Position::new(1, 34),
-//                                     ),
-//                                     "4".to_string(),
-//                                 )],
-//                             ),
-//                             (
-//                                 lsp::Url::from_file_path("/a/other.rs").unwrap(),
-//                                 vec![lsp::TextEdit::new(
-//                                     lsp::Range::new(
-//                                         lsp::Position::new(0, 0),
-//                                         lsp::Position::new(0, 27),
-//                                     ),
-//                                     "".to_string(),
-//                                 )],
-//                             ),
-//                         ]
-//                         .into_iter()
-//                         .collect(),
-//                     ),
-//                     ..Default::default()
-//                 }),
-//                 ..Default::default()
-//             })
-//         },
-//     );
-
-//     // After the action is confirmed, an editor containing both modified files is opened.
-//     confirm_action.await.unwrap();
-
-//     let code_action_editor = workspace_b.read_with(cx_b, |workspace, cx| {
-//         workspace
-//             .active_item(cx)
-//             .unwrap()
-//             .downcast::<Editor>()
-//             .unwrap()
-//     });
-//     code_action_editor.update(cx_b, |editor, cx| {
-//         assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(
-//             editor.text(cx),
-//             "mod other;\nfn main() { let foo = other::foo(); }\npub fn foo() -> usize { 4 }"
-//         );
-//         editor.redo(&Redo, cx);
-//         assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_collaborating_with_renames(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     cx_b.update(editor::init);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
-//                     prepare_provider: Some(true),
-//                     work_done_progress_options: Default::default(),
-//                 })),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/dir",
-//             json!({
-//                 "one.rs": "const ONE: usize = 1;",
-//                 "two.rs": "const TWO: usize = one::ONE + one::ONE;"
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     let window_b =
-//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
-//     let workspace_b = window_b.root(cx_b);
-//     let editor_b = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             workspace.open_path((worktree_id, "one.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-
-//     // Move cursor to a location that can be renamed.
-//     let prepare_rename = editor_b.update(cx_b, |editor, cx| {
-//         editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
-//         editor.rename(&Rename, cx).unwrap()
-//     });
-
-//     fake_language_server
-//         .handle_request::<lsp::request::PrepareRenameRequest, _, _>(|params, _| async move {
-//             assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs");
-//             assert_eq!(params.position, lsp::Position::new(0, 7));
-//             Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
-//                 lsp::Position::new(0, 6),
-//                 lsp::Position::new(0, 9),
-//             ))))
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-//     prepare_rename.await.unwrap();
-//     editor_b.update(cx_b, |editor, cx| {
-//         use editor::ToOffset;
-//         let rename = editor.pending_rename().unwrap();
-//         let buffer = editor.buffer().read(cx).snapshot(cx);
-//         assert_eq!(
-//             rename.range.start.to_offset(&buffer)..rename.range.end.to_offset(&buffer),
-//             6..9
-//         );
-//         rename.editor.update(cx, |rename_editor, cx| {
-//             rename_editor.buffer().update(cx, |rename_buffer, cx| {
-//                 rename_buffer.edit([(0..3, "THREE")], None, cx);
-//             });
-//         });
-//     });
-
-//     let confirm_rename = workspace_b.update(cx_b, |workspace, cx| {
-//         Editor::confirm_rename(workspace, &ConfirmRename, cx).unwrap()
-//     });
-//     fake_language_server
-//         .handle_request::<lsp::request::Rename, _, _>(|params, _| async move {
-//             assert_eq!(
-//                 params.text_document_position.text_document.uri.as_str(),
-//                 "file:///dir/one.rs"
-//             );
-//             assert_eq!(
-//                 params.text_document_position.position,
-//                 lsp::Position::new(0, 6)
-//             );
-//             assert_eq!(params.new_name, "THREE");
-//             Ok(Some(lsp::WorkspaceEdit {
-//                 changes: Some(
-//                     [
-//                         (
-//                             lsp::Url::from_file_path("/dir/one.rs").unwrap(),
-//                             vec![lsp::TextEdit::new(
-//                                 lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)),
-//                                 "THREE".to_string(),
-//                             )],
-//                         ),
-//                         (
-//                             lsp::Url::from_file_path("/dir/two.rs").unwrap(),
-//                             vec![
-//                                 lsp::TextEdit::new(
-//                                     lsp::Range::new(
-//                                         lsp::Position::new(0, 24),
-//                                         lsp::Position::new(0, 27),
-//                                     ),
-//                                     "THREE".to_string(),
-//                                 ),
-//                                 lsp::TextEdit::new(
-//                                     lsp::Range::new(
-//                                         lsp::Position::new(0, 35),
-//                                         lsp::Position::new(0, 38),
-//                                     ),
-//                                     "THREE".to_string(),
-//                                 ),
-//                             ],
-//                         ),
-//                     ]
-//                     .into_iter()
-//                     .collect(),
-//                 ),
-//                 ..Default::default()
-//             }))
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-//     confirm_rename.await.unwrap();
-
-//     let rename_editor = workspace_b.read_with(cx_b, |workspace, cx| {
-//         workspace
-//             .active_item(cx)
-//             .unwrap()
-//             .downcast::<Editor>()
-//             .unwrap()
-//     });
-//     rename_editor.update(cx_b, |editor, cx| {
-//         assert_eq!(
-//             editor.text(cx),
-//             "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
-//         );
-//         editor.undo(&Undo, cx);
-//         assert_eq!(
-//             editor.text(cx),
-//             "const ONE: usize = 1;\nconst TWO: usize = one::ONE + one::ONE;"
-//         );
-//         editor.redo(&Redo, cx);
-//         assert_eq!(
-//             editor.text(cx),
-//             "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
-//         );
-//     });
-
-//     // Ensure temporary rename edits cannot be undone/redone.
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "const ONE: usize = 1;");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "const ONE: usize = 1;");
-//         editor.redo(&Redo, cx);
-//         assert_eq!(editor.text(cx), "const THREE: usize = 1;");
-//     })
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_language_server_statuses(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     cx_b.update(editor::init);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             name: "the-language-server",
-//             ..Default::default()
-//         }))
-//         .await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/dir",
-//             json!({
-//                 "main.rs": "const ONE: usize = 1;",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
-
-//     let _buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     fake_language_server.start_progress("the-token").await;
-//     fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
-//         token: lsp::NumberOrString::String("the-token".to_string()),
-//         value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
-//             lsp::WorkDoneProgressReport {
-//                 message: Some("the-message".to_string()),
-//                 ..Default::default()
-//             },
-//         )),
-//     });
-//     executor.run_until_parked();
-
-//     project_a.read_with(cx_a, |project, _| {
-//         let status = project.language_server_statuses().next().unwrap();
-//         assert_eq!(status.name, "the-language-server");
-//         assert_eq!(status.pending_work.len(), 1);
-//         assert_eq!(
-//             status.pending_work["the-token"].message.as_ref().unwrap(),
-//             "the-message"
-//         );
-//     });
-
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-//     executor.run_until_parked();
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     project_b.read_with(cx_b, |project, _| {
-//         let status = project.language_server_statuses().next().unwrap();
-//         assert_eq!(status.name, "the-language-server");
-//     });
-
-//     fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
-//         token: lsp::NumberOrString::String("the-token".to_string()),
-//         value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
-//             lsp::WorkDoneProgressReport {
-//                 message: Some("the-message-2".to_string()),
-//                 ..Default::default()
-//             },
-//         )),
-//     });
-//     executor.run_until_parked();
-
-//     project_a.read_with(cx_a, |project, _| {
-//         let status = project.language_server_statuses().next().unwrap();
-//         assert_eq!(status.name, "the-language-server");
-//         assert_eq!(status.pending_work.len(), 1);
-//         assert_eq!(
-//             status.pending_work["the-token"].message.as_ref().unwrap(),
-//             "the-message-2"
-//         );
-//     });
-
-//     project_b.read_with(cx_b, |project, _| {
-//         let status = project.language_server_statuses().next().unwrap();
-//         assert_eq!(status.name, "the-language-server");
-//         assert_eq!(status.pending_work.len(), 1);
-//         assert_eq!(
-//             status.pending_work["the-token"].message.as_ref().unwrap(),
-//             "the-message-2"
-//         );
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_share_project(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-//     cx_c: &mut TestAppContext,
-// ) {
-//     let window_b = cx_b.add_empty_window();
-//     let mut server = TestServer::start(executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     let client_c = server.create_client(cx_c, "user_c").await;
-//     server
-//         .make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-//     let active_call_b = cx_b.read(ActiveCall::global);
-//     let active_call_c = cx_c.read(ActiveCall::global);
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 ".gitignore": "ignored-dir",
-//                 "a.txt": "a-contents",
-//                 "b.txt": "b-contents",
-//                 "ignored-dir": {
-//                     "c.txt": "",
-//                     "d.txt": "",
-//                 }
-//             }),
-//         )
-//         .await;
-
-//     // Invite client B to collaborate on a project
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     active_call_a
-//         .update(cx_a, |call, cx| {
-//             call.invite(client_b.user_id().unwrap(), Some(project_a.clone()), cx)
-//         })
-//         .await
-//         .unwrap();
-
-//     // Join that project as client B
-
-//     let incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming());
-//     executor.run_until_parked();
-//     let call = incoming_call_b.borrow().clone().unwrap();
-//     assert_eq!(call.calling_user.github_login, "user_a");
-//     let initial_project = call.initial_project.unwrap();
-//     active_call_b
-//         .update(cx_b, |call, cx| call.accept_incoming(cx))
-//         .await
-//         .unwrap();
-//     let client_b_peer_id = client_b.peer_id().unwrap();
-//     let project_b = client_b
-//         .build_remote_project(initial_project.id, cx_b)
-//         .await;
-
-//     let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
-
-//     executor.run_until_parked();
-
-//     project_a.read_with(cx_a, |project, _| {
-//         let client_b_collaborator = project.collaborators().get(&client_b_peer_id).unwrap();
-//         assert_eq!(client_b_collaborator.replica_id, replica_id_b);
-//     });
-
-//     project_b.read_with(cx_b, |project, cx| {
-//         let worktree = project.worktrees().next().unwrap().read(cx);
-//         assert_eq!(
-//             worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
-//             [
-//                 Path::new(".gitignore"),
-//                 Path::new("a.txt"),
-//                 Path::new("b.txt"),
-//                 Path::new("ignored-dir"),
-//             ]
-//         );
-//     });
-
-//     project_b
-//         .update(cx_b, |project, cx| {
-//             let worktree = project.worktrees().next().unwrap();
-//             let entry = worktree.read(cx).entry_for_path("ignored-dir").unwrap();
-//             project.expand_entry(worktree_id, entry.id, cx).unwrap()
-//         })
-//         .await
-//         .unwrap();
-
-//     project_b.read_with(cx_b, |project, cx| {
-//         let worktree = project.worktrees().next().unwrap().read(cx);
-//         assert_eq!(
-//             worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
-//             [
-//                 Path::new(".gitignore"),
-//                 Path::new("a.txt"),
-//                 Path::new("b.txt"),
-//                 Path::new("ignored-dir"),
-//                 Path::new("ignored-dir/c.txt"),
-//                 Path::new("ignored-dir/d.txt"),
-//             ]
-//         );
-//     });
-
-//     // Open the same file as client B and client A.
-//     let buffer_b = project_b
-//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
-//         .await
-//         .unwrap();
-
-//     buffer_b.read_with(cx_b, |buf, _| assert_eq!(buf.text(), "b-contents"));
-
-//     project_a.read_with(cx_a, |project, cx| {
-//         assert!(project.has_open_buffer((worktree_id, "b.txt"), cx))
-//     });
-//     let buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
-//         .await
-//         .unwrap();
-
-//     let editor_b = window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
-
-//     // Client A sees client B's selection
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         buffer
-//             .snapshot()
-//             .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
-//             .count()
-//             == 1
-//     });
-
-//     // Edit the buffer as client B and see that edit as client A.
-//     editor_b.update(cx_b, |editor, cx| editor.handle_input("ok, ", cx));
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(buffer.text(), "ok, b-contents")
-//     });
-
-//     // Client B can invite client C on a project shared by client A.
-//     active_call_b
-//         .update(cx_b, |call, cx| {
-//             call.invite(client_c.user_id().unwrap(), Some(project_b.clone()), cx)
-//         })
-//         .await
-//         .unwrap();
-
-//     let incoming_call_c = active_call_c.read_with(cx_c, |call, _| call.incoming());
-//     executor.run_until_parked();
-//     let call = incoming_call_c.borrow().clone().unwrap();
-//     assert_eq!(call.calling_user.github_login, "user_b");
-//     let initial_project = call.initial_project.unwrap();
-//     active_call_c
-//         .update(cx_c, |call, cx| call.accept_incoming(cx))
-//         .await
-//         .unwrap();
-//     let _project_c = client_c
-//         .build_remote_project(initial_project.id, cx_c)
-//         .await;
-
-//     // Client B closes the editor, and client A sees client B's selections removed.
-//     cx_b.update(move |_| drop(editor_b));
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         buffer
-//             .snapshot()
-//             .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
-//             .count()
-//             == 0
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_on_input_format_from_host_to_guest(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
-//                     first_trigger_character: ":".to_string(),
-//                     more_trigger_character: Some(vec![">".to_string()]),
-//                 }),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "fn main() { a }",
-//                 "other.rs": "// Test file",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     // Open a file in an editor as the host.
-//     let buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-//     let window_a = cx_a.add_empty_window();
-//     let editor_a = window_a
-//         .update(cx_a, |_, cx| {
-//             cx.build_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx))
-//         })
-//         .unwrap();
-
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     executor.run_until_parked();
-
-//     // Receive an OnTypeFormatting request as the host's language server.
-//     // Return some formattings from the host's language server.
-//     fake_language_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(
-//         |params, _| async move {
-//             assert_eq!(
-//                 params.text_document_position.text_document.uri,
-//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//             );
-//             assert_eq!(
-//                 params.text_document_position.position,
-//                 lsp::Position::new(0, 14),
-//             );
-
-//             Ok(Some(vec![lsp::TextEdit {
-//                 new_text: "~<".to_string(),
-//                 range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
-//             }]))
-//         },
-//     );
-
-//     // Open the buffer on the guest and see that the formattings worked
-//     let buffer_b = project_b
-//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-
-//     // Type a on type formatting trigger character as the guest.
-//     editor_a.update(cx_a, |editor, cx| {
-//         cx.focus(&editor_a);
-//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
-//         editor.handle_input(">", cx);
-//     });
-
-//     executor.run_until_parked();
-
-//     buffer_b.read_with(cx_b, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a>~< }")
-//     });
-
-//     // Undo should remove LSP edits first
-//     editor_a.update(cx_a, |editor, cx| {
-//         assert_eq!(editor.text(cx), "fn main() { a>~< }");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "fn main() { a> }");
-//     });
-//     executor.run_until_parked();
-
-//     buffer_b.read_with(cx_b, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a> }")
-//     });
-
-//     editor_a.update(cx_a, |editor, cx| {
-//         assert_eq!(editor.text(cx), "fn main() { a> }");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "fn main() { a }");
-//     });
-//     executor.run_until_parked();
-
-//     buffer_b.read_with(cx_b, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a }")
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_on_input_format_from_guest_to_host(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-
-//     // Set up a fake language server.
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
-//                     first_trigger_character: ":".to_string(),
-//                     more_trigger_character: Some(vec![">".to_string()]),
-//                 }),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     client_a.language_registry().add(Arc::new(language));
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "fn main() { a }",
-//                 "other.rs": "// Test file",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-
-//     // Open a file in an editor as the guest.
-//     let buffer_b = project_b
-//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-//     let window_b = cx_b.add_empty_window();
-//     let editor_b = window_b.build_view(cx_b, |cx| {
-//         Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
-//     });
-
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     executor.run_until_parked();
-//     // Type a on type formatting trigger character as the guest.
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
-//         editor.handle_input(":", cx);
-//         cx.focus(&editor_b);
-//     });
-
-//     // Receive an OnTypeFormatting request as the host's language server.
-//     // Return some formattings from the host's language server.
-//     cx_a.foreground().start_waiting();
-//     fake_language_server
-//         .handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
-//             assert_eq!(
-//                 params.text_document_position.text_document.uri,
-//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//             );
-//             assert_eq!(
-//                 params.text_document_position.position,
-//                 lsp::Position::new(0, 14),
-//             );
-
-//             Ok(Some(vec![lsp::TextEdit {
-//                 new_text: "~:".to_string(),
-//                 range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
-//             }]))
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-//     cx_a.foreground().finish_waiting();
-
-//     // Open the buffer on the host and see that the formattings worked
-//     let buffer_a = project_a
-//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
-//         .await
-//         .unwrap();
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a:~: }")
-//     });
-
-//     // Undo should remove LSP edits first
-//     editor_b.update(cx_b, |editor, cx| {
-//         assert_eq!(editor.text(cx), "fn main() { a:~: }");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "fn main() { a: }");
-//     });
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a: }")
-//     });
-
-//     editor_b.update(cx_b, |editor, cx| {
-//         assert_eq!(editor.text(cx), "fn main() { a: }");
-//         editor.undo(&Undo, cx);
-//         assert_eq!(editor.text(cx), "fn main() { a }");
-//     });
-//     executor.run_until_parked();
-
-//     buffer_a.read_with(cx_a, |buffer, _| {
-//         assert_eq!(buffer.text(), "fn main() { a }")
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_mutual_editor_inlay_hint_cache_update(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-//     let active_call_b = cx_b.read(ActiveCall::global);
-
-//     cx_a.update(editor::init);
-//     cx_b.update(editor::init);
-
-//     cx_a.update(|cx| {
-//         cx.update_global(|store: &mut SettingsStore, cx| {
-//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
-//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
-//                     enabled: true,
-//                     show_type_hints: true,
-//                     show_parameter_hints: false,
-//                     show_other_hints: true,
-//                 })
-//             });
-//         });
-//     });
-//     cx_b.update(|cx| {
-//         cx.update_global(|store: &mut SettingsStore, cx| {
-//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
-//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
-//                     enabled: true,
-//                     show_type_hints: true,
-//                     show_parameter_hints: false,
-//                     show_other_hints: true,
-//                 })
-//             });
-//         });
-//     });
-
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 inlay_hint_provider: Some(lsp::OneOf::Left(true)),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     let language = Arc::new(language);
-//     client_a.language_registry().add(Arc::clone(&language));
-//     client_b.language_registry().add(language);
-
-//     // Client A opens a project.
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
-//                 "other.rs": "// Test file",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     active_call_a
-//         .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
-//         .await
-//         .unwrap();
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     // Client B joins the project
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-//     active_call_b
-//         .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
-//         .await
-//         .unwrap();
-
-//     let workspace_a = client_a.build_workspace(&project_a, cx_a).root_view(cx_a);
-//     cx_a.foreground().start_waiting();
-
-//     // The host opens a rust file.
-//     let _buffer_a = project_a
-//         .update(cx_a, |project, cx| {
-//             project.open_local_buffer("/a/main.rs", cx)
-//         })
-//         .await
-//         .unwrap();
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     let editor_a = workspace_a
-//         .update(cx_a, |workspace, cx| {
-//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     // Set up the language server to return an additional inlay hint on each request.
-//     let edits_made = Arc::new(AtomicUsize::new(0));
-//     let closure_edits_made = Arc::clone(&edits_made);
-//     fake_language_server
-//         .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
-//             let task_edits_made = Arc::clone(&closure_edits_made);
-//             async move {
-//                 assert_eq!(
-//                     params.text_document.uri,
-//                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//                 );
-//                 let edits_made = task_edits_made.load(atomic::Ordering::Acquire);
-//                 Ok(Some(vec![lsp::InlayHint {
-//                     position: lsp::Position::new(0, edits_made as u32),
-//                     label: lsp::InlayHintLabel::String(edits_made.to_string()),
-//                     kind: None,
-//                     text_edits: None,
-//                     tooltip: None,
-//                     padding_left: None,
-//                     padding_right: None,
-//                     data: None,
-//                 }]))
-//             }
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-
-//     executor.run_until_parked();
-
-//     let initial_edit = edits_made.load(atomic::Ordering::Acquire);
-//     editor_a.update(cx_a, |editor, _| {
-//         assert_eq!(
-//             vec![initial_edit.to_string()],
-//             extract_hint_labels(editor),
-//             "Host should get its first hints when opens an editor"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             1,
-//             "Host editor update the cache version after every cache/view change",
-//         );
-//     });
-//     let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
-//     let editor_b = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     executor.run_until_parked();
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec![initial_edit.to_string()],
-//             extract_hint_labels(editor),
-//             "Client should get its first hints when opens an editor"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             1,
-//             "Guest editor update the cache version after every cache/view change"
-//         );
-//     });
-
-//     let after_client_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
-//     editor_b.update(cx_b, |editor, cx| {
-//         editor.change_selections(None, cx, |s| s.select_ranges([13..13].clone()));
-//         editor.handle_input(":", cx);
-//         cx.focus(&editor_b);
-//     });
-
-//     executor.run_until_parked();
-//     editor_a.update(cx_a, |editor, _| {
-//         assert_eq!(
-//             vec![after_client_edit.to_string()],
-//             extract_hint_labels(editor),
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(inlay_cache.version(), 2);
-//     });
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec![after_client_edit.to_string()],
-//             extract_hint_labels(editor),
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(inlay_cache.version(), 2);
-//     });
-
-//     let after_host_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
-//     editor_a.update(cx_a, |editor, cx| {
-//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
-//         editor.handle_input("a change to increment both buffers' versions", cx);
-//         cx.focus(&editor_a);
-//     });
-
-//     executor.run_until_parked();
-//     editor_a.update(cx_a, |editor, _| {
-//         assert_eq!(
-//             vec![after_host_edit.to_string()],
-//             extract_hint_labels(editor),
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(inlay_cache.version(), 3);
-//     });
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec![after_host_edit.to_string()],
-//             extract_hint_labels(editor),
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(inlay_cache.version(), 3);
-//     });
-
-//     let after_special_edit_for_refresh = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
-//     fake_language_server
-//         .request::<lsp::request::InlayHintRefreshRequest>(())
-//         .await
-//         .expect("inlay refresh request failed");
-
-//     executor.run_until_parked();
-//     editor_a.update(cx_a, |editor, _| {
-//         assert_eq!(
-//             vec![after_special_edit_for_refresh.to_string()],
-//             extract_hint_labels(editor),
-//             "Host should react to /refresh LSP request"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             4,
-//             "Host should accepted all edits and bump its cache version every time"
-//         );
-//     });
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec![after_special_edit_for_refresh.to_string()],
-//             extract_hint_labels(editor),
-//             "Guest should get a /refresh LSP request propagated by host"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             4,
-//             "Guest should accepted all edits and bump its cache version every time"
-//         );
-//     });
-// }
-
-// #[gpui::test(iterations = 10)]
-// async fn test_inlay_hint_refresh_is_forwarded(
-//     executor: BackgroundExecutor,
-//     cx_a: &mut TestAppContext,
-//     cx_b: &mut TestAppContext,
-// ) {
-//     let mut server = TestServer::start(&executor).await;
-//     let client_a = server.create_client(cx_a, "user_a").await;
-//     let client_b = server.create_client(cx_b, "user_b").await;
-//     server
-//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
-//         .await;
-//     let active_call_a = cx_a.read(ActiveCall::global);
-//     let active_call_b = cx_b.read(ActiveCall::global);
-
-//     cx_a.update(editor::init);
-//     cx_b.update(editor::init);
-
-//     cx_a.update(|cx| {
-//         cx.update_global(|store: &mut SettingsStore, cx| {
-//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
-//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
-//                     enabled: false,
-//                     show_type_hints: false,
-//                     show_parameter_hints: false,
-//                     show_other_hints: false,
-//                 })
-//             });
-//         });
-//     });
-//     cx_b.update(|cx| {
-//         cx.update_global(|store: &mut SettingsStore, cx| {
-//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
-//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
-//                     enabled: true,
-//                     show_type_hints: true,
-//                     show_parameter_hints: true,
-//                     show_other_hints: true,
-//                 })
-//             });
-//         });
-//     });
-
-//     let mut language = Language::new(
-//         LanguageConfig {
-//             name: "Rust".into(),
-//             path_suffixes: vec!["rs".to_string()],
-//             ..Default::default()
-//         },
-//         Some(tree_sitter_rust::language()),
-//     );
-//     let mut fake_language_servers = language
-//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-//             capabilities: lsp::ServerCapabilities {
-//                 inlay_hint_provider: Some(lsp::OneOf::Left(true)),
-//                 ..Default::default()
-//             },
-//             ..Default::default()
-//         }))
-//         .await;
-//     let language = Arc::new(language);
-//     client_a.language_registry().add(Arc::clone(&language));
-//     client_b.language_registry().add(language);
-
-//     client_a
-//         .fs()
-//         .insert_tree(
-//             "/a",
-//             json!({
-//                 "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
-//                 "other.rs": "// Test file",
-//             }),
-//         )
-//         .await;
-//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
-//     active_call_a
-//         .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
-//         .await
-//         .unwrap();
-//     let project_id = active_call_a
-//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
-//         .await
-//         .unwrap();
-
-//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
-//     active_call_b
-//         .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
-//         .await
-//         .unwrap();
-
-//     let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a);
-//     let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
-//     cx_a.foreground().start_waiting();
-//     cx_b.foreground().start_waiting();
-
-//     let editor_a = workspace_a
-//         .update(cx_a, |workspace, cx| {
-//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     let editor_b = workspace_b
-//         .update(cx_b, |workspace, cx| {
-//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
-//         })
-//         .await
-//         .unwrap()
-//         .downcast::<Editor>()
-//         .unwrap();
-
-//     let other_hints = Arc::new(AtomicBool::new(false));
-//     let fake_language_server = fake_language_servers.next().await.unwrap();
-//     let closure_other_hints = Arc::clone(&other_hints);
-//     fake_language_server
-//         .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
-//             let task_other_hints = Arc::clone(&closure_other_hints);
-//             async move {
-//                 assert_eq!(
-//                     params.text_document.uri,
-//                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
-//                 );
-//                 let other_hints = task_other_hints.load(atomic::Ordering::Acquire);
-//                 let character = if other_hints { 0 } else { 2 };
-//                 let label = if other_hints {
-//                     "other hint"
-//                 } else {
-//                     "initial hint"
-//                 };
-//                 Ok(Some(vec![lsp::InlayHint {
-//                     position: lsp::Position::new(0, character),
-//                     label: lsp::InlayHintLabel::String(label.to_string()),
-//                     kind: None,
-//                     text_edits: None,
-//                     tooltip: None,
-//                     padding_left: None,
-//                     padding_right: None,
-//                     data: None,
-//                 }]))
-//             }
-//         })
-//         .next()
-//         .await
-//         .unwrap();
-//     cx_a.foreground().finish_waiting();
-//     cx_b.foreground().finish_waiting();
-
-//     executor.run_until_parked();
-//     editor_a.update(cx_a, |editor, _| {
-//         assert!(
-//             extract_hint_labels(editor).is_empty(),
-//             "Host should get no hints due to them turned off"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             0,
-//             "Turned off hints should not generate version updates"
-//         );
-//     });
-
-//     executor.run_until_parked();
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec!["initial hint".to_string()],
-//             extract_hint_labels(editor),
-//             "Client should get its first hints when opens an editor"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             1,
-//             "Should update cache verison after first hints"
-//         );
-//     });
-
-//     other_hints.fetch_or(true, atomic::Ordering::Release);
-//     fake_language_server
-//         .request::<lsp::request::InlayHintRefreshRequest>(())
-//         .await
-//         .expect("inlay refresh request failed");
-//     executor.run_until_parked();
-//     editor_a.update(cx_a, |editor, _| {
-//         assert!(
-//             extract_hint_labels(editor).is_empty(),
-//             "Host should get nop hints due to them turned off, even after the /refresh"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             0,
-//             "Turned off hints should not generate version updates, again"
-//         );
-//     });
-
-//     executor.run_until_parked();
-//     editor_b.update(cx_b, |editor, _| {
-//         assert_eq!(
-//             vec!["other hint".to_string()],
-//             extract_hint_labels(editor),
-//             "Guest should get a /refresh LSP request propagated by host despite host hints are off"
-//         );
-//         let inlay_cache = editor.inlay_hint_cache();
-//         assert_eq!(
-//             inlay_cache.version(),
-//             2,
-//             "Guest should accepted all edits and bump its cache version every time"
-//         );
-//     });
-// }
-
-// fn extract_hint_labels(editor: &Editor) -> Vec<String> {
-//     let mut labels = Vec::new();
-//     for hint in editor.inlay_hint_cache().hints() {
-//         match hint.label {
-//             project::InlayHintLabel::String(s) => labels.push(s),
-//             _ => unreachable!(),
-//         }
-//     }
-//     labels
-// }
+use std::{
+    path::Path,
+    sync::{
+        atomic::{self, AtomicBool, AtomicUsize},
+        Arc,
+    },
+};
+
+use call::ActiveCall;
+use editor::{
+    test::editor_test_context::{AssertionContextManager, EditorTestContext},
+    ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename, ToggleCodeActions,
+    Undo,
+};
+use futures::StreamExt;
+use gpui::{TestAppContext, VisualContext, VisualTestContext};
+use indoc::indoc;
+use language::{
+    language_settings::{AllLanguageSettings, InlayHintSettings},
+    tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig,
+};
+use rpc::RECEIVE_TIMEOUT;
+use serde_json::json;
+use settings::SettingsStore;
+use text::Point;
+use workspace::Workspace;
+
+use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
+
+#[gpui::test(iterations = 10)]
+async fn test_host_disconnect(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+    cx_c: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    let client_c = server.create_client(cx_c, "user_c").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
+        .await;
+
+    cx_b.update(editor::init);
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            serde_json::json!({
+                "a.txt": "a-contents",
+                "b.txt": "b-contents",
+            }),
+        )
+        .await;
+
+    let active_call_a = cx_a.read(ActiveCall::global);
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+
+    let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap());
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+    cx_a.background_executor.run_until_parked();
+
+    assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
+
+    let workspace_b =
+        cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
+    let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
+
+    let editor_b = workspace_b
+        .update(cx_b, |workspace, cx| {
+            workspace.open_path((worktree_id, "b.txt"), None, true, cx)
+        })
+        .unwrap()
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    //TODO: focus
+    assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
+    editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
+    //todo(is_edited)
+    // assert!(workspace_b.is_edited(cx_b));
+
+    // Drop client A's connection. Collaborators should disappear and the project should not be shown as shared.
+    server.forbid_connections();
+    server.disconnect_client(client_a.peer_id().unwrap());
+    cx_a.background_executor
+        .advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
+
+    project_a.read_with(cx_a, |project, _| project.collaborators().is_empty());
+
+    project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
+
+    project_b.read_with(cx_b, |project, _| project.is_read_only());
+
+    assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
+
+    // Ensure client B's edited state is reset and that the whole window is blurred.
+
+    workspace_b
+        .update(cx_b, |_, cx| {
+            assert_eq!(cx.focused(), None);
+        })
+        .unwrap();
+    // assert!(!workspace_b.is_edited(cx_b));
+
+    // Ensure client B is not prompted to save edits when closing window after disconnecting.
+    let can_close = workspace_b
+        .update(cx_b, |workspace, cx| workspace.prepare_to_close(true, cx))
+        .unwrap()
+        .await
+        .unwrap();
+    assert!(can_close);
+
+    // Allow client A to reconnect to the server.
+    server.allow_connections();
+    cx_a.background_executor.advance_clock(RECEIVE_TIMEOUT);
+
+    // Client B calls client A again after they reconnected.
+    let active_call_b = cx_b.read(ActiveCall::global);
+    active_call_b
+        .update(cx_b, |call, cx| {
+            call.invite(client_a.user_id().unwrap(), None, cx)
+        })
+        .await
+        .unwrap();
+    cx_a.background_executor.run_until_parked();
+    active_call_a
+        .update(cx_a, |call, cx| call.accept_incoming(cx))
+        .await
+        .unwrap();
+
+    active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    // Drop client A's connection again. We should still unshare it successfully.
+    server.forbid_connections();
+    server.disconnect_client(client_a.peer_id().unwrap());
+    cx_a.background_executor
+        .advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
+
+    project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
+}
+
+#[gpui::test]
+async fn test_newline_above_or_below_does_not_move_guest_cursor(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    let executor = cx_a.executor();
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    client_a
+        .fs()
+        .insert_tree("/dir", json!({ "a.txt": "Some text\n" }))
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    // Open a buffer as client A
+    let buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
+        .await
+        .unwrap();
+    let window_a = cx_a.add_empty_window();
+    let editor_a =
+        window_a.build_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
+
+    let mut editor_cx_a = EditorTestContext {
+        cx: VisualTestContext::from_window(window_a, cx_a),
+        window: window_a.into(),
+        editor: editor_a,
+        assertion_cx: AssertionContextManager::new(),
+    };
+
+    let window_b = cx_b.add_empty_window();
+    let mut cx_b = VisualTestContext::from_window(window_b, cx_b);
+
+    // Open a buffer as client B
+    let buffer_b = project_b
+        .update(&mut cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
+        .await
+        .unwrap();
+    let editor_b = window_b.build_view(&mut cx_b, |cx| {
+        Editor::for_buffer(buffer_b, Some(project_b), cx)
+    });
+    let mut editor_cx_b = EditorTestContext {
+        cx: cx_b,
+        window: window_b.into(),
+        editor: editor_b,
+        assertion_cx: AssertionContextManager::new(),
+    };
+
+    // Test newline above
+    editor_cx_a.set_selections_state(indoc! {"
+        Some textˇ
+    "});
+    editor_cx_b.set_selections_state(indoc! {"
+        Some textˇ
+    "});
+    editor_cx_a.update_editor(|editor, cx| editor.newline_above(&editor::NewlineAbove, cx));
+    executor.run_until_parked();
+    editor_cx_a.assert_editor_state(indoc! {"
+        Λ‡
+        Some text
+    "});
+    editor_cx_b.assert_editor_state(indoc! {"
+
+        Some textˇ
+    "});
+
+    // Test newline below
+    editor_cx_a.set_selections_state(indoc! {"
+
+        Some textˇ
+    "});
+    editor_cx_b.set_selections_state(indoc! {"
+
+        Some textˇ
+    "});
+    editor_cx_a.update_editor(|editor, cx| editor.newline_below(&editor::NewlineBelow, cx));
+    executor.run_until_parked();
+    editor_cx_a.assert_editor_state(indoc! {"
+
+        Some text
+        Λ‡
+    "});
+    editor_cx_b.assert_editor_state(indoc! {"
+
+        Some textˇ
+
+    "});
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                completion_provider: Some(lsp::CompletionOptions {
+                    trigger_characters: Some(vec![".".to_string()]),
+                    resolve_provider: Some(true),
+                    ..Default::default()
+                }),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "fn main() { a }",
+                "other.rs": "",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    // Open a file in an editor as the guest.
+    let buffer_b = project_b
+        .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+    let window_b = cx_b.add_empty_window();
+    let editor_b = window_b.build_view(cx_b, |cx| {
+        Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
+    });
+
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    cx_a.background_executor.run_until_parked();
+
+    buffer_b.read_with(cx_b, |buffer, _| {
+        assert!(!buffer.completion_triggers().is_empty())
+    });
+
+    let mut cx_b = VisualTestContext::from_window(window_b, cx_b);
+
+    // Type a completion trigger character as the guest.
+    editor_b.update(&mut cx_b, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
+        editor.handle_input(".", cx);
+    });
+    cx_b.focus_view(&editor_b);
+
+    // Receive a completion request as the host's language server.
+    // Return some completions from the host's language server.
+    cx_a.executor().start_waiting();
+    fake_language_server
+        .handle_request::<lsp::request::Completion, _, _>(|params, _| async move {
+            assert_eq!(
+                params.text_document_position.text_document.uri,
+                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+            );
+            assert_eq!(
+                params.text_document_position.position,
+                lsp::Position::new(0, 14),
+            );
+
+            Ok(Some(lsp::CompletionResponse::Array(vec![
+                lsp::CompletionItem {
+                    label: "first_method(…)".into(),
+                    detail: Some("fn(&mut self, B) -> C".into()),
+                    text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                        new_text: "first_method($1)".to_string(),
+                        range: lsp::Range::new(
+                            lsp::Position::new(0, 14),
+                            lsp::Position::new(0, 14),
+                        ),
+                    })),
+                    insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
+                    ..Default::default()
+                },
+                lsp::CompletionItem {
+                    label: "second_method(…)".into(),
+                    detail: Some("fn(&mut self, C) -> D<E>".into()),
+                    text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                        new_text: "second_method()".to_string(),
+                        range: lsp::Range::new(
+                            lsp::Position::new(0, 14),
+                            lsp::Position::new(0, 14),
+                        ),
+                    })),
+                    insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
+                    ..Default::default()
+                },
+            ])))
+        })
+        .next()
+        .await
+        .unwrap();
+    cx_a.executor().finish_waiting();
+
+    // Open the buffer on the host.
+    let buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+    cx_a.executor().run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a. }")
+    });
+
+    // Confirm a completion on the guest.
+
+    editor_b.update(&mut cx_b, |editor, cx| {
+        assert!(editor.context_menu_visible());
+        editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
+        assert_eq!(editor.text(cx), "fn main() { a.first_method() }");
+    });
+
+    // Return a resolved completion from the host's language server.
+    // The resolved completion has an additional text edit.
+    fake_language_server.handle_request::<lsp::request::ResolveCompletionItem, _, _>(
+        |params, _| async move {
+            assert_eq!(params.label, "first_method(…)");
+            Ok(lsp::CompletionItem {
+                label: "first_method(…)".into(),
+                detail: Some("fn(&mut self, B) -> C".into()),
+                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                    new_text: "first_method($1)".to_string(),
+                    range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
+                })),
+                additional_text_edits: Some(vec![lsp::TextEdit {
+                    new_text: "use d::SomeTrait;\n".to_string(),
+                    range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)),
+                }]),
+                insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
+                ..Default::default()
+            })
+        },
+    );
+
+    // The additional edit is applied.
+    cx_a.executor().run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(
+            buffer.text(),
+            "use d::SomeTrait;\nfn main() { a.first_method() }"
+        );
+    });
+
+    buffer_b.read_with(&mut cx_b, |buffer, _| {
+        assert_eq!(
+            buffer.text(),
+            "use d::SomeTrait;\nfn main() { a.first_method() }"
+        );
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_collaborating_with_code_actions(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    //
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    cx_b.update(editor::init);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "mod other;\nfn main() { let foo = other::foo(); }",
+                "other.rs": "pub fn foo() -> usize { 4 }",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    // Join the project as client B.
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+    let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
+    let editor_b = workspace_b
+        .update(cx_b, |workspace, cx| {
+            workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    let mut fake_language_server = fake_language_servers.next().await.unwrap();
+    let mut requests = fake_language_server
+        .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
+            assert_eq!(
+                params.text_document.uri,
+                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+            );
+            assert_eq!(params.range.start, lsp::Position::new(0, 0));
+            assert_eq!(params.range.end, lsp::Position::new(0, 0));
+            Ok(None)
+        });
+    cx_a.background_executor
+        .advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
+    requests.next().await;
+
+    // Move cursor to a location that contains code actions.
+    editor_b.update(cx_b, |editor, cx| {
+        editor.change_selections(None, cx, |s| {
+            s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
+        });
+    });
+    cx_b.focus_view(&editor_b);
+
+    let mut requests = fake_language_server
+        .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
+            assert_eq!(
+                params.text_document.uri,
+                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+            );
+            assert_eq!(params.range.start, lsp::Position::new(1, 31));
+            assert_eq!(params.range.end, lsp::Position::new(1, 31));
+
+            Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
+                lsp::CodeAction {
+                    title: "Inline into all callers".to_string(),
+                    edit: Some(lsp::WorkspaceEdit {
+                        changes: Some(
+                            [
+                                (
+                                    lsp::Url::from_file_path("/a/main.rs").unwrap(),
+                                    vec![lsp::TextEdit::new(
+                                        lsp::Range::new(
+                                            lsp::Position::new(1, 22),
+                                            lsp::Position::new(1, 34),
+                                        ),
+                                        "4".to_string(),
+                                    )],
+                                ),
+                                (
+                                    lsp::Url::from_file_path("/a/other.rs").unwrap(),
+                                    vec![lsp::TextEdit::new(
+                                        lsp::Range::new(
+                                            lsp::Position::new(0, 0),
+                                            lsp::Position::new(0, 27),
+                                        ),
+                                        "".to_string(),
+                                    )],
+                                ),
+                            ]
+                            .into_iter()
+                            .collect(),
+                        ),
+                        ..Default::default()
+                    }),
+                    data: Some(json!({
+                        "codeActionParams": {
+                            "range": {
+                                "start": {"line": 1, "column": 31},
+                                "end": {"line": 1, "column": 31},
+                            }
+                        }
+                    })),
+                    ..Default::default()
+                },
+            )]))
+        });
+    cx_a.background_executor
+        .advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
+    requests.next().await;
+
+    // Toggle code actions and wait for them to display.
+    editor_b.update(cx_b, |editor, cx| {
+        editor.toggle_code_actions(
+            &ToggleCodeActions {
+                deployed_from_indicator: false,
+            },
+            cx,
+        );
+    });
+    cx_a.background_executor.run_until_parked();
+
+    editor_b.update(cx_b, |editor, _| assert!(editor.context_menu_visible()));
+
+    fake_language_server.remove_request_handler::<lsp::request::CodeActionRequest>();
+
+    // Confirming the code action will trigger a resolve request.
+    let confirm_action = editor_b
+        .update(cx_b, |editor, cx| {
+            Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, cx)
+        })
+        .unwrap();
+    fake_language_server.handle_request::<lsp::request::CodeActionResolveRequest, _, _>(
+        |_, _| async move {
+            Ok(lsp::CodeAction {
+                title: "Inline into all callers".to_string(),
+                edit: Some(lsp::WorkspaceEdit {
+                    changes: Some(
+                        [
+                            (
+                                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+                                vec![lsp::TextEdit::new(
+                                    lsp::Range::new(
+                                        lsp::Position::new(1, 22),
+                                        lsp::Position::new(1, 34),
+                                    ),
+                                    "4".to_string(),
+                                )],
+                            ),
+                            (
+                                lsp::Url::from_file_path("/a/other.rs").unwrap(),
+                                vec![lsp::TextEdit::new(
+                                    lsp::Range::new(
+                                        lsp::Position::new(0, 0),
+                                        lsp::Position::new(0, 27),
+                                    ),
+                                    "".to_string(),
+                                )],
+                            ),
+                        ]
+                        .into_iter()
+                        .collect(),
+                    ),
+                    ..Default::default()
+                }),
+                ..Default::default()
+            })
+        },
+    );
+
+    // After the action is confirmed, an editor containing both modified files is opened.
+    confirm_action.await.unwrap();
+
+    let code_action_editor = workspace_b.update(cx_b, |workspace, cx| {
+        workspace
+            .active_item(cx)
+            .unwrap()
+            .downcast::<Editor>()
+            .unwrap()
+    });
+    code_action_editor.update(cx_b, |editor, cx| {
+        assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
+        editor.undo(&Undo, cx);
+        assert_eq!(
+            editor.text(cx),
+            "mod other;\nfn main() { let foo = other::foo(); }\npub fn foo() -> usize { 4 }"
+        );
+        editor.redo(&Redo, cx);
+        assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    cx_b.update(editor::init);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
+                    prepare_provider: Some(true),
+                    work_done_progress_options: Default::default(),
+                })),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/dir",
+            json!({
+                "one.rs": "const ONE: usize = 1;",
+                "two.rs": "const TWO: usize = one::ONE + one::ONE;"
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
+    let editor_b = workspace_b
+        .update(cx_b, |workspace, cx| {
+            workspace.open_path((worktree_id, "one.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+
+    // Move cursor to a location that can be renamed.
+    let prepare_rename = editor_b.update(cx_b, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
+        editor.rename(&Rename, cx).unwrap()
+    });
+
+    fake_language_server
+        .handle_request::<lsp::request::PrepareRenameRequest, _, _>(|params, _| async move {
+            assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs");
+            assert_eq!(params.position, lsp::Position::new(0, 7));
+            Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
+                lsp::Position::new(0, 6),
+                lsp::Position::new(0, 9),
+            ))))
+        })
+        .next()
+        .await
+        .unwrap();
+    prepare_rename.await.unwrap();
+    editor_b.update(cx_b, |editor, cx| {
+        use editor::ToOffset;
+        let rename = editor.pending_rename().unwrap();
+        let buffer = editor.buffer().read(cx).snapshot(cx);
+        assert_eq!(
+            rename.range.start.to_offset(&buffer)..rename.range.end.to_offset(&buffer),
+            6..9
+        );
+        rename.editor.update(cx, |rename_editor, cx| {
+            rename_editor.buffer().update(cx, |rename_buffer, cx| {
+                rename_buffer.edit([(0..3, "THREE")], None, cx);
+            });
+        });
+    });
+
+    let confirm_rename = editor_b.update(cx_b, |editor, cx| {
+        Editor::confirm_rename(editor, &ConfirmRename, cx).unwrap()
+    });
+    fake_language_server
+        .handle_request::<lsp::request::Rename, _, _>(|params, _| async move {
+            assert_eq!(
+                params.text_document_position.text_document.uri.as_str(),
+                "file:///dir/one.rs"
+            );
+            assert_eq!(
+                params.text_document_position.position,
+                lsp::Position::new(0, 6)
+            );
+            assert_eq!(params.new_name, "THREE");
+            Ok(Some(lsp::WorkspaceEdit {
+                changes: Some(
+                    [
+                        (
+                            lsp::Url::from_file_path("/dir/one.rs").unwrap(),
+                            vec![lsp::TextEdit::new(
+                                lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)),
+                                "THREE".to_string(),
+                            )],
+                        ),
+                        (
+                            lsp::Url::from_file_path("/dir/two.rs").unwrap(),
+                            vec![
+                                lsp::TextEdit::new(
+                                    lsp::Range::new(
+                                        lsp::Position::new(0, 24),
+                                        lsp::Position::new(0, 27),
+                                    ),
+                                    "THREE".to_string(),
+                                ),
+                                lsp::TextEdit::new(
+                                    lsp::Range::new(
+                                        lsp::Position::new(0, 35),
+                                        lsp::Position::new(0, 38),
+                                    ),
+                                    "THREE".to_string(),
+                                ),
+                            ],
+                        ),
+                    ]
+                    .into_iter()
+                    .collect(),
+                ),
+                ..Default::default()
+            }))
+        })
+        .next()
+        .await
+        .unwrap();
+    confirm_rename.await.unwrap();
+
+    let rename_editor = workspace_b.update(cx_b, |workspace, cx| {
+        workspace.active_item_as::<Editor>(cx).unwrap()
+    });
+
+    rename_editor.update(cx_b, |editor, cx| {
+        assert_eq!(
+            editor.text(cx),
+            "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
+        );
+        editor.undo(&Undo, cx);
+        assert_eq!(
+            editor.text(cx),
+            "const ONE: usize = 1;\nconst TWO: usize = one::ONE + one::ONE;"
+        );
+        editor.redo(&Redo, cx);
+        assert_eq!(
+            editor.text(cx),
+            "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
+        );
+    });
+
+    // Ensure temporary rename edits cannot be undone/redone.
+    editor_b.update(cx_b, |editor, cx| {
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "const ONE: usize = 1;");
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "const ONE: usize = 1;");
+        editor.redo(&Redo, cx);
+        assert_eq!(editor.text(cx), "const THREE: usize = 1;");
+    })
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_language_server_statuses(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let executor = cx_a.executor();
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    cx_b.update(editor::init);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "the-language-server",
+            ..Default::default()
+        }))
+        .await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/dir",
+            json!({
+                "main.rs": "const ONE: usize = 1;",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
+
+    let _buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    fake_language_server.start_progress("the-token").await;
+    fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
+        token: lsp::NumberOrString::String("the-token".to_string()),
+        value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
+            lsp::WorkDoneProgressReport {
+                message: Some("the-message".to_string()),
+                ..Default::default()
+            },
+        )),
+    });
+    executor.run_until_parked();
+
+    project_a.read_with(cx_a, |project, _| {
+        let status = project.language_server_statuses().next().unwrap();
+        assert_eq!(status.name, "the-language-server");
+        assert_eq!(status.pending_work.len(), 1);
+        assert_eq!(
+            status.pending_work["the-token"].message.as_ref().unwrap(),
+            "the-message"
+        );
+    });
+
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    executor.run_until_parked();
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    project_b.read_with(cx_b, |project, _| {
+        let status = project.language_server_statuses().next().unwrap();
+        assert_eq!(status.name, "the-language-server");
+    });
+
+    fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
+        token: lsp::NumberOrString::String("the-token".to_string()),
+        value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
+            lsp::WorkDoneProgressReport {
+                message: Some("the-message-2".to_string()),
+                ..Default::default()
+            },
+        )),
+    });
+    executor.run_until_parked();
+
+    project_a.read_with(cx_a, |project, _| {
+        let status = project.language_server_statuses().next().unwrap();
+        assert_eq!(status.name, "the-language-server");
+        assert_eq!(status.pending_work.len(), 1);
+        assert_eq!(
+            status.pending_work["the-token"].message.as_ref().unwrap(),
+            "the-message-2"
+        );
+    });
+
+    project_b.read_with(cx_b, |project, _| {
+        let status = project.language_server_statuses().next().unwrap();
+        assert_eq!(status.name, "the-language-server");
+        assert_eq!(status.pending_work.len(), 1);
+        assert_eq!(
+            status.pending_work["the-token"].message.as_ref().unwrap(),
+            "the-message-2"
+        );
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_share_project(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+    cx_c: &mut TestAppContext,
+) {
+    let executor = cx_a.executor();
+    let window_b = cx_b.add_empty_window();
+    let mut server = TestServer::start(executor.clone()).await;
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    let client_c = server.create_client(cx_c, "user_c").await;
+    server
+        .make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+    let active_call_b = cx_b.read(ActiveCall::global);
+    let active_call_c = cx_c.read(ActiveCall::global);
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                ".gitignore": "ignored-dir",
+                "a.txt": "a-contents",
+                "b.txt": "b-contents",
+                "ignored-dir": {
+                    "c.txt": "",
+                    "d.txt": "",
+                }
+            }),
+        )
+        .await;
+
+    // Invite client B to collaborate on a project
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    active_call_a
+        .update(cx_a, |call, cx| {
+            call.invite(client_b.user_id().unwrap(), Some(project_a.clone()), cx)
+        })
+        .await
+        .unwrap();
+
+    // Join that project as client B
+
+    let incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming());
+    executor.run_until_parked();
+    let call = incoming_call_b.borrow().clone().unwrap();
+    assert_eq!(call.calling_user.github_login, "user_a");
+    let initial_project = call.initial_project.unwrap();
+    active_call_b
+        .update(cx_b, |call, cx| call.accept_incoming(cx))
+        .await
+        .unwrap();
+    let client_b_peer_id = client_b.peer_id().unwrap();
+    let project_b = client_b
+        .build_remote_project(initial_project.id, cx_b)
+        .await;
+
+    let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
+
+    executor.run_until_parked();
+
+    project_a.read_with(cx_a, |project, _| {
+        let client_b_collaborator = project.collaborators().get(&client_b_peer_id).unwrap();
+        assert_eq!(client_b_collaborator.replica_id, replica_id_b);
+    });
+
+    project_b.read_with(cx_b, |project, cx| {
+        let worktree = project.worktrees().next().unwrap().read(cx);
+        assert_eq!(
+            worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
+            [
+                Path::new(".gitignore"),
+                Path::new("a.txt"),
+                Path::new("b.txt"),
+                Path::new("ignored-dir"),
+            ]
+        );
+    });
+
+    project_b
+        .update(cx_b, |project, cx| {
+            let worktree = project.worktrees().next().unwrap();
+            let entry = worktree.read(cx).entry_for_path("ignored-dir").unwrap();
+            project.expand_entry(worktree_id, entry.id, cx).unwrap()
+        })
+        .await
+        .unwrap();
+
+    project_b.read_with(cx_b, |project, cx| {
+        let worktree = project.worktrees().next().unwrap().read(cx);
+        assert_eq!(
+            worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
+            [
+                Path::new(".gitignore"),
+                Path::new("a.txt"),
+                Path::new("b.txt"),
+                Path::new("ignored-dir"),
+                Path::new("ignored-dir/c.txt"),
+                Path::new("ignored-dir/d.txt"),
+            ]
+        );
+    });
+
+    // Open the same file as client B and client A.
+    let buffer_b = project_b
+        .update(cx_b, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
+        .await
+        .unwrap();
+
+    buffer_b.read_with(cx_b, |buf, _| assert_eq!(buf.text(), "b-contents"));
+
+    project_a.read_with(cx_a, |project, cx| {
+        assert!(project.has_open_buffer((worktree_id, "b.txt"), cx))
+    });
+    let buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
+        .await
+        .unwrap();
+
+    let editor_b = window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
+
+    // Client A sees client B's selection
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        buffer
+            .snapshot()
+            .remote_selections_in_range(text::Anchor::MIN..text::Anchor::MAX)
+            .count()
+            == 1
+    });
+
+    // Edit the buffer as client B and see that edit as client A.
+    let mut cx_b = VisualTestContext::from_window(window_b, cx_b);
+    editor_b.update(&mut cx_b, |editor, cx| editor.handle_input("ok, ", cx));
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(buffer.text(), "ok, b-contents")
+    });
+
+    // Client B can invite client C on a project shared by client A.
+    active_call_b
+        .update(&mut cx_b, |call, cx| {
+            call.invite(client_c.user_id().unwrap(), Some(project_b.clone()), cx)
+        })
+        .await
+        .unwrap();
+
+    let incoming_call_c = active_call_c.read_with(cx_c, |call, _| call.incoming());
+    executor.run_until_parked();
+    let call = incoming_call_c.borrow().clone().unwrap();
+    assert_eq!(call.calling_user.github_login, "user_b");
+    let initial_project = call.initial_project.unwrap();
+    active_call_c
+        .update(cx_c, |call, cx| call.accept_incoming(cx))
+        .await
+        .unwrap();
+    let _project_c = client_c
+        .build_remote_project(initial_project.id, cx_c)
+        .await;
+
+    // Client B closes the editor, and client A sees client B's selections removed.
+    cx_b.update(move |_| drop(editor_b));
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        buffer
+            .snapshot()
+            .remote_selections_in_range(text::Anchor::MIN..text::Anchor::MAX)
+            .count()
+            == 0
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_on_input_format_from_host_to_guest(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let executor = cx_a.executor();
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
+                    first_trigger_character: ":".to_string(),
+                    more_trigger_character: Some(vec![">".to_string()]),
+                }),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "fn main() { a }",
+                "other.rs": "// Test file",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    // Open a file in an editor as the host.
+    let buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+    let window_a = cx_a.add_empty_window();
+    let editor_a = window_a
+        .update(cx_a, |_, cx| {
+            cx.new_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx))
+        })
+        .unwrap();
+
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    executor.run_until_parked();
+
+    // Receive an OnTypeFormatting request as the host's language server.
+    // Return some formattings from the host's language server.
+    fake_language_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(
+        |params, _| async move {
+            assert_eq!(
+                params.text_document_position.text_document.uri,
+                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+            );
+            assert_eq!(
+                params.text_document_position.position,
+                lsp::Position::new(0, 14),
+            );
+
+            Ok(Some(vec![lsp::TextEdit {
+                new_text: "~<".to_string(),
+                range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
+            }]))
+        },
+    );
+
+    // Open the buffer on the guest and see that the formattings worked
+    let buffer_b = project_b
+        .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+
+    let mut cx_a = VisualTestContext::from_window(window_a, cx_a);
+    // Type a on type formatting trigger character as the guest.
+    cx_a.focus_view(&editor_a);
+    editor_a.update(&mut cx_a, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
+        editor.handle_input(">", cx);
+    });
+
+    executor.run_until_parked();
+
+    buffer_b.read_with(cx_b, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a>~< }")
+    });
+
+    // Undo should remove LSP edits first
+    editor_a.update(&mut cx_a, |editor, cx| {
+        assert_eq!(editor.text(cx), "fn main() { a>~< }");
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "fn main() { a> }");
+    });
+    executor.run_until_parked();
+
+    buffer_b.read_with(cx_b, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a> }")
+    });
+
+    editor_a.update(&mut cx_a, |editor, cx| {
+        assert_eq!(editor.text(cx), "fn main() { a> }");
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "fn main() { a }");
+    });
+    executor.run_until_parked();
+
+    buffer_b.read_with(cx_b, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a }")
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_on_input_format_from_guest_to_host(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let executor = cx_a.executor();
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+
+    // Set up a fake language server.
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
+                    first_trigger_character: ":".to_string(),
+                    more_trigger_character: Some(vec![">".to_string()]),
+                }),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    client_a.language_registry().add(Arc::new(language));
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "fn main() { a }",
+                "other.rs": "// Test file",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+
+    // Open a file in an editor as the guest.
+    let buffer_b = project_b
+        .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+    let window_b = cx_b.add_empty_window();
+    let editor_b = window_b.build_view(cx_b, |cx| {
+        Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
+    });
+
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    executor.run_until_parked();
+    let mut cx_b = VisualTestContext::from_window(window_b, cx_b);
+    // Type a on type formatting trigger character as the guest.
+    cx_b.focus_view(&editor_b);
+    editor_b.update(&mut cx_b, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
+        editor.handle_input(":", cx);
+    });
+
+    // Receive an OnTypeFormatting request as the host's language server.
+    // Return some formattings from the host's language server.
+    executor.start_waiting();
+    fake_language_server
+        .handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
+            assert_eq!(
+                params.text_document_position.text_document.uri,
+                lsp::Url::from_file_path("/a/main.rs").unwrap(),
+            );
+            assert_eq!(
+                params.text_document_position.position,
+                lsp::Position::new(0, 14),
+            );
+
+            Ok(Some(vec![lsp::TextEdit {
+                new_text: "~:".to_string(),
+                range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
+            }]))
+        })
+        .next()
+        .await
+        .unwrap();
+    executor.finish_waiting();
+
+    // Open the buffer on the host and see that the formattings worked
+    let buffer_a = project_a
+        .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
+        .await
+        .unwrap();
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a:~: }")
+    });
+
+    // Undo should remove LSP edits first
+    editor_b.update(&mut cx_b, |editor, cx| {
+        assert_eq!(editor.text(cx), "fn main() { a:~: }");
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "fn main() { a: }");
+    });
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a: }")
+    });
+
+    editor_b.update(&mut cx_b, |editor, cx| {
+        assert_eq!(editor.text(cx), "fn main() { a: }");
+        editor.undo(&Undo, cx);
+        assert_eq!(editor.text(cx), "fn main() { a }");
+    });
+    executor.run_until_parked();
+
+    buffer_a.read_with(cx_a, |buffer, _| {
+        assert_eq!(buffer.text(), "fn main() { a }")
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_mutual_editor_inlay_hint_cache_update(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let executor = cx_a.executor();
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+    let active_call_b = cx_b.read(ActiveCall::global);
+
+    cx_a.update(editor::init);
+    cx_b.update(editor::init);
+
+    cx_a.update(|cx| {
+        cx.update_global(|store: &mut SettingsStore, cx| {
+            store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
+                settings.defaults.inlay_hints = Some(InlayHintSettings {
+                    enabled: true,
+                    show_type_hints: true,
+                    show_parameter_hints: false,
+                    show_other_hints: true,
+                })
+            });
+        });
+    });
+    cx_b.update(|cx| {
+        cx.update_global(|store: &mut SettingsStore, cx| {
+            store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
+                settings.defaults.inlay_hints = Some(InlayHintSettings {
+                    enabled: true,
+                    show_type_hints: true,
+                    show_parameter_hints: false,
+                    show_other_hints: true,
+                })
+            });
+        });
+    });
+
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                inlay_hint_provider: Some(lsp::OneOf::Left(true)),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    let language = Arc::new(language);
+    client_a.language_registry().add(Arc::clone(&language));
+    client_b.language_registry().add(language);
+
+    // Client A opens a project.
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
+                "other.rs": "// Test file",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    active_call_a
+        .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
+        .await
+        .unwrap();
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    // Client B joins the project
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+    active_call_b
+        .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
+        .await
+        .unwrap();
+
+    let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
+    executor.start_waiting();
+
+    // The host opens a rust file.
+    let _buffer_a = project_a
+        .update(cx_a, |project, cx| {
+            project.open_local_buffer("/a/main.rs", cx)
+        })
+        .await
+        .unwrap();
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    let editor_a = workspace_a
+        .update(cx_a, |workspace, cx| {
+            workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    // Set up the language server to return an additional inlay hint on each request.
+    let edits_made = Arc::new(AtomicUsize::new(0));
+    let closure_edits_made = Arc::clone(&edits_made);
+    fake_language_server
+        .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
+            let task_edits_made = Arc::clone(&closure_edits_made);
+            async move {
+                assert_eq!(
+                    params.text_document.uri,
+                    lsp::Url::from_file_path("/a/main.rs").unwrap(),
+                );
+                let edits_made = task_edits_made.load(atomic::Ordering::Acquire);
+                Ok(Some(vec![lsp::InlayHint {
+                    position: lsp::Position::new(0, edits_made as u32),
+                    label: lsp::InlayHintLabel::String(edits_made.to_string()),
+                    kind: None,
+                    text_edits: None,
+                    tooltip: None,
+                    padding_left: None,
+                    padding_right: None,
+                    data: None,
+                }]))
+            }
+        })
+        .next()
+        .await
+        .unwrap();
+
+    executor.run_until_parked();
+
+    let initial_edit = edits_made.load(atomic::Ordering::Acquire);
+    editor_a.update(cx_a, |editor, _| {
+        assert_eq!(
+            vec![initial_edit.to_string()],
+            extract_hint_labels(editor),
+            "Host should get its first hints when opens an editor"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            1,
+            "Host editor update the cache version after every cache/view change",
+        );
+    });
+    let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
+    let editor_b = workspace_b
+        .update(cx_b, |workspace, cx| {
+            workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    executor.run_until_parked();
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec![initial_edit.to_string()],
+            extract_hint_labels(editor),
+            "Client should get its first hints when opens an editor"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            1,
+            "Guest editor update the cache version after every cache/view change"
+        );
+    });
+
+    let after_client_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
+    editor_b.update(cx_b, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([13..13].clone()));
+        editor.handle_input(":", cx);
+    });
+    cx_b.focus_view(&editor_b);
+
+    executor.run_until_parked();
+    editor_a.update(cx_a, |editor, _| {
+        assert_eq!(
+            vec![after_client_edit.to_string()],
+            extract_hint_labels(editor),
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(inlay_cache.version(), 2);
+    });
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec![after_client_edit.to_string()],
+            extract_hint_labels(editor),
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(inlay_cache.version(), 2);
+    });
+
+    let after_host_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
+    editor_a.update(cx_a, |editor, cx| {
+        editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
+        editor.handle_input("a change to increment both buffers' versions", cx);
+    });
+    cx_a.focus_view(&editor_a);
+
+    executor.run_until_parked();
+    editor_a.update(cx_a, |editor, _| {
+        assert_eq!(
+            vec![after_host_edit.to_string()],
+            extract_hint_labels(editor),
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(inlay_cache.version(), 3);
+    });
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec![after_host_edit.to_string()],
+            extract_hint_labels(editor),
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(inlay_cache.version(), 3);
+    });
+
+    let after_special_edit_for_refresh = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
+    fake_language_server
+        .request::<lsp::request::InlayHintRefreshRequest>(())
+        .await
+        .expect("inlay refresh request failed");
+
+    executor.run_until_parked();
+    editor_a.update(cx_a, |editor, _| {
+        assert_eq!(
+            vec![after_special_edit_for_refresh.to_string()],
+            extract_hint_labels(editor),
+            "Host should react to /refresh LSP request"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            4,
+            "Host should accepted all edits and bump its cache version every time"
+        );
+    });
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec![after_special_edit_for_refresh.to_string()],
+            extract_hint_labels(editor),
+            "Guest should get a /refresh LSP request propagated by host"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            4,
+            "Guest should accepted all edits and bump its cache version every time"
+        );
+    });
+}
+
+#[gpui::test(iterations = 10)]
+async fn test_inlay_hint_refresh_is_forwarded(
+    cx_a: &mut TestAppContext,
+    cx_b: &mut TestAppContext,
+) {
+    let mut server = TestServer::start(cx_a.executor()).await;
+    let executor = cx_a.executor();
+    let client_a = server.create_client(cx_a, "user_a").await;
+    let client_b = server.create_client(cx_b, "user_b").await;
+    server
+        .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
+        .await;
+    let active_call_a = cx_a.read(ActiveCall::global);
+    let active_call_b = cx_b.read(ActiveCall::global);
+
+    cx_a.update(editor::init);
+    cx_b.update(editor::init);
+
+    cx_a.update(|cx| {
+        cx.update_global(|store: &mut SettingsStore, cx| {
+            store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
+                settings.defaults.inlay_hints = Some(InlayHintSettings {
+                    enabled: false,
+                    show_type_hints: false,
+                    show_parameter_hints: false,
+                    show_other_hints: false,
+                })
+            });
+        });
+    });
+    cx_b.update(|cx| {
+        cx.update_global(|store: &mut SettingsStore, cx| {
+            store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
+                settings.defaults.inlay_hints = Some(InlayHintSettings {
+                    enabled: true,
+                    show_type_hints: true,
+                    show_parameter_hints: true,
+                    show_other_hints: true,
+                })
+            });
+        });
+    });
+
+    let mut language = Language::new(
+        LanguageConfig {
+            name: "Rust".into(),
+            path_suffixes: vec!["rs".to_string()],
+            ..Default::default()
+        },
+        Some(tree_sitter_rust::language()),
+    );
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                inlay_hint_provider: Some(lsp::OneOf::Left(true)),
+                ..Default::default()
+            },
+            ..Default::default()
+        }))
+        .await;
+    let language = Arc::new(language);
+    client_a.language_registry().add(Arc::clone(&language));
+    client_b.language_registry().add(language);
+
+    client_a
+        .fs()
+        .insert_tree(
+            "/a",
+            json!({
+                "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
+                "other.rs": "// Test file",
+            }),
+        )
+        .await;
+    let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
+    active_call_a
+        .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
+        .await
+        .unwrap();
+    let project_id = active_call_a
+        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+        .await
+        .unwrap();
+
+    let project_b = client_b.build_remote_project(project_id, cx_b).await;
+    active_call_b
+        .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
+        .await
+        .unwrap();
+
+    let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
+    let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
+
+    cx_a.background_executor.start_waiting();
+
+    let editor_a = workspace_a
+        .update(cx_a, |workspace, cx| {
+            workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    let editor_b = workspace_b
+        .update(cx_b, |workspace, cx| {
+            workspace.open_path((worktree_id, "main.rs"), None, true, cx)
+        })
+        .await
+        .unwrap()
+        .downcast::<Editor>()
+        .unwrap();
+
+    let other_hints = Arc::new(AtomicBool::new(false));
+    let fake_language_server = fake_language_servers.next().await.unwrap();
+    let closure_other_hints = Arc::clone(&other_hints);
+    fake_language_server
+        .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
+            let task_other_hints = Arc::clone(&closure_other_hints);
+            async move {
+                assert_eq!(
+                    params.text_document.uri,
+                    lsp::Url::from_file_path("/a/main.rs").unwrap(),
+                );
+                let other_hints = task_other_hints.load(atomic::Ordering::Acquire);
+                let character = if other_hints { 0 } else { 2 };
+                let label = if other_hints {
+                    "other hint"
+                } else {
+                    "initial hint"
+                };
+                Ok(Some(vec![lsp::InlayHint {
+                    position: lsp::Position::new(0, character),
+                    label: lsp::InlayHintLabel::String(label.to_string()),
+                    kind: None,
+                    text_edits: None,
+                    tooltip: None,
+                    padding_left: None,
+                    padding_right: None,
+                    data: None,
+                }]))
+            }
+        })
+        .next()
+        .await
+        .unwrap();
+    executor.finish_waiting();
+
+    executor.run_until_parked();
+    editor_a.update(cx_a, |editor, _| {
+        assert!(
+            extract_hint_labels(editor).is_empty(),
+            "Host should get no hints due to them turned off"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            0,
+            "Turned off hints should not generate version updates"
+        );
+    });
+
+    executor.run_until_parked();
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec!["initial hint".to_string()],
+            extract_hint_labels(editor),
+            "Client should get its first hints when opens an editor"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            1,
+            "Should update cache verison after first hints"
+        );
+    });
+
+    other_hints.fetch_or(true, atomic::Ordering::Release);
+    fake_language_server
+        .request::<lsp::request::InlayHintRefreshRequest>(())
+        .await
+        .expect("inlay refresh request failed");
+    executor.run_until_parked();
+    editor_a.update(cx_a, |editor, _| {
+        assert!(
+            extract_hint_labels(editor).is_empty(),
+            "Host should get nop hints due to them turned off, even after the /refresh"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            0,
+            "Turned off hints should not generate version updates, again"
+        );
+    });
+
+    executor.run_until_parked();
+    editor_b.update(cx_b, |editor, _| {
+        assert_eq!(
+            vec!["other hint".to_string()],
+            extract_hint_labels(editor),
+            "Guest should get a /refresh LSP request propagated by host despite host hints are off"
+        );
+        let inlay_cache = editor.inlay_hint_cache();
+        assert_eq!(
+            inlay_cache.version(),
+            2,
+            "Guest should accepted all edits and bump its cache version every time"
+        );
+    });
+}
+
+fn extract_hint_labels(editor: &Editor) -> Vec<String> {
+    let mut labels = Vec::new();
+    for hint in editor.inlay_hint_cache().hints() {
+        match hint.label {
+            project::InlayHintLabel::String(s) => labels.push(s),
+            _ => unreachable!(),
+        }
+    }
+    labels
+}

crates/collab/src/tests/integration_tests.rs πŸ”—

@@ -19,6 +19,7 @@ use project::{
     search::SearchQuery, DiagnosticSummary, FormatTrigger, HoverBlockKind, Project, ProjectPath,
 };
 use rand::prelude::*;
+use rpc::proto::ChannelRole;
 use serde_json::json;
 use settings::SettingsStore;
 use std::{
@@ -1380,7 +1381,7 @@ async fn test_unshare_project(
         .unwrap();
     executor.run_until_parked();
 
-    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
+    assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
 
     // Client C opens the project.
     let project_c = client_c.build_remote_project(project_id, cx_c).await;
@@ -1393,7 +1394,7 @@ async fn test_unshare_project(
 
     assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
 
-    assert!(project_c.read_with(cx_c, |project, _| project.is_read_only()));
+    assert!(project_c.read_with(cx_c, |project, _| project.is_disconnected()));
 
     // Client C can open the project again after client A re-shares.
     let project_id = active_call_a
@@ -1419,7 +1420,7 @@ async fn test_unshare_project(
     project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
 
     project_c2.read_with(cx_c, |project, _| {
-        assert!(project.is_read_only());
+        assert!(project.is_disconnected());
         assert!(project.collaborators().is_empty());
     });
 }
@@ -1551,7 +1552,7 @@ async fn test_project_reconnect(
     });
 
     project_b1.read_with(cx_b, |project, _| {
-        assert!(!project.is_read_only());
+        assert!(!project.is_disconnected());
         assert_eq!(project.collaborators().len(), 1);
     });
 
@@ -1653,7 +1654,7 @@ async fn test_project_reconnect(
     });
 
     project_b1.read_with(cx_b, |project, cx| {
-        assert!(!project.is_read_only());
+        assert!(!project.is_disconnected());
         assert_eq!(
             project
                 .worktree_for_id(worktree1_id, cx)
@@ -1687,9 +1688,9 @@ async fn test_project_reconnect(
         );
     });
 
-    project_b2.read_with(cx_b, |project, _| assert!(project.is_read_only()));
+    project_b2.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
 
-    project_b3.read_with(cx_b, |project, _| assert!(!project.is_read_only()));
+    project_b3.read_with(cx_b, |project, _| assert!(!project.is_disconnected()));
 
     buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WaZ"));
 
@@ -1746,7 +1747,7 @@ async fn test_project_reconnect(
     executor.run_until_parked();
 
     project_b1.read_with(cx_b, |project, cx| {
-        assert!(!project.is_read_only());
+        assert!(!project.is_disconnected());
         assert_eq!(
             project
                 .worktree_for_id(worktree1_id, cx)
@@ -1780,7 +1781,7 @@ async fn test_project_reconnect(
         );
     });
 
-    project_b3.read_with(cx_b, |project, _| assert!(project.is_read_only()));
+    project_b3.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
 
     buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WXaYZ"));
 
@@ -3535,7 +3536,7 @@ async fn test_leaving_project(
     });
 
     project_b2.read_with(cx_b, |project, _| {
-        assert!(project.is_read_only());
+        assert!(project.is_disconnected());
     });
 
     project_c.read_with(cx_c, |project, _| {
@@ -3550,6 +3551,7 @@ async fn test_leaving_project(
             client_b.user_store().clone(),
             client_b.language_registry().clone(),
             FakeFs::new(cx.background_executor().clone()),
+            ChannelRole::Member,
             cx,
         )
     })
@@ -3568,11 +3570,11 @@ async fn test_leaving_project(
     });
 
     project_b2.read_with(cx_b, |project, _| {
-        assert!(project.is_read_only());
+        assert!(project.is_disconnected());
     });
 
     project_c.read_with(cx_c, |project, _| {
-        assert!(project.is_read_only());
+        assert!(project.is_disconnected());
     });
 }
 

crates/collab/src/tests/random_project_collaboration_tests.rs πŸ”—

@@ -1149,7 +1149,7 @@ impl RandomizedTest for ProjectCollaborationTest {
                             Some((project, cx))
                         });
 
-                        if !guest_project.is_read_only() {
+                        if !guest_project.is_disconnected() {
                             if let Some((host_project, host_cx)) = host_project {
                                 let host_worktree_snapshots =
                                     host_project.read_with(host_cx, |host_project, cx| {
@@ -1236,7 +1236,7 @@ impl RandomizedTest for ProjectCollaborationTest {
             let buffers = client.buffers().clone();
             for (guest_project, guest_buffers) in &buffers {
                 let project_id = if guest_project.read_with(client_cx, |project, _| {
-                    project.is_local() || project.is_read_only()
+                    project.is_local() || project.is_disconnected()
                 }) {
                     continue;
                 } else {

crates/collab/src/tests/randomized_test_helpers.rs πŸ”—

@@ -518,7 +518,7 @@ impl<T: RandomizedTest> TestPlan<T> {
                 for project in client.remote_projects().iter() {
                     project.read_with(&client_cx, |project, _| {
                         assert!(
-                            project.is_read_only(),
+                            project.is_disconnected(),
                             "project {:?} should be read only",
                             project.remote_id()
                         )

crates/collab_ui/src/channel_view.rs πŸ”—

@@ -138,12 +138,6 @@ impl ChannelView {
             editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
                 channel_buffer.clone(),
             )));
-            editor.set_read_only(
-                !channel_buffer
-                    .read(cx)
-                    .channel(cx)
-                    .is_some_and(|c| c.can_edit_notes()),
-            );
             editor
         });
         let _editor_event_subscription =
@@ -178,8 +172,7 @@ impl ChannelView {
                 cx.notify();
             }),
             ChannelBufferEvent::ChannelChanged => {
-                self.editor.update(cx, |editor, cx| {
-                    editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
+                self.editor.update(cx, |_, cx| {
                     cx.emit(editor::EditorEvent::TitleChanged);
                     cx.notify()
                 });
@@ -254,11 +247,11 @@ impl Item for ChannelView {
     fn tab_content(&self, _: Option<usize>, selected: bool, cx: &WindowContext) -> AnyElement {
         let label = if let Some(channel) = self.channel(cx) {
             match (
-                channel.can_edit_notes(),
+                self.channel_buffer.read(cx).buffer().read(cx).read_only(),
                 self.channel_buffer.read(cx).is_connected(),
             ) {
-                (true, true) => format!("#{}", channel.name),
-                (false, true) => format!("#{} (read-only)", channel.name),
+                (false, true) => format!("#{}", channel.name),
+                (true, true) => format!("#{} (read-only)", channel.name),
                 (_, false) => format!("#{} (disconnected)", channel.name),
             }
         } else {

crates/collab_ui/src/chat_panel.rs πŸ”—

@@ -607,8 +607,12 @@ impl Panel for ChatPanel {
         "ChatPanel"
     }
 
-    fn icon(&self, _cx: &WindowContext) -> Option<ui::Icon> {
-        Some(ui::Icon::MessageBubbles)
+    fn icon(&self, cx: &WindowContext) -> Option<ui::Icon> {
+        if !is_channels_feature_enabled(cx) {
+            return None;
+        }
+
+        Some(ui::Icon::MessageBubbles).filter(|_| ChatPanelSettings::get_global(cx).button)
     }
 
     fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {

crates/collab_ui/src/collab_panel.rs πŸ”—

@@ -151,6 +151,10 @@ enum ListEntry {
         peer_id: Option<PeerId>,
         is_last: bool,
     },
+    GuestCount {
+        count: usize,
+        has_visible_participants: bool,
+    },
     IncomingRequest(Arc<User>),
     OutgoingRequest(Arc<User>),
     ChannelInvite(Arc<Channel>),
@@ -380,10 +384,14 @@ impl CollabPanel {
 
             if !self.collapsed_sections.contains(&Section::ActiveCall) {
                 let room = room.read(cx);
+                let mut guest_count_ix = 0;
+                let mut guest_count = if room.read_only() { 1 } else { 0 };
+                let mut non_guest_count = if room.read_only() { 0 } else { 1 };
 
                 if let Some(channel_id) = room.channel_id() {
                     self.entries.push(ListEntry::ChannelNotes { channel_id });
-                    self.entries.push(ListEntry::ChannelChat { channel_id })
+                    self.entries.push(ListEntry::ChannelChat { channel_id });
+                    guest_count_ix = self.entries.len();
                 }
 
                 // Populate the active user.
@@ -402,7 +410,7 @@ impl CollabPanel {
                         &Default::default(),
                         executor.clone(),
                     ));
-                    if !matches.is_empty() {
+                    if !matches.is_empty() && !room.read_only() {
                         let user_id = user.id;
                         self.entries.push(ListEntry::CallParticipant {
                             user,
@@ -430,13 +438,23 @@ impl CollabPanel {
                 // Populate remote participants.
                 self.match_candidates.clear();
                 self.match_candidates
-                    .extend(room.remote_participants().iter().map(|(_, participant)| {
-                        StringMatchCandidate {
-                            id: participant.user.id as usize,
-                            string: participant.user.github_login.clone(),
-                            char_bag: participant.user.github_login.chars().collect(),
-                        }
-                    }));
+                    .extend(
+                        room.remote_participants()
+                            .iter()
+                            .filter_map(|(_, participant)| {
+                                if participant.role == proto::ChannelRole::Guest {
+                                    guest_count += 1;
+                                    return None;
+                                } else {
+                                    non_guest_count += 1;
+                                }
+                                Some(StringMatchCandidate {
+                                    id: participant.user.id as usize,
+                                    string: participant.user.github_login.clone(),
+                                    char_bag: participant.user.github_login.chars().collect(),
+                                })
+                            }),
+                    );
                 let matches = executor.block(match_strings(
                     &self.match_candidates,
                     &query,
@@ -470,6 +488,15 @@ impl CollabPanel {
                         });
                     }
                 }
+                if guest_count > 0 {
+                    self.entries.insert(
+                        guest_count_ix,
+                        ListEntry::GuestCount {
+                            count: guest_count,
+                            has_visible_participants: non_guest_count > 0,
+                        },
+                    );
+                }
 
                 // Populate pending participants.
                 self.match_candidates.clear();
@@ -959,6 +986,41 @@ impl CollabPanel {
             .tooltip(move |cx| Tooltip::text("Open Chat", cx))
     }
 
+    fn render_guest_count(
+        &self,
+        count: usize,
+        has_visible_participants: bool,
+        is_selected: bool,
+        cx: &mut ViewContext<Self>,
+    ) -> impl IntoElement {
+        let manageable_channel_id = ActiveCall::global(cx).read(cx).room().and_then(|room| {
+            let room = room.read(cx);
+            if room.local_participant_is_admin() {
+                room.channel_id()
+            } else {
+                None
+            }
+        });
+
+        ListItem::new("guest_count")
+            .selected(is_selected)
+            .start_slot(
+                h_stack()
+                    .gap_1()
+                    .child(render_tree_branch(!has_visible_participants, cx))
+                    .child(""),
+            )
+            .child(Label::new(if count == 1 {
+                format!("{} guest", count)
+            } else {
+                format!("{} guests", count)
+            }))
+            .when_some(manageable_channel_id, |el, channel_id| {
+                el.tooltip(move |cx| Tooltip::text("Manage Members", cx))
+                    .on_click(cx.listener(move |this, _, cx| this.manage_members(channel_id, cx)))
+            })
+    }
+
     fn has_subchannels(&self, ix: usize) -> bool {
         self.entries.get(ix).map_or(false, |entry| {
             if let ListEntry::Channel { has_children, .. } = entry {
@@ -1180,6 +1242,18 @@ impl CollabPanel {
                             });
                         }
                     }
+                    ListEntry::GuestCount { .. } => {
+                        let Some(room) = ActiveCall::global(cx).read(cx).room() else {
+                            return;
+                        };
+                        let room = room.read(cx);
+                        let Some(channel_id) = room.channel_id() else {
+                            return;
+                        };
+                        if room.local_participant_is_admin() {
+                            self.manage_members(channel_id, cx)
+                        }
+                    }
                     ListEntry::Channel { channel, .. } => {
                         let is_active = maybe!({
                             let call_channel = ActiveCall::global(cx)
@@ -1735,6 +1809,12 @@ impl CollabPanel {
             ListEntry::ParticipantScreen { peer_id, is_last } => self
                 .render_participant_screen(*peer_id, *is_last, is_selected, cx)
                 .into_any_element(),
+            ListEntry::GuestCount {
+                count,
+                has_visible_participants,
+            } => self
+                .render_guest_count(*count, *has_visible_participants, is_selected, cx)
+                .into_any_element(),
             ListEntry::ChannelNotes { channel_id } => self
                 .render_channel_notes(*channel_id, is_selected, cx)
                 .into_any_element(),
@@ -1766,7 +1846,7 @@ impl CollabPanel {
     ) -> impl IntoElement {
         let settings = ThemeSettings::get_global(cx);
         let text_style = TextStyle {
-            color: if editor.read(cx).read_only() {
+            color: if editor.read(cx).read_only(cx) {
                 cx.theme().colors().text_disabled
             } else {
                 cx.theme().colors().text
@@ -2538,6 +2618,11 @@ impl PartialEq for ListEntry {
                     return true;
                 }
             }
+            ListEntry::GuestCount { .. } => {
+                if let ListEntry::GuestCount { .. } = other {
+                    return true;
+                }
+            }
         }
         false
     }

crates/collab_ui/src/collab_panel/channel_modal.rs πŸ”—

@@ -162,8 +162,7 @@ impl Render for ChannelModal {
                 v_stack()
                     .px_2()
                     .py_1()
-                    .rounded_t(px(8.))
-                    .bg(cx.theme().colors().element_background)
+                    .gap_2()
                     .child(
                         h_stack()
                             .w_px()
@@ -175,7 +174,9 @@ impl Render for ChannelModal {
                     .child(
                         h_stack()
                             .w_full()
+                            .h(rems(22. / 16.))
                             .justify_between()
+                            .line_height(rems(1.25))
                             .child(
                                 h_stack()
                                     .gap_2()
@@ -190,38 +191,54 @@ impl Render for ChannelModal {
                                         )
                                         .on_click(cx.listener(Self::set_channel_visiblity)),
                                     )
-                                    .child(Label::new("Public")),
+                                    .child(Label::new("Public").size(LabelSize::Small)),
                             )
-                            .children(if visibility == ChannelVisibility::Public {
-                                Some(Button::new("copy-link", "Copy Link").on_click(cx.listener(
-                                    move |this, _, cx| {
-                                        if let Some(channel) =
-                                            this.channel_store.read(cx).channel_for_id(channel_id)
-                                        {
-                                            let item = ClipboardItem::new(channel.link());
-                                            cx.write_to_clipboard(item);
-                                        }
-                                    },
-                                )))
-                            } else {
-                                None
-                            }),
+                            .children(
+                                Some(
+                                    Button::new("copy-link", "Copy Link")
+                                        .label_size(LabelSize::Small)
+                                        .on_click(cx.listener(move |this, _, cx| {
+                                            if let Some(channel) = this
+                                                .channel_store
+                                                .read(cx)
+                                                .channel_for_id(channel_id)
+                                            {
+                                                let item = ClipboardItem::new(channel.link());
+                                                cx.write_to_clipboard(item);
+                                            }
+                                        })),
+                                )
+                                .filter(|_| visibility == ChannelVisibility::Public),
+                            ),
                     )
                     .child(
-                        div()
-                            .w_full()
-                            .flex()
-                            .flex_row()
+                        h_stack()
                             .child(
-                                Button::new("manage-members", "Manage Members")
-                                    .selected(mode == Mode::ManageMembers)
+                                div()
+                                    .id("manage-members")
+                                    .px_2()
+                                    .py_1()
+                                    .cursor_pointer()
+                                    .border_b_2()
+                                    .when(mode == Mode::ManageMembers, |this| {
+                                        this.border_color(cx.theme().colors().border)
+                                    })
+                                    .child(Label::new("Manage Members"))
                                     .on_click(cx.listener(|this, _, cx| {
                                         this.set_mode(Mode::ManageMembers, cx);
                                     })),
                             )
                             .child(
-                                Button::new("invite-members", "Invite Members")
-                                    .selected(mode == Mode::InviteMembers)
+                                div()
+                                    .id("invite-members")
+                                    .px_2()
+                                    .py_1()
+                                    .cursor_pointer()
+                                    .border_b_2()
+                                    .when(mode == Mode::InviteMembers, |this| {
+                                        this.border_color(cx.theme().colors().border)
+                                    })
+                                    .child(Label::new("Invite Members"))
                                     .on_click(cx.listener(|this, _, cx| {
                                         this.set_mode(Mode::InviteMembers, cx);
                                     })),

crates/collab_ui/src/collab_titlebar_item.rs πŸ”—

@@ -10,11 +10,12 @@ use gpui::{
 };
 use project::{Project, RepositoryEntry};
 use recent_projects::RecentProjects;
+use rpc::proto;
 use std::sync::Arc;
 use theme::{ActiveTheme, PlayerColors};
 use ui::{
     h_stack, popover_menu, prelude::*, Avatar, Button, ButtonLike, ButtonStyle, ContextMenu, Icon,
-    IconButton, IconElement, Tooltip,
+    IconButton, IconElement, TintColor, Tooltip,
 };
 use util::ResultExt;
 use vcs_menu::{build_branch_list, BranchList, OpenRecent as ToggleVcsMenu};
@@ -175,14 +176,17 @@ impl Render for CollabTitlebarItem {
                         let is_muted = room.is_muted(cx);
                         let is_deafened = room.is_deafened().unwrap_or(false);
                         let is_screen_sharing = room.is_screen_sharing();
+                        let read_only = room.read_only();
 
-                        this.when(is_local, |this| {
+                        this.when(is_local && !read_only, |this| {
                             this.child(
                                 Button::new(
                                     "toggle_sharing",
                                     if is_shared { "Unshare" } else { "Share" },
                                 )
                                 .style(ButtonStyle::Subtle)
+                                .selected_style(ButtonStyle::Tinted(TintColor::Accent))
+                                .selected(is_shared)
                                 .label_size(LabelSize::Small)
                                 .on_click(cx.listener(
                                     move |this, _, cx| {
@@ -205,20 +209,23 @@ impl Render for CollabTitlebarItem {
                                         .detach_and_log_err(cx);
                                 }),
                         )
-                        .child(
-                            IconButton::new(
-                                "mute-microphone",
-                                if is_muted {
-                                    ui::Icon::MicMute
-                                } else {
-                                    ui::Icon::Mic
-                                },
+                        .when(!read_only, |this| {
+                            this.child(
+                                IconButton::new(
+                                    "mute-microphone",
+                                    if is_muted {
+                                        ui::Icon::MicMute
+                                    } else {
+                                        ui::Icon::Mic
+                                    },
+                                )
+                                .style(ButtonStyle::Subtle)
+                                .icon_size(IconSize::Small)
+                                .selected(is_muted)
+                                .selected_style(ButtonStyle::Tinted(TintColor::Negative))
+                                .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
                             )
-                            .style(ButtonStyle::Subtle)
-                            .icon_size(IconSize::Small)
-                            .selected(is_muted)
-                            .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
-                        )
+                        })
                         .child(
                             IconButton::new(
                                 "mute-sound",
@@ -229,22 +236,35 @@ impl Render for CollabTitlebarItem {
                                 },
                             )
                             .style(ButtonStyle::Subtle)
+                            .selected_style(ButtonStyle::Tinted(TintColor::Negative))
                             .icon_size(IconSize::Small)
                             .selected(is_deafened)
                             .tooltip(move |cx| {
-                                Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx)
+                                if !read_only {
+                                    Tooltip::with_meta(
+                                        "Deafen Audio",
+                                        None,
+                                        "Mic will be muted",
+                                        cx,
+                                    )
+                                } else {
+                                    Tooltip::text("Deafen Audio", cx)
+                                }
                             })
-                            .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
-                        )
-                        .child(
-                            IconButton::new("screen-share", ui::Icon::Screen)
-                                .style(ButtonStyle::Subtle)
-                                .icon_size(IconSize::Small)
-                                .selected(is_screen_sharing)
-                                .on_click(move |_, cx| {
-                                    crate::toggle_screen_sharing(&Default::default(), cx)
-                                }),
+                            .on_click(move |_, cx| crate::toggle_deafen(&Default::default(), cx)),
                         )
+                        .when(!read_only, |this| {
+                            this.child(
+                                IconButton::new("screen-share", ui::Icon::Screen)
+                                    .style(ButtonStyle::Subtle)
+                                    .icon_size(IconSize::Small)
+                                    .selected(is_screen_sharing)
+                                    .selected_style(ButtonStyle::Tinted(TintColor::Accent))
+                                    .on_click(move |_, cx| {
+                                        crate::toggle_screen_sharing(&Default::default(), cx)
+                                    }),
+                            )
+                        })
                     })
                     .map(|el| {
                         let status = self.client.status();
@@ -409,6 +429,10 @@ impl CollabTitlebarItem {
         current_user: &Arc<User>,
         cx: &ViewContext<Self>,
     ) -> Option<FacePile> {
+        if room.role_for_user(user.id) == Some(proto::ChannelRole::Guest) {
+            return None;
+        }
+
         let followers = project_id.map_or(&[] as &[_], |id| room.followers_for(peer_id, id));
 
         let pile = FacePile::default()
@@ -504,8 +528,7 @@ impl CollabTitlebarItem {
             | client::Status::ReconnectionError { .. } => Some(
                 div()
                     .id("disconnected")
-                    .bg(gpui::red()) // todo!() @nate
-                    .child(IconElement::new(Icon::Disconnected))
+                    .child(IconElement::new(Icon::Disconnected).size(IconSize::Small))
                     .tooltip(|cx| Tooltip::text("Disconnected", cx))
                     .into_any_element(),
             ),
@@ -522,9 +545,9 @@ impl CollabTitlebarItem {
                 };
 
                 Some(
-                    div()
-                        .bg(gpui::red()) // todo!() @nate
-                        .child(Button::new("connection-status", label).on_click(|_, cx| {
+                    Button::new("connection-status", label)
+                        .label_size(LabelSize::Small)
+                        .on_click(|_, cx| {
                             if let Some(auto_updater) = auto_update::AutoUpdater::get(cx) {
                                 if auto_updater.read(cx).status() == AutoUpdateStatus::Updated {
                                     workspace::restart(&Default::default(), cx);
@@ -532,7 +555,7 @@ impl CollabTitlebarItem {
                                 }
                             }
                             auto_update::check(&Default::default(), cx);
-                        }))
+                        })
                         .into_any_element(),
                 )
             }
@@ -542,16 +565,18 @@ impl CollabTitlebarItem {
 
     pub fn render_sign_in_button(&mut self, _: &mut ViewContext<Self>) -> Button {
         let client = self.client.clone();
-        Button::new("sign_in", "Sign in").on_click(move |_, cx| {
-            let client = client.clone();
-            cx.spawn(move |mut cx| async move {
-                client
-                    .authenticate_and_connect(true, &cx)
-                    .await
-                    .notify_async_err(&mut cx);
+        Button::new("sign_in", "Sign in")
+            .label_size(LabelSize::Small)
+            .on_click(move |_, cx| {
+                let client = client.clone();
+                cx.spawn(move |mut cx| async move {
+                    client
+                        .authenticate_and_connect(true, &cx)
+                        .await
+                        .notify_async_err(&mut cx);
+                })
+                .detach();
             })
-            .detach();
-        })
     }
 
     pub fn render_user_menu_button(&mut self, cx: &mut ViewContext<Self>) -> impl Element {

crates/diagnostics/src/diagnostics.rs πŸ”—

@@ -151,7 +151,12 @@ impl ProjectDiagnosticsEditor {
         let focus_in_subscription =
             cx.on_focus_in(&focus_handle, |diagnostics, cx| diagnostics.focus_in(cx));
 
-        let excerpts = cx.new_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id()));
+        let excerpts = cx.new_model(|cx| {
+            MultiBuffer::new(
+                project_handle.read(cx).replica_id(),
+                project_handle.read(cx).capability(),
+            )
+        });
         let editor = cx.new_view(|cx| {
             let mut editor =
                 Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), cx);
@@ -1572,6 +1577,7 @@ mod tests {
             workspace::init_settings(cx);
             Project::init_settings(cx);
             crate::init(cx);
+            editor::init(cx);
         });
     }
 

crates/editor/src/editor.rs πŸ”—

@@ -54,10 +54,10 @@ use itertools::Itertools;
 pub use language::{char_kind, CharKind};
 use language::{
     language_settings::{self, all_language_settings, InlayHintSettings},
-    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel,
-    Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language,
-    LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection, SelectionGoal,
-    TransactionId,
+    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CodeAction,
+    CodeLabel, Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize,
+    Language, LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection,
+    SelectionGoal, TransactionId,
 };
 
 use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
@@ -2049,8 +2049,8 @@ impl Editor {
         }
     }
 
-    pub fn read_only(&self) -> bool {
-        self.read_only
+    pub fn read_only(&self, cx: &AppContext) -> bool {
+        self.read_only || self.buffer.read(cx).read_only()
     }
 
     pub fn set_read_only(&mut self, read_only: bool) {
@@ -2199,7 +2199,7 @@ impl Editor {
         S: ToOffset,
         T: Into<Arc<str>>,
     {
-        if self.read_only {
+        if self.read_only(cx) {
             return;
         }
 
@@ -2213,7 +2213,7 @@ impl Editor {
         S: ToOffset,
         T: Into<Arc<str>>,
     {
-        if self.read_only {
+        if self.read_only(cx) {
             return;
         }
 
@@ -2232,7 +2232,7 @@ impl Editor {
         S: ToOffset,
         T: Into<Arc<str>>,
     {
-        if self.read_only {
+        if self.read_only(cx) {
             return;
         }
 
@@ -2596,7 +2596,7 @@ impl Editor {
     pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
         let text: Arc<str> = text.into();
 
-        if self.read_only {
+        if self.read_only(cx) {
             return;
         }
 
@@ -3049,7 +3049,7 @@ impl Editor {
         autoindent_mode: Option<AutoindentMode>,
         cx: &mut ViewContext<Self>,
     ) {
-        if self.read_only {
+        if self.read_only(cx) {
             return;
         }
 
@@ -3786,7 +3786,8 @@ impl Editor {
 
         let mut ranges_to_highlight = Vec::new();
         let excerpt_buffer = cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
+            let mut multibuffer =
+                MultiBuffer::new(replica_id, Capability::ReadWrite).with_title(title);
             for (buffer_handle, transaction) in &entries {
                 let buffer = buffer_handle.read(cx);
                 ranges_to_highlight.extend(
@@ -7491,9 +7492,10 @@ impl Editor {
         locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
         let mut locations = locations.into_iter().peekable();
         let mut ranges_to_highlight = Vec::new();
+        let capability = workspace.project().read(cx).capability();
 
         let excerpt_buffer = cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(replica_id);
+            let mut multibuffer = MultiBuffer::new(replica_id, capability);
             while let Some(location) = locations.next() {
                 let buffer = location.buffer.read(cx);
                 let mut ranges_for_buffer = Vec::new();
@@ -8608,7 +8610,8 @@ impl Editor {
     }
 
     pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
-        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
+        (self.read_only(cx) || self.blink_manager.read(cx).visible())
+            && self.focus_handle.is_focused(cx)
     }
 
     fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {

crates/editor/src/editor_tests.rs πŸ”—

@@ -17,8 +17,9 @@ use gpui::{
 use indoc::indoc;
 use language::{
     language_settings::{AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent},
-    BracketPairConfig, FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry,
-    Override, Point,
+    BracketPairConfig,
+    Capability::ReadWrite,
+    FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry, Override, Point,
 };
 use parking_lot::Mutex;
 use project::project_settings::{LspSettings, ProjectSettings};
@@ -2355,7 +2356,7 @@ fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) {
             .with_language(rust_language, cx)
     });
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         multibuffer.push_excerpts(
             toml_buffer.clone(),
             [ExcerptRange {
@@ -6019,7 +6020,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
 
     let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         multibuffer.push_excerpts(
             buffer.clone(),
             [
@@ -6103,7 +6104,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
     });
     let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), initial_text));
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
         multibuffer
     });
@@ -6162,7 +6163,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
     let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
     let mut excerpt1_id = None;
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         excerpt1_id = multibuffer
             .push_excerpts(
                 buffer.clone(),
@@ -6247,7 +6248,7 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
     let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
     let mut excerpt1_id = None;
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         excerpt1_id = multibuffer
             .push_excerpts(
                 buffer.clone(),
@@ -6636,7 +6637,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
     let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
 
     let leader = pane.update(cx, |_, cx| {
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, ReadWrite));
         cx.new_view(|cx| build_editor(multibuffer.clone(), cx))
     });
 
@@ -7425,7 +7426,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T
     let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n"));
     let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n"));
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         multibuffer.push_excerpts(
             buffer_1.clone(),
             [ExcerptRange {
@@ -7552,7 +7553,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui
         .unwrap();
 
     let multibuffer = cx.new_model(|cx| {
-        let mut multibuffer = MultiBuffer::new(0);
+        let mut multibuffer = MultiBuffer::new(0, ReadWrite);
         multibuffer.push_excerpts(
             private_buffer.clone(),
             [ExcerptRange {

crates/editor/src/element.rs πŸ”—

@@ -1910,7 +1910,13 @@ impl EditorElement {
                     layouts.push(layout);
                 }
 
-                selections.push((style.local_player, layouts));
+                let player = if editor.read_only(cx) {
+                    cx.theme().players().read_only()
+                } else {
+                    style.local_player
+                };
+
+                selections.push((player, layouts));
             }
 
             if let Some(collaboration_hub) = &editor.collaboration_hub {

crates/editor/src/git.rs πŸ”—

@@ -93,6 +93,7 @@ mod tests {
     use crate::editor_tests::init_test;
     use crate::Point;
     use gpui::{Context, TestAppContext};
+    use language::Capability::ReadWrite;
     use multi_buffer::{ExcerptRange, MultiBuffer};
     use project::{FakeFs, Project};
     use unindent::Unindent;
@@ -183,7 +184,7 @@ mod tests {
         cx.background_executor.run_until_parked();
 
         let multibuffer = cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(0);
+            let mut multibuffer = MultiBuffer::new(0, ReadWrite);
             multibuffer.push_excerpts(
                 buffer_1.clone(),
                 [

crates/editor/src/hover_popover.rs πŸ”—

@@ -515,34 +515,28 @@ impl DiagnosticPopover {
         };
 
         struct DiagnosticColors {
-            pub text: Hsla,
             pub background: Hsla,
             pub border: Hsla,
         }
 
         let diagnostic_colors = match self.local_diagnostic.diagnostic.severity {
             DiagnosticSeverity::ERROR => DiagnosticColors {
-                text: style.status.error,
                 background: style.status.error_background,
                 border: style.status.error_border,
             },
             DiagnosticSeverity::WARNING => DiagnosticColors {
-                text: style.status.warning,
                 background: style.status.warning_background,
                 border: style.status.warning_border,
             },
             DiagnosticSeverity::INFORMATION => DiagnosticColors {
-                text: style.status.info,
                 background: style.status.info_background,
                 border: style.status.info_border,
             },
             DiagnosticSeverity::HINT => DiagnosticColors {
-                text: style.status.hint,
                 background: style.status.hint_background,
                 border: style.status.hint_border,
             },
             _ => DiagnosticColors {
-                text: style.status.ignored,
                 background: style.status.ignored_background,
                 border: style.status.ignored_border,
             },
@@ -554,7 +548,7 @@ impl DiagnosticPopover {
             .px_2()
             .py_1()
             .bg(diagnostic_colors.background)
-            .text_color(diagnostic_colors.text)
+            .text_color(style.text.color)
             .border_1()
             .border_color(diagnostic_colors.border)
             .rounded_md()

crates/editor/src/inlay_hint_cache.rs πŸ”—

@@ -1206,7 +1206,8 @@ pub mod tests {
     use gpui::{Context, TestAppContext, WindowHandle};
     use itertools::Itertools;
     use language::{
-        language_settings::AllLanguageSettingsContent, FakeLspAdapter, Language, LanguageConfig,
+        language_settings::AllLanguageSettingsContent, Capability, FakeLspAdapter, Language,
+        LanguageConfig,
     };
     use lsp::FakeLanguageServer;
     use parking_lot::Mutex;
@@ -2459,7 +2460,7 @@ pub mod tests {
             .await
             .unwrap();
         let multibuffer = cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(0);
+            let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
             multibuffer.push_excerpts(
                 buffer_1.clone(),
                 [
@@ -2798,7 +2799,7 @@ pub mod tests {
             })
             .await
             .unwrap();
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let (buffer_1_excerpts, buffer_2_excerpts) = multibuffer.update(cx, |multibuffer, cx| {
             let buffer_1_excerpts = multibuffer.push_excerpts(
                 buffer_1.clone(),

crates/editor/src/items.rs πŸ”—

@@ -15,9 +15,11 @@ use language::{
     proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, OffsetRangeExt,
     Point, SelectionGoal,
 };
+use project::repository::GitFileStatus;
 use project::{search::SearchQuery, FormatTrigger, Item as _, Project, ProjectPath};
 use rpc::proto::{self, update_view, PeerId};
 use settings::Settings;
+use workspace::item::ItemSettings;
 
 use std::fmt::Write;
 use std::{
@@ -29,7 +31,7 @@ use std::{
     sync::Arc,
 };
 use text::Selection;
-use theme::{ActiveTheme, Theme};
+use theme::Theme;
 use ui::{h_stack, prelude::*, Label};
 use util::{paths::PathExt, paths::FILE_ROW_COLUMN_DELIMITER, ResultExt, TryFutureExt};
 use workspace::{
@@ -101,7 +103,8 @@ impl FollowableItem for Editor {
                         if state.singleton && buffers.len() == 1 {
                             multibuffer = MultiBuffer::singleton(buffers.pop().unwrap(), cx)
                         } else {
-                            multibuffer = MultiBuffer::new(replica_id);
+                            multibuffer =
+                                MultiBuffer::new(replica_id, project.read(cx).capability());
                             let mut excerpts = state.excerpts.into_iter().peekable();
                             while let Some(excerpt) = excerpts.peek() {
                                 let buffer_id = excerpt.buffer_id;
@@ -579,7 +582,28 @@ impl Item for Editor {
     }
 
     fn tab_content(&self, detail: Option<usize>, selected: bool, cx: &WindowContext) -> AnyElement {
-        let _theme = cx.theme();
+        let git_status = if ItemSettings::get_global(cx).git_status {
+            self.buffer()
+                .read(cx)
+                .as_singleton()
+                .and_then(|buffer| buffer.read(cx).project_path(cx))
+                .and_then(|path| self.project.as_ref()?.read(cx).entry_for_path(&path, cx))
+                .and_then(|entry| entry.git_status())
+        } else {
+            None
+        };
+        let label_color = match git_status {
+            Some(GitFileStatus::Added) => Color::Created,
+            Some(GitFileStatus::Modified) => Color::Modified,
+            Some(GitFileStatus::Conflict) => Color::Conflict,
+            None => {
+                if selected {
+                    Color::Default
+                } else {
+                    Color::Muted
+                }
+            }
+        };
 
         let description = detail.and_then(|detail| {
             let path = path_for_buffer(&self.buffer, detail, false, cx)?;
@@ -595,11 +619,7 @@ impl Item for Editor {
 
         h_stack()
             .gap_2()
-            .child(Label::new(self.title(cx).to_string()).color(if selected {
-                Color::Default
-            } else {
-                Color::Muted
-            }))
+            .child(Label::new(self.title(cx).to_string()).color(label_color))
             .when_some(description, |this, description| {
                 this.child(
                     Label::new(description)
@@ -930,10 +930,7 @@ mod tests {
                 fn do_work() { Β«testΒ»(); }
             "});
 
-        // Deactivating the window dismisses the highlight
-        cx.update_workspace(|workspace, cx| {
-            workspace.on_window_activation_changed(cx);
-        });
+        cx.cx.cx.deactivate_window();
         cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
                 fn test() { do_work(); }
                 fn do_work() { test(); }

crates/editor/src/movement.rs πŸ”—

@@ -461,6 +461,7 @@ mod tests {
         Buffer, DisplayMap, ExcerptRange, InlayId, MultiBuffer,
     };
     use gpui::{font, Context as _};
+    use language::Capability;
     use project::Project;
     use settings::SettingsStore;
     use util::post_inc;
@@ -766,7 +767,7 @@ mod tests {
             let buffer =
                 cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abc\ndefg\nhijkl\nmn"));
             let multibuffer = cx.new_model(|cx| {
-                let mut multibuffer = MultiBuffer::new(0);
+                let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
                 multibuffer.push_excerpts(
                     buffer.clone(),
                     [

crates/feedback/src/feedback_modal.rs πŸ”—

@@ -17,7 +17,7 @@ use regex::Regex;
 use serde_derive::Serialize;
 use ui::{prelude::*, Button, ButtonStyle, IconPosition, Tooltip};
 use util::ResultExt;
-use workspace::{ModalView, Workspace};
+use workspace::{ModalView, Toast, Workspace};
 
 use crate::{system_specs::SystemSpecs, GiveFeedback, OpenZedCommunityRepo};
 
@@ -125,6 +125,20 @@ impl FeedbackModal {
                 .language_for_name("Markdown");
 
             let project = workspace.project().clone();
+            let is_local_project = project.read(cx).is_local();
+
+            if !is_local_project {
+                const TOAST_ID: usize = 0xdeadbeef;
+
+                workspace.show_toast(
+                    Toast::new(
+                        TOAST_ID,
+                        "You can only submit feedback in your own project.",
+                    ),
+                    cx,
+                );
+                return;
+            }
 
             cx.spawn(|workspace, mut cx| async move {
                 let markdown = markdown.await.log_err();

crates/gpui/Cargo.toml πŸ”—

@@ -18,8 +18,7 @@ collections = { path = "../collections" }
 gpui_macros = { path = "../gpui_macros" }
 util = { path = "../util" }
 sum_tree = { path = "../sum_tree" }
-sqlez = { path = "../sqlez" }
-async-task = "4.0.3"
+async-task = "4.7"
 backtrace = { version = "0.3", optional = true }
 ctor.workspace = true
 linkme = "0.3"

crates/gpui/src/app/entity_map.rs πŸ”—

@@ -16,6 +16,9 @@ use std::{
     thread::panicking,
 };
 
+#[cfg(any(test, feature = "test-support"))]
+use collections::HashMap;
+
 slotmap::new_key_type! { pub struct EntityId; }
 
 impl EntityId {
@@ -38,6 +41,8 @@ pub(crate) struct EntityMap {
 struct EntityRefCounts {
     counts: SlotMap<EntityId, AtomicUsize>,
     dropped_entity_ids: Vec<EntityId>,
+    #[cfg(any(test, feature = "test-support"))]
+    leak_detector: LeakDetector,
 }
 
 impl EntityMap {
@@ -47,6 +52,11 @@ impl EntityMap {
             ref_counts: Arc::new(RwLock::new(EntityRefCounts {
                 counts: SlotMap::with_key(),
                 dropped_entity_ids: Vec::new(),
+                #[cfg(any(test, feature = "test-support"))]
+                leak_detector: LeakDetector {
+                    next_handle_id: 0,
+                    entity_handles: HashMap::default(),
+                },
             })),
         }
     }
@@ -156,6 +166,8 @@ pub struct AnyModel {
     pub(crate) entity_id: EntityId,
     pub(crate) entity_type: TypeId,
     entity_map: Weak<RwLock<EntityRefCounts>>,
+    #[cfg(any(test, feature = "test-support"))]
+    handle_id: HandleId,
 }
 
 impl AnyModel {
@@ -163,7 +175,14 @@ impl AnyModel {
         Self {
             entity_id: id,
             entity_type,
-            entity_map,
+            entity_map: entity_map.clone(),
+            #[cfg(any(test, feature = "test-support"))]
+            handle_id: entity_map
+                .upgrade()
+                .unwrap()
+                .write()
+                .leak_detector
+                .handle_created(id),
         }
     }
 
@@ -207,11 +226,20 @@ impl Clone for AnyModel {
             assert_ne!(prev_count, 0, "Detected over-release of a model.");
         }
 
-        Self {
+        let this = Self {
             entity_id: self.entity_id,
             entity_type: self.entity_type,
             entity_map: self.entity_map.clone(),
-        }
+            #[cfg(any(test, feature = "test-support"))]
+            handle_id: self
+                .entity_map
+                .upgrade()
+                .unwrap()
+                .write()
+                .leak_detector
+                .handle_created(self.entity_id),
+        };
+        this
     }
 }
 
@@ -231,6 +259,14 @@ impl Drop for AnyModel {
                 entity_map.dropped_entity_ids.push(self.entity_id);
             }
         }
+
+        #[cfg(any(test, feature = "test-support"))]
+        if let Some(entity_map) = self.entity_map.upgrade() {
+            entity_map
+                .write()
+                .leak_detector
+                .handle_dropped(self.entity_id, self.handle_id)
+        }
     }
 }
 
@@ -423,13 +459,43 @@ impl AnyWeakModel {
             return None;
         }
         ref_count.fetch_add(1, SeqCst);
+        drop(ref_counts);
 
         Some(AnyModel {
             entity_id: self.entity_id,
             entity_type: self.entity_type,
             entity_map: self.entity_ref_counts.clone(),
+            #[cfg(any(test, feature = "test-support"))]
+            handle_id: self
+                .entity_ref_counts
+                .upgrade()
+                .unwrap()
+                .write()
+                .leak_detector
+                .handle_created(self.entity_id),
         })
     }
+
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn assert_dropped(&self) {
+        self.entity_ref_counts
+            .upgrade()
+            .unwrap()
+            .write()
+            .leak_detector
+            .assert_dropped(self.entity_id);
+
+        if self
+            .entity_ref_counts
+            .upgrade()
+            .and_then(|ref_counts| Some(ref_counts.read().counts.get(self.entity_id)?.load(SeqCst)))
+            .is_some()
+        {
+            panic!(
+                "entity was recently dropped but resources are retained until the end of the effect cycle."
+            )
+        }
+    }
 }
 
 impl<T> From<WeakModel<T>> for AnyWeakModel {
@@ -534,6 +600,59 @@ impl<T> PartialEq<Model<T>> for WeakModel<T> {
     }
 }
 
+#[cfg(any(test, feature = "test-support"))]
+lazy_static::lazy_static! {
+    static ref LEAK_BACKTRACE: bool =
+        std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
+}
+
+#[cfg(any(test, feature = "test-support"))]
+#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
+pub struct HandleId {
+    id: u64, // id of the handle itself, not the pointed at object
+}
+
+#[cfg(any(test, feature = "test-support"))]
+pub struct LeakDetector {
+    next_handle_id: u64,
+    entity_handles: HashMap<EntityId, HashMap<HandleId, Option<backtrace::Backtrace>>>,
+}
+
+#[cfg(any(test, feature = "test-support"))]
+impl LeakDetector {
+    #[track_caller]
+    pub fn handle_created(&mut self, entity_id: EntityId) -> HandleId {
+        let id = util::post_inc(&mut self.next_handle_id);
+        let handle_id = HandleId { id };
+        let handles = self.entity_handles.entry(entity_id).or_default();
+        handles.insert(
+            handle_id,
+            LEAK_BACKTRACE.then(|| backtrace::Backtrace::new_unresolved()),
+        );
+        handle_id
+    }
+
+    pub fn handle_dropped(&mut self, entity_id: EntityId, handle_id: HandleId) {
+        let handles = self.entity_handles.entry(entity_id).or_default();
+        handles.remove(&handle_id);
+    }
+
+    pub fn assert_dropped(&mut self, entity_id: EntityId) {
+        let handles = self.entity_handles.entry(entity_id).or_default();
+        if !handles.is_empty() {
+            for (_, backtrace) in handles {
+                if let Some(mut backtrace) = backtrace.take() {
+                    backtrace.resolve();
+                    eprintln!("Leaked handle: {:#?}", backtrace);
+                } else {
+                    eprintln!("Leaked handle: export LEAK_BACKTRACE to find allocation site");
+                }
+            }
+            panic!();
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use crate::EntityMap;

crates/gpui/src/app/test_context.rs πŸ”—

@@ -1,14 +1,13 @@
 use crate::{
     div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
-    BackgroundExecutor, Bounds, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
-    InputEvent, IntoElement, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
-    PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
-    TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext,
-    WindowHandle, WindowOptions,
+    BackgroundExecutor, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
+    IntoElement, Keystroke, Model, ModelContext, Pixels, Platform, Render, Result, Size, Task,
+    TestDispatcher, TestPlatform, TestWindow, TextSystem, View, ViewContext, VisualContext,
+    WindowContext, WindowHandle, WindowOptions,
 };
 use anyhow::{anyhow, bail};
 use futures::{Stream, StreamExt};
-use std::{future::Future, mem, ops::Deref, rc::Rc, sync::Arc, time::Duration};
+use std::{future::Future, ops::Deref, rc::Rc, sync::Arc, time::Duration};
 
 #[derive(Clone)]
 pub struct TestAppContext {
@@ -185,42 +184,7 @@ impl TestAppContext {
     }
 
     pub fn simulate_window_resize(&self, window_handle: AnyWindowHandle, size: Size<Pixels>) {
-        let (mut handlers, scale_factor) = self
-            .app
-            .borrow_mut()
-            .update_window(window_handle, |_, cx| {
-                let platform_window = cx.window.platform_window.as_test().unwrap();
-                let scale_factor = platform_window.scale_factor();
-                match &mut platform_window.bounds {
-                    WindowBounds::Fullscreen | WindowBounds::Maximized => {
-                        platform_window.bounds = WindowBounds::Fixed(Bounds {
-                            origin: Point::default(),
-                            size: size.map(|pixels| f64::from(pixels).into()),
-                        });
-                    }
-                    WindowBounds::Fixed(bounds) => {
-                        bounds.size = size.map(|pixels| f64::from(pixels).into());
-                    }
-                }
-
-                (
-                    mem::take(&mut platform_window.handlers.lock().resize),
-                    scale_factor,
-                )
-            })
-            .unwrap();
-
-        for handler in &mut handlers {
-            handler(size, scale_factor);
-        }
-
-        self.app
-            .borrow_mut()
-            .update_window(window_handle, |_, cx| {
-                let platform_window = cx.window.platform_window.as_test().unwrap();
-                platform_window.handlers.lock().resize = handlers;
-            })
-            .unwrap();
+        self.test_window(window_handle).simulate_resize(size);
     }
 
     pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
@@ -313,41 +277,22 @@ impl TestAppContext {
         keystroke: Keystroke,
         is_held: bool,
     ) {
-        let keystroke2 = keystroke.clone();
-        let handled = window
-            .update(self, |_, cx| {
-                cx.dispatch_event(InputEvent::KeyDown(KeyDownEvent { keystroke, is_held }))
-            })
-            .is_ok_and(|handled| handled);
-        if handled {
-            return;
-        }
-
-        let input_handler = self.update_test_window(window, |window| window.input_handler.clone());
-        let Some(input_handler) = input_handler else {
-            panic!(
-                "dispatch_keystroke {:?} failed to dispatch action or input",
-                &keystroke2
-            );
-        };
-        let text = keystroke2.ime_key.unwrap_or(keystroke2.key);
-        input_handler.lock().replace_text_in_range(None, &text);
+        self.test_window(window)
+            .simulate_keystroke(keystroke, is_held)
     }
 
-    pub fn update_test_window<R>(
-        &mut self,
-        window: AnyWindowHandle,
-        f: impl FnOnce(&mut TestWindow) -> R,
-    ) -> R {
-        window
-            .update(self, |_, cx| {
-                f(cx.window
-                    .platform_window
-                    .as_any_mut()
-                    .downcast_mut::<TestWindow>()
-                    .unwrap())
-            })
+    pub fn test_window(&self, window: AnyWindowHandle) -> TestWindow {
+        self.app
+            .borrow_mut()
+            .windows
+            .get_mut(window.id)
+            .unwrap()
+            .as_mut()
             .unwrap()
+            .platform_window
+            .as_test()
+            .unwrap()
+            .clone()
     }
 
     pub fn notifications<T: 'static>(&mut self, entity: &impl Entity<T>) -> impl Stream<Item = ()> {
@@ -563,11 +508,7 @@ impl<'a> VisualTestContext<'a> {
     }
 
     pub fn window_title(&mut self) -> Option<String> {
-        self.cx
-            .update_window(self.window, |_, cx| {
-                cx.window.platform_window.as_test().unwrap().title.clone()
-            })
-            .unwrap()
+        self.cx.test_window(self.window).0.lock().title.clone()
     }
 
     pub fn simulate_keystrokes(&mut self, keystrokes: &str) {
@@ -578,37 +519,11 @@ impl<'a> VisualTestContext<'a> {
         self.cx.simulate_input(self.window, input)
     }
 
-    pub fn simulate_activation(&mut self) {
-        self.simulate_window_events(&mut |handlers| {
-            handlers
-                .active_status_change
-                .iter_mut()
-                .for_each(|f| f(true));
-        })
-    }
-
-    pub fn simulate_deactivation(&mut self) {
-        self.simulate_window_events(&mut |handlers| {
-            handlers
-                .active_status_change
-                .iter_mut()
-                .for_each(|f| f(false));
-        })
-    }
-
-    fn simulate_window_events(&mut self, f: &mut dyn FnMut(&mut TestWindowHandlers)) {
-        let handlers = self
-            .cx
-            .update_window(self.window, |_, cx| {
-                cx.window
-                    .platform_window
-                    .as_test()
-                    .unwrap()
-                    .handlers
-                    .clone()
-            })
-            .unwrap();
-        f(&mut *handlers.lock());
+    pub fn deactivate_window(&mut self) {
+        if Some(self.window) == self.test_platform.active_window() {
+            self.test_platform.set_active_window(None)
+        }
+        self.background_executor.run_until_parked();
     }
 }
 

crates/gpui/src/color.rs πŸ”—

@@ -339,6 +339,15 @@ impl Hsla {
         }
     }
 
+    pub fn grayscale(&self) -> Self {
+        Hsla {
+            h: self.h,
+            s: 0.,
+            l: self.l,
+            a: self.a,
+        }
+    }
+
     /// Fade out the color by a given factor. This factor should be between 0.0 and 1.0.
     /// Where 0.0 will leave the color unchanged, and 1.0 will completely fade out the color.
     pub fn fade_out(&mut self, factor: f32) {

crates/gpui/src/element.rs πŸ”—

@@ -44,8 +44,9 @@ pub trait IntoElement: Sized {
     }
 
     /// Convert into an element, then draw in the current window at the given origin.
-    /// The provided available space is provided to the layout engine to determine the size of the root element.
-    /// Once the element is drawn, its associated element staet is yielded to the given callback.
+    /// The available space argument is provided to the layout engine to determine the size of the
+    // root element.  Once the element is drawn, its associated element state is yielded to the
+    // given callback.
     fn draw_and_update_state<T, R>(
         self,
         origin: Point<Pixels>,

crates/gpui/src/geometry.rs πŸ”—

@@ -31,39 +31,6 @@ pub trait Along {
     fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self;
 }
 
-impl sqlez::bindable::StaticColumnCount for Axis {}
-impl sqlez::bindable::Bind for Axis {
-    fn bind(
-        &self,
-        statement: &sqlez::statement::Statement,
-        start_index: i32,
-    ) -> anyhow::Result<i32> {
-        match self {
-            Axis::Horizontal => "Horizontal",
-            Axis::Vertical => "Vertical",
-        }
-        .bind(statement, start_index)
-    }
-}
-
-impl sqlez::bindable::Column for Axis {
-    fn column(
-        statement: &mut sqlez::statement::Statement,
-        start_index: i32,
-    ) -> anyhow::Result<(Self, i32)> {
-        String::column(statement, start_index).and_then(|(axis_text, next_index)| {
-            Ok((
-                match axis_text.as_str() {
-                    "Horizontal" => Axis::Horizontal,
-                    "Vertical" => Axis::Vertical,
-                    _ => anyhow::bail!("Stored serialized item kind is incorrect"),
-                },
-                next_index,
-            ))
-        })
-    }
-}
-
 /// Describes a location in a 2D cartesian coordinate space.
 ///
 /// It holds two public fields, `x` and `y`, which represent the coordinates in the space.
@@ -2296,18 +2263,6 @@ impl From<f64> for GlobalPixels {
     }
 }
 
-impl sqlez::bindable::StaticColumnCount for GlobalPixels {}
-
-impl sqlez::bindable::Bind for GlobalPixels {
-    fn bind(
-        &self,
-        statement: &sqlez::statement::Statement,
-        start_index: i32,
-    ) -> anyhow::Result<i32> {
-        self.0.bind(statement, start_index)
-    }
-}
-
 /// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with [WindowContext::set_rem_size].
 ///
 /// Rems are used for defining lengths that are scalable and consistent across different UI elements.

crates/gpui/src/interactive.rs πŸ”—

@@ -307,7 +307,10 @@ mod test {
             div().id("testview").child(
                 div()
                     .key_context("parent")
-                    .on_key_down(cx.listener(|this, _, _| this.saw_key_down = true))
+                    .on_key_down(cx.listener(|this, _, cx| {
+                        cx.stop_propagation();
+                        this.saw_key_down = true
+                    }))
                     .on_action(
                         cx.listener(|this: &mut TestView, _: &TestAction, _| {
                             this.saw_action = true
@@ -343,6 +346,7 @@ mod test {
             .update(cx, |test_view, cx| cx.focus(&test_view.focus_handle))
             .unwrap();
 
+        cx.dispatch_keystroke(*window, Keystroke::parse("a").unwrap(), false);
         cx.dispatch_keystroke(*window, Keystroke::parse("ctrl-g").unwrap(), false);
 
         window

crates/gpui/src/platform.rs πŸ”—

@@ -6,19 +6,17 @@ mod mac;
 mod test;
 
 use crate::{
-    point, size, Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId,
-    FontMetrics, FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap,
-    LineLayout, Pixels, Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result,
-    Scene, SharedString, Size, TaskLabel,
+    Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, FontMetrics,
+    FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap, LineLayout, Pixels,
+    Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, Scene, SharedString,
+    Size, TaskLabel,
 };
-use anyhow::{anyhow, bail};
+use anyhow::anyhow;
 use async_task::Runnable;
 use futures::channel::oneshot;
 use parking::Unparker;
 use seahash::SeaHasher;
 use serde::{Deserialize, Serialize};
-use sqlez::bindable::{Bind, Column, StaticColumnCount};
-use sqlez::statement::Statement;
 use std::borrow::Cow;
 use std::hash::{Hash, Hasher};
 use std::time::Duration;
@@ -396,67 +394,6 @@ pub enum WindowBounds {
     Fixed(Bounds<GlobalPixels>),
 }
 
-impl StaticColumnCount for WindowBounds {
-    fn column_count() -> usize {
-        5
-    }
-}
-
-impl Bind for WindowBounds {
-    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
-        let (region, next_index) = match self {
-            WindowBounds::Fullscreen => {
-                let next_index = statement.bind(&"Fullscreen", start_index)?;
-                (None, next_index)
-            }
-            WindowBounds::Maximized => {
-                let next_index = statement.bind(&"Maximized", start_index)?;
-                (None, next_index)
-            }
-            WindowBounds::Fixed(region) => {
-                let next_index = statement.bind(&"Fixed", start_index)?;
-                (Some(*region), next_index)
-            }
-        };
-
-        statement.bind(
-            &region.map(|region| {
-                (
-                    region.origin.x,
-                    region.origin.y,
-                    region.size.width,
-                    region.size.height,
-                )
-            }),
-            next_index,
-        )
-    }
-}
-
-impl Column for WindowBounds {
-    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
-        let (window_state, next_index) = String::column(statement, start_index)?;
-        let bounds = match window_state.as_str() {
-            "Fullscreen" => WindowBounds::Fullscreen,
-            "Maximized" => WindowBounds::Maximized,
-            "Fixed" => {
-                let ((x, y, width, height), _) = Column::column(statement, next_index)?;
-                let x: f64 = x;
-                let y: f64 = y;
-                let width: f64 = width;
-                let height: f64 = height;
-                WindowBounds::Fixed(Bounds {
-                    origin: point(x.into(), y.into()),
-                    size: size(width.into(), height.into()),
-                })
-            }
-            _ => bail!("Window State did not have a valid string"),
-        };
-
-        Ok((bounds, next_index + 4))
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum WindowAppearance {
     Light,

crates/gpui/src/platform/mac/dispatcher.rs πŸ”—

@@ -11,7 +11,7 @@ use objc::{
 };
 use parking::{Parker, Unparker};
 use parking_lot::Mutex;
-use std::{ffi::c_void, sync::Arc, time::Duration};
+use std::{ffi::c_void, ptr::NonNull, sync::Arc, time::Duration};
 
 include!(concat!(env!("OUT_DIR"), "/dispatch_sys.rs"));
 
@@ -47,7 +47,7 @@ impl PlatformDispatcher for MacDispatcher {
         unsafe {
             dispatch_async_f(
                 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.try_into().unwrap(), 0),
-                runnable.into_raw() as *mut c_void,
+                runnable.into_raw().as_ptr() as *mut c_void,
                 Some(trampoline),
             );
         }
@@ -57,7 +57,7 @@ impl PlatformDispatcher for MacDispatcher {
         unsafe {
             dispatch_async_f(
                 dispatch_get_main_queue(),
-                runnable.into_raw() as *mut c_void,
+                runnable.into_raw().as_ptr() as *mut c_void,
                 Some(trampoline),
             );
         }
@@ -71,7 +71,7 @@ impl PlatformDispatcher for MacDispatcher {
             dispatch_after_f(
                 when,
                 queue,
-                runnable.into_raw() as *mut c_void,
+                runnable.into_raw().as_ptr() as *mut c_void,
                 Some(trampoline),
             );
         }
@@ -91,6 +91,6 @@ impl PlatformDispatcher for MacDispatcher {
 }
 
 extern "C" fn trampoline(runnable: *mut c_void) {
-    let task = unsafe { Runnable::from_raw(runnable as *mut ()) };
+    let task = unsafe { Runnable::<()>::from_raw(NonNull::new_unchecked(runnable as *mut ())) };
     task.run();
 }

crates/gpui/src/platform/test/platform.rs πŸ”—

@@ -19,7 +19,7 @@ pub struct TestPlatform {
     background_executor: BackgroundExecutor,
     foreground_executor: ForegroundExecutor,
 
-    active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
+    pub(crate) active_window: RefCell<Option<TestWindow>>,
     active_display: Rc<dyn PlatformDisplay>,
     active_cursor: Mutex<CursorStyle>,
     current_clipboard_item: Mutex<Option<ClipboardItem>>,
@@ -79,6 +79,28 @@ impl TestPlatform {
         self.prompts.borrow_mut().multiple_choice.push_back(tx);
         rx
     }
+
+    pub(crate) fn set_active_window(&self, window: Option<TestWindow>) {
+        let executor = self.foreground_executor().clone();
+        let previous_window = self.active_window.borrow_mut().take();
+        *self.active_window.borrow_mut() = window.clone();
+
+        executor
+            .spawn(async move {
+                if let Some(previous_window) = previous_window {
+                    if let Some(window) = window.as_ref() {
+                        if Arc::ptr_eq(&previous_window.0, &window.0) {
+                            return;
+                        }
+                    }
+                    previous_window.simulate_active_status_change(false);
+                }
+                if let Some(window) = window {
+                    window.simulate_active_status_change(true);
+                }
+            })
+            .detach();
+    }
 }
 
 // todo!("implement out what our tests needed in GPUI 1")
@@ -106,7 +128,7 @@ impl Platform for TestPlatform {
     }
 
     fn activate(&self, _ignoring_other_apps: bool) {
-        unimplemented!()
+        //
     }
 
     fn hide(&self) {
@@ -130,7 +152,10 @@ impl Platform for TestPlatform {
     }
 
     fn active_window(&self) -> Option<crate::AnyWindowHandle> {
-        self.active_window.lock().clone()
+        self.active_window
+            .borrow()
+            .as_ref()
+            .map(|window| window.0.lock().handle)
     }
 
     fn open_window(
@@ -139,12 +164,13 @@ impl Platform for TestPlatform {
         options: WindowOptions,
         _draw: Box<dyn FnMut() -> Result<Scene>>,
     ) -> Box<dyn crate::PlatformWindow> {
-        *self.active_window.lock() = Some(handle);
-        Box::new(TestWindow::new(
+        let window = TestWindow::new(
             options,
+            handle,
             self.weak.clone(),
             self.active_display.clone(),
-        ))
+        );
+        Box::new(window)
     }
 
     fn set_display_link_output_callback(

crates/gpui/src/platform/test/window.rs πŸ”—

@@ -1,7 +1,7 @@
 use crate::{
-    px, AtlasKey, AtlasTextureId, AtlasTile, Pixels, PlatformAtlas, PlatformDisplay,
-    PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
-    WindowBounds, WindowOptions,
+    px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, InputEvent, KeyDownEvent,
+    Keystroke, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
+    Size, TestPlatform, TileId, WindowAppearance, WindowBounds, WindowOptions,
 };
 use collections::HashMap;
 use parking_lot::Mutex;
@@ -10,51 +10,122 @@ use std::{
     sync::{self, Arc},
 };
 
-#[derive(Default)]
-pub(crate) struct TestWindowHandlers {
-    pub(crate) active_status_change: Vec<Box<dyn FnMut(bool)>>,
-    pub(crate) input: Vec<Box<dyn FnMut(crate::InputEvent) -> bool>>,
-    pub(crate) moved: Vec<Box<dyn FnMut()>>,
-    pub(crate) resize: Vec<Box<dyn FnMut(Size<Pixels>, f32)>>,
-}
-
-pub struct TestWindow {
+pub struct TestWindowState {
     pub(crate) bounds: WindowBounds,
+    pub(crate) handle: AnyWindowHandle,
     display: Rc<dyn PlatformDisplay>,
     pub(crate) title: Option<String>,
     pub(crate) edited: bool,
-    pub(crate) input_handler: Option<Arc<Mutex<Box<dyn PlatformInputHandler>>>>,
-    pub(crate) handlers: Arc<Mutex<TestWindowHandlers>>,
     platform: Weak<TestPlatform>,
     sprite_atlas: Arc<dyn PlatformAtlas>,
+
+    input_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
+    active_status_change_callback: Option<Box<dyn FnMut(bool)>>,
+    resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
+    moved_callback: Option<Box<dyn FnMut()>>,
+    input_handler: Option<Box<dyn PlatformInputHandler>>,
 }
 
+#[derive(Clone)]
+pub struct TestWindow(pub(crate) Arc<Mutex<TestWindowState>>);
+
 impl TestWindow {
     pub fn new(
         options: WindowOptions,
+        handle: AnyWindowHandle,
         platform: Weak<TestPlatform>,
         display: Rc<dyn PlatformDisplay>,
     ) -> Self {
-        Self {
+        Self(Arc::new(Mutex::new(TestWindowState {
             bounds: options.bounds,
             display,
             platform,
-            input_handler: None,
+            handle,
             sprite_atlas: Arc::new(TestAtlas::new()),
-            handlers: Default::default(),
             title: Default::default(),
             edited: false,
+
+            input_callback: None,
+            active_status_change_callback: None,
+            resize_callback: None,
+            moved_callback: None,
+            input_handler: None,
+        })))
+    }
+
+    pub fn simulate_resize(&mut self, size: Size<Pixels>) {
+        let scale_factor = self.scale_factor();
+        let mut lock = self.0.lock();
+        let Some(mut callback) = lock.resize_callback.take() else {
+            return;
+        };
+        match &mut lock.bounds {
+            WindowBounds::Fullscreen | WindowBounds::Maximized => {
+                lock.bounds = WindowBounds::Fixed(Bounds {
+                    origin: Point::default(),
+                    size: size.map(|pixels| f64::from(pixels).into()),
+                });
+            }
+            WindowBounds::Fixed(bounds) => {
+                bounds.size = size.map(|pixels| f64::from(pixels).into());
+            }
         }
+        drop(lock);
+        callback(size, scale_factor);
+        self.0.lock().resize_callback = Some(callback);
+    }
+
+    pub(crate) fn simulate_active_status_change(&self, active: bool) {
+        let mut lock = self.0.lock();
+        let Some(mut callback) = lock.active_status_change_callback.take() else {
+            return;
+        };
+        drop(lock);
+        callback(active);
+        self.0.lock().active_status_change_callback = Some(callback);
+    }
+
+    pub fn simulate_input(&mut self, event: InputEvent) -> bool {
+        let mut lock = self.0.lock();
+        let Some(mut callback) = lock.input_callback.take() else {
+            return false;
+        };
+        drop(lock);
+        let result = callback(event);
+        self.0.lock().input_callback = Some(callback);
+        result
+    }
+
+    pub fn simulate_keystroke(&mut self, keystroke: Keystroke, is_held: bool) {
+        if self.simulate_input(InputEvent::KeyDown(KeyDownEvent {
+            keystroke: keystroke.clone(),
+            is_held,
+        })) {
+            return;
+        }
+
+        let mut lock = self.0.lock();
+        let Some(mut input_handler) = lock.input_handler.take() else {
+            panic!(
+                "simulate_keystroke {:?} input event was not handled and there was no active input",
+                &keystroke
+            );
+        };
+        drop(lock);
+        let text = keystroke.ime_key.unwrap_or(keystroke.key);
+        input_handler.replace_text_in_range(None, &text);
+
+        self.0.lock().input_handler = Some(input_handler);
     }
 }
 
 impl PlatformWindow for TestWindow {
     fn bounds(&self) -> WindowBounds {
-        self.bounds
+        self.0.lock().bounds
     }
 
     fn content_size(&self) -> Size<Pixels> {
-        let bounds = match self.bounds {
+        let bounds = match self.bounds() {
             WindowBounds::Fixed(bounds) => bounds,
             WindowBounds::Maximized | WindowBounds::Fullscreen => self.display().bounds(),
         };
@@ -74,7 +145,7 @@ impl PlatformWindow for TestWindow {
     }
 
     fn display(&self) -> std::rc::Rc<dyn crate::PlatformDisplay> {
-        self.display.clone()
+        self.0.lock().display.clone()
     }
 
     fn mouse_position(&self) -> Point<Pixels> {
@@ -90,11 +161,11 @@ impl PlatformWindow for TestWindow {
     }
 
     fn set_input_handler(&mut self, input_handler: Box<dyn crate::PlatformInputHandler>) {
-        self.input_handler = Some(Arc::new(Mutex::new(input_handler)));
+        self.0.lock().input_handler = Some(input_handler);
     }
 
     fn clear_input_handler(&mut self) {
-        self.input_handler = None;
+        self.0.lock().input_handler = None;
     }
 
     fn prompt(
@@ -103,19 +174,29 @@ impl PlatformWindow for TestWindow {
         _msg: &str,
         _answers: &[&str],
     ) -> futures::channel::oneshot::Receiver<usize> {
-        self.platform.upgrade().expect("platform dropped").prompt()
+        self.0
+            .lock()
+            .platform
+            .upgrade()
+            .expect("platform dropped")
+            .prompt()
     }
 
     fn activate(&self) {
-        unimplemented!()
+        self.0
+            .lock()
+            .platform
+            .upgrade()
+            .unwrap()
+            .set_active_window(Some(self.clone()))
     }
 
     fn set_title(&mut self, title: &str) {
-        self.title = Some(title.to_owned());
+        self.0.lock().title = Some(title.to_owned());
     }
 
     fn set_edited(&mut self, edited: bool) {
-        self.edited = edited;
+        self.0.lock().edited = edited;
     }
 
     fn show_character_palette(&self) {
@@ -135,15 +216,15 @@ impl PlatformWindow for TestWindow {
     }
 
     fn on_input(&self, callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
-        self.handlers.lock().input.push(callback)
+        self.0.lock().input_callback = Some(callback)
     }
 
     fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
-        self.handlers.lock().active_status_change.push(callback)
+        self.0.lock().active_status_change_callback = Some(callback)
     }
 
     fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
-        self.handlers.lock().resize.push(callback)
+        self.0.lock().resize_callback = Some(callback)
     }
 
     fn on_fullscreen(&self, _callback: Box<dyn FnMut(bool)>) {
@@ -151,7 +232,7 @@ impl PlatformWindow for TestWindow {
     }
 
     fn on_moved(&self, callback: Box<dyn FnMut()>) {
-        self.handlers.lock().moved.push(callback)
+        self.0.lock().moved_callback = Some(callback)
     }
 
     fn on_should_close(&self, _callback: Box<dyn FnMut() -> bool>) {
@@ -175,7 +256,7 @@ impl PlatformWindow for TestWindow {
     }
 
     fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
-        self.sprite_atlas.clone()
+        self.0.lock().sprite_atlas.clone()
     }
 
     fn as_test(&mut self) -> Option<&mut TestWindow> {

crates/gpui/src/view.rs πŸ”—

@@ -143,6 +143,11 @@ impl<V: 'static> WeakView<V> {
         let view = self.upgrade().context("error upgrading view")?;
         Ok(view.update(cx, f)).flatten()
     }
+
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn assert_dropped(&self) {
+        self.model.assert_dropped()
+    }
 }
 
 impl<V> Clone for WeakView<V> {

crates/gpui/src/window.rs πŸ”—

@@ -1583,36 +1583,16 @@ impl<'a> WindowContext<'a> {
 
         let mut actions: Vec<Box<dyn Action>> = Vec::new();
 
-        // Capture phase
         let mut context_stack: SmallVec<[KeyContext; 16]> = SmallVec::new();
-        self.propagate_event = true;
-
         for node_id in &dispatch_path {
             let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
 
             if let Some(context) = node.context.clone() {
                 context_stack.push(context);
             }
-
-            for key_listener in node.key_listeners.clone() {
-                key_listener(event, DispatchPhase::Capture, self);
-                if !self.propagate_event {
-                    return;
-                }
-            }
         }
 
-        // Bubble phase
         for node_id in dispatch_path.iter().rev() {
-            // Handle low level key events
-            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
-            for key_listener in node.key_listeners.clone() {
-                key_listener(event, DispatchPhase::Bubble, self);
-                if !self.propagate_event {
-                    return;
-                }
-            }
-
             // Match keystrokes
             let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
             if node.context.is_some() {
@@ -1633,6 +1613,7 @@ impl<'a> WindowContext<'a> {
             self.clear_pending_keystrokes();
         }
 
+        self.propagate_event = true;
         for action in actions {
             self.dispatch_action_on_node(node_id, action.boxed_clone());
             if !self.propagate_event {
@@ -1640,6 +1621,31 @@ impl<'a> WindowContext<'a> {
                 return;
             }
         }
+
+        // Capture phase
+        for node_id in &dispatch_path {
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
+
+            for key_listener in node.key_listeners.clone() {
+                key_listener(event, DispatchPhase::Capture, self);
+                if !self.propagate_event {
+                    return;
+                }
+            }
+        }
+
+        // Bubble phase
+        for node_id in dispatch_path.iter().rev() {
+            // Handle low level key events
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
+            for key_listener in node.key_listeners.clone() {
+                key_listener(event, DispatchPhase::Bubble, self);
+                if !self.propagate_event {
+                    return;
+                }
+            }
+        }
+
         self.dispatch_keystroke_observers(event, None);
     }
 

crates/language/src/buffer.rs πŸ”—

@@ -57,6 +57,12 @@ lazy_static! {
     pub static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
 }
 
+#[derive(PartialEq, Clone, Copy, Debug)]
+pub enum Capability {
+    ReadWrite,
+    ReadOnly,
+}
+
 pub struct Buffer {
     text: TextBuffer,
     diff_base: Option<String>,
@@ -90,6 +96,7 @@ pub struct Buffer {
     completion_triggers: Vec<String>,
     completion_triggers_timestamp: clock::Lamport,
     deferred_ops: OperationQueue<Operation>,
+    capability: Capability,
 }
 
 pub struct BufferSnapshot {
@@ -405,19 +412,27 @@ impl Buffer {
             TextBuffer::new(replica_id, id, base_text.into()),
             None,
             None,
+            Capability::ReadWrite,
         )
     }
 
-    pub fn remote(remote_id: u64, replica_id: ReplicaId, base_text: String) -> Self {
+    pub fn remote(
+        remote_id: u64,
+        replica_id: ReplicaId,
+        capability: Capability,
+        base_text: String,
+    ) -> Self {
         Self::build(
             TextBuffer::new(replica_id, remote_id, base_text),
             None,
             None,
+            capability,
         )
     }
 
     pub fn from_proto(
         replica_id: ReplicaId,
+        capability: Capability,
         message: proto::BufferState,
         file: Option<Arc<dyn File>>,
     ) -> Result<Self> {
@@ -426,6 +441,7 @@ impl Buffer {
             buffer,
             message.diff_base.map(|text| text.into_boxed_str().into()),
             file,
+            capability,
         );
         this.text.set_line_ending(proto::deserialize_line_ending(
             rpc::proto::LineEnding::from_i32(message.line_ending)
@@ -504,10 +520,19 @@ impl Buffer {
         self
     }
 
+    pub fn capability(&self) -> Capability {
+        self.capability
+    }
+
+    pub fn read_only(&self) -> bool {
+        self.capability == Capability::ReadOnly
+    }
+
     pub fn build(
         buffer: TextBuffer,
         diff_base: Option<String>,
         file: Option<Arc<dyn File>>,
+        capability: Capability,
     ) -> Self {
         let saved_mtime = if let Some(file) = file.as_ref() {
             file.mtime()
@@ -526,6 +551,7 @@ impl Buffer {
             diff_base,
             git_diff: git::diff::BufferDiff::new(),
             file,
+            capability,
             syntax_map: Mutex::new(SyntaxMap::new()),
             parsing_in_background: false,
             parse_count: 0,

crates/language/src/buffer_tests.rs πŸ”—

@@ -1926,7 +1926,7 @@ fn test_serialization(cx: &mut gpui::AppContext) {
         .background_executor()
         .block(buffer1.read(cx).serialize_ops(None, cx));
     let buffer2 = cx.new_model(|cx| {
-        let mut buffer = Buffer::from_proto(1, state, None).unwrap();
+        let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
         buffer
             .apply_ops(
                 ops.into_iter()
@@ -1967,7 +1967,8 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
             let ops = cx
                 .background_executor()
                 .block(base_buffer.read(cx).serialize_ops(None, cx));
-            let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
+            let mut buffer =
+                Buffer::from_proto(i as ReplicaId, Capability::ReadWrite, state, None).unwrap();
             buffer
                 .apply_ops(
                     ops.into_iter()
@@ -2083,8 +2084,13 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
                     replica_id
                 );
                 new_buffer = Some(cx.new_model(|cx| {
-                    let mut new_buffer =
-                        Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
+                    let mut new_buffer = Buffer::from_proto(
+                        new_replica_id,
+                        Capability::ReadWrite,
+                        old_buffer_state,
+                        None,
+                    )
+                    .unwrap();
                     new_buffer
                         .apply_ops(
                             old_buffer_ops

crates/language_tools/src/lsp_log.rs πŸ”—

@@ -772,9 +772,10 @@ impl Render for LspLogToolbarItemView {
                                 }),
                             );
                         if server_selected && row.logs_selected {
+                            let selected_ix = menu.select_last();
                             debug_assert_eq!(
                                 Some(ix * 3 + 1),
-                                menu.select_last(),
+                                selected_ix,
                                 "Could not scroll to a just added LSP menu item"
                             );
                         }
@@ -822,9 +823,10 @@ impl Render for LspLogToolbarItemView {
                             }),
                         );
                         if server_selected && row.rpc_trace_selected {
+                            let selected_ix = menu.select_last();
                             debug_assert_eq!(
                                 Some(ix * 3 + 2),
-                                menu.select_last(),
+                                selected_ix,
                                 "Could not scroll to a just added LSP menu item"
                             );
                         }

crates/live_kit_server/src/token.rs πŸ”—

@@ -62,6 +62,7 @@ impl<'a> VideoGrant<'a> {
         Self {
             room: Some(Cow::Borrowed(room)),
             room_join: Some(true),
+            can_publish: Some(false),
             can_subscribe: Some(true),
             ..Default::default()
         }

crates/multi_buffer/src/multi_buffer.rs πŸ”—

@@ -11,7 +11,7 @@ pub use language::Completion;
 use language::{
     char_kind,
     language_settings::{language_settings, LanguageSettings},
-    AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape,
+    AutoindentMode, Buffer, BufferChunks, BufferSnapshot, Capability, CharKind, Chunk, CursorShape,
     DiagnosticEntry, File, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16,
     Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _,
     ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
@@ -55,6 +55,7 @@ pub struct MultiBuffer {
     replica_id: ReplicaId,
     history: History,
     title: Option<String>,
+    capability: Capability,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -225,13 +226,14 @@ struct ExcerptBytes<'a> {
 }
 
 impl MultiBuffer {
-    pub fn new(replica_id: ReplicaId) -> Self {
+    pub fn new(replica_id: ReplicaId, capability: Capability) -> Self {
         Self {
             snapshot: Default::default(),
             buffers: Default::default(),
             next_excerpt_id: 1,
             subscriptions: Default::default(),
             singleton: false,
+            capability,
             replica_id,
             history: History {
                 next_transaction_id: Default::default(),
@@ -271,6 +273,7 @@ impl MultiBuffer {
             next_excerpt_id: 1,
             subscriptions: Default::default(),
             singleton: self.singleton,
+            capability: self.capability,
             replica_id: self.replica_id,
             history: self.history.clone(),
             title: self.title.clone(),
@@ -282,8 +285,12 @@ impl MultiBuffer {
         self
     }
 
+    pub fn read_only(&self) -> bool {
+        self.capability == Capability::ReadOnly
+    }
+
     pub fn singleton(buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
-        let mut this = Self::new(buffer.read(cx).replica_id());
+        let mut this = Self::new(buffer.read(cx).replica_id(), buffer.read(cx).capability());
         this.singleton = true;
         this.push_excerpts(
             buffer,
@@ -1657,7 +1664,7 @@ impl MultiBuffer {
         excerpts: [(&str, Vec<Range<Point>>); COUNT],
         cx: &mut gpui::AppContext,
     ) -> Model<Self> {
-        let multi = cx.new_model(|_| Self::new(0));
+        let multi = cx.new_model(|_| Self::new(0, Capability::ReadWrite));
         for (text, ranges) in excerpts {
             let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
             let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
@@ -1678,7 +1685,7 @@ impl MultiBuffer {
 
     pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
         cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(0);
+            let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
             let mutation_count = rng.gen_range(1..=5);
             multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
             multibuffer
@@ -4176,7 +4183,7 @@ mod tests {
             let ops = cx
                 .background_executor()
                 .block(host_buffer.read(cx).serialize_ops(None, cx));
-            let mut buffer = Buffer::from_proto(1, state, None).unwrap();
+            let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
             buffer
                 .apply_ops(
                     ops.into_iter()
@@ -4205,7 +4212,7 @@ mod tests {
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a')));
         let buffer_2 =
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'g')));
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
 
         let events = Arc::new(RwLock::new(Vec::<Event>::new()));
         multibuffer.update(cx, |_, cx| {
@@ -4442,8 +4449,8 @@ mod tests {
         let buffer_2 =
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'm')));
 
-        let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
-        let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
+        let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let follower_edit_event_count = Arc::new(RwLock::new(0));
 
         follower_multibuffer.update(cx, |_, cx| {
@@ -4547,7 +4554,7 @@ mod tests {
     fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
         let buffer =
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
             multibuffer.push_excerpts_with_context_lines(
                 buffer.clone(),
@@ -4584,7 +4591,7 @@ mod tests {
     async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
         let buffer =
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
             let snapshot = buffer.read(cx);
             let ranges = vec![
@@ -4619,7 +4626,7 @@ mod tests {
 
     #[gpui::test]
     fn test_empty_multibuffer(cx: &mut AppContext) {
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
 
         let snapshot = multibuffer.read(cx).snapshot(cx);
         assert_eq!(snapshot.text(), "");
@@ -4652,7 +4659,7 @@ mod tests {
         let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
         let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "efghi"));
         let multibuffer = cx.new_model(|cx| {
-            let mut multibuffer = MultiBuffer::new(0);
+            let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
             multibuffer.push_excerpts(
                 buffer_1.clone(),
                 [ExcerptRange {
@@ -4710,7 +4717,7 @@ mod tests {
         let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
         let buffer_2 =
             cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "ABCDEFGHIJKLMNOP"));
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
 
         // Create an insertion id in buffer 1 that doesn't exist in buffer 2.
         // Add an excerpt from buffer 1 that spans this new insertion.
@@ -4844,7 +4851,7 @@ mod tests {
             .unwrap_or(10);
 
         let mut buffers: Vec<Model<Buffer>> = Vec::new();
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let mut excerpt_ids = Vec::<ExcerptId>::new();
         let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new();
         let mut anchors = Vec::new();
@@ -5266,7 +5273,7 @@ mod tests {
 
         let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "1234"));
         let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "5678"));
-        let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
+        let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
         let group_interval = multibuffer.read(cx).history.group_interval;
         multibuffer.update(cx, |multibuffer, cx| {
             multibuffer.push_excerpts(

crates/project/src/project.rs πŸ”—

@@ -39,11 +39,11 @@ use language::{
         deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
         serialize_anchor, serialize_version, split_operations,
     },
-    range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeAction,
-    CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Event as BufferEvent,
-    File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, LspAdapterDelegate,
-    OffsetRangeExt, Operation, Patch, PendingLanguageServer, PointUtf16, TextBufferSnapshot,
-    ToOffset, ToPointUtf16, Transaction, Unclipped,
+    range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, Capability,
+    CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff,
+    Event as BufferEvent, File as _, Language, LanguageRegistry, LanguageServerName, LocalFile,
+    LspAdapterDelegate, OffsetRangeExt, Operation, Patch, PendingLanguageServer, PointUtf16,
+    TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, Unclipped,
 };
 use log::error;
 use lsp::{
@@ -262,6 +262,7 @@ enum ProjectClientState {
     },
     Remote {
         sharing_has_stopped: bool,
+        capability: Capability,
         remote_id: u64,
         replica_id: ReplicaId,
     },
@@ -702,6 +703,7 @@ impl Project {
         user_store: Model<UserStore>,
         languages: Arc<LanguageRegistry>,
         fs: Arc<dyn Fs>,
+        role: proto::ChannelRole,
         mut cx: AsyncAppContext,
     ) -> Result<Model<Self>> {
         client.authenticate_and_connect(true, &cx).await?;
@@ -756,6 +758,7 @@ impl Project {
                 client: client.clone(),
                 client_state: Some(ProjectClientState::Remote {
                     sharing_has_stopped: false,
+                    capability: Capability::ReadWrite,
                     remote_id,
                     replica_id,
                 }),
@@ -796,6 +799,7 @@ impl Project {
                 prettiers_per_worktree: HashMap::default(),
                 prettier_instances: HashMap::default(),
             };
+            this.set_role(role);
             for worktree in worktrees {
                 let _ = this.add_worktree(&worktree, cx);
             }
@@ -1618,6 +1622,17 @@ impl Project {
         cx.notify();
     }
 
+    pub fn set_role(&mut self, role: proto::ChannelRole) {
+        if let Some(ProjectClientState::Remote { capability, .. }) = &mut self.client_state {
+            *capability = if role == proto::ChannelRole::Member || role == proto::ChannelRole::Admin
+            {
+                Capability::ReadWrite
+            } else {
+                Capability::ReadOnly
+            };
+        }
+    }
+
     fn disconnected_from_host_internal(&mut self, cx: &mut AppContext) {
         if let Some(ProjectClientState::Remote {
             sharing_has_stopped,
@@ -1659,7 +1674,7 @@ impl Project {
         cx.emit(Event::Closed);
     }
 
-    pub fn is_read_only(&self) -> bool {
+    pub fn is_disconnected(&self) -> bool {
         match &self.client_state {
             Some(ProjectClientState::Remote {
                 sharing_has_stopped,
@@ -1669,6 +1684,17 @@ impl Project {
         }
     }
 
+    pub fn capability(&self) -> Capability {
+        match &self.client_state {
+            Some(ProjectClientState::Remote { capability, .. }) => *capability,
+            Some(ProjectClientState::Local { .. }) | None => Capability::ReadWrite,
+        }
+    }
+
+    pub fn is_read_only(&self) -> bool {
+        self.is_disconnected() || self.capability() == Capability::ReadOnly
+    }
+
     pub fn is_local(&self) -> bool {
         match &self.client_state {
             Some(ProjectClientState::Remote { .. }) => false,
@@ -6013,7 +6039,7 @@ impl Project {
             this.upgrade().context("project dropped")?;
             let response = rpc.request(message).await?;
             let this = this.upgrade().context("project dropped")?;
-            if this.update(&mut cx, |this, _| this.is_read_only())? {
+            if this.update(&mut cx, |this, _| this.is_disconnected())? {
                 Err(anyhow!("disconnected before completing request"))
             } else {
                 request
@@ -7192,7 +7218,8 @@ impl Project {
 
                     let buffer_id = state.id;
                     let buffer = cx.new_model(|_| {
-                        Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap()
+                        Buffer::from_proto(this.replica_id(), this.capability(), state, buffer_file)
+                            .unwrap()
                     });
                     this.incomplete_remote_buffers
                         .insert(buffer_id, Some(buffer));
@@ -7940,7 +7967,7 @@ impl Project {
 
                 if let Some(buffer) = buffer {
                     break buffer;
-                } else if this.update(&mut cx, |this, _| this.is_read_only())? {
+                } else if this.update(&mut cx, |this, _| this.is_disconnected())? {
                     return Err(anyhow!("disconnected before buffer {} could be opened", id));
                 }
 

crates/project/src/worktree.rs πŸ”—

@@ -32,7 +32,8 @@ use language::{
         deserialize_fingerprint, deserialize_version, serialize_fingerprint, serialize_line_ending,
         serialize_version,
     },
-    Buffer, DiagnosticEntry, File as _, LineEnding, PointUtf16, Rope, RopeFingerprint, Unclipped,
+    Buffer, Capability, DiagnosticEntry, File as _, LineEnding, PointUtf16, Rope, RopeFingerprint,
+    Unclipped,
 };
 use lsp::LanguageServerId;
 use parking_lot::Mutex;
@@ -682,7 +683,14 @@ impl LocalWorktree {
                 .background_executor()
                 .spawn(async move { text::Buffer::new(0, id, contents) })
                 .await;
-            cx.new_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
+            cx.new_model(|_| {
+                Buffer::build(
+                    text_buffer,
+                    diff_base,
+                    Some(Arc::new(file)),
+                    Capability::ReadWrite,
+                )
+            })
         })
     }
 

crates/project_panel/src/project_panel.rs πŸ”—

@@ -388,8 +388,18 @@ impl ProjectPanel {
             let is_dir = entry.is_dir();
             let worktree_id = worktree.id();
             let is_local = project.is_local();
+            let is_read_only = project.is_read_only();
 
             let context_menu = ContextMenu::build(cx, |mut menu, cx| {
+                if is_read_only {
+                    menu = menu.action("Copy Relative Path", Box::new(CopyRelativePath));
+                    if is_dir {
+                        menu = menu.action("Search Inside", Box::new(NewSearchInDirectory))
+                    }
+
+                    return menu;
+                }
+
                 if is_local {
                     menu = menu.action(
                         "Add Folder to Project",
@@ -1473,6 +1483,7 @@ impl ProjectPanel {
 impl Render for ProjectPanel {
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
         let has_worktree = self.visible_entries.len() != 0;
+        let project = self.project.read(cx);
 
         if has_worktree {
             div()
@@ -1485,21 +1496,25 @@ impl Render for ProjectPanel {
                 .on_action(cx.listener(Self::expand_selected_entry))
                 .on_action(cx.listener(Self::collapse_selected_entry))
                 .on_action(cx.listener(Self::collapse_all_entries))
-                .on_action(cx.listener(Self::new_file))
-                .on_action(cx.listener(Self::new_directory))
-                .on_action(cx.listener(Self::rename))
-                .on_action(cx.listener(Self::delete))
-                .on_action(cx.listener(Self::confirm))
                 .on_action(cx.listener(Self::open_file))
+                .on_action(cx.listener(Self::confirm))
                 .on_action(cx.listener(Self::cancel))
-                .on_action(cx.listener(Self::cut))
-                .on_action(cx.listener(Self::copy))
                 .on_action(cx.listener(Self::copy_path))
                 .on_action(cx.listener(Self::copy_relative_path))
-                .on_action(cx.listener(Self::paste))
-                .on_action(cx.listener(Self::reveal_in_finder))
-                .on_action(cx.listener(Self::open_in_terminal))
                 .on_action(cx.listener(Self::new_search_in_directory))
+                .when(!project.is_read_only(), |el| {
+                    el.on_action(cx.listener(Self::new_file))
+                        .on_action(cx.listener(Self::new_directory))
+                        .on_action(cx.listener(Self::rename))
+                        .on_action(cx.listener(Self::delete))
+                        .on_action(cx.listener(Self::cut))
+                        .on_action(cx.listener(Self::copy))
+                        .on_action(cx.listener(Self::paste))
+                })
+                .when(project.is_local(), |el| {
+                    el.on_action(cx.listener(Self::reveal_in_finder))
+                        .on_action(cx.listener(Self::open_in_terminal))
+                })
                 .track_focus(&self.focus_handle)
                 .child(
                     uniform_list(

crates/rpc/proto/zed.proto πŸ”—

@@ -269,6 +269,7 @@ message Participant {
     repeated ParticipantProject projects = 3;
     ParticipantLocation location = 4;
     uint32 participant_index = 5;
+    ChannelRole role = 6;
 }
 
 message PendingParticipant {

crates/search/src/buffer_search.rs πŸ”—

@@ -70,7 +70,7 @@ impl BufferSearchBar {
     fn render_text_input(&self, editor: &View<Editor>, cx: &ViewContext<Self>) -> impl IntoElement {
         let settings = ThemeSettings::get_global(cx);
         let text_style = TextStyle {
-            color: if editor.read(cx).read_only() {
+            color: if editor.read(cx).read_only(cx) {
                 cx.theme().colors().text_disabled
             } else {
                 cx.theme().colors().text
@@ -223,6 +223,7 @@ impl Render for BufferSearchBar {
                     .gap_2()
                     .border_1()
                     .border_color(editor_border)
+                    .min_w(rems(384. / 16.))
                     .rounded_lg()
                     .child(IconElement::new(Icon::MagnifyingGlass))
                     .child(self.render_text_input(&self.query_editor, cx))

crates/search/src/project_search.rs πŸ”—

@@ -38,8 +38,8 @@ use std::{
 use theme::ThemeSettings;
 
 use ui::{
-    h_stack, prelude::*, v_stack, Button, Icon, IconButton, IconElement, Label, LabelCommon,
-    LabelSize, Selectable, Tooltip,
+    h_stack, prelude::*, v_stack, Icon, IconButton, IconElement, Label, LabelCommon, LabelSize,
+    Selectable, ToggleButton, Tooltip,
 };
 use util::{paths::PathMatcher, ResultExt as _};
 use workspace::{
@@ -61,12 +61,12 @@ struct ActiveSearches(HashMap<WeakModel<Project>, WeakView<ProjectSearchView>>);
 struct ActiveSettings(HashMap<WeakModel<Project>, ProjectSearchSettings>);
 
 pub fn init(cx: &mut AppContext) {
-    // todo!() po
     cx.set_global(ActiveSearches::default());
     cx.set_global(ActiveSettings::default());
     cx.observe_new_views(|workspace: &mut Workspace, _cx| {
         workspace
-            .register_action(ProjectSearchView::deploy)
+            .register_action(ProjectSearchView::new_search)
+            .register_action(ProjectSearchView::deploy_search)
             .register_action(ProjectSearchBar::search_in_new);
     })
     .detach();
@@ -132,9 +132,11 @@ pub struct ProjectSearchBar {
 impl ProjectSearch {
     fn new(project: Model<Project>, cx: &mut ModelContext<Self>) -> Self {
         let replica_id = project.read(cx).replica_id();
+        let capability = project.read(cx).capability();
+
         Self {
             project,
-            excerpts: cx.new_model(|_| MultiBuffer::new(replica_id)),
+            excerpts: cx.new_model(|_| MultiBuffer::new(replica_id, capability)),
             pending_search: Default::default(),
             match_ranges: Default::default(),
             active_query: None,
@@ -286,7 +288,6 @@ impl Render for ProjectSearchView {
                 .size_full()
                 .track_focus(&self.focus_handle)
                 .child(self.results_editor.clone())
-                .into_any()
         } else {
             let model = self.model.read(cx);
             let has_no_results = model.no_results.unwrap_or(false);
@@ -363,6 +364,7 @@ impl Render for ProjectSearchView {
                 .flex_1()
                 .size_full()
                 .justify_center()
+                .bg(cx.theme().colors().editor_background)
                 .track_focus(&self.focus_handle)
                 .child(
                     h_stack()
@@ -372,7 +374,6 @@ impl Render for ProjectSearchView {
                         .child(v_stack().child(major_text).children(minor_text))
                         .child(h_stack().flex_1()),
                 )
-                .into_any()
         }
     }
 }
@@ -941,11 +942,41 @@ impl ProjectSearchView {
         });
     }
 
+    // Re-activate the most recently activated search or the most recent if it has been closed.
+    // If no search exists in the workspace, create a new one.
+    fn deploy_search(
+        workspace: &mut Workspace,
+        _: &workspace::DeploySearch,
+        cx: &mut ViewContext<Workspace>,
+    ) {
+        let active_search = cx
+            .global::<ActiveSearches>()
+            .0
+            .get(&workspace.project().downgrade());
+        let existing = active_search
+            .and_then(|active_search| {
+                workspace
+                    .items_of_type::<ProjectSearchView>(cx)
+                    .filter(|search| &search.downgrade() == active_search)
+                    .last()
+            })
+            .or_else(|| workspace.item_of_type::<ProjectSearchView>(cx));
+        Self::existing_or_new_search(workspace, existing, cx)
+    }
+
     // Add another search tab to the workspace.
-    fn deploy(
+    fn new_search(
         workspace: &mut Workspace,
         _: &workspace::NewSearch,
         cx: &mut ViewContext<Workspace>,
+    ) {
+        Self::existing_or_new_search(workspace, None, cx)
+    }
+
+    fn existing_or_new_search(
+        workspace: &mut Workspace,
+        existing: Option<View<ProjectSearchView>>,
+        cx: &mut ViewContext<Workspace>,
     ) {
         // Clean up entries for dropped projects
         cx.update_global(|state: &mut ActiveSearches, _cx| {
@@ -962,19 +993,27 @@ impl ProjectSearchView {
             }
         });
 
-        let settings = cx
-            .global::<ActiveSettings>()
-            .0
-            .get(&workspace.project().downgrade());
-
-        let settings = if let Some(settings) = settings {
-            Some(settings.clone())
+        let search = if let Some(existing) = existing {
+            workspace.activate_item(&existing, cx);
+            existing
         } else {
-            None
-        };
+            let settings = cx
+                .global::<ActiveSettings>()
+                .0
+                .get(&workspace.project().downgrade());
 
-        let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
-        let search = cx.new_view(|cx| ProjectSearchView::new(model, cx, settings));
+            let settings = if let Some(settings) = settings {
+                Some(settings.clone())
+            } else {
+                None
+            };
+
+            let model = cx.new_model(|cx| ProjectSearch::new(workspace.project().clone(), cx));
+            let view = cx.new_view(|cx| ProjectSearchView::new(model, cx, settings));
+
+            workspace.add_item(Box::new(view.clone()), cx);
+            view
+        };
 
         workspace.add_item(Box::new(search.clone()), cx);
 
@@ -1519,7 +1558,7 @@ impl ProjectSearchBar {
     fn render_text_input(&self, editor: &View<Editor>, cx: &ViewContext<Self>) -> impl IntoElement {
         let settings = ThemeSettings::get_global(cx);
         let text_style = TextStyle {
-            color: if editor.read(cx).read_only() {
+            color: if editor.read(cx).read_only(cx) {
                 cx.theme().colors().text_disabled
             } else {
                 cx.theme().colors().text
@@ -1639,20 +1678,26 @@ impl Render for ProjectSearchBar {
 
         let mode_column = v_stack().items_start().justify_start().child(
             h_stack()
+                .gap_2()
                 .child(
                     h_stack()
                         .child(
-                            Button::new("project-search-text-button", "Text")
+                            ToggleButton::new("project-search-text-button", "Text")
+                                .style(ButtonStyle::Filled)
+                                .size(ButtonSize::Large)
                                 .selected(search.current_mode == SearchMode::Text)
                                 .on_click(cx.listener(|this, _, cx| {
                                     this.activate_search_mode(SearchMode::Text, cx)
                                 }))
                                 .tooltip(|cx| {
                                     Tooltip::for_action("Toggle text search", &ActivateTextMode, cx)
-                                }),
+                                })
+                                .first(),
                         )
                         .child(
-                            Button::new("project-search-regex-button", "Regex")
+                            ToggleButton::new("project-search-regex-button", "Regex")
+                                .style(ButtonStyle::Filled)
+                                .size(ButtonSize::Large)
                                 .selected(search.current_mode == SearchMode::Regex)
                                 .on_click(cx.listener(|this, _, cx| {
                                     this.activate_search_mode(SearchMode::Regex, cx)
@@ -1663,11 +1708,20 @@ impl Render for ProjectSearchBar {
                                         &ActivateRegexMode,
                                         cx,
                                     )
+                                })
+                                .map(|this| {
+                                    if semantic_is_available {
+                                        this.middle()
+                                    } else {
+                                        this.last()
+                                    }
                                 }),
                         )
                         .when(semantic_is_available, |this| {
                             this.child(
-                                Button::new("project-search-semantic-button", "Semantic")
+                                ToggleButton::new("project-search-semantic-button", "Semantic")
+                                    .style(ButtonStyle::Filled)
+                                    .size(ButtonSize::Large)
                                     .selected(search.current_mode == SearchMode::Semantic)
                                     .on_click(cx.listener(|this, _, cx| {
                                         this.activate_search_mode(SearchMode::Semantic, cx)
@@ -1678,7 +1732,8 @@ impl Render for ProjectSearchBar {
                                             &ActivateSemanticMode,
                                             cx,
                                         )
-                                    }),
+                                    })
+                                    .last(),
                             )
                         }),
                 )
@@ -1829,6 +1884,7 @@ impl Render for ProjectSearchBar {
             .child(
                 h_stack()
                     .justify_between()
+                    .gap_2()
                     .child(query_column)
                     .child(mode_column)
                     .child(replace_column)
@@ -2060,7 +2116,237 @@ pub mod tests {
     }
 
     #[gpui::test]
-    async fn test_project_search_focus(cx: &mut TestAppContext) {
+    async fn test_deploy_project_search_focus(cx: &mut TestAppContext) {
+        init_test(cx);
+
+        let fs = FakeFs::new(cx.background_executor.clone());
+        fs.insert_tree(
+            "/dir",
+            json!({
+                "one.rs": "const ONE: usize = 1;",
+                "two.rs": "const TWO: usize = one::ONE + one::ONE;",
+                "three.rs": "const THREE: usize = one::ONE + two::TWO;",
+                "four.rs": "const FOUR: usize = one::ONE + three::THREE;",
+            }),
+        )
+        .await;
+        let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
+        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+        let workspace = window.clone();
+        let search_bar = window.build_view(cx, |_| ProjectSearchBar::new());
+
+        let active_item = cx.read(|cx| {
+            workspace
+                .read(cx)
+                .unwrap()
+                .active_pane()
+                .read(cx)
+                .active_item()
+                .and_then(|item| item.downcast::<ProjectSearchView>())
+        });
+        assert!(
+            active_item.is_none(),
+            "Expected no search panel to be active"
+        );
+
+        window
+            .update(cx, move |workspace, cx| {
+                assert_eq!(workspace.panes().len(), 1);
+                workspace.panes()[0].update(cx, move |pane, cx| {
+                    pane.toolbar()
+                        .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx))
+                });
+
+                ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch, cx)
+            })
+            .unwrap();
+
+        let Some(search_view) = cx.read(|cx| {
+            workspace
+                .read(cx)
+                .unwrap()
+                .active_pane()
+                .read(cx)
+                .active_item()
+                .and_then(|item| item.downcast::<ProjectSearchView>())
+        }) else {
+            panic!("Search view expected to appear after new search event trigger")
+        };
+
+        cx.spawn(|mut cx| async move {
+            window
+                .update(&mut cx, |_, cx| {
+                    cx.dispatch_action(ToggleFocus.boxed_clone())
+                })
+                .unwrap();
+        })
+        .detach();
+        cx.background_executor.run_until_parked();
+        window
+            .update(cx, |_, cx| {
+                search_view.update(cx, |search_view, cx| {
+                assert!(
+                    search_view.query_editor.focus_handle(cx).is_focused(cx),
+                    "Empty search view should be focused after the toggle focus event: no results panel to focus on",
+                );
+           });
+        }).unwrap();
+
+        window
+            .update(cx, |_, cx| {
+                search_view.update(cx, |search_view, cx| {
+                    let query_editor = &search_view.query_editor;
+                    assert!(
+                        query_editor.focus_handle(cx).is_focused(cx),
+                        "Search view should be focused after the new search view is activated",
+                    );
+                    let query_text = query_editor.read(cx).text(cx);
+                    assert!(
+                        query_text.is_empty(),
+                        "New search query should be empty but got '{query_text}'",
+                    );
+                    let results_text = search_view
+                        .results_editor
+                        .update(cx, |editor, cx| editor.display_text(cx));
+                    assert!(
+                        results_text.is_empty(),
+                        "Empty search view should have no results but got '{results_text}'"
+                    );
+                });
+            })
+            .unwrap();
+
+        window
+            .update(cx, |_, cx| {
+                search_view.update(cx, |search_view, cx| {
+                    search_view.query_editor.update(cx, |query_editor, cx| {
+                        query_editor.set_text("sOMETHINGtHATsURELYdOESnOTeXIST", cx)
+                    });
+                    search_view.search(cx);
+                });
+            })
+            .unwrap();
+        cx.background_executor.run_until_parked();
+        window
+            .update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                let results_text = search_view
+                    .results_editor
+                    .update(cx, |editor, cx| editor.display_text(cx));
+                assert!(
+                    results_text.is_empty(),
+                    "Search view for mismatching query should have no results but got '{results_text}'"
+                );
+                assert!(
+                    search_view.query_editor.focus_handle(cx).is_focused(cx),
+                    "Search view should be focused after mismatching query had been used in search",
+                );
+            });
+        }).unwrap();
+
+        cx.spawn(|mut cx| async move {
+            window.update(&mut cx, |_, cx| {
+                cx.dispatch_action(ToggleFocus.boxed_clone())
+            })
+        })
+        .detach();
+        cx.background_executor.run_until_parked();
+        window.update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                assert!(
+                    search_view.query_editor.focus_handle(cx).is_focused(cx),
+                    "Search view with mismatching query should be focused after the toggle focus event: still no results panel to focus on",
+                );
+            });
+        }).unwrap();
+
+        window
+            .update(cx, |_, cx| {
+                search_view.update(cx, |search_view, cx| {
+                    search_view
+                        .query_editor
+                        .update(cx, |query_editor, cx| query_editor.set_text("TWO", cx));
+                    search_view.search(cx);
+                });
+            })
+            .unwrap();
+        cx.background_executor.run_until_parked();
+        window.update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                assert_eq!(
+                    search_view
+                        .results_editor
+                        .update(cx, |editor, cx| editor.display_text(cx)),
+                    "\n\nconst THREE: usize = one::ONE + two::TWO;\n\n\nconst TWO: usize = one::ONE + one::ONE;",
+                    "Search view results should match the query"
+                );
+                assert!(
+                    search_view.results_editor.focus_handle(cx).is_focused(cx),
+                    "Search view with mismatching query should be focused after search results are available",
+                );
+            });
+        }).unwrap();
+        cx.spawn(|mut cx| async move {
+            window
+                .update(&mut cx, |_, cx| {
+                    cx.dispatch_action(ToggleFocus.boxed_clone())
+                })
+                .unwrap();
+        })
+        .detach();
+        cx.background_executor.run_until_parked();
+        window.update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                assert!(
+                    search_view.results_editor.focus_handle(cx).is_focused(cx),
+                    "Search view with matching query should still have its results editor focused after the toggle focus event",
+                );
+            });
+        }).unwrap();
+
+        workspace
+            .update(cx, |workspace, cx| {
+                ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch, cx)
+            })
+            .unwrap();
+        window.update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                assert_eq!(search_view.query_editor.read(cx).text(cx), "two", "Query should be updated to first search result after search view 2nd open in a row");
+                assert_eq!(
+                    search_view
+                        .results_editor
+                        .update(cx, |editor, cx| editor.display_text(cx)),
+                    "\n\nconst THREE: usize = one::ONE + two::TWO;\n\n\nconst TWO: usize = one::ONE + one::ONE;",
+                    "Results should be unchanged after search view 2nd open in a row"
+                );
+                assert!(
+                    search_view.query_editor.focus_handle(cx).is_focused(cx),
+                    "Focus should be moved into query editor again after search view 2nd open in a row"
+                );
+            });
+        }).unwrap();
+
+        cx.spawn(|mut cx| async move {
+            window
+                .update(&mut cx, |_, cx| {
+                    cx.dispatch_action(ToggleFocus.boxed_clone())
+                })
+                .unwrap();
+        })
+        .detach();
+        cx.background_executor.run_until_parked();
+        window.update(cx, |_, cx| {
+            search_view.update(cx, |search_view, cx| {
+                assert!(
+                    search_view.results_editor.focus_handle(cx).is_focused(cx),
+                    "Search view with matching query should switch focus to the results editor after the toggle focus event",
+                );
+            });
+        }).unwrap();
+    }
+
+    #[gpui::test]
+    async fn test_new_project_search_focus(cx: &mut TestAppContext) {
         init_test(cx);
 
         let fs = FakeFs::new(cx.background_executor.clone());
@@ -2101,7 +2387,7 @@ pub mod tests {
                         .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx))
                 });
 
-                ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx)
+                ProjectSearchView::new_search(workspace, &workspace::NewSearch, cx)
             })
             .unwrap();
 
@@ -2250,7 +2536,7 @@ pub mod tests {
 
         workspace
             .update(cx, |workspace, cx| {
-                ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx)
+                ProjectSearchView::new_search(workspace, &workspace::NewSearch, cx)
             })
             .unwrap();
         cx.background_executor.run_until_parked();
@@ -2536,7 +2822,7 @@ pub mod tests {
                             .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx))
                     });
 
-                    ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx)
+                    ProjectSearchView::new_search(workspace, &workspace::NewSearch, cx)
                 }
             })
             .unwrap();

crates/settings/Cargo.toml πŸ”—

@@ -14,7 +14,6 @@ test-support = ["gpui/test-support", "fs/test-support"]
 [dependencies]
 collections = { path = "../collections" }
 gpui = { path = "../gpui" }
-sqlez = { path = "../sqlez" }
 fs = { path = "../fs" }
 feature_flags = { path = "../feature_flags" }
 util = { path = "../util" }

crates/terminal/src/terminal.rs πŸ”—

@@ -62,15 +62,7 @@ use lazy_static::lazy_static;
 
 actions!(
     terminal,
-    [
-        Clear,
-        Copy,
-        Paste,
-        ShowCharacterPalette,
-        SearchTest,
-        SendText,
-        SendKeystroke,
-    ]
+    [Clear, Copy, Paste, ShowCharacterPalette, SearchTest,]
 );
 
 ///Scrolling is unbearably sluggish by default. Alacritty supports a configurable

crates/terminal_view/src/terminal_panel.rs πŸ”—

@@ -53,7 +53,7 @@ pub struct TerminalPanel {
 
 impl TerminalPanel {
     fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
-        let terminal_panel = cx.view().clone();
+        let terminal_panel = cx.view().downgrade();
         let pane = cx.new_view(|cx| {
             let mut pane = Pane::new(
                 workspace.weak_handle(),
@@ -77,14 +77,17 @@ impl TerminalPanel {
             pane.set_can_navigate(false, cx);
             pane.display_nav_history_buttons(false);
             pane.set_render_tab_bar_buttons(cx, move |pane, cx| {
+                let terminal_panel = terminal_panel.clone();
                 h_stack()
                     .gap_2()
                     .child(
                         IconButton::new("plus", Icon::Plus)
                             .icon_size(IconSize::Small)
-                            .on_click(cx.listener_for(&terminal_panel, |terminal_panel, _, cx| {
-                                terminal_panel.add_terminal(None, cx);
-                            }))
+                            .on_click(move |_, cx| {
+                                terminal_panel
+                                    .update(cx, |panel, cx| panel.add_terminal(None, cx))
+                                    .log_err();
+                            })
                             .tooltip(|cx| Tooltip::text("New Terminal", cx)),
                     )
                     .child({

crates/terminal_view/src/terminal_view.rs πŸ”—

@@ -57,7 +57,7 @@ pub struct SendText(String);
 #[derive(Clone, Debug, Default, Deserialize, PartialEq)]
 pub struct SendKeystroke(String);
 
-impl_actions!(terminal_view, [SendText, SendKeystroke]);
+impl_actions!(terminal, [SendText, SendKeystroke]);
 
 pub fn init(cx: &mut AppContext) {
     terminal_panel::init(cx);

crates/theme/src/styles/players.rs πŸ”—

@@ -131,6 +131,15 @@ impl PlayerColors {
         *self.0.last().unwrap()
     }
 
+    pub fn read_only(&self) -> PlayerColor {
+        let local = self.local();
+        PlayerColor {
+            cursor: local.cursor.grayscale(),
+            background: local.background.grayscale(),
+            selection: local.selection.grayscale(),
+        }
+    }
+
     pub fn color_for_participant(&self, participant_index: u32) -> PlayerColor {
         let len = self.0.len() - 1;
         self.0[(participant_index as usize % len) + 1]

crates/theme/src/themes/LICENSES πŸ”—

@@ -0,0 +1,1013 @@
+## [Andromeda](https://github.com/EliverLara/Andromeda)
+
+The MIT License (MIT)
+
+Copyright (c) 2017 <eliverlara@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Cave Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Cave Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Dune Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Dune Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Estuary Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Estuary Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Forest Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Forest Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Heath Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Heath Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Lakeside Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Lakeside Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Plateau Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Plateau Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Savanna Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Savanna Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Seaside Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Seaside Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Sulphurpool Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Atelier Sulphurpool Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
+
+The MIT License (MIT)
+
+Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Ayu Dark](https://github.com/dempfi/ayu)
+
+The MIT License (MIT)
+
+Copyright (c) 2016 Ike Ku
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Ayu Light](https://github.com/dempfi/ayu)
+
+The MIT License (MIT)
+
+Copyright (c) 2016 Ike Ku
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Ayu Mirage](https://github.com/dempfi/ayu)
+
+The MIT License (MIT)
+
+Copyright (c) 2016 Ike Ku
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Dark](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Dark Hard](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Dark Soft](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Light](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Light Hard](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Gruvbox Light Soft](https://github.com/morhetz/gruvbox)
+
+The MIT License (MIT)
+
+Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [One Dark](https://github.com/atom/atom/tree/master/packages/one-dark-ui)
+
+The MIT License (MIT)
+
+Copyright (c) 2014 GitHub Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [One Light](https://github.com/atom/atom/tree/master/packages/one-light-ui)
+
+The MIT License (MIT)
+
+Copyright (c) 2014 GitHub Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [RosΓ© Pine](https://github.com/edunfelt/base16-rose-pine-scheme)
+
+The MIT License (MIT)
+
+Copyright (c) 2021 Emilia Dunfelt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [RosΓ© Pine Dawn](https://github.com/edunfelt/base16-rose-pine-scheme)
+
+The MIT License (MIT)
+
+Copyright (c) 2021 Emilia Dunfelt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [RosΓ© Pine Moon](https://github.com/edunfelt/base16-rose-pine-scheme)
+
+The MIT License (MIT)
+
+Copyright (c) 2021 Emilia Dunfelt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Sandcastle](https://github.com/gessig/base16-sandcastle-scheme)
+
+The MIT License (MIT)
+
+Copyright (c) 2019 George Essig
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Solarized Dark](https://github.com/altercation/solarized)
+
+The MIT License (MIT)
+
+Copyright (c) 2011 Ethan Schoonover
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Solarized Light](https://github.com/altercation/solarized)
+
+The MIT License (MIT)
+
+Copyright (c) 2011 Ethan Schoonover
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************
+
+## [Summercamp](https://github.com/zoefiri/base16-sc)
+
+The MIT License (MIT)
+
+Copyright (c) 2019 Zoe FiriH
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+********************************************************************************

crates/theme/src/themes/atelier.rs πŸ”—

@@ -16,170 +16,170 @@ pub fn atelier() -> UserThemeFamily {
         author: "Zed Industries".into(),
         themes: vec![
             UserTheme {
-                name: "Atelier Estuary Light".into(),
-                appearance: Appearance::Light,
+                name: "Atelier Cave Dark".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x969585ff).into()),
-                        border_variant: Some(rgba(0xd1d0c6ff).into()),
-                        border_focused: Some(rgba(0xbbddc6ff).into()),
-                        border_selected: Some(rgba(0xbbddc6ff).into()),
+                        border: Some(rgba(0x56505eff).into()),
+                        border_variant: Some(rgba(0x332f38ff).into()),
+                        border_focused: Some(rgba(0x222953ff).into()),
+                        border_selected: Some(rgba(0x222953ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xadac9fff).into()),
-                        elevated_surface_background: Some(rgba(0xebeae3ff).into()),
-                        surface_background: Some(rgba(0xebeae3ff).into()),
-                        background: Some(rgba(0xc5c4b9ff).into()),
-                        panel_background: Some(rgba(0xebeae3ff).into()),
-                        element_background: Some(rgba(0xebeae3ff).into()),
-                        element_hover: Some(rgba(0xd1d0c6ff).into()),
-                        element_active: Some(rgba(0x989788ff).into()),
-                        element_selected: Some(rgba(0x989788ff).into()),
-                        element_disabled: Some(rgba(0xebeae3ff).into()),
-                        drop_target_background: Some(rgba(0x61604f80).into()),
+                        border_disabled: Some(rgba(0x48434fff).into()),
+                        elevated_surface_background: Some(rgba(0x221f26ff).into()),
+                        surface_background: Some(rgba(0x221f26ff).into()),
+                        background: Some(rgba(0x3a353fff).into()),
+                        panel_background: Some(rgba(0x221f26ff).into()),
+                        element_background: Some(rgba(0x221f26ff).into()),
+                        element_hover: Some(rgba(0x332f38ff).into()),
+                        element_active: Some(rgba(0x544f5cff).into()),
+                        element_selected: Some(rgba(0x544f5cff).into()),
+                        element_disabled: Some(rgba(0x221f26ff).into()),
+                        drop_target_background: Some(rgba(0x89859180).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xd1d0c6ff).into()),
-                        ghost_element_active: Some(rgba(0x989788ff).into()),
-                        ghost_element_selected: Some(rgba(0x989788ff).into()),
-                        ghost_element_disabled: Some(rgba(0xebeae3ff).into()),
-                        text: Some(rgba(0x22221bff).into()),
-                        text_muted: Some(rgba(0x61604fff).into()),
-                        text_placeholder: Some(rgba(0x767463ff).into()),
-                        text_disabled: Some(rgba(0x767463ff).into()),
-                        text_accent: Some(rgba(0x38a166ff).into()),
-                        icon: Some(rgba(0x22221bff).into()),
-                        icon_muted: Some(rgba(0x61604fff).into()),
-                        icon_disabled: Some(rgba(0x767463ff).into()),
-                        icon_placeholder: Some(rgba(0x61604fff).into()),
-                        icon_accent: Some(rgba(0x38a166ff).into()),
-                        status_bar_background: Some(rgba(0xc5c4b9ff).into()),
-                        title_bar_background: Some(rgba(0xc5c4b9ff).into()),
-                        toolbar_background: Some(rgba(0xf4f3ecff).into()),
-                        tab_bar_background: Some(rgba(0xebeae3ff).into()),
-                        tab_inactive_background: Some(rgba(0xebeae3ff).into()),
-                        tab_active_background: Some(rgba(0xf4f3ecff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x22221b4c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xd1d0c6ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xd1d0c6ff).into()),
+                        ghost_element_hover: Some(rgba(0x332f38ff).into()),
+                        ghost_element_active: Some(rgba(0x544f5cff).into()),
+                        ghost_element_selected: Some(rgba(0x544f5cff).into()),
+                        ghost_element_disabled: Some(rgba(0x221f26ff).into()),
+                        text: Some(rgba(0xefecf4ff).into()),
+                        text_muted: Some(rgba(0x898591ff).into()),
+                        text_placeholder: Some(rgba(0x756f7eff).into()),
+                        text_disabled: Some(rgba(0x756f7eff).into()),
+                        text_accent: Some(rgba(0x576ddaff).into()),
+                        icon: Some(rgba(0xefecf4ff).into()),
+                        icon_muted: Some(rgba(0x898591ff).into()),
+                        icon_disabled: Some(rgba(0x756f7eff).into()),
+                        icon_placeholder: Some(rgba(0x898591ff).into()),
+                        icon_accent: Some(rgba(0x576ddaff).into()),
+                        status_bar_background: Some(rgba(0x3a353fff).into()),
+                        title_bar_background: Some(rgba(0x3a353fff).into()),
+                        toolbar_background: Some(rgba(0x19171cff).into()),
+                        tab_bar_background: Some(rgba(0x221f26ff).into()),
+                        tab_inactive_background: Some(rgba(0x221f26ff).into()),
+                        tab_active_background: Some(rgba(0x19171cff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xefecf44c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x332f38ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x332f38ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xedece5ff).into()),
-                        editor_foreground: Some(rgba(0x302f27ff).into()),
-                        editor_background: Some(rgba(0xf4f3ecff).into()),
-                        editor_gutter_background: Some(rgba(0xf4f3ecff).into()),
-                        editor_subheader_background: Some(rgba(0xebeae3ff).into()),
-                        editor_active_line_background: Some(rgba(0xebeae3bf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xebeae3ff).into()),
-                        editor_line_number: Some(rgba(0x22221b59).into()),
-                        editor_active_line_number: Some(rgba(0x22221bff).into()),
-                        editor_invisible: Some(rgba(0x61604fff).into()),
-                        editor_wrap_guide: Some(rgba(0x22221b0d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x22221b1a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x38a1661a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0x7a786766).into()),
-                        terminal_background: Some(rgba(0xf4f3ecff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x898775ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xe4af96ff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xc0ca93ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xd7ca8dff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0xa0d1b0ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xcfb4bcff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0xaecea1ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x22221bff).into()),
-                        terminal_ansi_black: Some(rgba(0xf4f3ecff).into()),
-                        terminal_ansi_red: Some(rgba(0xba6337ff).into()),
-                        terminal_ansi_green: Some(rgba(0x7d9728ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xa59810ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x38a166ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0x9d6c7cff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x5c9d49ff).into()),
-                        terminal_ansi_white: Some(rgba(0x22221bff).into()),
-                        link_text_hover: Some(rgba(0x38a166ff).into()),
+                        scrollbar_track_border: Some(rgba(0x201e24ff).into()),
+                        editor_foreground: Some(rgba(0xe2dfe7ff).into()),
+                        editor_background: Some(rgba(0x19171cff).into()),
+                        editor_gutter_background: Some(rgba(0x19171cff).into()),
+                        editor_subheader_background: Some(rgba(0x221f26ff).into()),
+                        editor_active_line_background: Some(rgba(0x221f26bf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x221f26ff).into()),
+                        editor_line_number: Some(rgba(0xefecf459).into()),
+                        editor_active_line_number: Some(rgba(0xefecf4ff).into()),
+                        editor_invisible: Some(rgba(0x898591ff).into()),
+                        editor_wrap_guide: Some(rgba(0xefecf40d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xefecf41a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x576dda1a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0x726c7a66).into()),
+                        terminal_background: Some(rgba(0x19171cff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x635d6bff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x5c283cff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x1f4747ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x4e3821ff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x2d376fff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x60255bff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x26445eff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xefecf4ff).into()),
+                        terminal_ansi_black: Some(rgba(0x19171cff).into()),
+                        terminal_ansi_red: Some(rgba(0xbe4678ff).into()),
+                        terminal_ansi_green: Some(rgba(0x2c9292ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xa06e3bff).into()),
+                        terminal_ansi_blue: Some(rgba(0x576ddaff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xbf41bfff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x3a8bc6ff).into()),
+                        terminal_ansi_white: Some(rgba(0xefecf4ff).into()),
+                        link_text_hover: Some(rgba(0x576ddaff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xa59810ff).into()),
-                        conflict_background: Some(rgba(0xf0e9d1ff).into()),
-                        conflict_border: Some(rgba(0xe3d8adff).into()),
-                        created: Some(rgba(0x7d9728ff).into()),
-                        created_background: Some(rgba(0xe6e9d3ff).into()),
-                        created_border: Some(rgba(0xd2d8b1ff).into()),
-                        deleted: Some(rgba(0xba6337ff).into()),
-                        deleted_background: Some(rgba(0xf6ded4ff).into()),
-                        deleted_border: Some(rgba(0xedc5b3ff).into()),
-                        error: Some(rgba(0xba6337ff).into()),
-                        error_background: Some(rgba(0xf6ded4ff).into()),
-                        error_border: Some(rgba(0xedc5b3ff).into()),
-                        hidden: Some(rgba(0x767463ff).into()),
-                        hidden_background: Some(rgba(0xc5c4b9ff).into()),
-                        hidden_border: Some(rgba(0xadac9fff).into()),
-                        hint: Some(rgba(0x768962ff).into()),
-                        hint_background: Some(rgba(0xd9ecdfff).into()),
-                        hint_border: Some(rgba(0xbbddc6ff).into()),
-                        ignored: Some(rgba(0x61604fff).into()),
-                        ignored_background: Some(rgba(0xc5c4b9ff).into()),
-                        ignored_border: Some(rgba(0x969585ff).into()),
-                        info: Some(rgba(0x38a166ff).into()),
-                        info_background: Some(rgba(0xd9ecdfff).into()),
-                        info_border: Some(rgba(0xbbddc6ff).into()),
-                        modified: Some(rgba(0xa59810ff).into()),
-                        modified_background: Some(rgba(0xf0e9d1ff).into()),
-                        modified_border: Some(rgba(0xe3d8adff).into()),
-                        predictive: Some(rgba(0x879a72ff).into()),
-                        predictive_background: Some(rgba(0xe6e9d3ff).into()),
-                        predictive_border: Some(rgba(0xd2d8b1ff).into()),
-                        renamed: Some(rgba(0x38a166ff).into()),
-                        renamed_background: Some(rgba(0xd9ecdfff).into()),
-                        renamed_border: Some(rgba(0xbbddc6ff).into()),
-                        success: Some(rgba(0x7d9728ff).into()),
-                        success_background: Some(rgba(0xe6e9d3ff).into()),
-                        success_border: Some(rgba(0xd2d8b1ff).into()),
-                        unreachable: Some(rgba(0x61604fff).into()),
-                        unreachable_background: Some(rgba(0xc5c4b9ff).into()),
-                        unreachable_border: Some(rgba(0x969585ff).into()),
-                        warning: Some(rgba(0xa59810ff).into()),
-                        warning_background: Some(rgba(0xf0e9d1ff).into()),
-                        warning_border: Some(rgba(0xe3d8adff).into()),
+                        conflict: Some(rgba(0xa06e3bff).into()),
+                        conflict_background: Some(rgba(0x231a12ff).into()),
+                        conflict_border: Some(rgba(0x392a1aff).into()),
+                        created: Some(rgba(0x2c9292ff).into()),
+                        created_background: Some(rgba(0x132020ff).into()),
+                        created_border: Some(rgba(0x1a3434ff).into()),
+                        deleted: Some(rgba(0xbe4678ff).into()),
+                        deleted_background: Some(rgba(0x28151cff).into()),
+                        deleted_border: Some(rgba(0x421f2dff).into()),
+                        error: Some(rgba(0xbe4678ff).into()),
+                        error_background: Some(rgba(0x28151cff).into()),
+                        error_border: Some(rgba(0x421f2dff).into()),
+                        hidden: Some(rgba(0x756f7eff).into()),
+                        hidden_background: Some(rgba(0x3a353fff).into()),
+                        hidden_border: Some(rgba(0x48434fff).into()),
+                        hint: Some(rgba(0x716998ff).into()),
+                        hint_background: Some(rgba(0x161a36ff).into()),
+                        hint_border: Some(rgba(0x222953ff).into()),
+                        ignored: Some(rgba(0x898591ff).into()),
+                        ignored_background: Some(rgba(0x3a353fff).into()),
+                        ignored_border: Some(rgba(0x56505eff).into()),
+                        info: Some(rgba(0x576ddaff).into()),
+                        info_background: Some(rgba(0x161a36ff).into()),
+                        info_border: Some(rgba(0x222953ff).into()),
+                        modified: Some(rgba(0xa06e3bff).into()),
+                        modified_background: Some(rgba(0x231a12ff).into()),
+                        modified_border: Some(rgba(0x392a1aff).into()),
+                        predictive: Some(rgba(0x625887ff).into()),
+                        predictive_background: Some(rgba(0x132020ff).into()),
+                        predictive_border: Some(rgba(0x1a3434ff).into()),
+                        renamed: Some(rgba(0x576ddaff).into()),
+                        renamed_background: Some(rgba(0x161a36ff).into()),
+                        renamed_border: Some(rgba(0x222953ff).into()),
+                        success: Some(rgba(0x2c9292ff).into()),
+                        success_background: Some(rgba(0x132020ff).into()),
+                        success_border: Some(rgba(0x1a3434ff).into()),
+                        unreachable: Some(rgba(0x898591ff).into()),
+                        unreachable_background: Some(rgba(0x3a353fff).into()),
+                        unreachable_border: Some(rgba(0x56505eff).into()),
+                        warning: Some(rgba(0xa06e3bff).into()),
+                        warning_background: Some(rgba(0x231a12ff).into()),
+                        warning_border: Some(rgba(0x392a1aff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x38a166ff).into(),
-                            background: rgba(0x38a166ff).into(),
-                            selection: rgba(0x38a1663d).into(),
+                            cursor: rgba(0x576ddaff).into(),
+                            background: rgba(0x576ddaff).into(),
+                            selection: rgba(0x576dda3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x9d6c7cff).into(),
-                            background: rgba(0x9d6c7cff).into(),
-                            selection: rgba(0x9d6c7c3d).into(),
+                            cursor: rgba(0xbf41bfff).into(),
+                            background: rgba(0xbf41bfff).into(),
+                            selection: rgba(0xbf41bf3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xae7315ff).into(),
-                            background: rgba(0xae7315ff).into(),
-                            selection: rgba(0xae73153d).into(),
+                            cursor: rgba(0xaa573cff).into(),
+                            background: rgba(0xaa573cff).into(),
+                            selection: rgba(0xaa573c3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x609182ff).into(),
-                            background: rgba(0x609182ff).into(),
-                            selection: rgba(0x6091823d).into(),
+                            cursor: rgba(0x955ae6ff).into(),
+                            background: rgba(0x955ae6ff).into(),
+                            selection: rgba(0x955ae63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x5c9d49ff).into(),
-                            background: rgba(0x5c9d49ff).into(),
-                            selection: rgba(0x5c9d493d).into(),
+                            cursor: rgba(0x3a8bc6ff).into(),
+                            background: rgba(0x3a8bc6ff).into(),
+                            selection: rgba(0x3a8bc63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xba6337ff).into(),
-                            background: rgba(0xba6337ff).into(),
-                            selection: rgba(0xba63373d).into(),
+                            cursor: rgba(0xbe4678ff).into(),
+                            background: rgba(0xbe4678ff).into(),
+                            selection: rgba(0xbe46783d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xa59810ff).into(),
-                            background: rgba(0xa59810ff).into(),
-                            selection: rgba(0xa598103d).into(),
+                            cursor: rgba(0xa06e3bff).into(),
+                            background: rgba(0xa06e3bff).into(),
+                            selection: rgba(0xa06e3b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x7d9728ff).into(),
-                            background: rgba(0x7d9728ff).into(),
-                            selection: rgba(0x7d97283d).into(),
+                            cursor: rgba(0x2c9292ff).into(),
+                            background: rgba(0x2c9292ff).into(),
+                            selection: rgba(0x2c92923d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -187,63 +187,63 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9728ff).into()),
+                                    color: Some(rgba(0x2c9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x878573ff).into()),
+                                    color: Some(rgba(0x655f6dff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f5e4eff).into()),
+                                    color: Some(rgba(0x8b8792ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9728ff).into()),
+                                    color: Some(rgba(0x2c9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x22221bff).into()),
+                                    color: Some(rgba(0xefecf4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -251,35 +251,35 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xae7315ff).into()),
+                                    color: Some(rgba(0xaa573cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x36a166ff).into()),
+                                    color: Some(rgba(0x576ddbff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function.method".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x36a166ff).into()),
+                                    color: Some(rgba(0x576ddbff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function.special.definition".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa5980dff).into()),
+                                    color: Some(rgba(0xa06e3bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x768962ff).into()),
+                                    color: Some(rgba(0x716998ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -287,21 +287,21 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f9182ff).into()),
+                                    color: Some(rgba(0x955ae7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xae7315ff).into()),
+                                    color: Some(rgba(0xaa573cff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -309,28 +309,28 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "link_uri".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9728ff).into()),
+                                    color: Some(rgba(0x2c9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "number".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xae7313ff).into()),
+                                    color: Some(rgba(0xaa573cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f5e4eff).into()),
+                                    color: Some(rgba(0x8b8792ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x879a72ff).into()),
+                                    color: Some(rgba(0x625887ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -338,112 +338,112 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x22221bff).into()),
+                                    color: Some(rgba(0xefecf4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x302f27ff).into()),
+                                    color: Some(rgba(0xe2dfe7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xba6236ff).into()),
+                                    color: Some(rgba(0xbe4678ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x302f27ff).into()),
+                                    color: Some(rgba(0xe2dfe7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f5e4eff).into()),
+                                    color: Some(rgba(0x8b8792ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f5e4eff).into()),
+                                    color: Some(rgba(0x8b8792ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x302f27ff).into()),
+                                    color: Some(rgba(0xe2dfe7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9d6c7cff).into()),
+                                    color: Some(rgba(0xbf40bfff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9726ff).into()),
+                                    color: Some(rgba(0x2a9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f5e4eff).into()),
+                                    color: Some(rgba(0x8b8792ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5b9d48ff).into()),
+                                    color: Some(rgba(0x398bc6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9d6c7cff).into()),
+                                    color: Some(rgba(0xbf40bfff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9726ff).into()),
+                                    color: Some(rgba(0x2a9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x38a166ff).into()),
+                                    color: Some(rgba(0x576ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xae7315ff).into()),
+                                    color: Some(rgba(0xaa573cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x22221bff).into()),
+                                    color: Some(rgba(0xefecf4ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -451,28 +451,28 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "type".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa5980dff).into()),
+                                    color: Some(rgba(0xa06e3bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x302f27ff).into()),
+                                    color: Some(rgba(0xe2dfe7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5f9182ff).into()),
+                                    color: Some(rgba(0x955ae7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa5980dff).into()),
+                                    color: Some(rgba(0xa06e3bff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -481,170 +481,170 @@ pub fn atelier() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "Atelier Forest Dark".into(),
-                appearance: Appearance::Dark,
+                name: "Atelier Cave Light".into(),
+                appearance: Appearance::Light,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x665f5cff).into()),
-                        border_variant: Some(rgba(0x3b3431ff).into()),
-                        border_focused: Some(rgba(0x192e5bff).into()),
-                        border_selected: Some(rgba(0x192e5bff).into()),
+                        border: Some(rgba(0x8f8b96ff).into()),
+                        border_variant: Some(rgba(0xcbc8d1ff).into()),
+                        border_focused: Some(rgba(0xc9c8f3ff).into()),
+                        border_selected: Some(rgba(0xc9c8f3ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0x554e4bff).into()),
-                        elevated_surface_background: Some(rgba(0x27211eff).into()),
-                        surface_background: Some(rgba(0x27211eff).into()),
-                        background: Some(rgba(0x443c39ff).into()),
-                        panel_background: Some(rgba(0x27211eff).into()),
-                        element_background: Some(rgba(0x27211eff).into()),
-                        element_hover: Some(rgba(0x3b3431ff).into()),
-                        element_active: Some(rgba(0x645d5aff).into()),
-                        element_selected: Some(rgba(0x645d5aff).into()),
-                        element_disabled: Some(rgba(0x27211eff).into()),
-                        drop_target_background: Some(rgba(0xa79f9d80).into()),
+                        border_disabled: Some(rgba(0xa7a3adff).into()),
+                        elevated_surface_background: Some(rgba(0xe6e3ebff).into()),
+                        surface_background: Some(rgba(0xe6e3ebff).into()),
+                        background: Some(rgba(0xbfbcc5ff).into()),
+                        panel_background: Some(rgba(0xe6e3ebff).into()),
+                        element_background: Some(rgba(0xe6e3ebff).into()),
+                        element_hover: Some(rgba(0xcbc8d1ff).into()),
+                        element_active: Some(rgba(0x918d98ff).into()),
+                        element_selected: Some(rgba(0x918d98ff).into()),
+                        element_disabled: Some(rgba(0xe6e3ebff).into()),
+                        drop_target_background: Some(rgba(0x5a546280).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0x3b3431ff).into()),
-                        ghost_element_active: Some(rgba(0x645d5aff).into()),
-                        ghost_element_selected: Some(rgba(0x645d5aff).into()),
-                        ghost_element_disabled: Some(rgba(0x27211eff).into()),
-                        text: Some(rgba(0xf1efeeff).into()),
-                        text_muted: Some(rgba(0xa79f9dff).into()),
-                        text_placeholder: Some(rgba(0x8e8683ff).into()),
-                        text_disabled: Some(rgba(0x8e8683ff).into()),
-                        text_accent: Some(rgba(0x417ee6ff).into()),
-                        icon: Some(rgba(0xf1efeeff).into()),
-                        icon_muted: Some(rgba(0xa79f9dff).into()),
-                        icon_disabled: Some(rgba(0x8e8683ff).into()),
-                        icon_placeholder: Some(rgba(0xa79f9dff).into()),
-                        icon_accent: Some(rgba(0x417ee6ff).into()),
-                        status_bar_background: Some(rgba(0x443c39ff).into()),
-                        title_bar_background: Some(rgba(0x443c39ff).into()),
-                        toolbar_background: Some(rgba(0x1b1918ff).into()),
-                        tab_bar_background: Some(rgba(0x27211eff).into()),
-                        tab_inactive_background: Some(rgba(0x27211eff).into()),
-                        tab_active_background: Some(rgba(0x1b1918ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0xf1efee4c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0x3b3431ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0x3b3431ff).into()),
+                        ghost_element_hover: Some(rgba(0xcbc8d1ff).into()),
+                        ghost_element_active: Some(rgba(0x918d98ff).into()),
+                        ghost_element_selected: Some(rgba(0x918d98ff).into()),
+                        ghost_element_disabled: Some(rgba(0xe6e3ebff).into()),
+                        text: Some(rgba(0x19171cff).into()),
+                        text_muted: Some(rgba(0x5a5462ff).into()),
+                        text_placeholder: Some(rgba(0x6e6876ff).into()),
+                        text_disabled: Some(rgba(0x6e6876ff).into()),
+                        text_accent: Some(rgba(0x586ddaff).into()),
+                        icon: Some(rgba(0x19171cff).into()),
+                        icon_muted: Some(rgba(0x5a5462ff).into()),
+                        icon_disabled: Some(rgba(0x6e6876ff).into()),
+                        icon_placeholder: Some(rgba(0x5a5462ff).into()),
+                        icon_accent: Some(rgba(0x586ddaff).into()),
+                        status_bar_background: Some(rgba(0xbfbcc5ff).into()),
+                        title_bar_background: Some(rgba(0xbfbcc5ff).into()),
+                        toolbar_background: Some(rgba(0xefecf4ff).into()),
+                        tab_bar_background: Some(rgba(0xe6e3ebff).into()),
+                        tab_inactive_background: Some(rgba(0xe6e3ebff).into()),
+                        tab_active_background: Some(rgba(0xefecf4ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0x19171c4c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0xcbc8d1ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0xcbc8d1ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0x251f1dff).into()),
-                        editor_foreground: Some(rgba(0xe6e2e0ff).into()),
-                        editor_background: Some(rgba(0x1b1918ff).into()),
-                        editor_gutter_background: Some(rgba(0x1b1918ff).into()),
-                        editor_subheader_background: Some(rgba(0x27211eff).into()),
-                        editor_active_line_background: Some(rgba(0x27211ebf).into()),
-                        editor_highlighted_line_background: Some(rgba(0x27211eff).into()),
-                        editor_line_number: Some(rgba(0xf1efee59).into()),
-                        editor_active_line_number: Some(rgba(0xf1efeeff).into()),
-                        editor_invisible: Some(rgba(0xa79f9dff).into()),
-                        editor_wrap_guide: Some(rgba(0xf1efee0d).into()),
-                        editor_active_wrap_guide: Some(rgba(0xf1efee1a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x417ee61a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0x89817e66).into()),
-                        terminal_background: Some(rgba(0x1b1918ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x746c69ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0x8c1223ff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0x3e491aff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0x674115ff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x213f78ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0x662186ff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x264958ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0xf1efeeff).into()),
-                        terminal_ansi_black: Some(rgba(0x1b1918ff).into()),
-                        terminal_ansi_red: Some(rgba(0xf22d40ff).into()),
-                        terminal_ansi_green: Some(rgba(0x7b9727ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xc38419ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x417ee6ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0xc340f2ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x3e97b8ff).into()),
-                        terminal_ansi_white: Some(rgba(0xf1efeeff).into()),
-                        link_text_hover: Some(rgba(0x417ee6ff).into()),
+                        scrollbar_track_border: Some(rgba(0xe8e5edff).into()),
+                        editor_foreground: Some(rgba(0x26232aff).into()),
+                        editor_background: Some(rgba(0xefecf4ff).into()),
+                        editor_gutter_background: Some(rgba(0xefecf4ff).into()),
+                        editor_subheader_background: Some(rgba(0xe6e3ebff).into()),
+                        editor_active_line_background: Some(rgba(0xe6e3ebbf).into()),
+                        editor_highlighted_line_background: Some(rgba(0xe6e3ebff).into()),
+                        editor_line_number: Some(rgba(0x19171c59).into()),
+                        editor_active_line_number: Some(rgba(0x19171cff).into()),
+                        editor_invisible: Some(rgba(0x5a5462ff).into()),
+                        editor_wrap_guide: Some(rgba(0x19171c0d).into()),
+                        editor_active_wrap_guide: Some(rgba(0x19171c1a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x586dda1a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0x726c7a66).into()),
+                        terminal_background: Some(rgba(0xefecf4ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x807b89ff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0xe3a4b9ff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x9dc8c8ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0xd4b499ff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0xb3b3eeff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0xe3a4dfff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0xa6c4e3ff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0x19171cff).into()),
+                        terminal_ansi_black: Some(rgba(0xefecf4ff).into()),
+                        terminal_ansi_red: Some(rgba(0xbe4778ff).into()),
+                        terminal_ansi_green: Some(rgba(0x2c9292ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xa06e3cff).into()),
+                        terminal_ansi_blue: Some(rgba(0x586ddaff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xbf41bfff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x3b8bc6ff).into()),
+                        terminal_ansi_white: Some(rgba(0x19171cff).into()),
+                        link_text_hover: Some(rgba(0x586ddaff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xc38419ff).into()),
-                        conflict_background: Some(rgba(0x371d0dff).into()),
-                        conflict_border: Some(rgba(0x4f2f12ff).into()),
-                        created: Some(rgba(0x7b9727ff).into()),
-                        created_background: Some(rgba(0x1d2110ff).into()),
-                        created_border: Some(rgba(0x2e3516ff).into()),
-                        deleted: Some(rgba(0xf22d40ff).into()),
-                        deleted_background: Some(rgba(0x550512ff).into()),
-                        deleted_border: Some(rgba(0x710c1bff).into()),
-                        error: Some(rgba(0xf22d40ff).into()),
-                        error_background: Some(rgba(0x550512ff).into()),
-                        error_border: Some(rgba(0x710c1bff).into()),
-                        hidden: Some(rgba(0x8e8683ff).into()),
-                        hidden_background: Some(rgba(0x443c39ff).into()),
-                        hidden_border: Some(rgba(0x554e4bff).into()),
-                        hint: Some(rgba(0xa87187ff).into()),
-                        hint_background: Some(rgba(0x0f1d3dff).into()),
-                        hint_border: Some(rgba(0x192e5bff).into()),
-                        ignored: Some(rgba(0xa79f9dff).into()),
-                        ignored_background: Some(rgba(0x443c39ff).into()),
-                        ignored_border: Some(rgba(0x665f5cff).into()),
-                        info: Some(rgba(0x417ee6ff).into()),
-                        info_background: Some(rgba(0x0f1d3dff).into()),
-                        info_border: Some(rgba(0x192e5bff).into()),
-                        modified: Some(rgba(0xc38419ff).into()),
-                        modified_background: Some(rgba(0x371d0dff).into()),
-                        modified_border: Some(rgba(0x4f2f12ff).into()),
-                        predictive: Some(rgba(0x8f5b71ff).into()),
-                        predictive_background: Some(rgba(0x1d2110ff).into()),
-                        predictive_border: Some(rgba(0x2e3516ff).into()),
-                        renamed: Some(rgba(0x417ee6ff).into()),
-                        renamed_background: Some(rgba(0x0f1d3dff).into()),
-                        renamed_border: Some(rgba(0x192e5bff).into()),
-                        success: Some(rgba(0x7b9727ff).into()),
-                        success_background: Some(rgba(0x1d2110ff).into()),
-                        success_border: Some(rgba(0x2e3516ff).into()),
-                        unreachable: Some(rgba(0xa79f9dff).into()),
-                        unreachable_background: Some(rgba(0x443c39ff).into()),
-                        unreachable_border: Some(rgba(0x665f5cff).into()),
-                        warning: Some(rgba(0xc38419ff).into()),
-                        warning_background: Some(rgba(0x371d0dff).into()),
-                        warning_border: Some(rgba(0x4f2f12ff).into()),
+                        conflict: Some(rgba(0xa06e3cff).into()),
+                        conflict_background: Some(rgba(0xeee0d5ff).into()),
+                        conflict_border: Some(rgba(0xe0c9b5ff).into()),
+                        created: Some(rgba(0x2c9292ff).into()),
+                        created_background: Some(rgba(0xd7e9e8ff).into()),
+                        created_border: Some(rgba(0xb9d7d6ff).into()),
+                        deleted: Some(rgba(0xbe4778ff).into()),
+                        deleted_background: Some(rgba(0xf5dae2ff).into()),
+                        deleted_border: Some(rgba(0xecbecdff).into()),
+                        error: Some(rgba(0xbe4778ff).into()),
+                        error_background: Some(rgba(0xf5dae2ff).into()),
+                        error_border: Some(rgba(0xecbecdff).into()),
+                        hidden: Some(rgba(0x6e6876ff).into()),
+                        hidden_background: Some(rgba(0xbfbcc5ff).into()),
+                        hidden_border: Some(rgba(0xa7a3adff).into()),
+                        hint: Some(rgba(0x786e9dff).into()),
+                        hint_background: Some(rgba(0xe1e0f9ff).into()),
+                        hint_border: Some(rgba(0xc9c8f3ff).into()),
+                        ignored: Some(rgba(0x5a5462ff).into()),
+                        ignored_background: Some(rgba(0xbfbcc5ff).into()),
+                        ignored_border: Some(rgba(0x8f8b96ff).into()),
+                        info: Some(rgba(0x586ddaff).into()),
+                        info_background: Some(rgba(0xe1e0f9ff).into()),
+                        info_border: Some(rgba(0xc9c8f3ff).into()),
+                        modified: Some(rgba(0xa06e3cff).into()),
+                        modified_background: Some(rgba(0xeee0d5ff).into()),
+                        modified_border: Some(rgba(0xe0c9b5ff).into()),
+                        predictive: Some(rgba(0x887fafff).into()),
+                        predictive_background: Some(rgba(0xd7e9e8ff).into()),
+                        predictive_border: Some(rgba(0xb9d7d6ff).into()),
+                        renamed: Some(rgba(0x586ddaff).into()),
+                        renamed_background: Some(rgba(0xe1e0f9ff).into()),
+                        renamed_border: Some(rgba(0xc9c8f3ff).into()),
+                        success: Some(rgba(0x2c9292ff).into()),
+                        success_background: Some(rgba(0xd7e9e8ff).into()),
+                        success_border: Some(rgba(0xb9d7d6ff).into()),
+                        unreachable: Some(rgba(0x5a5462ff).into()),
+                        unreachable_background: Some(rgba(0xbfbcc5ff).into()),
+                        unreachable_border: Some(rgba(0x8f8b96ff).into()),
+                        warning: Some(rgba(0xa06e3cff).into()),
+                        warning_background: Some(rgba(0xeee0d5ff).into()),
+                        warning_border: Some(rgba(0xe0c9b5ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x417ee6ff).into(),
-                            background: rgba(0x417ee6ff).into(),
-                            selection: rgba(0x417ee63d).into(),
+                            cursor: rgba(0x586ddaff).into(),
+                            background: rgba(0x586ddaff).into(),
+                            selection: rgba(0x586dda3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xc340f2ff).into(),
-                            background: rgba(0xc340f2ff).into(),
-                            selection: rgba(0xc340f23d).into(),
+                            cursor: rgba(0xbf41bfff).into(),
+                            background: rgba(0xbf41bfff).into(),
+                            selection: rgba(0xbf41bf3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xdf5321ff).into(),
-                            background: rgba(0xdf5321ff).into(),
-                            selection: rgba(0xdf53213d).into(),
+                            cursor: rgba(0xaa583dff).into(),
+                            background: rgba(0xaa583dff).into(),
+                            selection: rgba(0xaa583d3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x6666e9ff).into(),
-                            background: rgba(0x6666e9ff).into(),
-                            selection: rgba(0x6666e93d).into(),
+                            cursor: rgba(0x955be6ff).into(),
+                            background: rgba(0x955be6ff).into(),
+                            selection: rgba(0x955be63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x3e97b8ff).into(),
-                            background: rgba(0x3e97b8ff).into(),
-                            selection: rgba(0x3e97b83d).into(),
+                            cursor: rgba(0x3b8bc6ff).into(),
+                            background: rgba(0x3b8bc6ff).into(),
+                            selection: rgba(0x3b8bc63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xf22d40ff).into(),
-                            background: rgba(0xf22d40ff).into(),
-                            selection: rgba(0xf22d403d).into(),
+                            cursor: rgba(0xbe4778ff).into(),
+                            background: rgba(0xbe4778ff).into(),
+                            selection: rgba(0xbe47783d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xc38419ff).into(),
-                            background: rgba(0xc38419ff).into(),
-                            selection: rgba(0xc384193d).into(),
+                            cursor: rgba(0xa06e3cff).into(),
+                            background: rgba(0xa06e3cff).into(),
+                            selection: rgba(0xa06e3c3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x7b9727ff).into(),
-                            background: rgba(0x7b9727ff).into(),
-                            selection: rgba(0x7b97273d).into(),
+                            cursor: rgba(0x2c9292ff).into(),
+                            background: rgba(0x2c9292ff).into(),
+                            selection: rgba(0x2c92923d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -652,63 +652,63 @@ pub fn atelier() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x417ee6ff).into()),
+                                    color: Some(rgba(0x586ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7b9727ff).into()),
+                                    color: Some(rgba(0x2c9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x766e6bff).into()),
+                                    color: Some(rgba(0x7e7887ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa8a19fff).into()),
+                                    color: Some(rgba(0x585260ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7b9727ff).into()),
+                                    color: Some(rgba(0x2c9292ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x417ee6ff).into()),
+                                    color: Some(rgba(0x586ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xf1efeeff).into()),
+                                    color: Some(rgba(0x19171cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x417ee6ff).into()),
+                                    color: Some(rgba(0x586ddaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x417ee6ff).into()),
+                                    color: Some(rgba(0x586ddaff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },

crates/theme/src/themes/gruvbox.rs πŸ”—

@@ -16,170 +16,170 @@ pub fn gruvbox() -> UserThemeFamily {
         author: "Zed Industries".into(),
         themes: vec![
             UserTheme {
-                name: "Gruvbox Light Hard".into(),
-                appearance: Appearance::Light,
+                name: "Gruvbox Dark".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0xc9b99aff).into()),
-                        border_variant: Some(rgba(0xddcca7ff).into()),
-                        border_focused: Some(rgba(0xaec6cdff).into()),
-                        border_selected: Some(rgba(0xaec6cdff).into()),
+                        border: Some(rgba(0x5b534dff).into()),
+                        border_variant: Some(rgba(0x494340ff).into()),
+                        border_focused: Some(rgba(0x303a36ff).into()),
+                        border_selected: Some(rgba(0x303a36ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xd1c09eff).into()),
-                        elevated_surface_background: Some(rgba(0xecddb5ff).into()),
-                        surface_background: Some(rgba(0xecddb5ff).into()),
-                        background: Some(rgba(0xd9c8a4ff).into()),
-                        panel_background: Some(rgba(0xecddb5ff).into()),
-                        element_background: Some(rgba(0xecddb5ff).into()),
-                        element_hover: Some(rgba(0xddcca7ff).into()),
-                        element_active: Some(rgba(0xc9b99aff).into()),
-                        element_selected: Some(rgba(0xc9b99aff).into()),
-                        element_disabled: Some(rgba(0xecddb5ff).into()),
-                        drop_target_background: Some(rgba(0x5f565080).into()),
+                        border_disabled: Some(rgba(0x544c48ff).into()),
+                        elevated_surface_background: Some(rgba(0x3a3735ff).into()),
+                        surface_background: Some(rgba(0x3a3735ff).into()),
+                        background: Some(rgba(0x4c4642ff).into()),
+                        panel_background: Some(rgba(0x3a3735ff).into()),
+                        element_background: Some(rgba(0x3a3735ff).into()),
+                        element_hover: Some(rgba(0x494340ff).into()),
+                        element_active: Some(rgba(0x5b524cff).into()),
+                        element_selected: Some(rgba(0x5b524cff).into()),
+                        element_disabled: Some(rgba(0x3a3735ff).into()),
+                        drop_target_background: Some(rgba(0xc5b59780).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xddcca7ff).into()),
-                        ghost_element_active: Some(rgba(0xc9b99aff).into()),
-                        ghost_element_selected: Some(rgba(0xc9b99aff).into()),
-                        ghost_element_disabled: Some(rgba(0xecddb5ff).into()),
-                        text: Some(rgba(0x282828ff).into()),
-                        text_muted: Some(rgba(0x5f5650ff).into()),
-                        text_placeholder: Some(rgba(0x8a7c6fff).into()),
-                        text_disabled: Some(rgba(0x8a7c6fff).into()),
-                        text_accent: Some(rgba(0x0b6678ff).into()),
-                        icon: Some(rgba(0x282828ff).into()),
-                        icon_muted: Some(rgba(0x5f5650ff).into()),
-                        icon_disabled: Some(rgba(0x8a7c6fff).into()),
-                        icon_placeholder: Some(rgba(0x5f5650ff).into()),
-                        icon_accent: Some(rgba(0x0b6678ff).into()),
-                        status_bar_background: Some(rgba(0xd9c8a4ff).into()),
-                        title_bar_background: Some(rgba(0xd9c8a4ff).into()),
-                        toolbar_background: Some(rgba(0xf9f5d7ff).into()),
-                        tab_bar_background: Some(rgba(0xecddb5ff).into()),
-                        tab_inactive_background: Some(rgba(0xecddb5ff).into()),
-                        tab_active_background: Some(rgba(0xf9f5d7ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x2828284c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xddcca7ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xddcca7ff).into()),
+                        ghost_element_hover: Some(rgba(0x494340ff).into()),
+                        ghost_element_active: Some(rgba(0x5b524cff).into()),
+                        ghost_element_selected: Some(rgba(0x5b524cff).into()),
+                        ghost_element_disabled: Some(rgba(0x3a3735ff).into()),
+                        text: Some(rgba(0xfbf1c7ff).into()),
+                        text_muted: Some(rgba(0xc5b597ff).into()),
+                        text_placeholder: Some(rgba(0x9a8c79ff).into()),
+                        text_disabled: Some(rgba(0x9a8c79ff).into()),
+                        text_accent: Some(rgba(0x83a598ff).into()),
+                        icon: Some(rgba(0xfbf1c7ff).into()),
+                        icon_muted: Some(rgba(0xc5b597ff).into()),
+                        icon_disabled: Some(rgba(0x9a8c79ff).into()),
+                        icon_placeholder: Some(rgba(0xc5b597ff).into()),
+                        icon_accent: Some(rgba(0x83a598ff).into()),
+                        status_bar_background: Some(rgba(0x4c4642ff).into()),
+                        title_bar_background: Some(rgba(0x4c4642ff).into()),
+                        toolbar_background: Some(rgba(0x282828ff).into()),
+                        tab_bar_background: Some(rgba(0x3a3735ff).into()),
+                        tab_inactive_background: Some(rgba(0x3a3735ff).into()),
+                        tab_active_background: Some(rgba(0x282828ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xfbf1c74c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x494340ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x494340ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xefe2bcff).into()),
-                        editor_foreground: Some(rgba(0x282828ff).into()),
-                        editor_background: Some(rgba(0xf9f5d7ff).into()),
-                        editor_gutter_background: Some(rgba(0xf9f5d7ff).into()),
-                        editor_subheader_background: Some(rgba(0xecddb5ff).into()),
-                        editor_active_line_background: Some(rgba(0xecddb5bf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xecddb5ff).into()),
-                        editor_line_number: Some(rgba(0x28282859).into()),
-                        editor_active_line_number: Some(rgba(0x282828ff).into()),
-                        editor_invisible: Some(rgba(0x5f5650ff).into()),
-                        editor_wrap_guide: Some(rgba(0x2828280d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x2828281a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x0b66781a).into()),
+                        scrollbar_track_border: Some(rgba(0x373432ff).into()),
+                        editor_foreground: Some(rgba(0xebdbb2ff).into()),
+                        editor_background: Some(rgba(0x282828ff).into()),
+                        editor_gutter_background: Some(rgba(0x282828ff).into()),
+                        editor_subheader_background: Some(rgba(0x3a3735ff).into()),
+                        editor_active_line_background: Some(rgba(0x3a3735bf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x3a3735ff).into()),
+                        editor_line_number: Some(rgba(0xfbf1c759).into()),
+                        editor_active_line_number: Some(rgba(0xfbf1c7ff).into()),
+                        editor_invisible: Some(rgba(0xc5b597ff).into()),
+                        editor_wrap_guide: Some(rgba(0xfbf1c70d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x83a5981a).into()),
                         editor_document_highlight_write_background: Some(rgba(0x92847466).into()),
-                        terminal_background: Some(rgba(0xf9f5d7ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0xb1a28aff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xdc8c7bff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xbfb787ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xe2b88bff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x8fb0baff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xbcb5afff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x9fbca8ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x282828ff).into()),
-                        terminal_ansi_black: Some(rgba(0xf9f5d7ff).into()),
-                        terminal_ansi_red: Some(rgba(0x9d0408ff).into()),
-                        terminal_ansi_green: Some(rgba(0x797410ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xb57616ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x0b6678ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0x7c6f64ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x437b59ff).into()),
-                        terminal_ansi_white: Some(rgba(0x282828ff).into()),
-                        link_text_hover: Some(rgba(0x0b6678ff).into()),
+                        terminal_background: Some(rgba(0x282828ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x73675eff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x93211eff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x91611cff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x414f4aff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()),
+                        terminal_ansi_black: Some(rgba(0x282828ff).into()),
+                        terminal_ansi_red: Some(rgba(0xfb4a35ff).into()),
+                        terminal_ansi_green: Some(rgba(0xb8bb27ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x83a598ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xa89984ff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x8ec07cff).into()),
+                        terminal_ansi_white: Some(rgba(0xfbf1c7ff).into()),
+                        link_text_hover: Some(rgba(0x83a598ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xb57616ff).into()),
-                        conflict_background: Some(rgba(0xf5e2d0ff).into()),
-                        conflict_border: Some(rgba(0xebccabff).into()),
-                        created: Some(rgba(0x797410ff).into()),
-                        created_background: Some(rgba(0xe5e1ceff).into()),
-                        created_border: Some(rgba(0xd1cba8ff).into()),
-                        deleted: Some(rgba(0x9d0408ff).into()),
-                        deleted_background: Some(rgba(0xf4d1c9ff).into()),
-                        deleted_border: Some(rgba(0xe8ac9eff).into()),
-                        error: Some(rgba(0x9d0408ff).into()),
-                        error_background: Some(rgba(0xf4d1c9ff).into()),
-                        error_border: Some(rgba(0xe8ac9eff).into()),
-                        hidden: Some(rgba(0x8a7c6fff).into()),
-                        hidden_background: Some(rgba(0xd9c8a4ff).into()),
-                        hidden_border: Some(rgba(0xd1c09eff).into()),
-                        hint: Some(rgba(0x677562ff).into()),
-                        hint_background: Some(rgba(0xd2dee2ff).into()),
-                        hint_border: Some(rgba(0xaec6cdff).into()),
-                        ignored: Some(rgba(0x5f5650ff).into()),
-                        ignored_background: Some(rgba(0xd9c8a4ff).into()),
-                        ignored_border: Some(rgba(0xc9b99aff).into()),
-                        info: Some(rgba(0x0b6678ff).into()),
-                        info_background: Some(rgba(0xd2dee2ff).into()),
-                        info_border: Some(rgba(0xaec6cdff).into()),
-                        modified: Some(rgba(0xb57616ff).into()),
-                        modified_background: Some(rgba(0xf5e2d0ff).into()),
-                        modified_border: Some(rgba(0xebccabff).into()),
-                        predictive: Some(rgba(0x7d9881ff).into()),
-                        predictive_background: Some(rgba(0xe5e1ceff).into()),
-                        predictive_border: Some(rgba(0xd1cba8ff).into()),
-                        renamed: Some(rgba(0x0b6678ff).into()),
-                        renamed_background: Some(rgba(0xd2dee2ff).into()),
-                        renamed_border: Some(rgba(0xaec6cdff).into()),
-                        success: Some(rgba(0x797410ff).into()),
-                        success_background: Some(rgba(0xe5e1ceff).into()),
-                        success_border: Some(rgba(0xd1cba8ff).into()),
-                        unreachable: Some(rgba(0x5f5650ff).into()),
-                        unreachable_background: Some(rgba(0xd9c8a4ff).into()),
-                        unreachable_border: Some(rgba(0xc9b99aff).into()),
-                        warning: Some(rgba(0xb57616ff).into()),
-                        warning_background: Some(rgba(0xf5e2d0ff).into()),
-                        warning_border: Some(rgba(0xebccabff).into()),
+                        conflict: Some(rgba(0xf9bd30ff).into()),
+                        conflict_background: Some(rgba(0x582f10ff).into()),
+                        conflict_border: Some(rgba(0x754916ff).into()),
+                        created: Some(rgba(0xb8bb27ff).into()),
+                        created_background: Some(rgba(0x332b11ff).into()),
+                        created_border: Some(rgba(0x4a4516ff).into()),
+                        deleted: Some(rgba(0xfb4a35ff).into()),
+                        deleted_background: Some(rgba(0x5a0a10ff).into()),
+                        deleted_border: Some(rgba(0x771618ff).into()),
+                        error: Some(rgba(0xfb4a35ff).into()),
+                        error_background: Some(rgba(0x5a0a10ff).into()),
+                        error_border: Some(rgba(0x771618ff).into()),
+                        hidden: Some(rgba(0x9a8c79ff).into()),
+                        hidden_background: Some(rgba(0x4c4642ff).into()),
+                        hidden_border: Some(rgba(0x544c48ff).into()),
+                        hint: Some(rgba(0x8d957eff).into()),
+                        hint_background: Some(rgba(0x1e2321ff).into()),
+                        hint_border: Some(rgba(0x303a36ff).into()),
+                        ignored: Some(rgba(0xc5b597ff).into()),
+                        ignored_background: Some(rgba(0x4c4642ff).into()),
+                        ignored_border: Some(rgba(0x5b534dff).into()),
+                        info: Some(rgba(0x83a598ff).into()),
+                        info_background: Some(rgba(0x1e2321ff).into()),
+                        info_border: Some(rgba(0x303a36ff).into()),
+                        modified: Some(rgba(0xf9bd30ff).into()),
+                        modified_background: Some(rgba(0x582f10ff).into()),
+                        modified_border: Some(rgba(0x754916ff).into()),
+                        predictive: Some(rgba(0x717363ff).into()),
+                        predictive_background: Some(rgba(0x332b11ff).into()),
+                        predictive_border: Some(rgba(0x4a4516ff).into()),
+                        renamed: Some(rgba(0x83a598ff).into()),
+                        renamed_background: Some(rgba(0x1e2321ff).into()),
+                        renamed_border: Some(rgba(0x303a36ff).into()),
+                        success: Some(rgba(0xb8bb27ff).into()),
+                        success_background: Some(rgba(0x332b11ff).into()),
+                        success_border: Some(rgba(0x4a4516ff).into()),
+                        unreachable: Some(rgba(0xc5b597ff).into()),
+                        unreachable_background: Some(rgba(0x4c4642ff).into()),
+                        unreachable_border: Some(rgba(0x5b534dff).into()),
+                        warning: Some(rgba(0xf9bd30ff).into()),
+                        warning_background: Some(rgba(0x582f10ff).into()),
+                        warning_border: Some(rgba(0x754916ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x0b6678ff).into(),
-                            background: rgba(0x0b6678ff).into(),
-                            selection: rgba(0x0b66783d).into(),
+                            cursor: rgba(0x83a598ff).into(),
+                            background: rgba(0x83a598ff).into(),
+                            selection: rgba(0x83a5983d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x7c6f64ff).into(),
-                            background: rgba(0x7c6f64ff).into(),
-                            selection: rgba(0x7c6f643d).into(),
+                            cursor: rgba(0xa89984ff).into(),
+                            background: rgba(0xa89984ff).into(),
+                            selection: rgba(0xa899843d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xaf3b05ff).into(),
-                            background: rgba(0xaf3b05ff).into(),
-                            selection: rgba(0xaf3b053d).into(),
+                            cursor: rgba(0xfd801bff).into(),
+                            background: rgba(0xfd801bff).into(),
+                            selection: rgba(0xfd801b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x8f4071ff).into(),
-                            background: rgba(0x8f4071ff).into(),
-                            selection: rgba(0x8f40713d).into(),
+                            cursor: rgba(0xd3869bff).into(),
+                            background: rgba(0xd3869bff).into(),
+                            selection: rgba(0xd3869b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x437b59ff).into(),
-                            background: rgba(0x437b59ff).into(),
-                            selection: rgba(0x437b593d).into(),
+                            cursor: rgba(0x8ec07cff).into(),
+                            background: rgba(0x8ec07cff).into(),
+                            selection: rgba(0x8ec07c3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x9d0408ff).into(),
-                            background: rgba(0x9d0408ff).into(),
-                            selection: rgba(0x9d04083d).into(),
+                            cursor: rgba(0xfb4a35ff).into(),
+                            background: rgba(0xfb4a35ff).into(),
+                            selection: rgba(0xfb4a353d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb57616ff).into(),
-                            background: rgba(0xb57616ff).into(),
-                            selection: rgba(0xb576163d).into(),
+                            cursor: rgba(0xf9bd30ff).into(),
+                            background: rgba(0xf9bd30ff).into(),
+                            selection: rgba(0xf9bd303d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x797410ff).into(),
-                            background: rgba(0x797410ff).into(),
-                            selection: rgba(0x7974103d).into(),
+                            cursor: rgba(0xb8bb27ff).into(),
+                            background: rgba(0xb8bb27ff).into(),
+                            selection: rgba(0xb8bb273d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -187,63 +187,63 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x8f3f71ff).into()),
+                                    color: Some(rgba(0xd3869bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7c6f64ff).into()),
+                                    color: Some(rgba(0xa89984ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5d544eff).into()),
+                                    color: Some(rgba(0xc7b798ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xb57614ff).into()),
+                                    color: Some(rgba(0xfabd2fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x427b58ff).into()),
+                                    color: Some(rgba(0x8ec07cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -251,28 +251,28 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xaf3a03ff).into()),
+                                    color: Some(rgba(0xfe8019ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x79740eff).into()),
+                                    color: Some(rgba(0xb8bb26ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function.builtin".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9d0006ff).into()),
+                                    color: Some(rgba(0xfb4934ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x677562ff).into()),
+                                    color: Some(rgba(0x8d957eff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -280,21 +280,21 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9d0006ff).into()),
+                                    color: Some(rgba(0xfb4934ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x427b58ff).into()),
+                                    color: Some(rgba(0x8ec07cff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -302,28 +302,28 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "link_uri".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x8f3f71ff).into()),
+                                    color: Some(rgba(0xd3869bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "number".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x8f3f71ff).into()),
+                                    color: Some(rgba(0xd3869bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x427b58ff).into()),
+                                    color: Some(rgba(0x8ec07cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7d9881ff).into()),
+                                    color: Some(rgba(0x717363ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -331,112 +331,112 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x282828ff).into()),
+                                    color: Some(rgba(0xfbf1c7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x282828ff).into()),
+                                    color: Some(rgba(0xebdbb2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x282828ff).into()),
+                                    color: Some(rgba(0xebdbb2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3c3836ff).into()),
+                                    color: Some(rgba(0xd5c4a1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x665c54ff).into()),
+                                    color: Some(rgba(0xa89984ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x413d3aff).into()),
+                                    color: Some(rgba(0xe5d5adff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x282828ff).into()),
+                                    color: Some(rgba(0xebdbb2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x413d3aff).into()),
+                                    color: Some(rgba(0xe5d5adff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x79740eff).into()),
+                                    color: Some(rgba(0xb8bb26ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5d544eff).into()),
+                                    color: Some(rgba(0xc7b798ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xaf3a03ff).into()),
+                                    color: Some(rgba(0xfe8019ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x8f3f71ff).into()),
+                                    color: Some(rgba(0xd3869bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x427b58ff).into()),
+                                    color: Some(rgba(0x8ec07cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x427b58ff).into()),
+                                    color: Some(rgba(0x8ec07cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x076678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x79740eff).into()),
+                                    color: Some(rgba(0xb8bb26ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -444,21 +444,21 @@ pub fn gruvbox() -> UserThemeFamily {
                             (
                                 "type".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xb57614ff).into()),
+                                    color: Some(rgba(0xfabd2fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x076678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x0b6678ff).into()),
+                                    color: Some(rgba(0x83a598ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -467,7 +467,7 @@ pub fn gruvbox() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "Gruvbox Dark Soft".into(),
+                name: "Gruvbox Dark Hard".into(),
                 appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
@@ -477,21 +477,21 @@ pub fn gruvbox() -> UserThemeFamily {
                         border_selected: Some(rgba(0x303a36ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
                         border_disabled: Some(rgba(0x544c48ff).into()),
-                        elevated_surface_background: Some(rgba(0x3b3735ff).into()),
-                        surface_background: Some(rgba(0x3b3735ff).into()),
+                        elevated_surface_background: Some(rgba(0x393634ff).into()),
+                        surface_background: Some(rgba(0x393634ff).into()),
                         background: Some(rgba(0x4c4642ff).into()),
-                        panel_background: Some(rgba(0x3b3735ff).into()),
-                        element_background: Some(rgba(0x3b3735ff).into()),
+                        panel_background: Some(rgba(0x393634ff).into()),
+                        element_background: Some(rgba(0x393634ff).into()),
                         element_hover: Some(rgba(0x494340ff).into()),
                         element_active: Some(rgba(0x5b524cff).into()),
                         element_selected: Some(rgba(0x5b524cff).into()),
-                        element_disabled: Some(rgba(0x3b3735ff).into()),
+                        element_disabled: Some(rgba(0x393634ff).into()),
                         drop_target_background: Some(rgba(0xc5b59780).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
                         ghost_element_hover: Some(rgba(0x494340ff).into()),
                         ghost_element_active: Some(rgba(0x5b524cff).into()),
                         ghost_element_selected: Some(rgba(0x5b524cff).into()),
-                        ghost_element_disabled: Some(rgba(0x3b3735ff).into()),
+                        ghost_element_disabled: Some(rgba(0x393634ff).into()),
                         text: Some(rgba(0xfbf1c7ff).into()),
                         text_muted: Some(rgba(0xc5b597ff).into()),
                         text_placeholder: Some(rgba(0x9a8c79ff).into()),
@@ -504,21 +504,21 @@ pub fn gruvbox() -> UserThemeFamily {
                         icon_accent: Some(rgba(0x83a598ff).into()),
                         status_bar_background: Some(rgba(0x4c4642ff).into()),
                         title_bar_background: Some(rgba(0x4c4642ff).into()),
-                        toolbar_background: Some(rgba(0x32302fff).into()),
-                        tab_bar_background: Some(rgba(0x3b3735ff).into()),
-                        tab_inactive_background: Some(rgba(0x3b3735ff).into()),
-                        tab_active_background: Some(rgba(0x32302fff).into()),
+                        toolbar_background: Some(rgba(0x1d2021ff).into()),
+                        tab_bar_background: Some(rgba(0x393634ff).into()),
+                        tab_inactive_background: Some(rgba(0x393634ff).into()),
+                        tab_active_background: Some(rgba(0x1d2021ff).into()),
                         scrollbar_thumb_background: Some(rgba(0xfbf1c74c).into()),
                         scrollbar_thumb_hover_background: Some(rgba(0x494340ff).into()),
                         scrollbar_thumb_border: Some(rgba(0x494340ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0x393634ff).into()),
+                        scrollbar_track_border: Some(rgba(0x343130ff).into()),
                         editor_foreground: Some(rgba(0xebdbb2ff).into()),
-                        editor_background: Some(rgba(0x32302fff).into()),
-                        editor_gutter_background: Some(rgba(0x32302fff).into()),
-                        editor_subheader_background: Some(rgba(0x3b3735ff).into()),
-                        editor_active_line_background: Some(rgba(0x3b3735bf).into()),
-                        editor_highlighted_line_background: Some(rgba(0x3b3735ff).into()),
+                        editor_background: Some(rgba(0x1d2021ff).into()),
+                        editor_gutter_background: Some(rgba(0x1d2021ff).into()),
+                        editor_subheader_background: Some(rgba(0x393634ff).into()),
+                        editor_active_line_background: Some(rgba(0x393634bf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x393634ff).into()),
                         editor_line_number: Some(rgba(0xfbf1c759).into()),
                         editor_active_line_number: Some(rgba(0xfbf1c7ff).into()),
                         editor_invisible: Some(rgba(0xc5b597ff).into()),
@@ -526,7 +526,7 @@ pub fn gruvbox() -> UserThemeFamily {
                         editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()),
                         editor_document_highlight_read_background: Some(rgba(0x83a5981a).into()),
                         editor_document_highlight_write_background: Some(rgba(0x92847466).into()),
-                        terminal_background: Some(rgba(0x32302fff).into()),
+                        terminal_background: Some(rgba(0x1d2021ff).into()),
                         terminal_ansi_bright_black: Some(rgba(0x73675eff).into()),
                         terminal_ansi_bright_red: Some(rgba(0x93211eff).into()),
                         terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()),
@@ -535,7 +535,7 @@ pub fn gruvbox() -> UserThemeFamily {
                         terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()),
                         terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()),
                         terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()),
-                        terminal_ansi_black: Some(rgba(0x32302fff).into()),
+                        terminal_ansi_black: Some(rgba(0x1d2021ff).into()),
                         terminal_ansi_red: Some(rgba(0xfb4a35ff).into()),
                         terminal_ansi_green: Some(rgba(0xb8bb27ff).into()),
                         terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()),
@@ -918,170 +918,170 @@ pub fn gruvbox() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "Gruvbox Light".into(),
-                appearance: Appearance::Light,
+                name: "Gruvbox Dark Soft".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0xc9b99aff).into()),
-                        border_variant: Some(rgba(0xddcca7ff).into()),
-                        border_focused: Some(rgba(0xaec6cdff).into()),
-                        border_selected: Some(rgba(0xaec6cdff).into()),
+                        border: Some(rgba(0x5b534dff).into()),
+                        border_variant: Some(rgba(0x494340ff).into()),
+                        border_focused: Some(rgba(0x303a36ff).into()),
+                        border_selected: Some(rgba(0x303a36ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xd1c09eff).into()),
-                        elevated_surface_background: Some(rgba(0xecddb4ff).into()),
-                        surface_background: Some(rgba(0xecddb4ff).into()),
-                        background: Some(rgba(0xd9c8a4ff).into()),
-                        panel_background: Some(rgba(0xecddb4ff).into()),
-                        element_background: Some(rgba(0xecddb4ff).into()),
-                        element_hover: Some(rgba(0xddcca7ff).into()),
-                        element_active: Some(rgba(0xc9b99aff).into()),
-                        element_selected: Some(rgba(0xc9b99aff).into()),
-                        element_disabled: Some(rgba(0xecddb4ff).into()),
-                        drop_target_background: Some(rgba(0x5f565080).into()),
+                        border_disabled: Some(rgba(0x544c48ff).into()),
+                        elevated_surface_background: Some(rgba(0x3b3735ff).into()),
+                        surface_background: Some(rgba(0x3b3735ff).into()),
+                        background: Some(rgba(0x4c4642ff).into()),
+                        panel_background: Some(rgba(0x3b3735ff).into()),
+                        element_background: Some(rgba(0x3b3735ff).into()),
+                        element_hover: Some(rgba(0x494340ff).into()),
+                        element_active: Some(rgba(0x5b524cff).into()),
+                        element_selected: Some(rgba(0x5b524cff).into()),
+                        element_disabled: Some(rgba(0x3b3735ff).into()),
+                        drop_target_background: Some(rgba(0xc5b59780).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xddcca7ff).into()),
-                        ghost_element_active: Some(rgba(0xc9b99aff).into()),
-                        ghost_element_selected: Some(rgba(0xc9b99aff).into()),
-                        ghost_element_disabled: Some(rgba(0xecddb4ff).into()),
-                        text: Some(rgba(0x282828ff).into()),
-                        text_muted: Some(rgba(0x5f5650ff).into()),
-                        text_placeholder: Some(rgba(0x8a7c6fff).into()),
-                        text_disabled: Some(rgba(0x8a7c6fff).into()),
-                        text_accent: Some(rgba(0x0b6678ff).into()),
-                        icon: Some(rgba(0x282828ff).into()),
-                        icon_muted: Some(rgba(0x5f5650ff).into()),
-                        icon_disabled: Some(rgba(0x8a7c6fff).into()),
-                        icon_placeholder: Some(rgba(0x5f5650ff).into()),
-                        icon_accent: Some(rgba(0x0b6678ff).into()),
-                        status_bar_background: Some(rgba(0xd9c8a4ff).into()),
-                        title_bar_background: Some(rgba(0xd9c8a4ff).into()),
-                        toolbar_background: Some(rgba(0xfbf1c7ff).into()),
-                        tab_bar_background: Some(rgba(0xecddb4ff).into()),
-                        tab_inactive_background: Some(rgba(0xecddb4ff).into()),
-                        tab_active_background: Some(rgba(0xfbf1c7ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x2828284c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xddcca7ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xddcca7ff).into()),
+                        ghost_element_hover: Some(rgba(0x494340ff).into()),
+                        ghost_element_active: Some(rgba(0x5b524cff).into()),
+                        ghost_element_selected: Some(rgba(0x5b524cff).into()),
+                        ghost_element_disabled: Some(rgba(0x3b3735ff).into()),
+                        text: Some(rgba(0xfbf1c7ff).into()),
+                        text_muted: Some(rgba(0xc5b597ff).into()),
+                        text_placeholder: Some(rgba(0x9a8c79ff).into()),
+                        text_disabled: Some(rgba(0x9a8c79ff).into()),
+                        text_accent: Some(rgba(0x83a598ff).into()),
+                        icon: Some(rgba(0xfbf1c7ff).into()),
+                        icon_muted: Some(rgba(0xc5b597ff).into()),
+                        icon_disabled: Some(rgba(0x9a8c79ff).into()),
+                        icon_placeholder: Some(rgba(0xc5b597ff).into()),
+                        icon_accent: Some(rgba(0x83a598ff).into()),
+                        status_bar_background: Some(rgba(0x4c4642ff).into()),
+                        title_bar_background: Some(rgba(0x4c4642ff).into()),
+                        toolbar_background: Some(rgba(0x32302fff).into()),
+                        tab_bar_background: Some(rgba(0x3b3735ff).into()),
+                        tab_inactive_background: Some(rgba(0x3b3735ff).into()),
+                        tab_active_background: Some(rgba(0x32302fff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xfbf1c74c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x494340ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x494340ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xefe1b8ff).into()),
-                        editor_foreground: Some(rgba(0x282828ff).into()),
-                        editor_background: Some(rgba(0xfbf1c7ff).into()),
-                        editor_gutter_background: Some(rgba(0xfbf1c7ff).into()),
-                        editor_subheader_background: Some(rgba(0xecddb4ff).into()),
-                        editor_active_line_background: Some(rgba(0xecddb4bf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xecddb4ff).into()),
-                        editor_line_number: Some(rgba(0x28282859).into()),
-                        editor_active_line_number: Some(rgba(0x282828ff).into()),
-                        editor_invisible: Some(rgba(0x5f5650ff).into()),
-                        editor_wrap_guide: Some(rgba(0x2828280d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x2828281a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x0b66781a).into()),
+                        scrollbar_track_border: Some(rgba(0x393634ff).into()),
+                        editor_foreground: Some(rgba(0xebdbb2ff).into()),
+                        editor_background: Some(rgba(0x32302fff).into()),
+                        editor_gutter_background: Some(rgba(0x32302fff).into()),
+                        editor_subheader_background: Some(rgba(0x3b3735ff).into()),
+                        editor_active_line_background: Some(rgba(0x3b3735bf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x3b3735ff).into()),
+                        editor_line_number: Some(rgba(0xfbf1c759).into()),
+                        editor_active_line_number: Some(rgba(0xfbf1c7ff).into()),
+                        editor_invisible: Some(rgba(0xc5b597ff).into()),
+                        editor_wrap_guide: Some(rgba(0xfbf1c70d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x83a5981a).into()),
                         editor_document_highlight_write_background: Some(rgba(0x92847466).into()),
-                        terminal_background: Some(rgba(0xfbf1c7ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0xb1a28aff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xdc8c7bff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xbfb787ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xe2b88bff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x8fb0baff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xbcb5afff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x9fbca8ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x282828ff).into()),
-                        terminal_ansi_black: Some(rgba(0xfbf1c7ff).into()),
-                        terminal_ansi_red: Some(rgba(0x9d0408ff).into()),
-                        terminal_ansi_green: Some(rgba(0x797410ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xb57616ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x0b6678ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0x7c6f64ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x437b59ff).into()),
-                        terminal_ansi_white: Some(rgba(0x282828ff).into()),
-                        link_text_hover: Some(rgba(0x0b6678ff).into()),
+                        terminal_background: Some(rgba(0x32302fff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x73675eff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x93211eff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x91611cff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x414f4aff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()),
+                        terminal_ansi_black: Some(rgba(0x32302fff).into()),
+                        terminal_ansi_red: Some(rgba(0xfb4a35ff).into()),
+                        terminal_ansi_green: Some(rgba(0xb8bb27ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x83a598ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xa89984ff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x8ec07cff).into()),
+                        terminal_ansi_white: Some(rgba(0xfbf1c7ff).into()),
+                        link_text_hover: Some(rgba(0x83a598ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xb57616ff).into()),
-                        conflict_background: Some(rgba(0xf5e2d0ff).into()),
-                        conflict_border: Some(rgba(0xebccabff).into()),
-                        created: Some(rgba(0x797410ff).into()),
-                        created_background: Some(rgba(0xe5e1ceff).into()),
-                        created_border: Some(rgba(0xd1cba8ff).into()),
-                        deleted: Some(rgba(0x9d0408ff).into()),
-                        deleted_background: Some(rgba(0xf4d1c9ff).into()),
-                        deleted_border: Some(rgba(0xe8ac9eff).into()),
-                        error: Some(rgba(0x9d0408ff).into()),
-                        error_background: Some(rgba(0xf4d1c9ff).into()),
-                        error_border: Some(rgba(0xe8ac9eff).into()),
-                        hidden: Some(rgba(0x8a7c6fff).into()),
-                        hidden_background: Some(rgba(0xd9c8a4ff).into()),
-                        hidden_border: Some(rgba(0xd1c09eff).into()),
-                        hint: Some(rgba(0x677562ff).into()),
-                        hint_background: Some(rgba(0xd2dee2ff).into()),
-                        hint_border: Some(rgba(0xaec6cdff).into()),
-                        ignored: Some(rgba(0x5f5650ff).into()),
-                        ignored_background: Some(rgba(0xd9c8a4ff).into()),
-                        ignored_border: Some(rgba(0xc9b99aff).into()),
-                        info: Some(rgba(0x0b6678ff).into()),
-                        info_background: Some(rgba(0xd2dee2ff).into()),
-                        info_border: Some(rgba(0xaec6cdff).into()),
-                        modified: Some(rgba(0xb57616ff).into()),
-                        modified_background: Some(rgba(0xf5e2d0ff).into()),
-                        modified_border: Some(rgba(0xebccabff).into()),
-                        predictive: Some(rgba(0x7d9881ff).into()),
-                        predictive_background: Some(rgba(0xe5e1ceff).into()),
-                        predictive_border: Some(rgba(0xd1cba8ff).into()),
-                        renamed: Some(rgba(0x0b6678ff).into()),
-                        renamed_background: Some(rgba(0xd2dee2ff).into()),
-                        renamed_border: Some(rgba(0xaec6cdff).into()),
-                        success: Some(rgba(0x797410ff).into()),
-                        success_background: Some(rgba(0xe5e1ceff).into()),
-                        success_border: Some(rgba(0xd1cba8ff).into()),
-                        unreachable: Some(rgba(0x5f5650ff).into()),
-                        unreachable_background: Some(rgba(0xd9c8a4ff).into()),
-                        unreachable_border: Some(rgba(0xc9b99aff).into()),
-                        warning: Some(rgba(0xb57616ff).into()),
-                        warning_background: Some(rgba(0xf5e2d0ff).into()),
-                        warning_border: Some(rgba(0xebccabff).into()),
+                        conflict: Some(rgba(0xf9bd30ff).into()),
+                        conflict_background: Some(rgba(0x582f10ff).into()),
+                        conflict_border: Some(rgba(0x754916ff).into()),
+                        created: Some(rgba(0xb8bb27ff).into()),
+                        created_background: Some(rgba(0x332b11ff).into()),
+                        created_border: Some(rgba(0x4a4516ff).into()),
+                        deleted: Some(rgba(0xfb4a35ff).into()),
+                        deleted_background: Some(rgba(0x5a0a10ff).into()),
+                        deleted_border: Some(rgba(0x771618ff).into()),
+                        error: Some(rgba(0xfb4a35ff).into()),
+                        error_background: Some(rgba(0x5a0a10ff).into()),
+                        error_border: Some(rgba(0x771618ff).into()),
+                        hidden: Some(rgba(0x9a8c79ff).into()),
+                        hidden_background: Some(rgba(0x4c4642ff).into()),
+                        hidden_border: Some(rgba(0x544c48ff).into()),
+                        hint: Some(rgba(0x8d957eff).into()),
+                        hint_background: Some(rgba(0x1e2321ff).into()),
+                        hint_border: Some(rgba(0x303a36ff).into()),
+                        ignored: Some(rgba(0xc5b597ff).into()),
+                        ignored_background: Some(rgba(0x4c4642ff).into()),
+                        ignored_border: Some(rgba(0x5b534dff).into()),
+                        info: Some(rgba(0x83a598ff).into()),
+                        info_background: Some(rgba(0x1e2321ff).into()),
+                        info_border: Some(rgba(0x303a36ff).into()),
+                        modified: Some(rgba(0xf9bd30ff).into()),
+                        modified_background: Some(rgba(0x582f10ff).into()),
+                        modified_border: Some(rgba(0x754916ff).into()),
+                        predictive: Some(rgba(0x717363ff).into()),
+                        predictive_background: Some(rgba(0x332b11ff).into()),
+                        predictive_border: Some(rgba(0x4a4516ff).into()),
+                        renamed: Some(rgba(0x83a598ff).into()),
+                        renamed_background: Some(rgba(0x1e2321ff).into()),
+                        renamed_border: Some(rgba(0x303a36ff).into()),
+                        success: Some(rgba(0xb8bb27ff).into()),
+                        success_background: Some(rgba(0x332b11ff).into()),
+                        success_border: Some(rgba(0x4a4516ff).into()),
+                        unreachable: Some(rgba(0xc5b597ff).into()),
+                        unreachable_background: Some(rgba(0x4c4642ff).into()),
+                        unreachable_border: Some(rgba(0x5b534dff).into()),
+                        warning: Some(rgba(0xf9bd30ff).into()),
+                        warning_background: Some(rgba(0x582f10ff).into()),
+                        warning_border: Some(rgba(0x754916ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x0b6678ff).into(),
-                            background: rgba(0x0b6678ff).into(),
-                            selection: rgba(0x0b66783d).into(),
+                            cursor: rgba(0x83a598ff).into(),
+                            background: rgba(0x83a598ff).into(),
+                            selection: rgba(0x83a5983d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x7c6f64ff).into(),
-                            background: rgba(0x7c6f64ff).into(),
-                            selection: rgba(0x7c6f643d).into(),
+                            cursor: rgba(0xa89984ff).into(),
+                            background: rgba(0xa89984ff).into(),
+                            selection: rgba(0xa899843d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xaf3b05ff).into(),
-                            background: rgba(0xaf3b05ff).into(),
-                            selection: rgba(0xaf3b053d).into(),
+                            cursor: rgba(0xfd801bff).into(),
+                            background: rgba(0xfd801bff).into(),
+                            selection: rgba(0xfd801b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x8f4071ff).into(),
-                            background: rgba(0x8f4071ff).into(),
-                            selection: rgba(0x8f40713d).into(),
+                            cursor: rgba(0xd3869bff).into(),
+                            background: rgba(0xd3869bff).into(),
+                            selection: rgba(0xd3869b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x437b59ff).into(),
-                            background: rgba(0x437b59ff).into(),
-                            selection: rgba(0x437b593d).into(),
+                            cursor: rgba(0x8ec07cff).into(),
+                            background: rgba(0x8ec07cff).into(),
+                            selection: rgba(0x8ec07c3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x9d0408ff).into(),
-                            background: rgba(0x9d0408ff).into(),
-                            selection: rgba(0x9d04083d).into(),
+                            cursor: rgba(0xfb4a35ff).into(),
+                            background: rgba(0xfb4a35ff).into(),
+                            selection: rgba(0xfb4a353d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb57616ff).into(),
-                            background: rgba(0xb57616ff).into(),
-                            selection: rgba(0xb576163d).into(),
+                            cursor: rgba(0xf9bd30ff).into(),
+                            background: rgba(0xf9bd30ff).into(),
+                            selection: rgba(0xf9bd303d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x797410ff).into(),
-                            background: rgba(0x797410ff).into(),
-                            selection: rgba(0x7974103d).into(),
+                            cursor: rgba(0xb8bb27ff).into(),
+                            background: rgba(0xb8bb27ff).into(),
+                            selection: rgba(0xb8bb273d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {

crates/theme/src/themes/one.rs πŸ”—

@@ -16,160 +16,160 @@ pub fn one() -> UserThemeFamily {
         author: "Zed Industries".into(),
         themes: vec![
             UserTheme {
-                name: "One Light".into(),
-                appearance: Appearance::Light,
+                name: "One Dark".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0xc9c9caff).into()),
-                        border_variant: Some(rgba(0xdfdfe0ff).into()),
-                        border_focused: Some(rgba(0xcbcdf6ff).into()),
-                        border_selected: Some(rgba(0xcbcdf6ff).into()),
+                        border: Some(rgba(0x464b57ff).into()),
+                        border_variant: Some(rgba(0x363c46ff).into()),
+                        border_focused: Some(rgba(0x293c5bff).into()),
+                        border_selected: Some(rgba(0x293c5bff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xd3d3d4ff).into()),
-                        elevated_surface_background: Some(rgba(0xebebecff).into()),
-                        surface_background: Some(rgba(0xebebecff).into()),
-                        background: Some(rgba(0xdcdcddff).into()),
-                        panel_background: Some(rgba(0xebebecff).into()),
-                        element_background: Some(rgba(0xebebecff).into()),
-                        element_hover: Some(rgba(0xdfdfe0ff).into()),
-                        element_active: Some(rgba(0xcacacaff).into()),
-                        element_selected: Some(rgba(0xcacacaff).into()),
-                        element_disabled: Some(rgba(0xebebecff).into()),
-                        drop_target_background: Some(rgba(0x7f818880).into()),
+                        border_disabled: Some(rgba(0x414754ff).into()),
+                        elevated_surface_background: Some(rgba(0x2f343eff).into()),
+                        surface_background: Some(rgba(0x2f343eff).into()),
+                        background: Some(rgba(0x3b414dff).into()),
+                        panel_background: Some(rgba(0x2f343eff).into()),
+                        element_background: Some(rgba(0x2f343eff).into()),
+                        element_hover: Some(rgba(0x363c46ff).into()),
+                        element_active: Some(rgba(0x454a56ff).into()),
+                        element_selected: Some(rgba(0x454a56ff).into()),
+                        element_disabled: Some(rgba(0x2f343eff).into()),
+                        drop_target_background: Some(rgba(0x83899480).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xdfdfe0ff).into()),
-                        ghost_element_active: Some(rgba(0xcacacaff).into()),
-                        ghost_element_selected: Some(rgba(0xcacacaff).into()),
-                        ghost_element_disabled: Some(rgba(0xebebecff).into()),
-                        text: Some(rgba(0x383a41ff).into()),
-                        text_muted: Some(rgba(0x7f8188ff).into()),
-                        text_placeholder: Some(rgba(0xa1a1a3ff).into()),
-                        text_disabled: Some(rgba(0xa1a1a3ff).into()),
-                        text_accent: Some(rgba(0x5c79e2ff).into()),
-                        icon: Some(rgba(0x383a41ff).into()),
-                        icon_muted: Some(rgba(0x7f8188ff).into()),
-                        icon_disabled: Some(rgba(0xa1a1a3ff).into()),
-                        icon_placeholder: Some(rgba(0x7f8188ff).into()),
-                        icon_accent: Some(rgba(0x5c79e2ff).into()),
-                        status_bar_background: Some(rgba(0xdcdcddff).into()),
-                        title_bar_background: Some(rgba(0xdcdcddff).into()),
-                        toolbar_background: Some(rgba(0xfafafaff).into()),
-                        tab_bar_background: Some(rgba(0xebebecff).into()),
-                        tab_inactive_background: Some(rgba(0xebebecff).into()),
-                        tab_active_background: Some(rgba(0xfafafaff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x383a414c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xdfdfe0ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xdfdfe0ff).into()),
+                        ghost_element_hover: Some(rgba(0x363c46ff).into()),
+                        ghost_element_active: Some(rgba(0x454a56ff).into()),
+                        ghost_element_selected: Some(rgba(0x454a56ff).into()),
+                        ghost_element_disabled: Some(rgba(0x2f343eff).into()),
+                        text: Some(rgba(0xc8ccd4ff).into()),
+                        text_muted: Some(rgba(0x838994ff).into()),
+                        text_placeholder: Some(rgba(0x555a63ff).into()),
+                        text_disabled: Some(rgba(0x555a63ff).into()),
+                        text_accent: Some(rgba(0x74ade8ff).into()),
+                        icon: Some(rgba(0xc8ccd4ff).into()),
+                        icon_muted: Some(rgba(0x838994ff).into()),
+                        icon_disabled: Some(rgba(0x555a63ff).into()),
+                        icon_placeholder: Some(rgba(0x838994ff).into()),
+                        icon_accent: Some(rgba(0x74ade8ff).into()),
+                        status_bar_background: Some(rgba(0x3b414dff).into()),
+                        title_bar_background: Some(rgba(0x3b414dff).into()),
+                        toolbar_background: Some(rgba(0x282c34ff).into()),
+                        tab_bar_background: Some(rgba(0x2f343eff).into()),
+                        tab_inactive_background: Some(rgba(0x2f343eff).into()),
+                        tab_active_background: Some(rgba(0x282c34ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xc8ccd44c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x363c46ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x363c46ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xeeeeeeff).into()),
-                        editor_foreground: Some(rgba(0x383a41ff).into()),
-                        editor_background: Some(rgba(0xfafafaff).into()),
-                        editor_gutter_background: Some(rgba(0xfafafaff).into()),
-                        editor_subheader_background: Some(rgba(0xebebecff).into()),
-                        editor_active_line_background: Some(rgba(0xebebecbf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xebebecff).into()),
-                        editor_line_number: Some(rgba(0x383a4159).into()),
-                        editor_active_line_number: Some(rgba(0x383a41ff).into()),
-                        editor_invisible: Some(rgba(0x7f8188ff).into()),
-                        editor_wrap_guide: Some(rgba(0x383a410d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x383a411a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x5c79e21a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0xa3a3a466).into()),
-                        terminal_background: Some(rgba(0xfafafaff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0xaaaaaaff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xf0b0a4ff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xb2cfa9ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xf1dfc1ff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0xb5baf2ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xcea6d3ff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0xa4bfdbff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x383a41ff).into()),
-                        terminal_ansi_black: Some(rgba(0xfafafaff).into()),
-                        terminal_ansi_red: Some(rgba(0xd36151ff).into()),
-                        terminal_ansi_green: Some(rgba(0x669f59ff).into()),
+                        scrollbar_track_border: Some(rgba(0x2e333cff).into()),
+                        editor_foreground: Some(rgba(0xacb2beff).into()),
+                        editor_background: Some(rgba(0x282c34ff).into()),
+                        editor_gutter_background: Some(rgba(0x282c34ff).into()),
+                        editor_subheader_background: Some(rgba(0x2f343eff).into()),
+                        editor_active_line_background: Some(rgba(0x2f343ebf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x2f343eff).into()),
+                        editor_line_number: Some(rgba(0xc8ccd459).into()),
+                        editor_active_line_number: Some(rgba(0xc8ccd4ff).into()),
+                        editor_invisible: Some(rgba(0x838994ff).into()),
+                        editor_wrap_guide: Some(rgba(0xc8ccd40d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xc8ccd41a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x74ade81a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0x555a6366).into()),
+                        terminal_background: Some(rgba(0x282c34ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x525661ff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x673a3cff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x4d6140ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x786441ff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x385378ff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x5e2b26ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x3a565bff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xc8ccd4ff).into()),
+                        terminal_ansi_black: Some(rgba(0x282c34ff).into()),
+                        terminal_ansi_red: Some(rgba(0xd07277ff).into()),
+                        terminal_ansi_green: Some(rgba(0xa1c181ff).into()),
                         terminal_ansi_yellow: Some(rgba(0xdec184ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x5c79e2ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0x994fa6ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x3b82b7ff).into()),
-                        terminal_ansi_white: Some(rgba(0x383a41ff).into()),
-                        link_text_hover: Some(rgba(0x5c79e2ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x74ade8ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xbe5046ff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x6fb4c0ff).into()),
+                        terminal_ansi_white: Some(rgba(0xc8ccd4ff).into()),
+                        link_text_hover: Some(rgba(0x74ade8ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
                         conflict: Some(rgba(0xdec184ff).into()),
-                        conflict_background: Some(rgba(0xfaf2e6ff).into()),
-                        conflict_border: Some(rgba(0xf5e8d2ff).into()),
-                        created: Some(rgba(0x669f59ff).into()),
-                        created_background: Some(rgba(0xe0ebdcff).into()),
-                        created_border: Some(rgba(0xc8dcc1ff).into()),
-                        deleted: Some(rgba(0xd36151ff).into()),
-                        deleted_background: Some(rgba(0xfbdfd9ff).into()),
-                        deleted_border: Some(rgba(0xf6c6bdff).into()),
-                        error: Some(rgba(0xd36151ff).into()),
-                        error_background: Some(rgba(0xfbdfd9ff).into()),
-                        error_border: Some(rgba(0xf6c6bdff).into()),
-                        hidden: Some(rgba(0xa1a1a3ff).into()),
-                        hidden_background: Some(rgba(0xdcdcddff).into()),
-                        hidden_border: Some(rgba(0xd3d3d4ff).into()),
-                        hint: Some(rgba(0x9295beff).into()),
-                        hint_background: Some(rgba(0xe2e2faff).into()),
-                        hint_border: Some(rgba(0xcbcdf6ff).into()),
-                        ignored: Some(rgba(0x7f8188ff).into()),
-                        ignored_background: Some(rgba(0xdcdcddff).into()),
-                        ignored_border: Some(rgba(0xc9c9caff).into()),
-                        info: Some(rgba(0x5c79e2ff).into()),
-                        info_background: Some(rgba(0xe2e2faff).into()),
-                        info_border: Some(rgba(0xcbcdf6ff).into()),
+                        conflict_background: Some(rgba(0x41331dff).into()),
+                        conflict_border: Some(rgba(0x5d4c2fff).into()),
+                        created: Some(rgba(0xa1c181ff).into()),
+                        created_background: Some(rgba(0x222e1dff).into()),
+                        created_border: Some(rgba(0x38482fff).into()),
+                        deleted: Some(rgba(0xd07277ff).into()),
+                        deleted_background: Some(rgba(0x301b1cff).into()),
+                        deleted_border: Some(rgba(0x4c2b2cff).into()),
+                        error: Some(rgba(0xd07277ff).into()),
+                        error_background: Some(rgba(0x301b1cff).into()),
+                        error_border: Some(rgba(0x4c2b2cff).into()),
+                        hidden: Some(rgba(0x555a63ff).into()),
+                        hidden_background: Some(rgba(0x3b414dff).into()),
+                        hidden_border: Some(rgba(0x414754ff).into()),
+                        hint: Some(rgba(0x5b708aff).into()),
+                        hint_background: Some(rgba(0x18243dff).into()),
+                        hint_border: Some(rgba(0x293c5bff).into()),
+                        ignored: Some(rgba(0x838994ff).into()),
+                        ignored_background: Some(rgba(0x3b414dff).into()),
+                        ignored_border: Some(rgba(0x464b57ff).into()),
+                        info: Some(rgba(0x74ade8ff).into()),
+                        info_background: Some(rgba(0x18243dff).into()),
+                        info_border: Some(rgba(0x293c5bff).into()),
                         modified: Some(rgba(0xdec184ff).into()),
-                        modified_background: Some(rgba(0xfaf2e6ff).into()),
-                        modified_border: Some(rgba(0xf5e8d2ff).into()),
-                        predictive: Some(rgba(0x9c9fc7ff).into()),
-                        predictive_background: Some(rgba(0xe0ebdcff).into()),
-                        predictive_border: Some(rgba(0xc8dcc1ff).into()),
-                        renamed: Some(rgba(0x5c79e2ff).into()),
-                        renamed_background: Some(rgba(0xe2e2faff).into()),
-                        renamed_border: Some(rgba(0xcbcdf6ff).into()),
-                        success: Some(rgba(0x669f59ff).into()),
-                        success_background: Some(rgba(0xe0ebdcff).into()),
-                        success_border: Some(rgba(0xc8dcc1ff).into()),
-                        unreachable: Some(rgba(0x7f8188ff).into()),
-                        unreachable_background: Some(rgba(0xdcdcddff).into()),
-                        unreachable_border: Some(rgba(0xc9c9caff).into()),
+                        modified_background: Some(rgba(0x41331dff).into()),
+                        modified_border: Some(rgba(0x5d4c2fff).into()),
+                        predictive: Some(rgba(0x5b6b88ff).into()),
+                        predictive_background: Some(rgba(0x222e1dff).into()),
+                        predictive_border: Some(rgba(0x38482fff).into()),
+                        renamed: Some(rgba(0x74ade8ff).into()),
+                        renamed_background: Some(rgba(0x18243dff).into()),
+                        renamed_border: Some(rgba(0x293c5bff).into()),
+                        success: Some(rgba(0xa1c181ff).into()),
+                        success_background: Some(rgba(0x222e1dff).into()),
+                        success_border: Some(rgba(0x38482fff).into()),
+                        unreachable: Some(rgba(0x838994ff).into()),
+                        unreachable_background: Some(rgba(0x3b414dff).into()),
+                        unreachable_border: Some(rgba(0x464b57ff).into()),
                         warning: Some(rgba(0xdec184ff).into()),
-                        warning_background: Some(rgba(0xfaf2e6ff).into()),
-                        warning_border: Some(rgba(0xf5e8d2ff).into()),
+                        warning_background: Some(rgba(0x41331dff).into()),
+                        warning_border: Some(rgba(0x5d4c2fff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x5c79e2ff).into(),
-                            background: rgba(0x5c79e2ff).into(),
-                            selection: rgba(0x5c79e23d).into(),
+                            cursor: rgba(0x74ade8ff).into(),
+                            background: rgba(0x74ade8ff).into(),
+                            selection: rgba(0x74ade83d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x994fa6ff).into(),
-                            background: rgba(0x994fa6ff).into(),
-                            selection: rgba(0x994fa63d).into(),
+                            cursor: rgba(0xbe5046ff).into(),
+                            background: rgba(0xbe5046ff).into(),
+                            selection: rgba(0xbe50463d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xad6f27ff).into(),
-                            background: rgba(0xad6f27ff).into(),
-                            selection: rgba(0xad6f273d).into(),
+                            cursor: rgba(0xc0966bff).into(),
+                            background: rgba(0xc0966bff).into(),
+                            selection: rgba(0xc0966b3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xa44aabff).into(),
-                            background: rgba(0xa44aabff).into(),
-                            selection: rgba(0xa44aab3d).into(),
+                            cursor: rgba(0xb478cfff).into(),
+                            background: rgba(0xb478cfff).into(),
+                            selection: rgba(0xb478cf3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x3b82b7ff).into(),
-                            background: rgba(0x3b82b7ff).into(),
-                            selection: rgba(0x3b82b73d).into(),
+                            cursor: rgba(0x6fb4c0ff).into(),
+                            background: rgba(0x6fb4c0ff).into(),
+                            selection: rgba(0x6fb4c03d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xd36151ff).into(),
-                            background: rgba(0xd36151ff).into(),
-                            selection: rgba(0xd361513d).into(),
+                            cursor: rgba(0xd07277ff).into(),
+                            background: rgba(0xd07277ff).into(),
+                            selection: rgba(0xd072773d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0xdec184ff).into(),
@@ -177,9 +177,9 @@ pub fn one() -> UserThemeFamily {
                             selection: rgba(0xdec1843d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x669f59ff).into(),
-                            background: rgba(0x669f59ff).into(),
-                            selection: rgba(0x669f593d).into(),
+                            cursor: rgba(0xa1c181ff).into(),
+                            background: rgba(0xa1c181ff).into(),
+                            selection: rgba(0xa1c1813d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -187,63 +187,63 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5c79e2ff).into()),
+                                    color: Some(rgba(0x74ade8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f26ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa2a3a7ff).into()),
+                                    color: Some(rgba(0x5d636fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7c7e86ff).into()),
+                                    color: Some(rgba(0x878e98ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x669f59ff).into()),
+                                    color: Some(rgba(0xdfc184ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5c79e2ff).into()),
+                                    color: Some(rgba(0x74ade9ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x383a41ff).into()),
+                                    color: Some(rgba(0xc8ccd4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5c79e2ff).into()),
+                                    color: Some(rgba(0x74ade8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f26ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -251,21 +251,21 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd36050ff).into()),
+                                    color: Some(rgba(0xd07277ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5b79e3ff).into()),
+                                    color: Some(rgba(0x74ade9ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9295beff).into()),
+                                    color: Some(rgba(0x5b708aff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -273,50 +273,50 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa449abff).into()),
+                                    color: Some(rgba(0xb478cfff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5c79e2ff).into()),
+                                    color: Some(rgba(0x74ade8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5b79e3ff).into()),
-                                    font_style: Some(UserFontStyle::Italic),
+                                    color: Some(rgba(0x74ade9ff).into()),
+                                    font_style: Some(UserFontStyle::Normal),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_uri".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3982b7ff).into()),
+                                    color: Some(rgba(0x6fb4c0ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "number".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f26ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3982b7ff).into()),
+                                    color: Some(rgba(0x6fb4c0ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9c9fc7ff).into()),
+                                    color: Some(rgba(0x5b6b88ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -324,112 +324,112 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x383a41ff).into()),
+                                    color: Some(rgba(0xc8ccd4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x383a41ff).into()),
+                                    color: Some(rgba(0xacb2beff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd36050ff).into()),
+                                    color: Some(rgba(0xd07277ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x383a41ff).into()),
+                                    color: Some(rgba(0xacb2beff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x4d4f52ff).into()),
+                                    color: Some(rgba(0xb2b9c6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x4d4f52ff).into()),
+                                    color: Some(rgba(0xb2b9c6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd36050ff).into()),
+                                    color: Some(rgba(0xd07277ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xb92c46ff).into()),
+                                    color: Some(rgba(0xb1574bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x659f58ff).into()),
+                                    color: Some(rgba(0xa1c181ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7c7e86ff).into()),
+                                    color: Some(rgba(0x878e98ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f27ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f27ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f27ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5c79e2ff).into()),
+                                    color: Some(rgba(0x74ade8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x659f58ff).into()),
+                                    color: Some(rgba(0xa1c181ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd36050ff).into()),
+                                    color: Some(rgba(0xd07277ff).into()),
                                     font_weight: Some(UserFontWeight(400.0)),
                                     ..Default::default()
                                 },
@@ -437,28 +437,28 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "type".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3982b7ff).into()),
+                                    color: Some(rgba(0x6fb4c0ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x383a41ff).into()),
+                                    color: Some(rgba(0xc8ccd4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xad6f26ff).into()),
+                                    color: Some(rgba(0xc0966bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5b79e3ff).into()),
+                                    color: Some(rgba(0x74ade9ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -467,160 +467,160 @@ pub fn one() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "One Dark".into(),
-                appearance: Appearance::Dark,
+                name: "One Light".into(),
+                appearance: Appearance::Light,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x464b57ff).into()),
-                        border_variant: Some(rgba(0x363c46ff).into()),
-                        border_focused: Some(rgba(0x293c5bff).into()),
-                        border_selected: Some(rgba(0x293c5bff).into()),
+                        border: Some(rgba(0xc9c9caff).into()),
+                        border_variant: Some(rgba(0xdfdfe0ff).into()),
+                        border_focused: Some(rgba(0xcbcdf6ff).into()),
+                        border_selected: Some(rgba(0xcbcdf6ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0x414754ff).into()),
-                        elevated_surface_background: Some(rgba(0x2f343eff).into()),
-                        surface_background: Some(rgba(0x2f343eff).into()),
-                        background: Some(rgba(0x3b414dff).into()),
-                        panel_background: Some(rgba(0x2f343eff).into()),
-                        element_background: Some(rgba(0x2f343eff).into()),
-                        element_hover: Some(rgba(0x363c46ff).into()),
-                        element_active: Some(rgba(0x454a56ff).into()),
-                        element_selected: Some(rgba(0x454a56ff).into()),
-                        element_disabled: Some(rgba(0x2f343eff).into()),
-                        drop_target_background: Some(rgba(0x83899480).into()),
+                        border_disabled: Some(rgba(0xd3d3d4ff).into()),
+                        elevated_surface_background: Some(rgba(0xebebecff).into()),
+                        surface_background: Some(rgba(0xebebecff).into()),
+                        background: Some(rgba(0xdcdcddff).into()),
+                        panel_background: Some(rgba(0xebebecff).into()),
+                        element_background: Some(rgba(0xebebecff).into()),
+                        element_hover: Some(rgba(0xdfdfe0ff).into()),
+                        element_active: Some(rgba(0xcacacaff).into()),
+                        element_selected: Some(rgba(0xcacacaff).into()),
+                        element_disabled: Some(rgba(0xebebecff).into()),
+                        drop_target_background: Some(rgba(0x7f818880).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0x363c46ff).into()),
-                        ghost_element_active: Some(rgba(0x454a56ff).into()),
-                        ghost_element_selected: Some(rgba(0x454a56ff).into()),
-                        ghost_element_disabled: Some(rgba(0x2f343eff).into()),
-                        text: Some(rgba(0xc8ccd4ff).into()),
-                        text_muted: Some(rgba(0x838994ff).into()),
-                        text_placeholder: Some(rgba(0x555a63ff).into()),
-                        text_disabled: Some(rgba(0x555a63ff).into()),
-                        text_accent: Some(rgba(0x74ade8ff).into()),
-                        icon: Some(rgba(0xc8ccd4ff).into()),
-                        icon_muted: Some(rgba(0x838994ff).into()),
-                        icon_disabled: Some(rgba(0x555a63ff).into()),
-                        icon_placeholder: Some(rgba(0x838994ff).into()),
-                        icon_accent: Some(rgba(0x74ade8ff).into()),
-                        status_bar_background: Some(rgba(0x3b414dff).into()),
-                        title_bar_background: Some(rgba(0x3b414dff).into()),
-                        toolbar_background: Some(rgba(0x282c34ff).into()),
-                        tab_bar_background: Some(rgba(0x2f343eff).into()),
-                        tab_inactive_background: Some(rgba(0x2f343eff).into()),
-                        tab_active_background: Some(rgba(0x282c34ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0xc8ccd44c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0x363c46ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0x363c46ff).into()),
-                        scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0x2e333cff).into()),
-                        editor_foreground: Some(rgba(0xacb2beff).into()),
-                        editor_background: Some(rgba(0x282c34ff).into()),
-                        editor_gutter_background: Some(rgba(0x282c34ff).into()),
-                        editor_subheader_background: Some(rgba(0x2f343eff).into()),
-                        editor_active_line_background: Some(rgba(0x2f343ebf).into()),
-                        editor_highlighted_line_background: Some(rgba(0x2f343eff).into()),
-                        editor_line_number: Some(rgba(0xc8ccd459).into()),
-                        editor_active_line_number: Some(rgba(0xc8ccd4ff).into()),
-                        editor_invisible: Some(rgba(0x838994ff).into()),
-                        editor_wrap_guide: Some(rgba(0xc8ccd40d).into()),
-                        editor_active_wrap_guide: Some(rgba(0xc8ccd41a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x74ade81a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0x555a6366).into()),
-                        terminal_background: Some(rgba(0x282c34ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x525661ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0x673a3cff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0x4d6140ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0x786441ff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x385378ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0x5e2b26ff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x3a565bff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0xc8ccd4ff).into()),
-                        terminal_ansi_black: Some(rgba(0x282c34ff).into()),
-                        terminal_ansi_red: Some(rgba(0xd07277ff).into()),
-                        terminal_ansi_green: Some(rgba(0xa1c181ff).into()),
+                        ghost_element_hover: Some(rgba(0xdfdfe0ff).into()),
+                        ghost_element_active: Some(rgba(0xcacacaff).into()),
+                        ghost_element_selected: Some(rgba(0xcacacaff).into()),
+                        ghost_element_disabled: Some(rgba(0xebebecff).into()),
+                        text: Some(rgba(0x383a41ff).into()),
+                        text_muted: Some(rgba(0x7f8188ff).into()),
+                        text_placeholder: Some(rgba(0xa1a1a3ff).into()),
+                        text_disabled: Some(rgba(0xa1a1a3ff).into()),
+                        text_accent: Some(rgba(0x5c79e2ff).into()),
+                        icon: Some(rgba(0x383a41ff).into()),
+                        icon_muted: Some(rgba(0x7f8188ff).into()),
+                        icon_disabled: Some(rgba(0xa1a1a3ff).into()),
+                        icon_placeholder: Some(rgba(0x7f8188ff).into()),
+                        icon_accent: Some(rgba(0x5c79e2ff).into()),
+                        status_bar_background: Some(rgba(0xdcdcddff).into()),
+                        title_bar_background: Some(rgba(0xdcdcddff).into()),
+                        toolbar_background: Some(rgba(0xfafafaff).into()),
+                        tab_bar_background: Some(rgba(0xebebecff).into()),
+                        tab_inactive_background: Some(rgba(0xebebecff).into()),
+                        tab_active_background: Some(rgba(0xfafafaff).into()),
+                        scrollbar_thumb_background: Some(rgba(0x383a414c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0xdfdfe0ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0xdfdfe0ff).into()),
+                        scrollbar_track_background: Some(rgba(0x00000000).into()),
+                        scrollbar_track_border: Some(rgba(0xeeeeeeff).into()),
+                        editor_foreground: Some(rgba(0x383a41ff).into()),
+                        editor_background: Some(rgba(0xfafafaff).into()),
+                        editor_gutter_background: Some(rgba(0xfafafaff).into()),
+                        editor_subheader_background: Some(rgba(0xebebecff).into()),
+                        editor_active_line_background: Some(rgba(0xebebecbf).into()),
+                        editor_highlighted_line_background: Some(rgba(0xebebecff).into()),
+                        editor_line_number: Some(rgba(0x383a4159).into()),
+                        editor_active_line_number: Some(rgba(0x383a41ff).into()),
+                        editor_invisible: Some(rgba(0x7f8188ff).into()),
+                        editor_wrap_guide: Some(rgba(0x383a410d).into()),
+                        editor_active_wrap_guide: Some(rgba(0x383a411a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x5c79e21a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0xa3a3a466).into()),
+                        terminal_background: Some(rgba(0xfafafaff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0xaaaaaaff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0xf0b0a4ff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0xb2cfa9ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0xf1dfc1ff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0xb5baf2ff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0xcea6d3ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0xa4bfdbff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0x383a41ff).into()),
+                        terminal_ansi_black: Some(rgba(0xfafafaff).into()),
+                        terminal_ansi_red: Some(rgba(0xd36151ff).into()),
+                        terminal_ansi_green: Some(rgba(0x669f59ff).into()),
                         terminal_ansi_yellow: Some(rgba(0xdec184ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x74ade8ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0xbe5046ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x6fb4c0ff).into()),
-                        terminal_ansi_white: Some(rgba(0xc8ccd4ff).into()),
-                        link_text_hover: Some(rgba(0x74ade8ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x5c79e2ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0x994fa6ff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x3b82b7ff).into()),
+                        terminal_ansi_white: Some(rgba(0x383a41ff).into()),
+                        link_text_hover: Some(rgba(0x5c79e2ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
                         conflict: Some(rgba(0xdec184ff).into()),
-                        conflict_background: Some(rgba(0x41331dff).into()),
-                        conflict_border: Some(rgba(0x5d4c2fff).into()),
-                        created: Some(rgba(0xa1c181ff).into()),
-                        created_background: Some(rgba(0x222e1dff).into()),
-                        created_border: Some(rgba(0x38482fff).into()),
-                        deleted: Some(rgba(0xd07277ff).into()),
-                        deleted_background: Some(rgba(0x301b1cff).into()),
-                        deleted_border: Some(rgba(0x4c2b2cff).into()),
-                        error: Some(rgba(0xd07277ff).into()),
-                        error_background: Some(rgba(0x301b1cff).into()),
-                        error_border: Some(rgba(0x4c2b2cff).into()),
-                        hidden: Some(rgba(0x555a63ff).into()),
-                        hidden_background: Some(rgba(0x3b414dff).into()),
-                        hidden_border: Some(rgba(0x414754ff).into()),
-                        hint: Some(rgba(0x5b708aff).into()),
-                        hint_background: Some(rgba(0x18243dff).into()),
-                        hint_border: Some(rgba(0x293c5bff).into()),
-                        ignored: Some(rgba(0x838994ff).into()),
-                        ignored_background: Some(rgba(0x3b414dff).into()),
-                        ignored_border: Some(rgba(0x464b57ff).into()),
-                        info: Some(rgba(0x74ade8ff).into()),
-                        info_background: Some(rgba(0x18243dff).into()),
-                        info_border: Some(rgba(0x293c5bff).into()),
+                        conflict_background: Some(rgba(0xfaf2e6ff).into()),
+                        conflict_border: Some(rgba(0xf5e8d2ff).into()),
+                        created: Some(rgba(0x669f59ff).into()),
+                        created_background: Some(rgba(0xe0ebdcff).into()),
+                        created_border: Some(rgba(0xc8dcc1ff).into()),
+                        deleted: Some(rgba(0xd36151ff).into()),
+                        deleted_background: Some(rgba(0xfbdfd9ff).into()),
+                        deleted_border: Some(rgba(0xf6c6bdff).into()),
+                        error: Some(rgba(0xd36151ff).into()),
+                        error_background: Some(rgba(0xfbdfd9ff).into()),
+                        error_border: Some(rgba(0xf6c6bdff).into()),
+                        hidden: Some(rgba(0xa1a1a3ff).into()),
+                        hidden_background: Some(rgba(0xdcdcddff).into()),
+                        hidden_border: Some(rgba(0xd3d3d4ff).into()),
+                        hint: Some(rgba(0x9295beff).into()),
+                        hint_background: Some(rgba(0xe2e2faff).into()),
+                        hint_border: Some(rgba(0xcbcdf6ff).into()),
+                        ignored: Some(rgba(0x7f8188ff).into()),
+                        ignored_background: Some(rgba(0xdcdcddff).into()),
+                        ignored_border: Some(rgba(0xc9c9caff).into()),
+                        info: Some(rgba(0x5c79e2ff).into()),
+                        info_background: Some(rgba(0xe2e2faff).into()),
+                        info_border: Some(rgba(0xcbcdf6ff).into()),
                         modified: Some(rgba(0xdec184ff).into()),
-                        modified_background: Some(rgba(0x41331dff).into()),
-                        modified_border: Some(rgba(0x5d4c2fff).into()),
-                        predictive: Some(rgba(0x5b6b88ff).into()),
-                        predictive_background: Some(rgba(0x222e1dff).into()),
-                        predictive_border: Some(rgba(0x38482fff).into()),
-                        renamed: Some(rgba(0x74ade8ff).into()),
-                        renamed_background: Some(rgba(0x18243dff).into()),
-                        renamed_border: Some(rgba(0x293c5bff).into()),
-                        success: Some(rgba(0xa1c181ff).into()),
-                        success_background: Some(rgba(0x222e1dff).into()),
-                        success_border: Some(rgba(0x38482fff).into()),
-                        unreachable: Some(rgba(0x838994ff).into()),
-                        unreachable_background: Some(rgba(0x3b414dff).into()),
-                        unreachable_border: Some(rgba(0x464b57ff).into()),
+                        modified_background: Some(rgba(0xfaf2e6ff).into()),
+                        modified_border: Some(rgba(0xf5e8d2ff).into()),
+                        predictive: Some(rgba(0x9c9fc7ff).into()),
+                        predictive_background: Some(rgba(0xe0ebdcff).into()),
+                        predictive_border: Some(rgba(0xc8dcc1ff).into()),
+                        renamed: Some(rgba(0x5c79e2ff).into()),
+                        renamed_background: Some(rgba(0xe2e2faff).into()),
+                        renamed_border: Some(rgba(0xcbcdf6ff).into()),
+                        success: Some(rgba(0x669f59ff).into()),
+                        success_background: Some(rgba(0xe0ebdcff).into()),
+                        success_border: Some(rgba(0xc8dcc1ff).into()),
+                        unreachable: Some(rgba(0x7f8188ff).into()),
+                        unreachable_background: Some(rgba(0xdcdcddff).into()),
+                        unreachable_border: Some(rgba(0xc9c9caff).into()),
                         warning: Some(rgba(0xdec184ff).into()),
-                        warning_background: Some(rgba(0x41331dff).into()),
-                        warning_border: Some(rgba(0x5d4c2fff).into()),
+                        warning_background: Some(rgba(0xfaf2e6ff).into()),
+                        warning_border: Some(rgba(0xf5e8d2ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x74ade8ff).into(),
-                            background: rgba(0x74ade8ff).into(),
-                            selection: rgba(0x74ade83d).into(),
+                            cursor: rgba(0x5c79e2ff).into(),
+                            background: rgba(0x5c79e2ff).into(),
+                            selection: rgba(0x5c79e23d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xbe5046ff).into(),
-                            background: rgba(0xbe5046ff).into(),
-                            selection: rgba(0xbe50463d).into(),
+                            cursor: rgba(0x994fa6ff).into(),
+                            background: rgba(0x994fa6ff).into(),
+                            selection: rgba(0x994fa63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xc0966bff).into(),
-                            background: rgba(0xc0966bff).into(),
-                            selection: rgba(0xc0966b3d).into(),
+                            cursor: rgba(0xad6f27ff).into(),
+                            background: rgba(0xad6f27ff).into(),
+                            selection: rgba(0xad6f273d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb478cfff).into(),
-                            background: rgba(0xb478cfff).into(),
-                            selection: rgba(0xb478cf3d).into(),
+                            cursor: rgba(0xa44aabff).into(),
+                            background: rgba(0xa44aabff).into(),
+                            selection: rgba(0xa44aab3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x6fb4c0ff).into(),
-                            background: rgba(0x6fb4c0ff).into(),
-                            selection: rgba(0x6fb4c03d).into(),
+                            cursor: rgba(0x3b82b7ff).into(),
+                            background: rgba(0x3b82b7ff).into(),
+                            selection: rgba(0x3b82b73d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xd07277ff).into(),
-                            background: rgba(0xd07277ff).into(),
-                            selection: rgba(0xd072773d).into(),
+                            cursor: rgba(0xd36151ff).into(),
+                            background: rgba(0xd36151ff).into(),
+                            selection: rgba(0xd361513d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0xdec184ff).into(),
@@ -628,9 +628,9 @@ pub fn one() -> UserThemeFamily {
                             selection: rgba(0xdec1843d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xa1c181ff).into(),
-                            background: rgba(0xa1c181ff).into(),
-                            selection: rgba(0xa1c1813d).into(),
+                            cursor: rgba(0x669f59ff).into(),
+                            background: rgba(0x669f59ff).into(),
+                            selection: rgba(0x669f593d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -638,63 +638,63 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x74ade8ff).into()),
+                                    color: Some(rgba(0x5c79e2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xc0966bff).into()),
+                                    color: Some(rgba(0xad6f26ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5d636fff).into()),
+                                    color: Some(rgba(0xa2a3a7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x878e98ff).into()),
+                                    color: Some(rgba(0x7c7e86ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xdfc184ff).into()),
+                                    color: Some(rgba(0x669f59ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x74ade9ff).into()),
+                                    color: Some(rgba(0x5c79e2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xc8ccd4ff).into()),
+                                    color: Some(rgba(0x383a41ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x74ade8ff).into()),
+                                    color: Some(rgba(0x5c79e2ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xc0966bff).into()),
+                                    color: Some(rgba(0xad6f26ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -702,21 +702,21 @@ pub fn one() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd07277ff).into()),
+                                    color: Some(rgba(0xd36050ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x74ade9ff).into()),
+                                    color: Some(rgba(0x5b79e3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5b708aff).into()),
+                                    color: Some(rgba(0x9295beff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },

crates/theme/src/themes/rose_pine.rs πŸ”—

@@ -16,170 +16,170 @@ pub fn rose_pine() -> UserThemeFamily {
         author: "Zed Industries".into(),
         themes: vec![
             UserTheme {
-                name: "RosΓ© Pine Dawn".into(),
-                appearance: Appearance::Light,
+                name: "RosΓ© Pine".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0xdcd6d5ff).into()),
-                        border_variant: Some(rgba(0xe5e0dfff).into()),
-                        border_focused: Some(rgba(0xc3d7dbff).into()),
-                        border_selected: Some(rgba(0xc3d7dbff).into()),
+                        border: Some(rgba(0x423f55ff).into()),
+                        border_variant: Some(rgba(0x232132ff).into()),
+                        border_focused: Some(rgba(0x435255ff).into()),
+                        border_selected: Some(rgba(0x435255ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xd0cccfff).into()),
-                        elevated_surface_background: Some(rgba(0xfef9f2ff).into()),
-                        surface_background: Some(rgba(0xfef9f2ff).into()),
-                        background: Some(rgba(0xdcd8d8ff).into()),
-                        panel_background: Some(rgba(0xfef9f2ff).into()),
-                        element_background: Some(rgba(0xfef9f2ff).into()),
-                        element_hover: Some(rgba(0xe5e0dfff).into()),
-                        element_active: Some(rgba(0xdbd5d4ff).into()),
-                        element_selected: Some(rgba(0xdbd5d4ff).into()),
-                        element_disabled: Some(rgba(0xfef9f2ff).into()),
-                        drop_target_background: Some(rgba(0x706c8c80).into()),
+                        border_disabled: Some(rgba(0x353347ff).into()),
+                        elevated_surface_background: Some(rgba(0x1d1b2aff).into()),
+                        surface_background: Some(rgba(0x1d1b2aff).into()),
+                        background: Some(rgba(0x292739ff).into()),
+                        panel_background: Some(rgba(0x1d1b2aff).into()),
+                        element_background: Some(rgba(0x1d1b2aff).into()),
+                        element_hover: Some(rgba(0x232132ff).into()),
+                        element_active: Some(rgba(0x403e53ff).into()),
+                        element_selected: Some(rgba(0x403e53ff).into()),
+                        element_disabled: Some(rgba(0x1d1b2aff).into()),
+                        drop_target_background: Some(rgba(0x75718e80).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xe5e0dfff).into()),
-                        ghost_element_active: Some(rgba(0xdbd5d4ff).into()),
-                        ghost_element_selected: Some(rgba(0xdbd5d4ff).into()),
-                        ghost_element_disabled: Some(rgba(0xfef9f2ff).into()),
-                        text: Some(rgba(0x575279ff).into()),
-                        text_muted: Some(rgba(0x706c8cff).into()),
-                        text_placeholder: Some(rgba(0x938fa3ff).into()),
-                        text_disabled: Some(rgba(0x938fa3ff).into()),
-                        text_accent: Some(rgba(0x57949fff).into()),
-                        icon: Some(rgba(0x575279ff).into()),
-                        icon_muted: Some(rgba(0x706c8cff).into()),
-                        icon_disabled: Some(rgba(0x938fa3ff).into()),
-                        icon_placeholder: Some(rgba(0x706c8cff).into()),
-                        icon_accent: Some(rgba(0x57949fff).into()),
-                        status_bar_background: Some(rgba(0xdcd8d8ff).into()),
-                        title_bar_background: Some(rgba(0xdcd8d8ff).into()),
-                        toolbar_background: Some(rgba(0xfaf4edff).into()),
-                        tab_bar_background: Some(rgba(0xfef9f2ff).into()),
-                        tab_inactive_background: Some(rgba(0xfef9f2ff).into()),
-                        tab_active_background: Some(rgba(0xfaf4edff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x5752794c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xe5e0dfff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xe5e0dfff).into()),
+                        ghost_element_hover: Some(rgba(0x232132ff).into()),
+                        ghost_element_active: Some(rgba(0x403e53ff).into()),
+                        ghost_element_selected: Some(rgba(0x403e53ff).into()),
+                        ghost_element_disabled: Some(rgba(0x1d1b2aff).into()),
+                        text: Some(rgba(0xe0def4ff).into()),
+                        text_muted: Some(rgba(0x75718eff).into()),
+                        text_placeholder: Some(rgba(0x2f2b43ff).into()),
+                        text_disabled: Some(rgba(0x2f2b43ff).into()),
+                        text_accent: Some(rgba(0x9cced7ff).into()),
+                        icon: Some(rgba(0xe0def4ff).into()),
+                        icon_muted: Some(rgba(0x75718eff).into()),
+                        icon_disabled: Some(rgba(0x2f2b43ff).into()),
+                        icon_placeholder: Some(rgba(0x75718eff).into()),
+                        icon_accent: Some(rgba(0x9cced7ff).into()),
+                        status_bar_background: Some(rgba(0x292739ff).into()),
+                        title_bar_background: Some(rgba(0x292739ff).into()),
+                        toolbar_background: Some(rgba(0x191724ff).into()),
+                        tab_bar_background: Some(rgba(0x1d1b2aff).into()),
+                        tab_inactive_background: Some(rgba(0x1d1b2aff).into()),
+                        tab_active_background: Some(rgba(0x191724ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xe0def44c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x232132ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x232132ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xfdf8f1ff).into()),
-                        editor_foreground: Some(rgba(0x575279ff).into()),
-                        editor_background: Some(rgba(0xfaf4edff).into()),
-                        editor_gutter_background: Some(rgba(0xfaf4edff).into()),
-                        editor_subheader_background: Some(rgba(0xfef9f2ff).into()),
-                        editor_active_line_background: Some(rgba(0xfef9f2bf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xfef9f2ff).into()),
-                        editor_line_number: Some(rgba(0x57527959).into()),
-                        editor_active_line_number: Some(rgba(0x575279ff).into()),
-                        editor_invisible: Some(rgba(0x706c8cff).into()),
-                        editor_wrap_guide: Some(rgba(0x5752790d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x5752791a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x57949f1a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0x9691a466).into()),
-                        terminal_background: Some(rgba(0xfaf4edff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0xb8b2baff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xdcb0bbff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xa5d5c5ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xfccd9bff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0xacc9ceff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xbcb1bdff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x97b1c0ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x575279ff).into()),
-                        terminal_ansi_black: Some(rgba(0xfaf4edff).into()),
-                        terminal_ansi_red: Some(rgba(0xb4647aff).into()),
-                        terminal_ansi_green: Some(rgba(0x3eaa8eff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xe99d35ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x57949fff).into()),
-                        terminal_ansi_magenta: Some(rgba(0x7c697fff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x2a6983ff).into()),
-                        terminal_ansi_white: Some(rgba(0x575279ff).into()),
-                        link_text_hover: Some(rgba(0x57949fff).into()),
+                        scrollbar_track_border: Some(rgba(0x1c1a29ff).into()),
+                        editor_foreground: Some(rgba(0xe0def4ff).into()),
+                        editor_background: Some(rgba(0x191724ff).into()),
+                        editor_gutter_background: Some(rgba(0x191724ff).into()),
+                        editor_subheader_background: Some(rgba(0x1d1b2aff).into()),
+                        editor_active_line_background: Some(rgba(0x1d1b2abf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x1d1b2aff).into()),
+                        editor_line_number: Some(rgba(0xe0def459).into()),
+                        editor_active_line_number: Some(rgba(0xe0def4ff).into()),
+                        editor_invisible: Some(rgba(0x75718eff).into()),
+                        editor_wrap_guide: Some(rgba(0xe0def40d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xe0def41a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x9cced71a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0x28253c66).into()),
+                        terminal_background: Some(rgba(0x191724ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x403d55ff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x31614fff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x4c3b47ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x203a46ff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()),
+                        terminal_ansi_black: Some(rgba(0x191724ff).into()),
+                        terminal_ansi_red: Some(rgba(0xea6f92ff).into()),
+                        terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x9cced7ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0x9d7691ff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x32748fff).into()),
+                        terminal_ansi_white: Some(rgba(0xe0def4ff).into()),
+                        link_text_hover: Some(rgba(0x9cced7ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xe99d35ff).into()),
-                        conflict_background: Some(rgba(0xffebd6ff).into()),
-                        conflict_border: Some(rgba(0xffdab7ff).into()),
-                        created: Some(rgba(0x3eaa8eff).into()),
-                        created_background: Some(rgba(0xdbeee7ff).into()),
-                        created_border: Some(rgba(0xbee0d5ff).into()),
-                        deleted: Some(rgba(0xb4647aff).into()),
-                        deleted_background: Some(rgba(0xf1dfe3ff).into()),
-                        deleted_border: Some(rgba(0xe6c6cdff).into()),
-                        error: Some(rgba(0xb4647aff).into()),
-                        error_background: Some(rgba(0xf1dfe3ff).into()),
-                        error_border: Some(rgba(0xe6c6cdff).into()),
-                        hidden: Some(rgba(0x938fa3ff).into()),
-                        hidden_background: Some(rgba(0xdcd8d8ff).into()),
-                        hidden_border: Some(rgba(0xd0cccfff).into()),
-                        hint: Some(rgba(0x7a92aaff).into()),
-                        hint_background: Some(rgba(0xdde9ebff).into()),
-                        hint_border: Some(rgba(0xc3d7dbff).into()),
-                        ignored: Some(rgba(0x706c8cff).into()),
-                        ignored_background: Some(rgba(0xdcd8d8ff).into()),
-                        ignored_border: Some(rgba(0xdcd6d5ff).into()),
-                        info: Some(rgba(0x57949fff).into()),
-                        info_background: Some(rgba(0xdde9ebff).into()),
-                        info_border: Some(rgba(0xc3d7dbff).into()),
-                        modified: Some(rgba(0xe99d35ff).into()),
-                        modified_background: Some(rgba(0xffebd6ff).into()),
-                        modified_border: Some(rgba(0xffdab7ff).into()),
-                        predictive: Some(rgba(0xa2acbeff).into()),
-                        predictive_background: Some(rgba(0xdbeee7ff).into()),
-                        predictive_border: Some(rgba(0xbee0d5ff).into()),
-                        renamed: Some(rgba(0x57949fff).into()),
-                        renamed_background: Some(rgba(0xdde9ebff).into()),
-                        renamed_border: Some(rgba(0xc3d7dbff).into()),
-                        success: Some(rgba(0x3eaa8eff).into()),
-                        success_background: Some(rgba(0xdbeee7ff).into()),
-                        success_border: Some(rgba(0xbee0d5ff).into()),
-                        unreachable: Some(rgba(0x706c8cff).into()),
-                        unreachable_background: Some(rgba(0xdcd8d8ff).into()),
-                        unreachable_border: Some(rgba(0xdcd6d5ff).into()),
-                        warning: Some(rgba(0xe99d35ff).into()),
-                        warning_background: Some(rgba(0xffebd6ff).into()),
-                        warning_border: Some(rgba(0xffdab7ff).into()),
+                        conflict: Some(rgba(0xf5c177ff).into()),
+                        conflict_background: Some(rgba(0x50341aff).into()),
+                        conflict_border: Some(rgba(0x6d4d2bff).into()),
+                        created: Some(rgba(0x5dc2a3ff).into()),
+                        created_background: Some(rgba(0x182e23ff).into()),
+                        created_border: Some(rgba(0x254839ff).into()),
+                        deleted: Some(rgba(0xea6f92ff).into()),
+                        deleted_background: Some(rgba(0x431820ff).into()),
+                        deleted_border: Some(rgba(0x612834ff).into()),
+                        error: Some(rgba(0xea6f92ff).into()),
+                        error_background: Some(rgba(0x431820ff).into()),
+                        error_border: Some(rgba(0x612834ff).into()),
+                        hidden: Some(rgba(0x2f2b43ff).into()),
+                        hidden_background: Some(rgba(0x292739ff).into()),
+                        hidden_border: Some(rgba(0x353347ff).into()),
+                        hint: Some(rgba(0x5e768cff).into()),
+                        hint_background: Some(rgba(0x2f3739ff).into()),
+                        hint_border: Some(rgba(0x435255ff).into()),
+                        ignored: Some(rgba(0x75718eff).into()),
+                        ignored_background: Some(rgba(0x292739ff).into()),
+                        ignored_border: Some(rgba(0x423f55ff).into()),
+                        info: Some(rgba(0x9cced7ff).into()),
+                        info_background: Some(rgba(0x2f3739ff).into()),
+                        info_border: Some(rgba(0x435255ff).into()),
+                        modified: Some(rgba(0xf5c177ff).into()),
+                        modified_background: Some(rgba(0x50341aff).into()),
+                        modified_border: Some(rgba(0x6d4d2bff).into()),
+                        predictive: Some(rgba(0x556b81ff).into()),
+                        predictive_background: Some(rgba(0x182e23ff).into()),
+                        predictive_border: Some(rgba(0x254839ff).into()),
+                        renamed: Some(rgba(0x9cced7ff).into()),
+                        renamed_background: Some(rgba(0x2f3739ff).into()),
+                        renamed_border: Some(rgba(0x435255ff).into()),
+                        success: Some(rgba(0x5dc2a3ff).into()),
+                        success_background: Some(rgba(0x182e23ff).into()),
+                        success_border: Some(rgba(0x254839ff).into()),
+                        unreachable: Some(rgba(0x75718eff).into()),
+                        unreachable_background: Some(rgba(0x292739ff).into()),
+                        unreachable_border: Some(rgba(0x423f55ff).into()),
+                        warning: Some(rgba(0xf5c177ff).into()),
+                        warning_background: Some(rgba(0x50341aff).into()),
+                        warning_border: Some(rgba(0x6d4d2bff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x57949fff).into(),
-                            background: rgba(0x57949fff).into(),
-                            selection: rgba(0x57949f3d).into(),
+                            cursor: rgba(0x9cced7ff).into(),
+                            background: rgba(0x9cced7ff).into(),
+                            selection: rgba(0x9cced73d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x7c697fff).into(),
-                            background: rgba(0x7c697fff).into(),
-                            selection: rgba(0x7c697f3d).into(),
+                            cursor: rgba(0x9d7691ff).into(),
+                            background: rgba(0x9d7691ff).into(),
+                            selection: rgba(0x9d76913d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x907aa9ff).into(),
-                            background: rgba(0x907aa9ff).into(),
-                            selection: rgba(0x907aa93d).into(),
+                            cursor: rgba(0xc4a7e6ff).into(),
+                            background: rgba(0xc4a7e6ff).into(),
+                            selection: rgba(0xc4a7e63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x907aa9ff).into(),
-                            background: rgba(0x907aa9ff).into(),
-                            selection: rgba(0x907aa93d).into(),
+                            cursor: rgba(0xc4a7e6ff).into(),
+                            background: rgba(0xc4a7e6ff).into(),
+                            selection: rgba(0xc4a7e63d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x2a6983ff).into(),
-                            background: rgba(0x2a6983ff).into(),
-                            selection: rgba(0x2a69833d).into(),
+                            cursor: rgba(0x32748fff).into(),
+                            background: rgba(0x32748fff).into(),
+                            selection: rgba(0x32748f3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb4647aff).into(),
-                            background: rgba(0xb4647aff).into(),
-                            selection: rgba(0xb4647a3d).into(),
+                            cursor: rgba(0xea6f92ff).into(),
+                            background: rgba(0xea6f92ff).into(),
+                            selection: rgba(0xea6f923d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xe99d35ff).into(),
-                            background: rgba(0xe99d35ff).into(),
-                            selection: rgba(0xe99d353d).into(),
+                            cursor: rgba(0xf5c177ff).into(),
+                            background: rgba(0xf5c177ff).into(),
+                            selection: rgba(0xf5c1773d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x3eaa8eff).into(),
-                            background: rgba(0x3eaa8eff).into(),
-                            selection: rgba(0x3eaa8e3d).into(),
+                            cursor: rgba(0x5dc2a3ff).into(),
+                            background: rgba(0x5dc2a3ff).into(),
+                            selection: rgba(0x5dc2a33d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -187,63 +187,63 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd7827eff).into()),
+                                    color: Some(rgba(0xebbcbaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9893a5ff).into()),
+                                    color: Some(rgba(0x6e6a86ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x6f6b8cff).into()),
+                                    color: Some(rgba(0x777390ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3eaa8eff).into()),
+                                    color: Some(rgba(0x5dc2a3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x575279ff).into()),
+                                    color: Some(rgba(0xe0def4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -251,28 +251,28 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x907aa9ff).into()),
+                                    color: Some(rgba(0xc4a7e6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd7827eff).into()),
+                                    color: Some(rgba(0xebbcbaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function.method".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd7827eff).into()),
+                                    color: Some(rgba(0xebbcbaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x7a92aaff).into()),
+                                    color: Some(rgba(0x5e768cff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -280,21 +280,21 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x286983ff).into()),
+                                    color: Some(rgba(0x31748fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x56949fff).into()),
+                                    color: Some(rgba(0x9ccfd8ff).into()),
                                     font_style: Some(UserFontStyle::Normal),
                                     ..Default::default()
                                 },
@@ -302,28 +302,28 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "link_uri".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xd7827eff).into()),
+                                    color: Some(rgba(0xebbcbaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "number".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x3eaa8eff).into()),
+                                    color: Some(rgba(0x5dc2a3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x286983ff).into()),
+                                    color: Some(rgba(0x31748fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xa2acbeff).into()),
+                                    color: Some(rgba(0x556b81ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -331,112 +331,112 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x575279ff).into()),
+                                    color: Some(rgba(0xe0def4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x575279ff).into()),
+                                    color: Some(rgba(0xe0def4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x797593ff).into()),
+                                    color: Some(rgba(0x908caaff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x635e82ff).into()),
+                                    color: Some(rgba(0x9d99b6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x635e82ff).into()),
+                                    color: Some(rgba(0x9d99b6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x635e82ff).into()),
+                                    color: Some(rgba(0x9d99b6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x635e82ff).into()),
+                                    color: Some(rgba(0x9d99b6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xea9d34ff).into()),
+                                    color: Some(rgba(0xf6c177ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x6f6b8cff).into()),
+                                    color: Some(rgba(0x777390ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x907aa9ff).into()),
+                                    color: Some(rgba(0xc4a7e6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x907aa9ff).into()),
+                                    color: Some(rgba(0xc4a7e6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x907aa9ff).into()),
+                                    color: Some(rgba(0xc4a7e6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x56949fff).into()),
+                                    color: Some(rgba(0x9ccfd8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x907aa9ff).into()),
+                                    color: Some(rgba(0xc4a7e6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xea9d34ff).into()),
+                                    color: Some(rgba(0xf6c177ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -444,28 +444,28 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "type".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x56949fff).into()),
+                                    color: Some(rgba(0x9ccfd8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "type.builtin".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x56949fff).into()),
+                                    color: Some(rgba(0x9ccfd8ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variable".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x575279ff).into()),
+                                    color: Some(rgba(0xe0def4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x57949fff).into()),
+                                    color: Some(rgba(0x9cced7ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -474,170 +474,170 @@ pub fn rose_pine() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "RosΓ© Pine Moon".into(),
-                appearance: Appearance::Dark,
+                name: "RosΓ© Pine Dawn".into(),
+                appearance: Appearance::Light,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x504c68ff).into()),
-                        border_variant: Some(rgba(0x322f48ff).into()),
-                        border_focused: Some(rgba(0x435255ff).into()),
-                        border_selected: Some(rgba(0x435255ff).into()),
+                        border: Some(rgba(0xdcd6d5ff).into()),
+                        border_variant: Some(rgba(0xe5e0dfff).into()),
+                        border_focused: Some(rgba(0xc3d7dbff).into()),
+                        border_selected: Some(rgba(0xc3d7dbff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0x44415bff).into()),
-                        elevated_surface_background: Some(rgba(0x28253cff).into()),
-                        surface_background: Some(rgba(0x28253cff).into()),
-                        background: Some(rgba(0x38354eff).into()),
-                        panel_background: Some(rgba(0x28253cff).into()),
-                        element_background: Some(rgba(0x28253cff).into()),
-                        element_hover: Some(rgba(0x322f48ff).into()),
-                        element_active: Some(rgba(0x4f4b66ff).into()),
-                        element_selected: Some(rgba(0x4f4b66ff).into()),
-                        element_disabled: Some(rgba(0x28253cff).into()),
-                        drop_target_background: Some(rgba(0x85819e80).into()),
+                        border_disabled: Some(rgba(0xd0cccfff).into()),
+                        elevated_surface_background: Some(rgba(0xfef9f2ff).into()),
+                        surface_background: Some(rgba(0xfef9f2ff).into()),
+                        background: Some(rgba(0xdcd8d8ff).into()),
+                        panel_background: Some(rgba(0xfef9f2ff).into()),
+                        element_background: Some(rgba(0xfef9f2ff).into()),
+                        element_hover: Some(rgba(0xe5e0dfff).into()),
+                        element_active: Some(rgba(0xdbd5d4ff).into()),
+                        element_selected: Some(rgba(0xdbd5d4ff).into()),
+                        element_disabled: Some(rgba(0xfef9f2ff).into()),
+                        drop_target_background: Some(rgba(0x706c8c80).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0x322f48ff).into()),
-                        ghost_element_active: Some(rgba(0x4f4b66ff).into()),
-                        ghost_element_selected: Some(rgba(0x4f4b66ff).into()),
-                        ghost_element_disabled: Some(rgba(0x28253cff).into()),
-                        text: Some(rgba(0xe0def4ff).into()),
-                        text_muted: Some(rgba(0x85819eff).into()),
-                        text_placeholder: Some(rgba(0x615d7aff).into()),
-                        text_disabled: Some(rgba(0x615d7aff).into()),
-                        text_accent: Some(rgba(0x9cced7ff).into()),
-                        icon: Some(rgba(0xe0def4ff).into()),
-                        icon_muted: Some(rgba(0x85819eff).into()),
-                        icon_disabled: Some(rgba(0x615d7aff).into()),
-                        icon_placeholder: Some(rgba(0x85819eff).into()),
-                        icon_accent: Some(rgba(0x9cced7ff).into()),
-                        status_bar_background: Some(rgba(0x38354eff).into()),
-                        title_bar_background: Some(rgba(0x38354eff).into()),
-                        toolbar_background: Some(rgba(0x232136ff).into()),
-                        tab_bar_background: Some(rgba(0x28253cff).into()),
-                        tab_inactive_background: Some(rgba(0x28253cff).into()),
-                        tab_active_background: Some(rgba(0x232136ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0xe0def44c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0x322f48ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0x322f48ff).into()),
+                        ghost_element_hover: Some(rgba(0xe5e0dfff).into()),
+                        ghost_element_active: Some(rgba(0xdbd5d4ff).into()),
+                        ghost_element_selected: Some(rgba(0xdbd5d4ff).into()),
+                        ghost_element_disabled: Some(rgba(0xfef9f2ff).into()),
+                        text: Some(rgba(0x575279ff).into()),
+                        text_muted: Some(rgba(0x706c8cff).into()),
+                        text_placeholder: Some(rgba(0x938fa3ff).into()),
+                        text_disabled: Some(rgba(0x938fa3ff).into()),
+                        text_accent: Some(rgba(0x57949fff).into()),
+                        icon: Some(rgba(0x575279ff).into()),
+                        icon_muted: Some(rgba(0x706c8cff).into()),
+                        icon_disabled: Some(rgba(0x938fa3ff).into()),
+                        icon_placeholder: Some(rgba(0x706c8cff).into()),
+                        icon_accent: Some(rgba(0x57949fff).into()),
+                        status_bar_background: Some(rgba(0xdcd8d8ff).into()),
+                        title_bar_background: Some(rgba(0xdcd8d8ff).into()),
+                        toolbar_background: Some(rgba(0xfaf4edff).into()),
+                        tab_bar_background: Some(rgba(0xfef9f2ff).into()),
+                        tab_inactive_background: Some(rgba(0xfef9f2ff).into()),
+                        tab_active_background: Some(rgba(0xfaf4edff).into()),
+                        scrollbar_thumb_background: Some(rgba(0x5752794c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0xe5e0dfff).into()),
+                        scrollbar_thumb_border: Some(rgba(0xe5e0dfff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0x27243bff).into()),
-                        editor_foreground: Some(rgba(0xe0def4ff).into()),
-                        editor_background: Some(rgba(0x232136ff).into()),
-                        editor_gutter_background: Some(rgba(0x232136ff).into()),
-                        editor_subheader_background: Some(rgba(0x28253cff).into()),
-                        editor_active_line_background: Some(rgba(0x28253cbf).into()),
-                        editor_highlighted_line_background: Some(rgba(0x28253cff).into()),
-                        editor_line_number: Some(rgba(0xe0def459).into()),
-                        editor_active_line_number: Some(rgba(0xe0def4ff).into()),
-                        editor_invisible: Some(rgba(0x85819eff).into()),
-                        editor_wrap_guide: Some(rgba(0xe0def40d).into()),
-                        editor_active_wrap_guide: Some(rgba(0xe0def41a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x9cced71a).into()),
-                        editor_document_highlight_write_background: Some(rgba(0x59557166).into()),
-                        terminal_background: Some(rgba(0x232136ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x3f3b58ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0x31614fff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0x51414eff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x264654ff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()),
-                        terminal_ansi_black: Some(rgba(0x232136ff).into()),
-                        terminal_ansi_red: Some(rgba(0xea6f92ff).into()),
-                        terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x9cced7ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0xa784a1ff).into()),
-                        terminal_ansi_cyan: Some(rgba(0x3f8fb0ff).into()),
-                        terminal_ansi_white: Some(rgba(0xe0def4ff).into()),
-                        link_text_hover: Some(rgba(0x9cced7ff).into()),
+                        scrollbar_track_border: Some(rgba(0xfdf8f1ff).into()),
+                        editor_foreground: Some(rgba(0x575279ff).into()),
+                        editor_background: Some(rgba(0xfaf4edff).into()),
+                        editor_gutter_background: Some(rgba(0xfaf4edff).into()),
+                        editor_subheader_background: Some(rgba(0xfef9f2ff).into()),
+                        editor_active_line_background: Some(rgba(0xfef9f2bf).into()),
+                        editor_highlighted_line_background: Some(rgba(0xfef9f2ff).into()),
+                        editor_line_number: Some(rgba(0x57527959).into()),
+                        editor_active_line_number: Some(rgba(0x575279ff).into()),
+                        editor_invisible: Some(rgba(0x706c8cff).into()),
+                        editor_wrap_guide: Some(rgba(0x5752790d).into()),
+                        editor_active_wrap_guide: Some(rgba(0x5752791a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x57949f1a).into()),
+                        editor_document_highlight_write_background: Some(rgba(0x9691a466).into()),
+                        terminal_background: Some(rgba(0xfaf4edff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0xb8b2baff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0xdcb0bbff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0xa5d5c5ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0xfccd9bff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0xacc9ceff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0xbcb1bdff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x97b1c0ff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0x575279ff).into()),
+                        terminal_ansi_black: Some(rgba(0xfaf4edff).into()),
+                        terminal_ansi_red: Some(rgba(0xb4647aff).into()),
+                        terminal_ansi_green: Some(rgba(0x3eaa8eff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xe99d35ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x57949fff).into()),
+                        terminal_ansi_magenta: Some(rgba(0x7c697fff).into()),
+                        terminal_ansi_cyan: Some(rgba(0x2a6983ff).into()),
+                        terminal_ansi_white: Some(rgba(0x575279ff).into()),
+                        link_text_hover: Some(rgba(0x57949fff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xf5c177ff).into()),
-                        conflict_background: Some(rgba(0x50341aff).into()),
-                        conflict_border: Some(rgba(0x6d4d2bff).into()),
-                        created: Some(rgba(0x5dc2a3ff).into()),
-                        created_background: Some(rgba(0x182e23ff).into()),
-                        created_border: Some(rgba(0x254839ff).into()),
-                        deleted: Some(rgba(0xea6f92ff).into()),
-                        deleted_background: Some(rgba(0x431820ff).into()),
-                        deleted_border: Some(rgba(0x612834ff).into()),
-                        error: Some(rgba(0xea6f92ff).into()),
-                        error_background: Some(rgba(0x431820ff).into()),
-                        error_border: Some(rgba(0x612834ff).into()),
-                        hidden: Some(rgba(0x615d7aff).into()),
-                        hidden_background: Some(rgba(0x38354eff).into()),
-                        hidden_border: Some(rgba(0x44415bff).into()),
-                        hint: Some(rgba(0x728aa2ff).into()),
-                        hint_background: Some(rgba(0x2f3739ff).into()),
-                        hint_border: Some(rgba(0x435255ff).into()),
-                        ignored: Some(rgba(0x85819eff).into()),
-                        ignored_background: Some(rgba(0x38354eff).into()),
-                        ignored_border: Some(rgba(0x504c68ff).into()),
-                        info: Some(rgba(0x9cced7ff).into()),
-                        info_background: Some(rgba(0x2f3739ff).into()),
-                        info_border: Some(rgba(0x435255ff).into()),
-                        modified: Some(rgba(0xf5c177ff).into()),
-                        modified_background: Some(rgba(0x50341aff).into()),
-                        modified_border: Some(rgba(0x6d4d2bff).into()),
-                        predictive: Some(rgba(0x516b83ff).into()),
-                        predictive_background: Some(rgba(0x182e23ff).into()),
-                        predictive_border: Some(rgba(0x254839ff).into()),
-                        renamed: Some(rgba(0x9cced7ff).into()),
-                        renamed_background: Some(rgba(0x2f3739ff).into()),
-                        renamed_border: Some(rgba(0x435255ff).into()),
-                        success: Some(rgba(0x5dc2a3ff).into()),
-                        success_background: Some(rgba(0x182e23ff).into()),
-                        success_border: Some(rgba(0x254839ff).into()),
-                        unreachable: Some(rgba(0x85819eff).into()),
-                        unreachable_background: Some(rgba(0x38354eff).into()),
-                        unreachable_border: Some(rgba(0x504c68ff).into()),
-                        warning: Some(rgba(0xf5c177ff).into()),
-                        warning_background: Some(rgba(0x50341aff).into()),
-                        warning_border: Some(rgba(0x6d4d2bff).into()),
+                        conflict: Some(rgba(0xe99d35ff).into()),
+                        conflict_background: Some(rgba(0xffebd6ff).into()),
+                        conflict_border: Some(rgba(0xffdab7ff).into()),
+                        created: Some(rgba(0x3eaa8eff).into()),
+                        created_background: Some(rgba(0xdbeee7ff).into()),
+                        created_border: Some(rgba(0xbee0d5ff).into()),
+                        deleted: Some(rgba(0xb4647aff).into()),
+                        deleted_background: Some(rgba(0xf1dfe3ff).into()),
+                        deleted_border: Some(rgba(0xe6c6cdff).into()),
+                        error: Some(rgba(0xb4647aff).into()),
+                        error_background: Some(rgba(0xf1dfe3ff).into()),
+                        error_border: Some(rgba(0xe6c6cdff).into()),
+                        hidden: Some(rgba(0x938fa3ff).into()),
+                        hidden_background: Some(rgba(0xdcd8d8ff).into()),
+                        hidden_border: Some(rgba(0xd0cccfff).into()),
+                        hint: Some(rgba(0x7a92aaff).into()),
+                        hint_background: Some(rgba(0xdde9ebff).into()),
+                        hint_border: Some(rgba(0xc3d7dbff).into()),
+                        ignored: Some(rgba(0x706c8cff).into()),
+                        ignored_background: Some(rgba(0xdcd8d8ff).into()),
+                        ignored_border: Some(rgba(0xdcd6d5ff).into()),
+                        info: Some(rgba(0x57949fff).into()),
+                        info_background: Some(rgba(0xdde9ebff).into()),
+                        info_border: Some(rgba(0xc3d7dbff).into()),
+                        modified: Some(rgba(0xe99d35ff).into()),
+                        modified_background: Some(rgba(0xffebd6ff).into()),
+                        modified_border: Some(rgba(0xffdab7ff).into()),
+                        predictive: Some(rgba(0xa2acbeff).into()),
+                        predictive_background: Some(rgba(0xdbeee7ff).into()),
+                        predictive_border: Some(rgba(0xbee0d5ff).into()),
+                        renamed: Some(rgba(0x57949fff).into()),
+                        renamed_background: Some(rgba(0xdde9ebff).into()),
+                        renamed_border: Some(rgba(0xc3d7dbff).into()),
+                        success: Some(rgba(0x3eaa8eff).into()),
+                        success_background: Some(rgba(0xdbeee7ff).into()),
+                        success_border: Some(rgba(0xbee0d5ff).into()),
+                        unreachable: Some(rgba(0x706c8cff).into()),
+                        unreachable_background: Some(rgba(0xdcd8d8ff).into()),
+                        unreachable_border: Some(rgba(0xdcd6d5ff).into()),
+                        warning: Some(rgba(0xe99d35ff).into()),
+                        warning_background: Some(rgba(0xffebd6ff).into()),
+                        warning_border: Some(rgba(0xffdab7ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x9cced7ff).into(),
-                            background: rgba(0x9cced7ff).into(),
-                            selection: rgba(0x9cced73d).into(),
+                            cursor: rgba(0x57949fff).into(),
+                            background: rgba(0x57949fff).into(),
+                            selection: rgba(0x57949f3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xa784a1ff).into(),
-                            background: rgba(0xa784a1ff).into(),
-                            selection: rgba(0xa784a13d).into(),
+                            cursor: rgba(0x7c697fff).into(),
+                            background: rgba(0x7c697fff).into(),
+                            selection: rgba(0x7c697f3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xc4a7e6ff).into(),
-                            background: rgba(0xc4a7e6ff).into(),
-                            selection: rgba(0xc4a7e63d).into(),
+                            cursor: rgba(0x907aa9ff).into(),
+                            background: rgba(0x907aa9ff).into(),
+                            selection: rgba(0x907aa93d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xc4a7e6ff).into(),
-                            background: rgba(0xc4a7e6ff).into(),
-                            selection: rgba(0xc4a7e63d).into(),
+                            cursor: rgba(0x907aa9ff).into(),
+                            background: rgba(0x907aa9ff).into(),
+                            selection: rgba(0x907aa93d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x3f8fb0ff).into(),
-                            background: rgba(0x3f8fb0ff).into(),
-                            selection: rgba(0x3f8fb03d).into(),
+                            cursor: rgba(0x2a6983ff).into(),
+                            background: rgba(0x2a6983ff).into(),
+                            selection: rgba(0x2a69833d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xea6f92ff).into(),
-                            background: rgba(0xea6f92ff).into(),
-                            selection: rgba(0xea6f923d).into(),
+                            cursor: rgba(0xb4647aff).into(),
+                            background: rgba(0xb4647aff).into(),
+                            selection: rgba(0xb4647a3d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xf5c177ff).into(),
-                            background: rgba(0xf5c177ff).into(),
-                            selection: rgba(0xf5c1773d).into(),
+                            cursor: rgba(0xe99d35ff).into(),
+                            background: rgba(0xe99d35ff).into(),
+                            selection: rgba(0xe99d353d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x5dc2a3ff).into(),
-                            background: rgba(0x5dc2a3ff).into(),
-                            selection: rgba(0x5dc2a33d).into(),
+                            cursor: rgba(0x3eaa8eff).into(),
+                            background: rgba(0x3eaa8eff).into(),
+                            selection: rgba(0x3eaa8e3d).into(),
                         },
                     ])),
                     syntax: Some(UserSyntaxTheme {
@@ -645,63 +645,63 @@ pub fn rose_pine() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9cced7ff).into()),
+                                    color: Some(rgba(0x57949fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "boolean".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xea9a97ff).into()),
+                                    color: Some(rgba(0xd7827eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x6e6a86ff).into()),
+                                    color: Some(rgba(0x9893a5ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x8682a0ff).into()),
+                                    color: Some(rgba(0x6f6b8cff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5dc2a3ff).into()),
+                                    color: Some(rgba(0x3eaa8eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9cced7ff).into()),
+                                    color: Some(rgba(0x57949fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xe0def4ff).into()),
+                                    color: Some(rgba(0x575279ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9cced7ff).into()),
+                                    color: Some(rgba(0x57949fff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x9cced7ff).into()),
+                                    color: Some(rgba(0x57949fff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },

crates/theme/src/themes/solarized.rs πŸ”—

@@ -16,150 +16,150 @@ pub fn solarized() -> UserThemeFamily {
         author: "Zed Industries".into(),
         themes: vec![
             UserTheme {
-                name: "Solarized Light".into(),
-                appearance: Appearance::Light,
+                name: "Solarized Dark".into(),
+                appearance: Appearance::Dark,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x9faaa8ff).into()),
-                        border_variant: Some(rgba(0xdcdacbff).into()),
-                        border_focused: Some(rgba(0xbfd3efff).into()),
-                        border_selected: Some(rgba(0xbfd3efff).into()),
+                        border: Some(rgba(0x2b4f58ff).into()),
+                        border_variant: Some(rgba(0x063541ff).into()),
+                        border_focused: Some(rgba(0x1c3249ff).into()),
+                        border_selected: Some(rgba(0x1c3249ff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0xb7bdb6ff).into()),
-                        elevated_surface_background: Some(rgba(0xf3eddaff).into()),
-                        surface_background: Some(rgba(0xf3eddaff).into()),
-                        background: Some(rgba(0xcfd0c4ff).into()),
-                        panel_background: Some(rgba(0xf3eddaff).into()),
-                        element_background: Some(rgba(0xf3eddaff).into()),
-                        element_hover: Some(rgba(0xdcdacbff).into()),
-                        element_active: Some(rgba(0xa2aca9ff).into()),
-                        element_selected: Some(rgba(0xa2aca9ff).into()),
-                        element_disabled: Some(rgba(0xf3eddaff).into()),
-                        drop_target_background: Some(rgba(0x34555e80).into()),
+                        border_disabled: Some(rgba(0x19424dff).into()),
+                        elevated_surface_background: Some(rgba(0x04313cff).into()),
+                        surface_background: Some(rgba(0x04313cff).into()),
+                        background: Some(rgba(0x083743ff).into()),
+                        panel_background: Some(rgba(0x04313cff).into()),
+                        element_background: Some(rgba(0x04313cff).into()),
+                        element_hover: Some(rgba(0x063541ff).into()),
+                        element_active: Some(rgba(0x294e58ff).into()),
+                        element_selected: Some(rgba(0x294e58ff).into()),
+                        element_disabled: Some(rgba(0x04313cff).into()),
+                        drop_target_background: Some(rgba(0x93a1a180).into()),
                         ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0xdcdacbff).into()),
-                        ghost_element_active: Some(rgba(0xa2aca9ff).into()),
-                        ghost_element_selected: Some(rgba(0xa2aca9ff).into()),
-                        ghost_element_disabled: Some(rgba(0xf3eddaff).into()),
-                        text: Some(rgba(0x002b36ff).into()),
-                        text_muted: Some(rgba(0x34555eff).into()),
-                        text_placeholder: Some(rgba(0x6a7f86ff).into()),
-                        text_disabled: Some(rgba(0x6a7f86ff).into()),
-                        text_accent: Some(rgba(0x298bd1ff).into()),
-                        icon: Some(rgba(0x002b36ff).into()),
-                        icon_muted: Some(rgba(0x34555eff).into()),
-                        icon_disabled: Some(rgba(0x6a7f86ff).into()),
-                        icon_placeholder: Some(rgba(0x34555eff).into()),
-                        icon_accent: Some(rgba(0x298bd1ff).into()),
-                        status_bar_background: Some(rgba(0xcfd0c4ff).into()),
-                        title_bar_background: Some(rgba(0xcfd0c4ff).into()),
-                        toolbar_background: Some(rgba(0xfdf6e3ff).into()),
-                        tab_bar_background: Some(rgba(0xf3eddaff).into()),
-                        tab_inactive_background: Some(rgba(0xf3eddaff).into()),
-                        tab_active_background: Some(rgba(0xfdf6e3ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0x002b364c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0xdcdacbff).into()),
-                        scrollbar_thumb_border: Some(rgba(0xdcdacbff).into()),
+                        ghost_element_hover: Some(rgba(0x063541ff).into()),
+                        ghost_element_active: Some(rgba(0x294e58ff).into()),
+                        ghost_element_selected: Some(rgba(0x294e58ff).into()),
+                        ghost_element_disabled: Some(rgba(0x04313cff).into()),
+                        text: Some(rgba(0xfdf6e3ff).into()),
+                        text_muted: Some(rgba(0x93a1a1ff).into()),
+                        text_placeholder: Some(rgba(0x6f8389ff).into()),
+                        text_disabled: Some(rgba(0x6f8389ff).into()),
+                        text_accent: Some(rgba(0x288bd1ff).into()),
+                        icon: Some(rgba(0xfdf6e3ff).into()),
+                        icon_muted: Some(rgba(0x93a1a1ff).into()),
+                        icon_disabled: Some(rgba(0x6f8389ff).into()),
+                        icon_placeholder: Some(rgba(0x93a1a1ff).into()),
+                        icon_accent: Some(rgba(0x288bd1ff).into()),
+                        status_bar_background: Some(rgba(0x083743ff).into()),
+                        title_bar_background: Some(rgba(0x083743ff).into()),
+                        toolbar_background: Some(rgba(0x002b36ff).into()),
+                        tab_bar_background: Some(rgba(0x04313cff).into()),
+                        tab_inactive_background: Some(rgba(0x04313cff).into()),
+                        tab_active_background: Some(rgba(0x002b36ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0xfdf6e34c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0x063541ff).into()),
+                        scrollbar_thumb_border: Some(rgba(0x063541ff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0xf5eedbff).into()),
-                        editor_foreground: Some(rgba(0x002b36ff).into()),
-                        editor_background: Some(rgba(0xfdf6e3ff).into()),
-                        editor_gutter_background: Some(rgba(0xfdf6e3ff).into()),
-                        editor_subheader_background: Some(rgba(0xf3eddaff).into()),
-                        editor_active_line_background: Some(rgba(0xf3eddabf).into()),
-                        editor_highlighted_line_background: Some(rgba(0xf3eddaff).into()),
-                        editor_line_number: Some(rgba(0x002b3659).into()),
-                        editor_active_line_number: Some(rgba(0x002b36ff).into()),
-                        editor_invisible: Some(rgba(0x34555eff).into()),
-                        editor_wrap_guide: Some(rgba(0x002b360d).into()),
-                        editor_active_wrap_guide: Some(rgba(0x002b361a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x298bd11a).into()),
+                        scrollbar_track_border: Some(rgba(0x032f3bff).into()),
+                        editor_foreground: Some(rgba(0xfdf6e3ff).into()),
+                        editor_background: Some(rgba(0x002b36ff).into()),
+                        editor_gutter_background: Some(rgba(0x002b36ff).into()),
+                        editor_subheader_background: Some(rgba(0x04313cff).into()),
+                        editor_active_line_background: Some(rgba(0x04313cbf).into()),
+                        editor_highlighted_line_background: Some(rgba(0x04313cff).into()),
+                        editor_line_number: Some(rgba(0xfdf6e359).into()),
+                        editor_active_line_number: Some(rgba(0xfdf6e3ff).into()),
+                        editor_invisible: Some(rgba(0x93a1a1ff).into()),
+                        editor_wrap_guide: Some(rgba(0xfdf6e30d).into()),
+                        editor_active_wrap_guide: Some(rgba(0xfdf6e31a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x288bd11a).into()),
                         editor_document_highlight_write_background: Some(rgba(0x6d828866).into()),
-                        terminal_background: Some(rgba(0xfdf6e3ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x7b8e91ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0xfaa091ff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0xc6cb8bff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0xe1c28aff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0xa5c3e9ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0xf0a2bfff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x9fd0cbff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0x002b36ff).into()),
-                        terminal_ansi_black: Some(rgba(0xfdf6e3ff).into()),
+                        terminal_background: Some(rgba(0x002b36ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x5c7279ff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0x7d181cff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0x434a11ff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0x5d4310ff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0x214465ff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0x6f1f40ff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x204e4aff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0xfdf6e3ff).into()),
+                        terminal_ansi_black: Some(rgba(0x002b36ff).into()),
                         terminal_ansi_red: Some(rgba(0xdc3330ff).into()),
                         terminal_ansi_green: Some(rgba(0x859904ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xb58904ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x298bd1ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0xd33882ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xb58903ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x288bd1ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xd33782ff).into()),
                         terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()),
-                        terminal_ansi_white: Some(rgba(0x002b36ff).into()),
-                        link_text_hover: Some(rgba(0x298bd1ff).into()),
+                        terminal_ansi_white: Some(rgba(0xfdf6e3ff).into()),
+                        link_text_hover: Some(rgba(0x288bd1ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xb58904ff).into()),
-                        conflict_background: Some(rgba(0xf5e6d0ff).into()),
-                        conflict_border: Some(rgba(0xebd3aaff).into()),
+                        conflict: Some(rgba(0xb58903ff).into()),
+                        conflict_background: Some(rgba(0x2f1e0cff).into()),
+                        conflict_border: Some(rgba(0x473110ff).into()),
                         created: Some(rgba(0x859904ff).into()),
-                        created_background: Some(rgba(0xe9ead0ff).into()),
-                        created_border: Some(rgba(0xd6d9abff).into()),
+                        created_background: Some(rgba(0x1f210cff).into()),
+                        created_border: Some(rgba(0x323610ff).into()),
                         deleted: Some(rgba(0xdc3330ff).into()),
-                        deleted_background: Some(rgba(0xffd9d2ff).into()),
-                        deleted_border: Some(rgba(0xffbbafff).into()),
+                        deleted_background: Some(rgba(0x4a090fff).into()),
+                        deleted_border: Some(rgba(0x641116ff).into()),
                         error: Some(rgba(0xdc3330ff).into()),
-                        error_background: Some(rgba(0xffd9d2ff).into()),
-                        error_border: Some(rgba(0xffbbafff).into()),
-                        hidden: Some(rgba(0x6a7f86ff).into()),
-                        hidden_background: Some(rgba(0xcfd0c4ff).into()),
-                        hidden_border: Some(rgba(0xb7bdb6ff).into()),
-                        hint: Some(rgba(0x5889a3ff).into()),
-                        hint_background: Some(rgba(0xdbe6f6ff).into()),
-                        hint_border: Some(rgba(0xbfd3efff).into()),
-                        ignored: Some(rgba(0x34555eff).into()),
-                        ignored_background: Some(rgba(0xcfd0c4ff).into()),
-                        ignored_border: Some(rgba(0x9faaa8ff).into()),
-                        info: Some(rgba(0x298bd1ff).into()),
-                        info_background: Some(rgba(0xdbe6f6ff).into()),
-                        info_border: Some(rgba(0xbfd3efff).into()),
-                        modified: Some(rgba(0xb58904ff).into()),
-                        modified_background: Some(rgba(0xf5e6d0ff).into()),
-                        modified_border: Some(rgba(0xebd3aaff).into()),
-                        predictive: Some(rgba(0x679aafff).into()),
-                        predictive_background: Some(rgba(0xe9ead0ff).into()),
-                        predictive_border: Some(rgba(0xd6d9abff).into()),
-                        renamed: Some(rgba(0x298bd1ff).into()),
-                        renamed_background: Some(rgba(0xdbe6f6ff).into()),
-                        renamed_border: Some(rgba(0xbfd3efff).into()),
+                        error_background: Some(rgba(0x4a090fff).into()),
+                        error_border: Some(rgba(0x641116ff).into()),
+                        hidden: Some(rgba(0x6f8389ff).into()),
+                        hidden_background: Some(rgba(0x083743ff).into()),
+                        hidden_border: Some(rgba(0x19424dff).into()),
+                        hint: Some(rgba(0x4f8297ff).into()),
+                        hint_background: Some(rgba(0x141f2cff).into()),
+                        hint_border: Some(rgba(0x1c3249ff).into()),
+                        ignored: Some(rgba(0x93a1a1ff).into()),
+                        ignored_background: Some(rgba(0x083743ff).into()),
+                        ignored_border: Some(rgba(0x2b4f58ff).into()),
+                        info: Some(rgba(0x288bd1ff).into()),
+                        info_background: Some(rgba(0x141f2cff).into()),
+                        info_border: Some(rgba(0x1c3249ff).into()),
+                        modified: Some(rgba(0xb58903ff).into()),
+                        modified_background: Some(rgba(0x2f1e0cff).into()),
+                        modified_border: Some(rgba(0x473110ff).into()),
+                        predictive: Some(rgba(0x40728bff).into()),
+                        predictive_background: Some(rgba(0x1f210cff).into()),
+                        predictive_border: Some(rgba(0x323610ff).into()),
+                        renamed: Some(rgba(0x288bd1ff).into()),
+                        renamed_background: Some(rgba(0x141f2cff).into()),
+                        renamed_border: Some(rgba(0x1c3249ff).into()),
                         success: Some(rgba(0x859904ff).into()),
-                        success_background: Some(rgba(0xe9ead0ff).into()),
-                        success_border: Some(rgba(0xd6d9abff).into()),
-                        unreachable: Some(rgba(0x34555eff).into()),
-                        unreachable_background: Some(rgba(0xcfd0c4ff).into()),
-                        unreachable_border: Some(rgba(0x9faaa8ff).into()),
-                        warning: Some(rgba(0xb58904ff).into()),
-                        warning_background: Some(rgba(0xf5e6d0ff).into()),
-                        warning_border: Some(rgba(0xebd3aaff).into()),
+                        success_background: Some(rgba(0x1f210cff).into()),
+                        success_border: Some(rgba(0x323610ff).into()),
+                        unreachable: Some(rgba(0x93a1a1ff).into()),
+                        unreachable_background: Some(rgba(0x083743ff).into()),
+                        unreachable_border: Some(rgba(0x2b4f58ff).into()),
+                        warning: Some(rgba(0xb58903ff).into()),
+                        warning_background: Some(rgba(0x2f1e0cff).into()),
+                        warning_border: Some(rgba(0x473110ff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x298bd1ff).into(),
-                            background: rgba(0x298bd1ff).into(),
-                            selection: rgba(0x298bd13d).into(),
+                            cursor: rgba(0x288bd1ff).into(),
+                            background: rgba(0x288bd1ff).into(),
+                            selection: rgba(0x288bd13d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xd33882ff).into(),
-                            background: rgba(0xd33882ff).into(),
-                            selection: rgba(0xd338823d).into(),
+                            cursor: rgba(0xd33782ff).into(),
+                            background: rgba(0xd33782ff).into(),
+                            selection: rgba(0xd337823d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xcb4c18ff).into(),
-                            background: rgba(0xcb4c18ff).into(),
-                            selection: rgba(0xcb4c183d).into(),
+                            cursor: rgba(0xcb4b17ff).into(),
+                            background: rgba(0xcb4b17ff).into(),
+                            selection: rgba(0xcb4b173d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x6d71c4ff).into(),
-                            background: rgba(0x6d71c4ff).into(),
-                            selection: rgba(0x6d71c43d).into(),
+                            cursor: rgba(0x6c71c4ff).into(),
+                            background: rgba(0x6c71c4ff).into(),
+                            selection: rgba(0x6c71c43d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0x2ca198ff).into(),
@@ -172,9 +172,9 @@ pub fn solarized() -> UserThemeFamily {
                             selection: rgba(0xdc33303d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb58904ff).into(),
-                            background: rgba(0xb58904ff).into(),
-                            selection: rgba(0xb589043d).into(),
+                            cursor: rgba(0xb58903ff).into(),
+                            background: rgba(0xb58903ff).into(),
+                            selection: rgba(0xb589033d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0x859904ff).into(),
@@ -187,7 +187,7 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -201,14 +201,14 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x30525bff).into()),
+                                    color: Some(rgba(0x99a5a4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x30525bff).into()),
+                                    color: Some(rgba(0x99a5a4ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -222,28 +222,28 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x002b36ff).into()),
+                                    color: Some(rgba(0xfdf6e3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -251,21 +251,21 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xb58904ff).into()),
+                                    color: Some(rgba(0xb58903ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x5889a3ff).into()),
+                                    color: Some(rgba(0x4f8297ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -273,21 +273,21 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -309,14 +309,14 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x679aafff).into()),
+                                    color: Some(rgba(0x40728bff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -324,112 +324,112 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x002b36ff).into()),
+                                    color: Some(rgba(0xfdf6e3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x002b36ff).into()),
+                                    color: Some(rgba(0xfdf6e3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x05333eff).into()),
+                                    color: Some(rgba(0xefe9d6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x05333eff).into()),
+                                    color: Some(rgba(0xefe9d6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x05333eff).into()),
+                                    color: Some(rgba(0xefe9d6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x05333eff).into()),
+                                    color: Some(rgba(0xefe9d6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x05333eff).into()),
+                                    color: Some(rgba(0xefe9d6ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x30525bff).into()),
+                                    color: Some(rgba(0x99a5a4ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4c18ff).into()),
+                                    color: Some(rgba(0xcb4b17ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x002b36ff).into()),
+                                    color: Some(rgba(0xfdf6e3ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -444,14 +444,14 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "variable".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x002b36ff).into()),
+                                    color: Some(rgba(0xfdf6e3ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "variant".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x298bd1ff).into()),
+                                    color: Some(rgba(0x288bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -460,150 +460,150 @@ pub fn solarized() -> UserThemeFamily {
                 },
             },
             UserTheme {
-                name: "Solarized Dark".into(),
-                appearance: Appearance::Dark,
+                name: "Solarized Light".into(),
+                appearance: Appearance::Light,
                 styles: UserThemeStylesRefinement {
                     colors: ThemeColorsRefinement {
-                        border: Some(rgba(0x2b4f58ff).into()),
-                        border_variant: Some(rgba(0x063541ff).into()),
-                        border_focused: Some(rgba(0x1c3249ff).into()),
-                        border_selected: Some(rgba(0x1c3249ff).into()),
+                        border: Some(rgba(0x9faaa8ff).into()),
+                        border_variant: Some(rgba(0xdcdacbff).into()),
+                        border_focused: Some(rgba(0xbfd3efff).into()),
+                        border_selected: Some(rgba(0xbfd3efff).into()),
                         border_transparent: Some(rgba(0x00000000).into()),
-                        border_disabled: Some(rgba(0x19424dff).into()),
-                        elevated_surface_background: Some(rgba(0x04313cff).into()),
-                        surface_background: Some(rgba(0x04313cff).into()),
-                        background: Some(rgba(0x083743ff).into()),
-                        panel_background: Some(rgba(0x04313cff).into()),
-                        element_background: Some(rgba(0x04313cff).into()),
-                        element_hover: Some(rgba(0x063541ff).into()),
-                        element_active: Some(rgba(0x294e58ff).into()),
-                        element_selected: Some(rgba(0x294e58ff).into()),
-                        element_disabled: Some(rgba(0x04313cff).into()),
-                        drop_target_background: Some(rgba(0x93a1a180).into()),
-                        ghost_element_background: Some(rgba(0x00000000).into()),
-                        ghost_element_hover: Some(rgba(0x063541ff).into()),
-                        ghost_element_active: Some(rgba(0x294e58ff).into()),
-                        ghost_element_selected: Some(rgba(0x294e58ff).into()),
-                        ghost_element_disabled: Some(rgba(0x04313cff).into()),
-                        text: Some(rgba(0xfdf6e3ff).into()),
-                        text_muted: Some(rgba(0x93a1a1ff).into()),
-                        text_placeholder: Some(rgba(0x6f8389ff).into()),
-                        text_disabled: Some(rgba(0x6f8389ff).into()),
-                        text_accent: Some(rgba(0x288bd1ff).into()),
-                        icon: Some(rgba(0xfdf6e3ff).into()),
-                        icon_muted: Some(rgba(0x93a1a1ff).into()),
-                        icon_disabled: Some(rgba(0x6f8389ff).into()),
-                        icon_placeholder: Some(rgba(0x93a1a1ff).into()),
-                        icon_accent: Some(rgba(0x288bd1ff).into()),
-                        status_bar_background: Some(rgba(0x083743ff).into()),
-                        title_bar_background: Some(rgba(0x083743ff).into()),
-                        toolbar_background: Some(rgba(0x002b36ff).into()),
-                        tab_bar_background: Some(rgba(0x04313cff).into()),
-                        tab_inactive_background: Some(rgba(0x04313cff).into()),
-                        tab_active_background: Some(rgba(0x002b36ff).into()),
-                        scrollbar_thumb_background: Some(rgba(0xfdf6e34c).into()),
-                        scrollbar_thumb_hover_background: Some(rgba(0x063541ff).into()),
-                        scrollbar_thumb_border: Some(rgba(0x063541ff).into()),
+                        border_disabled: Some(rgba(0xb7bdb6ff).into()),
+                        elevated_surface_background: Some(rgba(0xf3eddaff).into()),
+                        surface_background: Some(rgba(0xf3eddaff).into()),
+                        background: Some(rgba(0xcfd0c4ff).into()),
+                        panel_background: Some(rgba(0xf3eddaff).into()),
+                        element_background: Some(rgba(0xf3eddaff).into()),
+                        element_hover: Some(rgba(0xdcdacbff).into()),
+                        element_active: Some(rgba(0xa2aca9ff).into()),
+                        element_selected: Some(rgba(0xa2aca9ff).into()),
+                        element_disabled: Some(rgba(0xf3eddaff).into()),
+                        drop_target_background: Some(rgba(0x34555e80).into()),
+                        ghost_element_background: Some(rgba(0x00000000).into()),
+                        ghost_element_hover: Some(rgba(0xdcdacbff).into()),
+                        ghost_element_active: Some(rgba(0xa2aca9ff).into()),
+                        ghost_element_selected: Some(rgba(0xa2aca9ff).into()),
+                        ghost_element_disabled: Some(rgba(0xf3eddaff).into()),
+                        text: Some(rgba(0x002b36ff).into()),
+                        text_muted: Some(rgba(0x34555eff).into()),
+                        text_placeholder: Some(rgba(0x6a7f86ff).into()),
+                        text_disabled: Some(rgba(0x6a7f86ff).into()),
+                        text_accent: Some(rgba(0x298bd1ff).into()),
+                        icon: Some(rgba(0x002b36ff).into()),
+                        icon_muted: Some(rgba(0x34555eff).into()),
+                        icon_disabled: Some(rgba(0x6a7f86ff).into()),
+                        icon_placeholder: Some(rgba(0x34555eff).into()),
+                        icon_accent: Some(rgba(0x298bd1ff).into()),
+                        status_bar_background: Some(rgba(0xcfd0c4ff).into()),
+                        title_bar_background: Some(rgba(0xcfd0c4ff).into()),
+                        toolbar_background: Some(rgba(0xfdf6e3ff).into()),
+                        tab_bar_background: Some(rgba(0xf3eddaff).into()),
+                        tab_inactive_background: Some(rgba(0xf3eddaff).into()),
+                        tab_active_background: Some(rgba(0xfdf6e3ff).into()),
+                        scrollbar_thumb_background: Some(rgba(0x002b364c).into()),
+                        scrollbar_thumb_hover_background: Some(rgba(0xdcdacbff).into()),
+                        scrollbar_thumb_border: Some(rgba(0xdcdacbff).into()),
                         scrollbar_track_background: Some(rgba(0x00000000).into()),
-                        scrollbar_track_border: Some(rgba(0x032f3bff).into()),
-                        editor_foreground: Some(rgba(0xfdf6e3ff).into()),
-                        editor_background: Some(rgba(0x002b36ff).into()),
-                        editor_gutter_background: Some(rgba(0x002b36ff).into()),
-                        editor_subheader_background: Some(rgba(0x04313cff).into()),
-                        editor_active_line_background: Some(rgba(0x04313cbf).into()),
-                        editor_highlighted_line_background: Some(rgba(0x04313cff).into()),
-                        editor_line_number: Some(rgba(0xfdf6e359).into()),
-                        editor_active_line_number: Some(rgba(0xfdf6e3ff).into()),
-                        editor_invisible: Some(rgba(0x93a1a1ff).into()),
-                        editor_wrap_guide: Some(rgba(0xfdf6e30d).into()),
-                        editor_active_wrap_guide: Some(rgba(0xfdf6e31a).into()),
-                        editor_document_highlight_read_background: Some(rgba(0x288bd11a).into()),
+                        scrollbar_track_border: Some(rgba(0xf5eedbff).into()),
+                        editor_foreground: Some(rgba(0x002b36ff).into()),
+                        editor_background: Some(rgba(0xfdf6e3ff).into()),
+                        editor_gutter_background: Some(rgba(0xfdf6e3ff).into()),
+                        editor_subheader_background: Some(rgba(0xf3eddaff).into()),
+                        editor_active_line_background: Some(rgba(0xf3eddabf).into()),
+                        editor_highlighted_line_background: Some(rgba(0xf3eddaff).into()),
+                        editor_line_number: Some(rgba(0x002b3659).into()),
+                        editor_active_line_number: Some(rgba(0x002b36ff).into()),
+                        editor_invisible: Some(rgba(0x34555eff).into()),
+                        editor_wrap_guide: Some(rgba(0x002b360d).into()),
+                        editor_active_wrap_guide: Some(rgba(0x002b361a).into()),
+                        editor_document_highlight_read_background: Some(rgba(0x298bd11a).into()),
                         editor_document_highlight_write_background: Some(rgba(0x6d828866).into()),
-                        terminal_background: Some(rgba(0x002b36ff).into()),
-                        terminal_ansi_bright_black: Some(rgba(0x5c7279ff).into()),
-                        terminal_ansi_bright_red: Some(rgba(0x7d181cff).into()),
-                        terminal_ansi_bright_green: Some(rgba(0x434a11ff).into()),
-                        terminal_ansi_bright_yellow: Some(rgba(0x5d4310ff).into()),
-                        terminal_ansi_bright_blue: Some(rgba(0x214465ff).into()),
-                        terminal_ansi_bright_magenta: Some(rgba(0x6f1f40ff).into()),
-                        terminal_ansi_bright_cyan: Some(rgba(0x204e4aff).into()),
-                        terminal_ansi_bright_white: Some(rgba(0xfdf6e3ff).into()),
-                        terminal_ansi_black: Some(rgba(0x002b36ff).into()),
+                        terminal_background: Some(rgba(0xfdf6e3ff).into()),
+                        terminal_ansi_bright_black: Some(rgba(0x7b8e91ff).into()),
+                        terminal_ansi_bright_red: Some(rgba(0xfaa091ff).into()),
+                        terminal_ansi_bright_green: Some(rgba(0xc6cb8bff).into()),
+                        terminal_ansi_bright_yellow: Some(rgba(0xe1c28aff).into()),
+                        terminal_ansi_bright_blue: Some(rgba(0xa5c3e9ff).into()),
+                        terminal_ansi_bright_magenta: Some(rgba(0xf0a2bfff).into()),
+                        terminal_ansi_bright_cyan: Some(rgba(0x9fd0cbff).into()),
+                        terminal_ansi_bright_white: Some(rgba(0x002b36ff).into()),
+                        terminal_ansi_black: Some(rgba(0xfdf6e3ff).into()),
                         terminal_ansi_red: Some(rgba(0xdc3330ff).into()),
                         terminal_ansi_green: Some(rgba(0x859904ff).into()),
-                        terminal_ansi_yellow: Some(rgba(0xb58903ff).into()),
-                        terminal_ansi_blue: Some(rgba(0x288bd1ff).into()),
-                        terminal_ansi_magenta: Some(rgba(0xd33782ff).into()),
+                        terminal_ansi_yellow: Some(rgba(0xb58904ff).into()),
+                        terminal_ansi_blue: Some(rgba(0x298bd1ff).into()),
+                        terminal_ansi_magenta: Some(rgba(0xd33882ff).into()),
                         terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()),
-                        terminal_ansi_white: Some(rgba(0xfdf6e3ff).into()),
-                        link_text_hover: Some(rgba(0x288bd1ff).into()),
+                        terminal_ansi_white: Some(rgba(0x002b36ff).into()),
+                        link_text_hover: Some(rgba(0x298bd1ff).into()),
                         ..Default::default()
                     },
                     status: StatusColorsRefinement {
-                        conflict: Some(rgba(0xb58903ff).into()),
-                        conflict_background: Some(rgba(0x2f1e0cff).into()),
-                        conflict_border: Some(rgba(0x473110ff).into()),
+                        conflict: Some(rgba(0xb58904ff).into()),
+                        conflict_background: Some(rgba(0xf5e6d0ff).into()),
+                        conflict_border: Some(rgba(0xebd3aaff).into()),
                         created: Some(rgba(0x859904ff).into()),
-                        created_background: Some(rgba(0x1f210cff).into()),
-                        created_border: Some(rgba(0x323610ff).into()),
+                        created_background: Some(rgba(0xe9ead0ff).into()),
+                        created_border: Some(rgba(0xd6d9abff).into()),
                         deleted: Some(rgba(0xdc3330ff).into()),
-                        deleted_background: Some(rgba(0x4a090fff).into()),
-                        deleted_border: Some(rgba(0x641116ff).into()),
+                        deleted_background: Some(rgba(0xffd9d2ff).into()),
+                        deleted_border: Some(rgba(0xffbbafff).into()),
                         error: Some(rgba(0xdc3330ff).into()),
-                        error_background: Some(rgba(0x4a090fff).into()),
-                        error_border: Some(rgba(0x641116ff).into()),
-                        hidden: Some(rgba(0x6f8389ff).into()),
-                        hidden_background: Some(rgba(0x083743ff).into()),
-                        hidden_border: Some(rgba(0x19424dff).into()),
-                        hint: Some(rgba(0x4f8297ff).into()),
-                        hint_background: Some(rgba(0x141f2cff).into()),
-                        hint_border: Some(rgba(0x1c3249ff).into()),
-                        ignored: Some(rgba(0x93a1a1ff).into()),
-                        ignored_background: Some(rgba(0x083743ff).into()),
-                        ignored_border: Some(rgba(0x2b4f58ff).into()),
-                        info: Some(rgba(0x288bd1ff).into()),
-                        info_background: Some(rgba(0x141f2cff).into()),
-                        info_border: Some(rgba(0x1c3249ff).into()),
-                        modified: Some(rgba(0xb58903ff).into()),
-                        modified_background: Some(rgba(0x2f1e0cff).into()),
-                        modified_border: Some(rgba(0x473110ff).into()),
-                        predictive: Some(rgba(0x40728bff).into()),
-                        predictive_background: Some(rgba(0x1f210cff).into()),
-                        predictive_border: Some(rgba(0x323610ff).into()),
-                        renamed: Some(rgba(0x288bd1ff).into()),
-                        renamed_background: Some(rgba(0x141f2cff).into()),
-                        renamed_border: Some(rgba(0x1c3249ff).into()),
+                        error_background: Some(rgba(0xffd9d2ff).into()),
+                        error_border: Some(rgba(0xffbbafff).into()),
+                        hidden: Some(rgba(0x6a7f86ff).into()),
+                        hidden_background: Some(rgba(0xcfd0c4ff).into()),
+                        hidden_border: Some(rgba(0xb7bdb6ff).into()),
+                        hint: Some(rgba(0x5889a3ff).into()),
+                        hint_background: Some(rgba(0xdbe6f6ff).into()),
+                        hint_border: Some(rgba(0xbfd3efff).into()),
+                        ignored: Some(rgba(0x34555eff).into()),
+                        ignored_background: Some(rgba(0xcfd0c4ff).into()),
+                        ignored_border: Some(rgba(0x9faaa8ff).into()),
+                        info: Some(rgba(0x298bd1ff).into()),
+                        info_background: Some(rgba(0xdbe6f6ff).into()),
+                        info_border: Some(rgba(0xbfd3efff).into()),
+                        modified: Some(rgba(0xb58904ff).into()),
+                        modified_background: Some(rgba(0xf5e6d0ff).into()),
+                        modified_border: Some(rgba(0xebd3aaff).into()),
+                        predictive: Some(rgba(0x679aafff).into()),
+                        predictive_background: Some(rgba(0xe9ead0ff).into()),
+                        predictive_border: Some(rgba(0xd6d9abff).into()),
+                        renamed: Some(rgba(0x298bd1ff).into()),
+                        renamed_background: Some(rgba(0xdbe6f6ff).into()),
+                        renamed_border: Some(rgba(0xbfd3efff).into()),
                         success: Some(rgba(0x859904ff).into()),
-                        success_background: Some(rgba(0x1f210cff).into()),
-                        success_border: Some(rgba(0x323610ff).into()),
-                        unreachable: Some(rgba(0x93a1a1ff).into()),
-                        unreachable_background: Some(rgba(0x083743ff).into()),
-                        unreachable_border: Some(rgba(0x2b4f58ff).into()),
-                        warning: Some(rgba(0xb58903ff).into()),
-                        warning_background: Some(rgba(0x2f1e0cff).into()),
-                        warning_border: Some(rgba(0x473110ff).into()),
+                        success_background: Some(rgba(0xe9ead0ff).into()),
+                        success_border: Some(rgba(0xd6d9abff).into()),
+                        unreachable: Some(rgba(0x34555eff).into()),
+                        unreachable_background: Some(rgba(0xcfd0c4ff).into()),
+                        unreachable_border: Some(rgba(0x9faaa8ff).into()),
+                        warning: Some(rgba(0xb58904ff).into()),
+                        warning_background: Some(rgba(0xf5e6d0ff).into()),
+                        warning_border: Some(rgba(0xebd3aaff).into()),
                         ..Default::default()
                     },
                     player: Some(PlayerColors(vec![
                         PlayerColor {
-                            cursor: rgba(0x288bd1ff).into(),
-                            background: rgba(0x288bd1ff).into(),
-                            selection: rgba(0x288bd13d).into(),
+                            cursor: rgba(0x298bd1ff).into(),
+                            background: rgba(0x298bd1ff).into(),
+                            selection: rgba(0x298bd13d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xd33782ff).into(),
-                            background: rgba(0xd33782ff).into(),
-                            selection: rgba(0xd337823d).into(),
+                            cursor: rgba(0xd33882ff).into(),
+                            background: rgba(0xd33882ff).into(),
+                            selection: rgba(0xd338823d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xcb4b17ff).into(),
-                            background: rgba(0xcb4b17ff).into(),
-                            selection: rgba(0xcb4b173d).into(),
+                            cursor: rgba(0xcb4c18ff).into(),
+                            background: rgba(0xcb4c18ff).into(),
+                            selection: rgba(0xcb4c183d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0x6c71c4ff).into(),
-                            background: rgba(0x6c71c4ff).into(),
-                            selection: rgba(0x6c71c43d).into(),
+                            cursor: rgba(0x6d71c4ff).into(),
+                            background: rgba(0x6d71c4ff).into(),
+                            selection: rgba(0x6d71c43d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0x2ca198ff).into(),
@@ -616,9 +616,9 @@ pub fn solarized() -> UserThemeFamily {
                             selection: rgba(0xdc33303d).into(),
                         },
                         PlayerColor {
-                            cursor: rgba(0xb58903ff).into(),
-                            background: rgba(0xb58903ff).into(),
-                            selection: rgba(0xb589033d).into(),
+                            cursor: rgba(0xb58904ff).into(),
+                            background: rgba(0xb58904ff).into(),
+                            selection: rgba(0xb589043d).into(),
                         },
                         PlayerColor {
                             cursor: rgba(0x859904ff).into(),
@@ -631,7 +631,7 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "attribute".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -645,14 +645,14 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "comment".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x99a5a4ff).into()),
+                                    color: Some(rgba(0x30525bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "comment.doc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x99a5a4ff).into()),
+                                    color: Some(rgba(0x30525bff).into()),
                                     ..Default::default()
                                 },
                             ),
@@ -666,28 +666,28 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "constructor".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "embedded".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xfdf6e3ff).into()),
+                                    color: Some(rgba(0x002b36ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "emphasis.strong".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -695,21 +695,21 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "enum".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "function".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xb58903ff).into()),
+                                    color: Some(rgba(0xb58904ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "hint".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x4f8297ff).into()),
+                                    color: Some(rgba(0x5889a3ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },
@@ -717,21 +717,21 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "keyword".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "label".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "link_text".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -753,14 +753,14 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "operator".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "predictive".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x40728bff).into()),
+                                    color: Some(rgba(0x679aafff).into()),
                                     font_style: Some(UserFontStyle::Italic),
                                     ..Default::default()
                                 },
@@ -768,112 +768,112 @@ pub fn solarized() -> UserThemeFamily {
                             (
                                 "preproc".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xfdf6e3ff).into()),
+                                    color: Some(rgba(0x002b36ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "primary".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xfdf6e3ff).into()),
+                                    color: Some(rgba(0x002b36ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "property".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xefe9d6ff).into()),
+                                    color: Some(rgba(0x05333eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.bracket".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xefe9d6ff).into()),
+                                    color: Some(rgba(0x05333eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.delimiter".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xefe9d6ff).into()),
+                                    color: Some(rgba(0x05333eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.list_marker".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xefe9d6ff).into()),
+                                    color: Some(rgba(0x05333eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "punctuation.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xefe9d6ff).into()),
+                                    color: Some(rgba(0x05333eff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.escape".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x99a5a4ff).into()),
+                                    color: Some(rgba(0x30525bff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.regex".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "string.special.symbol".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "tag".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0x288bd1ff).into()),
+                                    color: Some(rgba(0x298bd1ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "text.literal".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xcb4b17ff).into()),
+                                    color: Some(rgba(0xcb4c18ff).into()),
                                     ..Default::default()
                                 },
                             ),
                             (
                                 "title".into(),
                                 UserHighlightStyle {
-                                    color: Some(rgba(0xfdf6e3ff).into()),
+                                    color: Some(rgba(0x002b36ff).into()),
                                     font_weight: Some(UserFontWeight(700.0)),
                                     ..Default::default()
                                 },

crates/theme_importer/Cargo.toml πŸ”—

@@ -11,6 +11,7 @@ clap = { version = "4.4", features = ["derive"] }
 convert_case = "0.6.0"
 gpui = { path = "../gpui" }
 indexmap = { version = "1.6.2", features = ["serde"] }
+indoc.workspace = true
 json_comments = "0.2.2"
 log.workspace = true
 palette = { version = "0.7.3", default-features = false, features = ["std"] }

crates/theme_importer/src/main.rs πŸ”—

@@ -18,6 +18,7 @@ use clap::Parser;
 use convert_case::{Case, Casing};
 use gpui::serde_json;
 use indexmap::IndexMap;
+use indoc::formatdoc;
 use json_comments::StripComments;
 use log::LevelFilter;
 use serde::Deserialize;
@@ -28,7 +29,7 @@ use crate::theme_printer::UserThemeFamilyPrinter;
 use crate::vscode::VsCodeTheme;
 use crate::vscode::VsCodeThemeConverter;
 use crate::zed1::theme::Theme as Zed1Theme;
-use crate::zed1::Zed1ThemeConverter;
+use crate::zed1::{zed1_theme_licenses, Zed1ThemeConverter};
 
 #[derive(Debug, Deserialize)]
 struct FamilyMetadata {
@@ -200,7 +201,13 @@ fn main() -> Result<()> {
         "Summercamp",
     ];
 
-    let mut zed1_themes_by_family: HashMap<String, Vec<UserTheme>> = HashMap::from_iter(
+    let zed1_licenses_by_theme: HashMap<String, zed1::Zed1ThemeLicense> = HashMap::from_iter(
+        zed1_theme_licenses()
+            .into_iter()
+            .map(|theme_license| (theme_license.theme.clone(), theme_license)),
+    );
+
+    let mut zed1_themes_by_family: IndexMap<String, Vec<UserTheme>> = IndexMap::from_iter(
         zed1_theme_familes
             .into_iter()
             .map(|family| (family.to_string(), Vec::new())),
@@ -254,13 +261,44 @@ fn main() -> Result<()> {
         themes_for_family.push(theme);
     }
 
+    zed1_themes_by_family.sort_keys();
+
+    let mut licenses = Vec::new();
+
     for (family, themes) in zed1_themes_by_family {
-        let theme_family = UserThemeFamily {
+        let mut theme_family = UserThemeFamily {
             name: family,
             author: "Zed Industries".to_string(),
             themes,
         };
 
+        theme_family
+            .themes
+            .sort_unstable_by_key(|theme| theme.name.clone());
+
+        for theme in &theme_family.themes {
+            let license = zed1_licenses_by_theme
+                .get(&theme.name)
+                .ok_or_else(|| anyhow!("missing license for theme: '{}'", theme.name))?;
+
+            let license_header = match license.license_url.as_ref() {
+                Some(license_url) => {
+                    format!("[{theme_name}]({license_url})", theme_name = theme.name)
+                }
+                None => theme.name.clone(),
+            };
+
+            licenses.push(formatdoc!(
+                "
+                ## {license_header}
+
+                {license_text}
+                ********************************************************************************
+                ",
+                license_text = license.license_text
+            ));
+        }
+
         theme_families.push(theme_family);
     }
 
@@ -357,6 +395,12 @@ fn main() -> Result<()> {
 
     mod_rs_file.write_all(mod_rs_contents.as_bytes())?;
 
+    log::info!("Writing LICENSES file...");
+
+    let mut licenses_file = File::create(themes_output_path.join(format!("LICENSES")))?;
+
+    licenses_file.write_all(licenses.join("\n").as_bytes())?;
+
     log::info!("Formatting themes...");
 
     let format_result = format_themes_crate()

crates/theme_importer/src/zed1/licenses.rs πŸ”—

@@ -0,0 +1,1192 @@
+use std::fmt::Display;
+
+use indoc::indoc;
+
+#[derive(Debug)]
+pub enum License {
+    Mit,
+    // We don't currently have any themes using the Apache 2.0 license.
+    #[allow(unused)]
+    Apache2,
+}
+
+impl Display for License {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                License::Mit => "MIT",
+                License::Apache2 => "Apache License 2.0",
+            }
+        )
+    }
+}
+
+pub struct Zed1ThemeLicense {
+    pub theme: String,
+    pub license: License,
+    pub license_url: Option<String>,
+    pub license_text: &'static str,
+}
+
+pub fn zed1_theme_licenses() -> Vec<Zed1ThemeLicense> {
+    vec![
+        Zed1ThemeLicense {
+            theme: "One Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://github.com/atom/atom/tree/master/packages/one-dark-ui".to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2014 GitHub Inc.
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "One Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://github.com/atom/atom/tree/master/packages/one-light-ui".to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2014 GitHub Inc.
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Ayu Light".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/dempfi/ayu".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2016 Ike Ku
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Ayu Dark".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/dempfi/ayu".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2016 Ike Ku
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Ayu Mirage".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/dempfi/ayu".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2016 Ike Ku
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Dark".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Dark Hard".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Dark Soft".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Light".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Light Hard".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Gruvbox Light Soft".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/morhetz/gruvbox".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) <YEAR> <COPYRIGHT HOLDER>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "RosΓ© Pine".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/edunfelt/base16-rose-pine-scheme".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2021 Emilia Dunfelt
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "RosΓ© Pine Dawn".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/edunfelt/base16-rose-pine-scheme".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2021 Emilia Dunfelt
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "RosΓ© Pine Moon".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/edunfelt/base16-rose-pine-scheme".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2021 Emilia Dunfelt
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Sandcastle".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/gessig/base16-sandcastle-scheme".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2019 George Essig
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Solarized Dark".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/altercation/solarized".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2011 Ethan Schoonover
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Solarized Light".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/altercation/solarized".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2011 Ethan Schoonover
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Andromeda".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/EliverLara/Andromeda".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2017 <eliverlara@gmail.com>
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Summercamp".to_string(),
+            license: License::Mit,
+            license_url: Some("https://github.com/zoefiri/base16-sc".to_string()),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2019 Zoe FiriH
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Cave Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Cave Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Dune Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Dune Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Estuary Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Estuary Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Forest Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Forest Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Heath Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Heath Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Lakeside Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Lakeside Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Plateau Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Plateau Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Savanna Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Savanna Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Seaside Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Seaside Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Sulphurpool Dark".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+        Zed1ThemeLicense {
+            theme: "Atelier Sulphurpool Light".to_string(),
+            license: License::Mit,
+            license_url: Some(
+                "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/"
+                    .to_string(),
+            ),
+            license_text: indoc! {r#"
+                The MIT License (MIT)
+
+                Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
+
+                Permission is hereby granted, free of charge, to any person obtaining a copy
+                of this software and associated documentation files (the "Software"), to deal
+                in the Software without restriction, including without limitation the rights
+                to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+                copies of the Software, and to permit persons to whom the Software is
+                furnished to do so, subject to the following conditions:
+
+                The above copyright notice and this permission notice shall be included in all
+                copies or substantial portions of the Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+                IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+                AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+                LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+                SOFTWARE.
+            "#},
+        },
+    ]
+}

crates/ui/src/components/button/button.rs πŸ”—

@@ -92,6 +92,13 @@ impl Selectable for Button {
     }
 }
 
+impl SelectableButton for Button {
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.base = self.base.selected_style(style);
+        self
+    }
+}
+
 impl Disableable for Button {
     fn disabled(mut self, disabled: bool) -> Self {
         self.base = self.base.disabled(disabled);

crates/ui/src/components/button/button_icon.rs πŸ”—

@@ -12,6 +12,7 @@ pub(super) struct ButtonIcon {
     disabled: bool,
     selected: bool,
     selected_icon: Option<Icon>,
+    selected_style: Option<ButtonStyle>,
 }
 
 impl ButtonIcon {
@@ -23,6 +24,7 @@ impl ButtonIcon {
             disabled: false,
             selected: false,
             selected_icon: None,
+            selected_style: None,
         }
     }
 
@@ -62,6 +64,13 @@ impl Selectable for ButtonIcon {
     }
 }
 
+impl SelectableButton for ButtonIcon {
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.selected_style = Some(style);
+        self
+    }
+}
+
 impl RenderOnce for ButtonIcon {
     fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
         let icon = self
@@ -71,6 +80,8 @@ impl RenderOnce for ButtonIcon {
 
         let icon_color = if self.disabled {
             Color::Disabled
+        } else if self.selected_style.is_some() && self.selected {
+            self.selected_style.unwrap().into()
         } else if self.selected {
             Color::Selected
         } else {

crates/ui/src/components/button/button_like.rs πŸ”—

@@ -4,6 +4,10 @@ use smallvec::SmallVec;
 
 use crate::prelude::*;
 
+pub trait SelectableButton: Selectable {
+    fn selected_style(self, style: ButtonStyle) -> Self;
+}
+
 pub trait ButtonCommon: Clickable + Disableable {
     /// A unique element ID to identify the button.
     fn id(&self) -> &ElementId;
@@ -36,17 +40,68 @@ pub enum IconPosition {
     End,
 }
 
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
+pub enum TintColor {
+    #[default]
+    Accent,
+    Negative,
+    Warning,
+}
+
+impl TintColor {
+    fn button_like_style(self, cx: &mut WindowContext) -> ButtonLikeStyles {
+        match self {
+            TintColor::Accent => ButtonLikeStyles {
+                background: cx.theme().status().info_background,
+                border_color: cx.theme().status().info_border,
+                label_color: cx.theme().colors().text,
+                icon_color: cx.theme().colors().text,
+            },
+            TintColor::Negative => ButtonLikeStyles {
+                background: cx.theme().status().error_background,
+                border_color: cx.theme().status().error_border,
+                label_color: cx.theme().colors().text,
+                icon_color: cx.theme().colors().text,
+            },
+            TintColor::Warning => ButtonLikeStyles {
+                background: cx.theme().status().warning_background,
+                border_color: cx.theme().status().warning_border,
+                label_color: cx.theme().colors().text,
+                icon_color: cx.theme().colors().text,
+            },
+        }
+    }
+}
+
+impl From<TintColor> for Color {
+    fn from(tint: TintColor) -> Self {
+        match tint {
+            TintColor::Accent => Color::Accent,
+            TintColor::Negative => Color::Error,
+            TintColor::Warning => Color::Warning,
+        }
+    }
+}
+
+// Used to go from ButtonStyle -> Color through tint colors.
+impl From<ButtonStyle> for Color {
+    fn from(style: ButtonStyle) -> Self {
+        match style {
+            ButtonStyle::Tinted(tint) => tint.into(),
+            _ => Color::Default,
+        }
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
 pub enum ButtonStyle {
     /// A filled button with a solid background color. Provides emphasis versus
     /// the more common subtle button.
     Filled,
 
-    /// 🚧 Under construction 🚧
-    ///
     /// Used to emphasize a button in some way, like a selected state, or a semantic
     /// coloring like an error or success button.
-    Tinted,
+    Tinted(TintColor),
 
     /// The default button style, used for most buttons. Has a transparent background,
     /// but has a background color to indicate states like hover and active.
@@ -86,12 +141,7 @@ impl ButtonStyle {
                 label_color: Color::Default.color(cx),
                 icon_color: Color::Default.color(cx),
             },
-            ButtonStyle::Tinted => ButtonLikeStyles {
-                background: gpui::red(),
-                border_color: gpui::red(),
-                label_color: gpui::red(),
-                icon_color: gpui::red(),
-            },
+            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_background,
                 border_color: transparent_black(),
@@ -115,12 +165,7 @@ impl ButtonStyle {
                 label_color: Color::Default.color(cx),
                 icon_color: Color::Default.color(cx),
             },
-            ButtonStyle::Tinted => ButtonLikeStyles {
-                background: gpui::red(),
-                border_color: gpui::red(),
-                label_color: gpui::red(),
-                icon_color: gpui::red(),
-            },
+            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_hover,
                 border_color: transparent_black(),
@@ -146,12 +191,7 @@ impl ButtonStyle {
                 label_color: Color::Default.color(cx),
                 icon_color: Color::Default.color(cx),
             },
-            ButtonStyle::Tinted => ButtonLikeStyles {
-                background: gpui::red(),
-                border_color: gpui::red(),
-                label_color: gpui::red(),
-                icon_color: gpui::red(),
-            },
+            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_active,
                 border_color: transparent_black(),
@@ -178,12 +218,7 @@ impl ButtonStyle {
                 label_color: Color::Default.color(cx),
                 icon_color: Color::Default.color(cx),
             },
-            ButtonStyle::Tinted => ButtonLikeStyles {
-                background: gpui::red(),
-                border_color: gpui::red(),
-                label_color: gpui::red(),
-                icon_color: gpui::red(),
-            },
+            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_background,
                 border_color: cx.theme().colors().border_focused,
@@ -208,12 +243,7 @@ impl ButtonStyle {
                 label_color: Color::Disabled.color(cx),
                 icon_color: Color::Disabled.color(cx),
             },
-            ButtonStyle::Tinted => ButtonLikeStyles {
-                background: gpui::red(),
-                border_color: gpui::red(),
-                label_color: gpui::red(),
-                icon_color: gpui::red(),
-            },
+            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_disabled,
                 border_color: cx.theme().colors().border_disabled,
@@ -264,6 +294,7 @@ pub struct ButtonLike {
     pub(super) style: ButtonStyle,
     pub(super) disabled: bool,
     pub(super) selected: bool,
+    pub(super) selected_style: Option<ButtonStyle>,
     pub(super) width: Option<DefiniteLength>,
     size: ButtonSize,
     rounding: Option<ButtonLikeRounding>,
@@ -280,6 +311,7 @@ impl ButtonLike {
             style: ButtonStyle::default(),
             disabled: false,
             selected: false,
+            selected_style: None,
             width: None,
             size: ButtonSize::Default,
             rounding: Some(ButtonLikeRounding::All),
@@ -309,6 +341,13 @@ impl Selectable for ButtonLike {
     }
 }
 
+impl SelectableButton for ButtonLike {
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.selected_style = Some(style);
+        self
+    }
+}
+
 impl Clickable for ButtonLike {
     fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
         self.on_click = Some(Box::new(handler));
@@ -364,6 +403,11 @@ impl ParentElement for ButtonLike {
 
 impl RenderOnce for ButtonLike {
     fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+        let style = self
+            .selected_style
+            .filter(|_| self.selected)
+            .unwrap_or(self.style);
+
         self.base
             .h_flex()
             .id(self.id.clone())
@@ -382,12 +426,12 @@ impl RenderOnce for ButtonLike {
                 ButtonSize::Default | ButtonSize::Compact => this.px_1(),
                 ButtonSize::None => this,
             })
-            .bg(self.style.enabled(cx).background)
+            .bg(style.enabled(cx).background)
             .when(self.disabled, |this| this.cursor_not_allowed())
             .when(!self.disabled, |this| {
                 this.cursor_pointer()
-                    .hover(|hover| hover.bg(self.style.hovered(cx).background))
-                    .active(|active| active.bg(self.style.active(cx).background))
+                    .hover(|hover| hover.bg(style.hovered(cx).background))
+                    .active(|active| active.bg(style.active(cx).background))
             })
             .when_some(
                 self.on_click.filter(|_| !self.disabled),

crates/ui/src/components/button/icon_button.rs πŸ”—

@@ -1,6 +1,6 @@
 use gpui::{AnyView, DefiniteLength};
 
-use crate::prelude::*;
+use crate::{prelude::*, SelectableButton};
 use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
 
 use super::button_icon::ButtonIcon;
@@ -55,6 +55,13 @@ impl Selectable for IconButton {
     }
 }
 
+impl SelectableButton for IconButton {
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.base = self.base.selected_style(style);
+        self
+    }
+}
+
 impl Clickable for IconButton {
     fn on_click(
         mut self,
@@ -109,12 +116,14 @@ impl RenderOnce for IconButton {
     fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
         let is_disabled = self.base.disabled;
         let is_selected = self.base.selected;
+        let selected_style = self.base.selected_style;
 
         self.base.child(
             ButtonIcon::new(self.icon)
                 .disabled(is_disabled)
                 .selected(is_selected)
                 .selected_icon(self.selected_icon)
+                .when_some(selected_style, |this, style| this.selected_style(style))
                 .size(self.icon_size)
                 .color(self.icon_color),
         )

crates/ui/src/components/button/toggle_button.rs πŸ”—

@@ -63,6 +63,13 @@ impl Selectable for ToggleButton {
     }
 }
 
+impl SelectableButton for ToggleButton {
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.base.selected_style = Some(style);
+        self
+    }
+}
+
 impl Disableable for ToggleButton {
     fn disabled(mut self, disabled: bool) -> Self {
         self.base = self.base.disabled(disabled);

crates/ui/src/components/checkbox.rs πŸ”—

@@ -1,4 +1,4 @@
-use gpui::{div, prelude::*, Element, ElementId, IntoElement, Styled, WindowContext};
+use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext};
 
 use crate::prelude::*;
 use crate::{Color, Icon, IconElement, Selection};
@@ -18,126 +18,6 @@ pub struct Checkbox {
     on_click: Option<CheckHandler>,
 }
 
-impl RenderOnce for Checkbox {
-    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
-        let group_id = format!("checkbox_group_{:?}", self.id);
-
-        let icon = match self.checked {
-            // When selected, we show a checkmark.
-            Selection::Selected => {
-                Some(
-                    IconElement::new(Icon::Check)
-                        .size(crate::IconSize::Small)
-                        .color(
-                            // If the checkbox is disabled we change the color of the icon.
-                            if self.disabled {
-                                Color::Disabled
-                            } else {
-                                Color::Selected
-                            },
-                        ),
-                )
-            }
-            // In an indeterminate state, we show a dash.
-            Selection::Indeterminate => {
-                Some(
-                    IconElement::new(Icon::Dash)
-                        .size(crate::IconSize::Small)
-                        .color(
-                            // If the checkbox is disabled we change the color of the icon.
-                            if self.disabled {
-                                Color::Disabled
-                            } else {
-                                Color::Selected
-                            },
-                        ),
-                )
-            }
-            // When unselected, we show nothing.
-            Selection::Unselected => None,
-        };
-
-        // A checkbox could be in an indeterminate state,
-        // for example the indeterminate state could represent:
-        //  - a group of options of which only some are selected
-        //  - an enabled option that is no longer available
-        //  - a previously agreed to license that has been updated
-        //
-        // For the sake of styles we treat the indeterminate state as selected,
-        // but it's icon will be different.
-        let selected =
-            self.checked == Selection::Selected || self.checked == Selection::Indeterminate;
-
-        // We could use something like this to make the checkbox background when selected:
-        //
-        // ~~~rust
-        // ...
-        // .when(selected, |this| {
-        //     this.bg(cx.theme().colors().element_selected)
-        // })
-        // ~~~
-        //
-        // But we use a match instead here because the checkbox might be disabled,
-        // and it could be disabled _while_ it is selected, as well as while it is not selected.
-        let (bg_color, border_color) = match (self.disabled, selected) {
-            (true, _) => (
-                cx.theme().colors().ghost_element_disabled,
-                cx.theme().colors().border_disabled,
-            ),
-            (false, true) => (
-                cx.theme().colors().element_selected,
-                cx.theme().colors().border,
-            ),
-            (false, false) => (
-                cx.theme().colors().element_background,
-                cx.theme().colors().border,
-            ),
-        };
-
-        div()
-            .id(self.id)
-            // Rather than adding `px_1()` to add some space around the checkbox,
-            // we use a larger parent element to create a slightly larger
-            // click area for the checkbox.
-            .size_5()
-            // Because we've enlarged the click area, we need to create a
-            // `group` to pass down interactivity events to the checkbox.
-            .group(group_id.clone())
-            .child(
-                div()
-                    .flex()
-                    // This prevent the flex element from growing
-                    // or shrinking in response to any size changes
-                    .flex_none()
-                    // The combo of `justify_center()` and `items_center()`
-                    // is used frequently to center elements in a flex container.
-                    //
-                    // We use this to center the icon in the checkbox.
-                    .justify_center()
-                    .items_center()
-                    .m_1()
-                    .size_4()
-                    .rounded_sm()
-                    .bg(bg_color)
-                    .border()
-                    .border_color(border_color)
-                    // We only want the interactivity states to fire when we
-                    // are in a checkbox that isn't disabled.
-                    .when(!self.disabled, |this| {
-                        // Here instead of `hover()` we use `group_hover()`
-                        // to pass it the group id.
-                        this.group_hover(group_id.clone(), |el| {
-                            el.bg(cx.theme().colors().element_hover)
-                        })
-                    })
-                    .children(icon),
-            )
-            .when_some(
-                self.on_click.filter(|_| !self.disabled),
-                |this, on_click| this.on_click(move |_, cx| on_click(&self.checked.inverse(), cx)),
-            )
-    }
-}
 impl Checkbox {
     pub fn new(id: impl Into<ElementId>, checked: Selection) -> Self {
         Self {
@@ -160,42 +40,29 @@ impl Checkbox {
         self.on_click = Some(Box::new(handler));
         self
     }
+}
 
-    pub fn render(self, cx: &mut WindowContext) -> impl Element {
+impl RenderOnce for Checkbox {
+    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
         let group_id = format!("checkbox_group_{:?}", self.id);
 
         let icon = match self.checked {
-            // When selected, we show a checkmark.
-            Selection::Selected => {
-                Some(
-                    IconElement::new(Icon::Check)
-                        .size(crate::IconSize::Small)
-                        .color(
-                            // If the checkbox is disabled we change the color of the icon.
-                            if self.disabled {
-                                Color::Disabled
-                            } else {
-                                Color::Selected
-                            },
-                        ),
-                )
-            }
-            // In an indeterminate state, we show a dash.
-            Selection::Indeterminate => {
-                Some(
-                    IconElement::new(Icon::Dash)
-                        .size(crate::IconSize::Small)
-                        .color(
-                            // If the checkbox is disabled we change the color of the icon.
-                            if self.disabled {
-                                Color::Disabled
-                            } else {
-                                Color::Selected
-                            },
-                        ),
-                )
-            }
-            // When unselected, we show nothing.
+            Selection::Selected => Some(IconElement::new(Icon::Check).size(IconSize::Small).color(
+                if self.disabled {
+                    Color::Disabled
+                } else {
+                    Color::Selected
+                },
+            )),
+            Selection::Indeterminate => Some(
+                IconElement::new(Icon::Dash)
+                    .size(IconSize::Small)
+                    .color(if self.disabled {
+                        Color::Disabled
+                    } else {
+                        Color::Selected
+                    }),
+            ),
             Selection::Unselected => None,
         };
 
@@ -212,12 +79,12 @@ impl Checkbox {
 
         // We could use something like this to make the checkbox background when selected:
         //
-        // ~~~rust
+        // ```rs
         // ...
         // .when(selected, |this| {
         //     this.bg(cx.theme().colors().element_selected)
         // })
-        // ~~~
+        // ```
         //
         // But we use a match instead here because the checkbox might be disabled,
         // and it could be disabled _while_ it is selected, as well as while it is not selected.
@@ -236,7 +103,7 @@ impl Checkbox {
             ),
         };
 
-        div()
+        h_stack()
             .id(self.id)
             // Rather than adding `px_1()` to add some space around the checkbox,
             // we use a larger parent element to create a slightly larger

crates/ui/src/prelude.rs πŸ”—

@@ -12,7 +12,7 @@ pub use crate::selectable::*;
 pub use crate::styles::{vh, vw};
 pub use crate::visible_on_hover::*;
 pub use crate::{h_stack, v_stack};
-pub use crate::{Button, ButtonSize, ButtonStyle, IconButton};
+pub use crate::{Button, ButtonSize, ButtonStyle, IconButton, SelectableButton};
 pub use crate::{ButtonCommon, Color, StyledExt};
 pub use crate::{Icon, IconElement, IconPosition, IconSize};
 pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle};

crates/welcome/src/welcome.rs πŸ”—

@@ -59,153 +59,159 @@ pub struct WelcomePage {
 
 impl Render for WelcomePage {
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
-        h_stack().full().track_focus(&self.focus_handle).child(
-            v_stack()
-                .w_96()
-                .gap_4()
-                .mx_auto()
-                .child(
-                    svg()
-                        .path("icons/logo_96.svg")
-                        .text_color(gpui::white())
-                        .w(px(96.))
-                        .h(px(96.))
-                        .mx_auto(),
-                )
-                .child(
-                    h_stack()
-                        .justify_center()
-                        .child(Label::new("Code at the speed of thought")),
-                )
-                .child(
-                    v_stack()
-                        .gap_2()
-                        .child(
-                            Button::new("choose-theme", "Choose a theme")
-                                .full_width()
-                                .on_click(cx.listener(|this, _, cx| {
-                                    this.workspace
-                                        .update(cx, |workspace, cx| {
-                                            theme_selector::toggle(
-                                                workspace,
-                                                &Default::default(),
-                                                cx,
-                                            )
-                                        })
-                                        .ok();
-                                })),
-                        )
-                        .child(
-                            Button::new("choose-keymap", "Choose a keymap")
-                                .full_width()
-                                .on_click(cx.listener(|this, _, cx| {
-                                    this.workspace
-                                        .update(cx, |workspace, cx| {
-                                            base_keymap_picker::toggle(
-                                                workspace,
-                                                &Default::default(),
-                                                cx,
-                                            )
-                                        })
-                                        .ok();
-                                })),
-                        )
-                        .child(
-                            Button::new("install-cli", "Install the CLI")
-                                .full_width()
-                                .on_click(cx.listener(|_, _, cx| {
-                                    cx.app_mut()
-                                        .spawn(
-                                            |cx| async move { install_cli::install_cli(&cx).await },
+        h_stack()
+            .full()
+            .bg(cx.theme().colors().editor_background)
+            .track_focus(&self.focus_handle)
+            .child(
+                v_stack()
+                    .w_96()
+                    .gap_4()
+                    .mx_auto()
+                    .child(
+                        svg()
+                            .path("icons/logo_96.svg")
+                            .text_color(gpui::white())
+                            .w(px(96.))
+                            .h(px(96.))
+                            .mx_auto(),
+                    )
+                    .child(
+                        h_stack()
+                            .justify_center()
+                            .child(Label::new("Code at the speed of thought")),
+                    )
+                    .child(
+                        v_stack()
+                            .gap_2()
+                            .child(
+                                Button::new("choose-theme", "Choose a theme")
+                                    .full_width()
+                                    .on_click(cx.listener(|this, _, cx| {
+                                        this.workspace
+                                            .update(cx, |workspace, cx| {
+                                                theme_selector::toggle(
+                                                    workspace,
+                                                    &Default::default(),
+                                                    cx,
+                                                )
+                                            })
+                                            .ok();
+                                    })),
+                            )
+                            .child(
+                                Button::new("choose-keymap", "Choose a keymap")
+                                    .full_width()
+                                    .on_click(cx.listener(|this, _, cx| {
+                                        this.workspace
+                                            .update(cx, |workspace, cx| {
+                                                base_keymap_picker::toggle(
+                                                    workspace,
+                                                    &Default::default(),
+                                                    cx,
+                                                )
+                                            })
+                                            .ok();
+                                    })),
+                            )
+                            .child(
+                                Button::new("install-cli", "Install the CLI")
+                                    .full_width()
+                                    .on_click(cx.listener(|_, _, cx| {
+                                        cx.app_mut()
+                                            .spawn(|cx| async move {
+                                                install_cli::install_cli(&cx).await
+                                            })
+                                            .detach_and_log_err(cx);
+                                    })),
+                            ),
+                    )
+                    .child(
+                        v_stack()
+                            .p_3()
+                            .gap_2()
+                            .bg(cx.theme().colors().elevated_surface_background)
+                            .border_1()
+                            .border_color(cx.theme().colors().border)
+                            .rounded_md()
+                            .child(
+                                h_stack()
+                                    .gap_2()
+                                    .child(
+                                        Checkbox::new(
+                                            "enable-vim",
+                                            if VimModeSetting::get_global(cx).0 {
+                                                ui::Selection::Selected
+                                            } else {
+                                                ui::Selection::Unselected
+                                            },
                                         )
-                                        .detach_and_log_err(cx);
-                                })),
-                        ),
-                )
-                .child(
-                    v_stack()
-                        .p_3()
-                        .gap_2()
-                        .bg(cx.theme().colors().elevated_surface_background)
-                        .border_1()
-                        .border_color(cx.theme().colors().border)
-                        .rounded_md()
-                        .child(
-                            h_stack()
-                                .gap_2()
-                                .child(
-                                    Checkbox::new(
-                                        "enable-vim",
-                                        if VimModeSetting::get_global(cx).0 {
-                                            ui::Selection::Selected
-                                        } else {
-                                            ui::Selection::Unselected
-                                        },
+                                        .on_click(
+                                            cx.listener(move |this, selection, cx| {
+                                                this.update_settings::<VimModeSetting>(
+                                                    selection,
+                                                    cx,
+                                                    |setting, value| *setting = Some(value),
+                                                );
+                                            }),
+                                        ),
                                     )
-                                    .on_click(cx.listener(
-                                        move |this, selection, cx| {
-                                            this.update_settings::<VimModeSetting>(
-                                                selection,
-                                                cx,
-                                                |setting, value| *setting = Some(value),
-                                            );
-                                        },
-                                    )),
-                                )
-                                .child(Label::new("Enable vim mode")),
-                        )
-                        .child(
-                            h_stack()
-                                .gap_2()
-                                .child(
-                                    Checkbox::new(
-                                        "enable-telemetry",
-                                        if TelemetrySettings::get_global(cx).metrics {
-                                            ui::Selection::Selected
-                                        } else {
-                                            ui::Selection::Unselected
-                                        },
+                                    .child(Label::new("Enable vim mode")),
+                            )
+                            .child(
+                                h_stack()
+                                    .gap_2()
+                                    .child(
+                                        Checkbox::new(
+                                            "enable-telemetry",
+                                            if TelemetrySettings::get_global(cx).metrics {
+                                                ui::Selection::Selected
+                                            } else {
+                                                ui::Selection::Unselected
+                                            },
+                                        )
+                                        .on_click(
+                                            cx.listener(move |this, selection, cx| {
+                                                this.update_settings::<TelemetrySettings>(
+                                                    selection,
+                                                    cx,
+                                                    |settings, value| {
+                                                        settings.metrics = Some(value)
+                                                    },
+                                                );
+                                            }),
+                                        ),
                                     )
-                                    .on_click(cx.listener(
-                                        move |this, selection, cx| {
-                                            this.update_settings::<TelemetrySettings>(
-                                                selection,
-                                                cx,
-                                                |settings, value| settings.metrics = Some(value),
-                                            );
-                                        },
-                                    )),
-                                )
-                                .child(Label::new("Send anonymous usage data")),
-                        )
-                        .child(
-                            h_stack()
-                                .gap_2()
-                                .child(
-                                    Checkbox::new(
-                                        "enable-crash",
-                                        if TelemetrySettings::get_global(cx).diagnostics {
-                                            ui::Selection::Selected
-                                        } else {
-                                            ui::Selection::Unselected
-                                        },
+                                    .child(Label::new("Send anonymous usage data")),
+                            )
+                            .child(
+                                h_stack()
+                                    .gap_2()
+                                    .child(
+                                        Checkbox::new(
+                                            "enable-crash",
+                                            if TelemetrySettings::get_global(cx).diagnostics {
+                                                ui::Selection::Selected
+                                            } else {
+                                                ui::Selection::Unselected
+                                            },
+                                        )
+                                        .on_click(
+                                            cx.listener(move |this, selection, cx| {
+                                                this.update_settings::<TelemetrySettings>(
+                                                    selection,
+                                                    cx,
+                                                    |settings, value| {
+                                                        settings.diagnostics = Some(value)
+                                                    },
+                                                );
+                                            }),
+                                        ),
                                     )
-                                    .on_click(cx.listener(
-                                        move |this, selection, cx| {
-                                            this.update_settings::<TelemetrySettings>(
-                                                selection,
-                                                cx,
-                                                |settings, value| {
-                                                    settings.diagnostics = Some(value)
-                                                },
-                                            );
-                                        },
-                                    )),
-                                )
-                                .child(Label::new("Send crash reports")),
-                        ),
-                ),
-        )
+                                    .child(Label::new("Send crash reports")),
+                            ),
+                    ),
+            )
     }
 }
 

crates/workspace/Cargo.toml πŸ”—

@@ -32,6 +32,7 @@ language = { path = "../language" }
 node_runtime = { path = "../node_runtime" }
 project = { path = "../project" }
 settings = { path = "../settings" }
+sqlez = { path = "../sqlez" }
 terminal = { path = "../terminal" }
 theme = { path = "../theme" }
 util = { path = "../util" }

crates/workspace/src/dock.rs πŸ”—

@@ -651,9 +651,13 @@ impl Render for PanelButtons {
                                         && panel.position_is_valid(position, cx)
                                     {
                                         let panel = panel.clone();
-                                        menu = menu.entry(position.to_label(), None, move |cx| {
-                                            panel.set_position(position, cx);
-                                        })
+                                        menu = menu.entry(
+                                            format!("Dock {}", position.to_label()),
+                                            None,
+                                            move |cx| {
+                                                panel.set_position(position, cx);
+                                            },
+                                        )
                                     }
                                 }
                                 menu

crates/workspace/src/pane_group.rs πŸ”—

@@ -246,7 +246,15 @@ impl Member {
                     .size_full()
                     .child(pane.clone())
                     .when_some(leader_border, |this, color| {
-                        this.border_2().border_color(color)
+                        this.child(
+                            div()
+                                .absolute()
+                                .size_full()
+                                .left_0()
+                                .top_0()
+                                .border_2()
+                                .border_color(color),
+                        )
                     })
                     .when_some(leader_status_box, |this, status_box| {
                         this.child(

crates/workspace/src/persistence.rs πŸ”—

@@ -6,7 +6,12 @@ use std::path::Path;
 
 use anyhow::{anyhow, bail, Context, Result};
 use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
-use gpui::{Axis, WindowBounds};
+use gpui::{point, size, Axis, Bounds, WindowBounds};
+
+use sqlez::{
+    bindable::{Bind, Column, StaticColumnCount},
+    statement::Statement,
+};
 
 use util::{unzip_option, ResultExt};
 use uuid::Uuid;
@@ -20,6 +25,121 @@ use model::{
 
 use self::model::DockStructure;
 
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub(crate) struct SerializedAxis(pub(crate) gpui::Axis);
+impl sqlez::bindable::StaticColumnCount for SerializedAxis {}
+impl sqlez::bindable::Bind for SerializedAxis {
+    fn bind(
+        &self,
+        statement: &sqlez::statement::Statement,
+        start_index: i32,
+    ) -> anyhow::Result<i32> {
+        match self.0 {
+            gpui::Axis::Horizontal => "Horizontal",
+            gpui::Axis::Vertical => "Vertical",
+        }
+        .bind(statement, start_index)
+    }
+}
+
+impl sqlez::bindable::Column for SerializedAxis {
+    fn column(
+        statement: &mut sqlez::statement::Statement,
+        start_index: i32,
+    ) -> anyhow::Result<(Self, i32)> {
+        String::column(statement, start_index).and_then(|(axis_text, next_index)| {
+            Ok((
+                match axis_text.as_str() {
+                    "Horizontal" => Self(Axis::Horizontal),
+                    "Vertical" => Self(Axis::Vertical),
+                    _ => anyhow::bail!("Stored serialized item kind is incorrect"),
+                },
+                next_index,
+            ))
+        })
+    }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub(crate) struct SerializedWindowsBounds(pub(crate) WindowBounds);
+
+impl StaticColumnCount for SerializedWindowsBounds {
+    fn column_count() -> usize {
+        5
+    }
+}
+
+impl Bind for SerializedWindowsBounds {
+    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
+        let (region, next_index) = match self.0 {
+            WindowBounds::Fullscreen => {
+                let next_index = statement.bind(&"Fullscreen", start_index)?;
+                (None, next_index)
+            }
+            WindowBounds::Maximized => {
+                let next_index = statement.bind(&"Maximized", start_index)?;
+                (None, next_index)
+            }
+            WindowBounds::Fixed(region) => {
+                let next_index = statement.bind(&"Fixed", start_index)?;
+                (Some(region), next_index)
+            }
+        };
+
+        statement.bind(
+            &region.map(|region| {
+                (
+                    SerializedGlobalPixels(region.origin.x),
+                    SerializedGlobalPixels(region.origin.y),
+                    SerializedGlobalPixels(region.size.width),
+                    SerializedGlobalPixels(region.size.height),
+                )
+            }),
+            next_index,
+        )
+    }
+}
+
+impl Column for SerializedWindowsBounds {
+    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
+        let (window_state, next_index) = String::column(statement, start_index)?;
+        let bounds = match window_state.as_str() {
+            "Fullscreen" => SerializedWindowsBounds(WindowBounds::Fullscreen),
+            "Maximized" => SerializedWindowsBounds(WindowBounds::Maximized),
+            "Fixed" => {
+                let ((x, y, width, height), _) = Column::column(statement, next_index)?;
+                let x: f64 = x;
+                let y: f64 = y;
+                let width: f64 = width;
+                let height: f64 = height;
+                SerializedWindowsBounds(WindowBounds::Fixed(Bounds {
+                    origin: point(x.into(), y.into()),
+                    size: size(width.into(), height.into()),
+                }))
+            }
+            _ => bail!("Window State did not have a valid string"),
+        };
+
+        Ok((bounds, next_index + 4))
+    }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+struct SerializedGlobalPixels(gpui::GlobalPixels);
+impl sqlez::bindable::StaticColumnCount for SerializedGlobalPixels {}
+
+impl sqlez::bindable::Bind for SerializedGlobalPixels {
+    fn bind(
+        &self,
+        statement: &sqlez::statement::Statement,
+        start_index: i32,
+    ) -> anyhow::Result<i32> {
+        let this: f64 = self.0.into();
+        let this: f32 = this as _;
+        this.bind(statement, start_index)
+    }
+}
+
 define_connection! {
     // Current schema shape using pseudo-rust syntax:
     //
@@ -181,7 +301,7 @@ impl WorkspaceDb {
     /// Returns a serialized workspace for the given worktree_roots. If the passed array
     /// is empty, the most recent workspace is returned instead. If no workspace for the
     /// passed roots is stored, returns none.
-    pub fn workspace_for_roots<P: AsRef<Path>>(
+    pub(crate) fn workspace_for_roots<P: AsRef<Path>>(
         &self,
         worktree_roots: &[P],
     ) -> Option<SerializedWorkspace> {
@@ -192,7 +312,7 @@ impl WorkspaceDb {
         let (workspace_id, workspace_location, bounds, display, docks): (
             WorkspaceId,
             WorkspaceLocation,
-            Option<WindowBounds>,
+            Option<SerializedWindowsBounds>,
             Option<Uuid>,
             DockStructure,
         ) = self
@@ -230,7 +350,7 @@ impl WorkspaceDb {
                 .get_center_pane_group(workspace_id)
                 .context("Getting center group")
                 .log_err()?,
-            bounds,
+            bounds: bounds.map(|bounds| bounds.0),
             display,
             docks,
         })
@@ -238,7 +358,7 @@ impl WorkspaceDb {
 
     /// Saves a workspace using the worktree roots. Will garbage collect any workspaces
     /// that used this workspace previously
-    pub async fn save_workspace(&self, workspace: SerializedWorkspace) {
+    pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
         self.write(move |conn| {
             conn.with_savepoint("update_worktrees", || {
                 // Clear out panes and pane_groups
@@ -367,7 +487,7 @@ impl WorkspaceDb {
         type GroupKey = (Option<GroupId>, WorkspaceId);
         type GroupOrPane = (
             Option<GroupId>,
-            Option<Axis>,
+            Option<SerializedAxis>,
             Option<PaneId>,
             Option<bool>,
             Option<String>,
@@ -536,7 +656,7 @@ impl WorkspaceDb {
     }
 
     query! {
-        pub async fn set_window_bounds(workspace_id: WorkspaceId, bounds: WindowBounds, display: Uuid) -> Result<()> {
+        pub(crate) async fn set_window_bounds(workspace_id: WorkspaceId, bounds: SerializedWindowsBounds, display: Uuid) -> Result<()> {
             UPDATE workspaces
             SET window_state = ?2,
                 window_x = ?3,
@@ -683,7 +803,7 @@ mod tests {
 
     fn group(axis: Axis, children: Vec<SerializedPaneGroup>) -> SerializedPaneGroup {
         SerializedPaneGroup::Group {
-            axis,
+            axis: SerializedAxis(axis),
             flexes: None,
             children,
         }

crates/workspace/src/persistence/model.rs πŸ”—

@@ -1,3 +1,4 @@
+use super::SerializedAxis;
 use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId};
 use anyhow::{Context, Result};
 use async_recursion::async_recursion;
@@ -5,7 +6,7 @@ use db::sqlez::{
     bindable::{Bind, Column, StaticColumnCount},
     statement::Statement,
 };
-use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView, WindowBounds};
+use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
 use project::Project;
 use std::{
     path::{Path, PathBuf},
@@ -54,13 +55,13 @@ impl Column for WorkspaceLocation {
 }
 
 #[derive(Debug, PartialEq, Clone)]
-pub struct SerializedWorkspace {
-    pub id: WorkspaceId,
-    pub location: WorkspaceLocation,
-    pub center_group: SerializedPaneGroup,
-    pub bounds: Option<WindowBounds>,
-    pub display: Option<Uuid>,
-    pub docks: DockStructure,
+pub(crate) struct SerializedWorkspace {
+    pub(crate) id: WorkspaceId,
+    pub(crate) location: WorkspaceLocation,
+    pub(crate) center_group: SerializedPaneGroup,
+    pub(crate) bounds: Option<WindowBounds>,
+    pub(crate) display: Option<Uuid>,
+    pub(crate) docks: DockStructure,
 }
 
 #[derive(Debug, PartialEq, Clone, Default)]
@@ -126,9 +127,9 @@ impl Bind for DockData {
 }
 
 #[derive(Debug, PartialEq, Clone)]
-pub enum SerializedPaneGroup {
+pub(crate) enum SerializedPaneGroup {
     Group {
-        axis: Axis,
+        axis: SerializedAxis,
         flexes: Option<Vec<f32>>,
         children: Vec<SerializedPaneGroup>,
     },
@@ -183,7 +184,7 @@ impl SerializedPaneGroup {
                 }
 
                 Some((
-                    Member::Axis(PaneAxis::load(axis, members, flexes)),
+                    Member::Axis(PaneAxis::load(axis.0, members, flexes)),
                     current_active_pane,
                     items,
                 ))

crates/workspace/src/workspace.rs πŸ”—

@@ -42,9 +42,9 @@ use node_runtime::NodeRuntime;
 use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
 pub use pane::*;
 pub use pane_group::*;
-use persistence::DB;
+use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB};
 pub use persistence::{
-    model::{ItemId, SerializedWorkspace, WorkspaceLocation},
+    model::{ItemId, WorkspaceLocation},
     WorkspaceDb, DB as WORKSPACE_DB,
 };
 use postage::stream::Stream;
@@ -70,8 +70,9 @@ use util::ResultExt;
 use uuid::Uuid;
 pub use workspace_settings::{AutosaveSetting, WorkspaceSettings};
 
-use crate::persistence::model::{
-    DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
+use crate::persistence::{
+    model::{DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup},
+    SerializedAxis,
 };
 
 lazy_static! {
@@ -107,6 +108,7 @@ actions!(
         NewCenterTerminal,
         ToggleTerminalFocus,
         NewSearch,
+        DeploySearch,
         Feedback,
         Restart,
         Welcome,
@@ -624,7 +626,11 @@ impl Workspace {
 
                     if let Some(display_uuid) = display.uuid().log_err() {
                         cx.background_executor()
-                            .spawn(DB.set_window_bounds(workspace_id, bounds, display_uuid))
+                            .spawn(DB.set_window_bounds(
+                                workspace_id,
+                                SerializedWindowsBounds(bounds),
+                                display_uuid,
+                            ))
                             .detach_and_log_err(cx);
                     }
                 }
@@ -1186,7 +1192,7 @@ impl Workspace {
         mut save_intent: SaveIntent,
         cx: &mut ViewContext<Self>,
     ) -> Task<Result<bool>> {
-        if self.project.read(cx).is_read_only() {
+        if self.project.read(cx).is_disconnected() {
             return Task::ready(Ok(true));
         }
         let dirty_items = self
@@ -2509,7 +2515,7 @@ impl Workspace {
     }
 
     fn update_window_edited(&mut self, cx: &mut ViewContext<Self>) {
-        let is_edited = !self.project.read(cx).is_read_only()
+        let is_edited = !self.project.read(cx).is_disconnected()
             && self
                 .items(cx)
                 .any(|item| item.has_conflict(cx) || item.is_dirty(cx));
@@ -2988,7 +2994,7 @@ impl Workspace {
                     flexes,
                     bounding_boxes: _,
                 }) => SerializedPaneGroup::Group {
-                    axis: *axis,
+                    axis: SerializedAxis(*axis),
                     children: members
                         .iter()
                         .map(|member| build_serialized_pane_group(member, cx))
@@ -3265,6 +3271,7 @@ impl Workspace {
         let user_store = project.read(cx).user_store();
 
         let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
+        cx.activate_window();
         let app_state = Arc::new(AppState {
             languages: project.read(cx).languages().clone(),
             workspace_store,
@@ -3633,7 +3640,7 @@ impl Render for Workspace {
                     })),
             )
             .child(self.status_bar.clone())
-            .children(if self.project.read(cx).is_read_only() {
+            .children(if self.project.read(cx).is_disconnected() {
                 Some(DisconnectedOverlay)
             } else {
                 None
@@ -4763,8 +4770,7 @@ mod tests {
         });
 
         // Deactivating the window saves the file.
-        cx.simulate_deactivation();
-        cx.executor().run_until_parked();
+        cx.deactivate_window();
         item.update(cx, |item, _| assert_eq!(item.save_count, 1));
 
         // Autosave on focus change.
@@ -4784,14 +4790,13 @@ mod tests {
         item.update(cx, |item, _| assert_eq!(item.save_count, 2));
 
         // Deactivating the window still saves the file.
-        cx.simulate_activation();
+        cx.update(|cx| cx.activate_window());
         item.update(cx, |item, cx| {
             cx.focus_self();
             item.is_dirty = true;
         });
-        cx.simulate_deactivation();
+        cx.deactivate_window();
 
-        cx.executor().run_until_parked();
         item.update(cx, |item, _| assert_eq!(item.save_count, 3));
 
         // Autosave after delay.

docs/old/theme/generating-theme-types.md πŸ”—

@@ -1,29 +0,0 @@
-[β¬… Back to Index](../index.md)
-
-# Generating Theme Types
-
-
-## How to generate theme types:
-
-Run a script
-
-```bash
-./script/build-theme-types
-```
-
-Types are generated in `styles/src/types/zed.ts`
-
-
-## How it works:
-
-1. Rust types
-
-    The `crates/theme` contains theme types.
-    Crate `schemars` used to generate a JSON schema from the theme structs.
-    Every struct that represent theme type has a `#[derive(JsonSchema)]` attribute.
-
-    Task lotaked at `crates/xtask/src/main.rs` generates a JSON schema from the theme structs.
-
-2. TypeScript types
-
-    Script `npm run build-types` from `styles` package generates TypeScript types from the JSON schema and saves them to `styles/src/types/zed.ts`.

script/deploy-migration πŸ”—

@@ -4,17 +4,12 @@ set -eu
 source script/lib/deploy-helpers.sh
 
 if [[ $# < 2 ]]; then
-  echo "Usage: $0 <production|staging|preview> <tag-name> (nightly is not yet supported)"
+  echo "Usage: $0 <production|staging|preview|nightly> <tag-name>"
   exit 1
 fi
 environment=$1
 version=$2
 
-if [[ ${environment} == "nightly" ]]; then
-  echo "nightly is not yet supported"
-  exit 1
-fi
-
 export_vars_for_environment ${environment}
 image_id=$(image_id_for_version ${version})
 

script/generate-licenses πŸ”—

@@ -9,10 +9,7 @@ OUTPUT_FILE=$(pwd)/assets/licenses.md
 echo -e "# ###### THEME LICENSES ######\n" >> $OUTPUT_FILE
 
 echo "Generating theme licenses"
-cd styles
-npm --silent ci
-npm run --silent build-licenses >> $OUTPUT_FILE
-cd ..
+cat crates/theme/src/themes/LICENSES >> $OUTPUT_FILE
 
 echo -e "# ###### CODE LICENSES ######\n" >> $OUTPUT_FILE
 

styles/.eslintrc.js πŸ”—

@@ -1,34 +0,0 @@
-module.exports = {
-    env: {
-        node: true,
-    },
-    extends: [
-        "eslint:recommended",
-        "plugin:@typescript-eslint/recommended",
-        "plugin:import/typescript",
-    ],
-    parser: "@typescript-eslint/parser",
-    parserOptions: {
-        ecmaVersion: "latest",
-        sourceType: "module",
-    },
-    plugins: ["@typescript-eslint", "import"],
-    globals: {
-        module: true,
-    },
-    settings: {
-        "import/parsers": {
-            "@typescript-eslint/parser": [".ts"],
-        },
-        "import/resolver": {
-            typescript: true,
-            node: true,
-        },
-        "import/extensions": [".ts"],
-    },
-    rules: {
-        "linebreak-style": ["error", "unix"],
-        "@typescript-eslint/no-explicit-any": "off",
-        semi: ["error", "never"],
-    },
-}

styles/.prettierrc πŸ”—

@@ -1,6 +0,0 @@
-{
-    "semi": false,
-    "printWidth": 80,
-    "htmlWhitespaceSensitivity": "strict",
-    "tabWidth": 4
-}

styles/.zed/settings.json πŸ”—

@@ -1,20 +0,0 @@
-// Folder-specific settings
-//
-// For a full list of overridable settings, and general information on folder-specific settings,
-// see the documentation: https://docs.zed.dev/configuration/configuring-zed#folder-specific-settings
-{
-    "languages": {
-        "TypeScript": {
-            "tab_size": 4
-        },
-        "TSX": {
-            "tab_size": 4
-        },
-        "JavaScript": {
-            "tab_size": 4
-        },
-        "JSON": {
-            "tab_size": 4
-        }
-    }
-}

styles/package-lock.json πŸ”—

@@ -1,4372 +0,0 @@
-{
-    "name": "styles",
-    "version": "1.0.0",
-    "lockfileVersion": 3,
-    "requires": true,
-    "packages": {
-        "": {
-            "name": "styles",
-            "version": "1.0.0",
-            "license": "ISC",
-            "dependencies": {
-                "@tokens-studio/types": "^0.2.3",
-                "@types/chroma-js": "^2.4.0",
-                "@types/node": "^18.14.1",
-                "@typescript-eslint/eslint-plugin": "^5.60.1",
-                "@typescript-eslint/parser": "^5.60.1",
-                "@vitest/coverage-v8": "^0.32.0",
-                "ayu": "^8.0.1",
-                "chroma-js": "^2.4.2",
-                "deepmerge": "^4.3.0",
-                "eslint": "^8.43.0",
-                "eslint-import-resolver-typescript": "^3.5.5",
-                "eslint-plugin-import": "^2.27.5",
-                "json-schema-to-typescript": "^13.0.2",
-                "toml": "^3.0.0",
-                "ts-deepmerge": "^6.0.3",
-                "ts-node": "^10.9.1",
-                "typescript": "^5.1.5",
-                "utility-types": "^3.10.0",
-                "vitest": "^0.32.0",
-                "zustand": "^4.3.8"
-            }
-        },
-        "node_modules/@aashutoshrathi/word-wrap": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-            "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@ampproject/remapping": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
-            "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
-            "dependencies": {
-                "@jridgewell/gen-mapping": "^0.3.0",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@bcherny/json-schema-ref-parser": {
-            "version": "10.0.5-fork",
-            "resolved": "https://registry.npmjs.org/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-10.0.5-fork.tgz",
-            "integrity": "sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==",
-            "dependencies": {
-                "@jsdevtools/ono": "^7.1.3",
-                "@types/json-schema": "^7.0.6",
-                "call-me-maybe": "^1.0.1",
-                "js-yaml": "^4.1.0"
-            },
-            "engines": {
-                "node": ">= 16"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/philsturgeon"
-            }
-        },
-        "node_modules/@bcoe/v8-coverage": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
-            "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
-        },
-        "node_modules/@cspotcode/source-map-support": {
-            "version": "0.8.1",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-            "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-            "dependencies": {
-                "@jridgewell/trace-mapping": "0.3.9"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/@esbuild/darwin-arm64": {
-            "version": "0.17.19",
-            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
-            "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
-            "cpu": [
-                "arm64"
-            ],
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/@eslint-community/eslint-utils": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-            "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
-            "dependencies": {
-                "eslint-visitor-keys": "^3.3.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
-            }
-        },
-        "node_modules/@eslint-community/regexpp": {
-            "version": "4.5.1",
-            "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
-            "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
-            "engines": {
-                "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@eslint/eslintrc": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
-            "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
-            "dependencies": {
-                "ajv": "^6.12.4",
-                "debug": "^4.3.2",
-                "espree": "^9.5.2",
-                "globals": "^13.19.0",
-                "ignore": "^5.2.0",
-                "import-fresh": "^3.2.1",
-                "js-yaml": "^4.1.0",
-                "minimatch": "^3.1.2",
-                "strip-json-comments": "^3.1.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/@eslint/js": {
-            "version": "8.43.0",
-            "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
-            "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@humanwhocodes/config-array": {
-            "version": "0.11.10",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
-            "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
-            "dependencies": {
-                "@humanwhocodes/object-schema": "^1.2.1",
-                "debug": "^4.1.1",
-                "minimatch": "^3.0.5"
-            },
-            "engines": {
-                "node": ">=10.10.0"
-            }
-        },
-        "node_modules/@humanwhocodes/module-importer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-            "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-            "engines": {
-                "node": ">=12.22"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/nzakas"
-            }
-        },
-        "node_modules/@humanwhocodes/object-schema": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
-            "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA=="
-        },
-        "node_modules/@istanbuljs/schema": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
-            "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/@jridgewell/gen-mapping": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
-            "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
-            "dependencies": {
-                "@jridgewell/set-array": "^1.0.1",
-                "@jridgewell/sourcemap-codec": "^1.4.10",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/resolve-uri": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
-            "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/set-array": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
-            "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/sourcemap-codec": {
-            "version": "1.4.14",
-            "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
-            "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
-        },
-        "node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.9",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-            "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-            "dependencies": {
-                "@jridgewell/resolve-uri": "^3.0.3",
-                "@jridgewell/sourcemap-codec": "^1.4.10"
-            }
-        },
-        "node_modules/@jsdevtools/ono": {
-            "version": "7.1.3",
-            "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
-            "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
-        },
-        "node_modules/@nodelib/fs.scandir": {
-            "version": "2.1.5",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-            "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-            "dependencies": {
-                "@nodelib/fs.stat": "2.0.5",
-                "run-parallel": "^1.1.9"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@nodelib/fs.stat": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-            "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@nodelib/fs.walk": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-            "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-            "dependencies": {
-                "@nodelib/fs.scandir": "2.1.5",
-                "fastq": "^1.6.0"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@pkgr/utils": {
-            "version": "2.4.1",
-            "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.1.tgz",
-            "integrity": "sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==",
-            "dependencies": {
-                "cross-spawn": "^7.0.3",
-                "fast-glob": "^3.2.12",
-                "is-glob": "^4.0.3",
-                "open": "^9.1.0",
-                "picocolors": "^1.0.0",
-                "tslib": "^2.5.0"
-            },
-            "engines": {
-                "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/unts"
-            }
-        },
-        "node_modules/@pkgr/utils/node_modules/tslib": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
-            "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
-        },
-        "node_modules/@tokens-studio/types": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.2.3.tgz",
-            "integrity": "sha512-2KN3V0JPf+Zh8aoVMwykJq29Lsi7vYgKGYBQ/zQ+FbDEmrH6T/Vwn8kG7cvbTmW1JAAvgxVxMIivgC9PmFelNA=="
-        },
-        "node_modules/@tsconfig/node10": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
-            "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
-        },
-        "node_modules/@tsconfig/node12": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-            "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
-        },
-        "node_modules/@tsconfig/node14": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-            "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
-        },
-        "node_modules/@tsconfig/node16": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
-            "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
-        },
-        "node_modules/@types/chai": {
-            "version": "4.3.5",
-            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz",
-            "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng=="
-        },
-        "node_modules/@types/chai-subset": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
-            "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
-            "dependencies": {
-                "@types/chai": "*"
-            }
-        },
-        "node_modules/@types/chroma-js": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.0.tgz",
-            "integrity": "sha512-JklMxityrwjBTjGY2anH8JaTx3yjRU3/sEHSblLH1ba5lqcSh1LnImXJZO5peJfXyqKYWjHTGy4s5Wz++hARrw=="
-        },
-        "node_modules/@types/glob": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
-            "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
-            "dependencies": {
-                "@types/minimatch": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/istanbul-lib-coverage": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
-            "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g=="
-        },
-        "node_modules/@types/json-schema": {
-            "version": "7.0.12",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
-            "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA=="
-        },
-        "node_modules/@types/json5": {
-            "version": "0.0.29",
-            "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
-            "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
-        },
-        "node_modules/@types/lodash": {
-            "version": "4.14.195",
-            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz",
-            "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg=="
-        },
-        "node_modules/@types/minimatch": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
-            "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="
-        },
-        "node_modules/@types/node": {
-            "version": "18.14.1",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz",
-            "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ=="
-        },
-        "node_modules/@types/prettier": {
-            "version": "2.7.3",
-            "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
-            "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA=="
-        },
-        "node_modules/@types/semver": {
-            "version": "7.5.0",
-            "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
-            "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw=="
-        },
-        "node_modules/@typescript-eslint/eslint-plugin": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz",
-            "integrity": "sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==",
-            "dependencies": {
-                "@eslint-community/regexpp": "^4.4.0",
-                "@typescript-eslint/scope-manager": "5.60.1",
-                "@typescript-eslint/type-utils": "5.60.1",
-                "@typescript-eslint/utils": "5.60.1",
-                "debug": "^4.3.4",
-                "grapheme-splitter": "^1.0.4",
-                "ignore": "^5.2.0",
-                "natural-compare-lite": "^1.4.0",
-                "semver": "^7.3.7",
-                "tsutils": "^3.21.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "@typescript-eslint/parser": "^5.0.0",
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/parser": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.1.tgz",
-            "integrity": "sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==",
-            "dependencies": {
-                "@typescript-eslint/scope-manager": "5.60.1",
-                "@typescript-eslint/types": "5.60.1",
-                "@typescript-eslint/typescript-estree": "5.60.1",
-                "debug": "^4.3.4"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/scope-manager": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz",
-            "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==",
-            "dependencies": {
-                "@typescript-eslint/types": "5.60.1",
-                "@typescript-eslint/visitor-keys": "5.60.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/type-utils": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz",
-            "integrity": "sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==",
-            "dependencies": {
-                "@typescript-eslint/typescript-estree": "5.60.1",
-                "@typescript-eslint/utils": "5.60.1",
-                "debug": "^4.3.4",
-                "tsutils": "^3.21.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "*"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/types": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz",
-            "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==",
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/typescript-estree": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz",
-            "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==",
-            "dependencies": {
-                "@typescript-eslint/types": "5.60.1",
-                "@typescript-eslint/visitor-keys": "5.60.1",
-                "debug": "^4.3.4",
-                "globby": "^11.1.0",
-                "is-glob": "^4.0.3",
-                "semver": "^7.3.7",
-                "tsutils": "^3.21.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/utils": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz",
-            "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==",
-            "dependencies": {
-                "@eslint-community/eslint-utils": "^4.2.0",
-                "@types/json-schema": "^7.0.9",
-                "@types/semver": "^7.3.12",
-                "@typescript-eslint/scope-manager": "5.60.1",
-                "@typescript-eslint/types": "5.60.1",
-                "@typescript-eslint/typescript-estree": "5.60.1",
-                "eslint-scope": "^5.1.1",
-                "semver": "^7.3.7"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-            "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^4.1.1"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/@typescript-eslint/utils/node_modules/estraverse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/@typescript-eslint/visitor-keys": {
-            "version": "5.60.1",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz",
-            "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==",
-            "dependencies": {
-                "@typescript-eslint/types": "5.60.1",
-                "eslint-visitor-keys": "^3.3.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@vitest/coverage-v8": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.32.0.tgz",
-            "integrity": "sha512-VXXlWq9X/NbsoP/l/CHLBjutsFFww1UY1qEhzGjn/DY7Tqe+z0Nu8XKc8im/XUAmjiWsh2XV7sy/F0IKAl4eaw==",
-            "dependencies": {
-                "@ampproject/remapping": "^2.2.1",
-                "@bcoe/v8-coverage": "^0.2.3",
-                "istanbul-lib-coverage": "^3.2.0",
-                "istanbul-lib-report": "^3.0.0",
-                "istanbul-lib-source-maps": "^4.0.1",
-                "istanbul-reports": "^3.1.5",
-                "magic-string": "^0.30.0",
-                "picocolors": "^1.0.0",
-                "std-env": "^3.3.2",
-                "test-exclude": "^6.0.0",
-                "v8-to-istanbul": "^9.1.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            },
-            "peerDependencies": {
-                "vitest": ">=0.32.0 <1"
-            }
-        },
-        "node_modules/@vitest/expect": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.0.tgz",
-            "integrity": "sha512-VxVHhIxKw9Lux+O9bwLEEk2gzOUe93xuFHy9SzYWnnoYZFYg1NfBtnfnYWiJN7yooJ7KNElCK5YtA7DTZvtXtg==",
-            "dependencies": {
-                "@vitest/spy": "0.32.0",
-                "@vitest/utils": "0.32.0",
-                "chai": "^4.3.7"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/@vitest/runner": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.0.tgz",
-            "integrity": "sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==",
-            "dependencies": {
-                "@vitest/utils": "0.32.0",
-                "concordance": "^5.0.4",
-                "p-limit": "^4.0.0",
-                "pathe": "^1.1.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/@vitest/snapshot": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.0.tgz",
-            "integrity": "sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==",
-            "dependencies": {
-                "magic-string": "^0.30.0",
-                "pathe": "^1.1.0",
-                "pretty-format": "^27.5.1"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/@vitest/spy": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.0.tgz",
-            "integrity": "sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==",
-            "dependencies": {
-                "tinyspy": "^2.1.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/@vitest/utils": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.0.tgz",
-            "integrity": "sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==",
-            "dependencies": {
-                "concordance": "^5.0.4",
-                "loupe": "^2.3.6",
-                "pretty-format": "^27.5.1"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/acorn": {
-            "version": "8.8.2",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
-            "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/acorn-jsx": {
-            "version": "5.3.2",
-            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-            "peerDependencies": {
-                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.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/ajv": {
-            "version": "6.12.6",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "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": "5.2.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-            "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
-        "node_modules/any-promise": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
-        },
-        "node_modules/arg": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
-        },
-        "node_modules/argparse": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-        },
-        "node_modules/array-buffer-byte-length": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
-            "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "is-array-buffer": "^3.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array-includes": {
-            "version": "3.1.6",
-            "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
-            "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4",
-                "get-intrinsic": "^1.1.3",
-                "is-string": "^1.0.7"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array-union": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-            "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/array.prototype.flat": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
-            "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array.prototype.flatmap": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
-            "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/assertion-error": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
-            "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/available-typed-arrays": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
-            "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/ayu": {
-            "version": "8.0.1",
-            "resolved": "https://registry.npmjs.org/ayu/-/ayu-8.0.1.tgz",
-            "integrity": "sha512-yuPZ2kZYQoYaPRQ/78F9rXDVx1rVGCJ1neBYithBoSprD6zPdIJdAKizUXG0jtTBu7nTFyAnVFFYuLnCS3cpDw==",
-            "dependencies": {
-                "@types/chroma-js": "^2.0.0",
-                "chroma-js": "^2.1.0",
-                "nonenumerable": "^1.1.1"
-            }
-        },
-        "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/big-integer": {
-            "version": "1.6.51",
-            "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
-            "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/blueimp-md5": {
-            "version": "2.19.0",
-            "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz",
-            "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w=="
-        },
-        "node_modules/bplist-parser": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
-            "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
-            "dependencies": {
-                "big-integer": "^1.6.44"
-            },
-            "engines": {
-                "node": ">= 5.10.0"
-            }
-        },
-        "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/bundle-name": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
-            "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
-            "dependencies": {
-                "run-applescript": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/cac": {
-            "version": "6.7.14",
-            "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
-            "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/call-bind": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-            "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-            "dependencies": {
-                "function-bind": "^1.1.1",
-                "get-intrinsic": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/call-me-maybe": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
-            "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="
-        },
-        "node_modules/callsites": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/chai": {
-            "version": "4.3.7",
-            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
-            "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
-            "dependencies": {
-                "assertion-error": "^1.1.0",
-                "check-error": "^1.0.2",
-                "deep-eql": "^4.1.2",
-                "get-func-name": "^2.0.0",
-                "loupe": "^2.3.1",
-                "pathval": "^1.1.1",
-                "type-detect": "^4.0.5"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "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/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/check-error": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "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/cli-color": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz",
-            "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==",
-            "dependencies": {
-                "d": "^1.0.1",
-                "es5-ext": "^0.10.61",
-                "es6-iterator": "^2.0.3",
-                "memoizee": "^0.4.15",
-                "timers-ext": "^0.1.7"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "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": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
-        },
-        "node_modules/concordance": {
-            "version": "5.0.4",
-            "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz",
-            "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==",
-            "dependencies": {
-                "date-time": "^3.1.0",
-                "esutils": "^2.0.3",
-                "fast-diff": "^1.2.0",
-                "js-string-escape": "^1.0.1",
-                "lodash": "^4.17.15",
-                "md5-hex": "^3.0.1",
-                "semver": "^7.3.2",
-                "well-known-symbols": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14"
-            }
-        },
-        "node_modules/convert-source-map": {
-            "version": "1.9.0",
-            "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
-            "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
-        },
-        "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/cross-spawn": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-            "dependencies": {
-                "path-key": "^3.1.0",
-                "shebang-command": "^2.0.0",
-                "which": "^2.0.1"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/d": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-            "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-            "dependencies": {
-                "es5-ext": "^0.10.50",
-                "type": "^1.0.1"
-            }
-        },
-        "node_modules/date-time": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz",
-            "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==",
-            "dependencies": {
-                "time-zone": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/deep-eql": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
-            "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
-            "dependencies": {
-                "type-detect": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/deep-is": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
-        },
-        "node_modules/deepmerge": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz",
-            "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/default-browser": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
-            "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
-            "dependencies": {
-                "bundle-name": "^3.0.0",
-                "default-browser-id": "^3.0.0",
-                "execa": "^7.1.1",
-                "titleize": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=14.16"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/default-browser-id": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
-            "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
-            "dependencies": {
-                "bplist-parser": "^0.2.0",
-                "untildify": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/define-lazy-prop": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
-            "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/define-properties": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
-            "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
-            "dependencies": {
-                "has-property-descriptors": "^1.0.0",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "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/dir-glob": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-            "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-            "dependencies": {
-                "path-type": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/doctrine": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/enhanced-resolve": {
-            "version": "5.15.0",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
-            "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
-            "dependencies": {
-                "graceful-fs": "^4.2.4",
-                "tapable": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/es-abstract": {
-            "version": "1.21.2",
-            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
-            "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
-            "dependencies": {
-                "array-buffer-byte-length": "^1.0.0",
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "es-set-tostringtag": "^2.0.1",
-                "es-to-primitive": "^1.2.1",
-                "function.prototype.name": "^1.1.5",
-                "get-intrinsic": "^1.2.0",
-                "get-symbol-description": "^1.0.0",
-                "globalthis": "^1.0.3",
-                "gopd": "^1.0.1",
-                "has": "^1.0.3",
-                "has-property-descriptors": "^1.0.0",
-                "has-proto": "^1.0.1",
-                "has-symbols": "^1.0.3",
-                "internal-slot": "^1.0.5",
-                "is-array-buffer": "^3.0.2",
-                "is-callable": "^1.2.7",
-                "is-negative-zero": "^2.0.2",
-                "is-regex": "^1.1.4",
-                "is-shared-array-buffer": "^1.0.2",
-                "is-string": "^1.0.7",
-                "is-typed-array": "^1.1.10",
-                "is-weakref": "^1.0.2",
-                "object-inspect": "^1.12.3",
-                "object-keys": "^1.1.1",
-                "object.assign": "^4.1.4",
-                "regexp.prototype.flags": "^1.4.3",
-                "safe-regex-test": "^1.0.0",
-                "string.prototype.trim": "^1.2.7",
-                "string.prototype.trimend": "^1.0.6",
-                "string.prototype.trimstart": "^1.0.6",
-                "typed-array-length": "^1.0.4",
-                "unbox-primitive": "^1.0.2",
-                "which-typed-array": "^1.1.9"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es-set-tostringtag": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
-            "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.3",
-                "has": "^1.0.3",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/es-shim-unscopables": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
-            "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
-            "dependencies": {
-                "has": "^1.0.3"
-            }
-        },
-        "node_modules/es-to-primitive": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-            "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-            "dependencies": {
-                "is-callable": "^1.1.4",
-                "is-date-object": "^1.0.1",
-                "is-symbol": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es5-ext": {
-            "version": "0.10.62",
-            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
-            "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "es6-iterator": "^2.0.3",
-                "es6-symbol": "^3.1.3",
-                "next-tick": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/es6-iterator": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-            "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
-            "dependencies": {
-                "d": "1",
-                "es5-ext": "^0.10.35",
-                "es6-symbol": "^3.1.1"
-            }
-        },
-        "node_modules/es6-symbol": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
-            "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
-            "dependencies": {
-                "d": "^1.0.1",
-                "ext": "^1.1.2"
-            }
-        },
-        "node_modules/es6-weak-map": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
-            "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
-            "dependencies": {
-                "d": "1",
-                "es5-ext": "^0.10.46",
-                "es6-iterator": "^2.0.3",
-                "es6-symbol": "^3.1.1"
-            }
-        },
-        "node_modules/esbuild": {
-            "version": "0.17.19",
-            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
-            "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
-            "hasInstallScript": true,
-            "bin": {
-                "esbuild": "bin/esbuild"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "optionalDependencies": {
-                "@esbuild/android-arm": "0.17.19",
-                "@esbuild/android-arm64": "0.17.19",
-                "@esbuild/android-x64": "0.17.19",
-                "@esbuild/darwin-arm64": "0.17.19",
-                "@esbuild/darwin-x64": "0.17.19",
-                "@esbuild/freebsd-arm64": "0.17.19",
-                "@esbuild/freebsd-x64": "0.17.19",
-                "@esbuild/linux-arm": "0.17.19",
-                "@esbuild/linux-arm64": "0.17.19",
-                "@esbuild/linux-ia32": "0.17.19",
-                "@esbuild/linux-loong64": "0.17.19",
-                "@esbuild/linux-mips64el": "0.17.19",
-                "@esbuild/linux-ppc64": "0.17.19",
-                "@esbuild/linux-riscv64": "0.17.19",
-                "@esbuild/linux-s390x": "0.17.19",
-                "@esbuild/linux-x64": "0.17.19",
-                "@esbuild/netbsd-x64": "0.17.19",
-                "@esbuild/openbsd-x64": "0.17.19",
-                "@esbuild/sunos-x64": "0.17.19",
-                "@esbuild/win32-arm64": "0.17.19",
-                "@esbuild/win32-ia32": "0.17.19",
-                "@esbuild/win32-x64": "0.17.19"
-            }
-        },
-        "node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint": {
-            "version": "8.43.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
-            "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
-            "dependencies": {
-                "@eslint-community/eslint-utils": "^4.2.0",
-                "@eslint-community/regexpp": "^4.4.0",
-                "@eslint/eslintrc": "^2.0.3",
-                "@eslint/js": "8.43.0",
-                "@humanwhocodes/config-array": "^0.11.10",
-                "@humanwhocodes/module-importer": "^1.0.1",
-                "@nodelib/fs.walk": "^1.2.8",
-                "ajv": "^6.10.0",
-                "chalk": "^4.0.0",
-                "cross-spawn": "^7.0.2",
-                "debug": "^4.3.2",
-                "doctrine": "^3.0.0",
-                "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.2.0",
-                "eslint-visitor-keys": "^3.4.1",
-                "espree": "^9.5.2",
-                "esquery": "^1.4.2",
-                "esutils": "^2.0.2",
-                "fast-deep-equal": "^3.1.3",
-                "file-entry-cache": "^6.0.1",
-                "find-up": "^5.0.0",
-                "glob-parent": "^6.0.2",
-                "globals": "^13.19.0",
-                "graphemer": "^1.4.0",
-                "ignore": "^5.2.0",
-                "import-fresh": "^3.0.0",
-                "imurmurhash": "^0.1.4",
-                "is-glob": "^4.0.0",
-                "is-path-inside": "^3.0.3",
-                "js-yaml": "^4.1.0",
-                "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.4.1",
-                "lodash.merge": "^4.6.2",
-                "minimatch": "^3.1.2",
-                "natural-compare": "^1.4.0",
-                "optionator": "^0.9.1",
-                "strip-ansi": "^6.0.1",
-                "strip-json-comments": "^3.1.0",
-                "text-table": "^0.2.0"
-            },
-            "bin": {
-                "eslint": "bin/eslint.js"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-import-resolver-node": {
-            "version": "0.3.7",
-            "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
-            "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
-            "dependencies": {
-                "debug": "^3.2.7",
-                "is-core-module": "^2.11.0",
-                "resolve": "^1.22.1"
-            }
-        },
-        "node_modules/eslint-import-resolver-node/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/eslint-import-resolver-typescript": {
-            "version": "3.5.5",
-            "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz",
-            "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==",
-            "dependencies": {
-                "debug": "^4.3.4",
-                "enhanced-resolve": "^5.12.0",
-                "eslint-module-utils": "^2.7.4",
-                "get-tsconfig": "^4.5.0",
-                "globby": "^13.1.3",
-                "is-core-module": "^2.11.0",
-                "is-glob": "^4.0.3",
-                "synckit": "^0.8.5"
-            },
-            "engines": {
-                "node": "^14.18.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
-            },
-            "peerDependencies": {
-                "eslint": "*",
-                "eslint-plugin-import": "*"
-            }
-        },
-        "node_modules/eslint-import-resolver-typescript/node_modules/globby": {
-            "version": "13.2.0",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.0.tgz",
-            "integrity": "sha512-jWsQfayf13NvqKUIL3Ta+CIqMnvlaIDFveWE/dpOZ9+3AMEJozsxDvKA02zync9UuvOM8rOXzsD5GqKP4OnWPQ==",
-            "dependencies": {
-                "dir-glob": "^3.0.1",
-                "fast-glob": "^3.2.11",
-                "ignore": "^5.2.0",
-                "merge2": "^1.4.1",
-                "slash": "^4.0.0"
-            },
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-import-resolver-typescript/node_modules/slash": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
-            "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-module-utils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
-            "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
-            "dependencies": {
-                "debug": "^3.2.7"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependenciesMeta": {
-                "eslint": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint-module-utils/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/eslint-plugin-import": {
-            "version": "2.27.5",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
-            "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
-            "dependencies": {
-                "array-includes": "^3.1.6",
-                "array.prototype.flat": "^1.3.1",
-                "array.prototype.flatmap": "^1.3.1",
-                "debug": "^3.2.7",
-                "doctrine": "^2.1.0",
-                "eslint-import-resolver-node": "^0.3.7",
-                "eslint-module-utils": "^2.7.4",
-                "has": "^1.0.3",
-                "is-core-module": "^2.11.0",
-                "is-glob": "^4.0.3",
-                "minimatch": "^3.1.2",
-                "object.values": "^1.1.6",
-                "resolve": "^1.22.1",
-                "semver": "^6.3.0",
-                "tsconfig-paths": "^3.14.1"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependencies": {
-                "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
-            }
-        },
-        "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/doctrine": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
-            "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/eslint-plugin-import/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/eslint-scope": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
-            "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-visitor-keys": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
-            "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/espree": {
-            "version": "9.5.2",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
-            "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
-            "dependencies": {
-                "acorn": "^8.8.0",
-                "acorn-jsx": "^5.3.2",
-                "eslint-visitor-keys": "^3.4.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/esquery": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-            "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
-            "dependencies": {
-                "estraverse": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/esrecurse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-            "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-            "dependencies": {
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esutils": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/event-emitter": {
-            "version": "0.3.5",
-            "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
-            "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
-            "dependencies": {
-                "d": "1",
-                "es5-ext": "~0.10.14"
-            }
-        },
-        "node_modules/execa": {
-            "version": "7.1.1",
-            "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
-            "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
-            "dependencies": {
-                "cross-spawn": "^7.0.3",
-                "get-stream": "^6.0.1",
-                "human-signals": "^4.3.0",
-                "is-stream": "^3.0.0",
-                "merge-stream": "^2.0.0",
-                "npm-run-path": "^5.1.0",
-                "onetime": "^6.0.0",
-                "signal-exit": "^3.0.7",
-                "strip-final-newline": "^3.0.0"
-            },
-            "engines": {
-                "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sindresorhus/execa?sponsor=1"
-            }
-        },
-        "node_modules/ext": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
-            "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
-            "dependencies": {
-                "type": "^2.7.2"
-            }
-        },
-        "node_modules/ext/node_modules/type": {
-            "version": "2.7.2",
-            "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
-            "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
-        },
-        "node_modules/fast-deep-equal": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-        },
-        "node_modules/fast-diff": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
-            "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
-        },
-        "node_modules/fast-glob": {
-            "version": "3.2.12",
-            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
-            "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
-            "dependencies": {
-                "@nodelib/fs.stat": "^2.0.2",
-                "@nodelib/fs.walk": "^1.2.3",
-                "glob-parent": "^5.1.2",
-                "merge2": "^1.3.0",
-                "micromatch": "^4.0.4"
-            },
-            "engines": {
-                "node": ">=8.6.0"
-            }
-        },
-        "node_modules/fast-glob/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/fast-json-stable-stringify": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
-        },
-        "node_modules/fast-levenshtein": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
-        },
-        "node_modules/fastq": {
-            "version": "1.15.0",
-            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
-            "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
-            "dependencies": {
-                "reusify": "^1.0.4"
-            }
-        },
-        "node_modules/file-entry-cache": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-            "dependencies": {
-                "flat-cache": "^3.0.4"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            }
-        },
-        "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/find-up": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-            "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-            "dependencies": {
-                "locate-path": "^6.0.0",
-                "path-exists": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/flat-cache": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
-            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
-            "dependencies": {
-                "flatted": "^3.1.0",
-                "rimraf": "^3.0.2"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            }
-        },
-        "node_modules/flatted": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
-            "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ=="
-        },
-        "node_modules/for-each": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-            "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
-            "dependencies": {
-                "is-callable": "^1.1.3"
-            }
-        },
-        "node_modules/fs.realpath": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
-        },
-        "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/function-bind": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-            "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
-        },
-        "node_modules/function.prototype.name": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
-            "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.0",
-                "functions-have-names": "^1.2.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/functions-have-names": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
-            "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-func-name": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/get-intrinsic": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
-            "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
-            "dependencies": {
-                "function-bind": "^1.1.1",
-                "has": "^1.0.3",
-                "has-proto": "^1.0.1",
-                "has-symbols": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-stdin": {
-            "version": "8.0.0",
-            "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
-            "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/get-stream": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/get-symbol-description": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
-            "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-tsconfig": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.2.tgz",
-            "integrity": "sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg==",
-            "dependencies": {
-                "resolve-pkg-maps": "^1.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
-            }
-        },
-        "node_modules/glob": {
-            "version": "7.2.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.1.1",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/glob-parent": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-            "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-            "dependencies": {
-                "is-glob": "^4.0.3"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/glob-promise": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz",
-            "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==",
-            "dependencies": {
-                "@types/glob": "^7.1.3"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "type": "individual",
-                "url": "https://github.com/sponsors/ahmadnassri"
-            },
-            "peerDependencies": {
-                "glob": "^7.1.6"
-            }
-        },
-        "node_modules/globals": {
-            "version": "13.20.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
-            "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
-            "dependencies": {
-                "type-fest": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/globalthis": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
-            "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
-            "dependencies": {
-                "define-properties": "^1.1.3"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/globby": {
-            "version": "11.1.0",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-            "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-            "dependencies": {
-                "array-union": "^2.1.0",
-                "dir-glob": "^3.0.1",
-                "fast-glob": "^3.2.9",
-                "ignore": "^5.2.0",
-                "merge2": "^1.4.1",
-                "slash": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/gopd": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
-            "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/graceful-fs": {
-            "version": "4.2.11",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-            "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
-        },
-        "node_modules/grapheme-splitter": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
-            "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="
-        },
-        "node_modules/graphemer": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
-            "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
-        },
-        "node_modules/has": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-            "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-            "dependencies": {
-                "function-bind": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/has-bigints": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
-            "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "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/has-property-descriptors": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
-            "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-proto": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
-            "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-symbols": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-            "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-tostringtag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-            "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/html-escaper": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
-            "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="
-        },
-        "node_modules/human-signals": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
-            "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
-            "engines": {
-                "node": ">=14.18.0"
-            }
-        },
-        "node_modules/ignore": {
-            "version": "5.2.4",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-            "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/import-fresh": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-            "dependencies": {
-                "parent-module": "^1.0.0",
-                "resolve-from": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/imurmurhash": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-            "engines": {
-                "node": ">=0.8.19"
-            }
-        },
-        "node_modules/inflight": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-            "dependencies": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-            }
-        },
-        "node_modules/inherits": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-        },
-        "node_modules/internal-slot": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
-            "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
-            "dependencies": {
-                "get-intrinsic": "^1.2.0",
-                "has": "^1.0.3",
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/is-array-buffer": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
-            "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.2.0",
-                "is-typed-array": "^1.1.10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-bigint": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
-            "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
-            "dependencies": {
-                "has-bigints": "^1.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-boolean-object": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
-            "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-callable": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
-            "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-core-module": {
-            "version": "2.12.1",
-            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
-            "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
-            "dependencies": {
-                "has": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-date-object": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
-            "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-docker": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
-            "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
-            "bin": {
-                "is-docker": "cli.js"
-            },
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-extglob": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "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-inside-container": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
-            "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
-            "dependencies": {
-                "is-docker": "^3.0.0"
-            },
-            "bin": {
-                "is-inside-container": "cli.js"
-            },
-            "engines": {
-                "node": ">=14.16"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-negative-zero": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
-            "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "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-number-object": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
-            "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "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-promise": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
-            "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
-        },
-        "node_modules/is-regex": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
-            "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-shared-array-buffer": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
-            "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-stream": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
-            "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-string": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
-            "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-symbol": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-            "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-typed-array": {
-            "version": "1.1.10",
-            "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
-            "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "gopd": "^1.0.1",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-weakref": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
-            "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-wsl": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
-            "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
-            "dependencies": {
-                "is-docker": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/is-wsl/node_modules/is-docker": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-            "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-            "bin": {
-                "is-docker": "cli.js"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/isexe": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
-        },
-        "node_modules/istanbul-lib-coverage": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
-            "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/istanbul-lib-report": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
-            "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
-            "dependencies": {
-                "istanbul-lib-coverage": "^3.0.0",
-                "make-dir": "^3.0.0",
-                "supports-color": "^7.1.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/istanbul-lib-source-maps": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
-            "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
-            "dependencies": {
-                "debug": "^4.1.1",
-                "istanbul-lib-coverage": "^3.0.0",
-                "source-map": "^0.6.1"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/istanbul-reports": {
-            "version": "3.1.5",
-            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
-            "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
-            "dependencies": {
-                "html-escaper": "^2.0.0",
-                "istanbul-lib-report": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/js-string-escape": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
-            "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/js-tokens": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-            "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-            "peer": true
-        },
-        "node_modules/js-yaml": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-            "dependencies": {
-                "argparse": "^2.0.1"
-            },
-            "bin": {
-                "js-yaml": "bin/js-yaml.js"
-            }
-        },
-        "node_modules/json-schema-to-typescript": {
-            "version": "13.0.2",
-            "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.2.tgz",
-            "integrity": "sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==",
-            "dependencies": {
-                "@bcherny/json-schema-ref-parser": "10.0.5-fork",
-                "@types/json-schema": "^7.0.11",
-                "@types/lodash": "^4.14.182",
-                "@types/prettier": "^2.6.1",
-                "cli-color": "^2.0.2",
-                "get-stdin": "^8.0.0",
-                "glob": "^7.1.6",
-                "glob-promise": "^4.2.2",
-                "is-glob": "^4.0.3",
-                "lodash": "^4.17.21",
-                "minimist": "^1.2.6",
-                "mkdirp": "^1.0.4",
-                "mz": "^2.7.0",
-                "prettier": "^2.6.2"
-            },
-            "bin": {
-                "json2ts": "dist/src/cli.js"
-            },
-            "engines": {
-                "node": ">=12.0.0"
-            }
-        },
-        "node_modules/json-schema-traverse": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
-        },
-        "node_modules/json-stable-stringify-without-jsonify": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-            "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
-        },
-        "node_modules/json5": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
-            "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
-            "dependencies": {
-                "minimist": "^1.2.0"
-            },
-            "bin": {
-                "json5": "lib/cli.js"
-            }
-        },
-        "node_modules/jsonc-parser": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
-            "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
-        },
-        "node_modules/levn": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-            "dependencies": {
-                "prelude-ls": "^1.2.1",
-                "type-check": "~0.4.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/local-pkg": {
-            "version": "0.4.3",
-            "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
-            "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
-            "engines": {
-                "node": ">=14"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/antfu"
-            }
-        },
-        "node_modules/locate-path": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-            "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-            "dependencies": {
-                "p-locate": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/lodash": {
-            "version": "4.17.21",
-            "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-            "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
-        },
-        "node_modules/lodash.merge": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
-        },
-        "node_modules/loose-envify": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
-            "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
-            "peer": true,
-            "dependencies": {
-                "js-tokens": "^3.0.0 || ^4.0.0"
-            },
-            "bin": {
-                "loose-envify": "cli.js"
-            }
-        },
-        "node_modules/loupe": {
-            "version": "2.3.6",
-            "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
-            "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
-            "dependencies": {
-                "get-func-name": "^2.0.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/lru-queue": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
-            "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==",
-            "dependencies": {
-                "es5-ext": "~0.10.2"
-            }
-        },
-        "node_modules/magic-string": {
-            "version": "0.30.0",
-            "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
-            "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==",
-            "dependencies": {
-                "@jridgewell/sourcemap-codec": "^1.4.13"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "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/md5-hex": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz",
-            "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==",
-            "dependencies": {
-                "blueimp-md5": "^2.10.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/memoizee": {
-            "version": "0.4.15",
-            "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz",
-            "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==",
-            "dependencies": {
-                "d": "^1.0.1",
-                "es5-ext": "^0.10.53",
-                "es6-weak-map": "^2.0.3",
-                "event-emitter": "^0.3.5",
-                "is-promise": "^2.2.2",
-                "lru-queue": "^0.1.0",
-                "next-tick": "^1.1.0",
-                "timers-ext": "^0.1.7"
-            }
-        },
-        "node_modules/merge-stream": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
-        },
-        "node_modules/merge2": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-            "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/micromatch": {
-            "version": "4.0.5",
-            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-            "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
-            "dependencies": {
-                "braces": "^3.0.2",
-                "picomatch": "^2.3.1"
-            },
-            "engines": {
-                "node": ">=8.6"
-            }
-        },
-        "node_modules/mimic-fn": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
-            "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "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.8",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-            "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/mkdirp": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-            "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/mlly": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz",
-            "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==",
-            "dependencies": {
-                "acorn": "^8.8.2",
-                "pathe": "^1.1.0",
-                "pkg-types": "^1.0.3",
-                "ufo": "^1.1.2"
-            }
-        },
-        "node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/mz": {
-            "version": "2.7.0",
-            "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
-            "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-            "dependencies": {
-                "any-promise": "^1.0.0",
-                "object-assign": "^4.0.1",
-                "thenify-all": "^1.0.0"
-            }
-        },
-        "node_modules/nanoid": {
-            "version": "3.3.6",
-            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
-            "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/ai"
-                }
-            ],
-            "bin": {
-                "nanoid": "bin/nanoid.cjs"
-            },
-            "engines": {
-                "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-            }
-        },
-        "node_modules/natural-compare": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-            "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
-        },
-        "node_modules/natural-compare-lite": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
-            "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g=="
-        },
-        "node_modules/next-tick": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
-            "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
-        },
-        "node_modules/nonenumerable": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/nonenumerable/-/nonenumerable-1.1.1.tgz",
-            "integrity": "sha512-ptUD9w9D8WqW6fuJJkZNCImkf+0vdbgUTbRK3i7jsy3olqtH96hYE6Q/S3Tx9NWbcB/ocAjYshXCAUP0lZ9B4Q=="
-        },
-        "node_modules/npm-run-path": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
-            "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
-            "dependencies": {
-                "path-key": "^4.0.0"
-            },
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/npm-run-path/node_modules/path-key": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
-            "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/object-assign": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-inspect": {
-            "version": "1.12.3",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
-            "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object-keys": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-            "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/object.assign": {
-            "version": "4.1.4",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
-            "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "has-symbols": "^1.0.3",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.values": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
-            "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/once": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-            "dependencies": {
-                "wrappy": "1"
-            }
-        },
-        "node_modules/onetime": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
-            "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
-            "dependencies": {
-                "mimic-fn": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/open": {
-            "version": "9.1.0",
-            "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
-            "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
-            "dependencies": {
-                "default-browser": "^4.0.0",
-                "define-lazy-prop": "^3.0.0",
-                "is-inside-container": "^1.0.0",
-                "is-wsl": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=14.16"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/optionator": {
-            "version": "0.9.3",
-            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-            "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
-            "dependencies": {
-                "@aashutoshrathi/word-wrap": "^1.2.3",
-                "deep-is": "^0.1.3",
-                "fast-levenshtein": "^2.0.6",
-                "levn": "^0.4.1",
-                "prelude-ls": "^1.2.1",
-                "type-check": "^0.4.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/p-limit": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
-            "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
-            "dependencies": {
-                "yocto-queue": "^1.0.0"
-            },
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/p-locate": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-            "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-            "dependencies": {
-                "p-limit": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/p-locate/node_modules/p-limit": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-            "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-            "dependencies": {
-                "yocto-queue": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/p-locate/node_modules/yocto-queue": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-            "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/parent-module": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-            "dependencies": {
-                "callsites": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/path-exists": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-            "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/path-is-absolute": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/path-key": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/path-parse": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-            "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
-        },
-        "node_modules/path-type": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pathe": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
-            "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q=="
-        },
-        "node_modules/pathval": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-            "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/picocolors": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-            "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
-        },
-        "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/pkg-types": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
-            "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
-            "dependencies": {
-                "jsonc-parser": "^3.2.0",
-                "mlly": "^1.2.0",
-                "pathe": "^1.1.0"
-            }
-        },
-        "node_modules/postcss": {
-            "version": "8.4.24",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
-            "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/postcss/"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/postcss"
-                },
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/ai"
-                }
-            ],
-            "dependencies": {
-                "nanoid": "^3.3.6",
-                "picocolors": "^1.0.0",
-                "source-map-js": "^1.0.2"
-            },
-            "engines": {
-                "node": "^10 || ^12 || >=14"
-            }
-        },
-        "node_modules/prelude-ls": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/prettier": {
-            "version": "2.8.8",
-            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
-            "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
-            "bin": {
-                "prettier": "bin-prettier.js"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            },
-            "funding": {
-                "url": "https://github.com/prettier/prettier?sponsor=1"
-            }
-        },
-        "node_modules/pretty-format": {
-            "version": "27.5.1",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
-            "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
-            "dependencies": {
-                "ansi-regex": "^5.0.1",
-                "ansi-styles": "^5.0.0",
-                "react-is": "^17.0.1"
-            },
-            "engines": {
-                "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
-            }
-        },
-        "node_modules/punycode": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
-            "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/queue-microtask": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-            "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/react": {
-            "version": "18.2.0",
-            "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
-            "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
-            "peer": true,
-            "dependencies": {
-                "loose-envify": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/react-is": {
-            "version": "17.0.2",
-            "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
-            "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
-        },
-        "node_modules/regexp.prototype.flags": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
-            "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "functions-have-names": "^1.2.3"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/resolve": {
-            "version": "1.22.2",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
-            "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
-            "dependencies": {
-                "is-core-module": "^2.11.0",
-                "path-parse": "^1.0.7",
-                "supports-preserve-symlinks-flag": "^1.0.0"
-            },
-            "bin": {
-                "resolve": "bin/resolve"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/resolve-from": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/resolve-pkg-maps": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
-            "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
-            "funding": {
-                "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
-            }
-        },
-        "node_modules/reusify": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-            "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-            "engines": {
-                "iojs": ">=1.0.0",
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/rimraf": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/rollup": {
-            "version": "3.25.1",
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz",
-            "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==",
-            "bin": {
-                "rollup": "dist/bin/rollup"
-            },
-            "engines": {
-                "node": ">=14.18.0",
-                "npm": ">=8.0.0"
-            },
-            "optionalDependencies": {
-                "fsevents": "~2.3.2"
-            }
-        },
-        "node_modules/run-applescript": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
-            "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
-            "dependencies": {
-                "execa": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/run-applescript/node_modules/execa": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
-            "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
-            "dependencies": {
-                "cross-spawn": "^7.0.3",
-                "get-stream": "^6.0.0",
-                "human-signals": "^2.1.0",
-                "is-stream": "^2.0.0",
-                "merge-stream": "^2.0.0",
-                "npm-run-path": "^4.0.1",
-                "onetime": "^5.1.2",
-                "signal-exit": "^3.0.3",
-                "strip-final-newline": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sindresorhus/execa?sponsor=1"
-            }
-        },
-        "node_modules/run-applescript/node_modules/human-signals": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
-            "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
-            "engines": {
-                "node": ">=10.17.0"
-            }
-        },
-        "node_modules/run-applescript/node_modules/is-stream": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
-            "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/run-applescript/node_modules/mimic-fn": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-            "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/run-applescript/node_modules/npm-run-path": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
-            "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
-            "dependencies": {
-                "path-key": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/run-applescript/node_modules/onetime": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-            "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-            "dependencies": {
-                "mimic-fn": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/run-applescript/node_modules/strip-final-newline": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
-            "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/run-parallel": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-            "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "dependencies": {
-                "queue-microtask": "^1.2.2"
-            }
-        },
-        "node_modules/safe-regex-test": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
-            "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.1.3",
-                "is-regex": "^1.1.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/semver": {
-            "version": "7.5.2",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
-            "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/shebang-command": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-            "dependencies": {
-                "shebang-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/shebang-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/side-channel": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-            "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "get-intrinsic": "^1.0.2",
-                "object-inspect": "^1.9.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/siginfo": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
-            "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="
-        },
-        "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/slash": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-            "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/source-map-js": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
-            "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/stackback": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
-            "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="
-        },
-        "node_modules/std-env": {
-            "version": "3.3.3",
-            "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz",
-            "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg=="
-        },
-        "node_modules/string.prototype.trim": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
-            "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimend": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
-            "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimstart": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
-            "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "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-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/strip-final-newline": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
-            "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/strip-literal": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz",
-            "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==",
-            "dependencies": {
-                "acorn": "^8.8.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/antfu"
-            }
-        },
-        "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/supports-preserve-symlinks-flag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-            "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/synckit": {
-            "version": "0.8.5",
-            "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
-            "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
-            "dependencies": {
-                "@pkgr/utils": "^2.3.1",
-                "tslib": "^2.5.0"
-            },
-            "engines": {
-                "node": "^14.18.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/unts"
-            }
-        },
-        "node_modules/synckit/node_modules/tslib": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
-            "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
-        },
-        "node_modules/tapable": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-            "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/test-exclude": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
-            "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
-            "dependencies": {
-                "@istanbuljs/schema": "^0.1.2",
-                "glob": "^7.1.4",
-                "minimatch": "^3.0.4"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/text-table": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
-        },
-        "node_modules/thenify": {
-            "version": "3.3.1",
-            "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
-            "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-            "dependencies": {
-                "any-promise": "^1.0.0"
-            }
-        },
-        "node_modules/thenify-all": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
-            "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-            "dependencies": {
-                "thenify": ">= 3.1.0 < 4"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/time-zone": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz",
-            "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/timers-ext": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
-            "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==",
-            "dependencies": {
-                "es5-ext": "~0.10.46",
-                "next-tick": "1"
-            }
-        },
-        "node_modules/tinybench": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz",
-            "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA=="
-        },
-        "node_modules/tinypool": {
-            "version": "0.5.0",
-            "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz",
-            "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==",
-            "engines": {
-                "node": ">=14.0.0"
-            }
-        },
-        "node_modules/tinyspy": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz",
-            "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==",
-            "engines": {
-                "node": ">=14.0.0"
-            }
-        },
-        "node_modules/titleize": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
-            "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "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/toml": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
-            "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
-        },
-        "node_modules/ts-deepmerge": {
-            "version": "6.0.3",
-            "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-6.0.3.tgz",
-            "integrity": "sha512-MBBJL0UK/mMnZRONMz4J1CRu5NsGtsh+gR1nkn8KLE9LXo/PCzeHhQduhNary8m5/m9ryOOyFwVKxq81cPlaow==",
-            "engines": {
-                "node": ">=14.13.1"
-            }
-        },
-        "node_modules/ts-node": {
-            "version": "10.9.1",
-            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
-            "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
-            "dependencies": {
-                "@cspotcode/source-map-support": "^0.8.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.1",
-                "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/tsconfig-paths": {
-            "version": "3.14.2",
-            "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
-            "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
-            "dependencies": {
-                "@types/json5": "^0.0.29",
-                "json5": "^1.0.2",
-                "minimist": "^1.2.6",
-                "strip-bom": "^3.0.0"
-            }
-        },
-        "node_modules/tslib": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-            "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
-        },
-        "node_modules/tsutils": {
-            "version": "3.21.0",
-            "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
-            "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
-            "dependencies": {
-                "tslib": "^1.8.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            },
-            "peerDependencies": {
-                "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
-            }
-        },
-        "node_modules/type": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
-        },
-        "node_modules/type-check": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-            "dependencies": {
-                "prelude-ls": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/type-detect": {
-            "version": "4.0.8",
-            "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-            "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "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/typed-array-length": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
-            "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "is-typed-array": "^1.1.9"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/typescript": {
-            "version": "5.1.5",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.5.tgz",
-            "integrity": "sha512-FOH+WN/DQjUvN6WgW+c4Ml3yi0PH+a/8q+kNIfRehv1wLhWONedw85iu+vQ39Wp49IzTJEsZ2lyLXpBF7mkF1g==",
-            "bin": {
-                "tsc": "bin/tsc",
-                "tsserver": "bin/tsserver"
-            },
-            "engines": {
-                "node": ">=14.17"
-            }
-        },
-        "node_modules/ufo": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz",
-            "integrity": "sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ=="
-        },
-        "node_modules/unbox-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
-            "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-bigints": "^1.0.2",
-                "has-symbols": "^1.0.3",
-                "which-boxed-primitive": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/untildify": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
-            "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/uri-js": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/use-sync-external-store": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
-            "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
-            "peerDependencies": {
-                "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
-            }
-        },
-        "node_modules/utility-types": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
-            "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/v8-compile-cache-lib": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-            "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
-        },
-        "node_modules/v8-to-istanbul": {
-            "version": "9.1.0",
-            "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
-            "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==",
-            "dependencies": {
-                "@jridgewell/trace-mapping": "^0.3.12",
-                "@types/istanbul-lib-coverage": "^2.0.1",
-                "convert-source-map": "^1.6.0"
-            },
-            "engines": {
-                "node": ">=10.12.0"
-            }
-        },
-        "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.18",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
-            "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
-            "dependencies": {
-                "@jridgewell/resolve-uri": "3.1.0",
-                "@jridgewell/sourcemap-codec": "1.4.14"
-            }
-        },
-        "node_modules/vite": {
-            "version": "4.3.9",
-            "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
-            "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
-            "dependencies": {
-                "esbuild": "^0.17.5",
-                "postcss": "^8.4.23",
-                "rollup": "^3.21.0"
-            },
-            "bin": {
-                "vite": "bin/vite.js"
-            },
-            "engines": {
-                "node": "^14.18.0 || >=16.0.0"
-            },
-            "optionalDependencies": {
-                "fsevents": "~2.3.2"
-            },
-            "peerDependencies": {
-                "@types/node": ">= 14",
-                "less": "*",
-                "sass": "*",
-                "stylus": "*",
-                "sugarss": "*",
-                "terser": "^5.4.0"
-            },
-            "peerDependenciesMeta": {
-                "@types/node": {
-                    "optional": true
-                },
-                "less": {
-                    "optional": true
-                },
-                "sass": {
-                    "optional": true
-                },
-                "stylus": {
-                    "optional": true
-                },
-                "sugarss": {
-                    "optional": true
-                },
-                "terser": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/vite-node": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.32.0.tgz",
-            "integrity": "sha512-220P/y8YacYAU+daOAqiGEFXx2A8AwjadDzQqos6wSukjvvTWNqleJSwoUn0ckyNdjHIKoxn93Nh1vWBqEKr3Q==",
-            "dependencies": {
-                "cac": "^6.7.14",
-                "debug": "^4.3.4",
-                "mlly": "^1.2.0",
-                "pathe": "^1.1.0",
-                "picocolors": "^1.0.0",
-                "vite": "^3.0.0 || ^4.0.0"
-            },
-            "bin": {
-                "vite-node": "vite-node.mjs"
-            },
-            "engines": {
-                "node": ">=v14.18.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            }
-        },
-        "node_modules/vitest": {
-            "version": "0.32.0",
-            "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.32.0.tgz",
-            "integrity": "sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==",
-            "dependencies": {
-                "@types/chai": "^4.3.5",
-                "@types/chai-subset": "^1.3.3",
-                "@types/node": "*",
-                "@vitest/expect": "0.32.0",
-                "@vitest/runner": "0.32.0",
-                "@vitest/snapshot": "0.32.0",
-                "@vitest/spy": "0.32.0",
-                "@vitest/utils": "0.32.0",
-                "acorn": "^8.8.2",
-                "acorn-walk": "^8.2.0",
-                "cac": "^6.7.14",
-                "chai": "^4.3.7",
-                "concordance": "^5.0.4",
-                "debug": "^4.3.4",
-                "local-pkg": "^0.4.3",
-                "magic-string": "^0.30.0",
-                "pathe": "^1.1.0",
-                "picocolors": "^1.0.0",
-                "std-env": "^3.3.2",
-                "strip-literal": "^1.0.1",
-                "tinybench": "^2.5.0",
-                "tinypool": "^0.5.0",
-                "vite": "^3.0.0 || ^4.0.0",
-                "vite-node": "0.32.0",
-                "why-is-node-running": "^2.2.2"
-            },
-            "bin": {
-                "vitest": "vitest.mjs"
-            },
-            "engines": {
-                "node": ">=v14.18.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/vitest"
-            },
-            "peerDependencies": {
-                "@edge-runtime/vm": "*",
-                "@vitest/browser": "*",
-                "@vitest/ui": "*",
-                "happy-dom": "*",
-                "jsdom": "*",
-                "playwright": "*",
-                "safaridriver": "*",
-                "webdriverio": "*"
-            },
-            "peerDependenciesMeta": {
-                "@edge-runtime/vm": {
-                    "optional": true
-                },
-                "@vitest/browser": {
-                    "optional": true
-                },
-                "@vitest/ui": {
-                    "optional": true
-                },
-                "happy-dom": {
-                    "optional": true
-                },
-                "jsdom": {
-                    "optional": true
-                },
-                "playwright": {
-                    "optional": true
-                },
-                "safaridriver": {
-                    "optional": true
-                },
-                "webdriverio": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/well-known-symbols": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz",
-            "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/which": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "node-which": "bin/node-which"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/which-boxed-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-            "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-            "dependencies": {
-                "is-bigint": "^1.0.1",
-                "is-boolean-object": "^1.1.0",
-                "is-number-object": "^1.0.4",
-                "is-string": "^1.0.5",
-                "is-symbol": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/which-typed-array": {
-            "version": "1.1.9",
-            "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
-            "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "gopd": "^1.0.1",
-                "has-tostringtag": "^1.0.0",
-                "is-typed-array": "^1.1.10"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/why-is-node-running": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
-            "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
-            "dependencies": {
-                "siginfo": "^2.0.0",
-                "stackback": "0.0.2"
-            },
-            "bin": {
-                "why-is-node-running": "cli.js"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/wrappy": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-            "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
-        },
-        "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"
-            }
-        },
-        "node_modules/yocto-queue": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
-            "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
-            "engines": {
-                "node": ">=12.20"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/zustand": {
-            "version": "4.3.8",
-            "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.8.tgz",
-            "integrity": "sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==",
-            "dependencies": {
-                "use-sync-external-store": "1.2.0"
-            },
-            "engines": {
-                "node": ">=12.7.0"
-            },
-            "peerDependencies": {
-                "immer": ">=9.0",
-                "react": ">=16.8"
-            },
-            "peerDependenciesMeta": {
-                "immer": {
-                    "optional": true
-                },
-                "react": {
-                    "optional": true
-                }
-            }
-        }
-    }
-}

styles/package.json πŸ”—

@@ -1,37 +0,0 @@
-{
-    "name": "styles",
-    "version": "1.0.0",
-    "description": "Typescript app that builds Zed's themes",
-    "main": "./src/build_themes.ts",
-    "scripts": {
-        "build": "ts-node ./src/build_themes.ts",
-        "build-licenses": "ts-node ./src/build_licenses.ts",
-        "build-tokens": "ts-node ./src/build_tokens.ts",
-        "build-types": "ts-node ./src/build_types.ts",
-        "test": "vitest"
-    },
-    "author": "Zed Industries (https://github.com/zed-industries/)",
-    "license": "ISC",
-    "dependencies": {
-        "@tokens-studio/types": "^0.2.3",
-        "@types/chroma-js": "^2.4.0",
-        "@types/node": "^18.14.1",
-        "@typescript-eslint/eslint-plugin": "^5.60.1",
-        "@typescript-eslint/parser": "^5.60.1",
-        "@vitest/coverage-v8": "^0.32.0",
-        "ayu": "^8.0.1",
-        "chroma-js": "^2.4.2",
-        "deepmerge": "^4.3.0",
-        "eslint": "^8.43.0",
-        "eslint-import-resolver-typescript": "^3.5.5",
-        "eslint-plugin-import": "^2.27.5",
-        "json-schema-to-typescript": "^13.0.2",
-        "toml": "^3.0.0",
-        "ts-deepmerge": "^6.0.3",
-        "ts-node": "^10.9.1",
-        "typescript": "^5.1.5",
-        "utility-types": "^3.10.0",
-        "vitest": "^0.32.0",
-        "zustand": "^4.3.8"
-    }
-}

styles/src/build_licenses.ts πŸ”—

@@ -1,50 +0,0 @@
-import * as fs from "fs"
-import toml from "toml"
-import { themes } from "./themes"
-import { ThemeConfig } from "./common"
-
-const ACCEPTED_LICENSES_FILE = `${__dirname}/../../script/licenses/zed-licenses.toml`
-
-// Use the cargo-about configuration file as the source of truth for supported licenses.
-function parse_accepted_toml(file: string): string[] {
-    const buffer = fs.readFileSync(file).toString()
-
-    const obj = toml.parse(buffer)
-
-    if (!Array.isArray(obj.accepted)) {
-        throw Error("Accepted license source is malformed")
-    }
-
-    return obj.accepted
-}
-
-function check_licenses(themes: ThemeConfig[]) {
-    for (const theme of themes) {
-        if (!theme.license_file) {
-            throw Error(`Theme ${theme.name} should have a LICENSE file`)
-        }
-    }
-}
-
-function generate_license_file(themes: ThemeConfig[]) {
-    check_licenses(themes)
-    for (const theme of themes) {
-        const license_text = fs.readFileSync(theme.license_file).toString()
-        write_license(theme.name, license_text, theme.license_url)
-    }
-}
-
-function write_license(
-    theme_name: string,
-    license_text: string,
-    license_url?: string
-) {
-    process.stdout.write(
-        license_url
-            ? `## [${theme_name}](${license_url})\n\n${license_text}\n********************************************************************************\n\n`
-            : `## ${theme_name}\n\n${license_text}\n********************************************************************************\n\n`
-    )
-}
-
-const accepted_licenses = parse_accepted_toml(ACCEPTED_LICENSES_FILE)
-generate_license_file(themes)

styles/src/build_themes.ts πŸ”—

@@ -1,45 +0,0 @@
-import * as fs from "fs"
-import { tmpdir } from "os"
-import * as path from "path"
-import app from "./style_tree/app"
-import { Theme, create_theme } from "./theme/create_theme"
-import { themes } from "./themes"
-import { useThemeStore } from "./theme"
-
-const assets_directory = `${__dirname}/../../assets`
-const temp_directory = fs.mkdtempSync(path.join(tmpdir(), "build-themes"))
-
-function clear_themes(theme_directory: string) {
-    if (!fs.existsSync(theme_directory)) {
-        fs.mkdirSync(theme_directory, { recursive: true })
-    } else {
-        for (const file of fs.readdirSync(theme_directory)) {
-            if (file.endsWith(".json")) {
-                fs.unlinkSync(path.join(theme_directory, file))
-            }
-        }
-    }
-}
-
-const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
-
-function write_themes(themes: Theme[], output_directory: string) {
-    clear_themes(output_directory)
-    for (const theme of themes) {
-        const { setTheme } = useThemeStore.getState()
-        setTheme(theme)
-
-        const style_tree = app()
-        // Nathan: New elements will read directly from the theme colors.
-        // Adding this during the transition. Afterwards, we can port all themes to Rust.
-        style_tree.base_theme = theme
-        const style_tree_json = JSON.stringify(style_tree, null, 2)
-        const temp_path = path.join(temp_directory, `${theme.name}.json`)
-        const out_path = path.join(output_directory, `${theme.name}.json`)
-        fs.writeFileSync(temp_path, style_tree_json)
-        fs.renameSync(temp_path, out_path)
-        console.log(`- ${out_path} created`)
-    }
-}
-
-write_themes(all_themes, `${assets_directory}/themes`)

styles/src/build_tokens.ts πŸ”—

@@ -1,88 +0,0 @@
-import * as fs from "fs"
-import * as path from "path"
-import { Theme, create_theme, useThemeStore } from "./common"
-import { themes } from "./themes"
-import { slugify } from "./utils/slugify"
-import { theme_tokens } from "./theme/tokens/theme"
-
-const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
-const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json")
-const METADATA_FILE = path.join(TOKENS_DIRECTORY, "$metadata.json")
-
-function clear_tokens(tokens_directory: string) {
-    if (!fs.existsSync(tokens_directory)) {
-        fs.mkdirSync(tokens_directory, { recursive: true })
-    } else {
-        for (const file of fs.readdirSync(tokens_directory)) {
-            if (file.endsWith(".json")) {
-                fs.unlinkSync(path.join(tokens_directory, file))
-            }
-        }
-    }
-}
-
-type TokenSet = {
-    id: string
-    name: string
-    selected_token_sets: { [key: string]: "enabled" }
-}
-
-function build_token_set_order(theme: Theme[]): {
-    token_set_order: string[]
-} {
-    const token_set_order: string[] = theme.map((scheme) =>
-        scheme.name.toLowerCase().replace(/\s+/g, "_")
-    )
-    return { token_set_order }
-}
-
-function build_themes_index(theme: Theme[]): TokenSet[] {
-    const themes_index: TokenSet[] = theme.map((scheme, index) => {
-        const id = `${scheme.is_light ? "light" : "dark"}_${scheme.name
-            .toLowerCase()
-            .replace(/\s+/g, "_")}_${index}`
-        const selected_token_sets: { [key: string]: "enabled" } = {}
-        const token_set = scheme.name.toLowerCase().replace(/\s+/g, "_")
-        selected_token_sets[token_set] = "enabled"
-
-        return {
-            id,
-            name: `${scheme.name} - ${scheme.is_light ? "Light" : "Dark"}`,
-            selected_token_sets,
-        }
-    })
-
-    return themes_index
-}
-
-function write_tokens(themes: Theme[], tokens_directory: string) {
-    clear_tokens(tokens_directory)
-
-    for (const theme of themes) {
-        const { setTheme } = useThemeStore.getState()
-        setTheme(theme)
-
-        const file_name = slugify(theme.name) + ".json"
-        const tokens = theme_tokens()
-        const tokens_json = JSON.stringify(tokens, null, 2)
-        const out_path = path.join(tokens_directory, file_name)
-        fs.writeFileSync(out_path, tokens_json, { mode: 0o644 })
-        console.log(`- ${out_path} created`)
-    }
-
-    const theme_index_data = build_themes_index(themes)
-
-    const themes_json = JSON.stringify(theme_index_data, null, 2)
-    fs.writeFileSync(TOKENS_FILE, themes_json, { mode: 0o644 })
-    console.log(`- ${TOKENS_FILE} created`)
-
-    const token_set_order_data = build_token_set_order(themes)
-
-    const metadata_json = JSON.stringify(token_set_order_data, null, 2)
-    fs.writeFileSync(METADATA_FILE, metadata_json, { mode: 0o644 })
-    console.log(`- ${METADATA_FILE} created`)
-}
-
-const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
-
-write_tokens(all_themes, TOKENS_DIRECTORY)

styles/src/build_types.ts πŸ”—

@@ -1,62 +0,0 @@
-import * as fs from "fs/promises"
-import * as fsSync from "fs"
-import * as path from "path"
-import { compile } from "json-schema-to-typescript"
-
-const BANNER = `/*
-* This file is autogenerated
-*/\n\n`
-const dirname = __dirname
-
-async function main() {
-    const schemas_path = path.join(dirname, "../../", "crates/theme/schemas")
-    const schema_files = (await fs.readdir(schemas_path)).filter((x) =>
-        x.endsWith(".json")
-    )
-
-    const compiled_types = new Set()
-
-    for (const filename of schema_files) {
-        const file_path = path.join(schemas_path, filename)
-        const file_contents = await fs.readFile(file_path)
-        const schema = JSON.parse(file_contents.toString())
-        const compiled = await compile(schema, schema.title, {
-            bannerComment: "",
-        })
-        const each_type = compiled.split("export")
-        for (const type of each_type) {
-            if (!type) {
-                continue
-            }
-            compiled_types.add("export " + type.trim())
-        }
-    }
-
-    const output = BANNER + Array.from(compiled_types).join("\n\n")
-    const output_path = path.join(dirname, "../../styles/src/types/zed.ts")
-
-    try {
-        const existing = await fs.readFile(output_path)
-        if (existing.toString() == output) {
-            // Skip writing if it hasn't changed
-            console.log("Schemas are up to date")
-            return
-        }
-    } catch (e) {
-        if (e.code !== "ENOENT") {
-            throw e
-        }
-    }
-
-    const types_dic = path.dirname(output_path)
-    if (!fsSync.existsSync(types_dic)) {
-        await fs.mkdir(types_dic)
-    }
-    await fs.writeFile(output_path, output)
-    console.log(`Wrote Typescript types to ${output_path}`)
-}
-
-main().catch((e) => {
-    console.error(e)
-    process.exit(1)
-})

styles/src/common.ts πŸ”—

@@ -1,34 +0,0 @@
-import chroma from "chroma-js"
-export * from "./theme"
-export * from "./theme/theme_config"
-export { chroma }
-
-export const font_families = {
-    ui_sans: "IBM Plex Sans",
-    sans: "Zed Sans",
-    mono: "Zed Mono",
-}
-
-export const font_sizes = {
-    "2xs": 10,
-    xs: 12,
-    sm: 14,
-    md: 16,
-    lg: 18,
-}
-
-export type FontWeight = "normal" | "bold"
-
-export const font_weights: { [key: string]: FontWeight } = {
-    normal: "normal",
-    bold: "bold",
-}
-
-export const sizes = {
-    px: 1,
-    xs: 2,
-    sm: 4,
-    md: 6,
-    lg: 8,
-    xl: 12,
-}

styles/src/component/button.ts πŸ”—

@@ -1,127 +0,0 @@
-import { font_sizes, useTheme } from "../common"
-import { Layer, Theme } from "../theme"
-import { TextStyle, background } from "../style_tree/components"
-
-// eslint-disable-next-line @typescript-eslint/no-namespace
-export namespace Button {
-    export type Options = {
-        layer: Layer
-        background: keyof Theme["lowest"]
-        color: keyof Theme["lowest"]
-        variant: Button.Variant
-        size: Button.Size
-        shape: Button.Shape
-        margin: {
-            top?: number
-            bottom?: number
-            left?: number
-            right?: number
-        }
-        states: {
-            enabled?: boolean
-            hovered?: boolean
-            pressed?: boolean
-            focused?: boolean
-            disabled?: boolean
-        }
-    }
-
-    export type ToggleableOptions = Options & {
-        active_background: keyof Theme["lowest"]
-        active_color: keyof Theme["lowest"]
-    }
-
-    /** Padding added to each side of a Shape.Rectangle button */
-    export const RECTANGLE_PADDING = 2
-    export const FONT_SIZE = font_sizes.sm
-    export const ICON_SIZE = 14
-    export const CORNER_RADIUS = 6
-
-    export const variant = {
-        Default: "filled",
-        Outline: "outline",
-        Ghost: "ghost",
-    } as const
-
-    export type Variant = (typeof variant)[keyof typeof variant]
-
-    export const shape = {
-        Rectangle: "rectangle",
-        Square: "square",
-    } as const
-
-    export type Shape = (typeof shape)[keyof typeof shape]
-
-    export const size = {
-        Small: "sm",
-        Medium: "md",
-    } as const
-
-    export type Size = (typeof size)[keyof typeof size]
-
-    export type BaseStyle = {
-        corder_radius: number
-        background: string | null
-        padding: {
-            top: number
-            bottom: number
-            left: number
-            right: number
-        }
-        margin: Button.Options["margin"]
-        button_height: number
-    }
-
-    export type LabelButtonStyle = BaseStyle & TextStyle
-    // export type IconButtonStyle = ButtonStyle
-
-    export const button_base = (
-        options: Partial<Button.Options> = {
-            variant: Button.variant.Default,
-            shape: Button.shape.Rectangle,
-            states: {
-                hovered: true,
-                pressed: true,
-            },
-        }
-    ): BaseStyle => {
-        const theme = useTheme()
-
-        const layer = options.layer ?? theme.middle
-        const color = options.color ?? "base"
-        const background_color =
-            options.variant === Button.variant.Ghost
-                ? null
-                : background(layer, options.background ?? color)
-
-        const m = {
-            top: options.margin?.top ?? 0,
-            bottom: options.margin?.bottom ?? 0,
-            left: options.margin?.left ?? 0,
-            right: options.margin?.right ?? 0,
-        }
-        const size = options.size || Button.size.Medium
-        const padding = 2
-
-        const base: BaseStyle = {
-            background: background_color,
-            corder_radius: Button.CORNER_RADIUS,
-            padding: {
-                top: padding,
-                bottom: padding,
-                left:
-                    options.shape === Button.shape.Rectangle
-                        ? padding + Button.RECTANGLE_PADDING
-                        : padding,
-                right:
-                    options.shape === Button.shape.Rectangle
-                        ? padding + Button.RECTANGLE_PADDING
-                        : padding,
-            },
-            margin: m,
-            button_height: 16,
-        }
-
-        return base
-    }
-}

styles/src/component/icon_button.ts πŸ”—

@@ -1,111 +0,0 @@
-import { interactive, toggleable } from "../element"
-import { background, foreground } from "../style_tree/components"
-import { useTheme, Theme, Layer } from "../theme"
-import { Button } from "./button"
-
-export type Margin = {
-    top: number
-    bottom: number
-    left: number
-    right: number
-}
-
-interface IconButtonOptions {
-    layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
-    color?: keyof Theme["lowest"]
-    background_color?: keyof Theme["lowest"]
-    margin?: Partial<Margin>
-    variant?: Button.Variant
-    size?: Button.Size
-}
-
-type ToggleableIconButtonOptions = IconButtonOptions & {
-    active_color?: keyof Theme["lowest"]
-    active_background_color?: keyof Theme["lowest"]
-    active_layer?: Layer
-    active_variant?: Button.Variant
-}
-
-export function icon_button(
-    { color, background_color, margin, layer, variant, size }: IconButtonOptions = {
-        variant: Button.variant.Default,
-        size: Button.size.Medium,
-    }
-) {
-    const theme = useTheme()
-
-    if (!color) color = "base"
-
-    const default_background =
-        variant === Button.variant.Ghost
-            ? null
-            : background(layer ?? theme.lowest, background_color ?? color)
-
-    const m = {
-        top: margin?.top ?? 0,
-        bottom: margin?.bottom ?? 0,
-        left: margin?.left ?? 0,
-        right: margin?.right ?? 0,
-    }
-
-    const padding = {
-        top: size === Button.size.Small ? 2 : 2,
-        bottom: size === Button.size.Small ? 2 : 2,
-        left: size === Button.size.Small ? 2 : 4,
-        right: size === Button.size.Small ? 2 : 4,
-    }
-
-    return interactive({
-        base: {
-            corner_radius: 6,
-            padding: padding,
-            margin: m,
-            icon_width: 14,
-            icon_height: 14,
-            button_width: size === Button.size.Small ? 16 : 20,
-            button_height: 14,
-        },
-        state: {
-            default: {
-                background: default_background,
-                color: foreground(layer ?? theme.lowest, color),
-            },
-            hovered: {
-                background: background(layer ?? theme.lowest, background_color ?? color, "hovered"),
-                color: foreground(layer ?? theme.lowest, color, "hovered"),
-            },
-            clicked: {
-                background: background(layer ?? theme.lowest, background_color ?? color, "pressed"),
-                color: foreground(layer ?? theme.lowest, color, "pressed"),
-            },
-        },
-    })
-}
-
-export function toggleable_icon_button({
-    color,
-    background_color,
-    active_color,
-    active_background_color,
-    active_variant,
-    margin,
-    variant,
-    size,
-    active_layer,
-}: ToggleableIconButtonOptions) {
-    if (!color) color = "base"
-
-    return toggleable({
-        state: {
-            inactive: icon_button({ color, background_color, margin, variant, size }),
-            active: icon_button({
-                color: active_color ? active_color : color,
-                background_color: active_background_color ? active_background_color : background_color,
-                margin,
-                layer: active_layer,
-                variant: active_variant || variant,
-                size,
-            }),
-        },
-    })
-}

styles/src/component/index.ts πŸ”—

@@ -1,6 +0,0 @@
-export * from "./icon_button"
-export * from "./indicator"
-export * from "./input"
-export * from "./tab"
-export * from "./tab_bar_button"
-export * from "./text_button"

styles/src/component/indicator.ts πŸ”—

@@ -1,15 +0,0 @@
-import { foreground } from "../style_tree/components"
-import { Layer, StyleSets } from "../theme"
-
-export const indicator = ({
-    layer,
-    color,
-}: {
-    layer: Layer
-    color: StyleSets
-}) => ({
-    corner_radius: 4,
-    padding: 4,
-    margin: { top: 12, left: 12 },
-    background: foreground(layer, color),
-})

styles/src/component/input.ts πŸ”—

@@ -1,23 +0,0 @@
-import { useTheme } from "../common"
-import { background, border, text } from "../style_tree/components"
-
-export const input = () => {
-    const theme = useTheme()
-
-    return {
-        background: background(theme.highest),
-        corner_radius: 8,
-        min_width: 200,
-        max_width: 500,
-        placeholder_text: text(theme.highest, "mono", "disabled"),
-        selection: theme.players[0],
-        text: text(theme.highest, "mono", "default"),
-        border: border(theme.highest),
-        padding: {
-            top: 3,
-            bottom: 3,
-            left: 12,
-            right: 8,
-        },
-    }
-}

styles/src/component/tab.ts πŸ”—

@@ -1,73 +0,0 @@
-import { Layer } from "../common"
-import { interactive, toggleable } from "../element"
-import { Border, text } from "../style_tree/components"
-
-type TabProps = {
-    layer: Layer
-}
-
-export const tab = ({ layer }: TabProps) => {
-    const active_color = text(layer, "sans", "base").color
-    const inactive_border: Border = {
-        color: "#FFFFFF00",
-        width: 1,
-        bottom: true,
-        left: false,
-        right: false,
-        top: false,
-    }
-    const active_border: Border = {
-        ...inactive_border,
-        color: active_color,
-    }
-
-    const base = {
-        ...text(layer, "sans", "variant"),
-        padding: {
-            top: 8,
-            left: 8,
-            right: 8,
-            bottom: 6,
-        },
-        border: inactive_border,
-    }
-
-    const i = interactive({
-        state: {
-            default: {
-                ...base,
-            },
-            hovered: {
-                ...base,
-                ...text(layer, "sans", "base", "hovered"),
-            },
-            clicked: {
-                ...base,
-                ...text(layer, "sans", "base", "pressed"),
-            },
-        },
-    })
-
-    return toggleable({
-        base: i,
-        state: {
-            active: {
-                default: {
-                    ...i,
-                    ...text(layer, "sans", "base"),
-                    border: active_border,
-                },
-                hovered: {
-                    ...i,
-                    ...text(layer, "sans", "base", "hovered"),
-                    border: active_border,
-                },
-                clicked: {
-                    ...i,
-                    ...text(layer, "sans", "base", "pressed"),
-                    border: active_border,
-                },
-            },
-        },
-    })
-}

styles/src/component/tab_bar_button.ts πŸ”—

@@ -1,58 +0,0 @@
-import { Theme, StyleSets } from "../common"
-import { interactive } from "../element"
-import { InteractiveState } from "../element/interactive"
-import { background, foreground } from "../style_tree/components"
-
-interface TabBarButtonOptions {
-    icon: string
-    color?: StyleSets
-}
-
-type TabBarButtonProps = TabBarButtonOptions & {
-    state?: Partial<Record<InteractiveState, Partial<TabBarButtonOptions>>>
-}
-
-export function tab_bar_button(
-    theme: Theme,
-    { icon, color = "base" }: TabBarButtonProps
-) {
-    const button_spacing = 8
-
-    return interactive({
-        base: {
-            icon: {
-                color: foreground(theme.middle, color),
-                asset: icon,
-                dimensions: {
-                    width: 15,
-                    height: 15,
-                },
-            },
-            container: {
-                corner_radius: 4,
-                padding: {
-                    top: 4,
-                    bottom: 4,
-                    left: 4,
-                    right: 4,
-                },
-                margin: {
-                    left: button_spacing / 2,
-                    right: button_spacing / 2,
-                },
-            },
-        },
-        state: {
-            hovered: {
-                container: {
-                    background: background(theme.middle, color, "hovered"),
-                },
-            },
-            clicked: {
-                container: {
-                    background: background(theme.middle, color, "pressed"),
-                },
-            },
-        },
-    })
-}

styles/src/component/text_button.ts πŸ”—

@@ -1,129 +0,0 @@
-import { interactive, toggleable } from "../element"
-import {
-    Border,
-    TextProperties,
-    background,
-    foreground,
-    text,
-} from "../style_tree/components"
-import { useTheme, Theme } from "../theme"
-import { Button } from "./button"
-import { Margin } from "./icon_button"
-
-interface TextButtonOptions {
-    layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
-    variant?: Button.Variant
-    color?: keyof Theme["lowest"]
-    margin?: Partial<Margin>
-    disabled?: boolean
-    text_properties?: TextProperties
-    border?: Border
-}
-
-type ToggleableTextButtonOptions = TextButtonOptions & {
-    active_color?: keyof Theme["lowest"]
-}
-
-export function text_button({
-    variant = Button.variant.Default,
-    color,
-    layer,
-    margin,
-    disabled,
-    text_properties,
-    border,
-}: TextButtonOptions = {}) {
-    const theme = useTheme()
-    if (!color) color = "base"
-
-    const background_color =
-        variant === Button.variant.Ghost
-            ? null
-            : background(layer ?? theme.lowest, color)
-
-    const text_options: TextProperties = {
-        size: "xs",
-        weight: "normal",
-        ...text_properties,
-    }
-
-    const m = {
-        top: margin?.top ?? 0,
-        bottom: margin?.bottom ?? 0,
-        left: margin?.left ?? 0,
-        right: margin?.right ?? 0,
-    }
-
-    return interactive({
-        base: {
-            corner_radius: 6,
-            padding: {
-                top: 1,
-                bottom: 1,
-                left: 6,
-                right: 6,
-            },
-            margin: m,
-            button_height: 22,
-            ...text(layer ?? theme.lowest, "sans", color, text_options),
-        },
-        state: {
-            default: {
-                border,
-                background: background_color,
-                color: disabled
-                    ? foreground(layer ?? theme.lowest, "disabled")
-                    : foreground(layer ?? theme.lowest, color),
-            },
-            hovered: disabled
-                ? {}
-                : {
-                    border,
-                    background: background(
-                        layer ?? theme.lowest,
-                        color,
-                        "hovered"
-                    ),
-                    color: foreground(
-                        layer ?? theme.lowest,
-                        color,
-                        "hovered"
-                    ),
-                },
-            clicked: disabled
-                ? {}
-                : {
-                    border,
-                    background: background(
-                        layer ?? theme.lowest,
-                        color,
-                        "pressed"
-                    ),
-                    color: foreground(
-                        layer ?? theme.lowest,
-                        color,
-                        "pressed"
-                    ),
-                },
-        },
-    })
-}
-
-export function toggleable_text_button(
-    theme: Theme,
-    { variant, color, active_color, margin }: ToggleableTextButtonOptions = {}
-) {
-    if (!color) color = "base"
-
-    return toggleable({
-        state: {
-            inactive: text_button({ variant, color, margin }),
-            active: text_button({
-                variant,
-                color: active_color ? active_color : color,
-                margin,
-                layer: theme.middle,
-            }),
-        },
-    })
-}

styles/src/element/index.ts πŸ”—

@@ -1,6 +0,0 @@
-import { interactive, Interactive } from "./interactive"
-import { toggleable, Toggleable } from "./toggle"
-
-export * from "./padding"
-export * from "./margin"
-export { interactive, Interactive, toggleable, Toggleable }

styles/src/element/interactive.test.ts πŸ”—

@@ -1,56 +0,0 @@
-import {
-    NOT_ENOUGH_STATES_ERROR,
-    NO_DEFAULT_OR_BASE_ERROR,
-    interactive,
-} from "./interactive"
-import { describe, it, expect } from "vitest"
-
-describe("interactive", () => {
-    it("creates an Interactive<Element> with base properties and states", () => {
-        const result = interactive({
-            base: { font_size: 10, color: "#FFFFFF" },
-            state: {
-                hovered: { color: "#EEEEEE" },
-                clicked: { color: "#CCCCCC" },
-            },
-        })
-
-        expect(result).toEqual({
-            default: { color: "#FFFFFF", font_size: 10 },
-            hovered: { color: "#EEEEEE", font_size: 10 },
-            clicked: { color: "#CCCCCC", font_size: 10 },
-        })
-    })
-
-    it("creates an Interactive<Element> with no base properties", () => {
-        const result = interactive({
-            state: {
-                default: { color: "#FFFFFF", font_size: 10 },
-                hovered: { color: "#EEEEEE" },
-                clicked: { color: "#CCCCCC" },
-            },
-        })
-
-        expect(result).toEqual({
-            default: { color: "#FFFFFF", font_size: 10 },
-            hovered: { color: "#EEEEEE", font_size: 10 },
-            clicked: { color: "#CCCCCC", font_size: 10 },
-        })
-    })
-
-    it("throws error when both default and base are missing", () => {
-        const state = {
-            hovered: { color: "blue" },
-        }
-
-        expect(() => interactive({ state })).toThrow(NO_DEFAULT_OR_BASE_ERROR)
-    })
-
-    it("throws error when no other state besides default is present", () => {
-        const state = {
-            default: { font_size: 10 },
-        }
-
-        expect(() => interactive({ state })).toThrow(NOT_ENOUGH_STATES_ERROR)
-    })
-})

styles/src/element/interactive.ts πŸ”—

@@ -1,97 +0,0 @@
-import merge from "ts-deepmerge"
-import { DeepPartial } from "utility-types"
-
-export type InteractiveState =
-    | "default"
-    | "hovered"
-    | "clicked"
-    | "selected"
-    | "disabled"
-
-export type Interactive<T> = {
-    default: T
-    hovered?: T
-    clicked?: T
-    selected?: T
-    disabled?: T
-}
-
-export const NO_DEFAULT_OR_BASE_ERROR =
-    "An interactive object must have a default state, or a base property."
-export const NOT_ENOUGH_STATES_ERROR =
-    "An interactive object must have a default and at least one other state."
-
-interface InteractiveProps<T> {
-    base?: T
-    state: Partial<Record<InteractiveState, DeepPartial<T>>>
-}
-
-/**
- * Helper function for creating Interactive<T> objects that works with Toggle<T>-like behavior.
- * It takes a default object to be used as the value for `default` field and fills out other fields
- * with fields from either `base` or from the `state` object which contains values for specific states.
- * Notably, it does not touch `hover`, `clicked`, `selected` and `disabled` states if there are no modifications for them.
- *
- * @param defaultObj Object to be used as the value for the `default` field.
- * @param base Optional object containing base fields to be included in the resulting object.
- * @param state Object containing optional modified fields to be included in the resulting object for each state.
- * @returns Interactive<T> object with fields from `base` and `state`.
- */
-export function interactive<T extends object>({
-    base,
-    state,
-}: InteractiveProps<T>): Interactive<T> {
-    if (!base && !state.default) throw new Error(NO_DEFAULT_OR_BASE_ERROR)
-
-    let default_state: T
-
-    if (state.default && base) {
-        default_state = merge(base, state.default) as T
-    } else {
-        default_state = base ? base : (state.default as T)
-    }
-
-    const interactive_obj: Interactive<T> = {
-        default: default_state,
-    }
-
-    let state_count = 0
-
-    if (state.hovered !== undefined) {
-        interactive_obj.hovered = merge(
-            interactive_obj.default,
-            state.hovered
-        ) as T
-        state_count++
-    }
-
-    if (state.clicked !== undefined) {
-        interactive_obj.clicked = merge(
-            interactive_obj.default,
-            state.clicked
-        ) as T
-        state_count++
-    }
-
-    if (state.selected !== undefined) {
-        interactive_obj.selected = merge(
-            interactive_obj.default,
-            state.selected
-        ) as T
-        state_count++
-    }
-
-    if (state.disabled !== undefined) {
-        interactive_obj.disabled = merge(
-            interactive_obj.default,
-            state.disabled
-        ) as T
-        state_count++
-    }
-
-    if (state_count < 1) {
-        throw new Error(NOT_ENOUGH_STATES_ERROR)
-    }
-
-    return interactive_obj
-}

styles/src/element/margin.ts πŸ”—

@@ -1,41 +0,0 @@
-type MarginOptions = {
-    all?: number
-    left?: number
-    right?: number
-    top?: number
-    bottom?: number
-}
-
-export type MarginStyle = {
-    top: number
-    bottom: number
-    left: number
-    right: number
-}
-
-export const margin_style = (options: MarginOptions): MarginStyle => {
-    const { all, top, bottom, left, right } = options
-
-    if (all !== undefined)
-        return {
-            top: all,
-            bottom: all,
-            left: all,
-            right: all,
-        }
-
-    if (
-        top === undefined &&
-        bottom === undefined &&
-        left === undefined &&
-        right === undefined
-    )
-        throw new Error("Margin must have at least one value")
-
-    return {
-        top: top || 0,
-        bottom: bottom || 0,
-        left: left || 0,
-        right: right || 0,
-    }
-}

styles/src/element/padding.ts πŸ”—

@@ -1,41 +0,0 @@
-type PaddingOptions = {
-    all?: number
-    left?: number
-    right?: number
-    top?: number
-    bottom?: number
-}
-
-export type PaddingStyle = {
-    top: number
-    bottom: number
-    left: number
-    right: number
-}
-
-export const padding_style = (options: PaddingOptions): PaddingStyle => {
-    const { all, top, bottom, left, right } = options
-
-    if (all !== undefined)
-        return {
-            top: all,
-            bottom: all,
-            left: all,
-            right: all,
-        }
-
-    if (
-        top === undefined &&
-        bottom === undefined &&
-        left === undefined &&
-        right === undefined
-    )
-        throw new Error("Padding must have at least one value")
-
-    return {
-        top: top || 0,
-        bottom: bottom || 0,
-        left: left || 0,
-        right: right || 0,
-    }
-}

styles/src/element/toggle.test.ts πŸ”—

@@ -1,52 +0,0 @@
-import {
-    NO_ACTIVE_ERROR,
-    NO_INACTIVE_OR_BASE_ERROR,
-    toggleable,
-} from "./toggle"
-import { describe, it, expect } from "vitest"
-
-describe("toggleable", () => {
-    it("creates a Toggleable<Element> with base properties and states", () => {
-        const result = toggleable({
-            base: { background: "#000000", color: "#CCCCCC" },
-            state: {
-                active: { color: "#FFFFFF" },
-            },
-        })
-
-        expect(result).toEqual({
-            inactive: { background: "#000000", color: "#CCCCCC" },
-            active: { background: "#000000", color: "#FFFFFF" },
-        })
-    })
-
-    it("creates a Toggleable<Element> with no base properties", () => {
-        const result = toggleable({
-            state: {
-                inactive: { background: "#000000", color: "#CCCCCC" },
-                active: { background: "#000000", color: "#FFFFFF" },
-            },
-        })
-
-        expect(result).toEqual({
-            inactive: { background: "#000000", color: "#CCCCCC" },
-            active: { background: "#000000", color: "#FFFFFF" },
-        })
-    })
-
-    it("throws error when both inactive and base are missing", () => {
-        const state = {
-            active: { background: "#000000", color: "#FFFFFF" },
-        }
-
-        expect(() => toggleable({ state })).toThrow(NO_INACTIVE_OR_BASE_ERROR)
-    })
-
-    it("throws error when no active state is present", () => {
-        const state = {
-            inactive: { background: "#000000", color: "#CCCCCC" },
-        }
-
-        expect(() => toggleable({ state })).toThrow(NO_ACTIVE_ERROR)
-    })
-})

styles/src/element/toggle.ts πŸ”—

@@ -1,47 +0,0 @@
-import merge from "ts-deepmerge"
-import { DeepPartial } from "utility-types"
-
-type ToggleState = "inactive" | "active"
-
-export type Toggleable<T> = Record<ToggleState, T>
-
-export const NO_INACTIVE_OR_BASE_ERROR =
-    "A toggleable object must have an inactive state, or a base property."
-export const NO_ACTIVE_ERROR = "A toggleable object must have an active state."
-
-interface ToggleableProps<T> {
-    base?: T
-    state: Partial<Record<ToggleState, DeepPartial<T>>>
-}
-
-/**
- * Helper function for creating Toggleable objects.
- * @template T The type of the object being toggled.
- * @param props Object containing the base (inactive) state and state modifications to create the active state.
- * @returns A Toggleable object containing both the inactive and active states.
- * @example
- * ```
- * toggleable({
- *   base: { background: "#000000", text: "#CCCCCC" },
- *   state: { active: { text: "#CCCCCC" } },
- * })
- * ```
- */
-export function toggleable<T extends object>(
-    props: ToggleableProps<T>
-): Toggleable<T> {
-    const { base, state } = props
-
-    if (!base && !state.inactive) throw new Error(NO_INACTIVE_OR_BASE_ERROR)
-    if (!state.active) throw new Error(NO_ACTIVE_ERROR)
-
-    const inactive_state = base
-        ? ((state.inactive ? merge(base, state.inactive) : base) as T)
-        : (state.inactive as T)
-
-    const toggle_obj: Toggleable<T> = {
-        inactive: inactive_state,
-        active: merge(base ?? {}, state.active) as T,
-    }
-    return toggle_obj
-}

styles/src/style_tree/app.ts πŸ”—

@@ -1,65 +0,0 @@
-import command_palette from "./command_palette"
-import project_panel from "./project_panel"
-import search from "./search"
-import picker from "./picker"
-import workspace from "./workspace"
-import context_menu from "./context_menu"
-import shared_screen from "./shared_screen"
-import project_diagnostics from "./project_diagnostics"
-import contact_notification from "./contact_notification"
-import update_notification from "./update_notification"
-import simple_message_notification from "./simple_message_notification"
-import project_shared_notification from "./project_shared_notification"
-import tooltip from "./tooltip"
-import terminal from "./terminal"
-import chat_panel from "./chat_panel"
-import notification_panel from "./notification_panel"
-import collab_panel from "./collab_panel"
-import toolbar_dropdown_menu from "./toolbar_dropdown_menu"
-import incoming_call_notification from "./incoming_call_notification"
-import welcome from "./welcome"
-import copilot from "./copilot"
-import assistant from "./assistant"
-import { titlebar } from "./titlebar"
-import editor from "./editor"
-import feedback from "./feedback"
-import component_test from "./component_test"
-import { useTheme } from "../common"
-
-export default function app(): any {
-    const theme = useTheme()
-
-    return {
-        meta: {
-            name: theme.name,
-            is_light: theme.is_light,
-        },
-        command_palette: command_palette(),
-        contact_notification: contact_notification(),
-        project_shared_notification: project_shared_notification(),
-        incoming_call_notification: incoming_call_notification(),
-        picker: picker(),
-        workspace: workspace(),
-        titlebar: titlebar(),
-        copilot: copilot(),
-        welcome: welcome(),
-        context_menu: context_menu(),
-        editor: editor(),
-        project_diagnostics: project_diagnostics(),
-        project_panel: project_panel(),
-        collab_panel: collab_panel(),
-        toolbar_dropdown_menu: toolbar_dropdown_menu(),
-        search: search(),
-        shared_screen: shared_screen(),
-        update_notification: update_notification(),
-        simple_message_notification: simple_message_notification(),
-        tooltip: tooltip(),
-        terminal: terminal(),
-        assistant: assistant(),
-        feedback: feedback(),
-        chat_panel: chat_panel(),
-        notification_panel: notification_panel(),
-        component_test: component_test(),
-        base_theme: theme,
-    }
-}

styles/src/style_tree/assistant.ts πŸ”—

@@ -1,398 +0,0 @@
-import { text, border, background, foreground, TextStyle } from "./components"
-import { Interactive, interactive, toggleable } from "../element"
-import { tab_bar_button } from "../component/tab_bar_button"
-import { StyleSets, useTheme } from "../theme"
-
-type RoleCycleButton = TextStyle & {
-    background?: string
-}
-// TODO: Replace these with zed types
-type RemainingTokens = TextStyle & {
-    background: string
-    margin: { top: number; right: number }
-    padding: {
-        right: number
-        left: number
-        top: number
-        bottom: number
-    }
-    corner_radius: number
-}
-
-export default function assistant(): any {
-    const theme = useTheme()
-
-    const interactive_role = (
-        color: StyleSets,
-    ): Interactive<RoleCycleButton> => {
-        return interactive({
-            base: {
-                ...text(theme.highest, "sans", color, { size: "sm" }),
-            },
-            state: {
-                hovered: {
-                    ...text(theme.highest, "sans", color, { size: "sm" }),
-                    background: background(theme.highest, color, "hovered"),
-                },
-                clicked: {
-                    ...text(theme.highest, "sans", color, { size: "sm" }),
-                    background: background(theme.highest, color, "pressed"),
-                },
-            },
-        })
-    }
-
-    const tokens_remaining = (color: StyleSets): RemainingTokens => {
-        return {
-            ...text(theme.highest, "mono", color, { size: "xs" }),
-            background: background(theme.highest, "on", "default"),
-            margin: { top: 12, right: 20 },
-            padding: { right: 4, left: 4, top: 1, bottom: 1 },
-            corner_radius: 6,
-        }
-    }
-
-    return {
-        container: {
-            background: background(theme.highest),
-            padding: { left: 12 },
-        },
-        inline: {
-            background: background(theme.highest),
-            margin: { top: 3, bottom: 3 },
-            border: border(theme.lowest, "on", {
-                top: true,
-                bottom: true,
-                overlay: true,
-            }),
-            editor: {
-                text: text(theme.highest, "mono", "default", { size: "sm" }),
-                placeholder_text: text(theme.highest, "sans", "on", "disabled"),
-                selection: theme.players[0],
-            },
-            disabled_editor: {
-                text: text(theme.highest, "mono", "disabled", { size: "sm" }),
-                placeholder_text: text(theme.highest, "sans", "on", "disabled"),
-                selection: {
-                    cursor: text(theme.highest, "mono", "disabled").color,
-                    selection: theme.players[0].selection,
-                },
-            },
-            pending_edit_background: background(theme.highest, "positive"),
-            context_status: {
-                error_icon: {
-                    margin: { left: 8, right: 18 },
-                    color: foreground(theme.highest, "negative"),
-                    width: 12,
-                },
-                in_progress_icon: {
-                    margin: { left: 8, right: 18 },
-                    color: foreground(theme.highest, "positive"),
-                    width: 12,
-                },
-                complete_icon: {
-                    margin: { left: 8, right: 18 },
-                    color: foreground(theme.highest, "positive"),
-                    width: 12,
-                },
-            },
-            retrieve_context: toggleable({
-                base: interactive({
-                    base: {
-                        icon_size: 12,
-                        color: foreground(theme.highest, "variant"),
-
-                        button_width: 12,
-                        background: background(theme.highest, "on"),
-                        corner_radius: 2,
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on"),
-                        },
-                        margin: { left: 2 },
-                        padding: {
-                            left: 4,
-                            right: 4,
-                            top: 4,
-                            bottom: 4,
-                        },
-                    },
-                    state: {
-                        hovered: {
-                            ...text(
-                                theme.highest,
-                                "mono",
-                                "variant",
-                                "hovered",
-                            ),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "hovered",
-                            ),
-                            border: {
-                                width: 1,
-                                color: background(
-                                    theme.highest,
-                                    "on",
-                                    "hovered",
-                                ),
-                            },
-                        },
-                        clicked: {
-                            ...text(
-                                theme.highest,
-                                "mono",
-                                "variant",
-                                "pressed",
-                            ),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "pressed",
-                            ),
-                            border: {
-                                width: 1,
-                                color: background(
-                                    theme.highest,
-                                    "on",
-                                    "pressed",
-                                ),
-                            },
-                        },
-                    },
-                }),
-                state: {
-                    active: {
-                        default: {
-                            icon_size: 12,
-                            button_width: 12,
-                            color: foreground(theme.highest, "variant"),
-                            background: background(theme.highest, "accent"),
-                            border: border(theme.highest, "accent"),
-                        },
-                        hovered: {
-                            background: background(
-                                theme.highest,
-                                "accent",
-                                "hovered",
-                            ),
-                            border: border(theme.highest, "accent", "hovered"),
-                        },
-                        clicked: {
-                            background: background(
-                                theme.highest,
-                                "accent",
-                                "pressed",
-                            ),
-                            border: border(theme.highest, "accent", "pressed"),
-                        },
-                    },
-                },
-            }),
-            include_conversation: toggleable({
-                base: interactive({
-                    base: {
-                        icon_size: 12,
-                        color: foreground(theme.highest, "variant"),
-
-                        button_width: 12,
-                        background: background(theme.highest, "on"),
-                        corner_radius: 2,
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on"),
-                        },
-                        padding: {
-                            left: 4,
-                            right: 4,
-                            top: 4,
-                            bottom: 4,
-                        },
-                    },
-                    state: {
-                        hovered: {
-                            ...text(
-                                theme.highest,
-                                "mono",
-                                "variant",
-                                "hovered",
-                            ),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "hovered",
-                            ),
-                            border: {
-                                width: 1,
-                                color: background(
-                                    theme.highest,
-                                    "on",
-                                    "hovered",
-                                ),
-                            },
-                        },
-                        clicked: {
-                            ...text(
-                                theme.highest,
-                                "mono",
-                                "variant",
-                                "pressed",
-                            ),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "pressed",
-                            ),
-                            border: {
-                                width: 1,
-                                color: background(
-                                    theme.highest,
-                                    "on",
-                                    "pressed",
-                                ),
-                            },
-                        },
-                    },
-                }),
-                state: {
-                    active: {
-                        default: {
-                            icon_size: 12,
-                            button_width: 12,
-                            color: foreground(theme.highest, "variant"),
-                            background: background(theme.highest, "accent"),
-                            border: border(theme.highest, "accent"),
-                        },
-                        hovered: {
-                            background: background(
-                                theme.highest,
-                                "accent",
-                                "hovered",
-                            ),
-                            border: border(theme.highest, "accent", "hovered"),
-                        },
-                        clicked: {
-                            background: background(
-                                theme.highest,
-                                "accent",
-                                "pressed",
-                            ),
-                            border: border(theme.highest, "accent", "pressed"),
-                        },
-                    },
-                },
-            }),
-        },
-        message_header: {
-            margin: { bottom: 4, top: 4 },
-            background: background(theme.highest),
-        },
-        hamburger_button: tab_bar_button(theme, {
-            icon: "icons/menu.svg",
-        }),
-
-        split_button: tab_bar_button(theme, {
-            icon: "icons/split_message.svg",
-        }),
-        quote_button: tab_bar_button(theme, {
-            icon: "icons/quote.svg",
-        }),
-        assist_button: tab_bar_button(theme, {
-            icon: "icons/magic-wand.svg",
-        }),
-        zoom_in_button: tab_bar_button(theme, {
-            icon: "icons/maximize.svg",
-        }),
-        zoom_out_button: tab_bar_button(theme, {
-            icon: "icons/minimize.svg",
-        }),
-        plus_button: tab_bar_button(theme, {
-            icon: "icons/plus.svg",
-        }),
-        title: {
-            ...text(theme.highest, "sans", "default", { size: "xs" }),
-        },
-        saved_conversation: {
-            container: interactive({
-                base: {
-                    background: background(theme.middle),
-                    padding: { top: 4, bottom: 4 },
-                    border: border(theme.middle, "default", {
-                        top: true,
-                        overlay: true,
-                    }),
-                },
-                state: {
-                    hovered: {
-                        background: background(theme.middle, "hovered"),
-                    },
-                    clicked: {
-                        background: background(theme.middle, "pressed"),
-                    },
-                },
-            }),
-            saved_at: {
-                margin: { left: 8 },
-                ...text(theme.highest, "sans", "variant", { size: "xs" }),
-            },
-            title: {
-                margin: { left: 12 },
-                ...text(theme.highest, "sans", "default", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-            },
-        },
-        user_sender: interactive_role("base"),
-        assistant_sender: interactive_role("accent"),
-        system_sender: interactive_role("warning"),
-        sent_at: {
-            margin: { top: 2, left: 8 },
-            ...text(theme.highest, "sans", "variant", { size: "2xs" }),
-        },
-        model: interactive({
-            base: {
-                background: background(theme.highest),
-                margin: { left: 12, right: 4, top: 12 },
-                padding: { right: 4, left: 4, top: 1, bottom: 1 },
-                corner_radius: 4,
-                ...text(theme.highest, "sans", "default", { size: "xs" }),
-            },
-            state: {
-                hovered: {
-                    background: background(theme.highest, "on", "hovered"),
-                    border: border(theme.highest, "on", { overlay: true }),
-                },
-            },
-        }),
-        remaining_tokens: tokens_remaining("positive"),
-        low_remaining_tokens: tokens_remaining("warning"),
-        no_remaining_tokens: tokens_remaining("negative"),
-        error_icon: {
-            margin: { left: 8 },
-            color: foreground(theme.highest, "negative"),
-            width: 12,
-        },
-        api_key_editor: {
-            background: background(theme.highest, "on"),
-            corner_radius: 4,
-            text: text(theme.highest, "mono", "on"),
-            placeholder_text: text(theme.highest, "mono", "on", "disabled", {
-                size: "xs",
-            }),
-            selection: theme.players[0],
-            border: border(theme.highest, "on"),
-            padding: {
-                bottom: 4,
-                left: 8,
-                right: 8,
-                top: 4,
-            },
-        },
-        api_key_prompt: {
-            padding: 10,
-            ...text(theme.highest, "sans", "default", { size: "xs" }),
-        },
-    }
-}

styles/src/style_tree/chat_panel.ts πŸ”—

@@ -1,160 +0,0 @@
-import { background, border, foreground, text } from "./components"
-import { icon_button } from "../component/icon_button"
-import { useTheme, with_opacity } from "../theme"
-import { interactive } from "../element"
-
-export default function chat_panel(): any {
-    const theme = useTheme()
-    const layer = theme.middle
-
-    const SPACING = 12 as const
-
-    const channel_name = {
-        padding: {
-            left: SPACING,
-            right: SPACING,
-            top: 4,
-            bottom: 4,
-        },
-        hash: {
-            ...text(layer, "sans", "base"),
-        },
-        name: text(layer, "sans", "base"),
-    }
-
-    return {
-        background: background(layer),
-        avatar: {
-            icon_width: 24,
-            icon_height: 24,
-            corner_radius: 4,
-            outer_width: 24,
-            outer_corner_radius: 16,
-        },
-        avatar_container: {
-            padding: {
-                right: 6,
-                left: 2,
-                top: 2,
-                bottom: 2,
-            },
-        },
-        list: {},
-        channel_select: {
-            header: {
-                ...channel_name,
-                border: border(layer, { bottom: true }),
-            },
-            item: channel_name,
-            active_item: {
-                ...channel_name,
-                background: background(layer, "on", "active"),
-            },
-            hovered_item: {
-                ...channel_name,
-                background: background(layer, "on", "hovered"),
-            },
-            menu: {
-                background: background(layer, "on"),
-                border: border(layer, { bottom: true }),
-            },
-        },
-        icon_button: icon_button({
-            variant: "ghost",
-            color: "variant",
-            size: "sm",
-        }),
-        input_editor: {
-            background: background(layer, "on"),
-            corner_radius: 6,
-            text: text(layer, "sans", "base"),
-            placeholder_text: text(layer, "sans", "base", "disabled", {
-                size: "xs",
-            }),
-            selection: theme.players[0],
-            border: border(layer, "on"),
-            margin: {
-                left: SPACING,
-                right: SPACING,
-                bottom: SPACING,
-            },
-            padding: {
-                bottom: 4,
-                left: 8,
-                right: 8,
-                top: 4,
-            },
-        },
-
-        rich_text: {
-            text: text(layer, "sans", "base"),
-            code_background: with_opacity(foreground(layer, "accent"), 0.1),
-            mention_highlight: { weight: "bold" },
-            self_mention_highlight: { weight: "bold" },
-            self_mention_background: background(layer, "active"),
-        },
-        message_sender: {
-            margin: {
-                right: 8,
-            },
-            ...text(layer, "sans", "base", { weight: "bold" }),
-        },
-        message_timestamp: text(layer, "sans", "base", "disabled"),
-        message: {
-            ...interactive({
-                base: {
-                    margin: { top: SPACING },
-                    padding: {
-                        top: 4,
-                        bottom: 4,
-                        left: SPACING / 2,
-                        right: SPACING / 3,
-                    },
-                },
-                state: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-            }),
-        },
-        last_message_bottom_spacing: SPACING,
-        continuation_message: {
-            ...interactive({
-                base: {
-                    padding: {
-                        top: 4,
-                        bottom: 4,
-                        left: SPACING / 2,
-                        right: SPACING / 3,
-                    },
-                },
-                state: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-            }),
-        },
-        pending_message: {
-            ...interactive({
-                base: {
-                    padding: {
-                        top: 4,
-                        bottom: 4,
-                        left: SPACING / 2,
-                        right: SPACING / 3,
-                    },
-                },
-                state: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-            }),
-        },
-        sign_in_prompt: {
-            default: text(layer, "sans", "base"),
-        },
-    }
-}

styles/src/style_tree/collab_modals.ts πŸ”—

@@ -1,176 +0,0 @@
-import { StyleSets, useTheme } from "../theme"
-import { background, border, foreground, text } from "./components"
-import picker from "./picker"
-import { input } from "../component/input"
-import contact_finder from "./contact_finder"
-import { tab } from "../component/tab"
-import { icon_button } from "../component/icon_button"
-import { interactive } from "../element/interactive"
-
-export default function channel_modal(): any {
-    const theme = useTheme()
-
-    const SPACING = 12 as const
-    const BUTTON_OFFSET = 6 as const
-    const ITEM_HEIGHT = 36 as const
-
-    const contact_button = {
-        background: background(theme.middle, "variant"),
-        color: foreground(theme.middle, "variant"),
-        icon_width: 8,
-        button_width: 16,
-        corner_radius: 8,
-    }
-
-    const picker_style = picker()
-    delete picker_style.shadow
-    delete picker_style.border
-
-    const picker_input = input()
-
-    const interactive_text = (styleset: StyleSets) =>
-        interactive({
-            base: {
-                padding: {
-                    left: 8,
-                    top: 8
-                },
-                ...text(theme.middle, "sans", styleset, "default"),
-            }, state: {
-                hovered: {
-                    ...text(theme.middle, "sans", styleset, "hovered"),
-                },
-                clicked: {
-                    ...text(theme.middle, "sans", styleset, "active"),
-                }
-            }
-        })
-
-    const member_icon_style = icon_button({
-        variant: "ghost",
-        size: "sm",
-    }).default
-
-    return {
-        contact_finder: contact_finder(),
-        tabbed_modal: {
-            tab_button: tab({ layer: theme.middle }),
-            row_height: ITEM_HEIGHT,
-            header: {
-                background: background(theme.lowest),
-                border: border(theme.middle, {
-                    bottom: true,
-                    top: false,
-                    left: false,
-                    right: false,
-                }),
-                padding: {
-                    top: SPACING,
-                    left: SPACING - BUTTON_OFFSET,
-                    right: SPACING - BUTTON_OFFSET,
-                },
-                corner_radii: {
-                    top_right: 12,
-                    top_left: 12,
-                },
-            },
-            body: {
-                background: background(theme.middle),
-                padding: {
-                    top: SPACING - 4,
-                    left: SPACING,
-                    right: SPACING,
-                    bottom: SPACING,
-                },
-                corner_radii: {
-                    bottom_right: 12,
-                    bottom_left: 12,
-                },
-            },
-            modal: {
-                background: background(theme.middle),
-                shadow: theme.modal_shadow,
-                corner_radius: 12,
-                padding: {
-                    bottom: 0,
-                    left: 0,
-                    right: 0,
-                    top: 0,
-                },
-            },
-            // FIXME: due to a bug in the picker's size calculation, this must be 600
-            max_height: 600,
-            max_width: 540,
-            title: {
-                ...text(theme.middle, "sans", "on", { size: "lg" }),
-                padding: {
-                    left: BUTTON_OFFSET,
-                },
-            },
-            visibility_toggle: interactive_text("base"),
-            channel_link: interactive_text("accent"),
-            picker: {
-                empty_container: {},
-                item: {
-                    ...picker_style.item,
-                    margin: { left: SPACING, right: SPACING },
-                },
-                no_matches: picker_style.no_matches,
-                input_editor: picker_input,
-                empty_input_editor: picker_input,
-                header: picker_style.header,
-                footer: picker_style.footer,
-            },
-        },
-        channel_modal: {
-            // This is used for the icons that are rendered to the right of channel Members in both UIs
-            member_icon: member_icon_style,
-            // This is used for the icons that are rendered to the right of channel invites in both UIs
-            invitee_icon: member_icon_style,
-            remove_member_button: {
-                ...text(theme.middle, "sans", { size: "xs" }),
-                background: background(theme.middle),
-                padding: {
-                    left: 7,
-                    right: 7,
-                },
-            },
-            cancel_invite_button: {
-                ...text(theme.middle, "sans", { size: "xs" }),
-                background: background(theme.middle),
-            },
-            member_tag: {
-                ...text(theme.middle, "sans", { size: "xs" }),
-                border: border(theme.middle, "active"),
-                background: background(theme.middle),
-                margin: {
-                    left: 8,
-                },
-                padding: {
-                    left: 4,
-                    right: 4,
-                },
-            },
-            contact_avatar: {
-                corner_radius: 10,
-                width: 18,
-            },
-            contact_username: {
-                padding: {
-                    left: 8,
-                },
-            },
-            contact_button: {
-                ...contact_button,
-                hover: {
-                    background: background(theme.middle, "variant", "hovered"),
-                },
-            },
-            disabled_contact_button: {
-                ...contact_button,
-                background: background(theme.middle, "disabled"),
-                color: foreground(theme.middle, "disabled"),
-            },
-        },
-    }
-}

styles/src/style_tree/collab_panel.ts πŸ”—

@@ -1,427 +0,0 @@
-import {
-    background,
-    border,
-    border_color,
-    foreground,
-    text,
-} from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-import collab_modals from "./collab_modals"
-import { icon_button, toggleable_icon_button } from "../component/icon_button"
-import { indicator } from "../component/indicator"
-
-export default function contacts_panel(): any {
-    const theme = useTheme()
-
-    const CHANNEL_SPACING = 4 as const
-    const NAME_MARGIN = 6 as const
-    const SPACING = 12 as const
-    const INDENT_SIZE = 8 as const
-    const ITEM_HEIGHT = 28 as const
-
-    const layer = theme.middle
-
-    const contact_button = {
-        background: background(layer, "on"),
-        color: foreground(layer, "on"),
-        icon_width: 14,
-        button_width: 16,
-        corner_radius: 8,
-    }
-
-    const project_row = {
-        guest_avatar_spacing: 4,
-        height: 24,
-        guest_avatar: {
-            corner_radius: 8,
-            width: 14,
-        },
-        name: {
-            ...text(layer, "sans", { size: "sm" }),
-            margin: {
-                left: NAME_MARGIN,
-                right: 4,
-            },
-        },
-        guests: {
-            margin: {
-                left: NAME_MARGIN,
-                right: NAME_MARGIN,
-            },
-        },
-        padding: {
-            left: SPACING,
-            right: SPACING,
-        },
-    }
-
-    const icon_style = {
-        color: foreground(layer, "variant"),
-        width: 14,
-    }
-
-    const header_icon_button = toggleable_icon_button({
-        variant: "ghost",
-        size: "sm",
-        active_layer: theme.lowest,
-    })
-
-    const subheader_row = toggleable({
-        base: interactive({
-            base: {
-                ...text(layer, "sans", { size: "sm" }),
-                padding: {
-                    left: SPACING,
-                    right: SPACING,
-                },
-            },
-            state: {
-                hovered: {
-                    background: background(layer, "hovered"),
-                },
-                clicked: {
-                    background: background(layer, "pressed"),
-                },
-            },
-        }),
-        state: {
-            active: {
-                default: {
-                    ...text(theme.lowest, "sans", { size: "sm" }),
-                    background: background(theme.lowest),
-                },
-                clicked: {
-                    background: background(layer, "pressed"),
-                },
-            },
-        },
-    })
-
-    const filter_input = {
-        background: background(layer, "on"),
-        corner_radius: 6,
-        text: text(layer, "sans", "base"),
-        placeholder_text: text(layer, "sans", "base", "disabled", {
-            size: "xs",
-        }),
-        selection: theme.players[0],
-        border: border(layer, "on"),
-        padding: {
-            bottom: 4,
-            left: 8,
-            right: 8,
-            top: 4,
-        },
-        margin: {
-            left: SPACING,
-            right: SPACING,
-        },
-    }
-
-    const item_row = toggleable({
-        base: interactive({
-            base: {
-                padding: {
-                    left: SPACING,
-                    right: SPACING,
-                },
-            },
-            state: {
-                clicked: {
-                    background: background(layer, "pressed"),
-                },
-            },
-        }),
-        state: {
-            inactive: {
-                hovered: {
-                    background: background(layer, "hovered"),
-                },
-            },
-            active: {
-                default: {
-                    ...text(theme.lowest, "sans", { size: "sm" }),
-                    background: background(theme.lowest),
-                },
-                clicked: {
-                    background: background(layer, "pressed"),
-                },
-            },
-        },
-    })
-
-    return {
-        ...collab_modals(),
-        disclosure: {
-            button: icon_button({ variant: "ghost", size: "sm" }),
-            spacing: CHANNEL_SPACING,
-        },
-        log_in_button: interactive({
-            base: {
-                background: background(theme.middle),
-                border: border(theme.middle, "active"),
-                corner_radius: 4,
-                margin: {
-                    top: 4,
-                    left: 16,
-                    right: 16,
-                },
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 7,
-                    right: 7,
-                },
-                ...text(theme.middle, "sans", "default", { size: "sm" }),
-            },
-            state: {
-                hovered: {
-                    ...text(theme.middle, "sans", "default", { size: "sm" }),
-                    background: background(theme.middle, "hovered"),
-                    border: border(theme.middle, "active"),
-                },
-                clicked: {
-                    ...text(theme.middle, "sans", "default", { size: "sm" }),
-                    background: background(theme.middle, "pressed"),
-                    border: border(theme.middle, "active"),
-                },
-            },
-        }),
-        background: background(layer),
-        padding: {
-            top: SPACING,
-        },
-        user_query_editor: filter_input,
-        channel_hash: icon_style,
-        channel_note_active_color: foreground(layer, "active"),
-        user_query_editor_height: 33,
-        add_contact_button: header_icon_button,
-        add_channel_button: header_icon_button,
-        leave_call_button: header_icon_button,
-        row_height: ITEM_HEIGHT,
-        channel_indent: INDENT_SIZE * 2 + 2,
-        section_icon_size: 14,
-        header_row: {
-            ...text(layer, "sans", { size: "sm", weight: "bold" }),
-            margin: { top: SPACING },
-            padding: {
-                left: SPACING,
-                right: SPACING,
-            },
-        },
-        dragged_over_header: {
-            margin: { top: SPACING },
-            padding: {
-                left: SPACING,
-                right: SPACING,
-            },
-            background: background(layer, "hovered"),
-        },
-        subheader_row,
-        leave_call: interactive({
-            base: {
-                background: background(layer),
-                border: border(layer),
-                corner_radius: 6,
-                margin: {
-                    top: 1,
-                },
-                padding: {
-                    top: 1,
-                    bottom: 1,
-                    left: 7,
-                    right: 7,
-                },
-                ...text(layer, "sans", "variant", { size: "xs" }),
-            },
-            state: {
-                hovered: {
-                    ...text(layer, "sans", "hovered", { size: "xs" }),
-                    background: background(layer, "hovered"),
-                    border: border(layer, "hovered"),
-                },
-            },
-        }),
-        contact_row: toggleable({
-            base: interactive({
-                base: {
-                    padding: {
-                        left: SPACING,
-                        right: SPACING,
-                    },
-                },
-                state: {
-                    clicked: {
-                        background: background(layer, "pressed"),
-                    },
-                },
-            }),
-            state: {
-                inactive: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-                active: {
-                    default: {
-                        ...text(theme.lowest, "sans", { size: "sm" }),
-                        background: background(theme.lowest),
-                    },
-                    clicked: {
-                        background: background(layer, "pressed"),
-                    },
-                },
-            },
-        }),
-        channel_row: item_row,
-        channel_name: {
-            active: {
-                ...text(layer, "sans", { size: "sm", weight: "bold" }),
-                margin: {
-                    left: CHANNEL_SPACING,
-                },
-            },
-            inactive: {
-                ...text(layer, "sans", { size: "sm" }),
-                margin: {
-                    left: CHANNEL_SPACING,
-                },
-            },
-        },
-        list_empty_label_container: {
-            margin: {
-                left: NAME_MARGIN,
-            },
-        },
-        list_empty_icon: {
-            color: foreground(layer, "variant"),
-            width: 14,
-        },
-        list_empty_state: toggleable({
-            base: interactive({
-                base: {
-                    ...text(layer, "sans", "variant", { size: "sm" }),
-                    padding: {
-                        top: SPACING / 2,
-                        bottom: SPACING / 2,
-                        left: SPACING,
-                        right: SPACING,
-                    },
-                },
-                state: {
-                    clicked: {
-                        background: background(layer, "pressed"),
-                    },
-                },
-            }),
-            state: {
-                inactive: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-                active: {
-                    default: {
-                        ...text(theme.lowest, "sans", { size: "sm" }),
-                        background: background(theme.lowest),
-                    },
-                    clicked: {
-                        background: background(layer, "pressed"),
-                    },
-                },
-            },
-        }),
-        contact_avatar: {
-            corner_radius: 10,
-            width: 20,
-        },
-        channel_avatar: {
-            corner_radius: 10,
-            width: 20,
-        },
-        extra_participant_label: {
-            corner_radius: 10,
-            padding: {
-                left: 10,
-                right: 4,
-            },
-            background: background(layer, "hovered"),
-            ...text(layer, "sans", "hovered", { size: "xs" }),
-        },
-        contact_status_free: indicator({ layer, color: "positive" }),
-        contact_status_busy: indicator({ layer, color: "negative" }),
-        contact_username: {
-            ...text(layer, "sans", { size: "sm" }),
-            margin: {
-                left: NAME_MARGIN,
-            },
-        },
-        contact_button_spacing: NAME_MARGIN,
-        contact_button: icon_button({
-            variant: "ghost",
-            color: "variant",
-            size: "sm",
-        }),
-        disabled_button: {
-            ...contact_button,
-            background: background(layer, "on"),
-            color: foreground(layer, "on"),
-        },
-        calling_indicator: {
-            ...text(layer, "sans", "variant", { size: "xs" }),
-        },
-        tree_branch: toggleable({
-            base: interactive({
-                base: {
-                    color: border_color(layer),
-                    width: 1,
-                },
-                state: {
-                    hovered: {
-                        color: border_color(layer),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        color: border_color(layer),
-                    },
-                },
-            },
-        }),
-        project_row: toggleable({
-            base: interactive({
-                base: {
-                    ...project_row,
-                    icon: {
-                        margin: { left: NAME_MARGIN },
-                        color: foreground(layer, "variant"),
-                        width: 14,
-                    },
-                    name: {
-                        ...project_row.name,
-                        ...text(layer, "sans", { size: "sm" }),
-                    },
-                },
-                state: {
-                    hovered: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: { background: background(theme.lowest) },
-                },
-            },
-        }),
-        face_overlap: 8,
-        channel_editor: {
-            padding: {
-                left: NAME_MARGIN,
-            },
-        },
-    }
-}

styles/src/style_tree/command_palette.ts πŸ”—

@@ -1,46 +0,0 @@
-import { with_opacity } from "../theme/color"
-import { text, background } from "./components"
-import { toggleable } from "../element"
-import { useTheme } from "../theme"
-
-export default function command_palette(): any {
-    const theme = useTheme()
-
-    const key = toggleable({
-        base: {
-            text: text(theme.highest, "mono", "variant", "default", {
-                size: "xs",
-            }),
-            corner_radius: 2,
-            background: background(theme.highest, "on"),
-            padding: {
-                top: 1,
-                bottom: 1,
-                left: 6,
-                right: 6,
-            },
-            margin: {
-                top: 1,
-                bottom: 1,
-                left: 2,
-            },
-        },
-        state: {
-            active: {
-                text: text(theme.highest, "mono", "on", "default", {
-                    size: "xs",
-                }),
-                background: with_opacity(background(theme.highest, "on"), 0.2),
-            },
-        },
-    })
-
-    return {
-        keystroke_spacing: 8,
-        // TODO: This should be a Toggle<ContainedText> on the rust side so we don't have to do this
-        key: {
-            inactive: { ...key.inactive },
-            active: key.active,
-        },
-    }
-}

styles/src/style_tree/component_test.ts πŸ”—

@@ -1,27 +0,0 @@
-import { useTheme } from "../common"
-import { text_button } from "../component/text_button"
-import { icon_button } from "../component/icon_button"
-import { text } from "./components"
-import { toggleable } from "../element"
-
-export default function contacts_panel(): any {
-    const theme = useTheme()
-
-    return {
-        button: text_button({}),
-        toggle: toggleable({
-            base: text_button({}),
-            state: {
-                active: {
-                    ...text_button({ color: "accent" }),
-                },
-            },
-        }),
-        disclosure: {
-            ...text(theme.lowest, "sans", "base"),
-            button: icon_button({ variant: "ghost" }),
-            spacing: 4,
-            padding: 4,
-        },
-    }
-}

styles/src/style_tree/components.ts πŸ”—

@@ -1,302 +0,0 @@
-import { font_families, font_sizes, FontWeight } from "../common"
-import { Layer, Styles, StyleSets, Style } from "../theme/create_theme"
-
-function is_style_set(key: any): key is StyleSets {
-    return [
-        "base",
-        "variant",
-        "on",
-        "accent",
-        "positive",
-        "warning",
-        "negative",
-    ].includes(key)
-}
-
-function is_style(key: any): key is Styles {
-    return [
-        "default",
-        "active",
-        "disabled",
-        "hovered",
-        "pressed",
-        "inverted",
-    ].includes(key)
-}
-function get_style(
-    layer: Layer,
-    possible_style_set_or_style?: any,
-    possible_style?: any
-): Style {
-    let style_set: StyleSets = "base"
-    let style: Styles = "default"
-    if (is_style_set(possible_style_set_or_style)) {
-        style_set = possible_style_set_or_style
-    } else if (is_style(possible_style_set_or_style)) {
-        style = possible_style_set_or_style
-    }
-
-    if (is_style(possible_style)) {
-        style = possible_style
-    }
-
-    return layer[style_set][style]
-}
-
-export function background(layer: Layer, style?: Styles): string
-export function background(
-    layer: Layer,
-    style_set?: StyleSets,
-    style?: Styles
-): string
-export function background(
-    layer: Layer,
-    style_set_or_styles?: StyleSets | Styles,
-    style?: Styles
-): string {
-    return get_style(layer, style_set_or_styles, style).background
-}
-
-export function border_color(layer: Layer, style?: Styles): string
-export function border_color(
-    layer: Layer,
-    style_set?: StyleSets,
-    style?: Styles
-): string
-export function border_color(
-    layer: Layer,
-    style_set_or_styles?: StyleSets | Styles,
-    style?: Styles
-): string {
-    return get_style(layer, style_set_or_styles, style).border
-}
-
-export function foreground(layer: Layer, style?: Styles): string
-export function foreground(
-    layer: Layer,
-    style_set?: StyleSets,
-    style?: Styles
-): string
-export function foreground(
-    layer: Layer,
-    style_set_or_styles?: StyleSets | Styles,
-    style?: Styles
-): string {
-    return get_style(layer, style_set_or_styles, style).foreground
-}
-
-export interface TextStyle extends Object {
-    family: keyof typeof font_families
-    color: string
-    size: number
-    weight?: FontWeight
-    underline?: boolean
-}
-
-export interface TextProperties {
-    size?: keyof typeof font_sizes
-    weight?: FontWeight
-    underline?: boolean
-    color?: string
-    features?: FontFeatures
-}
-
-interface FontFeatures {
-    /** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
-    calt?: boolean
-    /** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
-    case?: boolean
-    /** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
-    cpsp?: boolean
-    /** Fractions: Replaces figures separated by a slash with diagonal fractions */
-    frac?: boolean
-    /** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
-    liga?: boolean
-    /** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
-    onum?: boolean
-    /** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
-    ordn?: boolean
-    /** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
-    pnum?: boolean
-    /** Stylistic set 01 */
-    ss01?: boolean
-    /** Stylistic set 02 */
-    ss02?: boolean
-    /** Stylistic set 03 */
-    ss03?: boolean
-    /** Stylistic set 04 */
-    ss04?: boolean
-    /** Stylistic set 05 */
-    ss05?: boolean
-    /** Stylistic set 06 */
-    ss06?: boolean
-    /** Stylistic set 07 */
-    ss07?: boolean
-    /** Stylistic set 08 */
-    ss08?: boolean
-    /** Stylistic set 09 */
-    ss09?: boolean
-    /** Stylistic set 10 */
-    ss10?: boolean
-    /** Stylistic set 11 */
-    ss11?: boolean
-    /** Stylistic set 12 */
-    ss12?: boolean
-    /** Stylistic set 13 */
-    ss13?: boolean
-    /** Stylistic set 14 */
-    ss14?: boolean
-    /** Stylistic set 15 */
-    ss15?: boolean
-    /** Stylistic set 16 */
-    ss16?: boolean
-    /** Stylistic set 17 */
-    ss17?: boolean
-    /** Stylistic set 18 */
-    ss18?: boolean
-    /** Stylistic set 19 */
-    ss19?: boolean
-    /** Stylistic set 20 */
-    ss20?: boolean
-    /** Subscript: Replaces default glyphs with subscript glyphs */
-    subs?: boolean
-    /** Superscript: Replaces default glyphs with superscript glyphs */
-    sups?: boolean
-    /** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
-    swsh?: boolean
-    /** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
-    titl?: boolean
-    /** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
-    tnum?: boolean
-    /** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
-    zero?: boolean
-}
-
-export function text(
-    layer: Layer,
-    font_family: keyof typeof font_families,
-    style_set: StyleSets,
-    style: Styles,
-    properties?: TextProperties
-): TextStyle
-export function text(
-    layer: Layer,
-    font_family: keyof typeof font_families,
-    style_set: StyleSets,
-    properties?: TextProperties
-): TextStyle
-export function text(
-    layer: Layer,
-    font_family: keyof typeof font_families,
-    style: Styles,
-    properties?: TextProperties
-): TextStyle
-export function text(
-    layer: Layer,
-    font_family: keyof typeof font_families,
-    properties?: TextProperties
-): TextStyle
-export function text(
-    layer: Layer,
-    font_family: keyof typeof font_families,
-    style_set_style_or_properties?: StyleSets | Styles | TextProperties,
-    style_or_properties?: Styles | TextProperties,
-    properties?: TextProperties
-) {
-    const style = get_style(
-        layer,
-        style_set_style_or_properties,
-        style_or_properties
-    )
-
-    if (typeof style_set_style_or_properties === "object") {
-        properties = style_set_style_or_properties
-    }
-    if (typeof style_or_properties === "object") {
-        properties = style_or_properties
-    }
-
-    const size = font_sizes[properties?.size || "sm"]
-    const color = properties?.color || style.foreground
-
-    return {
-        family: font_families[font_family],
-        ...properties,
-        color,
-        size,
-    }
-}
-
-export interface Border {
-    color: string
-    width: number
-    top?: boolean
-    bottom?: boolean
-    left?: boolean
-    right?: boolean
-    overlay?: boolean
-}
-
-export interface BorderProperties {
-    width?: number
-    top?: boolean
-    bottom?: boolean
-    left?: boolean
-    right?: boolean
-    overlay?: boolean
-}
-
-export function border(
-    layer: Layer,
-    style_set: StyleSets,
-    style: Styles,
-    properties?: BorderProperties
-): Border
-export function border(
-    layer: Layer,
-    style_set: StyleSets,
-    properties?: BorderProperties
-): Border
-export function border(
-    layer: Layer,
-    style: Styles,
-    properties?: BorderProperties
-): Border
-export function border(layer: Layer, properties?: BorderProperties): Border
-export function border(
-    layer: Layer,
-    style_set_or_properties?: StyleSets | Styles | BorderProperties,
-    style_or_properties?: Styles | BorderProperties,
-    properties?: BorderProperties
-): Border {
-    const style = get_style(layer, style_set_or_properties, style_or_properties)
-
-    if (typeof style_set_or_properties === "object") {
-        properties = style_set_or_properties
-    }
-    if (typeof style_or_properties === "object") {
-        properties = style_or_properties
-    }
-
-    return {
-        color: style.border,
-        width: 1,
-        ...properties,
-    }
-}
-
-export function svg(
-    color: string,
-    asset: string,
-    width: number,
-    height: number
-) {
-    return {
-        color,
-        asset,
-        dimensions: {
-            width,
-            height,
-        },
-    }
-}

styles/src/style_tree/contact_finder.ts πŸ”—

@@ -1,74 +0,0 @@
-// import picker from "./picker"
-import { background, border, foreground, text } from "./components"
-import { useTheme } from "../theme"
-
-export default function contact_finder(): any {
-    const theme = useTheme()
-
-    // const side_margin = 6
-    const contact_button = {
-        background: background(theme.middle, "variant"),
-        color: foreground(theme.middle, "variant"),
-        icon_width: 8,
-        button_width: 16,
-        corner_radius: 8,
-    }
-
-    // const picker_style = picker()
-    // const picker_input = {
-    //     background: background(theme.middle, "on"),
-    //     corner_radius: 6,
-    //     text: text(theme.middle, "mono"),
-    //     placeholder_text: text(theme.middle, "mono", "on", "disabled", {
-    //         size: "xs",
-    //     }),
-    //     selection: theme.players[0],
-    //     border: border(theme.middle),
-    //     padding: {
-    //         bottom: 4,
-    //         left: 8,
-    //         right: 8,
-    //         top: 4,
-    //     },
-    //     margin: {
-    //         left: side_margin,
-    //         right: side_margin,
-    //     },
-    // }
-
-    return {
-        // picker: {
-        //     empty_container: {},
-        //     item: {
-        //         ...picker_style.item,
-        //         margin: { left: side_margin, right: side_margin },
-        //     },
-        //     no_matches: picker_style.no_matches,
-        //     input_editor: picker_input,
-        //     empty_input_editor: picker_input,
-        //     header: picker_style.header,
-        //     footer: picker_style.footer,
-        // },
-        // row_height: 28,
-        contact_avatar: {
-            corner_radius: 10,
-            width: 18,
-        },
-        contact_username: {
-            padding: {
-                left: 8,
-            },
-        },
-        contact_button: {
-            ...contact_button,
-            hover: {
-                background: background(theme.middle, "variant", "hovered"),
-            },
-        },
-        disabled_contact_button: {
-            ...contact_button,
-            background: background(theme.middle, "disabled"),
-            color: foreground(theme.middle, "disabled"),
-        },
-    }
-}

styles/src/style_tree/contact_notification.ts πŸ”—

@@ -1,55 +0,0 @@
-import { background, foreground, text } from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-
-export default function contact_notification(): any {
-    const theme = useTheme()
-
-    const avatar_size = 12
-    const header_padding = 8
-
-    return {
-        header_avatar: {
-            height: avatar_size,
-            width: avatar_size,
-            corner_radius: 6,
-        },
-        header_message: {
-            ...text(theme.lowest, "sans", { size: "xs" }),
-            margin: { left: header_padding, right: header_padding },
-        },
-        header_height: 18,
-        body_message: {
-            ...text(theme.lowest, "sans", { size: "xs" }),
-            margin: { left: avatar_size + header_padding, top: 6, bottom: 6 },
-        },
-        button: interactive({
-            base: {
-                ...text(theme.lowest, "sans", "on", { size: "xs" }),
-                background: background(theme.lowest, "on"),
-                padding: 4,
-                corner_radius: 6,
-                margin: { left: 6 },
-            },
-
-            state: {
-                hovered: {
-                    background: background(theme.lowest, "on", "hovered"),
-                },
-            },
-        }),
-
-        dismiss_button: {
-            default: {
-                color: foreground(theme.lowest, "variant"),
-                icon_width: 14,
-                icon_height: 14,
-                button_width: 14,
-                button_height: 14,
-                hover: {
-                    color: foreground(theme.lowest, "hovered"),
-                },
-            },
-        },
-    }
-}

styles/src/style_tree/context_menu.ts πŸ”—

@@ -1,60 +0,0 @@
-import { background, border, border_color, text } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-
-export default function context_menu(): any {
-    const theme = useTheme()
-
-    return {
-        background: background(theme.middle),
-        corner_radius: 10,
-        padding: 4,
-        shadow: theme.popover_shadow,
-        border: border(theme.middle),
-        keystroke_margin: 30,
-        item: toggleable({
-            base: interactive({
-                base: {
-                    icon_spacing: 8,
-                    icon_width: 14,
-                    padding: { left: 6, right: 6, top: 2, bottom: 2 },
-                    corner_radius: 6,
-                    label: text(theme.middle, "sans", { size: "sm" }),
-                    keystroke: {
-                        ...text(theme.middle, "sans", "variant", {
-                            size: "sm",
-                            weight: "bold",
-                        }),
-                        padding: { left: 3, right: 3 },
-                    },
-                },
-                state: {
-                    hovered: {
-                        background: background(theme.middle, "hovered"),
-                    },
-                    clicked: {
-                        background: background(theme.middle, "pressed"),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        background: background(theme.middle, "active"),
-                    },
-                    hovered: {
-                        background: background(theme.middle, "hovered"),
-                    },
-                    clicked: {
-                        background: background(theme.middle, "pressed"),
-                    },
-                },
-            },
-        }),
-
-        separator: {
-            background: border_color(theme.middle),
-            margin: { top: 2, bottom: 2 },
-        },
-    }
-}

styles/src/style_tree/copilot.ts πŸ”—

@@ -1,293 +0,0 @@
-import { background, border, foreground, svg, text } from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-export default function copilot(): any {
-    const theme = useTheme()
-
-    const content_width = 264
-
-    const cta_button =
-        // Copied from welcome screen. FIXME: Move this into a ZDS component
-        interactive({
-            base: {
-                background: background(theme.middle),
-                border: border(theme.middle, "default"),
-                corner_radius: 4,
-                margin: {
-                    top: 4,
-                    bottom: 4,
-                    left: 8,
-                    right: 8,
-                },
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 7,
-                    right: 7,
-                },
-                ...text(theme.middle, "sans", "default", { size: "sm" }),
-            },
-            state: {
-                hovered: {
-                    ...text(theme.middle, "sans", "default", { size: "sm" }),
-                    background: background(theme.middle, "hovered"),
-                    border: border(theme.middle, "active"),
-                },
-            },
-        })
-
-    return {
-        out_link_icon: interactive({
-            base: {
-                icon: svg(
-                    foreground(theme.middle, "variant"),
-                    "icons/external_link.svg",
-                    12,
-                    12
-                ),
-                container: {
-                    corner_radius: 6,
-                    padding: { left: 6 },
-                },
-            },
-            state: {
-                hovered: {
-                    icon: {
-                        color: foreground(theme.middle, "hovered"),
-                    },
-                },
-            },
-        }),
-
-        modal: {
-            title_text: {
-                default: {
-                    ...text(theme.middle, "sans", {
-                        size: "xs",
-                        weight: "bold",
-                    }),
-                },
-            },
-            titlebar: {
-                background: background(theme.lowest),
-                border: border(theme.middle, "active"),
-                padding: {
-                    top: 4,
-                    bottom: 4,
-                    left: 8,
-                    right: 8,
-                },
-            },
-            container: {
-                background: background(theme.lowest),
-                padding: {
-                    top: 0,
-                    left: 0,
-                    right: 0,
-                    bottom: 8,
-                },
-            },
-            close_icon: interactive({
-                base: {
-                    icon: svg(
-                        foreground(theme.middle, "variant"),
-                        "icons/x.svg",
-                        8,
-                        8
-                    ),
-                    container: {
-                        corner_radius: 2,
-                        padding: {
-                            top: 4,
-                            bottom: 4,
-                            left: 4,
-                            right: 4,
-                        },
-                        margin: {
-                            right: 0,
-                        },
-                    },
-                },
-                state: {
-                    hovered: {
-                        icon: svg(
-                            foreground(theme.middle, "on"),
-                            "icons/x.svg",
-                            8,
-                            8
-                        ),
-                    },
-                    clicked: {
-                        icon: svg(
-                            foreground(theme.middle, "base"),
-                            "icons/x.svg",
-                            8,
-                            8
-                        ),
-                    },
-                },
-            }),
-            dimensions: {
-                width: 280,
-                height: 280,
-            },
-        },
-
-        auth: {
-            content_width,
-
-            cta_button,
-
-            header: {
-                icon: svg(
-                    foreground(theme.middle, "default"),
-                    "icons/zed_x_copilot.svg",
-                    92,
-                    32
-                ),
-                container: {
-                    margin: {
-                        top: 35,
-                        bottom: 5,
-                        left: 0,
-                        right: 0,
-                    },
-                },
-            },
-
-            prompting: {
-                subheading: {
-                    ...text(theme.middle, "sans", { size: "xs" }),
-                    margin: {
-                        top: 6,
-                        bottom: 12,
-                        left: 0,
-                        right: 0,
-                    },
-                },
-
-                hint: {
-                    ...text(theme.middle, "sans", {
-                        size: "xs",
-                        color: "#838994",
-                    }),
-                    margin: {
-                        top: 6,
-                        bottom: 2,
-                    },
-                },
-
-                device_code: {
-                    text: text(theme.middle, "mono", { size: "sm" }),
-                    cta: {
-                        ...cta_button,
-                        background: background(theme.lowest),
-                        border: border(theme.lowest, "inverted"),
-                        padding: {
-                            top: 0,
-                            bottom: 0,
-                            left: 16,
-                            right: 16,
-                        },
-                        margin: {
-                            left: 16,
-                            right: 16,
-                        },
-                    },
-                    left: content_width / 2,
-                    left_container: {
-                        padding: {
-                            top: 3,
-                            bottom: 3,
-                            left: 0,
-                            right: 6,
-                        },
-                    },
-                    right: (content_width * 1) / 3,
-                    right_container: interactive({
-                        base: {
-                            border: border(theme.lowest, "inverted", {
-                                bottom: false,
-                                right: false,
-                                top: false,
-                                left: true,
-                            }),
-                            padding: {
-                                top: 3,
-                                bottom: 5,
-                                left: 8,
-                                right: 0,
-                            },
-                        },
-                        state: {
-                            hovered: {
-                                border: border(theme.middle, "active", {
-                                    bottom: false,
-                                    right: false,
-                                    top: false,
-                                    left: true,
-                                }),
-                            },
-                        },
-                    }),
-                },
-            },
-
-            not_authorized: {
-                subheading: {
-                    ...text(theme.middle, "sans", { size: "xs" }),
-
-                    margin: {
-                        top: 16,
-                        bottom: 16,
-                        left: 0,
-                        right: 0,
-                    },
-                },
-
-                warning: {
-                    ...text(theme.middle, "sans", {
-                        size: "xs",
-                        color: foreground(theme.middle, "warning"),
-                    }),
-                    border: border(theme.middle, "warning"),
-                    background: background(theme.middle, "warning"),
-                    corner_radius: 2,
-                    padding: {
-                        top: 4,
-                        left: 4,
-                        bottom: 4,
-                        right: 4,
-                    },
-                    margin: {
-                        bottom: 16,
-                        left: 8,
-                        right: 8,
-                    },
-                },
-            },
-
-            authorized: {
-                subheading: {
-                    ...text(theme.middle, "sans", { size: "xs" }),
-
-                    margin: {
-                        top: 16,
-                        bottom: 16,
-                    },
-                },
-
-                hint: {
-                    ...text(theme.middle, "sans", {
-                        size: "xs",
-                        color: "#838994",
-                    }),
-                    margin: {
-                        top: 24,
-                        bottom: 4,
-                    },
-                },
-            },
-        },
-    }
-}

styles/src/style_tree/editor.ts πŸ”—

@@ -1,327 +0,0 @@
-import { with_opacity } from "../theme/color"
-import { Layer, StyleSets } from "../theme/create_theme"
-import {
-    background,
-    border,
-    border_color,
-    foreground,
-    text,
-} from "./components"
-import hover_popover from "./hover_popover"
-
-import { build_syntax } from "../theme/syntax"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-
-export default function editor(): any {
-    const theme = useTheme()
-
-    const { is_light } = theme
-
-    const layer = theme.highest
-
-    const autocomplete_item = {
-        corner_radius: 6,
-        padding: {
-            bottom: 2,
-            left: 6,
-            right: 6,
-            top: 2,
-        },
-    }
-
-    function diagnostic(layer: Layer, style_set: StyleSets) {
-        return {
-            text_scale_factor: 0.857,
-            header: {
-                border: border(layer, {
-                    top: true,
-                }),
-            },
-            message: {
-                text: text(layer, "sans", style_set, "default", { size: "sm" }),
-                highlight_text: text(layer, "sans", style_set, "default", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-            },
-        }
-    }
-
-    const syntax = build_syntax()
-
-    return {
-        text_color: syntax.primary.color,
-        background: background(layer),
-        active_line_background: with_opacity(background(layer, "on"), 0.75),
-        highlighted_line_background: background(layer, "on"),
-        // Inline autocomplete suggestions, Co-pilot suggestions, etc.
-        hint: syntax.hint,
-        suggestion: syntax.predictive,
-        code_actions: {
-            indicator: toggleable({
-                base: interactive({
-                    base: {
-                        color: foreground(layer, "variant"),
-                    },
-                    state: {
-                        hovered: {
-                            color: foreground(layer, "variant", "hovered"),
-                        },
-                        clicked: {
-                            color: foreground(layer, "variant", "pressed"),
-                        },
-                    },
-                }),
-                state: {
-                    active: {
-                        default: {
-                            color: foreground(layer, "accent"),
-                        },
-                        hovered: {
-                            color: foreground(layer, "accent", "hovered"),
-                        },
-                        clicked: {
-                            color: foreground(layer, "accent", "pressed"),
-                        },
-                    },
-                },
-            }),
-
-            vertical_scale: 0.55,
-        },
-        folds: {
-            icon_margin_scale: 4,
-            folded_icon: "icons/chevron_right.svg",
-            foldable_icon: "icons/chevron_down.svg",
-            indicator: toggleable({
-                base: interactive({
-                    base: {
-                        color: foreground(layer, "variant"),
-                    },
-                    state: {
-                        hovered: {
-                            color: foreground(layer, "on"),
-                        },
-                        clicked: {
-                            color: foreground(layer, "base"),
-                        },
-                    },
-                }),
-                state: {
-                    active: {
-                        default: {
-                            color: foreground(layer, "default"),
-                        },
-                        hovered: {
-                            color: foreground(layer, "on"),
-                        },
-                    },
-                },
-            }),
-            ellipses: {
-                text_color: theme.ramps.neutral(0.71).hex(),
-                corner_radius_factor: 0.15,
-                background: {
-                    // Copied from hover_popover highlight
-                    default: {
-                        color: theme.ramps.neutral(0.5).alpha(0.0).hex(),
-                    },
-
-                    hovered: {
-                        color: theme.ramps.neutral(0.5).alpha(0.5).hex(),
-                    },
-
-                    clicked: {
-                        color: theme.ramps.neutral(0.5).alpha(0.7).hex(),
-                    },
-                },
-            },
-            fold_background: foreground(layer, "variant"),
-        },
-        diff: {
-            deleted: is_light
-                ? theme.ramps.red(0.5).hex()
-                : theme.ramps.red(0.4).hex(),
-            modified: is_light
-                ? theme.ramps.yellow(0.5).hex()
-                : theme.ramps.yellow(0.5).hex(),
-            inserted: is_light
-                ? theme.ramps.green(0.4).hex()
-                : theme.ramps.green(0.5).hex(),
-            removed_width_em: 0.275,
-            width_em: 0.15,
-            corner_radius: 0.05,
-        },
-        /** Highlights matching occurrences of what is under the cursor
-         * as well as matched brackets
-         */
-        document_highlight_read_background: with_opacity(
-            foreground(layer, "accent"),
-            0.1
-        ),
-        document_highlight_write_background: theme.ramps
-            .neutral(0.5)
-            .alpha(0.4)
-            .hex(), // TODO: This was blend * 2
-        error_color: background(layer, "negative"),
-        gutter_background: background(layer),
-        gutter_padding_factor: 3.5,
-        line_number: with_opacity(foreground(layer), 0.35),
-        line_number_active: foreground(layer),
-        rename_fade: 0.6,
-        wrap_guide: with_opacity(foreground(layer), 0.05),
-        active_wrap_guide: with_opacity(foreground(layer), 0.1),
-        unnecessary_code_fade: 0.5,
-        selection: theme.players[0],
-        whitespace: theme.ramps.neutral(0.5).hex(),
-        guest_selections: [
-            theme.players[1],
-            theme.players[2],
-            theme.players[3],
-            theme.players[4],
-            theme.players[5],
-            theme.players[6],
-            theme.players[7],
-        ],
-        absent_selection: theme.players[7],
-        autocomplete: {
-            background: background(theme.middle),
-            corner_radius: 8,
-            padding: 4,
-            margin: {
-                left: -14,
-            },
-            border: border(theme.middle),
-            shadow: theme.popover_shadow,
-            match_highlight: foreground(theme.middle, "accent"),
-            item: autocomplete_item,
-            hovered_item: {
-                ...autocomplete_item,
-                match_highlight: foreground(theme.middle, "accent", "hovered"),
-                background: background(theme.middle, "hovered"),
-            },
-            selected_item: {
-                ...autocomplete_item,
-                match_highlight: foreground(theme.middle, "accent", "active"),
-                background: background(theme.middle, "active"),
-            },
-            completion_min_width: 300,
-            completion_max_width: 700,
-            inline_docs_container: { padding: { left: 40 } },
-            inline_docs_color: text(theme.middle, "sans", "disabled", {}).color,
-            inline_docs_size_percent: 0.75,
-            alongside_docs_max_width: 700,
-            alongside_docs_container: { padding: autocomplete_item.padding }
-        },
-        diagnostic_header: {
-            background: background(theme.middle),
-            icon_width_factor: 1.5,
-            text_scale_factor: 0.857,
-            border: border(theme.middle, {
-                bottom: true,
-                top: true,
-            }),
-            code: {
-                ...text(theme.middle, "mono", { size: "sm" }),
-                margin: {
-                    left: 10,
-                },
-            },
-            source: {
-                text: text(theme.middle, "sans", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-            },
-            message: {
-                highlight_text: text(theme.middle, "sans", {
-                    size: "sm",
-                    weight: "bold",
-                }),
-                text: text(theme.middle, "sans", { size: "sm" }),
-            },
-        },
-        diagnostic_path_header: {
-            background: background(theme.middle),
-            text_scale_factor: 0.857,
-            filename: text(theme.middle, "mono", { size: "sm" }),
-            path: {
-                ...text(theme.middle, "mono", { size: "sm" }),
-                margin: {
-                    left: 12,
-                },
-            },
-        },
-        error_diagnostic: diagnostic(theme.middle, "negative"),
-        warning_diagnostic: diagnostic(theme.middle, "warning"),
-        information_diagnostic: diagnostic(theme.middle, "accent"),
-        hint_diagnostic: diagnostic(theme.middle, "warning"),
-        invalid_error_diagnostic: diagnostic(theme.middle, "base"),
-        invalid_hint_diagnostic: diagnostic(theme.middle, "base"),
-        invalid_information_diagnostic: diagnostic(theme.middle, "base"),
-        invalid_warning_diagnostic: diagnostic(theme.middle, "base"),
-        hover_popover: hover_popover(),
-        link_definition: {
-            color: syntax.link_uri.color,
-            underline: syntax.link_uri.underline,
-        },
-        jump_icon: interactive({
-            base: {
-                color: foreground(layer, "on"),
-                icon_width: 20,
-                button_width: 20,
-                corner_radius: 6,
-                padding: {
-                    top: 6,
-                    bottom: 6,
-                    left: 6,
-                    right: 6,
-                },
-            },
-            state: {
-                hovered: {
-                    background: background(layer, "on", "hovered"),
-                },
-            },
-        }),
-
-        scrollbar: {
-            width: 12,
-            min_height_factor: 1.0,
-            track: {
-                border: border(layer, "variant", { left: true }),
-            },
-            thumb: {
-                background: with_opacity(background(layer, "inverted"), 0.3),
-                border: {
-                    width: 1,
-                    color: border_color(layer, "variant"),
-                    top: false,
-                    right: true,
-                    left: true,
-                    bottom: false,
-                },
-            },
-            git: {
-                deleted: is_light
-                    ? with_opacity(theme.ramps.red(0.5).hex(), 0.8)
-                    : with_opacity(theme.ramps.red(0.4).hex(), 0.8),
-                modified: is_light
-                    ? with_opacity(theme.ramps.yellow(0.5).hex(), 0.8)
-                    : with_opacity(theme.ramps.yellow(0.4).hex(), 0.8),
-                inserted: is_light
-                    ? with_opacity(theme.ramps.green(0.5).hex(), 0.8)
-                    : with_opacity(theme.ramps.green(0.4).hex(), 0.8),
-            },
-            selections: foreground(layer, "accent"),
-        },
-        composition_mark: {
-            underline: {
-                thickness: 1.0,
-                color: border_color(layer),
-            },
-        },
-        syntax,
-    }
-}

styles/src/style_tree/feedback.ts πŸ”—

@@ -1,59 +0,0 @@
-import { background, border, text } from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-
-export default function feedback(): any {
-    const theme = useTheme()
-
-    return {
-        submit_button: interactive({
-            base: {
-                ...text(theme.highest, "mono", "on"),
-                background: background(theme.highest, "on"),
-                corner_radius: 6,
-                border: border(theme.highest, "on"),
-                padding: {
-                    bottom: 2,
-                    left: 10,
-                    right: 10,
-                    top: 2,
-                },
-            },
-            state: {
-                clicked: {
-                    ...text(theme.highest, "mono", "on", "pressed"),
-                    background: background(theme.highest, "on", "pressed"),
-                    border: border(theme.highest, "on", "pressed"),
-                },
-                hovered: {
-                    ...text(theme.highest, "mono", "on", "hovered"),
-                    background: background(theme.highest, "on", "hovered"),
-                    border: border(theme.highest, "on", "hovered"),
-                },
-                disabled: {
-                    ...text(theme.highest, "mono", "on", "disabled"),
-                    background: background(theme.highest, "on", "disabled"),
-                    border: border(theme.highest, "on", "disabled"),
-                },
-            },
-        }),
-        button_margin: 8,
-        info_text_default: {
-            padding: {
-                left: 4,
-                right: 4,
-            },
-            ...text(theme.highest, "sans", "default", {
-                size: "xs",
-            })
-        },
-        link_text_default: text(theme.highest, "sans", "default", {
-            size: "xs",
-            underline: true,
-        }),
-        link_text_hover: text(theme.highest, "sans", "hovered", {
-            size: "xs",
-            underline: true,
-        }),
-    }
-}

styles/src/style_tree/hover_popover.ts πŸ”—

@@ -1,49 +0,0 @@
-import { useTheme } from "../theme"
-import { background, border, foreground, text } from "./components"
-
-export default function hover_popover(): any {
-    const theme = useTheme()
-
-    const base_container = {
-        background: background(theme.middle),
-        corner_radius: 8,
-        padding: {
-            left: 8,
-            right: 8,
-            top: 4,
-            bottom: 4,
-        },
-        shadow: theme.popover_shadow,
-        border: border(theme.middle),
-        margin: {
-            left: -8,
-        },
-    }
-
-    return {
-        container: base_container,
-        info_container: {
-            ...base_container,
-            background: background(theme.middle, "accent"),
-            border: border(theme.middle, "accent"),
-        },
-        warning_container: {
-            ...base_container,
-            background: background(theme.middle, "warning"),
-            border: border(theme.middle, "warning"),
-        },
-        error_container: {
-            ...base_container,
-            background: background(theme.middle, "negative"),
-            border: border(theme.middle, "negative"),
-        },
-        block_style: {
-            padding: { top: 4 },
-        },
-        prose: text(theme.middle, "sans", { size: "sm" }),
-        diagnostic_source_highlight: {
-            color: foreground(theme.middle, "accent"),
-        },
-        highlight: theme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
-    }
-}

styles/src/style_tree/incoming_call_notification.ts πŸ”—

@@ -1,55 +0,0 @@
-import { useTheme } from "../theme"
-import { background, border, text } from "./components"
-
-export default function incoming_call_notification(): unknown {
-    const theme = useTheme()
-
-    const avatar_size = 48
-    return {
-        window_height: 74,
-        window_width: 380,
-        background: background(theme.middle),
-        caller_container: {
-            padding: 12,
-        },
-        caller_avatar: {
-            height: avatar_size,
-            width: avatar_size,
-            corner_radius: avatar_size / 2,
-        },
-        caller_metadata: {
-            margin: { left: 10 },
-        },
-        caller_username: {
-            ...text(theme.middle, "sans", { size: "sm", weight: "bold" }),
-            margin: { top: -3 },
-        },
-        caller_message: {
-            ...text(theme.middle, "sans", "variant", { size: "xs" }),
-            margin: { top: -3 },
-        },
-        worktree_roots: {
-            ...text(theme.middle, "sans", "variant", {
-                size: "xs",
-                weight: "bold",
-            }),
-            margin: { top: -3 },
-        },
-        button_width: 96,
-        accept_button: {
-            background: background(theme.middle, "accent"),
-            border: border(theme.middle, { left: true, bottom: true }),
-            ...text(theme.middle, "sans", "positive", {
-                size: "xs",
-                weight: "bold",
-            }),
-        },
-        decline_button: {
-            border: border(theme.middle, { left: true }),
-            ...text(theme.middle, "sans", "negative", {
-                size: "xs",
-                weight: "bold",
-            }),
-        },
-    }
-}

styles/src/style_tree/notification_panel.ts πŸ”—

@@ -1,75 +0,0 @@
-import { background, border, text } from "./components"
-import { icon_button } from "../component/icon_button"
-import { useTheme, with_opacity } from "../theme"
-import { text_button } from "../component"
-
-export default function (): any {
-    const theme = useTheme()
-    const layer = theme.middle
-
-    const notification_text = {
-        padding: { top: 4, bottom: 4 },
-        ...text(layer, "sans", "base"),
-    }
-
-    const notification_read_text_color = with_opacity(
-        theme.middle.base.default.foreground,
-        0.6
-    )
-
-    return {
-        background: background(layer),
-        avatar: {
-            icon_width: 24,
-            icon_height: 24,
-            corner_radius: 12,
-            outer_width: 24,
-            outer_corner_radius: 24,
-        },
-        title: {
-            ...text(layer, "sans", "default"),
-            padding: { left: 8, right: 8 },
-            border: border(layer, { bottom: true }),
-        },
-        title_height: 32,
-        title_icon: {
-            asset: "icons/feedback.svg",
-            color: text(theme.lowest, "sans", "default").color,
-            dimensions: {
-                width: 16,
-                height: 16,
-            },
-        },
-        read_text: {
-            ...notification_text,
-            color: notification_read_text_color,
-        },
-        unread_text: notification_text,
-        button: text_button({
-            variant: "ghost",
-        }),
-        timestamp: text(layer, "sans", "base", "disabled"),
-        avatar_container: {
-            padding: {
-                right: 8,
-                left: 2,
-                top: 4,
-                bottom: 2,
-            },
-        },
-        list: {
-            padding: {
-                left: 8,
-                right: 8,
-            },
-        },
-        icon_button: icon_button({
-            variant: "ghost",
-            color: "variant",
-            size: "sm",
-        }),
-        sign_in_prompt: {
-            default: text(layer, "sans", "base"),
-        },
-    }
-}

styles/src/style_tree/picker.ts πŸ”—

@@ -1,158 +0,0 @@
-import { with_opacity } from "../theme/color"
-import { background, border, text } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-
-export default function picker(): any {
-    const theme = useTheme()
-
-    const container = {
-        background: background(theme.lowest),
-        border: border(theme.lowest),
-        shadow: theme.modal_shadow,
-        corner_radius: 12,
-        padding: {
-            bottom: 4,
-        },
-    }
-    const input_editor = {
-        placeholder_text: text(theme.lowest, "sans", "on", "disabled"),
-        selection: theme.players[0],
-        text: text(theme.lowest, "mono", "on"),
-        border: border(theme.lowest, { bottom: true }),
-        padding: {
-            bottom: 8,
-            left: 16,
-            right: 16,
-            top: 8,
-        },
-        margin: {
-            bottom: 4,
-        },
-    }
-    const empty_input_editor: any = { ...input_editor }
-    delete empty_input_editor.border
-    delete empty_input_editor.margin
-
-    return {
-        ...container,
-        empty_container: {
-            ...container,
-            padding: {},
-        },
-        item: toggleable({
-            base: interactive({
-                base: {
-                    padding: {
-                        bottom: 4,
-                        left: 12,
-                        right: 12,
-                        top: 4,
-                    },
-                    margin: {
-                        top: 1,
-                        left: 4,
-                        right: 4,
-                    },
-                    corner_radius: 8,
-                    text: text(theme.lowest, "sans", "variant"),
-                    highlight_text: text(theme.lowest, "sans", "accent", {
-                        weight: "bold",
-                    }),
-                },
-                state: {
-                    hovered: {
-                        background: with_opacity(
-                            background(theme.lowest, "hovered"),
-                            0.5
-                        ),
-                    },
-                    clicked: {
-                        background: with_opacity(
-                            background(theme.lowest, "pressed"),
-                            0.5
-                        ),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        background: with_opacity(
-                            background(theme.lowest, "base", "active"),
-                            0.5
-                        ),
-                    },
-                    hovered: {
-                        background: with_opacity(
-                            background(theme.lowest, "hovered"),
-                            0.5
-                        ),
-                    },
-                    clicked: {
-                        background: with_opacity(
-                            background(theme.lowest, "pressed"),
-                            0.5
-                        ),
-                    },
-                },
-            },
-        }),
-
-        input_editor,
-        empty_input_editor,
-        no_matches: {
-            text: text(theme.lowest, "sans", "variant"),
-            padding: {
-                bottom: 8,
-                left: 16,
-                right: 16,
-                top: 8,
-            },
-        },
-        header: {
-            text: text(theme.lowest, "sans", "variant", { size: "xs" }),
-
-            margin: {
-                top: 1,
-                left: 8,
-                right: 8,
-            },
-        },
-        footer: interactive({
-            base: {
-                text: text(theme.lowest, "sans", "base", { size: "xs" }),
-                padding: {
-                    bottom: 4,
-                    left: 12,
-                    right: 12,
-                    top: 4,
-                },
-                margin: {
-                    top: 1,
-                    left: 4,
-                    right: 4,
-                },
-                corner_radius: 8,
-                background: with_opacity(
-                    background(theme.lowest, "active"),
-                    0.5
-                ),
-            },
-            state: {
-                hovered: {
-                    background: with_opacity(
-                        background(theme.lowest, "hovered"),
-                        0.5
-                    ),
-                },
-                clicked: {
-                    background: with_opacity(
-                        background(theme.lowest, "pressed"),
-                        0.5
-                    ),
-                },
-            },
-        }),
-    }
-}

styles/src/style_tree/project_diagnostics.ts πŸ”—

@@ -1,14 +0,0 @@
-import { useTheme } from "../theme"
-import { background, text } from "./components"
-
-export default function project_diagnostics(): any {
-    const theme = useTheme()
-
-    return {
-        background: background(theme.highest),
-        tab_icon_spacing: 4,
-        tab_icon_width: 13,
-        tab_summary_spacing: 10,
-        empty_message: text(theme.highest, "sans", "variant", { size: "md" }),
-    }
-}

styles/src/style_tree/project_panel.ts πŸ”—

@@ -1,201 +0,0 @@
-import { with_opacity } from "../theme/color"
-import {
-    Border,
-    TextStyle,
-    background,
-    border,
-    foreground,
-    text,
-} from "./components"
-import { interactive, toggleable } from "../element"
-import merge from "ts-deepmerge"
-import { useTheme } from "../theme"
-export default function project_panel(): any {
-    const theme = useTheme()
-
-    const { is_light } = theme
-
-    type EntryStateProps = {
-        background?: string
-        border?: Border
-        text?: TextStyle
-        icon_color?: string
-    }
-
-    type EntryState = {
-        default: EntryStateProps
-        hovered?: EntryStateProps
-        clicked?: EntryStateProps
-    }
-
-    const entry = (unselected?: EntryState, selected?: EntryState) => {
-        const git_status = {
-            git: {
-                modified: is_light
-                    ? theme.ramps.yellow(0.6).hex()
-                    : theme.ramps.yellow(0.5).hex(),
-                inserted: is_light
-                    ? theme.ramps.green(0.45).hex()
-                    : theme.ramps.green(0.5).hex(),
-                conflict: is_light
-                    ? theme.ramps.red(0.6).hex()
-                    : theme.ramps.red(0.5).hex(),
-            },
-        }
-
-        const base_properties = {
-            height: 22,
-            background: background(theme.middle),
-            chevron_color: foreground(theme.middle, "variant"),
-            icon_color: with_opacity(foreground(theme.middle, "active"), 0.3),
-            chevron_size: 7,
-            icon_size: 14,
-            icon_spacing: 6,
-            text: text(theme.middle, "sans", "variant", { size: "sm" }),
-            status: {
-                ...git_status,
-            },
-        }
-
-        const selected_style: EntryState | undefined = selected
-            ? selected
-            : unselected
-
-        const unselected_default_style = merge(
-            base_properties,
-            unselected?.default ?? {},
-            {}
-        )
-        const unselected_hovered_style = merge(
-            base_properties,
-            { background: background(theme.middle, "hovered") },
-            unselected?.hovered ?? {}
-        )
-        const unselected_clicked_style = merge(
-            base_properties,
-            { background: background(theme.middle, "pressed") },
-            unselected?.clicked ?? {}
-        )
-        const selected_default_style = merge(
-            base_properties,
-            {
-                background: background(theme.lowest),
-                text: text(theme.lowest, "sans", { size: "sm" }),
-            },
-            selected_style?.default ?? {}
-        )
-        const selected_hovered_style = merge(
-            base_properties,
-            {
-                background: background(theme.lowest, "hovered"),
-                text: text(theme.lowest, "sans", { size: "sm" }),
-            },
-            selected_style?.hovered ?? {}
-        )
-        const selected_clicked_style = merge(
-            base_properties,
-            {
-                background: background(theme.lowest, "pressed"),
-                text: text(theme.lowest, "sans", { size: "sm" }),
-            },
-            selected_style?.clicked ?? {}
-        )
-
-        return toggleable({
-            state: {
-                inactive: interactive({
-                    state: {
-                        default: unselected_default_style,
-                        hovered: unselected_hovered_style,
-                        clicked: unselected_clicked_style,
-                    },
-                }),
-                active: interactive({
-                    state: {
-                        default: selected_default_style,
-                        hovered: selected_hovered_style,
-                        clicked: selected_clicked_style,
-                    },
-                }),
-            },
-        })
-    }
-
-    const default_entry = entry()
-
-    return {
-        open_project_button: interactive({
-            base: {
-                background: background(theme.middle),
-                border: border(theme.middle, "active"),
-                corner_radius: 4,
-                margin: {
-                    top: 16,
-                    left: 16,
-                    right: 16,
-                },
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 7,
-                    right: 7,
-                },
-                ...text(theme.middle, "sans", "default", { size: "sm" }),
-            },
-            state: {
-                hovered: {
-                    ...text(theme.middle, "sans", "default", { size: "sm" }),
-                    background: background(theme.middle, "hovered"),
-                    border: border(theme.middle, "active"),
-                },
-                clicked: {
-                    ...text(theme.middle, "sans", "default", { size: "sm" }),
-                    background: background(theme.middle, "pressed"),
-                    border: border(theme.middle, "active"),
-                },
-            },
-        }),
-        background: background(theme.middle),
-        padding: { left: 6, right: 6, top: 0, bottom: 6 },
-        indent_width: 20,
-        entry: default_entry,
-        dragged_entry: {
-            ...default_entry.inactive.default,
-            text: text(theme.middle, "sans", "on", { size: "sm" }),
-            background: with_opacity(background(theme.middle, "on"), 0.9),
-            border: border(theme.middle),
-        },
-        ignored_entry: entry(
-            {
-                default: {
-                    text: text(theme.middle, "sans", "disabled"),
-                },
-            },
-            {
-                default: {
-                    icon_color: foreground(theme.middle, "variant"),
-                },
-            }
-        ),
-        cut_entry: entry(
-            {
-                default: {
-                    text: text(theme.middle, "sans", "disabled"),
-                },
-            },
-            {
-                default: {
-                    background: background(theme.middle, "active"),
-                    text: text(theme.middle, "sans", "disabled", {
-                        size: "sm",
-                    }),
-                },
-            }
-        ),
-        filename_editor: {
-            background: background(theme.middle, "on"),
-            text: text(theme.middle, "sans", "on", { size: "sm" }),
-            selection: theme.players[0],
-        },
-    }
-}

styles/src/style_tree/project_shared_notification.ts πŸ”—

@@ -1,55 +0,0 @@
-import { useTheme } from "../theme"
-import { background, border, text } from "./components"
-
-export default function project_shared_notification(): unknown {
-    const theme = useTheme()
-
-    const avatar_size = 48
-    return {
-        window_height: 74,
-        window_width: 380,
-        background: background(theme.middle),
-        owner_container: {
-            padding: 12,
-        },
-        owner_avatar: {
-            height: avatar_size,
-            width: avatar_size,
-            corner_radius: avatar_size / 2,
-        },
-        owner_metadata: {
-            margin: { left: 10 },
-        },
-        owner_username: {
-            ...text(theme.middle, "sans", { size: "sm", weight: "bold" }),
-            margin: { top: -3 },
-        },
-        message: {
-            ...text(theme.middle, "sans", "variant", { size: "xs" }),
-            margin: { top: -3 },
-        },
-        worktree_roots: {
-            ...text(theme.middle, "sans", "variant", {
-                size: "xs",
-                weight: "bold",
-            }),
-            margin: { top: -3 },
-        },
-        button_width: 96,
-        open_button: {
-            background: background(theme.middle, "accent"),
-            border: border(theme.middle, { left: true, bottom: true }),
-            ...text(theme.middle, "sans", "accent", {
-                size: "xs",
-                weight: "bold",
-            }),
-        },
-        dismiss_button: {
-            border: border(theme.middle, { left: true }),
-            ...text(theme.middle, "sans", "variant", {
-                size: "xs",
-                weight: "bold",
-            }),
-        },
-    }
-}

styles/src/style_tree/search.ts πŸ”—

@@ -1,437 +0,0 @@
-import { with_opacity } from "../theme/color"
-import { background, border, foreground, text } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-
-const search_results = () => {
-    const theme = useTheme()
-
-    return {
-        // TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
-        match_background: with_opacity(
-            foreground(theme.highest, "accent"),
-            0.4
-        ),
-    }
-}
-
-export default function search(): any {
-    const theme = useTheme()
-    const SEARCH_ROW_SPACING = 12
-
-    // Search input
-    const editor = {
-        background: background(theme.highest),
-        corner_radius: 8,
-        min_width: 200,
-        max_width: 500,
-        placeholder_text: text(theme.highest, "mono", "disabled"),
-        selection: theme.players[0],
-        text: text(theme.highest, "mono", "default"),
-        border: border(theme.highest),
-        padding: {
-            top: 4,
-            bottom: 4,
-            left: 10,
-            right: 4,
-        },
-        margin: { right: SEARCH_ROW_SPACING },
-    }
-
-    const include_exclude_editor = {
-        ...editor,
-        min_width: 100,
-        max_width: 250,
-    }
-
-    return {
-        padding: { top: 4, bottom: 4 },
-
-        option_button: toggleable({
-            base: interactive({
-                base: {
-                    icon_width: 14,
-                    button_width: 32,
-                    color: foreground(theme.highest, "variant"),
-                    background: background(theme.highest, "on"),
-                    corner_radius: 2,
-                    margin: { right: 2 },
-                    border: {
-                        width: 1,
-                        color: background(theme.highest, "on"),
-                    },
-                    padding: {
-                        left: 4,
-                        right: 4,
-                        top: 4,
-                        bottom: 4,
-                    },
-                },
-                state: {
-                    hovered: {
-                        ...text(theme.highest, "mono", "variant", "hovered"),
-                        background: background(theme.highest, "on", "hovered"),
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on", "hovered"),
-                        },
-                    },
-                    clicked: {
-                        ...text(theme.highest, "mono", "variant", "pressed"),
-                        background: background(theme.highest, "on", "pressed"),
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on", "pressed"),
-                        },
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        icon_width: 14,
-                        button_width: 32,
-                        color: foreground(theme.highest, "variant"),
-                        background: background(theme.highest, "accent"),
-                        border: border(theme.highest, "accent"),
-                    },
-                    hovered: {
-                        background: background(
-                            theme.highest,
-                            "accent",
-                            "hovered"
-                        ),
-                        border: border(theme.highest, "accent", "hovered"),
-                    },
-                    clicked: {
-                        background: background(
-                            theme.highest,
-                            "accent",
-                            "pressed"
-                        ),
-                        border: border(theme.highest, "accent", "pressed"),
-                    },
-                },
-            },
-        }),
-        option_button_component: toggleable({
-            base: interactive({
-                base: {
-                    icon_size: 14,
-                    color: foreground(theme.highest, "variant"),
-
-                    button_width: 32,
-                    background: background(theme.highest, "on"),
-                    corner_radius: 6,
-                    margin: { right: 2 },
-                    border: {
-                        width: 1,
-                        color: background(theme.highest, "on"),
-                    },
-                    padding: {
-                        left: 4,
-                        right: 4,
-                        top: 4,
-                        bottom: 4,
-                    },
-                },
-                state: {
-                    hovered: {
-                        ...text(theme.highest, "mono", "variant", "hovered"),
-                        background: background(theme.highest, "on", "hovered"),
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on", "hovered"),
-                        },
-                    },
-                    clicked: {
-                        ...text(theme.highest, "mono", "variant", "pressed"),
-                        background: background(theme.highest, "on", "pressed"),
-                        border: {
-                            width: 1,
-                            color: background(theme.highest, "on", "pressed"),
-                        },
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        icon_size: 14,
-                        button_width: 32,
-                        color: foreground(theme.highest, "variant"),
-                        background: background(theme.highest, "accent"),
-                        border: border(theme.highest, "accent"),
-                    },
-                    hovered: {
-                        background: background(
-                            theme.highest,
-                            "accent",
-                            "hovered"
-                        ),
-                        border: border(theme.highest, "accent", "hovered"),
-                    },
-                    clicked: {
-                        background: background(
-                            theme.highest,
-                            "accent",
-                            "pressed"
-                        ),
-                        border: border(theme.highest, "accent", "pressed"),
-                    },
-                },
-            },
-        }),
-        editor,
-        invalid_editor: {
-            ...editor,
-            border: border(theme.highest, "negative"),
-        },
-        include_exclude_editor,
-        invalid_include_exclude_editor: {
-            ...include_exclude_editor,
-            border: border(theme.highest, "negative"),
-        },
-        match_index: {
-            ...text(theme.highest, "mono", { size: "sm" }),
-            padding: {
-                left: SEARCH_ROW_SPACING,
-                right: SEARCH_ROW_SPACING,
-            },
-        },
-        option_button_group: {
-            padding: {
-                right: SEARCH_ROW_SPACING,
-            },
-        },
-        include_exclude_inputs: {
-            ...text(theme.highest, "mono", "variant"),
-            padding: {
-                right: 6,
-            },
-        },
-        major_results_status: {
-            ...text(theme.highest, "mono", "on"),
-            size: 15,
-        },
-        minor_results_status: {
-            ...text(theme.highest, "mono", "variant"),
-            size: 13,
-        },
-        // Input Icon
-        editor_icon: {
-            icon: {
-                color: foreground(theme.highest, "disabled"),
-                asset: "icons/magnifying_glass.svg",
-                dimensions: {
-                    width: 14,
-                    height: 14,
-                },
-            },
-            container: {
-                margin: { right: 4 },
-                padding: { left: 1, right: 1 },
-            },
-        },
-        // Toggle group buttons - Text | Regex | Semantic
-        mode_button: toggleable({
-            base: interactive({
-                base: {
-                    ...text(theme.highest, "mono", "variant", { size: "sm" }),
-                    background: background(theme.highest, "variant"),
-
-                    border: {
-                        ...border(theme.highest, "on"),
-                        left: false,
-                        right: false,
-                    },
-                    margin: {
-                        top: 1,
-                        bottom: 1,
-                    },
-                    padding: {
-                        left: 10,
-                        right: 10,
-                    },
-                    corner_radius: 6,
-                },
-                state: {
-                    hovered: {
-                        ...text(theme.highest, "mono", "variant", "hovered", {
-                            size: "sm",
-                        }),
-                        background: background(
-                            theme.highest,
-                            "variant",
-                            "hovered"
-                        ),
-                        border: border(theme.highest, "on", "hovered"),
-                    },
-                    clicked: {
-                        ...text(theme.highest, "mono", "variant", "pressed", {
-                            size: "sm",
-                        }),
-                        background: background(
-                            theme.highest,
-                            "variant",
-                            "pressed"
-                        ),
-                        border: border(theme.highest, "on", "pressed"),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        ...text(theme.highest, "mono", "on", { size: "sm" }),
-                        background: background(theme.highest, "on"),
-                    },
-                    hovered: {
-                        ...text(theme.highest, "mono", "on", "hovered", {
-                            size: "sm",
-                        }),
-                        background: background(theme.highest, "on", "hovered"),
-                    },
-                    clicked: {
-                        ...text(theme.highest, "mono", "on", "pressed", {
-                            size: "sm",
-                        }),
-                        background: background(theme.highest, "on", "pressed"),
-                    },
-                },
-            },
-        }),
-        // Next/Previous Match buttons
-        // HACK: This is not how disabled elements should be created
-        // Disabled elements should use a disabled state of an interactive element, not a toggleable element with the inactive state being disabled
-        nav_button: toggleable({
-            state: {
-                inactive: interactive({
-                    base: {
-                        background: background(theme.highest, "disabled"),
-                        text: text(theme.highest, "mono", "disabled"),
-                        corner_radius: 6,
-                        border: {
-                            ...border(theme.highest, "disabled"),
-                            left: false,
-                            right: false,
-                        },
-                        margin: {
-                            top: 1,
-                            bottom: 1,
-                        },
-                        padding: {
-                            left: 10,
-                            right: 10,
-                        },
-                    },
-                    state: {
-                        hovered: {},
-                    },
-                }),
-                active: interactive({
-                    base: {
-                        text: text(theme.highest, "mono", "on"),
-                        background: background(theme.highest, "on"),
-                        corner_radius: 6,
-                        border: {
-                            ...border(theme.highest, "on"),
-                            left: false,
-                            right: false,
-                        },
-                        margin: {
-                            top: 1,
-                            bottom: 1,
-                        },
-                        padding: {
-                            left: 10,
-                            right: 10,
-                        },
-                    },
-                    state: {
-                        hovered: {
-                            ...text(theme.highest, "mono", "on", "hovered"),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "hovered"
-                            ),
-                            border: border(theme.highest, "on", "hovered"),
-                        },
-                        clicked: {
-                            ...text(theme.highest, "mono", "on", "pressed"),
-                            background: background(
-                                theme.highest,
-                                "on",
-                                "pressed"
-                            ),
-                            border: border(theme.highest, "on", "pressed"),
-                        },
-                    },
-                }),
-            },
-        }),
-        search_bar_row_height: 34,
-        search_row_spacing: 8,
-        option_button_height: 22,
-        modes_container: {
-            padding: {
-                right: SEARCH_ROW_SPACING,
-            },
-        },
-        replace_icon: {
-            icon: {
-                color: foreground(theme.highest, "disabled"),
-                asset: "icons/replace.svg",
-                dimensions: {
-                    width: 14,
-                    height: 14,
-                },
-            },
-            container: {
-                margin: { right: 4 },
-                padding: { left: 1, right: 1 },
-            },
-        },
-        action_button: interactive({
-            base: {
-                icon_size: 14,
-                color: foreground(theme.highest, "variant"),
-
-                button_width: 32,
-                background: background(theme.highest, "on"),
-                corner_radius: 6,
-                margin: { right: 2 },
-                border: {
-                    width: 1,
-                    color: background(theme.highest, "on"),
-                },
-                padding: {
-                    left: 4,
-                    right: 4,
-                    top: 4,
-                    bottom: 4,
-                },
-            },
-            state: {
-                hovered: {
-                    ...text(theme.highest, "mono", "variant", "hovered"),
-                    background: background(theme.highest, "on", "hovered"),
-                    border: {
-                        width: 1,
-                        color: background(theme.highest, "on", "hovered"),
-                    },
-                },
-                clicked: {
-                    ...text(theme.highest, "mono", "variant", "pressed"),
-                    background: background(theme.highest, "on", "pressed"),
-                    border: {
-                        width: 1,
-                        color: background(theme.highest, "on", "pressed"),
-                    },
-                },
-            },
-        }),
-        ...search_results(),
-    }
-}

styles/src/style_tree/shared_screen.ts πŸ”—

@@ -1,10 +0,0 @@
-import { useTheme } from "../theme"
-import { background } from "./components"
-
-export default function sharedScreen() {
-    const theme = useTheme()
-
-    return {
-        background: background(theme.highest),
-    }
-}

styles/src/style_tree/simple_message_notification.ts πŸ”—

@@ -1,52 +0,0 @@
-import { background, border, foreground, text } from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-
-export default function simple_message_notification(): any {
-    const theme = useTheme()
-
-    const header_padding = 8
-
-    return {
-        message: {
-            ...text(theme.middle, "sans", { size: "xs" }),
-            margin: { left: header_padding, right: header_padding },
-        },
-        action_message: interactive({
-            base: {
-                ...text(theme.middle, "sans", { size: "xs" }),
-                border: border(theme.middle, "active"),
-                corner_radius: 4,
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 7,
-                    right: 7,
-                },
-
-                margin: { left: header_padding, top: 6, bottom: 6 },
-            },
-            state: {
-                hovered: {
-                    ...text(theme.middle, "sans", "default", { size: "xs" }),
-                    background: background(theme.middle, "hovered"),
-                    border: border(theme.middle, "active"),
-                },
-            },
-        }),
-        dismiss_button: interactive({
-            base: {
-                color: foreground(theme.middle),
-                icon_width: 14,
-                icon_height: 14,
-                button_width: 14,
-                button_height: 14,
-            },
-            state: {
-                hovered: {
-                    color: foreground(theme.middle, "hovered"),
-                },
-            },
-        }),
-    }
-}

styles/src/style_tree/status_bar.ts πŸ”—

@@ -1,161 +0,0 @@
-import { background, border, foreground, text } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../common"
-import { text_button } from "../component/text_button"
-
-export default function status_bar(): any {
-    const theme = useTheme()
-
-    const layer = theme.lowest
-
-    const status_container = {
-        corner_radius: 6,
-        padding: { top: 3, bottom: 3, left: 6, right: 6 },
-    }
-
-    const diagnostic_status_container = {
-        corner_radius: 6,
-        padding: { top: 1, bottom: 1, left: 6, right: 6 },
-    }
-
-    return {
-        height: 30,
-        item_spacing: 8,
-        padding: {
-            top: 1,
-            bottom: 1,
-            left: 6,
-            right: 6,
-        },
-        border: border(layer, { top: true, overlay: true }),
-        cursor_position: text(layer, "sans", "base", { size: "xs" }),
-        vim_mode_indicator: {
-            margin: { left: 6 },
-            ...text(layer, "mono", "base", { size: "xs" }),
-        },
-        active_language: text_button({
-            color: "base",
-        }),
-        auto_update_progress_message: text(layer, "sans", "base", {
-            size: "xs",
-        }),
-        auto_update_done_message: text(layer, "sans", "base", { size: "xs" }),
-        lsp_status: interactive({
-            base: {
-                ...diagnostic_status_container,
-                icon_spacing: 4,
-                icon_width: 14,
-                height: 18,
-                message: text(layer, "sans", { size: "xs" }),
-                icon_color: foreground(layer),
-            },
-            state: {
-                hovered: {
-                    message: text(layer, "sans", { size: "xs" }),
-                    icon_color: foreground(layer),
-                    background: background(layer, "hovered"),
-                },
-            },
-        }),
-        diagnostic_message: interactive({
-            base: {
-                ...text(layer, "sans", { size: "xs" }),
-            },
-            state: { hovered: text(layer, "sans", "hovered", { size: "xs" }) },
-        }),
-        diagnostic_summary: interactive({
-            base: {
-                height: 20,
-                icon_width: 14,
-                icon_spacing: 2,
-                summary_spacing: 6,
-                text: text(layer, "sans", { size: "sm" }),
-                icon_color_ok: foreground(layer, "base"),
-                icon_color_warning: foreground(layer, "warning"),
-                icon_color_error: foreground(layer, "negative"),
-                container_ok: {
-                    corner_radius: 6,
-                    padding: { top: 2, bottom: 2, left: 6, right: 6 },
-                },
-                container_warning: diagnostic_status_container,
-                container_error: diagnostic_status_container,
-            },
-            state: {
-                hovered: {
-                    icon_color_ok: foreground(layer, "on"),
-                    container_ok: {
-                        background: background(layer, "hovered"),
-                    },
-                    container_warning: {
-                        background: background(layer, "hovered"),
-                    },
-                    container_error: {
-                        background: background(layer, "hovered"),
-                    },
-                },
-                clicked: {
-                    icon_color_ok: foreground(layer, "on"),
-                    container_ok: {
-                        background: background(layer, "pressed"),
-                    },
-                    container_warning: {
-                        background: background(layer, "pressed"),
-                    },
-                    container_error: {
-                        background: background(layer, "pressed"),
-                    },
-                },
-            },
-        }),
-        panel_buttons: {
-            group_left: {},
-            group_bottom: {},
-            group_right: {},
-            button: toggleable({
-                base: interactive({
-                    base: {
-                        ...status_container,
-                        icon_size: 14,
-                        icon_color: foreground(layer, "base"),
-                        background: background(layer, "default"),
-                        label: {
-                            margin: { left: 6 },
-                            ...text(layer, "sans", { size: "xs" }),
-                        },
-                    },
-                    state: {
-                        hovered: {
-                            background: background(layer, "hovered"),
-                        },
-                        clicked: {
-                            background: background(layer, "pressed"),
-                        },
-                    },
-                }),
-                state: {
-                    active: {
-                        default: {
-                            icon_color: foreground(layer, "accent", "default"),
-                            background: background(layer, "default"),
-                        },
-                        hovered: {
-                            icon_color: foreground(layer, "accent", "hovered"),
-                            background: background(layer, "hovered"),
-                        },
-                        clicked: {
-                            icon_color: foreground(layer, "accent", "pressed"),
-                            background: background(layer, "pressed"),
-                        },
-                    },
-                },
-            }),
-            badge: {
-                corner_radius: 3,
-                padding: 2,
-                margin: { bottom: -1, right: -1 },
-                border: border(layer),
-                background: background(layer, "accent"),
-            },
-        },
-    }
-}

styles/src/style_tree/tab_bar.ts πŸ”—

@@ -1,167 +0,0 @@
-import { with_opacity } from "../theme/color"
-import { text, border, background, foreground } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../common"
-
-export default function tab_bar(): any {
-    const theme = useTheme()
-
-    const { is_light } = theme
-
-    const height = 32
-
-    const active_layer = theme.highest
-    const layer = theme.middle
-
-    const tab = {
-        height,
-        text: text(layer, "sans", "variant", { size: "sm" }),
-        background: background(layer),
-        border: border(layer, {
-            right: true,
-            bottom: true,
-            overlay: true,
-        }),
-        padding: {
-            left: 8,
-            right: 12,
-        },
-        spacing: 8,
-
-        // Tab type icons (e.g. Project Search)
-        type_icon_width: 14,
-
-        // Close icons
-        close_icon_width: 14,
-        icon_close: foreground(layer, "variant"),
-        icon_close_active: foreground(layer, "hovered"),
-
-        // Indicators
-        icon_conflict: foreground(layer, "warning"),
-        icon_dirty: foreground(layer, "accent"),
-
-        git: {
-            modified: is_light
-                ? theme.ramps.yellow(0.6).hex()
-                : theme.ramps.yellow(0.5).hex(),
-            inserted: is_light
-                ? theme.ramps.green(0.45).hex()
-                : theme.ramps.green(0.5).hex(),
-            conflict: is_light
-                ? theme.ramps.red(0.6).hex()
-                : theme.ramps.red(0.5).hex(),
-        },
-
-        // When two tabs of the same name are open, a label appears next to them
-        description: {
-            margin: { left: 8 },
-            ...text(layer, "sans", "disabled", { size: "2xs" }),
-        },
-    }
-
-    const active_pane_active_tab = {
-        ...tab,
-        background: background(active_layer),
-        text: text(active_layer, "sans", "active", { size: "sm" }),
-        border: {
-            ...tab.border,
-            bottom: false,
-        },
-    }
-
-    const inactive_pane_inactive_tab = {
-        ...tab,
-        background: background(layer),
-        text: text(layer, "sans", "variant", { size: "sm" }),
-    }
-
-    const inactive_pane_active_tab = {
-        ...tab,
-        background: background(active_layer),
-        text: text(layer, "sans", "variant", { size: "sm" }),
-        border: {
-            ...tab.border,
-            bottom: false,
-        },
-    }
-    const nav_button = interactive({
-        base: {
-            color: foreground(theme.highest, "on"),
-            icon_width: 12,
-
-            button_width: active_pane_active_tab.height,
-            border: border(theme.lowest, "on", {
-                bottom: true,
-                overlay: true,
-            }),
-        },
-        state: {
-            hovered: {
-                color: foreground(theme.highest, "on", "hovered"),
-                background: background(theme.highest, "on", "hovered"),
-            },
-            disabled: {
-                color: foreground(theme.highest, "on", "disabled"),
-            },
-        },
-    })
-
-    const dragged_tab = {
-        ...active_pane_active_tab,
-        background: with_opacity(tab.background, 0.9),
-        border: undefined as any,
-        shadow: theme.popover_shadow,
-    }
-
-    return {
-        height,
-        background: background(layer),
-        active_pane: {
-            active_tab: active_pane_active_tab,
-            inactive_tab: tab,
-        },
-        inactive_pane: {
-            active_tab: inactive_pane_active_tab,
-            inactive_tab: inactive_pane_inactive_tab,
-        },
-        dragged_tab,
-        pane_button: toggleable({
-            base: interactive({
-                base: {
-                    color: foreground(layer, "variant"),
-                    icon_width: 12,
-                    button_width: active_pane_active_tab.height,
-                },
-                state: {
-                    hovered: {
-                        color: foreground(layer, "hovered"),
-                    },
-                    clicked: {
-                        color: foreground(layer, "pressed"),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        color: foreground(layer, "accent"),
-                    },
-                    hovered: {
-                        color: foreground(layer, "hovered"),
-                    },
-                    clicked: {
-                        color: foreground(layer, "pressed"),
-                    },
-                },
-            },
-        }),
-        pane_button_container: {
-            background: tab.background,
-            border: {
-                ...tab.border,
-                right: false,
-            },
-        },
-        nav_button: nav_button,
-    }
-}

styles/src/style_tree/terminal.ts πŸ”—

@@ -1,54 +0,0 @@
-import { useTheme } from "../theme"
-
-export default function terminal() {
-    const theme = useTheme()
-
-    /**
-     * Colors are controlled per-cell in the terminal grid.
-     * Cells can be set to any of these more 'theme-capable' colors
-     * or can be set directly with RGB values.
-     * Here are the common interpretations of these names:
-     * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
-     */
-    return {
-        black: theme.ramps.neutral(0).hex(),
-        red: theme.ramps.red(0.5).hex(),
-        green: theme.ramps.green(0.5).hex(),
-        yellow: theme.ramps.yellow(0.5).hex(),
-        blue: theme.ramps.blue(0.5).hex(),
-        magenta: theme.ramps.magenta(0.5).hex(),
-        cyan: theme.ramps.cyan(0.5).hex(),
-        white: theme.ramps.neutral(1).hex(),
-        bright_black: theme.ramps.neutral(0.4).hex(),
-        bright_red: theme.ramps.red(0.25).hex(),
-        bright_green: theme.ramps.green(0.25).hex(),
-        bright_yellow: theme.ramps.yellow(0.25).hex(),
-        bright_blue: theme.ramps.blue(0.25).hex(),
-        bright_magenta: theme.ramps.magenta(0.25).hex(),
-        bright_cyan: theme.ramps.cyan(0.25).hex(),
-        bright_white: theme.ramps.neutral(1).hex(),
-        /**
-         * Default color for characters
-         */
-        foreground: theme.ramps.neutral(1).hex(),
-        /**
-         * Default color for the rectangle background of a cell
-         */
-        background: theme.ramps.neutral(0).hex(),
-        modal_background: theme.ramps.neutral(0.1).hex(),
-        /**
-         * Default color for the cursor
-         */
-        cursor: theme.players[0].cursor,
-        dim_black: theme.ramps.neutral(1).hex(),
-        dim_red: theme.ramps.red(0.75).hex(),
-        dim_green: theme.ramps.green(0.75).hex(),
-        dim_yellow: theme.ramps.yellow(0.75).hex(),
-        dim_blue: theme.ramps.blue(0.75).hex(),
-        dim_magenta: theme.ramps.magenta(0.75).hex(),
-        dim_cyan: theme.ramps.cyan(0.75).hex(),
-        dim_white: theme.ramps.neutral(0.6).hex(),
-        bright_foreground: theme.ramps.neutral(1).hex(),
-        dim_foreground: theme.ramps.neutral(0).hex(),
-    }
-}

styles/src/style_tree/titlebar.ts πŸ”—

@@ -1,287 +0,0 @@
-import { icon_button, text_button, toggleable_icon_button, toggleable_text_button } from "../component"
-import { interactive, toggleable } from "../element"
-import { useTheme, with_opacity } from "../theme"
-import { background, border, foreground, text } from "./components"
-
-const ITEM_SPACING = 8
-const TITLEBAR_HEIGHT = 32
-
-function build_spacing(
-    container_height: number,
-    element_height: number,
-    spacing: number
-) {
-    return {
-        group: spacing,
-        item: spacing / 2,
-        half_item: spacing / 4,
-        margin_y: (container_height - element_height) / 2,
-        margin_x: (container_height - element_height) / 2,
-    }
-}
-
-function call_controls() {
-    const theme = useTheme()
-
-    const button_height = 18
-
-    const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING)
-    const margin_y = {
-        top: space.margin_y,
-        bottom: space.margin_y,
-    }
-
-    return {
-        toggle_microphone_button: toggleable_icon_button({
-            margin: {
-                ...margin_y,
-                left: space.group,
-                right: space.half_item,
-            },
-            active_color: "negative",
-            active_background_color: "negative",
-        }),
-
-        toggle_speakers_button: toggleable_icon_button({
-            margin: {
-                ...margin_y,
-                left: space.half_item,
-                right: space.half_item,
-            },
-        }),
-
-        screen_share_button: toggleable_icon_button({
-            margin: {
-                ...margin_y,
-                left: space.half_item,
-                right: space.group,
-            },
-            active_color: "accent",
-            active_background_color: "accent",
-        }),
-
-        muted: foreground(theme.lowest, "negative"),
-        speaking: foreground(theme.lowest, "accent"),
-    }
-}
-
-/**
- * Opens the User Menu when toggled
- *
- * When logged in shows the user's avatar and a chevron,
- * When logged out only shows a chevron.
- */
-function user_menu() {
-    const theme = useTheme()
-
-    const button_height = 18
-
-    const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING)
-
-    const build_button = ({ online }: { online: boolean }) => {
-        const button = toggleable({
-            base: interactive({
-                base: {
-                    corner_radius: 6,
-                    height: button_height,
-                    width: 20,
-                    padding: {
-                        top: 2,
-                        bottom: 2,
-                        left: 6,
-                        right: 6,
-                    },
-                    margin: {
-                        left: space.item,
-                        right: space.item,
-                    },
-                    ...text(theme.lowest, "sans", { size: "xs" }),
-                    background: background(theme.lowest),
-                },
-                state: {
-                    hovered: {
-                        ...text(theme.lowest, "sans", "hovered", {
-                            size: "xs",
-                        }),
-                        background: background(theme.lowest, "hovered"),
-                    },
-                    clicked: {
-                        ...text(theme.lowest, "sans", "pressed", {
-                            size: "xs",
-                        }),
-                        background: background(theme.lowest, "pressed"),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        ...text(theme.lowest, "sans", "active", { size: "xs" }),
-                        background: background(theme.middle),
-                    },
-                    hovered: {
-                        ...text(theme.lowest, "sans", "active", { size: "xs" }),
-                        background: background(theme.middle, "hovered"),
-                    },
-                    clicked: {
-                        ...text(theme.lowest, "sans", "active", { size: "xs" }),
-                        background: background(theme.middle, "pressed"),
-                    },
-                },
-            },
-        })
-
-        return {
-            user_menu: button,
-            avatar: {
-                icon_width: 16,
-                icon_height: 16,
-                corner_radius: 4,
-                outer_width: 16,
-                outer_corner_radius: 16,
-            },
-            icon: {
-                margin: {
-                    top: 2,
-                    left: online ? space.item : 0,
-                    right: space.group,
-                    bottom: 2,
-                },
-                width: 11,
-                height: 11,
-                color: foreground(theme.lowest),
-            },
-        }
-    }
-
-    return {
-        user_menu_button_online: build_button({ online: true }),
-        user_menu_button_offline: build_button({ online: false }),
-    }
-}
-
-export function titlebar(): any {
-    const theme = useTheme()
-
-    const avatar_width = 15
-    const avatar_outer_width = avatar_width + 4
-    const follower_avatar_width = 14
-    const follower_avatar_outer_width = follower_avatar_width + 4
-
-    return {
-        item_spacing: ITEM_SPACING,
-        face_pile_spacing: 2,
-        height: TITLEBAR_HEIGHT,
-        background: background(theme.lowest),
-        border: border(theme.lowest, { bottom: true }),
-        padding: {
-            left: 80,
-            right: 0,
-        },
-        menu: {
-            width: 300,
-            height: 400,
-        },
-
-        project_menu_button: toggleable_text_button(theme, {
-            color: "base"
-        }),
-
-        git_menu_button: toggleable_text_button(theme, {
-            color: "variant",
-        }),
-
-        project_host: text_button({
-            text_properties: {
-                weight: "bold"
-            }
-        }),
-
-        // Collaborators
-        leader_avatar: {
-            width: avatar_width,
-            outer_width: avatar_outer_width,
-            corner_radius: avatar_width / 2,
-            outer_corner_radius: avatar_outer_width / 2,
-        },
-        follower_avatar: {
-            width: follower_avatar_width,
-            outer_width: follower_avatar_outer_width,
-            corner_radius: follower_avatar_width / 2,
-            outer_corner_radius: follower_avatar_outer_width / 2,
-        },
-        inactive_avatar_grayscale: true,
-        follower_avatar_overlap: 8,
-        leader_selection: {
-            margin: {
-                top: 4,
-                bottom: 4,
-            },
-            padding: {
-                left: 2,
-                right: 2,
-                top: 2,
-                bottom: 2,
-            },
-            corner_radius: 6,
-        },
-        avatar_ribbon: {
-            height: 3,
-            width: 14,
-            // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
-        },
-
-        sign_in_button: toggleable_text_button(theme, {}),
-        offline_icon: {
-            color: foreground(theme.lowest, "variant"),
-            width: 16,
-            margin: {
-                left: ITEM_SPACING,
-            },
-            padding: {
-                right: 4,
-            },
-        },
-
-        // When the collaboration server is out of date, show a warning
-        outdated_warning: {
-            ...text(theme.lowest, "sans", "warning", { size: "xs" }),
-            background: with_opacity(background(theme.lowest, "warning"), 0.3),
-            border: border(theme.lowest, "warning"),
-            margin: {
-                left: ITEM_SPACING,
-            },
-            padding: {
-                left: 8,
-                right: 8,
-            },
-            corner_radius: 6,
-        },
-
-        leave_call_button: icon_button({
-            margin: {
-                left: ITEM_SPACING / 2,
-                right: ITEM_SPACING,
-            },
-        }),
-
-        ...call_controls(),
-
-        toggle_contacts_button: toggleable_icon_button({
-            margin: {
-                left: ITEM_SPACING,
-            },
-        }),
-
-        // Jewel that notifies you that there are new contact requests
-        toggle_contacts_badge: {
-            corner_radius: 3,
-            padding: 2,
-            margin: { top: 3, left: 3 },
-            border: border(theme.lowest),
-            background: foreground(theme.lowest, "accent"),
-        },
-        share_button: toggleable_text_button(theme, {}),
-        user_menu: user_menu(),
-    }
-}

styles/src/style_tree/toolbar.ts πŸ”—

@@ -1,58 +0,0 @@
-import { useTheme } from "../common"
-import { toggleable_icon_button } from "../component/icon_button"
-import { interactive, toggleable } from "../element"
-import { background, border, foreground, text } from "./components"
-import { text_button } from "../component"
-
-export const toolbar = () => {
-    const theme = useTheme()
-
-    return {
-        height: 42,
-        padding: { left: 8, right: 8 },
-        background: background(theme.highest),
-        border: border(theme.highest, { bottom: true }),
-        item_spacing: 4,
-        toggleable_tool: toggleable_icon_button({
-            margin: { left: 4 },
-            variant: "ghost",
-            active_color: "accent",
-        }),
-        breadcrumb_height: 24,
-        breadcrumbs: interactive({
-            base: {
-                ...text(theme.highest, "sans", "variant"),
-                corner_radius: 6,
-                padding: {
-                    left: 4,
-                    right: 4,
-                }
-            },
-            state: {
-                hovered: {
-                    color: foreground(theme.highest, "on", "hovered"),
-                    background: background(theme.highest, "on", "hovered"),
-                },
-            },
-        }),
-        toggleable_text_tool: toggleable({
-            state: {
-                inactive: text_button({
-                    disabled: true,
-                    variant: "ghost",
-                    layer: theme.highest,
-                    margin: { left: 4 },
-                    text_properties: { size: "sm" },
-                    border: border(theme.middle),
-                }),
-                active: text_button({
-                    variant: "ghost",
-                    layer: theme.highest,
-                    margin: { left: 4 },
-                    text_properties: { size: "sm" },
-                    border: border(theme.middle),
-                }),
-            }
-        }),
-    }
-}

styles/src/style_tree/toolbar_dropdown_menu.ts πŸ”—

@@ -1,66 +0,0 @@
-import { background, border, text } from "./components"
-import { interactive, toggleable } from "../element"
-import { useTheme } from "../theme"
-export default function dropdown_menu(): any {
-    const theme = useTheme()
-
-    return {
-        row_height: 30,
-        background: background(theme.middle),
-        border: border(theme.middle),
-        shadow: theme.popover_shadow,
-        header: interactive({
-            base: {
-                ...text(theme.middle, "sans", { size: "sm" }),
-                secondary_text: text(theme.middle, "sans", {
-                    size: "sm",
-                    color: "#aaaaaa",
-                }),
-                secondary_text_spacing: 10,
-                padding: { left: 8, right: 8, top: 2, bottom: 2 },
-                corner_radius: 6,
-                background: background(theme.middle, "on"),
-            },
-            state: {
-                hovered: {
-                    background: background(theme.middle, "hovered"),
-                },
-                clicked: {
-                    background: background(theme.middle, "pressed"),
-                },
-            },
-        }),
-        section_header: {
-            ...text(theme.middle, "sans", { size: "sm" }),
-            padding: { left: 8, right: 8, top: 8, bottom: 8 },
-        },
-        item: toggleable({
-            base: interactive({
-                base: {
-                    ...text(theme.middle, "sans", { size: "sm" }),
-                    secondary_text_spacing: 10,
-                    secondary_text: text(theme.middle, "sans", { size: "sm" }),
-                    padding: { left: 18, right: 18, top: 2, bottom: 2 },
-                },
-                state: {
-                    hovered: {
-                        background: background(theme.middle, "hovered"),
-                        ...text(theme.middle, "sans", "hovered", {
-                            size: "sm",
-                        }),
-                    },
-                },
-            }),
-            state: {
-                active: {
-                    default: {
-                        background: background(theme.middle, "active"),
-                    },
-                    hovered: {
-                        background: background(theme.middle, "hovered"),
-                    },
-                },
-            },
-        }),
-    }
-}

styles/src/style_tree/tooltip.ts πŸ”—

@@ -1,24 +0,0 @@
-import { useTheme } from "../theme"
-import { background, border, text } from "./components"
-
-export default function tooltip(): any {
-    const theme = useTheme()
-
-    return {
-        background: background(theme.middle),
-        border: border(theme.middle),
-        padding: { top: 4, bottom: 4, left: 8, right: 8 },
-        margin: { top: 6, left: 6 },
-        shadow: theme.popover_shadow,
-        corner_radius: 6,
-        text: text(theme.middle, "sans", { size: "xs" }),
-        keystroke: {
-            background: background(theme.middle, "on"),
-            corner_radius: 4,
-            margin: { left: 6 },
-            padding: { left: 4, right: 4 },
-            ...text(theme.middle, "mono", "on", { size: "xs", weight: "bold" }),
-        },
-        max_text_width: 200,
-    }
-}

styles/src/style_tree/update_notification.ts πŸ”—

@@ -1,41 +0,0 @@
-import { foreground, text } from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-
-export default function update_notification(): any {
-    const theme = useTheme()
-
-    const header_padding = 8
-
-    return {
-        message: {
-            ...text(theme.middle, "sans", { size: "xs" }),
-            margin: { left: header_padding, right: header_padding },
-        },
-        action_message: interactive({
-            base: {
-                ...text(theme.middle, "sans", { size: "xs" }),
-                margin: { left: header_padding, top: 6, bottom: 6 },
-            },
-            state: {
-                hovered: {
-                    color: foreground(theme.middle, "hovered"),
-                },
-            },
-        }),
-        dismiss_button: interactive({
-            base: {
-                color: foreground(theme.middle),
-                icon_width: 14,
-                icon_height: 14,
-                button_width: 14,
-                button_height: 14,
-            },
-            state: {
-                hovered: {
-                    color: foreground(theme.middle, "hovered"),
-                },
-            },
-        }),
-    }
-}

styles/src/style_tree/welcome.ts πŸ”—

@@ -1,157 +0,0 @@
-import { with_opacity } from "../theme/color"
-import {
-    border,
-    background,
-    foreground,
-    text,
-    TextProperties,
-    svg,
-} from "./components"
-import { interactive } from "../element"
-import { useTheme } from "../theme"
-
-export default function welcome(): any {
-    const theme = useTheme()
-
-    const checkbox_base = {
-        corner_radius: 4,
-        padding: {
-            left: 3,
-            right: 3,
-            top: 3,
-            bottom: 3,
-        },
-        // shadow: theme.popover_shadow,
-        border: border(theme.highest),
-        margin: {
-            right: 8,
-            top: 5,
-            bottom: 5,
-        },
-    }
-
-    const interactive_text_size: TextProperties = { size: "sm" }
-
-    return {
-        page_width: 320,
-        logo: svg(
-            foreground(theme.highest, "default"),
-            "icons/logo_96.svg",
-            64,
-            64
-        ),
-        logo_subheading: {
-            ...text(theme.highest, "sans", "variant", { size: "md" }),
-            margin: {
-                top: 10,
-                bottom: 7,
-            },
-        },
-        button_group: {
-            margin: {
-                top: 8,
-                bottom: 16,
-            },
-        },
-        heading_group: {
-            margin: {
-                top: 8,
-                bottom: 12,
-            },
-        },
-        checkbox_group: {
-            border: border(theme.highest, "variant"),
-            background: with_opacity(
-                background(theme.highest, "hovered"),
-                0.25
-            ),
-            corner_radius: 4,
-            padding: {
-                left: 12,
-                top: 2,
-                bottom: 2,
-            },
-        },
-        button: interactive({
-            base: {
-                background: background(theme.highest),
-                border: border(theme.highest, "active"),
-                corner_radius: 4,
-                margin: {
-                    top: 4,
-                    bottom: 4,
-                },
-                padding: {
-                    top: 3,
-                    bottom: 3,
-                    left: 7,
-                    right: 7,
-                },
-                ...text(
-                    theme.highest,
-                    "sans",
-                    "default",
-                    interactive_text_size
-                ),
-            },
-            state: {
-                hovered: {
-                    ...text(
-                        theme.highest,
-                        "sans",
-                        "default",
-                        interactive_text_size
-                    ),
-                    background: background(theme.highest, "hovered"),
-                },
-            },
-        }),
-
-        usage_note: {
-            ...text(theme.highest, "sans", "variant", { size: "2xs" }),
-            padding: {
-                top: -4,
-            },
-        },
-        checkbox_container: {
-            margin: {
-                top: 4,
-            },
-            padding: {
-                bottom: 8,
-            },
-        },
-        checkbox: {
-            label: {
-                ...text(theme.highest, "sans", interactive_text_size),
-                // Also supports margin, container, border, etc.
-            },
-            icon: svg(
-                foreground(theme.highest, "on"),
-                "icons/check.svg",
-                12,
-                12
-            ),
-            default: {
-                ...checkbox_base,
-                background: background(theme.highest, "default"),
-                border: border(theme.highest, "active"),
-            },
-            checked: {
-                ...checkbox_base,
-                background: background(theme.highest, "hovered"),
-                border: border(theme.highest, "active"),
-            },
-            hovered: {
-                ...checkbox_base,
-                background: background(theme.highest, "hovered"),
-                border: border(theme.highest, "active"),
-            },
-            hovered_and_checked: {
-                ...checkbox_base,
-                background: background(theme.highest, "hovered"),
-                border: border(theme.highest, "active"),
-            },
-        },
-    }
-}

styles/src/style_tree/workspace.ts πŸ”—

@@ -1,153 +0,0 @@
-import { with_opacity } from "../theme/color"
-import {
-    background,
-    border,
-    border_color,
-    foreground,
-    svg,
-    text,
-} from "./components"
-import statusBar from "./status_bar"
-import tabBar from "./tab_bar"
-import { interactive } from "../element"
-import { titlebar } from "./titlebar"
-import { useTheme } from "../theme"
-import { toolbar } from "./toolbar"
-
-export default function workspace(): any {
-    const theme = useTheme()
-
-    const { is_light } = theme
-
-    return {
-        background: background(theme.lowest),
-        blank_pane: {
-            logo_container: {
-                width: 256,
-                height: 256,
-            },
-            logo: svg(
-                with_opacity("#000000", theme.is_light ? 0.6 : 0.8),
-                "icons/logo_96.svg",
-                256,
-                256
-            ),
-
-            logo_shadow: svg(
-                with_opacity(
-                    theme.is_light
-                        ? "#FFFFFF"
-                        : theme.lowest.base.default.background,
-                    theme.is_light ? 1 : 0.6
-                ),
-                "icons/logo_96.svg",
-                256,
-                256
-            ),
-            keyboard_hints: {
-                margin: {
-                    top: 96,
-                },
-                corner_radius: 4,
-            },
-            keyboard_hint: interactive({
-                base: {
-                    ...text(theme.lowest, "sans", "variant", { size: "sm" }),
-                    padding: {
-                        top: 3,
-                        left: 8,
-                        right: 8,
-                        bottom: 3,
-                    },
-                    corner_radius: 8,
-                },
-                state: {
-                    hovered: {
-                        ...text(theme.lowest, "sans", "active", { size: "sm" }),
-                    },
-                },
-            }),
-
-            keyboard_hint_width: 320,
-        },
-        joining_project_avatar: {
-            corner_radius: 40,
-            width: 80,
-        },
-        joining_project_message: {
-            padding: 12,
-            ...text(theme.lowest, "sans", { size: "lg" }),
-        },
-        external_location_message: {
-            background: background(theme.middle, "accent"),
-            border: border(theme.middle, "accent"),
-            corner_radius: 6,
-            padding: 12,
-            margin: { bottom: 8, right: 8 },
-            ...text(theme.middle, "sans", "accent", { size: "xs" }),
-        },
-        leader_border_opacity: 0.7,
-        leader_border_width: 2.0,
-        tab_bar: tabBar(),
-        modal: {
-            margin: {
-                bottom: 52,
-                top: 52,
-            },
-            cursor: "Arrow",
-        },
-        zoomed_background: {
-            cursor: "Arrow",
-            background: is_light
-                ? with_opacity(background(theme.lowest), 0.8)
-                : with_opacity(background(theme.highest), 0.6),
-        },
-        zoomed_pane_foreground: {
-            margin: 16,
-            shadow: theme.modal_shadow,
-            border: border(theme.lowest, { overlay: true }),
-        },
-        zoomed_panel_foreground: {
-            margin: 16,
-            border: border(theme.lowest, { overlay: true }),
-        },
-        dock: {
-            left: {
-                border: border(theme.lowest, { right: true }),
-            },
-            bottom: {
-                border: border(theme.lowest, { top: true }),
-            },
-            right: {
-                border: border(theme.lowest, { left: true }),
-            },
-        },
-        pane_divider: {
-            color: border_color(theme.lowest),
-            width: 1,
-        },
-        status_bar: statusBar(),
-        titlebar: titlebar(),
-        toolbar: toolbar(),
-        disconnected_overlay: {
-            ...text(theme.lowest, "sans"),
-            background: with_opacity(background(theme.lowest), 0.8),
-        },
-        notification: {
-            margin: { top: 10 },
-            background: background(theme.middle),
-            corner_radius: 6,
-            padding: 12,
-            border: border(theme.middle),
-            shadow: theme.popover_shadow,
-        },
-        notifications: {
-            width: 400,
-            margin: { right: 10, bottom: 10 },
-        },
-        drop_target_overlay_color: with_opacity(
-            foreground(theme.lowest, "variant"),
-            0.5
-        ),
-    }
-}

styles/src/theme/color.ts πŸ”—

@@ -1,5 +0,0 @@
-import chroma from "chroma-js"
-
-export function with_opacity(color: string, opacity: number): string {
-    return chroma(color).alpha(opacity).hex()
-}

styles/src/theme/create_theme.ts πŸ”—

@@ -1,329 +0,0 @@
-import { Scale, Color } from "chroma-js"
-import { Syntax, ThemeSyntax, SyntaxHighlightStyle } from "./syntax"
-export { Syntax, ThemeSyntax, SyntaxHighlightStyle }
-import {
-    ThemeConfig,
-    ThemeAppearance,
-    ThemeConfigInputColors,
-} from "./theme_config"
-import { get_ramps } from "./ramps"
-
-export interface Theme {
-    name: string
-    is_light: boolean
-
-    /**
-     * App background, other elements that should sit directly on top of the background.
-     */
-    lowest: Layer
-    /**
-     * Panels, tabs, other UI surfaces that sit on top of the background.
-     */
-    middle: Layer
-    /**
-     * Editors like code buffers, conversation editors, etc.
-     */
-    highest: Layer
-
-    ramps: RampSet
-
-    popover_shadow: Shadow
-    modal_shadow: Shadow
-
-    players: Players
-    syntax?: Partial<ThemeSyntax>
-    color_family: ColorFamily
-}
-
-export interface Meta {
-    name: string
-    author: string
-    url: string
-    license: License
-}
-
-export interface License {
-    SPDX: SPDXExpression
-}
-
-// License name -> License text
-export interface Licenses {
-    [key: string]: string
-}
-
-// FIXME: Add support for the SPDX expression syntax
-export type SPDXExpression = "MIT"
-
-export interface Player {
-    cursor: string
-    selection: string
-}
-
-export interface Players {
-    "0": Player
-    "1": Player
-    "2": Player
-    "3": Player
-    "4": Player
-    "5": Player
-    "6": Player
-    "7": Player
-}
-
-export type ColorFamily = Partial<{ [K in keyof RampSet]: ColorFamilyRange }>
-
-export interface ColorFamilyRange {
-    low: number
-    high: number
-    range: number
-    scaling_value: number
-}
-
-export interface Shadow {
-    blur: number
-    color: string
-    offset: number[]
-}
-
-export type StyleSets = keyof Layer
-export interface Layer {
-    base: StyleSet
-    variant: StyleSet
-    on: StyleSet
-    accent: StyleSet
-    positive: StyleSet
-    warning: StyleSet
-    negative: StyleSet
-}
-
-export interface RampSet {
-    neutral: Scale
-    red: Scale
-    orange: Scale
-    yellow: Scale
-    green: Scale
-    cyan: Scale
-    blue: Scale
-    violet: Scale
-    magenta: Scale
-}
-
-export type Styles = keyof StyleSet
-export interface StyleSet {
-    default: Style
-    active: Style
-    disabled: Style
-    hovered: Style
-    pressed: Style
-    inverted: Style
-}
-
-export interface Style {
-    background: string
-    border: string
-    foreground: string
-}
-
-export function create_theme(theme: ThemeConfig): Theme {
-    const {
-        name,
-        appearance,
-        input_color,
-        override: { syntax },
-    } = theme
-
-    const is_light = appearance === ThemeAppearance.Light
-    const color_ramps: ThemeConfigInputColors = input_color
-
-    // Chromajs scales from 0 to 1 flipped if is_light is true
-    const ramps = get_ramps(is_light, color_ramps)
-    const lowest = lowest_layer(ramps)
-    const middle = middle_layer(ramps)
-    const highest = highest_layer(ramps)
-
-    const popover_shadow = {
-        blur: 4,
-        color: ramps
-            .neutral(is_light ? 7 : 0)
-            .darken()
-            .alpha(0.2)
-            .hex(), // TODO used blend previously. Replace with something else
-        offset: [1, 2],
-    }
-
-    const modal_shadow = {
-        blur: 16,
-        color: ramps
-            .neutral(is_light ? 7 : 0)
-            .darken()
-            .alpha(0.2)
-            .hex(), // TODO used blend previously. Replace with something else
-        offset: [0, 2],
-    }
-
-    const players = {
-        "0": player(ramps.blue),
-        "1": player(ramps.green),
-        "2": player(ramps.magenta),
-        "3": player(ramps.orange),
-        "4": player(ramps.violet),
-        "5": player(ramps.cyan),
-        "6": player(ramps.red),
-        "7": player(ramps.yellow),
-    }
-
-    const color_family = build_color_family(ramps)
-
-    return {
-        name,
-        is_light,
-
-        ramps,
-
-        lowest,
-        middle,
-        highest,
-
-        popover_shadow,
-        modal_shadow,
-
-        players,
-        syntax,
-        color_family,
-    }
-}
-
-function player(ramp: Scale): Player {
-    return {
-        selection: ramp(0.5).alpha(0.24).hex(),
-        cursor: ramp(0.5).hex(),
-    }
-}
-
-function build_color_family(ramps: RampSet): ColorFamily {
-    const color_family: ColorFamily = {}
-
-    for (const ramp in ramps) {
-        const ramp_value = ramps[ramp as keyof RampSet]
-
-        const lightnessValues = [
-            ramp_value(0).get("hsl.l") * 100,
-            ramp_value(1).get("hsl.l") * 100,
-        ]
-        const low = Math.min(...lightnessValues)
-        const high = Math.max(...lightnessValues)
-        const range = high - low
-
-        color_family[ramp as keyof RampSet] = {
-            low,
-            high,
-            range,
-            scaling_value: 100 / range,
-        }
-    }
-
-    return color_family
-}
-
-function lowest_layer(ramps: RampSet): Layer {
-    return {
-        base: build_style_set(ramps.neutral, 0.2, 1),
-        variant: build_style_set(ramps.neutral, 0.2, 0.7),
-        on: build_style_set(ramps.neutral, 0.1, 1),
-        accent: build_style_set(ramps.blue, 0.1, 0.5),
-        positive: build_style_set(ramps.green, 0.1, 0.5),
-        warning: build_style_set(ramps.yellow, 0.1, 0.5),
-        negative: build_style_set(ramps.red, 0.1, 0.5),
-    }
-}
-
-function middle_layer(ramps: RampSet): Layer {
-    return {
-        base: build_style_set(ramps.neutral, 0.1, 1),
-        variant: build_style_set(ramps.neutral, 0.1, 0.7),
-        on: build_style_set(ramps.neutral, 0, 1),
-        accent: build_style_set(ramps.blue, 0.1, 0.5),
-        positive: build_style_set(ramps.green, 0.1, 0.5),
-        warning: build_style_set(ramps.yellow, 0.1, 0.5),
-        negative: build_style_set(ramps.red, 0.1, 0.5),
-    }
-}
-
-function highest_layer(ramps: RampSet): Layer {
-    return {
-        base: build_style_set(ramps.neutral, 0, 1),
-        variant: build_style_set(ramps.neutral, 0, 0.7),
-        on: build_style_set(ramps.neutral, 0.1, 1),
-        accent: build_style_set(ramps.blue, 0.1, 0.5),
-        positive: build_style_set(ramps.green, 0.1, 0.5),
-        warning: build_style_set(ramps.yellow, 0.1, 0.5),
-        negative: build_style_set(ramps.red, 0.1, 0.5),
-    }
-}
-
-function build_style_set(
-    ramp: Scale,
-    background_base: number,
-    foreground_base: number,
-    step = 0.08
-): StyleSet {
-    const style_definitions = build_style_definition(
-        background_base,
-        foreground_base,
-        step
-    )
-
-    function color_string(index_or_color: number | Color): string {
-        if (typeof index_or_color === "number") {
-            return ramp(index_or_color).hex()
-        } else {
-            return index_or_color.hex()
-        }
-    }
-
-    function build_style(style: Styles): Style {
-        return {
-            background: color_string(style_definitions.background[style]),
-            border: color_string(style_definitions.border[style]),
-            foreground: color_string(style_definitions.foreground[style]),
-        }
-    }
-
-    return {
-        default: build_style("default"),
-        hovered: build_style("hovered"),
-        pressed: build_style("pressed"),
-        active: build_style("active"),
-        disabled: build_style("disabled"),
-        inverted: build_style("inverted"),
-    }
-}
-
-function build_style_definition(bg_base: number, fg_base: number, step = 0.08) {
-    return {
-        background: {
-            default: bg_base,
-            hovered: bg_base + step,
-            pressed: bg_base + step * 1.5,
-            active: bg_base + step * 2.2,
-            disabled: bg_base,
-            inverted: fg_base + step * 6,
-        },
-        border: {
-            default: bg_base + step * 1,
-            hovered: bg_base + step,
-            pressed: bg_base + step,
-            active: bg_base + step * 3,
-            disabled: bg_base + step * 0.5,
-            inverted: bg_base - step * 3,
-        },
-        foreground: {
-            default: fg_base,
-            hovered: fg_base,
-            pressed: fg_base,
-            active: fg_base + step * 6,
-            disabled: bg_base + step * 4,
-            inverted: bg_base + step * 2,
-        },
-    }
-}

styles/src/theme/index.ts πŸ”—

@@ -1,26 +0,0 @@
-import { create } from "zustand"
-import { Theme } from "./create_theme"
-
-type ThemeState = {
-    theme: Theme | undefined
-    setTheme: (theme: Theme) => void
-}
-
-export const useThemeStore = create<ThemeState>((set) => ({
-    theme: undefined,
-    setTheme: (theme) => set(() => ({ theme })),
-}))
-
-export const useTheme = (): Theme => {
-    const { theme } = useThemeStore.getState()
-
-    if (!theme) throw new Error("Tried to use theme before it was loaded")
-
-    return theme
-}
-
-export * from "./create_theme"
-export * from "./ramps"
-export * from "./syntax"
-export * from "./theme_config"
-export * from "./color"

styles/src/theme/ramps.ts πŸ”—

@@ -1,47 +0,0 @@
-import chroma, { Color, Scale } from "chroma-js"
-import { RampSet } from "./create_theme"
-import {
-    ThemeConfigInputColors,
-    ThemeConfigInputColorsKeys,
-} from "./theme_config"
-
-export function color_ramp(color: Color): Scale {
-    const end_color = color.desaturate(1).brighten(5)
-    const start_color = color.desaturate(1).darken(4)
-    return chroma.scale([start_color, color, end_color]).mode("lab")
-}
-
-/**
- * Chromajs mutates the underlying ramp when you call domain. This causes problems because
-    we now store the ramps object in the theme so that we can pull colors out of them.
-    So instead of calling domain and storing the result, we have to construct new ramps for each
-    theme so that we don't modify the passed in ramps.
-    This combined with an error in the type definitions for chroma js means we have to cast the colors
-    function to any in order to get the colors back out from the original ramps.
- * @param is_light
- * @param color_ramps
- * @returns
- */
-export function get_ramps(
-    is_light: boolean,
-    color_ramps: ThemeConfigInputColors
-): RampSet {
-    const ramps: RampSet = {} as any // eslint-disable-line @typescript-eslint/no-explicit-any
-    const color_keys = Object.keys(color_ramps) as ThemeConfigInputColorsKeys[]
-
-    if (is_light) {
-        for (const ramp_name of color_keys) {
-            ramps[ramp_name] = chroma.scale(
-                color_ramps[ramp_name].colors(100).reverse()
-            )
-        }
-        ramps.neutral = chroma.scale(color_ramps.neutral.colors(100).reverse())
-    } else {
-        for (const ramp_name of color_keys) {
-            ramps[ramp_name] = chroma.scale(color_ramps[ramp_name].colors(100))
-        }
-        ramps.neutral = chroma.scale(color_ramps.neutral.colors(100))
-    }
-
-    return ramps
-}

styles/src/theme/syntax.ts πŸ”—

@@ -1,332 +0,0 @@
-import deepmerge from "deepmerge"
-import { FontWeight, font_weights, useTheme } from "../common"
-import chroma from "chroma-js"
-
-export interface SyntaxHighlightStyle {
-    color?: string
-    weight?: FontWeight
-    underline?: boolean
-    italic?: boolean
-}
-
-export interface Syntax {
-    // == Text Styles ====== /
-    comment: SyntaxHighlightStyle
-    // elixir: doc comment
-    "comment.doc": SyntaxHighlightStyle
-    primary: SyntaxHighlightStyle
-    predictive: SyntaxHighlightStyle
-    hint: SyntaxHighlightStyle
-
-    // === Formatted Text ====== /
-    emphasis: SyntaxHighlightStyle
-    "emphasis.strong": SyntaxHighlightStyle
-    title: SyntaxHighlightStyle
-    link_uri: SyntaxHighlightStyle
-    link_text: SyntaxHighlightStyle
-    /** md: indented_code_block, fenced_code_block, code_span */
-    "text.literal": SyntaxHighlightStyle
-
-    // == Punctuation ====== /
-    punctuation: SyntaxHighlightStyle
-    /** Example: `(`, `[`, `{`...*/
-    "punctuation.bracket": SyntaxHighlightStyle
-    /**., ;*/
-    "punctuation.delimiter": SyntaxHighlightStyle
-    // js, ts: ${, } in a template literal
-    // yaml: *, &, ---, ...
-    "punctuation.special": SyntaxHighlightStyle
-    // md: list_marker_plus, list_marker_dot, etc
-    "punctuation.list_marker": SyntaxHighlightStyle
-
-    // == Strings ====== /
-
-    string: SyntaxHighlightStyle
-    // css: color_value
-    // js: this, super
-    // toml: offset_date_time, local_date_time...
-    "string.special": SyntaxHighlightStyle
-    // elixir: atom, quoted_atom, keyword, quoted_keyword
-    // ruby: simple_symbol, delimited_symbol...
-    "string.special.symbol"?: SyntaxHighlightStyle
-    // elixir, python, yaml...: escape_sequence
-    "string.escape"?: SyntaxHighlightStyle
-    // Regular expressions
-    "string.regex"?: SyntaxHighlightStyle
-
-    // == Types ====== /
-    // We allow Function here because all JS objects literals have this property
-    constructor: SyntaxHighlightStyle | Function // eslint-disable-line  @typescript-eslint/ban-types
-    variant: SyntaxHighlightStyle
-    type: SyntaxHighlightStyle
-    // js: predefined_type
-    "type.builtin"?: SyntaxHighlightStyle
-
-    // == Values
-    variable: SyntaxHighlightStyle
-    // this, ...
-    // css: -- (var(--foo))
-    // lua: self
-    "variable.special"?: SyntaxHighlightStyle
-    // c: statement_identifier,
-    label: SyntaxHighlightStyle
-    // css: tag_name, nesting_selector, universal_selector...
-    tag: SyntaxHighlightStyle
-    // css: attribute, pseudo_element_selector (tag_name),
-    attribute: SyntaxHighlightStyle
-    // css: class_name, property_name, namespace_name...
-    property: SyntaxHighlightStyle
-    // true, false, null, nullptr
-    constant: SyntaxHighlightStyle
-    // css: @media, @import, @supports...
-    // js: declare, implements, interface, keyof, public...
-    keyword: SyntaxHighlightStyle
-    // note: js enum is currently defined as a keyword
-    enum: SyntaxHighlightStyle
-    // -, --, ->, !=, &&, ||, <=...
-    operator: SyntaxHighlightStyle
-    number: SyntaxHighlightStyle
-    boolean: SyntaxHighlightStyle
-    // elixir: __MODULE__, __DIR__, __ENV__, etc
-    // go: nil, iota
-    "constant.builtin"?: SyntaxHighlightStyle
-
-    // == Functions ====== /
-
-    function: SyntaxHighlightStyle
-    // lua: assert, error, loadfile, tostring, unpack...
-    "function.builtin"?: SyntaxHighlightStyle
-    // go: call_expression, method_declaration
-    // js: call_expression, method_definition, pair (key, arrow function)
-    // rust: function_item name: (identifier)
-    "function.definition"?: SyntaxHighlightStyle
-    // rust: macro_definition name: (identifier)
-    "function.special.definition"?: SyntaxHighlightStyle
-    "function.method"?: SyntaxHighlightStyle
-    // ruby: identifier/"defined?" // Nate note: I don't fully understand this one.
-    "function.method.builtin"?: SyntaxHighlightStyle
-
-    // == Unsorted ====== /
-    // lua: hash_bang_line
-    preproc: SyntaxHighlightStyle
-    // elixir, python: interpolation (ex: foo in ${foo})
-    // js: template_substitution
-    embedded: SyntaxHighlightStyle
-}
-
-export type ThemeSyntax = Partial<Syntax>
-
-const default_syntax_highlight_style: Omit<SyntaxHighlightStyle, "color"> = {
-    weight: "normal",
-    underline: false,
-    italic: false,
-}
-
-function build_default_syntax(): Syntax {
-    const theme = useTheme()
-
-    // Make a temporary object that is allowed to be missing
-    // the "color" property for each style
-    const syntax: {
-        [key: string]: Omit<SyntaxHighlightStyle, "color">
-    } = {}
-
-    // then spread the default to each style
-    for (const key of Object.keys({} as Syntax)) {
-        syntax[key as keyof Syntax] = {
-            ...default_syntax_highlight_style,
-        }
-    }
-
-    // Mix the neutral and blue colors to get a
-    // predictive color distinct from any other color in the theme
-    const predictive = chroma
-        .mix(
-            theme.ramps.neutral(0.4).hex(),
-            theme.ramps.blue(0.4).hex(),
-            0.45,
-            "lch"
-        )
-        .hex()
-    // Mix the neutral and green colors to get a
-    // hint color distinct from any other color in the theme
-    const hint = chroma
-        .mix(
-            theme.ramps.neutral(0.6).hex(),
-            theme.ramps.blue(0.4).hex(),
-            0.45,
-            "lch"
-        )
-        .hex()
-
-    const color = {
-        primary: theme.ramps.neutral(1).hex(),
-        comment: theme.ramps.neutral(0.71).hex(),
-        punctuation: theme.ramps.neutral(0.86).hex(),
-        predictive: predictive,
-        hint: hint,
-        emphasis: theme.ramps.blue(0.5).hex(),
-        string: theme.ramps.orange(0.5).hex(),
-        function: theme.ramps.yellow(0.5).hex(),
-        type: theme.ramps.cyan(0.5).hex(),
-        constructor: theme.ramps.blue(0.5).hex(),
-        variant: theme.ramps.blue(0.5).hex(),
-        property: theme.ramps.blue(0.5).hex(),
-        enum: theme.ramps.orange(0.5).hex(),
-        operator: theme.ramps.orange(0.5).hex(),
-        number: theme.ramps.green(0.5).hex(),
-        boolean: theme.ramps.green(0.5).hex(),
-        constant: theme.ramps.green(0.5).hex(),
-        keyword: theme.ramps.blue(0.5).hex(),
-    }
-
-    // Then assign colors and use Syntax to enforce each style getting it's own color
-    const default_syntax: Syntax = {
-        ...syntax,
-        comment: {
-            color: color.comment,
-        },
-        "comment.doc": {
-            color: color.comment,
-        },
-        primary: {
-            color: color.primary,
-        },
-        predictive: {
-            color: color.predictive,
-            italic: true,
-        },
-        hint: {
-            color: color.hint,
-            weight: font_weights.bold,
-        },
-        emphasis: {
-            color: color.emphasis,
-        },
-        "emphasis.strong": {
-            color: color.emphasis,
-            weight: font_weights.bold,
-        },
-        title: {
-            color: color.primary,
-            weight: font_weights.bold,
-        },
-        link_uri: {
-            color: theme.ramps.green(0.5).hex(),
-            underline: true,
-        },
-        link_text: {
-            color: theme.ramps.orange(0.5).hex(),
-            italic: true,
-        },
-        "text.literal": {
-            color: color.string,
-        },
-        punctuation: {
-            color: color.punctuation,
-        },
-        "punctuation.bracket": {
-            color: color.punctuation,
-        },
-        "punctuation.delimiter": {
-            color: color.punctuation,
-        },
-        "punctuation.special": {
-            color: theme.ramps.neutral(0.86).hex(),
-        },
-        "punctuation.list_marker": {
-            color: color.punctuation,
-        },
-        string: {
-            color: color.string,
-        },
-        "string.special": {
-            color: color.string,
-        },
-        "string.special.symbol": {
-            color: color.string,
-        },
-        "string.escape": {
-            color: color.comment,
-        },
-        "string.regex": {
-            color: color.string,
-        },
-        constructor: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        variant: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        type: {
-            color: color.type,
-        },
-        variable: {
-            color: color.primary,
-        },
-        label: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        tag: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        attribute: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        property: {
-            color: theme.ramps.blue(0.5).hex(),
-        },
-        constant: {
-            color: color.constant,
-        },
-        keyword: {
-            color: color.keyword,
-        },
-        enum: {
-            color: color.enum,
-        },
-        operator: {
-            color: color.operator,
-        },
-        number: {
-            color: color.number,
-        },
-        boolean: {
-            color: color.boolean,
-        },
-        function: {
-            color: color.function,
-        },
-        preproc: {
-            color: color.primary,
-        },
-        embedded: {
-            color: color.primary,
-        },
-    }
-
-    return default_syntax
-}
-
-export function build_syntax(): Syntax {
-    const theme = useTheme()
-
-    const default_syntax: Syntax = build_default_syntax()
-
-    if (!theme.syntax) {
-        return default_syntax
-    }
-
-    const syntax = deepmerge<Syntax, Partial<ThemeSyntax>>(
-        default_syntax,
-        theme.syntax,
-        {
-            arrayMerge: (destinationArray, sourceArray) => [
-                ...destinationArray,
-                ...sourceArray,
-            ],
-        }
-    )
-
-    return syntax
-}

styles/src/theme/theme_config.ts πŸ”—

@@ -1,81 +0,0 @@
-import { Scale, Color } from "chroma-js"
-import { Syntax } from "./syntax"
-
-interface ThemeMeta {
-    /** The name of the theme */
-    name: string
-    /** The theme's appearance. Either `light` or `dark`. */
-    appearance: ThemeAppearance
-    /** The author of the theme
-     *
-     * Ideally formatted as `Full Name <email>`
-     *
-     * Example: `John Doe <john@doe.com>`
-     */
-    author: string
-    /** SPDX License string
-     *
-     * Example: `MIT`
-     */
-    license_type?: string | ThemeLicenseType
-    license_url?: string
-    license_file: string
-    theme_url?: string
-}
-
-export type ThemeFamilyMeta = Pick<
-    ThemeMeta,
-    "name" | "author" | "license_type" | "license_url"
->
-
-export interface ThemeConfigInputColors {
-    neutral: Scale<Color>
-    red: Scale<Color>
-    orange: Scale<Color>
-    yellow: Scale<Color>
-    green: Scale<Color>
-    cyan: Scale<Color>
-    blue: Scale<Color>
-    violet: Scale<Color>
-    magenta: Scale<Color>
-}
-
-export type ThemeConfigInputColorsKeys = keyof ThemeConfigInputColors
-
-/** Allow any part of a syntax highlight style to be overriden by the theme
- *
- * Example:
- * ```ts
- * override: {
- *   syntax: {
- *     boolean: {
- *       underline: true,
- *     },
- *   },
- * }
- * ```
- */
-export type ThemeConfigInputSyntax = Partial<Syntax>
-
-interface ThemeConfigOverrides {
-    syntax: ThemeConfigInputSyntax
-}
-
-type ThemeConfigProperties = ThemeMeta & {
-    input_color: ThemeConfigInputColors
-    override: ThemeConfigOverrides
-}
-
-export type ThemeConfig = {
-    [K in keyof ThemeConfigProperties]: ThemeConfigProperties[K]
-}
-
-export enum ThemeAppearance {
-    Light = "light",
-    Dark = "dark",
-}
-
-export enum ThemeLicenseType {
-    MIT = "MIT",
-    Apache2 = "Apache License 2.0",
-}

styles/src/theme/tokens/layer.ts πŸ”—

@@ -1,63 +0,0 @@
-import { SingleColorToken } from "@tokens-studio/types"
-import { Layer, Style, StyleSet } from "../create_theme"
-import { color_token } from "./token"
-
-interface StyleToken {
-    background: SingleColorToken
-    border: SingleColorToken
-    foreground: SingleColorToken
-}
-
-interface StyleSetToken {
-    default: StyleToken
-    active: StyleToken
-    disabled: StyleToken
-    hovered: StyleToken
-    pressed: StyleToken
-    inverted: StyleToken
-}
-
-export interface LayerToken {
-    base: StyleSetToken
-    variant: StyleSetToken
-    on: StyleSetToken
-    accent: StyleSetToken
-    positive: StyleSetToken
-    warning: StyleSetToken
-    negative: StyleSetToken
-}
-
-export const style_token = (style: Style, name: string): StyleToken => {
-    const token = {
-        background: color_token(`${name}Background`, style.background),
-        border: color_token(`${name}Border`, style.border),
-        foreground: color_token(`${name}Foreground`, style.foreground),
-    }
-
-    return token
-}
-
-export const style_set_token = (
-    style_set: StyleSet,
-    name: string
-): StyleSetToken => {
-    const token: StyleSetToken = {} as StyleSetToken
-
-    for (const style in style_set) {
-        const s = style as keyof StyleSet
-        token[s] = style_token(style_set[s], `${name}${style}`)
-    }
-
-    return token
-}
-
-export const layer_token = (layer: Layer, name: string): LayerToken => {
-    const token: LayerToken = {} as LayerToken
-
-    for (const style_set in layer) {
-        const s = style_set as keyof Layer
-        token[s] = style_set_token(layer[s], `${name}${style_set}`)
-    }
-
-    return token
-}

styles/src/theme/tokens/players.ts πŸ”—

@@ -1,37 +0,0 @@
-import { SingleColorToken } from "@tokens-studio/types"
-import { color_token } from "./token"
-import { Players } from "../create_theme"
-import { useTheme } from "../../../src/common"
-
-export type PlayerToken = Record<"selection" | "cursor", SingleColorToken>
-
-export type PlayersToken = Record<keyof Players, PlayerToken>
-
-function build_player_token(index: number): PlayerToken {
-    const theme = useTheme()
-    const player_number = index.toString() as keyof Players
-
-    return {
-        selection: color_token(
-            `player${index}Selection`,
-            theme.players[player_number].selection
-        ),
-        cursor: color_token(
-            `player${index}Cursor`,
-            theme.players[player_number].cursor
-        ),
-    }
-}
-
-export const players_token = (): PlayersToken => {
-    return {
-        "0": build_player_token(0),
-        "1": build_player_token(1),
-        "2": build_player_token(2),
-        "3": build_player_token(3),
-        "4": build_player_token(4),
-        "5": build_player_token(5),
-        "6": build_player_token(6),
-        "7": build_player_token(7),
-    }
-}

styles/src/theme/tokens/theme.ts πŸ”—

@@ -1,97 +0,0 @@
-import {
-    SingleBoxShadowToken,
-    SingleColorToken,
-    SingleOtherToken,
-    TokenTypes,
-} from "@tokens-studio/types"
-import { Shadow, SyntaxHighlightStyle, ThemeSyntax } from "../create_theme"
-import { LayerToken, layer_token } from "./layer"
-import { PlayersToken, players_token } from "./players"
-import { color_token } from "./token"
-import { Syntax } from "../syntax"
-import editor from "../../style_tree/editor"
-import { useTheme } from "../../../src/common"
-
-interface ThemeTokens {
-    name: SingleOtherToken
-    appearance: SingleOtherToken
-    lowest: LayerToken
-    middle: LayerToken
-    highest: LayerToken
-    players: PlayersToken
-    popover_shadow: SingleBoxShadowToken
-    modal_shadow: SingleBoxShadowToken
-    syntax?: Partial<ThemeSyntaxColorTokens>
-}
-
-const create_shadow_token = (
-    shadow: Shadow,
-    token_name: string
-): SingleBoxShadowToken => {
-    return {
-        name: token_name,
-        type: TokenTypes.BOX_SHADOW,
-        value: `${shadow.offset[0]}px ${shadow.offset[1]}px ${shadow.blur}px 0px ${shadow.color}`,
-    }
-}
-
-const popover_shadow_token = (): SingleBoxShadowToken => {
-    const theme = useTheme()
-    const shadow = theme.popover_shadow
-    return create_shadow_token(shadow, "popover_shadow")
-}
-
-const modal_shadow_token = (): SingleBoxShadowToken => {
-    const theme = useTheme()
-    const shadow = theme.modal_shadow
-    return create_shadow_token(shadow, "modal_shadow")
-}
-
-type ThemeSyntaxColorTokens = Record<keyof ThemeSyntax, SingleColorToken>
-
-function syntax_highlight_style_color_tokens(
-    syntax: Syntax
-): ThemeSyntaxColorTokens {
-    const style_keys = Object.keys(syntax) as (keyof Syntax)[]
-
-    return style_keys.reduce((acc, style_key) => {
-        // Hack: The type of a style could be "Function"
-        // This can happen because we have a "constructor" property on the syntax object
-        // and a "constructor" property on the prototype of the syntax object
-        // To work around this just assert that the type of the style is not a function
-        if (!syntax[style_key] || typeof syntax[style_key] === "function")
-            return acc
-        const { color } = syntax[style_key] as Required<SyntaxHighlightStyle>
-        return { ...acc, [style_key]: color_token(style_key, color) }
-    }, {} as ThemeSyntaxColorTokens)
-}
-
-const syntax_tokens = (): ThemeTokens["syntax"] => {
-    const syntax = editor().syntax
-
-    return syntax_highlight_style_color_tokens(syntax)
-}
-
-export function theme_tokens(): ThemeTokens {
-    const theme = useTheme()
-
-    return {
-        name: {
-            name: "themeName",
-            value: theme.name,
-            type: TokenTypes.OTHER,
-        },
-        appearance: {
-            name: "themeAppearance",
-            value: theme.is_light ? "light" : "dark",
-            type: TokenTypes.OTHER,
-        },
-        lowest: layer_token(theme.lowest, "lowest"),
-        middle: layer_token(theme.middle, "middle"),
-        highest: layer_token(theme.highest, "highest"),
-        popover_shadow: popover_shadow_token(),
-        modal_shadow: modal_shadow_token(),
-        players: players_token(),
-        syntax: syntax_tokens(),
-    }
-}

styles/src/theme/tokens/token.ts πŸ”—

@@ -1,19 +0,0 @@
-import { SingleColorToken, TokenTypes } from "@tokens-studio/types"
-
-export function color_token(
-    name: string,
-    value: string,
-    description?: string
-): SingleColorToken {
-    const token: SingleColorToken = {
-        name,
-        type: TokenTypes.COLOR,
-        value,
-        description,
-    }
-
-    if (!token.value || token.value === "")
-        throw new Error("Color token must have a value")
-
-    return token
-}

styles/src/themes/andromeda/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2017 <eliverlara@gmail.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/andromeda/andromeda.ts πŸ”—

@@ -1,39 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-export const dark: ThemeConfig = {
-    name: "Andromeda",
-    author: "EliverLara",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/EliverLara/Andromeda",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale([
-                "#1E2025",
-                "#23262E",
-                "#292E38",
-                "#2E323C",
-                "#ACA8AE",
-                "#CBC9CF",
-                "#E1DDE4",
-                "#F7F7F8",
-            ])
-            .domain([0, 0.15, 0.25, 0.35, 0.7, 0.8, 0.9, 1]),
-        red: color_ramp(chroma("#F92672")),
-        orange: color_ramp(chroma("#F39C12")),
-        yellow: color_ramp(chroma("#FFE66D")),
-        green: color_ramp(chroma("#96E072")),
-        cyan: color_ramp(chroma("#00E8C6")),
-        blue: color_ramp(chroma("#0CA793")),
-        violet: color_ramp(chroma("#8A3FA6")),
-        magenta: color_ramp(chroma("#C74DED")),
-    },
-    override: { syntax: {} },
-}

styles/src/themes/atelier/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/atelier/atelier-cave-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#19171c",
-        base01: "#26232a",
-        base02: "#585260",
-        base03: "#655f6d",
-        base04: "#7e7887",
-        base05: "#8b8792",
-        base06: "#e2dfe7",
-        base07: "#efecf4",
-        base08: "#be4678",
-        base09: "#aa573c",
-        base0A: "#a06e3b",
-        base0B: "#2a9292",
-        base0C: "#398bc6",
-        base0D: "#576ddb",
-        base0E: "#955ae7",
-        base0F: "#bf40bf",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Cave Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-cave-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#efecf4",
-        base01: "#e2dfe7",
-        base02: "#8b8792",
-        base03: "#7e7887",
-        base04: "#655f6d",
-        base05: "#585260",
-        base06: "#26232a",
-        base07: "#19171c",
-        base08: "#be4678",
-        base09: "#aa573c",
-        base0A: "#a06e3b",
-        base0B: "#2a9292",
-        base0C: "#398bc6",
-        base0D: "#576ddb",
-        base0E: "#955ae7",
-        base0F: "#bf40bf",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Cave Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-dune-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#20201d",
-        base01: "#292824",
-        base02: "#6e6b5e",
-        base03: "#7d7a68",
-        base04: "#999580",
-        base05: "#a6a28c",
-        base06: "#e8e4cf",
-        base07: "#fefbec",
-        base08: "#d73737",
-        base09: "#b65611",
-        base0A: "#ae9513",
-        base0B: "#60ac39",
-        base0C: "#1fad83",
-        base0D: "#6684e1",
-        base0E: "#b854d4",
-        base0F: "#d43552",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Dune Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-dune-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#fefbec",
-        base01: "#e8e4cf",
-        base02: "#a6a28c",
-        base03: "#999580",
-        base04: "#7d7a68",
-        base05: "#6e6b5e",
-        base06: "#292824",
-        base07: "#20201d",
-        base08: "#d73737",
-        base09: "#b65611",
-        base0A: "#ae9513",
-        base0B: "#60ac39",
-        base0C: "#1fad83",
-        base0D: "#6684e1",
-        base0E: "#b854d4",
-        base0F: "#d43552",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Dune Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-estuary-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#22221b",
-        base01: "#302f27",
-        base02: "#5f5e4e",
-        base03: "#6c6b5a",
-        base04: "#878573",
-        base05: "#929181",
-        base06: "#e7e6df",
-        base07: "#f4f3ec",
-        base08: "#ba6236",
-        base09: "#ae7313",
-        base0A: "#a5980d",
-        base0B: "#7d9726",
-        base0C: "#5b9d48",
-        base0D: "#36a166",
-        base0E: "#5f9182",
-        base0F: "#9d6c7c",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Estuary Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-estuary-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f4f3ec",
-        base01: "#e7e6df",
-        base02: "#929181",
-        base03: "#878573",
-        base04: "#6c6b5a",
-        base05: "#5f5e4e",
-        base06: "#302f27",
-        base07: "#22221b",
-        base08: "#ba6236",
-        base09: "#ae7313",
-        base0A: "#a5980d",
-        base0B: "#7d9726",
-        base0C: "#5b9d48",
-        base0D: "#36a166",
-        base0E: "#5f9182",
-        base0F: "#9d6c7c",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Estuary Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-forest-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#1b1918",
-        base01: "#2c2421",
-        base02: "#68615e",
-        base03: "#766e6b",
-        base04: "#9c9491",
-        base05: "#a8a19f",
-        base06: "#e6e2e0",
-        base07: "#f1efee",
-        base08: "#f22c40",
-        base09: "#df5320",
-        base0A: "#c38418",
-        base0B: "#7b9726",
-        base0C: "#3d97b8",
-        base0D: "#407ee7",
-        base0E: "#6666ea",
-        base0F: "#c33ff3",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Forest Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-forest-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f1efee",
-        base01: "#e6e2e0",
-        base02: "#a8a19f",
-        base03: "#9c9491",
-        base04: "#766e6b",
-        base05: "#68615e",
-        base06: "#2c2421",
-        base07: "#1b1918",
-        base08: "#f22c40",
-        base09: "#df5320",
-        base0A: "#c38418",
-        base0B: "#7b9726",
-        base0C: "#3d97b8",
-        base0D: "#407ee7",
-        base0E: "#6666ea",
-        base0F: "#c33ff3",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Forest Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-heath-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#1b181b",
-        base01: "#292329",
-        base02: "#695d69",
-        base03: "#776977",
-        base04: "#9e8f9e",
-        base05: "#ab9bab",
-        base06: "#d8cad8",
-        base07: "#f7f3f7",
-        base08: "#ca402b",
-        base09: "#a65926",
-        base0A: "#bb8a35",
-        base0B: "#918b3b",
-        base0C: "#159393",
-        base0D: "#516aec",
-        base0E: "#7b59c0",
-        base0F: "#cc33cc",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Heath Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-heath-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f7f3f7",
-        base01: "#d8cad8",
-        base02: "#ab9bab",
-        base03: "#9e8f9e",
-        base04: "#776977",
-        base05: "#695d69",
-        base06: "#292329",
-        base07: "#1b181b",
-        base08: "#ca402b",
-        base09: "#a65926",
-        base0A: "#bb8a35",
-        base0B: "#918b3b",
-        base0C: "#159393",
-        base0D: "#516aec",
-        base0E: "#7b59c0",
-        base0F: "#cc33cc",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Heath Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-lakeside-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#161b1d",
-        base01: "#1f292e",
-        base02: "#516d7b",
-        base03: "#5a7b8c",
-        base04: "#7195a8",
-        base05: "#7ea2b4",
-        base06: "#c1e4f6",
-        base07: "#ebf8ff",
-        base08: "#d22d72",
-        base09: "#935c25",
-        base0A: "#8a8a0f",
-        base0B: "#568c3b",
-        base0C: "#2d8f6f",
-        base0D: "#257fad",
-        base0E: "#6b6bb8",
-        base0F: "#b72dd2",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Lakeside Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-lakeside-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#ebf8ff",
-        base01: "#c1e4f6",
-        base02: "#7ea2b4",
-        base03: "#7195a8",
-        base04: "#5a7b8c",
-        base05: "#516d7b",
-        base06: "#1f292e",
-        base07: "#161b1d",
-        base08: "#d22d72",
-        base09: "#935c25",
-        base0A: "#8a8a0f",
-        base0B: "#568c3b",
-        base0C: "#2d8f6f",
-        base0D: "#257fad",
-        base0E: "#6b6bb8",
-        base0F: "#b72dd2",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Lakeside Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-plateau-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#1b1818",
-        base01: "#292424",
-        base02: "#585050",
-        base03: "#655d5d",
-        base04: "#7e7777",
-        base05: "#8a8585",
-        base06: "#e7dfdf",
-        base07: "#f4ecec",
-        base08: "#ca4949",
-        base09: "#b45a3c",
-        base0A: "#a06e3b",
-        base0B: "#4b8b8b",
-        base0C: "#5485b6",
-        base0D: "#7272ca",
-        base0E: "#8464c4",
-        base0F: "#bd5187",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Plateau Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-plateau-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f4ecec",
-        base01: "#e7dfdf",
-        base02: "#8a8585",
-        base03: "#7e7777",
-        base04: "#655d5d",
-        base05: "#585050",
-        base06: "#292424",
-        base07: "#1b1818",
-        base08: "#ca4949",
-        base09: "#b45a3c",
-        base0A: "#a06e3b",
-        base0B: "#4b8b8b",
-        base0C: "#5485b6",
-        base0D: "#7272ca",
-        base0E: "#8464c4",
-        base0F: "#bd5187",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Plateau Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-savanna-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#171c19",
-        base01: "#232a25",
-        base02: "#526057",
-        base03: "#5f6d64",
-        base04: "#78877d",
-        base05: "#87928a",
-        base06: "#dfe7e2",
-        base07: "#ecf4ee",
-        base08: "#b16139",
-        base09: "#9f713c",
-        base0A: "#a07e3b",
-        base0B: "#489963",
-        base0C: "#1c9aa0",
-        base0D: "#478c90",
-        base0E: "#55859b",
-        base0F: "#867469",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Savanna Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-savanna-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#ecf4ee",
-        base01: "#dfe7e2",
-        base02: "#87928a",
-        base03: "#78877d",
-        base04: "#5f6d64",
-        base05: "#526057",
-        base06: "#232a25",
-        base07: "#171c19",
-        base08: "#b16139",
-        base09: "#9f713c",
-        base0A: "#a07e3b",
-        base0B: "#489963",
-        base0C: "#1c9aa0",
-        base0D: "#478c90",
-        base0E: "#55859b",
-        base0F: "#867469",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Savanna Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-seaside-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#131513",
-        base01: "#242924",
-        base02: "#5e6e5e",
-        base03: "#687d68",
-        base04: "#809980",
-        base05: "#8ca68c",
-        base06: "#cfe8cf",
-        base07: "#f4fbf4",
-        base08: "#e6193c",
-        base09: "#87711d",
-        base0A: "#98981b",
-        base0B: "#29a329",
-        base0C: "#1999b3",
-        base0D: "#3d62f5",
-        base0E: "#ad2bee",
-        base0F: "#e619c3",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Seaside Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-seaside-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f4fbf4",
-        base01: "#cfe8cf",
-        base02: "#8ca68c",
-        base03: "#809980",
-        base04: "#687d68",
-        base05: "#5e6e5e",
-        base06: "#242924",
-        base07: "#131513",
-        base08: "#e6193c",
-        base09: "#87711d",
-        base0A: "#98981b",
-        base0B: "#29a329",
-        base0C: "#1999b3",
-        base0D: "#3d62f5",
-        base0E: "#ad2bee",
-        base0F: "#e619c3",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Seaside Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-sulphurpool-dark.ts πŸ”—

@@ -1,61 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#202746",
-        base01: "#293256",
-        base02: "#5e6687",
-        base03: "#6b7394",
-        base04: "#898ea4",
-        base05: "#979db4",
-        base06: "#dfe2f1",
-        base07: "#f5f7ff",
-        base08: "#c94922",
-        base09: "#c76b29",
-        base0A: "#c08b30",
-        base0B: "#ac9739",
-        base0C: "#22a2c9",
-        base0D: "#3d8fd1",
-        base0E: "#6679cc",
-        base0F: "#9c637a",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Sulphurpool Dark`,
-        author: meta.author,
-        appearance: ThemeAppearance.Dark,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale([
-                colors.base00,
-                colors.base01,
-                colors.base02,
-                colors.base03,
-                colors.base04,
-                colors.base05,
-                colors.base06,
-                colors.base07,
-            ]),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/atelier-sulphurpool-light.ts πŸ”—

@@ -1,63 +0,0 @@
-import { chroma, ThemeAppearance, ThemeConfig, color_ramp } from "../../common"
-import { meta, build_syntax, Variant } from "./common"
-
-const variant: Variant = {
-    colors: {
-        base00: "#f5f7ff",
-        base01: "#dfe2f1",
-        base02: "#979db4",
-        base03: "#898ea4",
-        base04: "#6b7394",
-        base05: "#5e6687",
-        base06: "#293256",
-        base07: "#202746",
-        base08: "#c94922",
-        base09: "#c76b29",
-        base0A: "#c08b30",
-        base0B: "#ac9739",
-        base0C: "#22a2c9",
-        base0D: "#3d8fd1",
-        base0E: "#6679cc",
-        base0F: "#9c637a",
-    },
-}
-
-const syntax = build_syntax(variant)
-
-const get_theme = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    return {
-        name: `${meta.name} Sulphurpool Light`,
-        author: meta.author,
-        appearance: ThemeAppearance.Light,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: {
-            neutral: chroma.scale(
-                [
-                    colors.base00,
-                    colors.base01,
-                    colors.base02,
-                    colors.base03,
-                    colors.base04,
-                    colors.base05,
-                    colors.base06,
-                    colors.base07,
-                ].reverse()
-            ),
-            red: color_ramp(chroma(colors.base08)),
-            orange: color_ramp(chroma(colors.base09)),
-            yellow: color_ramp(chroma(colors.base0A)),
-            green: color_ramp(chroma(colors.base0B)),
-            cyan: color_ramp(chroma(colors.base0C)),
-            blue: color_ramp(chroma(colors.base0D)),
-            violet: color_ramp(chroma(colors.base0E)),
-            magenta: color_ramp(chroma(colors.base0F)),
-        },
-        override: { syntax },
-    }
-}
-
-export const theme = get_theme(variant)

styles/src/themes/atelier/common.ts πŸ”—

@@ -1,56 +0,0 @@
-import { ThemeLicenseType, ThemeSyntax, ThemeFamilyMeta } from "../../common"
-
-export interface Variant {
-    colors: {
-        base00: string
-        base01: string
-        base02: string
-        base03: string
-        base04: string
-        base05: string
-        base06: string
-        base07: string
-        base08: string
-        base09: string
-        base0A: string
-        base0B: string
-        base0C: string
-        base0D: string
-        base0E: string
-        base0F: string
-    }
-}
-
-export const meta: ThemeFamilyMeta = {
-    name: "Atelier",
-    author: "Bram de Haan (http://atelierbramdehaan.nl)",
-    license_type: ThemeLicenseType.MIT,
-    license_url:
-        "https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/",
-}
-
-export const build_syntax = (variant: Variant): ThemeSyntax => {
-    const { colors } = variant
-    return {
-        primary: { color: colors.base06 },
-        comment: { color: colors.base03 },
-        "punctuation.delimiter": { color: colors.base05 },
-        "punctuation.bracket": { color: colors.base05 },
-        "punctuation.special": { color: colors.base0F },
-        "string.special.symbol": { color: colors.base0B },
-        operator: { color: colors.base05 },
-        function: { color: colors.base0D },
-        "function.method": { color: colors.base0D },
-        "function.special.definition": { color: colors.base0A },
-        string: { color: colors.base0B },
-        "string.special": { color: colors.base0F },
-        "string.regex": { color: colors.base0C },
-        type: { color: colors.base0A },
-        number: { color: colors.base09 },
-        property: { color: colors.base08 },
-        variable: { color: colors.base06 },
-        "variable.special": { color: colors.base0E },
-        variant: { color: colors.base0A },
-        keyword: { color: colors.base0E },
-    }
-}

styles/src/themes/ayu/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Ike Ku
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/ayu/ayu-dark.ts πŸ”—

@@ -1,16 +0,0 @@
-import { ThemeAppearance, ThemeConfig } from "../../common"
-import { ayu, meta, build_theme } from "./common"
-
-const variant = ayu.dark
-const { ramps, syntax } = build_theme(variant, false)
-
-export const theme: ThemeConfig = {
-    name: `${meta.name} Dark`,
-    author: meta.author,
-    appearance: ThemeAppearance.Dark,
-    license_type: meta.license_type,
-    license_url: meta.license_url,
-    license_file: `${__dirname}/LICENSE`,
-    input_color: ramps,
-    override: { syntax },
-}

styles/src/themes/ayu/ayu-light.ts πŸ”—

@@ -1,16 +0,0 @@
-import { ThemeAppearance, ThemeConfig } from "../../common"
-import { ayu, meta, build_theme } from "./common"
-
-const variant = ayu.light
-const { ramps, syntax } = build_theme(variant, true)
-
-export const theme: ThemeConfig = {
-    name: `${meta.name} Light`,
-    author: meta.author,
-    appearance: ThemeAppearance.Light,
-    license_type: meta.license_type,
-    license_url: meta.license_url,
-    license_file: `${__dirname}/LICENSE`,
-    input_color: ramps,
-    override: { syntax },
-}

styles/src/themes/ayu/ayu-mirage.ts πŸ”—

@@ -1,16 +0,0 @@
-import { ThemeAppearance, ThemeConfig } from "../../common"
-import { ayu, meta, build_theme } from "./common"
-
-const variant = ayu.mirage
-const { ramps, syntax } = build_theme(variant, false)
-
-export const theme: ThemeConfig = {
-    name: `${meta.name} Mirage`,
-    author: meta.author,
-    appearance: ThemeAppearance.Dark,
-    license_type: meta.license_type,
-    license_url: meta.license_url,
-    license_file: `${__dirname}/LICENSE`,
-    input_color: ramps,
-    override: { syntax },
-}

styles/src/themes/ayu/common.ts πŸ”—

@@ -1,85 +0,0 @@
-import { dark, light, mirage } from "ayu"
-import {
-    chroma,
-    color_ramp,
-    ThemeLicenseType,
-    ThemeSyntax,
-    ThemeFamilyMeta,
-} from "../../common"
-
-export const ayu = {
-    dark,
-    light,
-    mirage,
-}
-
-export const build_theme = (t: typeof dark, light: boolean) => {
-    const color = {
-        light_blue: t.syntax.tag.hex(),
-        yellow: t.syntax.func.hex(),
-        blue: t.syntax.entity.hex(),
-        green: t.syntax.string.hex(),
-        teal: t.syntax.regexp.hex(),
-        red: t.syntax.markup.hex(),
-        orange: t.syntax.keyword.hex(),
-        light_yellow: t.syntax.special.hex(),
-        gray: t.syntax.comment.hex(),
-        purple: t.syntax.constant.hex(),
-    }
-
-    const syntax: ThemeSyntax = {
-        constant: { color: t.syntax.constant.hex() },
-        "string.regex": { color: t.syntax.regexp.hex() },
-        string: { color: t.syntax.string.hex() },
-        comment: { color: t.syntax.comment.hex() },
-        keyword: { color: t.syntax.keyword.hex() },
-        operator: { color: t.syntax.operator.hex() },
-        number: { color: t.syntax.constant.hex() },
-        type: { color: color.blue },
-        boolean: { color: color.purple },
-        "punctuation.special": { color: color.purple },
-        "string.special": { color: t.syntax.special.hex() },
-        function: { color: t.syntax.func.hex() },
-    }
-
-    return {
-        ramps: {
-            neutral: chroma.scale([
-                light ? t.editor.fg.hex() : t.editor.bg.hex(),
-                light ? t.editor.bg.hex() : t.editor.fg.hex(),
-            ]),
-            red: color_ramp(chroma(color.red)),
-            orange: color_ramp(chroma(color.orange)),
-            yellow: color_ramp(chroma(color.yellow)),
-            green: color_ramp(chroma(color.green)),
-            cyan: color_ramp(chroma(color.teal)),
-            blue: color_ramp(chroma(color.blue)),
-            violet: color_ramp(chroma(color.purple)),
-            magenta: color_ramp(chroma(color.light_blue)),
-        },
-        syntax,
-    }
-}
-
-export const build_syntax = (t: typeof dark): ThemeSyntax => {
-    return {
-        constant: { color: t.syntax.constant.hex() },
-        "string.regex": { color: t.syntax.regexp.hex() },
-        string: { color: t.syntax.string.hex() },
-        comment: { color: t.syntax.comment.hex() },
-        keyword: { color: t.syntax.keyword.hex() },
-        operator: { color: t.syntax.operator.hex() },
-        number: { color: t.syntax.constant.hex() },
-        type: { color: t.syntax.regexp.hex() },
-        "punctuation.special": { color: t.syntax.special.hex() },
-        "string.special": { color: t.syntax.special.hex() },
-        function: { color: t.syntax.func.hex() },
-    }
-}
-
-export const meta: ThemeFamilyMeta = {
-    name: "Ayu",
-    author: "dempfi",
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/dempfi/ayu",
-}

styles/src/themes/gruvbox/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) <YEAR> <COPYRIGHT HOLDER>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/gruvbox/gruvbox-common.ts πŸ”—

@@ -1,264 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-    ThemeSyntax,
-    ThemeFamilyMeta,
-} from "../../common"
-
-const meta: ThemeFamilyMeta = {
-    name: "Gruvbox",
-    author: "morhetz <morhetz@gmail.com>",
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/morhetz/gruvbox",
-}
-
-const color = {
-    dark0_hard: "#1d2021",
-    dark0: "#282828",
-    dark0_soft: "#32302f",
-    dark1: "#3c3836",
-    dark2: "#504945",
-    dark3: "#665c54",
-    dark4: "#7c6f64",
-    dark4_256: "#7c6f64",
-
-    gray_245: "#928374",
-    gray_244: "#928374",
-
-    light0_hard: "#f9f5d7",
-    light0: "#fbf1c7",
-    light0_soft: "#f2e5bc",
-    light1: "#ebdbb2",
-    light2: "#d5c4a1",
-    light3: "#bdae93",
-    light4: "#a89984",
-    light4_256: "#a89984",
-
-    bright_red: "#fb4934",
-    bright_green: "#b8bb26",
-    bright_yellow: "#fabd2f",
-    bright_blue: "#83a598",
-    bright_purple: "#d3869b",
-    bright_aqua: "#8ec07c",
-    bright_orange: "#fe8019",
-
-    neutral_red: "#cc241d",
-    neutral_green: "#98971a",
-    neutral_yellow: "#d79921",
-    neutral_blue: "#458588",
-    neutral_purple: "#b16286",
-    neutral_aqua: "#689d6a",
-    neutral_orange: "#d65d0e",
-
-    faded_red: "#9d0006",
-    faded_green: "#79740e",
-    faded_yellow: "#b57614",
-    faded_blue: "#076678",
-    faded_purple: "#8f3f71",
-    faded_aqua: "#427b58",
-    faded_orange: "#af3a03",
-}
-
-interface ThemeColors {
-    red: string
-    green: string
-    yellow: string
-    blue: string
-    purple: string
-    aqua: string
-    orange: string
-    gray: string
-}
-
-const dark_neutrals = [
-    color.dark1,
-    color.dark2,
-    color.dark3,
-    color.dark4,
-    color.light4,
-    color.light3,
-    color.light2,
-    color.light1,
-    color.light0,
-]
-
-const dark: ThemeColors = {
-    red: color.bright_red,
-    green: color.bright_green,
-    yellow: color.bright_yellow,
-    blue: color.bright_blue,
-    purple: color.bright_purple,
-    aqua: color.bright_aqua,
-    orange: color.bright_orange,
-    gray: color.light4,
-}
-
-const light_neutrals = [
-    color.light1,
-    color.light2,
-    color.light3,
-    color.light4,
-    color.dark4,
-    color.dark3,
-    color.dark2,
-    color.dark1,
-    color.dark0,
-]
-
-const light: ThemeColors = {
-    red: color.faded_red,
-    green: color.faded_green,
-    yellow: color.faded_yellow,
-    blue: color.faded_blue,
-    purple: color.faded_purple,
-    aqua: color.faded_aqua,
-    orange: color.faded_orange,
-    gray: color.dark4,
-}
-
-interface Variant {
-    name: string
-    appearance: "light" | "dark"
-    colors: ThemeColors
-}
-
-const variant: Variant[] = [
-    {
-        name: "Dark Hard",
-        appearance: "dark",
-        colors: dark,
-    },
-    {
-        name: "Dark",
-        appearance: "dark",
-        colors: dark,
-    },
-    {
-        name: "Dark Soft",
-        appearance: "dark",
-        colors: dark,
-    },
-    {
-        name: "Light Hard",
-        appearance: "light",
-        colors: light,
-    },
-    {
-        name: "Light",
-        appearance: "light",
-
-        colors: light,
-    },
-    {
-        name: "Light Soft",
-        appearance: "light",
-        colors: light,
-    },
-]
-
-const dark_hard_neutral = [color.dark0_hard, ...dark_neutrals]
-const dark_neutral = [color.dark0, ...dark_neutrals]
-const dark_soft_neutral = [color.dark0_soft, ...dark_neutrals]
-
-const light_hard_neutral = [color.light0_hard, ...light_neutrals]
-const light_neutral = [color.light0, ...light_neutrals]
-const light_soft_neutral = [color.light0_soft, ...light_neutrals]
-
-const build_variant = (variant: Variant): ThemeConfig => {
-    const { colors } = variant
-
-    const name = `Gruvbox ${variant.name}`
-
-    const is_light = variant.appearance === "light"
-
-    let neutral: string[] = []
-
-    switch (variant.name) {
-        case "Dark Hard":
-            neutral = dark_hard_neutral
-            break
-
-        case "Dark":
-            neutral = dark_neutral
-            break
-
-        case "Dark Soft":
-            neutral = dark_soft_neutral
-            break
-
-        case "Light Hard":
-            neutral = light_hard_neutral
-            break
-
-        case "Light":
-            neutral = light_neutral
-            break
-
-        case "Light Soft":
-            neutral = light_soft_neutral
-            break
-    }
-
-    const ramps = {
-        neutral: chroma.scale(is_light ? neutral.reverse() : neutral),
-        red: color_ramp(chroma(variant.colors.red)),
-        orange: color_ramp(chroma(variant.colors.orange)),
-        yellow: color_ramp(chroma(variant.colors.yellow)),
-        green: color_ramp(chroma(variant.colors.green)),
-        cyan: color_ramp(chroma(variant.colors.aqua)),
-        blue: color_ramp(chroma(variant.colors.blue)),
-        violet: color_ramp(chroma(variant.colors.purple)),
-        magenta: color_ramp(chroma(variant.colors.gray)),
-    }
-
-    const syntax: ThemeSyntax = {
-        primary: { color: neutral[is_light ? 0 : 8] },
-        "text.literal": { color: colors.blue },
-        comment: { color: colors.gray },
-        punctuation: { color: neutral[is_light ? 1 : 7] },
-        "punctuation.bracket": { color: neutral[is_light ? 3 : 5] },
-        "punctuation.list_marker": { color: neutral[is_light ? 0 : 8] },
-        operator: { color: colors.aqua },
-        boolean: { color: colors.purple },
-        number: { color: colors.purple },
-        string: { color: colors.green },
-        "string.special": { color: colors.purple },
-        "string.special.symbol": { color: colors.aqua },
-        "string.regex": { color: colors.orange },
-        type: { color: colors.yellow },
-        enum: { color: colors.orange },
-        tag: { color: colors.aqua },
-        constant: { color: colors.yellow },
-        keyword: { color: colors.red },
-        function: { color: colors.green },
-        "function.builtin": { color: colors.red },
-        variable: { color: colors.blue },
-        property: { color: neutral[is_light ? 0 : 8] },
-        embedded: { color: colors.aqua },
-        link_text: { color: colors.aqua },
-        link_uri: { color: colors.purple },
-        title: { color: colors.green },
-    }
-
-    return {
-        name,
-        author: meta.author,
-        appearance: variant.appearance as ThemeAppearance,
-        license_type: meta.license_type,
-        license_url: meta.license_url,
-        license_file: `${__dirname}/LICENSE`,
-        input_color: ramps,
-        override: { syntax },
-    }
-}
-
-// Variants
-export const dark_hard = build_variant(variant[0])
-export const dark_default = build_variant(variant[1])
-export const dark_soft = build_variant(variant[2])
-export const light_hard = build_variant(variant[3])
-export const light_default = build_variant(variant[4])
-export const light_soft = build_variant(variant[5])

styles/src/themes/index.ts πŸ”—

@@ -1,82 +0,0 @@
-import { ThemeConfig } from "../theme"
-import { dark_default as gruvbox_dark } from "./gruvbox/gruvbox-dark"
-import { dark_hard as gruvbox_dark_hard } from "./gruvbox/gruvbox-dark-hard"
-import { dark_soft as gruvbox_dark_soft } from "./gruvbox/gruvbox-dark-soft"
-import { light_default as gruvbox_light } from "./gruvbox/gruvbox-light"
-import { light_hard as gruvbox_light_hard } from "./gruvbox/gruvbox-light-hard"
-import { light_soft as gruvbox_light_soft } from "./gruvbox/gruvbox-light-soft"
-import { dark as solarized_dark } from "./solarized/solarized"
-import { light as solarized_light } from "./solarized/solarized"
-import { dark as andromeda_dark } from "./andromeda/andromeda"
-import { theme as one_dark } from "./one/one-dark"
-import { theme as one_light } from "./one/one-light"
-import { theme as ayu_light } from "./ayu/ayu-light"
-import { theme as ayu_dark } from "./ayu/ayu-dark"
-import { theme as ayu_mirage } from "./ayu/ayu-mirage"
-import { theme as rose_pine } from "./rose-pine/rose-pine"
-import { theme as rose_pine_dawn } from "./rose-pine/rose-pine-dawn"
-import { theme as rose_pine_moon } from "./rose-pine/rose-pine-moon"
-import { theme as sandcastle } from "./sandcastle/sandcastle"
-import { theme as summercamp } from "./summercamp/summercamp"
-import { theme as atelier_cave_dark } from "./atelier/atelier-cave-dark"
-import { theme as atelier_cave_light } from "./atelier/atelier-cave-light"
-import { theme as atelier_dune_dark } from "./atelier/atelier-dune-dark"
-import { theme as atelier_dune_light } from "./atelier/atelier-dune-light"
-import { theme as atelier_estuary_dark } from "./atelier/atelier-estuary-dark"
-import { theme as atelier_estuary_light } from "./atelier/atelier-estuary-light"
-import { theme as atelier_forest_dark } from "./atelier/atelier-forest-dark"
-import { theme as atelier_forest_light } from "./atelier/atelier-forest-light"
-import { theme as atelier_heath_dark } from "./atelier/atelier-heath-dark"
-import { theme as atelier_heath_light } from "./atelier/atelier-heath-light"
-import { theme as atelier_lakeside_dark } from "./atelier/atelier-lakeside-dark"
-import { theme as atelier_lakeside_light } from "./atelier/atelier-lakeside-light"
-import { theme as atelier_plateau_dark } from "./atelier/atelier-plateau-dark"
-import { theme as atelier_plateau_light } from "./atelier/atelier-plateau-light"
-import { theme as atelier_savanna_dark } from "./atelier/atelier-savanna-dark"
-import { theme as atelier_savanna_light } from "./atelier/atelier-savanna-light"
-import { theme as atelier_seaside_dark } from "./atelier/atelier-seaside-dark"
-import { theme as atelier_seaside_light } from "./atelier/atelier-seaside-light"
-import { theme as atelier_sulphurpool_dark } from "./atelier/atelier-sulphurpool-dark"
-import { theme as atelier_sulphurpool_light } from "./atelier/atelier-sulphurpool-light"
-
-export const themes: ThemeConfig[] = [
-    one_dark,
-    one_light,
-    ayu_light,
-    ayu_dark,
-    ayu_mirage,
-    gruvbox_dark,
-    gruvbox_dark_hard,
-    gruvbox_dark_soft,
-    gruvbox_light,
-    gruvbox_light_hard,
-    gruvbox_light_soft,
-    rose_pine,
-    rose_pine_dawn,
-    rose_pine_moon,
-    sandcastle,
-    solarized_dark,
-    solarized_light,
-    andromeda_dark,
-    summercamp,
-    atelier_cave_dark,
-    atelier_cave_light,
-    atelier_dune_dark,
-    atelier_dune_light,
-    atelier_estuary_dark,
-    atelier_estuary_light,
-    atelier_forest_dark,
-    atelier_forest_light,
-    atelier_heath_dark,
-    atelier_heath_light,
-    atelier_lakeside_dark,
-    atelier_lakeside_light,
-    atelier_plateau_dark,
-    atelier_plateau_light,
-    atelier_savanna_dark,
-    atelier_savanna_light,
-    atelier_seaside_dark,
-    atelier_seaside_light,
-    atelier_sulphurpool_dark,
-    atelier_sulphurpool_light,
-]

styles/src/themes/one/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 GitHub Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/one/one-dark.ts πŸ”—

@@ -1,80 +0,0 @@
-import {
-    chroma,
-    font_weights,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-const color = {
-    white: "#ACB2BE",
-    grey: "#5D636F",
-    red: "#D07277",
-    dark_red: "#B1574B",
-    orange: "#C0966B",
-    yellow: "#DFC184",
-    green: "#A1C181",
-    teal: "#6FB4C0",
-    blue: "#74ADE9",
-    purple: "#B478CF",
-}
-
-export const theme: ThemeConfig = {
-    name: "One Dark",
-    author: "simurai",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url:
-        "https://github.com/atom/atom/tree/master/packages/one-dark-ui",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale([
-                "#282c34",
-                "#353b45",
-                "#3e4451",
-                "#545862",
-                "#565c64",
-                "#abb2bf",
-                "#b6bdca",
-                "#c8ccd4",
-            ])
-            .domain([0.05, 0.22, 0.25, 0.45, 0.62, 0.8, 0.9, 1]),
-        red: color_ramp(chroma(color.red)),
-        orange: color_ramp(chroma(color.orange)),
-        yellow: color_ramp(chroma(color.yellow)),
-        green: color_ramp(chroma(color.green)),
-        cyan: color_ramp(chroma(color.teal)),
-        blue: color_ramp(chroma(color.blue)),
-        violet: color_ramp(chroma(color.purple)),
-        magenta: color_ramp(chroma("#be5046")),
-    },
-    override: {
-        syntax: {
-            boolean: { color: color.orange },
-            comment: { color: color.grey },
-            enum: { color: color.red },
-            "emphasis.strong": { color: color.orange },
-            function: { color: color.blue },
-            keyword: { color: color.purple },
-            link_text: { color: color.blue, italic: false },
-            link_uri: { color: color.teal },
-            number: { color: color.orange },
-            constant: { color: color.yellow },
-            operator: { color: color.teal },
-            primary: { color: color.white },
-            property: { color: color.red },
-            punctuation: { color: color.white },
-            "punctuation.list_marker": { color: color.red },
-            "punctuation.special": { color: color.dark_red },
-            string: { color: color.green },
-            title: { color: color.red, weight: font_weights.normal },
-            "text.literal": { color: color.green },
-            type: { color: color.teal },
-            "variable.special": { color: color.orange },
-            variant: { color: color.blue },
-            constructor: { color: color.blue },
-        },
-    },
-}

styles/src/themes/one/one-light.ts πŸ”—

@@ -1,79 +0,0 @@
-import {
-    chroma,
-    font_weights,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-const color = {
-    black: "#383A41",
-    grey: "#A2A3A7",
-    red: "#D36050",
-    dark_red: "#B92C46",
-    orange: "#AD6F26",
-    yellow: "#DFC184",
-    green: "#659F58",
-    teal: "#3982B7",
-    blue: "#5B79E3",
-    purple: "#A449AB",
-    magenta: "#994EA6",
-}
-
-export const theme: ThemeConfig = {
-    name: "One Light",
-    author: "simurai",
-    appearance: ThemeAppearance.Light,
-    license_type: ThemeLicenseType.MIT,
-    license_url:
-        "https://github.com/atom/atom/tree/master/packages/one-light-ui",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale([
-                "#383A41",
-                "#535456",
-                "#696c77",
-                "#9D9D9F",
-                "#A9A9A9",
-                "#DBDBDC",
-                "#EAEAEB",
-                "#FAFAFA",
-            ])
-            .domain([0.05, 0.22, 0.25, 0.45, 0.62, 0.8, 0.9, 1]),
-        red: color_ramp(chroma(color.red)),
-        orange: color_ramp(chroma(color.orange)),
-        yellow: color_ramp(chroma(color.yellow)),
-        green: color_ramp(chroma(color.green)),
-        cyan: color_ramp(chroma(color.teal)),
-        blue: color_ramp(chroma(color.blue)),
-        violet: color_ramp(chroma(color.purple)),
-        magenta: color_ramp(chroma(color.magenta)),
-    },
-    override: {
-        syntax: {
-            boolean: { color: color.orange },
-            comment: { color: color.grey },
-            enum: { color: color.red },
-            "emphasis.strong": { color: color.orange },
-            function: { color: color.blue },
-            keyword: { color: color.purple },
-            link_text: { color: color.blue },
-            link_uri: { color: color.teal },
-            number: { color: color.orange },
-            operator: { color: color.teal },
-            primary: { color: color.black },
-            property: { color: color.red },
-            punctuation: { color: color.black },
-            "punctuation.list_marker": { color: color.red },
-            "punctuation.special": { color: color.dark_red },
-            string: { color: color.green },
-            title: { color: color.red, weight: font_weights.normal },
-            "text.literal": { color: color.green },
-            type: { color: color.teal },
-            "variable.special": { color: color.orange },
-            variant: { color: color.blue },
-        },
-    },
-}

styles/src/themes/rose-pine/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2021 Emilia Dunfelt
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/rose-pine/common.ts πŸ”—

@@ -1,75 +0,0 @@
-import { ThemeSyntax } from "../../common"
-
-export const color = {
-    default: {
-        base: "#191724",
-        surface: "#1f1d2e",
-        overlay: "#26233a",
-        muted: "#6e6a86",
-        subtle: "#908caa",
-        text: "#e0def4",
-        love: "#eb6f92",
-        gold: "#f6c177",
-        rose: "#ebbcba",
-        pine: "#31748f",
-        foam: "#9ccfd8",
-        iris: "#c4a7e7",
-        highlight_low: "#21202e",
-        highlight_med: "#403d52",
-        highlight_high: "#524f67",
-    },
-    moon: {
-        base: "#232136",
-        surface: "#2a273f",
-        overlay: "#393552",
-        muted: "#6e6a86",
-        subtle: "#908caa",
-        text: "#e0def4",
-        love: "#eb6f92",
-        gold: "#f6c177",
-        rose: "#ea9a97",
-        pine: "#3e8fb0",
-        foam: "#9ccfd8",
-        iris: "#c4a7e7",
-        highlight_low: "#2a283e",
-        highlight_med: "#44415a",
-        highlight_high: "#56526e",
-    },
-    dawn: {
-        base: "#faf4ed",
-        surface: "#fffaf3",
-        overlay: "#f2e9e1",
-        muted: "#9893a5",
-        subtle: "#797593",
-        text: "#575279",
-        love: "#b4637a",
-        gold: "#ea9d34",
-        rose: "#d7827e",
-        pine: "#286983",
-        foam: "#56949f",
-        iris: "#907aa9",
-        highlight_low: "#f4ede8",
-        highlight_med: "#dfdad9",
-        highlight_high: "#cecacd",
-    },
-}
-
-export const syntax = (c: typeof color.default): Partial<ThemeSyntax> => {
-    return {
-        comment: { color: c.muted },
-        operator: { color: c.pine },
-        punctuation: { color: c.subtle },
-        variable: { color: c.text },
-        string: { color: c.gold },
-        type: { color: c.foam },
-        "type.builtin": { color: c.foam },
-        boolean: { color: c.rose },
-        function: { color: c.rose },
-        keyword: { color: c.pine },
-        tag: { color: c.foam },
-        "function.method": { color: c.rose },
-        title: { color: c.gold },
-        link_text: { color: c.foam, italic: false },
-        link_uri: { color: c.rose },
-    }
-}

styles/src/themes/rose-pine/rose-pine-dawn.ts πŸ”—

@@ -1,49 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-import { color as c, syntax } from "./common"
-
-const color = c.dawn
-
-const green = chroma.mix(color.foam, "#10b981", 0.6, "lab")
-const magenta = chroma.mix(color.love, color.pine, 0.5, "lab")
-
-export const theme: ThemeConfig = {
-    name: "RosΓ© Pine Dawn",
-    author: "edunfelt",
-    appearance: ThemeAppearance.Light,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/edunfelt/base16-rose-pine-scheme",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale(
-                [
-                    color.base,
-                    color.surface,
-                    color.highlight_high,
-                    color.overlay,
-                    color.muted,
-                    color.subtle,
-                    color.text,
-                ].reverse(),
-            )
-            .domain([0, 0.35, 0.45, 0.65, 0.7, 0.8, 0.9, 1]),
-        red: color_ramp(chroma(color.love)),
-        orange: color_ramp(chroma(color.iris)),
-        yellow: color_ramp(chroma(color.gold)),
-        green: color_ramp(chroma(green)),
-        cyan: color_ramp(chroma(color.pine)),
-        blue: color_ramp(chroma(color.foam)),
-        violet: color_ramp(chroma(color.iris)),
-        magenta: color_ramp(chroma(magenta)),
-    },
-    override: {
-        syntax: syntax(color),
-    },
-}

styles/src/themes/rose-pine/rose-pine-moon.ts πŸ”—

@@ -1,47 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-import { color as c, syntax } from "./common"
-
-const color = c.moon
-
-const green = chroma.mix(color.foam, "#10b981", 0.6, "lab")
-const magenta = chroma.mix(color.love, color.pine, 0.5, "lab")
-
-export const theme: ThemeConfig = {
-    name: "RosΓ© Pine Moon",
-    author: "edunfelt",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/edunfelt/base16-rose-pine-scheme",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale([
-                color.base,
-                color.surface,
-                color.highlight_high,
-                color.overlay,
-                color.muted,
-                color.subtle,
-                color.text,
-            ])
-            .domain([0, 0.3, 0.55, 1]),
-        red: color_ramp(chroma(color.love)),
-        orange: color_ramp(chroma(color.iris)),
-        yellow: color_ramp(chroma(color.gold)),
-        green: color_ramp(chroma(green)),
-        cyan: color_ramp(chroma(color.pine)),
-        blue: color_ramp(chroma(color.foam)),
-        violet: color_ramp(chroma(color.iris)),
-        magenta: color_ramp(chroma(magenta)),
-    },
-    override: {
-        syntax: syntax(color),
-    },
-}

styles/src/themes/rose-pine/rose-pine.ts πŸ”—

@@ -1,44 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-import { color as c, syntax } from "./common"
-
-const color = c.default
-
-const green = chroma.mix(color.foam, "#10b981", 0.6, "lab")
-const magenta = chroma.mix(color.love, color.pine, 0.5, "lab")
-
-export const theme: ThemeConfig = {
-    name: "RosΓ© Pine",
-    author: "edunfelt",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/edunfelt/base16-rose-pine-scheme",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma.scale([
-            color.base,
-            color.surface,
-            color.highlight_high,
-            color.overlay,
-            color.muted,
-            color.subtle,
-            color.text,
-        ]),
-        red: color_ramp(chroma(color.love)),
-        orange: color_ramp(chroma(color.iris)),
-        yellow: color_ramp(chroma(color.gold)),
-        green: color_ramp(chroma(green)),
-        cyan: color_ramp(chroma(color.pine)),
-        blue: color_ramp(chroma(color.foam)),
-        violet: color_ramp(chroma(color.iris)),
-        magenta: color_ramp(chroma(magenta)),
-    },
-    override: {
-        syntax: syntax(color),
-    },
-}

styles/src/themes/sandcastle/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2019 George Essig
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/sandcastle/sandcastle.ts πŸ”—

@@ -1,37 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-export const theme: ThemeConfig = {
-    name: "Sandcastle",
-    author: "gessig",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/gessig/base16-sandcastle-scheme",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma.scale([
-            "#282c34",
-            "#2c323b",
-            "#3e4451",
-            "#665c54",
-            "#928374",
-            "#a89984",
-            "#d5c4a1",
-            "#fdf4c1",
-        ]),
-        red: color_ramp(chroma("#B4637A")),
-        orange: color_ramp(chroma("#a07e3b")),
-        yellow: color_ramp(chroma("#a07e3b")),
-        green: color_ramp(chroma("#83a598")),
-        cyan: color_ramp(chroma("#83a598")),
-        blue: color_ramp(chroma("#528b8b")),
-        violet: color_ramp(chroma("#d75f5f")),
-        magenta: color_ramp(chroma("#a87322")),
-    },
-    override: { syntax: {} },
-}

styles/src/themes/solarized/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2011 Ethan Schoonover
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/solarized/solarized.ts πŸ”—

@@ -1,52 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-const ramps = {
-    neutral: chroma
-        .scale([
-            "#002b36",
-            "#073642",
-            "#586e75",
-            "#657b83",
-            "#839496",
-            "#93a1a1",
-            "#eee8d5",
-            "#fdf6e3",
-        ])
-        .domain([0, 0.2, 0.38, 0.45, 0.65, 0.7, 0.85, 1]),
-    red: color_ramp(chroma("#dc322f")),
-    orange: color_ramp(chroma("#cb4b16")),
-    yellow: color_ramp(chroma("#b58900")),
-    green: color_ramp(chroma("#859900")),
-    cyan: color_ramp(chroma("#2aa198")),
-    blue: color_ramp(chroma("#268bd2")),
-    violet: color_ramp(chroma("#6c71c4")),
-    magenta: color_ramp(chroma("#d33682")),
-}
-
-export const dark: ThemeConfig = {
-    name: "Solarized Dark",
-    author: "Ethan Schoonover",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/altercation/solarized",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: ramps,
-    override: { syntax: {} },
-}
-
-export const light: ThemeConfig = {
-    name: "Solarized Light",
-    author: "Ethan Schoonover",
-    appearance: ThemeAppearance.Light,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/altercation/solarized",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: ramps,
-    override: { syntax: {} },
-}

styles/src/themes/summercamp/LICENSE πŸ”—

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2019 Zoe FiriH
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

styles/src/themes/summercamp/summercamp.ts πŸ”—

@@ -1,39 +0,0 @@
-import {
-    chroma,
-    color_ramp,
-    ThemeAppearance,
-    ThemeLicenseType,
-    ThemeConfig,
-} from "../../common"
-
-export const theme: ThemeConfig = {
-    name: "Summercamp",
-    author: "zoefiri",
-    appearance: ThemeAppearance.Dark,
-    license_type: ThemeLicenseType.MIT,
-    license_url: "https://github.com/zoefiri/base16-sc",
-    license_file: `${__dirname}/LICENSE`,
-    input_color: {
-        neutral: chroma
-            .scale([
-                "#1c1810",
-                "#2a261c",
-                "#3a3527",
-                "#3a3527",
-                "#5f5b45",
-                "#736e55",
-                "#bab696",
-                "#f8f5de",
-            ])
-            .domain([0, 0.2, 0.38, 0.4, 0.65, 0.7, 0.85, 1]),
-        red: color_ramp(chroma("#e35142")),
-        orange: color_ramp(chroma("#fba11b")),
-        yellow: color_ramp(chroma("#f2ff27")),
-        green: color_ramp(chroma("#5ceb5a")),
-        cyan: color_ramp(chroma("#5aebbc")),
-        blue: color_ramp(chroma("#489bf0")),
-        violet: color_ramp(chroma("#FF8080")),
-        magenta: color_ramp(chroma("#F69BE7")),
-    },
-    override: { syntax: {} },
-}

styles/src/utils/slugify.ts πŸ”—

@@ -1,10 +0,0 @@
-export function slugify(t: string): string {
-    return t
-        .toString()
-        .toLowerCase()
-        .replace(/\s+/g, "-")
-        .replace(/[^\w-]+/g, "")
-        .replace(/--+/g, "-")
-        .replace(/^-+/, "")
-        .replace(/-+$/, "")
-}

styles/tsconfig.json πŸ”—

@@ -1,27 +0,0 @@
-{
-    "compilerOptions": {
-        "target": "es2015",
-        "module": "commonjs",
-        "esModuleInterop": true,
-        "noImplicitAny": true,
-        "removeComments": true,
-        "preserveConstEnums": true,
-        "sourceMap": true,
-        "noEmit": true,
-        "forceConsistentCasingInFileNames": true,
-        "declaration": true,
-        "strict": true,
-        "strictNullChecks": true,
-        "noImplicitThis": true,
-        "alwaysStrict": true,
-        "noUnusedLocals": false,
-        "noUnusedParameters": false,
-        "noImplicitReturns": true,
-        "noFallthroughCasesInSwitch": false,
-        "experimentalDecorators": true,
-        "strictPropertyInitialization": false,
-        "skipLibCheck": true,
-        "useUnknownInCatchVariables": false
-    },
-    "exclude": ["node_modules"]
-}

styles/vitest.config.ts πŸ”—

@@ -1,8 +0,0 @@
-import { configDefaults, defineConfig } from "vitest/config"
-
-export default defineConfig({
-    test: {
-        exclude: [...configDefaults.exclude, "target/*"],
-        include: ["src/**/*.{spec,test}.ts"],
-    },
-})