Merge remote-tracking branch 'origin/main' into save-conversations
This commit is contained in:
commit
6f0efec146
112 changed files with 4161 additions and 1653 deletions
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[alias]
|
||||||
|
xtask = "run --package xtask --"
|
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -51,6 +51,7 @@ jobs:
|
||||||
rustup set profile minimal
|
rustup set profile minimal
|
||||||
rustup update stable
|
rustup update stable
|
||||||
rustup target add wasm32-wasi
|
rustup target add wasm32-wasi
|
||||||
|
cargo install cargo-nextest
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
|
@ -70,7 +71,7 @@ jobs:
|
||||||
run: cargo check --workspace
|
run: cargo check --workspace
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --workspace --no-fail-fast
|
run: cargo nextest run --workspace --no-fail-fast
|
||||||
|
|
||||||
- name: Build collab
|
- name: Build collab
|
||||||
run: cargo build -p collab
|
run: cargo build -p collab
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,6 +4,8 @@
|
||||||
/plugins/bin
|
/plugins/bin
|
||||||
/script/node_modules
|
/script/node_modules
|
||||||
/styles/node_modules
|
/styles/node_modules
|
||||||
|
/styles/src/types/zed.ts
|
||||||
|
/crates/theme/schemas/theme.json
|
||||||
/crates/collab/static/styles.css
|
/crates/collab/static/styles.css
|
||||||
/vendor/bin
|
/vendor/bin
|
||||||
/assets/themes/*.json
|
/assets/themes/*.json
|
||||||
|
|
131
Cargo.lock
generated
131
Cargo.lock
generated
|
@ -192,6 +192,55 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is-terminal 0.4.7",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.71"
|
version = "1.0.71"
|
||||||
|
@ -1104,8 +1153,8 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_derive",
|
"clap_derive 3.2.25",
|
||||||
"clap_lex",
|
"clap_lex 0.2.4",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"strsim",
|
"strsim",
|
||||||
|
@ -1113,6 +1162,30 @@ dependencies = [
|
||||||
"textwrap",
|
"textwrap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2686c4115cb0810d9a984776e197823d08ec94f176549a89a9efded477c456dc"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive 4.3.2",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e53afce1efce6ed1f633cf0e57612fe51db54a1ee4fd8f8503d078fe02d69ae"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"bitflags",
|
||||||
|
"clap_lex 0.5.0",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "3.2.25"
|
version = "3.2.25"
|
||||||
|
@ -1126,6 +1199,18 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.4.1",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.18",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
@ -1135,12 +1220,18 @@ dependencies = [
|
||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cli"
|
name = "cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap 3.2.25",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-services",
|
"core-services",
|
||||||
"dirs 3.0.2",
|
"dirs 3.0.2",
|
||||||
|
@ -1250,7 +1341,7 @@ dependencies = [
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"call",
|
"call",
|
||||||
"clap",
|
"clap 3.2.25",
|
||||||
"client",
|
"client",
|
||||||
"collections",
|
"collections",
|
||||||
"ctor",
|
"ctor",
|
||||||
|
@ -1345,6 +1436,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "command_palette"
|
name = "command_palette"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -6918,18 +7015,6 @@ dependencies = [
|
||||||
"workspace",
|
"workspace",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "theme_testbench"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"gpui",
|
|
||||||
"project",
|
|
||||||
"settings",
|
|
||||||
"smallvec",
|
|
||||||
"theme",
|
|
||||||
"workspace",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
|
@ -8782,6 +8867,17 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xtask"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap 4.3.5",
|
||||||
|
"schemars",
|
||||||
|
"serde_json",
|
||||||
|
"theme",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yaml-rust"
|
name = "yaml-rust"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -8811,7 +8907,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zed"
|
name = "zed"
|
||||||
version = "0.92.0"
|
version = "0.93.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activity_indicator",
|
"activity_indicator",
|
||||||
"ai",
|
"ai",
|
||||||
|
@ -8890,7 +8986,6 @@ dependencies = [
|
||||||
"text",
|
"text",
|
||||||
"theme",
|
"theme",
|
||||||
"theme_selector",
|
"theme_selector",
|
||||||
"theme_testbench",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tiny_http",
|
"tiny_http",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
|
@ -61,11 +61,11 @@ members = [
|
||||||
"crates/text",
|
"crates/text",
|
||||||
"crates/theme",
|
"crates/theme",
|
||||||
"crates/theme_selector",
|
"crates/theme_selector",
|
||||||
"crates/theme_testbench",
|
|
||||||
"crates/util",
|
"crates/util",
|
||||||
"crates/vim",
|
"crates/vim",
|
||||||
"crates/workspace",
|
"crates/workspace",
|
||||||
"crates/welcome",
|
"crates/welcome",
|
||||||
|
"crates/xtask",
|
||||||
"crates/zed",
|
"crates/zed",
|
||||||
]
|
]
|
||||||
default-members = ["crates/zed"]
|
default-members = ["crates/zed"]
|
||||||
|
@ -118,3 +118,4 @@ split-debuginfo = "unpacked"
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
lto = "thin"
|
lto = "thin"
|
||||||
|
codegen-units = 1
|
||||||
|
|
|
@ -412,6 +412,7 @@
|
||||||
"ctrl-shift-k": "editor::DeleteLine",
|
"ctrl-shift-k": "editor::DeleteLine",
|
||||||
"cmd-shift-d": "editor::DuplicateLine",
|
"cmd-shift-d": "editor::DuplicateLine",
|
||||||
"cmd-shift-l": "editor::SplitSelectionIntoLines",
|
"cmd-shift-l": "editor::SplitSelectionIntoLines",
|
||||||
|
"ctrl-j": "editor::JoinLines",
|
||||||
"ctrl-cmd-up": "editor::MoveLineUp",
|
"ctrl-cmd-up": "editor::MoveLineUp",
|
||||||
"ctrl-cmd-down": "editor::MoveLineDown",
|
"ctrl-cmd-down": "editor::MoveLineDown",
|
||||||
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
|
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
|
||||||
|
|
|
@ -25,11 +25,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"h": "vim::Left",
|
"h": "vim::Left",
|
||||||
|
"left": "vim::Left",
|
||||||
"backspace": "vim::Backspace",
|
"backspace": "vim::Backspace",
|
||||||
"j": "vim::Down",
|
"j": "vim::Down",
|
||||||
|
"down": "vim::Down",
|
||||||
"enter": "vim::NextLineStart",
|
"enter": "vim::NextLineStart",
|
||||||
"k": "vim::Up",
|
"k": "vim::Up",
|
||||||
|
"up": "vim::Up",
|
||||||
"l": "vim::Right",
|
"l": "vim::Right",
|
||||||
|
"right": "vim::Right",
|
||||||
"$": "vim::EndOfLine",
|
"$": "vim::EndOfLine",
|
||||||
"shift-g": "vim::EndOfDocument",
|
"shift-g": "vim::EndOfDocument",
|
||||||
"w": "vim::NextWordStart",
|
"w": "vim::NextWordStart",
|
||||||
|
@ -90,6 +94,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"ctrl-o": "pane::GoBack",
|
||||||
|
"ctrl-]": "editor::GoToDefinition",
|
||||||
"escape": "editor::Cancel",
|
"escape": "editor::Cancel",
|
||||||
"0": "vim::StartOfLine", // When no number operator present, use start of line motion
|
"0": "vim::StartOfLine", // When no number operator present, use start of line motion
|
||||||
"1": [
|
"1": [
|
||||||
|
@ -143,6 +149,7 @@
|
||||||
"Delete"
|
"Delete"
|
||||||
],
|
],
|
||||||
"shift-d": "vim::DeleteToEndOfLine",
|
"shift-d": "vim::DeleteToEndOfLine",
|
||||||
|
"shift-j": "editor::JoinLines",
|
||||||
"y": [
|
"y": [
|
||||||
"vim::PushOperator",
|
"vim::PushOperator",
|
||||||
"Yank"
|
"Yank"
|
||||||
|
@ -184,7 +191,6 @@
|
||||||
"p": "vim::Paste",
|
"p": "vim::Paste",
|
||||||
"u": "editor::Undo",
|
"u": "editor::Undo",
|
||||||
"ctrl-r": "editor::Redo",
|
"ctrl-r": "editor::Redo",
|
||||||
"ctrl-o": "pane::GoBack",
|
|
||||||
"/": [
|
"/": [
|
||||||
"buffer_search::Deploy",
|
"buffer_search::Deploy",
|
||||||
{
|
{
|
||||||
|
|
|
@ -326,7 +326,7 @@ impl View for ActivityIndicator {
|
||||||
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
|
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
|
||||||
let theme = &theme::current(cx).workspace.status_bar.lsp_status;
|
let theme = &theme::current(cx).workspace.status_bar.lsp_status;
|
||||||
let style = if state.hovered() && on_click.is_some() {
|
let style = if state.hovered() && on_click.is_some() {
|
||||||
theme.hover.as_ref().unwrap_or(&theme.default)
|
theme.hovered.as_ref().unwrap_or(&theme.default)
|
||||||
} else {
|
} else {
|
||||||
&theme.default
|
&theme.default
|
||||||
};
|
};
|
||||||
|
|
|
@ -309,7 +309,7 @@ impl AssistantPanel {
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
||||||
let style = style.model.style_for(state, false);
|
let style = style.model.style_for(state);
|
||||||
Label::new(model, style.text.clone())
|
Label::new(model, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -414,7 +414,7 @@ impl AssistantPanel {
|
||||||
.with_style(style.title.container),
|
.with_style(style.title.container),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(*style.container.style_for(state, false))
|
.with_style(*style.container.style_for(state))
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
|
@ -1668,19 +1668,19 @@ impl ConversationEditor {
|
||||||
cx,
|
cx,
|
||||||
|state, _| match message.role {
|
|state, _| match message.role {
|
||||||
Role::User => {
|
Role::User => {
|
||||||
let style = style.user_sender.style_for(state, false);
|
let style = style.user_sender.style_for(state);
|
||||||
Label::new("You", style.text.clone())
|
Label::new("You", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
}
|
}
|
||||||
Role::Assistant => {
|
Role::Assistant => {
|
||||||
let style = style.assistant_sender.style_for(state, false);
|
let style = style.assistant_sender.style_for(state);
|
||||||
Label::new("Assistant", style.text.clone())
|
Label::new("Assistant", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
}
|
}
|
||||||
Role::System => {
|
Role::System => {
|
||||||
let style = style.system_sender.style_for(state, false);
|
let style = style.system_sender.style_for(state);
|
||||||
Label::new("System", style.text.clone())
|
Label::new("System", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl View for UpdateNotification {
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -74,7 +74,7 @@ impl View for UpdateNotification {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.with_child({
|
.with_child({
|
||||||
let style = theme.action_message.style_for(state, false);
|
let style = theme.action_message.style_for(state);
|
||||||
Text::new("View the release notes", style.text.clone())
|
Text::new("View the release notes", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl View for Breadcrumbs {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
|
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
|
||||||
let style = style.style_for(state, false);
|
let style = style.style_for(state);
|
||||||
crumbs.with_style(style.container)
|
crumbs.with_style(style.container)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, |_, this, cx| {
|
.on_click(MouseButton::Left, |_, this, cx| {
|
||||||
|
|
|
@ -299,7 +299,12 @@ impl CollabTitlebarItem {
|
||||||
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext<Self>) {
|
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext<Self>) {
|
||||||
let theme = theme::current(cx).clone();
|
let theme = theme::current(cx).clone();
|
||||||
let avatar_style = theme.workspace.titlebar.leader_avatar.clone();
|
let avatar_style = theme.workspace.titlebar.leader_avatar.clone();
|
||||||
let item_style = theme.context_menu.item.disabled_style().clone();
|
let item_style = theme
|
||||||
|
.context_menu
|
||||||
|
.item
|
||||||
|
.inactive_state()
|
||||||
|
.disabled_style()
|
||||||
|
.clone();
|
||||||
self.user_menu.update(cx, |user_menu, cx| {
|
self.user_menu.update(cx, |user_menu, cx| {
|
||||||
let items = if let Some(user) = self.user_store.read(cx).current_user() {
|
let items = if let Some(user) = self.user_store.read(cx).current_user() {
|
||||||
vec![
|
vec![
|
||||||
|
@ -361,8 +366,20 @@ impl CollabTitlebarItem {
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(titlebar.toggle_contacts_badge)
|
.with_style(titlebar.toggle_contacts_badge)
|
||||||
.contained()
|
.contained()
|
||||||
.with_margin_left(titlebar.toggle_contacts_button.default.icon_width)
|
.with_margin_left(
|
||||||
.with_margin_top(titlebar.toggle_contacts_button.default.icon_width)
|
titlebar
|
||||||
|
.toggle_contacts_button
|
||||||
|
.inactive_state()
|
||||||
|
.default
|
||||||
|
.icon_width,
|
||||||
|
)
|
||||||
|
.with_margin_top(
|
||||||
|
titlebar
|
||||||
|
.toggle_contacts_button
|
||||||
|
.inactive_state()
|
||||||
|
.default
|
||||||
|
.icon_width,
|
||||||
|
)
|
||||||
.aligned(),
|
.aligned(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -372,7 +389,8 @@ impl CollabTitlebarItem {
|
||||||
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar
|
let style = titlebar
|
||||||
.toggle_contacts_button
|
.toggle_contacts_button
|
||||||
.style_for(state, self.contacts_popover.is_some());
|
.in_state(self.contacts_popover.is_some())
|
||||||
|
.style_for(state);
|
||||||
Svg::new("icons/user_plus_16.svg")
|
Svg::new("icons/user_plus_16.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -419,7 +437,7 @@ impl CollabTitlebarItem {
|
||||||
|
|
||||||
let titlebar = &theme.workspace.titlebar;
|
let titlebar = &theme.workspace.titlebar;
|
||||||
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.call_control.style_for(state, false);
|
let style = titlebar.call_control.style_for(state);
|
||||||
Svg::new(icon)
|
Svg::new(icon)
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -473,7 +491,7 @@ impl CollabTitlebarItem {
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| {
|
||||||
//TODO: Ensure this button has consistent width for both text variations
|
//TODO: Ensure this button has consistent width for both text variations
|
||||||
let style = titlebar.share_button.style_for(state, false);
|
let style = titlebar.share_button.inactive_state().style_for(state);
|
||||||
Label::new(label, style.text.clone())
|
Label::new(label, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -511,7 +529,7 @@ impl CollabTitlebarItem {
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.call_control.style_for(state, false);
|
let style = titlebar.call_control.style_for(state);
|
||||||
Svg::new("icons/ellipsis_14.svg")
|
Svg::new("icons/ellipsis_14.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -549,7 +567,7 @@ impl CollabTitlebarItem {
|
||||||
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
let titlebar = &theme.workspace.titlebar;
|
let titlebar = &theme.workspace.titlebar;
|
||||||
MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.sign_in_prompt.style_for(state, false);
|
let style = titlebar.sign_in_prompt.inactive_state().style_for(state);
|
||||||
Label::new("Sign In", style.text.clone())
|
Label::new("Sign In", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -117,7 +117,8 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
.contact_finder
|
.contact_finder
|
||||||
.picker
|
.picker
|
||||||
.item
|
.item
|
||||||
.style_for(mouse_state, selected);
|
.in_state(selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(user.avatar.clone().map(|avatar| {
|
.with_children(user.avatar.clone().map(|avatar| {
|
||||||
Image::from_data(avatar)
|
Image::from_data(avatar)
|
||||||
|
|
|
@ -774,7 +774,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
@ -797,7 +798,7 @@ impl ContactList {
|
||||||
.width
|
.width
|
||||||
.or(theme.contact_avatar.height)
|
.or(theme.contact_avatar.height)
|
||||||
.unwrap_or(0.);
|
.unwrap_or(0.);
|
||||||
let row = &theme.project_row.default;
|
let row = &theme.project_row.inactive_state().default;
|
||||||
let tree_branch = theme.tree_branch;
|
let tree_branch = theme.tree_branch;
|
||||||
let line_height = row.name.text.line_height(font_cache);
|
let line_height = row.name.text.line_height(font_cache);
|
||||||
let cap_height = row.name.text.cap_height(font_cache);
|
let cap_height = row.name.text.cap_height(font_cache);
|
||||||
|
@ -810,8 +811,11 @@ impl ContactList {
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| {
|
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| {
|
||||||
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
|
||||||
let row = theme.project_row.style_for(mouse_state, is_selected);
|
let row = theme
|
||||||
|
.project_row
|
||||||
|
.in_state(is_selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -893,7 +897,7 @@ impl ContactList {
|
||||||
.width
|
.width
|
||||||
.or(theme.contact_avatar.height)
|
.or(theme.contact_avatar.height)
|
||||||
.unwrap_or(0.);
|
.unwrap_or(0.);
|
||||||
let row = &theme.project_row.default;
|
let row = &theme.project_row.inactive_state().default;
|
||||||
let tree_branch = theme.tree_branch;
|
let tree_branch = theme.tree_branch;
|
||||||
let line_height = row.name.text.line_height(font_cache);
|
let line_height = row.name.text.line_height(font_cache);
|
||||||
let cap_height = row.name.text.cap_height(font_cache);
|
let cap_height = row.name.text.cap_height(font_cache);
|
||||||
|
@ -904,8 +908,11 @@ impl ContactList {
|
||||||
peer_id.as_u64() as usize,
|
peer_id.as_u64() as usize,
|
||||||
cx,
|
cx,
|
||||||
|mouse_state, _| {
|
|mouse_state, _| {
|
||||||
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
|
||||||
let row = theme.project_row.style_for(mouse_state, is_selected);
|
let row = theme
|
||||||
|
.project_row
|
||||||
|
.in_state(is_selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -989,7 +996,8 @@ impl ContactList {
|
||||||
|
|
||||||
let header_style = theme
|
let header_style = theme
|
||||||
.header_row
|
.header_row
|
||||||
.style_for(&mut Default::default(), is_selected);
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default());
|
||||||
let text = match section {
|
let text = match section {
|
||||||
Section::ActiveCall => "Collaborators",
|
Section::ActiveCall => "Collaborators",
|
||||||
Section::Requests => "Contact Requests",
|
Section::Requests => "Contact Requests",
|
||||||
|
@ -999,7 +1007,7 @@ impl ContactList {
|
||||||
let leave_call = if section == Section::ActiveCall {
|
let leave_call = if section == Section::ActiveCall {
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
|
||||||
let style = theme.leave_call.style_for(state, false);
|
let style = theme.leave_call.style_for(state);
|
||||||
Label::new("Leave Call", style.text.clone())
|
Label::new("Leave Call", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -1110,8 +1118,7 @@ impl ContactList {
|
||||||
contact.user.id as usize,
|
contact.user.id as usize,
|
||||||
cx,
|
cx,
|
||||||
|mouse_state, _| {
|
|mouse_state, _| {
|
||||||
let button_style =
|
let button_style = theme.contact_button.style_for(mouse_state);
|
||||||
theme.contact_button.style_for(mouse_state, false);
|
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg")
|
render_icon_button(button_style, "icons/x_mark_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
.flex_float()
|
.flex_float()
|
||||||
|
@ -1146,7 +1153,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
|
@ -1204,7 +1212,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg").aligned()
|
render_icon_button(button_style, "icons/x_mark_8.svg").aligned()
|
||||||
})
|
})
|
||||||
|
@ -1227,7 +1235,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/check_8.svg")
|
render_icon_button(button_style, "icons/check_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
|
@ -1250,7 +1258,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg")
|
render_icon_button(button_style, "icons/x_mark_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
|
@ -1277,7 +1285,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ where
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
|
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -93,7 +93,7 @@ where
|
||||||
.with_children(buttons.into_iter().enumerate().map(
|
.with_children(buttons.into_iter().enumerate().map(
|
||||||
|(ix, (message, handler))| {
|
|(ix, (message, handler))| {
|
||||||
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
|
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
|
||||||
let button = theme.button.style_for(state, false);
|
let button = theme.button.style_for(state);
|
||||||
Label::new(message, button.text.clone())
|
Label::new(message, button.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(button.container)
|
.with_style(button.container)
|
||||||
|
|
|
@ -185,8 +185,8 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
let mat = &self.matches[ix];
|
let mat = &self.matches[ix];
|
||||||
let command = &self.actions[mat.candidate_id];
|
let command = &self.actions[mat.candidate_id];
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let key_style = &theme.command_palette.key.style_for(mouse_state, selected);
|
let key_style = &theme.command_palette.key.in_state(selected);
|
||||||
let keystroke_spacing = theme.command_palette.keystroke_spacing;
|
let keystroke_spacing = theme.command_palette.keystroke_spacing;
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
|
|
|
@ -328,10 +328,8 @@ impl ContextMenu {
|
||||||
Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
||||||
match item {
|
match item {
|
||||||
ContextMenuItem::Item { label, .. } => {
|
ContextMenuItem::Item { label, .. } => {
|
||||||
let style = style.item.style_for(
|
let style = style.item.in_state(self.selected_index == Some(ix));
|
||||||
&mut Default::default(),
|
let style = style.style_for(&mut Default::default());
|
||||||
Some(ix) == self.selected_index,
|
|
||||||
);
|
|
||||||
|
|
||||||
match label {
|
match label {
|
||||||
ContextMenuItemLabel::String(label) => {
|
ContextMenuItemLabel::String(label) => {
|
||||||
|
@ -363,10 +361,8 @@ impl ContextMenu {
|
||||||
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
||||||
match item {
|
match item {
|
||||||
ContextMenuItem::Item { action, .. } => {
|
ContextMenuItem::Item { action, .. } => {
|
||||||
let style = style.item.style_for(
|
let style = style.item.in_state(self.selected_index == Some(ix));
|
||||||
&mut Default::default(),
|
let style = style.style_for(&mut Default::default());
|
||||||
Some(ix) == self.selected_index,
|
|
||||||
);
|
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
|
ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
|
||||||
|
@ -412,8 +408,8 @@ impl ContextMenu {
|
||||||
let action = action.clone();
|
let action = action.clone();
|
||||||
let view_id = self.parent_view_id;
|
let view_id = self.parent_view_id;
|
||||||
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
|
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
|
||||||
let style =
|
let style = style.item.in_state(self.selected_index == Some(ix));
|
||||||
style.item.style_for(state, Some(ix) == self.selected_index);
|
let style = style.style_for(state);
|
||||||
let keystroke = match &action {
|
let keystroke = match &action {
|
||||||
ContextMenuItemAction::Action(action) => Some(
|
ContextMenuItemAction::Action(action) => Some(
|
||||||
KeystrokeLabel::new(
|
KeystrokeLabel::new(
|
||||||
|
|
|
@ -127,16 +127,16 @@ impl CopilotCodeVerification {
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(
|
Label::new(
|
||||||
if copied { "Copied!" } else { "Copy" },
|
if copied { "Copied!" } else { "Copy" },
|
||||||
device_code_style.cta.style_for(state, false).text.clone(),
|
device_code_style.cta.style_for(state).text.clone(),
|
||||||
)
|
)
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(*device_code_style.right_container.style_for(state, false))
|
.with_style(*device_code_style.right_container.style_for(state))
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_width(device_code_style.right),
|
.with_width(device_code_style.right),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(device_code_style.cta.style_for(state, false).container)
|
.with_style(device_code_style.cta.style_for(state).container)
|
||||||
})
|
})
|
||||||
.on_click(gpui::platform::MouseButton::Left, {
|
.on_click(gpui::platform::MouseButton::Left, {
|
||||||
let user_code = data.user_code.clone();
|
let user_code = data.user_code.clone();
|
||||||
|
|
|
@ -71,7 +71,8 @@ impl View for CopilotButton {
|
||||||
.status_bar
|
.status_bar
|
||||||
.panel_buttons
|
.panel_buttons
|
||||||
.button
|
.button
|
||||||
.style_for(state, active);
|
.in_state(active)
|
||||||
|
.style_for(state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -255,7 +256,7 @@ impl CopilotButton {
|
||||||
move |state: &mut MouseState, style: &theme::ContextMenuItem| {
|
move |state: &mut MouseState, style: &theme::ContextMenuItem| {
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(Label::new("Copilot Settings", style.label.clone()))
|
.with_child(Label::new("Copilot Settings", style.label.clone()))
|
||||||
.with_child(theme::ui::icon(icon_style.style_for(state, false)))
|
.with_child(theme::ui::icon(icon_style.style_for(state)))
|
||||||
.align_children_center()
|
.align_children_center()
|
||||||
.into_any()
|
.into_any()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1509,7 +1509,8 @@ mod tests {
|
||||||
let snapshot = editor.snapshot(cx);
|
let snapshot = editor.snapshot(cx);
|
||||||
snapshot
|
snapshot
|
||||||
.blocks_in_range(0..snapshot.max_point().row())
|
.blocks_in_range(0..snapshot.max_point().row())
|
||||||
.filter_map(|(row, block)| {
|
.enumerate()
|
||||||
|
.filter_map(|(ix, (row, block))| {
|
||||||
let name = match block {
|
let name = match block {
|
||||||
TransformBlock::Custom(block) => block
|
TransformBlock::Custom(block) => block
|
||||||
.render(&mut BlockContext {
|
.render(&mut BlockContext {
|
||||||
|
@ -1520,6 +1521,7 @@ mod tests {
|
||||||
gutter_width: 0.,
|
gutter_width: 0.,
|
||||||
line_height: 0.,
|
line_height: 0.,
|
||||||
em_width: 0.,
|
em_width: 0.,
|
||||||
|
block_id: ix,
|
||||||
})
|
})
|
||||||
.name()?
|
.name()?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl View for DiagnosticIndicator {
|
||||||
.workspace
|
.workspace
|
||||||
.status_bar
|
.status_bar
|
||||||
.diagnostic_summary
|
.diagnostic_summary
|
||||||
.style_for(state, false);
|
.style_for(state);
|
||||||
|
|
||||||
let mut summary_row = Flex::row();
|
let mut summary_row = Flex::row();
|
||||||
if self.summary.error_count > 0 {
|
if self.summary.error_count > 0 {
|
||||||
|
@ -198,7 +198,7 @@ impl View for DiagnosticIndicator {
|
||||||
MouseEventHandler::<Message, _>::new(1, cx, |state, _| {
|
MouseEventHandler::<Message, _>::new(1, cx, |state, _| {
|
||||||
Label::new(
|
Label::new(
|
||||||
diagnostic.message.split('\n').next().unwrap().to_string(),
|
diagnostic.message.split('\n').next().unwrap().to_string(),
|
||||||
message_style.style_for(state, false).text.clone(),
|
message_style.style_for(state).text.clone(),
|
||||||
)
|
)
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
|
|
|
@ -88,6 +88,7 @@ pub struct BlockContext<'a, 'b, 'c> {
|
||||||
pub gutter_padding: f32,
|
pub gutter_padding: f32,
|
||||||
pub em_width: f32,
|
pub em_width: f32,
|
||||||
pub line_height: f32,
|
pub line_height: f32,
|
||||||
|
pub block_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
|
|
@ -206,6 +206,7 @@ actions!(
|
||||||
DuplicateLine,
|
DuplicateLine,
|
||||||
MoveLineUp,
|
MoveLineUp,
|
||||||
MoveLineDown,
|
MoveLineDown,
|
||||||
|
JoinLines,
|
||||||
Transpose,
|
Transpose,
|
||||||
Cut,
|
Cut,
|
||||||
Copy,
|
Copy,
|
||||||
|
@ -321,6 +322,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(Editor::indent);
|
cx.add_action(Editor::indent);
|
||||||
cx.add_action(Editor::outdent);
|
cx.add_action(Editor::outdent);
|
||||||
cx.add_action(Editor::delete_line);
|
cx.add_action(Editor::delete_line);
|
||||||
|
cx.add_action(Editor::join_lines);
|
||||||
cx.add_action(Editor::delete_to_previous_word_start);
|
cx.add_action(Editor::delete_to_previous_word_start);
|
||||||
cx.add_action(Editor::delete_to_previous_subword_start);
|
cx.add_action(Editor::delete_to_previous_subword_start);
|
||||||
cx.add_action(Editor::delete_to_next_word_end);
|
cx.add_action(Editor::delete_to_next_word_end);
|
||||||
|
@ -3320,15 +3322,21 @@ impl Editor {
|
||||||
pub fn render_code_actions_indicator(
|
pub fn render_code_actions_indicator(
|
||||||
&self,
|
&self,
|
||||||
style: &EditorStyle,
|
style: &EditorStyle,
|
||||||
active: bool,
|
is_active: bool,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<AnyElement<Self>> {
|
) -> Option<AnyElement<Self>> {
|
||||||
if self.available_code_actions.is_some() {
|
if self.available_code_actions.is_some() {
|
||||||
enum CodeActions {}
|
enum CodeActions {}
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
|
||||||
Svg::new("icons/bolt_8.svg")
|
Svg::new("icons/bolt_8.svg").with_color(
|
||||||
.with_color(style.code_actions.indicator.style_for(state, active).color)
|
style
|
||||||
|
.code_actions
|
||||||
|
.indicator
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state)
|
||||||
|
.color,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.with_padding(Padding::uniform(3.))
|
.with_padding(Padding::uniform(3.))
|
||||||
|
@ -3378,10 +3386,8 @@ impl Editor {
|
||||||
.with_color(
|
.with_color(
|
||||||
style
|
style
|
||||||
.indicator
|
.indicator
|
||||||
.style_for(
|
.in_state(fold_status == FoldStatus::Folded)
|
||||||
mouse_state,
|
.style_for(mouse_state)
|
||||||
fold_status == FoldStatus::Folded,
|
|
||||||
)
|
|
||||||
.color,
|
.color,
|
||||||
)
|
)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -3952,6 +3958,60 @@ impl Editor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
|
||||||
|
let mut row_ranges = Vec::<Range<u32>>::new();
|
||||||
|
for selection in self.selections.all::<Point>(cx) {
|
||||||
|
let start = selection.start.row;
|
||||||
|
let end = if selection.start.row == selection.end.row {
|
||||||
|
selection.start.row + 1
|
||||||
|
} else {
|
||||||
|
selection.end.row
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(last_row_range) = row_ranges.last_mut() {
|
||||||
|
if start <= last_row_range.end {
|
||||||
|
last_row_range.end = end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row_ranges.push(start..end);
|
||||||
|
}
|
||||||
|
|
||||||
|
let snapshot = self.buffer.read(cx).snapshot(cx);
|
||||||
|
let mut cursor_positions = Vec::new();
|
||||||
|
for row_range in &row_ranges {
|
||||||
|
let anchor = snapshot.anchor_before(Point::new(
|
||||||
|
row_range.end - 1,
|
||||||
|
snapshot.line_len(row_range.end - 1),
|
||||||
|
));
|
||||||
|
cursor_positions.push(anchor.clone()..anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.transact(cx, |this, cx| {
|
||||||
|
for row_range in row_ranges.into_iter().rev() {
|
||||||
|
for row in row_range.rev() {
|
||||||
|
let end_of_line = Point::new(row, snapshot.line_len(row));
|
||||||
|
let indent = snapshot.indent_size_for_line(row + 1);
|
||||||
|
let start_of_next_line = Point::new(row + 1, indent.len);
|
||||||
|
|
||||||
|
let replace = if snapshot.line_len(row + 1) > indent.len {
|
||||||
|
" "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||||
|
s.select_anchor_ranges(cursor_positions)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
|
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = &display_map.buffer_snapshot;
|
let buffer = &display_map.buffer_snapshot;
|
||||||
|
@ -7949,6 +8009,7 @@ impl Deref for EditorStyle {
|
||||||
|
|
||||||
pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
|
pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
|
||||||
let mut highlighted_lines = Vec::new();
|
let mut highlighted_lines = Vec::new();
|
||||||
|
|
||||||
for (index, line) in diagnostic.message.lines().enumerate() {
|
for (index, line) in diagnostic.message.lines().enumerate() {
|
||||||
let line = match &diagnostic.source {
|
let line = match &diagnostic.source {
|
||||||
Some(source) if index == 0 => {
|
Some(source) if index == 0 => {
|
||||||
|
@ -7960,25 +8021,44 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
|
||||||
};
|
};
|
||||||
highlighted_lines.push(line);
|
highlighted_lines.push(line);
|
||||||
}
|
}
|
||||||
|
let message = diagnostic.message;
|
||||||
Arc::new(move |cx: &mut BlockContext| {
|
Arc::new(move |cx: &mut BlockContext| {
|
||||||
|
let message = message.clone();
|
||||||
let settings = settings::get::<ThemeSettings>(cx);
|
let settings = settings::get::<ThemeSettings>(cx);
|
||||||
|
let tooltip_style = settings.theme.tooltip.clone();
|
||||||
let theme = &settings.theme.editor;
|
let theme = &settings.theme.editor;
|
||||||
let style = diagnostic_style(diagnostic.severity, is_valid, theme);
|
let style = diagnostic_style(diagnostic.severity, is_valid, theme);
|
||||||
let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
|
let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
|
||||||
Flex::column()
|
let anchor_x = cx.anchor_x;
|
||||||
.with_children(highlighted_lines.iter().map(|(line, highlights)| {
|
enum BlockContextToolip {}
|
||||||
Label::new(
|
MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
|
||||||
line.clone(),
|
Flex::column()
|
||||||
style.message.clone().with_font_size(font_size),
|
.with_children(highlighted_lines.iter().map(|(line, highlights)| {
|
||||||
)
|
Label::new(
|
||||||
.with_highlights(highlights.clone())
|
line.clone(),
|
||||||
.contained()
|
style.message.clone().with_font_size(font_size),
|
||||||
.with_margin_left(cx.anchor_x)
|
)
|
||||||
}))
|
.with_highlights(highlights.clone())
|
||||||
.aligned()
|
.contained()
|
||||||
.left()
|
.with_margin_left(anchor_x)
|
||||||
.into_any()
|
}))
|
||||||
|
.aligned()
|
||||||
|
.left()
|
||||||
|
.into_any()
|
||||||
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.on_click(MouseButton::Left, move |_, _, cx| {
|
||||||
|
cx.write_to_clipboard(ClipboardItem::new(message.clone()));
|
||||||
|
})
|
||||||
|
// We really need to rethink this ID system...
|
||||||
|
.with_tooltip::<BlockContextToolip>(
|
||||||
|
cx.block_id,
|
||||||
|
"Copy diagnostic message".to_string(),
|
||||||
|
None,
|
||||||
|
tooltip_style,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.into_any()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::test::{
|
use crate::{
|
||||||
assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
|
test::{
|
||||||
editor_test_context::EditorTestContext, select_ranges,
|
assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
|
||||||
|
editor_test_context::EditorTestContext, select_ranges,
|
||||||
|
},
|
||||||
|
JoinLines,
|
||||||
};
|
};
|
||||||
use drag_and_drop::DragAndDrop;
|
use drag_and_drop::DragAndDrop;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
@ -2325,6 +2328,137 @@ fn test_delete_line(cx: &mut TestAppContext) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
|
cx.add_window(|cx| {
|
||||||
|
let buffer = MultiBuffer::build_simple("aaa\nbbb\nccc\nddd\n\n", cx);
|
||||||
|
let mut editor = build_editor(buffer.clone(), cx);
|
||||||
|
let buffer = buffer.read(cx).as_singleton().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
&[Point::new(0, 0)..Point::new(0, 0)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// When on single line, replace newline at end by space
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
&[Point::new(0, 3)..Point::new(0, 3)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// When multiple lines are selected, remove newlines that are spanned by the selection
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.select_ranges([Point::new(0, 5)..Point::new(2, 2)])
|
||||||
|
});
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb ccc ddd\n\n");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
&[Point::new(0, 11)..Point::new(0, 11)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Undo should be transactional
|
||||||
|
editor.undo(&Undo, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
&[Point::new(0, 5)..Point::new(2, 2)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// When joining an empty line don't insert a space
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.select_ranges([Point::new(2, 1)..Point::new(2, 2)])
|
||||||
|
});
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
[Point::new(2, 3)..Point::new(2, 3)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// We can remove trailing newlines
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
[Point::new(2, 3)..Point::new(2, 3)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// We don't blow up on the last line
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
[Point::new(2, 3)..Point::new(2, 3)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// reset to test indentation
|
||||||
|
editor.buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.edit(
|
||||||
|
[
|
||||||
|
(Point::new(1, 0)..Point::new(1, 2), " "),
|
||||||
|
(Point::new(2, 0)..Point::new(2, 3), " \n\td"),
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
// We remove any leading spaces
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb\n c\n \n\td");
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.select_ranges([Point::new(0, 1)..Point::new(0, 1)])
|
||||||
|
});
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb c\n \n\td");
|
||||||
|
|
||||||
|
// We don't insert a space for a line containing only spaces
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb c\n\td");
|
||||||
|
|
||||||
|
// We ignore any leading tabs
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb c d");
|
||||||
|
|
||||||
|
editor
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_join_lines_with_multi_selection(cx: &mut TestAppContext) {
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
|
cx.add_window(|cx| {
|
||||||
|
let buffer = MultiBuffer::build_simple("aaa\nbbb\nccc\nddd\n\n", cx);
|
||||||
|
let mut editor = build_editor(buffer.clone(), cx);
|
||||||
|
let buffer = buffer.read(cx).as_singleton().unwrap();
|
||||||
|
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.select_ranges([
|
||||||
|
Point::new(0, 2)..Point::new(1, 1),
|
||||||
|
Point::new(1, 2)..Point::new(1, 2),
|
||||||
|
Point::new(3, 1)..Point::new(3, 2),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.join_lines(&JoinLines, cx);
|
||||||
|
assert_eq!(buffer.read(cx).text(), "aaa bbb ccc\nddd\n");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.ranges::<Point>(cx),
|
||||||
|
[
|
||||||
|
Point::new(0, 7)..Point::new(0, 7),
|
||||||
|
Point::new(1, 3)..Point::new(1, 3)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
editor
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_duplicate_line(cx: &mut TestAppContext) {
|
fn test_duplicate_line(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
|
|
@ -1467,6 +1467,7 @@ impl EditorElement {
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
cx: &mut LayoutContext<Editor>,
|
cx: &mut LayoutContext<Editor>,
|
||||||
) -> (f32, Vec<BlockLayout>) {
|
) -> (f32, Vec<BlockLayout>) {
|
||||||
|
let mut block_id = 0;
|
||||||
let scroll_x = snapshot.scroll_anchor.offset.x();
|
let scroll_x = snapshot.scroll_anchor.offset.x();
|
||||||
let (fixed_blocks, non_fixed_blocks) = snapshot
|
let (fixed_blocks, non_fixed_blocks) = snapshot
|
||||||
.blocks_in_range(rows.clone())
|
.blocks_in_range(rows.clone())
|
||||||
|
@ -1474,7 +1475,7 @@ impl EditorElement {
|
||||||
TransformBlock::ExcerptHeader { .. } => false,
|
TransformBlock::ExcerptHeader { .. } => false,
|
||||||
TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed,
|
TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed,
|
||||||
});
|
});
|
||||||
let mut render_block = |block: &TransformBlock, width: f32| {
|
let mut render_block = |block: &TransformBlock, width: f32, block_id: usize| {
|
||||||
let mut element = match block {
|
let mut element = match block {
|
||||||
TransformBlock::Custom(block) => {
|
TransformBlock::Custom(block) => {
|
||||||
let align_to = block
|
let align_to = block
|
||||||
|
@ -1499,6 +1500,7 @@ impl EditorElement {
|
||||||
scroll_x,
|
scroll_x,
|
||||||
gutter_width,
|
gutter_width,
|
||||||
em_width,
|
em_width,
|
||||||
|
block_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
TransformBlock::ExcerptHeader {
|
TransformBlock::ExcerptHeader {
|
||||||
|
@ -1527,7 +1529,7 @@ impl EditorElement {
|
||||||
|
|
||||||
enum JumpIcon {}
|
enum JumpIcon {}
|
||||||
MouseEventHandler::<JumpIcon, _>::new((*id).into(), cx, |state, _| {
|
MouseEventHandler::<JumpIcon, _>::new((*id).into(), cx, |state, _| {
|
||||||
let style = style.jump_icon.style_for(state, false);
|
let style = style.jump_icon.style_for(state);
|
||||||
Svg::new("icons/arrow_up_right_8.svg")
|
Svg::new("icons/arrow_up_right_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -1634,7 +1636,8 @@ impl EditorElement {
|
||||||
let mut fixed_block_max_width = 0f32;
|
let mut fixed_block_max_width = 0f32;
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
for (row, block) in fixed_blocks {
|
for (row, block) in fixed_blocks {
|
||||||
let element = render_block(block, f32::INFINITY);
|
let element = render_block(block, f32::INFINITY, block_id);
|
||||||
|
block_id += 1;
|
||||||
fixed_block_max_width = fixed_block_max_width.max(element.size().x() + em_width);
|
fixed_block_max_width = fixed_block_max_width.max(element.size().x() + em_width);
|
||||||
blocks.push(BlockLayout {
|
blocks.push(BlockLayout {
|
||||||
row,
|
row,
|
||||||
|
@ -1654,7 +1657,8 @@ impl EditorElement {
|
||||||
.max(gutter_width + scroll_width),
|
.max(gutter_width + scroll_width),
|
||||||
BlockStyle::Fixed => unreachable!(),
|
BlockStyle::Fixed => unreachable!(),
|
||||||
};
|
};
|
||||||
let element = render_block(block, width);
|
let element = render_block(block, width, block_id);
|
||||||
|
block_id += 1;
|
||||||
blocks.push(BlockLayout {
|
blocks.push(BlockLayout {
|
||||||
row,
|
row,
|
||||||
element,
|
element,
|
||||||
|
@ -2090,7 +2094,7 @@ impl Element<Editor> for EditorElement {
|
||||||
.folds
|
.folds
|
||||||
.ellipses
|
.ellipses
|
||||||
.background
|
.background
|
||||||
.style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize), false)
|
.style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize))
|
||||||
.color;
|
.color;
|
||||||
|
|
||||||
(id, fold, color)
|
(id, fold, color)
|
||||||
|
|
|
@ -41,7 +41,8 @@ impl View for DeployFeedbackButton {
|
||||||
.status_bar
|
.status_bar
|
||||||
.panel_buttons
|
.panel_buttons
|
||||||
.button
|
.button
|
||||||
.style_for(state, active);
|
.in_state(active)
|
||||||
|
.style_for(state);
|
||||||
|
|
||||||
Svg::new("icons/feedback_16.svg")
|
Svg::new("icons/feedback_16.svg")
|
||||||
.with_color(style.icon_color)
|
.with_color(style.icon_color)
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl View for SubmitFeedbackButton {
|
||||||
let theme = theme::current(cx).clone();
|
let theme = theme::current(cx).clone();
|
||||||
enum SubmitFeedbackButton {}
|
enum SubmitFeedbackButton {}
|
||||||
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| {
|
||||||
let style = theme.feedback.submit_button.style_for(state, false);
|
let style = theme.feedback.submit_button.style_for(state);
|
||||||
Label::new("Submit as Markdown", style.text.clone())
|
Label::new("Submit as Markdown", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -546,7 +546,7 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.get(ix)
|
.get(ix)
|
||||||
.expect("Invalid matches state: no element for index {ix}");
|
.expect("Invalid matches state: no element for index {ix}");
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
self.labels_for_match(path_match, cx, ix);
|
self.labels_for_match(path_match, cx, ix);
|
||||||
Flex::column()
|
Flex::column()
|
||||||
|
|
|
@ -6,15 +6,16 @@ use std::{
|
||||||
|
|
||||||
use crate::json::ToJson;
|
use crate::json::ToJson;
|
||||||
use pathfinder_color::{ColorF, ColorU};
|
use pathfinder_color::{ColorF, ColorU};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{self, Unexpected},
|
de::{self, Unexpected},
|
||||||
Deserialize, Deserializer,
|
Deserialize, Deserializer,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Color(ColorU);
|
pub struct Color(#[schemars(with = "String")] ColorU);
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
pub fn transparent_black() -> Self {
|
pub fn transparent_black() -> Self {
|
||||||
|
|
|
@ -12,10 +12,11 @@ use crate::{
|
||||||
scene::{self, Border, CursorRegion, Quad},
|
scene::{self, Border, CursorRegion, Quad},
|
||||||
AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)]
|
||||||
pub struct ContainerStyle {
|
pub struct ContainerStyle {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub margin: Margin,
|
pub margin: Margin,
|
||||||
|
@ -332,7 +333,7 @@ impl ToJson for ContainerStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default, JsonSchema)]
|
||||||
pub struct Margin {
|
pub struct Margin {
|
||||||
pub top: f32,
|
pub top: f32,
|
||||||
pub left: f32,
|
pub left: f32,
|
||||||
|
@ -359,7 +360,7 @@ impl ToJson for Margin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default, JsonSchema)]
|
||||||
pub struct Padding {
|
pub struct Padding {
|
||||||
pub top: f32,
|
pub top: f32,
|
||||||
pub left: f32,
|
pub left: f32,
|
||||||
|
@ -486,9 +487,10 @@ impl ToJson for Padding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
#[serde(default, deserialize_with = "deserialize_vec2f")]
|
#[serde(default, deserialize_with = "deserialize_vec2f")]
|
||||||
|
#[schemars(with = "Vec::<f32>")]
|
||||||
offset: Vector2F,
|
offset: Vector2F,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
blur: f32,
|
blur: f32,
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
scene, Border, Element, ImageData, LayoutContext, SceneBuilder, SizeConstraint, View,
|
scene, Border, Element, ImageData, LayoutContext, SceneBuilder, SizeConstraint, View,
|
||||||
ViewContext,
|
ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{ops::Range, sync::Arc};
|
use std::{ops::Range, sync::Arc};
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ pub struct Image {
|
||||||
style: ImageStyle,
|
style: ImageStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Deserialize)]
|
#[derive(Copy, Clone, Default, Deserialize, JsonSchema)]
|
||||||
pub struct ImageStyle {
|
pub struct ImageStyle {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub border: Border,
|
pub border: Border,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
text_layout::{Line, RunStyle},
|
text_layout::{Line, RunStyle},
|
||||||
Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
@ -20,7 +21,7 @@ pub struct Label {
|
||||||
highlight_indices: Vec<usize>,
|
highlight_indices: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct LabelStyle {
|
pub struct LabelStyle {
|
||||||
pub text: TextStyle,
|
pub text: TextStyle,
|
||||||
pub highlight_text: Option<TextStyle>,
|
pub highlight_text: Option<TextStyle>,
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
scene, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
scene, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{borrow::Cow, ops::Range};
|
use std::{borrow::Cow, ops::Range};
|
||||||
|
@ -115,14 +116,14 @@ impl<V: View> Element<V> for Svg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct SvgStyle {
|
pub struct SvgStyle {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
pub asset: String,
|
pub asset: String,
|
||||||
pub dimensions: Dimensions,
|
pub dimensions: Dimensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Dimensions {
|
pub struct Dimensions {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
Action, Axis, ElementStateHandle, LayoutContext, SceneBuilder, SizeConstraint, Task, View,
|
Action, Axis, ElementStateHandle, LayoutContext, SceneBuilder, SizeConstraint, Task, View,
|
||||||
ViewContext,
|
ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
|
@ -33,7 +34,7 @@ struct TooltipState {
|
||||||
debounce: RefCell<Option<Task<()>>>,
|
debounce: RefCell<Option<Task<()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct TooltipStyle {
|
pub struct TooltipStyle {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -42,7 +43,7 @@ pub struct TooltipStyle {
|
||||||
pub max_text_width: Option<f32>,
|
pub max_text_width: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct KeystrokeStyle {
|
pub struct KeystrokeStyle {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
container: ContainerStyle,
|
container: ContainerStyle,
|
||||||
|
|
|
@ -7,13 +7,14 @@ use crate::{
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, JsonSchema)]
|
||||||
pub struct FamilyId(usize);
|
pub struct FamilyId(usize);
|
||||||
|
|
||||||
struct Family {
|
struct Family {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use serde::{de, Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{cell::RefCell, sync::Arc};
|
use std::{cell::RefCell, sync::Arc};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, JsonSchema)]
|
||||||
pub struct FontId(pub usize);
|
pub struct FontId(pub usize);
|
||||||
|
|
||||||
pub type GlyphId = u32;
|
pub type GlyphId = u32;
|
||||||
|
@ -59,20 +59,44 @@ pub struct Features {
|
||||||
pub zero: Option<bool>,
|
pub zero: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, JsonSchema)]
|
||||||
pub struct TextStyle {
|
pub struct TextStyle {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
pub font_family_name: Arc<str>,
|
pub font_family_name: Arc<str>,
|
||||||
pub font_family_id: FamilyId,
|
pub font_family_id: FamilyId,
|
||||||
pub font_id: FontId,
|
pub font_id: FontId,
|
||||||
pub font_size: f32,
|
pub font_size: f32,
|
||||||
|
#[schemars(with = "PropertiesDef")]
|
||||||
pub font_properties: Properties,
|
pub font_properties: Properties,
|
||||||
pub underline: Underline,
|
pub underline: Underline,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
#[derive(JsonSchema)]
|
||||||
|
#[serde(remote = "Properties")]
|
||||||
|
pub struct PropertiesDef {
|
||||||
|
/// The font style, as defined in CSS.
|
||||||
|
pub style: StyleDef,
|
||||||
|
/// The font weight, as defined in CSS.
|
||||||
|
pub weight: f32,
|
||||||
|
/// The font stretchiness, as defined in CSS.
|
||||||
|
pub stretch: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(remote = "Style")]
|
||||||
|
pub enum StyleDef {
|
||||||
|
/// A face that is neither italic not obliqued.
|
||||||
|
Normal,
|
||||||
|
/// A form that is generally cursive in nature.
|
||||||
|
Italic,
|
||||||
|
/// A typically-sloped version of the regular face.
|
||||||
|
Oblique,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default, PartialEq, JsonSchema)]
|
||||||
pub struct HighlightStyle {
|
pub struct HighlightStyle {
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
|
#[schemars(with = "Option::<f32>")]
|
||||||
pub weight: Option<Weight>,
|
pub weight: Option<Weight>,
|
||||||
pub italic: Option<bool>,
|
pub italic: Option<bool>,
|
||||||
pub underline: Option<Underline>,
|
pub underline: Option<Underline>,
|
||||||
|
@ -81,9 +105,10 @@ pub struct HighlightStyle {
|
||||||
|
|
||||||
impl Eq for HighlightStyle {}
|
impl Eq for HighlightStyle {}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, JsonSchema)]
|
||||||
pub struct Underline {
|
pub struct Underline {
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
|
#[schemars(with = "f32")]
|
||||||
pub thickness: OrderedFloat<f32>,
|
pub thickness: OrderedFloat<f32>,
|
||||||
pub squiggly: bool,
|
pub squiggly: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use anyhow::{anyhow, bail, Result};
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
use postage::oneshot;
|
use postage::oneshot;
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlez::{
|
use sqlez::{
|
||||||
bindable::{Bind, Column, StaticColumnCount},
|
bindable::{Bind, Column, StaticColumnCount},
|
||||||
|
@ -282,7 +283,7 @@ pub enum PromptLevel {
|
||||||
Critical,
|
Critical,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize)]
|
#[derive(Copy, Clone, Debug, Deserialize, JsonSchema)]
|
||||||
pub enum CursorStyle {
|
pub enum CursorStyle {
|
||||||
Arrow,
|
Arrow,
|
||||||
ResizeLeftRight,
|
ResizeLeftRight,
|
||||||
|
|
|
@ -3,6 +3,7 @@ mod mouse_region;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use collections::HashSet;
|
use collections::HashSet;
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
@ -99,7 +100,7 @@ pub struct Icon {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Debug)]
|
#[derive(Clone, Copy, Default, Debug, JsonSchema)]
|
||||||
pub struct Border {
|
pub struct Border {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl View for ActiveBufferLanguage {
|
||||||
|
|
||||||
MouseEventHandler::<Self, Self>::new(0, cx, |state, cx| {
|
MouseEventHandler::<Self, Self>::new(0, cx, |state, cx| {
|
||||||
let theme = &theme::current(cx).workspace.status_bar;
|
let theme = &theme::current(cx).workspace.status_bar;
|
||||||
let style = theme.active_language.style_for(state, false);
|
let style = theme.active_language.style_for(state);
|
||||||
Label::new(active_language_text, style.text.clone())
|
Label::new(active_language_text, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -180,7 +180,7 @@ impl PickerDelegate for LanguageSelectorDelegate {
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let mat = &self.matches[ix];
|
let mat = &self.matches[ix];
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
|
let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
|
||||||
let mut label = mat.string.clone();
|
let mut label = mat.string.clone();
|
||||||
if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
|
if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
|
||||||
|
|
|
@ -681,7 +681,7 @@ impl LspLogToolbarItemView {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| "No server selected".into());
|
.unwrap_or_else(|| "No server selected".into());
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state, false);
|
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
||||||
Label::new(label, style.text.clone())
|
Label::new(label, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -722,7 +722,8 @@ impl LspLogToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, logs_selected);
|
.in_state(logs_selected)
|
||||||
|
.style_for(state);
|
||||||
Label::new(SERVER_LOGS, style.text.clone())
|
Label::new(SERVER_LOGS, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -739,7 +740,8 @@ impl LspLogToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, rpc_trace_selected);
|
.in_state(rpc_trace_selected)
|
||||||
|
.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(RPC_MESSAGES, style.text.clone())
|
Label::new(RPC_MESSAGES, style.text.clone())
|
||||||
|
|
|
@ -565,7 +565,7 @@ impl SyntaxTreeToolbarItemView {
|
||||||
) -> impl Element<Self> {
|
) -> impl Element<Self> {
|
||||||
enum ToggleMenu {}
|
enum ToggleMenu {}
|
||||||
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, _| {
|
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, _| {
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state, false);
|
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(active_layer.language.name().to_string(), style.text.clone())
|
Label::new(active_layer.language.name().to_string(), style.text.clone())
|
||||||
|
@ -601,7 +601,8 @@ impl SyntaxTreeToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, is_selected);
|
.in_state(is_selected)
|
||||||
|
.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(layer.language.name().to_string(), style.text.clone())
|
Label::new(layer.language.name().to_string(), style.text.clone())
|
||||||
|
|
|
@ -33,7 +33,7 @@ const JSON_RPC_VERSION: &str = "2.0";
|
||||||
const CONTENT_LEN_HEADER: &str = "Content-Length: ";
|
const CONTENT_LEN_HEADER: &str = "Content-Length: ";
|
||||||
|
|
||||||
type NotificationHandler = Box<dyn Send + FnMut(Option<usize>, &str, AsyncAppContext)>;
|
type NotificationHandler = Box<dyn Send + FnMut(Option<usize>, &str, AsyncAppContext)>;
|
||||||
type ResponseHandler = Box<dyn Send + FnOnce(Result<&str, Error>)>;
|
type ResponseHandler = Box<dyn Send + FnOnce(Result<String, Error>)>;
|
||||||
type IoHandler = Box<dyn Send + FnMut(bool, &str)>;
|
type IoHandler = Box<dyn Send + FnMut(bool, &str)>;
|
||||||
|
|
||||||
pub struct LanguageServer {
|
pub struct LanguageServer {
|
||||||
|
@ -302,9 +302,9 @@ impl LanguageServer {
|
||||||
if let Some(error) = error {
|
if let Some(error) = error {
|
||||||
handler(Err(error));
|
handler(Err(error));
|
||||||
} else if let Some(result) = result {
|
} else if let Some(result) = result {
|
||||||
handler(Ok(result.get()));
|
handler(Ok(result.get().into()));
|
||||||
} else {
|
} else {
|
||||||
handler(Ok("null"));
|
handler(Ok("null".into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -457,11 +457,13 @@ impl LanguageServer {
|
||||||
let response_handlers = self.response_handlers.clone();
|
let response_handlers = self.response_handlers.clone();
|
||||||
let next_id = AtomicUsize::new(self.next_id.load(SeqCst));
|
let next_id = AtomicUsize::new(self.next_id.load(SeqCst));
|
||||||
let outbound_tx = self.outbound_tx.clone();
|
let outbound_tx = self.outbound_tx.clone();
|
||||||
|
let executor = self.executor.clone();
|
||||||
let mut output_done = self.output_done_rx.lock().take().unwrap();
|
let mut output_done = self.output_done_rx.lock().take().unwrap();
|
||||||
let shutdown_request = Self::request_internal::<request::Shutdown>(
|
let shutdown_request = Self::request_internal::<request::Shutdown>(
|
||||||
&next_id,
|
&next_id,
|
||||||
&response_handlers,
|
&response_handlers,
|
||||||
&outbound_tx,
|
&outbound_tx,
|
||||||
|
&executor,
|
||||||
(),
|
(),
|
||||||
);
|
);
|
||||||
let exit = Self::notify_internal::<notification::Exit>(&outbound_tx, ());
|
let exit = Self::notify_internal::<notification::Exit>(&outbound_tx, ());
|
||||||
|
@ -658,6 +660,7 @@ impl LanguageServer {
|
||||||
&self.next_id,
|
&self.next_id,
|
||||||
&self.response_handlers,
|
&self.response_handlers,
|
||||||
&self.outbound_tx,
|
&self.outbound_tx,
|
||||||
|
&self.executor,
|
||||||
params,
|
params,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -666,6 +669,7 @@ impl LanguageServer {
|
||||||
next_id: &AtomicUsize,
|
next_id: &AtomicUsize,
|
||||||
response_handlers: &Mutex<Option<HashMap<usize, ResponseHandler>>>,
|
response_handlers: &Mutex<Option<HashMap<usize, ResponseHandler>>>,
|
||||||
outbound_tx: &channel::Sender<String>,
|
outbound_tx: &channel::Sender<String>,
|
||||||
|
executor: &Arc<executor::Background>,
|
||||||
params: T::Params,
|
params: T::Params,
|
||||||
) -> impl 'static + Future<Output = Result<T::Result>>
|
) -> impl 'static + Future<Output = Result<T::Result>>
|
||||||
where
|
where
|
||||||
|
@ -686,15 +690,20 @@ impl LanguageServer {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.ok_or_else(|| anyhow!("server shut down"))
|
.ok_or_else(|| anyhow!("server shut down"))
|
||||||
.map(|handlers| {
|
.map(|handlers| {
|
||||||
|
let executor = executor.clone();
|
||||||
handlers.insert(
|
handlers.insert(
|
||||||
id,
|
id,
|
||||||
Box::new(move |result| {
|
Box::new(move |result| {
|
||||||
let response = match result {
|
executor
|
||||||
Ok(response) => serde_json::from_str(response)
|
.spawn(async move {
|
||||||
.context("failed to deserialize response"),
|
let response = match result {
|
||||||
Err(error) => Err(anyhow!("{}", error.message)),
|
Ok(response) => serde_json::from_str(&response)
|
||||||
};
|
.context("failed to deserialize response"),
|
||||||
let _ = tx.send(response);
|
Err(error) => Err(anyhow!("{}", error.message)),
|
||||||
|
};
|
||||||
|
let _ = tx.send(response);
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl PickerDelegate for OutlineViewDelegate {
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
let outline_item = &self.outline.items[string_match.candidate_id];
|
let outline_item = &self.outline.items[string_match.candidate_id];
|
||||||
|
|
||||||
|
|
|
@ -1254,7 +1254,10 @@ impl ProjectPanel {
|
||||||
let show_editor = details.is_editing && !details.is_processing;
|
let show_editor = details.is_editing && !details.is_processing;
|
||||||
|
|
||||||
MouseEventHandler::<Self, _>::new(entry_id.to_usize(), cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(entry_id.to_usize(), cx, |state, cx| {
|
||||||
let mut style = entry_style.style_for(state, details.is_selected).clone();
|
let mut style = entry_style
|
||||||
|
.in_state(details.is_selected)
|
||||||
|
.style_for(state)
|
||||||
|
.clone();
|
||||||
|
|
||||||
if cx
|
if cx
|
||||||
.global::<DragAndDrop<Workspace>>()
|
.global::<DragAndDrop<Workspace>>()
|
||||||
|
@ -1265,7 +1268,7 @@ impl ProjectPanel {
|
||||||
.filter(|destination| details.path.starts_with(destination))
|
.filter(|destination| details.path.starts_with(destination))
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
style = entry_style.active.clone().unwrap();
|
style = entry_style.active_state().default.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let row_container_style = if show_editor {
|
let row_container_style = if show_editor {
|
||||||
|
@ -1406,9 +1409,11 @@ impl View for ProjectPanel {
|
||||||
let button_style = theme.open_project_button.clone();
|
let button_style = theme.open_project_button.clone();
|
||||||
let context_menu_item_style = theme::current(cx).context_menu.item.clone();
|
let context_menu_item_style = theme::current(cx).context_menu.item.clone();
|
||||||
move |state, cx| {
|
move |state, cx| {
|
||||||
let button_style = button_style.style_for(state, false).clone();
|
let button_style = button_style.style_for(state).clone();
|
||||||
let context_menu_item =
|
let context_menu_item = context_menu_item_style
|
||||||
context_menu_item_style.style_for(state, true).clone();
|
.active_state()
|
||||||
|
.style_for(state)
|
||||||
|
.clone();
|
||||||
|
|
||||||
theme::ui::keystroke_label(
|
theme::ui::keystroke_label(
|
||||||
"Open a project",
|
"Open a project",
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = &theme.picker.item;
|
let style = &theme.picker.item;
|
||||||
let current_style = style.style_for(mouse_state, selected);
|
let current_style = style.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
let symbol = &self.symbols[string_match.candidate_id];
|
let symbol = &self.symbols[string_match.candidate_id];
|
||||||
|
@ -229,7 +229,10 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
||||||
.with_child(
|
.with_child(
|
||||||
// Avoid styling the path differently when it is selected, since
|
// Avoid styling the path differently when it is selected, since
|
||||||
// the symbol's syntax highlighting doesn't change when selected.
|
// the symbol's syntax highlighting doesn't change when selected.
|
||||||
Label::new(path.to_string(), style.default.label.clone()),
|
Label::new(
|
||||||
|
path.to_string(),
|
||||||
|
style.inactive_state().default.label.clone(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(current_style.container)
|
.with_style(current_style.container)
|
||||||
|
|
|
@ -173,7 +173,7 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
cx: &gpui::AppContext,
|
cx: &gpui::AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,11 @@ impl BufferSearchBar {
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, is_active);
|
let style = theme
|
||||||
|
.search
|
||||||
|
.option_button
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -371,7 +375,7 @@ impl BufferSearchBar {
|
||||||
enum NavButton {}
|
enum NavButton {}
|
||||||
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, false);
|
let style = theme.search.option_button.inactive_state().style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -403,7 +407,7 @@ impl BufferSearchBar {
|
||||||
|
|
||||||
enum CloseButton {}
|
enum CloseButton {}
|
||||||
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
|
|
@ -896,7 +896,7 @@ impl ProjectSearchBar {
|
||||||
enum NavButton {}
|
enum NavButton {}
|
||||||
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, false);
|
let style = theme.search.option_button.inactive_state().style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -927,7 +927,11 @@ impl ProjectSearchBar {
|
||||||
let is_active = self.is_option_enabled(option, cx);
|
let is_active = self.is_option_enabled(option, cx);
|
||||||
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, is_active);
|
let style = theme
|
||||||
|
.search
|
||||||
|
.option_button
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -8,6 +8,7 @@ use gpui::{
|
||||||
fonts::{HighlightStyle, TextStyle},
|
fonts::{HighlightStyle, TextStyle},
|
||||||
platform, AppContext, AssetSource, Border, MouseState,
|
platform, AppContext, AssetSource, Border, MouseState,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
|
@ -36,7 +37,7 @@ pub fn init(source: impl AssetSource, cx: &mut AppContext) {
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub meta: ThemeMeta,
|
pub meta: ThemeMeta,
|
||||||
|
@ -67,7 +68,7 @@ pub struct Theme {
|
||||||
pub color_scheme: ColorScheme,
|
pub color_scheme: ColorScheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct ThemeMeta {
|
pub struct ThemeMeta {
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
|
@ -75,7 +76,7 @@ pub struct ThemeMeta {
|
||||||
pub is_light: bool,
|
pub is_light: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
pub background: Color,
|
pub background: Color,
|
||||||
pub blank_pane: BlankPaneStyle,
|
pub blank_pane: BlankPaneStyle,
|
||||||
|
@ -102,7 +103,7 @@ pub struct Workspace {
|
||||||
pub drop_target_overlay_color: Color,
|
pub drop_target_overlay_color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct BlankPaneStyle {
|
pub struct BlankPaneStyle {
|
||||||
pub logo: SvgStyle,
|
pub logo: SvgStyle,
|
||||||
pub logo_shadow: SvgStyle,
|
pub logo_shadow: SvgStyle,
|
||||||
|
@ -112,7 +113,7 @@ pub struct BlankPaneStyle {
|
||||||
pub keyboard_hint_width: f32,
|
pub keyboard_hint_width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Titlebar {
|
pub struct Titlebar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -128,16 +129,16 @@ pub struct Titlebar {
|
||||||
pub leader_avatar: AvatarStyle,
|
pub leader_avatar: AvatarStyle,
|
||||||
pub follower_avatar: AvatarStyle,
|
pub follower_avatar: AvatarStyle,
|
||||||
pub inactive_avatar_grayscale: bool,
|
pub inactive_avatar_grayscale: bool,
|
||||||
pub sign_in_prompt: Interactive<ContainedText>,
|
pub sign_in_prompt: Toggleable<Interactive<ContainedText>>,
|
||||||
pub outdated_warning: ContainedText,
|
pub outdated_warning: ContainedText,
|
||||||
pub share_button: Interactive<ContainedText>,
|
pub share_button: Toggleable<Interactive<ContainedText>>,
|
||||||
pub call_control: Interactive<IconButton>,
|
pub call_control: Interactive<IconButton>,
|
||||||
pub toggle_contacts_button: Interactive<IconButton>,
|
pub toggle_contacts_button: Toggleable<Interactive<IconButton>>,
|
||||||
pub user_menu_button: Interactive<IconButton>,
|
pub user_menu_button: Toggleable<Interactive<IconButton>>,
|
||||||
pub toggle_contacts_badge: ContainerStyle,
|
pub toggle_contacts_badge: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Deserialize, Default)]
|
#[derive(Copy, Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct AvatarStyle {
|
pub struct AvatarStyle {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub image: ImageStyle,
|
pub image: ImageStyle,
|
||||||
|
@ -145,14 +146,14 @@ pub struct AvatarStyle {
|
||||||
pub outer_corner_radius: f32,
|
pub outer_corner_radius: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct Copilot {
|
pub struct Copilot {
|
||||||
pub out_link_icon: Interactive<IconStyle>,
|
pub out_link_icon: Interactive<IconStyle>,
|
||||||
pub modal: ModalStyle,
|
pub modal: ModalStyle,
|
||||||
pub auth: CopilotAuth,
|
pub auth: CopilotAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct CopilotAuth {
|
pub struct CopilotAuth {
|
||||||
pub content_width: f32,
|
pub content_width: f32,
|
||||||
pub prompting: CopilotAuthPrompting,
|
pub prompting: CopilotAuthPrompting,
|
||||||
|
@ -162,14 +163,14 @@ pub struct CopilotAuth {
|
||||||
pub header: IconStyle,
|
pub header: IconStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct CopilotAuthPrompting {
|
pub struct CopilotAuthPrompting {
|
||||||
pub subheading: ContainedText,
|
pub subheading: ContainedText,
|
||||||
pub hint: ContainedText,
|
pub hint: ContainedText,
|
||||||
pub device_code: DeviceCode,
|
pub device_code: DeviceCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct DeviceCode {
|
pub struct DeviceCode {
|
||||||
pub text: TextStyle,
|
pub text: TextStyle,
|
||||||
pub cta: ButtonStyle,
|
pub cta: ButtonStyle,
|
||||||
|
@ -179,19 +180,19 @@ pub struct DeviceCode {
|
||||||
pub right_container: Interactive<ContainerStyle>,
|
pub right_container: Interactive<ContainerStyle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct CopilotAuthNotAuthorized {
|
pub struct CopilotAuthNotAuthorized {
|
||||||
pub subheading: ContainedText,
|
pub subheading: ContainedText,
|
||||||
pub warning: ContainedText,
|
pub warning: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, JsonSchema)]
|
||||||
pub struct CopilotAuthAuthorized {
|
pub struct CopilotAuthAuthorized {
|
||||||
pub subheading: ContainedText,
|
pub subheading: ContainedText,
|
||||||
pub hint: ContainedText,
|
pub hint: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContactsPopover {
|
pub struct ContactsPopover {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -199,17 +200,17 @@ pub struct ContactsPopover {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContactList {
|
pub struct ContactList {
|
||||||
pub user_query_editor: FieldEditor,
|
pub user_query_editor: FieldEditor,
|
||||||
pub user_query_editor_height: f32,
|
pub user_query_editor_height: f32,
|
||||||
pub add_contact_button: IconButton,
|
pub add_contact_button: IconButton,
|
||||||
pub header_row: Interactive<ContainedText>,
|
pub header_row: Toggleable<Interactive<ContainedText>>,
|
||||||
pub leave_call: Interactive<ContainedText>,
|
pub leave_call: Interactive<ContainedText>,
|
||||||
pub contact_row: Interactive<ContainerStyle>,
|
pub contact_row: Toggleable<Interactive<ContainerStyle>>,
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
pub project_row: Interactive<ProjectRow>,
|
pub project_row: Toggleable<Interactive<ProjectRow>>,
|
||||||
pub tree_branch: Interactive<TreeBranch>,
|
pub tree_branch: Toggleable<Interactive<TreeBranch>>,
|
||||||
pub contact_avatar: ImageStyle,
|
pub contact_avatar: ImageStyle,
|
||||||
pub contact_status_free: ContainerStyle,
|
pub contact_status_free: ContainerStyle,
|
||||||
pub contact_status_busy: ContainerStyle,
|
pub contact_status_busy: ContainerStyle,
|
||||||
|
@ -221,7 +222,7 @@ pub struct ContactList {
|
||||||
pub calling_indicator: ContainedText,
|
pub calling_indicator: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ProjectRow {
|
pub struct ProjectRow {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -229,13 +230,13 @@ pub struct ProjectRow {
|
||||||
pub name: ContainedText,
|
pub name: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone, Copy)]
|
#[derive(Deserialize, Default, Clone, Copy, JsonSchema)]
|
||||||
pub struct TreeBranch {
|
pub struct TreeBranch {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContactFinder {
|
pub struct ContactFinder {
|
||||||
pub picker: Picker,
|
pub picker: Picker,
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
|
@ -245,17 +246,17 @@ pub struct ContactFinder {
|
||||||
pub disabled_contact_button: IconButton,
|
pub disabled_contact_button: IconButton,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct DropdownMenu {
|
pub struct DropdownMenu {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub header: Interactive<DropdownMenuItem>,
|
pub header: Interactive<DropdownMenuItem>,
|
||||||
pub section_header: ContainedText,
|
pub section_header: ContainedText,
|
||||||
pub item: Interactive<DropdownMenuItem>,
|
pub item: Toggleable<Interactive<DropdownMenuItem>>,
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct DropdownMenuItem {
|
pub struct DropdownMenuItem {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -266,11 +267,11 @@ pub struct DropdownMenuItem {
|
||||||
pub secondary_text_spacing: f32,
|
pub secondary_text_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct TabBar {
|
pub struct TabBar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub pane_button: Interactive<IconButton>,
|
pub pane_button: Toggleable<Interactive<IconButton>>,
|
||||||
pub pane_button_container: ContainerStyle,
|
pub pane_button_container: ContainerStyle,
|
||||||
pub active_pane: TabStyles,
|
pub active_pane: TabStyles,
|
||||||
pub inactive_pane: TabStyles,
|
pub inactive_pane: TabStyles,
|
||||||
|
@ -294,13 +295,13 @@ impl TabBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct TabStyles {
|
pub struct TabStyles {
|
||||||
pub active_tab: Tab,
|
pub active_tab: Tab,
|
||||||
pub inactive_tab: Tab,
|
pub inactive_tab: Tab,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct AvatarRibbon {
|
pub struct AvatarRibbon {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -308,7 +309,7 @@ pub struct AvatarRibbon {
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct OfflineIcon {
|
pub struct OfflineIcon {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -316,7 +317,7 @@ pub struct OfflineIcon {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -333,7 +334,7 @@ pub struct Tab {
|
||||||
pub icon_conflict: Color,
|
pub icon_conflict: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Toolbar {
|
pub struct Toolbar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -342,14 +343,14 @@ pub struct Toolbar {
|
||||||
pub nav_button: Interactive<IconButton>,
|
pub nav_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Notifications {
|
pub struct Notifications {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Search {
|
pub struct Search {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -359,14 +360,14 @@ pub struct Search {
|
||||||
pub include_exclude_editor: FindEditor,
|
pub include_exclude_editor: FindEditor,
|
||||||
pub invalid_include_exclude_editor: ContainerStyle,
|
pub invalid_include_exclude_editor: ContainerStyle,
|
||||||
pub include_exclude_inputs: ContainedText,
|
pub include_exclude_inputs: ContainedText,
|
||||||
pub option_button: Interactive<ContainedText>,
|
pub option_button: Toggleable<Interactive<ContainedText>>,
|
||||||
pub match_background: Color,
|
pub match_background: Color,
|
||||||
pub match_index: ContainedText,
|
pub match_index: ContainedText,
|
||||||
pub results_status: TextStyle,
|
pub results_status: TextStyle,
|
||||||
pub dismiss_button: Interactive<IconButton>,
|
pub dismiss_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct FindEditor {
|
pub struct FindEditor {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub input: FieldEditor,
|
pub input: FieldEditor,
|
||||||
|
@ -374,7 +375,7 @@ pub struct FindEditor {
|
||||||
pub max_width: f32,
|
pub max_width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct StatusBar {
|
pub struct StatusBar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -390,15 +391,15 @@ pub struct StatusBar {
|
||||||
pub diagnostic_message: Interactive<ContainedText>,
|
pub diagnostic_message: Interactive<ContainedText>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct StatusBarPanelButtons {
|
pub struct StatusBarPanelButtons {
|
||||||
pub group_left: ContainerStyle,
|
pub group_left: ContainerStyle,
|
||||||
pub group_bottom: ContainerStyle,
|
pub group_bottom: ContainerStyle,
|
||||||
pub group_right: ContainerStyle,
|
pub group_right: ContainerStyle,
|
||||||
pub button: Interactive<PanelButton>,
|
pub button: Toggleable<Interactive<PanelButton>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct StatusBarDiagnosticSummary {
|
pub struct StatusBarDiagnosticSummary {
|
||||||
pub container_ok: ContainerStyle,
|
pub container_ok: ContainerStyle,
|
||||||
pub container_warning: ContainerStyle,
|
pub container_warning: ContainerStyle,
|
||||||
|
@ -413,7 +414,7 @@ pub struct StatusBarDiagnosticSummary {
|
||||||
pub summary_spacing: f32,
|
pub summary_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct StatusBarLspStatus {
|
pub struct StatusBarLspStatus {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -424,14 +425,14 @@ pub struct StatusBarLspStatus {
|
||||||
pub message: TextStyle,
|
pub message: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct Dock {
|
pub struct Dock {
|
||||||
pub left: ContainerStyle,
|
pub left: ContainerStyle,
|
||||||
pub bottom: ContainerStyle,
|
pub bottom: ContainerStyle,
|
||||||
pub right: ContainerStyle,
|
pub right: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct PanelButton {
|
pub struct PanelButton {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -440,20 +441,20 @@ pub struct PanelButton {
|
||||||
pub label: ContainedText,
|
pub label: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ProjectPanel {
|
pub struct ProjectPanel {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub entry: Interactive<ProjectPanelEntry>,
|
pub entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub dragged_entry: ProjectPanelEntry,
|
pub dragged_entry: ProjectPanelEntry,
|
||||||
pub ignored_entry: Interactive<ProjectPanelEntry>,
|
pub ignored_entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub cut_entry: Interactive<ProjectPanelEntry>,
|
pub cut_entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub filename_editor: FieldEditor,
|
pub filename_editor: FieldEditor,
|
||||||
pub indent_width: f32,
|
pub indent_width: f32,
|
||||||
pub open_project_button: Interactive<ContainedText>,
|
pub open_project_button: Interactive<ContainedText>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ProjectPanelEntry {
|
pub struct ProjectPanelEntry {
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -465,28 +466,28 @@ pub struct ProjectPanelEntry {
|
||||||
pub status: EntryStatus,
|
pub status: EntryStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct EntryStatus {
|
pub struct EntryStatus {
|
||||||
pub git: GitProjectStatus,
|
pub git: GitProjectStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct GitProjectStatus {
|
pub struct GitProjectStatus {
|
||||||
pub modified: Color,
|
pub modified: Color,
|
||||||
pub inserted: Color,
|
pub inserted: Color,
|
||||||
pub conflict: Color,
|
pub conflict: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContextMenu {
|
pub struct ContextMenu {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub item: Interactive<ContextMenuItem>,
|
pub item: Toggleable<Interactive<ContextMenuItem>>,
|
||||||
pub keystroke_margin: f32,
|
pub keystroke_margin: f32,
|
||||||
pub separator: ContainerStyle,
|
pub separator: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContextMenuItem {
|
pub struct ContextMenuItem {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -496,13 +497,13 @@ pub struct ContextMenuItem {
|
||||||
pub icon_spacing: f32,
|
pub icon_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Default)]
|
#[derive(Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct CommandPalette {
|
pub struct CommandPalette {
|
||||||
pub key: Interactive<ContainedLabel>,
|
pub key: Toggleable<ContainedLabel>,
|
||||||
pub keystroke_spacing: f32,
|
pub keystroke_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct InviteLink {
|
pub struct InviteLink {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -511,7 +512,7 @@ pub struct InviteLink {
|
||||||
pub icon: Icon,
|
pub icon: Icon,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Copy, Default)]
|
#[derive(Deserialize, Clone, Copy, Default, JsonSchema)]
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -519,7 +520,7 @@ pub struct Icon {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Copy, Default)]
|
#[derive(Deserialize, Clone, Copy, Default, JsonSchema)]
|
||||||
pub struct IconButton {
|
pub struct IconButton {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -528,7 +529,7 @@ pub struct IconButton {
|
||||||
pub button_width: f32,
|
pub button_width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ChatMessage {
|
pub struct ChatMessage {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -537,7 +538,7 @@ pub struct ChatMessage {
|
||||||
pub timestamp: ContainedText,
|
pub timestamp: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ChannelSelect {
|
pub struct ChannelSelect {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -549,7 +550,7 @@ pub struct ChannelSelect {
|
||||||
pub menu: ContainerStyle,
|
pub menu: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ChannelName {
|
pub struct ChannelName {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -557,7 +558,7 @@ pub struct ChannelName {
|
||||||
pub name: TextStyle,
|
pub name: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Picker {
|
pub struct Picker {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -565,10 +566,10 @@ pub struct Picker {
|
||||||
pub input_editor: FieldEditor,
|
pub input_editor: FieldEditor,
|
||||||
pub empty_input_editor: FieldEditor,
|
pub empty_input_editor: FieldEditor,
|
||||||
pub no_matches: ContainedLabel,
|
pub no_matches: ContainedLabel,
|
||||||
pub item: Interactive<ContainedLabel>,
|
pub item: Toggleable<Interactive<ContainedLabel>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContainedText {
|
pub struct ContainedText {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -576,7 +577,7 @@ pub struct ContainedText {
|
||||||
pub text: TextStyle,
|
pub text: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContainedLabel {
|
pub struct ContainedLabel {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -584,7 +585,7 @@ pub struct ContainedLabel {
|
||||||
pub label: LabelStyle,
|
pub label: LabelStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ProjectDiagnostics {
|
pub struct ProjectDiagnostics {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -594,7 +595,7 @@ pub struct ProjectDiagnostics {
|
||||||
pub tab_summary_spacing: f32,
|
pub tab_summary_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContactNotification {
|
pub struct ContactNotification {
|
||||||
pub header_avatar: ImageStyle,
|
pub header_avatar: ImageStyle,
|
||||||
pub header_message: ContainedText,
|
pub header_message: ContainedText,
|
||||||
|
@ -604,21 +605,21 @@ pub struct ContactNotification {
|
||||||
pub dismiss_button: Interactive<IconButton>,
|
pub dismiss_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct UpdateNotification {
|
pub struct UpdateNotification {
|
||||||
pub message: ContainedText,
|
pub message: ContainedText,
|
||||||
pub action_message: Interactive<ContainedText>,
|
pub action_message: Interactive<ContainedText>,
|
||||||
pub dismiss_button: Interactive<IconButton>,
|
pub dismiss_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct MessageNotification {
|
pub struct MessageNotification {
|
||||||
pub message: ContainedText,
|
pub message: ContainedText,
|
||||||
pub action_message: Interactive<ContainedText>,
|
pub action_message: Interactive<ContainedText>,
|
||||||
pub dismiss_button: Interactive<IconButton>,
|
pub dismiss_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ProjectSharedNotification {
|
pub struct ProjectSharedNotification {
|
||||||
pub window_height: f32,
|
pub window_height: f32,
|
||||||
pub window_width: f32,
|
pub window_width: f32,
|
||||||
|
@ -635,7 +636,7 @@ pub struct ProjectSharedNotification {
|
||||||
pub dismiss_button: ContainedText,
|
pub dismiss_button: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct IncomingCallNotification {
|
pub struct IncomingCallNotification {
|
||||||
pub window_height: f32,
|
pub window_height: f32,
|
||||||
pub window_width: f32,
|
pub window_width: f32,
|
||||||
|
@ -652,7 +653,7 @@ pub struct IncomingCallNotification {
|
||||||
pub decline_button: ContainedText,
|
pub decline_button: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Editor {
|
pub struct Editor {
|
||||||
pub text_color: Color,
|
pub text_color: Color,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -693,7 +694,7 @@ pub struct Editor {
|
||||||
pub whitespace: Color,
|
pub whitespace: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Scrollbar {
|
pub struct Scrollbar {
|
||||||
pub track: ContainerStyle,
|
pub track: ContainerStyle,
|
||||||
pub thumb: ContainerStyle,
|
pub thumb: ContainerStyle,
|
||||||
|
@ -702,14 +703,14 @@ pub struct Scrollbar {
|
||||||
pub git: GitDiffColors,
|
pub git: GitDiffColors,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct GitDiffColors {
|
pub struct GitDiffColors {
|
||||||
pub inserted: Color,
|
pub inserted: Color,
|
||||||
pub modified: Color,
|
pub modified: Color,
|
||||||
pub deleted: Color,
|
pub deleted: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct DiagnosticPathHeader {
|
pub struct DiagnosticPathHeader {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -718,7 +719,7 @@ pub struct DiagnosticPathHeader {
|
||||||
pub text_scale_factor: f32,
|
pub text_scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct DiagnosticHeader {
|
pub struct DiagnosticHeader {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -729,7 +730,7 @@ pub struct DiagnosticHeader {
|
||||||
pub icon_width_factor: f32,
|
pub icon_width_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct DiagnosticStyle {
|
pub struct DiagnosticStyle {
|
||||||
pub message: LabelStyle,
|
pub message: LabelStyle,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -737,7 +738,7 @@ pub struct DiagnosticStyle {
|
||||||
pub text_scale_factor: f32,
|
pub text_scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct AutocompleteStyle {
|
pub struct AutocompleteStyle {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -747,13 +748,13 @@ pub struct AutocompleteStyle {
|
||||||
pub match_highlight: HighlightStyle,
|
pub match_highlight: HighlightStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Deserialize)]
|
#[derive(Clone, Copy, Default, Deserialize, JsonSchema)]
|
||||||
pub struct SelectionStyle {
|
pub struct SelectionStyle {
|
||||||
pub cursor: Color,
|
pub cursor: Color,
|
||||||
pub selection: Color,
|
pub selection: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct FieldEditor {
|
pub struct FieldEditor {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -763,21 +764,21 @@ pub struct FieldEditor {
|
||||||
pub selection: SelectionStyle,
|
pub selection: SelectionStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct InteractiveColor {
|
pub struct InteractiveColor {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct CodeActions {
|
pub struct CodeActions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub indicator: Interactive<InteractiveColor>,
|
pub indicator: Toggleable<Interactive<InteractiveColor>>,
|
||||||
pub vertical_scale: f32,
|
pub vertical_scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Folds {
|
pub struct Folds {
|
||||||
pub indicator: Interactive<InteractiveColor>,
|
pub indicator: Toggleable<Interactive<InteractiveColor>>,
|
||||||
pub ellipses: FoldEllipses,
|
pub ellipses: FoldEllipses,
|
||||||
pub fold_background: Color,
|
pub fold_background: Color,
|
||||||
pub icon_margin_scale: f32,
|
pub icon_margin_scale: f32,
|
||||||
|
@ -785,14 +786,14 @@ pub struct Folds {
|
||||||
pub foldable_icon: String,
|
pub foldable_icon: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct FoldEllipses {
|
pub struct FoldEllipses {
|
||||||
pub text_color: Color,
|
pub text_color: Color,
|
||||||
pub background: Interactive<InteractiveColor>,
|
pub background: Interactive<InteractiveColor>,
|
||||||
pub corner_radius_factor: f32,
|
pub corner_radius_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct DiffStyle {
|
pub struct DiffStyle {
|
||||||
pub inserted: Color,
|
pub inserted: Color,
|
||||||
pub modified: Color,
|
pub modified: Color,
|
||||||
|
@ -802,41 +803,49 @@ pub struct DiffStyle {
|
||||||
pub corner_radius: f32,
|
pub corner_radius: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy, JsonSchema)]
|
||||||
pub struct Interactive<T> {
|
pub struct Interactive<T> {
|
||||||
pub default: T,
|
pub default: T,
|
||||||
pub hover: Option<T>,
|
pub hovered: Option<T>,
|
||||||
pub hover_and_active: Option<T>,
|
|
||||||
pub clicked: Option<T>,
|
pub clicked: Option<T>,
|
||||||
pub click_and_active: Option<T>,
|
|
||||||
pub active: Option<T>,
|
|
||||||
pub disabled: Option<T>,
|
pub disabled: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Interactive<T> {
|
#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)]
|
||||||
pub fn style_for(&self, state: &mut MouseState, active: bool) -> &T {
|
pub struct Toggleable<T> {
|
||||||
|
active: T,
|
||||||
|
inactive: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Toggleable<T> {
|
||||||
|
pub fn new(active: T, inactive: T) -> Self {
|
||||||
|
Self { active, inactive }
|
||||||
|
}
|
||||||
|
pub fn in_state(&self, active: bool) -> &T {
|
||||||
if active {
|
if active {
|
||||||
if state.hovered() {
|
&self.active
|
||||||
self.hover_and_active
|
} else {
|
||||||
.as_ref()
|
&self.inactive
|
||||||
.unwrap_or(self.active.as_ref().unwrap_or(&self.default))
|
}
|
||||||
} else if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some()
|
}
|
||||||
{
|
pub fn active_state(&self) -> &T {
|
||||||
self.click_and_active
|
self.in_state(true)
|
||||||
.as_ref()
|
}
|
||||||
.unwrap_or(self.active.as_ref().unwrap_or(&self.default))
|
pub fn inactive_state(&self) -> &T {
|
||||||
} else {
|
self.in_state(false)
|
||||||
self.active.as_ref().unwrap_or(&self.default)
|
}
|
||||||
}
|
}
|
||||||
} else if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some() {
|
|
||||||
|
impl<T> Interactive<T> {
|
||||||
|
pub fn style_for(&self, state: &mut MouseState) -> &T {
|
||||||
|
if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some() {
|
||||||
self.clicked.as_ref().unwrap()
|
self.clicked.as_ref().unwrap()
|
||||||
} else if state.hovered() {
|
} else if state.hovered() {
|
||||||
self.hover.as_ref().unwrap_or(&self.default)
|
self.hovered.as_ref().unwrap_or(&self.default)
|
||||||
} else {
|
} else {
|
||||||
&self.default
|
&self.default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disabled_style(&self) -> &T {
|
pub fn disabled_style(&self) -> &T {
|
||||||
self.disabled.as_ref().unwrap_or(&self.default)
|
self.disabled.as_ref().unwrap_or(&self.default)
|
||||||
}
|
}
|
||||||
|
@ -849,13 +858,9 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
|
||||||
{
|
{
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Helper {
|
struct Helper {
|
||||||
#[serde(flatten)]
|
|
||||||
default: Value,
|
default: Value,
|
||||||
hover: Option<Value>,
|
hovered: Option<Value>,
|
||||||
hover_and_active: Option<Value>,
|
|
||||||
clicked: Option<Value>,
|
clicked: Option<Value>,
|
||||||
click_and_active: Option<Value>,
|
|
||||||
active: Option<Value>,
|
|
||||||
disabled: Option<Value>,
|
disabled: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,21 +885,15 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let hover = deserialize_state(json.hover)?;
|
let hovered = deserialize_state(json.hovered)?;
|
||||||
let hover_and_active = deserialize_state(json.hover_and_active)?;
|
|
||||||
let clicked = deserialize_state(json.clicked)?;
|
let clicked = deserialize_state(json.clicked)?;
|
||||||
let click_and_active = deserialize_state(json.click_and_active)?;
|
|
||||||
let active = deserialize_state(json.active)?;
|
|
||||||
let disabled = deserialize_state(json.disabled)?;
|
let disabled = deserialize_state(json.disabled)?;
|
||||||
let default = serde_json::from_value(json.default).map_err(serde::de::Error::custom)?;
|
let default = serde_json::from_value(json.default).map_err(serde::de::Error::custom)?;
|
||||||
|
|
||||||
Ok(Interactive {
|
Ok(Interactive {
|
||||||
default,
|
default,
|
||||||
hover,
|
hovered,
|
||||||
hover_and_active,
|
|
||||||
clicked,
|
clicked,
|
||||||
click_and_active,
|
|
||||||
active,
|
|
||||||
disabled,
|
disabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -911,7 +910,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, JsonSchema)]
|
||||||
pub struct SyntaxTheme {
|
pub struct SyntaxTheme {
|
||||||
pub highlights: Vec<(String, HighlightStyle)>,
|
pub highlights: Vec<(String, HighlightStyle)>,
|
||||||
}
|
}
|
||||||
|
@ -945,7 +944,7 @@ impl<'de> Deserialize<'de> for SyntaxTheme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct HoverPopover {
|
pub struct HoverPopover {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub info_container: ContainerStyle,
|
pub info_container: ContainerStyle,
|
||||||
|
@ -957,7 +956,7 @@ pub struct HoverPopover {
|
||||||
pub highlight: Color,
|
pub highlight: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct TerminalStyle {
|
pub struct TerminalStyle {
|
||||||
pub black: Color,
|
pub black: Color,
|
||||||
pub red: Color,
|
pub red: Color,
|
||||||
|
@ -991,7 +990,7 @@ pub struct TerminalStyle {
|
||||||
pub dim_foreground: Color,
|
pub dim_foreground: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct AssistantStyle {
|
pub struct AssistantStyle {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub hamburger_button: IconStyle,
|
pub hamburger_button: IconStyle,
|
||||||
|
@ -1014,15 +1013,14 @@ pub struct AssistantStyle {
|
||||||
pub saved_conversation: SavedConversation,
|
pub saved_conversation: SavedConversation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct SavedConversation {
|
pub struct SavedConversation {
|
||||||
#[serde(flatten)]
|
|
||||||
pub container: Interactive<ContainerStyle>,
|
pub container: Interactive<ContainerStyle>,
|
||||||
pub saved_at: ContainedText,
|
pub saved_at: ContainedText,
|
||||||
pub title: ContainedText,
|
pub title: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct FeedbackStyle {
|
pub struct FeedbackStyle {
|
||||||
pub submit_button: Interactive<ContainedText>,
|
pub submit_button: Interactive<ContainedText>,
|
||||||
pub button_margin: f32,
|
pub button_margin: f32,
|
||||||
|
@ -1031,7 +1029,7 @@ pub struct FeedbackStyle {
|
||||||
pub link_text_hover: ContainedText,
|
pub link_text_hover: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct WelcomeStyle {
|
pub struct WelcomeStyle {
|
||||||
pub page_width: f32,
|
pub page_width: f32,
|
||||||
pub logo: SvgStyle,
|
pub logo: SvgStyle,
|
||||||
|
@ -1045,7 +1043,7 @@ pub struct WelcomeStyle {
|
||||||
pub checkbox_group: ContainerStyle,
|
pub checkbox_group: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ColorScheme {
|
pub struct ColorScheme {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub is_light: bool,
|
pub is_light: bool,
|
||||||
|
@ -1060,13 +1058,13 @@ pub struct ColorScheme {
|
||||||
pub players: Vec<Player>,
|
pub players: Vec<Player>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
pub cursor: Color,
|
pub cursor: Color,
|
||||||
pub selection: Color,
|
pub selection: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct RampSet {
|
pub struct RampSet {
|
||||||
pub neutral: Vec<Color>,
|
pub neutral: Vec<Color>,
|
||||||
pub red: Vec<Color>,
|
pub red: Vec<Color>,
|
||||||
|
@ -1079,7 +1077,7 @@ pub struct RampSet {
|
||||||
pub magenta: Vec<Color>,
|
pub magenta: Vec<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Layer {
|
pub struct Layer {
|
||||||
pub base: StyleSet,
|
pub base: StyleSet,
|
||||||
pub variant: StyleSet,
|
pub variant: StyleSet,
|
||||||
|
@ -1090,7 +1088,7 @@ pub struct Layer {
|
||||||
pub negative: StyleSet,
|
pub negative: StyleSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct StyleSet {
|
pub struct StyleSet {
|
||||||
pub default: Style,
|
pub default: Style,
|
||||||
pub active: Style,
|
pub active: Style,
|
||||||
|
@ -1100,7 +1098,7 @@ pub struct StyleSet {
|
||||||
pub inverted: Style,
|
pub inverted: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct Style {
|
pub struct Style {
|
||||||
pub background: Color,
|
pub background: Color,
|
||||||
pub border: Color,
|
pub border: Color,
|
||||||
|
|
|
@ -14,12 +14,13 @@ use util::ResultExt as _;
|
||||||
|
|
||||||
const MIN_FONT_SIZE: f32 = 6.0;
|
const MIN_FONT_SIZE: f32 = 6.0;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, JsonSchema)]
|
||||||
pub struct ThemeSettings {
|
pub struct ThemeSettings {
|
||||||
pub buffer_font_family_name: String,
|
pub buffer_font_family_name: String,
|
||||||
pub buffer_font_features: fonts::Features,
|
pub buffer_font_features: fonts::Features,
|
||||||
pub buffer_font_family: FamilyId,
|
pub buffer_font_family: FamilyId,
|
||||||
pub(crate) buffer_font_size: f32,
|
pub(crate) buffer_font_size: f32,
|
||||||
|
#[serde(skip)]
|
||||||
pub theme: Arc<Theme>,
|
pub theme: Arc<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,12 @@ use gpui::{
|
||||||
scene::MouseClick,
|
scene::MouseClick,
|
||||||
Action, Element, EventContext, MouseState, View, ViewContext,
|
Action, Element, EventContext, MouseState, View, ViewContext,
|
||||||
};
|
};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{ContainedText, Interactive};
|
use crate::{ContainedText, Interactive};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct CheckboxStyle {
|
pub struct CheckboxStyle {
|
||||||
pub icon: SvgStyle,
|
pub icon: SvgStyle,
|
||||||
pub label: ContainedText,
|
pub label: ContainedText,
|
||||||
|
@ -100,7 +101,7 @@ pub fn svg<V: View>(style: &SvgStyle) -> ConstrainedBox<V> {
|
||||||
.with_height(style.dimensions.height)
|
.with_height(style.dimensions.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct IconStyle {
|
pub struct IconStyle {
|
||||||
pub icon: SvgStyle,
|
pub icon: SvgStyle,
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
@ -150,7 +151,7 @@ where
|
||||||
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
||||||
{
|
{
|
||||||
MouseEventHandler::<Tag, V>::new(0, cx, |state, _| {
|
MouseEventHandler::<Tag, V>::new(0, cx, |state, _| {
|
||||||
let style = style.style_for(state, false);
|
let style = style.style_for(state);
|
||||||
Label::new(label, style.text.to_owned())
|
Label::new(label, style.text.to_owned())
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
|
@ -162,7 +163,7 @@ where
|
||||||
.with_cursor_style(platform::CursorStyle::PointingHand)
|
.with_cursor_style(platform::CursorStyle::PointingHand)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct ModalStyle {
|
pub struct ModalStyle {
|
||||||
close_icon: Interactive<IconStyle>,
|
close_icon: Interactive<IconStyle>,
|
||||||
container: ContainerStyle,
|
container: ContainerStyle,
|
||||||
|
@ -200,13 +201,13 @@ where
|
||||||
title,
|
title,
|
||||||
style
|
style
|
||||||
.title_text
|
.title_text
|
||||||
.style_for(&mut MouseState::default(), false)
|
.style_for(&mut MouseState::default())
|
||||||
.clone(),
|
.clone(),
|
||||||
))
|
))
|
||||||
.with_child(
|
.with_child(
|
||||||
// FIXME: Get a better tag type
|
// FIXME: Get a better tag type
|
||||||
MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| {
|
MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| {
|
||||||
let style = style.close_icon.style_for(state, false);
|
let style = style.close_icon.style_for(state);
|
||||||
icon(style)
|
icon(style)
|
||||||
})
|
})
|
||||||
.on_click(platform::MouseButton::Left, move |_, _, cx| {
|
.on_click(platform::MouseButton::Left, move |_, _, cx| {
|
||||||
|
|
|
@ -208,7 +208,7 @@ impl PickerDelegate for ThemeSelectorDelegate {
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let theme_match = &self.matches[ix];
|
let theme_match = &self.matches[ix];
|
||||||
Label::new(theme_match.string.clone(), style.label.clone())
|
Label::new(theme_match.string.clone(), style.label.clone())
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "theme_testbench"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
publish = false
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/theme_testbench.rs"
|
|
||||||
doctest = false
|
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
gpui = { path = "../gpui" }
|
|
||||||
theme = { path = "../theme" }
|
|
||||||
settings = { path = "../settings" }
|
|
||||||
workspace = { path = "../workspace" }
|
|
||||||
project = { path = "../project" }
|
|
||||||
|
|
||||||
smallvec.workspace = true
|
|
|
@ -1,300 +0,0 @@
|
||||||
use gpui::{
|
|
||||||
actions,
|
|
||||||
color::Color,
|
|
||||||
elements::{
|
|
||||||
AnyElement, Canvas, Container, ContainerStyle, Flex, Label, Margin, MouseEventHandler,
|
|
||||||
Padding, ParentElement,
|
|
||||||
},
|
|
||||||
fonts::TextStyle,
|
|
||||||
AppContext, Border, Element, Entity, ModelHandle, Quad, Task, View, ViewContext, ViewHandle,
|
|
||||||
WeakViewHandle,
|
|
||||||
};
|
|
||||||
use project::Project;
|
|
||||||
use theme::{ColorScheme, Layer, Style, StyleSet, ThemeSettings};
|
|
||||||
use workspace::{item::Item, register_deserializable_item, Pane, Workspace};
|
|
||||||
|
|
||||||
actions!(theme, [DeployThemeTestbench]);
|
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
|
||||||
cx.add_action(ThemeTestbench::deploy);
|
|
||||||
|
|
||||||
register_deserializable_item::<ThemeTestbench>(cx)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ThemeTestbench {}
|
|
||||||
|
|
||||||
impl ThemeTestbench {
|
|
||||||
pub fn deploy(
|
|
||||||
workspace: &mut Workspace,
|
|
||||||
_: &DeployThemeTestbench,
|
|
||||||
cx: &mut ViewContext<Workspace>,
|
|
||||||
) {
|
|
||||||
let view = cx.add_view(|_| ThemeTestbench {});
|
|
||||||
workspace.add_item(Box::new(view), cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_ramps(color_scheme: &ColorScheme) -> Flex<Self> {
|
|
||||||
fn display_ramp(ramp: &Vec<Color>) -> AnyElement<ThemeTestbench> {
|
|
||||||
Flex::row()
|
|
||||||
.with_children(ramp.iter().cloned().map(|color| {
|
|
||||||
Canvas::new(move |scene, bounds, _, _, _| {
|
|
||||||
scene.push_quad(Quad {
|
|
||||||
bounds,
|
|
||||||
background: Some(color),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.flex(1.0, false)
|
|
||||||
}))
|
|
||||||
.flex(1.0, false)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
Flex::column()
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.neutral))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.red))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.orange))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.yellow))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.green))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.cyan))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.blue))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.violet))
|
|
||||||
.with_child(display_ramp(&color_scheme.ramps.magenta))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_layer(
|
|
||||||
layer_index: usize,
|
|
||||||
layer: &Layer,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> Container<Self> {
|
|
||||||
Flex::column()
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(0, layer_index, "base", &layer.base, cx).flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(1, layer_index, "variant", &layer.variant, cx)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(2, layer_index, "on", &layer.on, cx).flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(3, layer_index, "accent", &layer.accent, cx)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(4, layer_index, "positive", &layer.positive, cx)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(5, layer_index, "warning", &layer.warning, cx)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Self::render_button_set(6, layer_index, "negative", &layer.negative, cx)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.contained()
|
|
||||||
.with_style(ContainerStyle {
|
|
||||||
margin: Margin {
|
|
||||||
top: 10.,
|
|
||||||
bottom: 10.,
|
|
||||||
left: 10.,
|
|
||||||
right: 10.,
|
|
||||||
},
|
|
||||||
background_color: Some(layer.base.default.background),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_button_set(
|
|
||||||
set_index: usize,
|
|
||||||
layer_index: usize,
|
|
||||||
set_name: &'static str,
|
|
||||||
style_set: &StyleSet,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> Flex<Self> {
|
|
||||||
Flex::row()
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6,
|
|
||||||
layer_index,
|
|
||||||
set_name,
|
|
||||||
&style_set,
|
|
||||||
None,
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6 + 1,
|
|
||||||
layer_index,
|
|
||||||
"hovered",
|
|
||||||
&style_set,
|
|
||||||
Some(|style_set| &style_set.hovered),
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6 + 2,
|
|
||||||
layer_index,
|
|
||||||
"pressed",
|
|
||||||
&style_set,
|
|
||||||
Some(|style_set| &style_set.pressed),
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6 + 3,
|
|
||||||
layer_index,
|
|
||||||
"active",
|
|
||||||
&style_set,
|
|
||||||
Some(|style_set| &style_set.active),
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6 + 4,
|
|
||||||
layer_index,
|
|
||||||
"disabled",
|
|
||||||
&style_set,
|
|
||||||
Some(|style_set| &style_set.disabled),
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_child(Self::render_button(
|
|
||||||
set_index * 6 + 5,
|
|
||||||
layer_index,
|
|
||||||
"inverted",
|
|
||||||
&style_set,
|
|
||||||
Some(|style_set| &style_set.inverted),
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_button(
|
|
||||||
button_index: usize,
|
|
||||||
layer_index: usize,
|
|
||||||
text: &'static str,
|
|
||||||
style_set: &StyleSet,
|
|
||||||
style_override: Option<fn(&StyleSet) -> &Style>,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> AnyElement<Self> {
|
|
||||||
enum TestBenchButton {}
|
|
||||||
MouseEventHandler::<TestBenchButton, _>::new(layer_index + button_index, cx, |state, cx| {
|
|
||||||
let style = if let Some(style_override) = style_override {
|
|
||||||
style_override(&style_set)
|
|
||||||
} else if state.clicked().is_some() {
|
|
||||||
&style_set.pressed
|
|
||||||
} else if state.hovered() {
|
|
||||||
&style_set.hovered
|
|
||||||
} else {
|
|
||||||
&style_set.default
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::render_label(text.to_string(), style, cx)
|
|
||||||
.contained()
|
|
||||||
.with_style(ContainerStyle {
|
|
||||||
margin: Margin {
|
|
||||||
top: 4.,
|
|
||||||
bottom: 4.,
|
|
||||||
left: 4.,
|
|
||||||
right: 4.,
|
|
||||||
},
|
|
||||||
padding: Padding {
|
|
||||||
top: 4.,
|
|
||||||
bottom: 4.,
|
|
||||||
left: 4.,
|
|
||||||
right: 4.,
|
|
||||||
},
|
|
||||||
background_color: Some(style.background),
|
|
||||||
border: Border {
|
|
||||||
width: 1.,
|
|
||||||
color: style.border,
|
|
||||||
overlay: false,
|
|
||||||
top: true,
|
|
||||||
bottom: true,
|
|
||||||
left: true,
|
|
||||||
right: true,
|
|
||||||
},
|
|
||||||
corner_radius: 2.,
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.flex(1., true)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_label(text: String, style: &Style, cx: &mut ViewContext<Self>) -> Label {
|
|
||||||
let settings = settings::get::<ThemeSettings>(cx);
|
|
||||||
let font_cache = cx.font_cache();
|
|
||||||
let family_id = settings.buffer_font_family;
|
|
||||||
let font_size = settings.buffer_font_size(cx);
|
|
||||||
let font_id = font_cache
|
|
||||||
.select_font(family_id, &Default::default())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let text_style = TextStyle {
|
|
||||||
color: style.foreground,
|
|
||||||
font_family_id: family_id,
|
|
||||||
font_family_name: font_cache.family_name(family_id).unwrap(),
|
|
||||||
font_id,
|
|
||||||
font_size,
|
|
||||||
font_properties: Default::default(),
|
|
||||||
underline: Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Label::new(text, text_style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entity for ThemeTestbench {
|
|
||||||
type Event = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl View for ThemeTestbench {
|
|
||||||
fn ui_name() -> &'static str {
|
|
||||||
"ThemeTestbench"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> AnyElement<Self> {
|
|
||||||
let color_scheme = &theme::current(cx).clone().color_scheme;
|
|
||||||
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Self::render_ramps(color_scheme)
|
|
||||||
.contained()
|
|
||||||
.with_margin_right(10.)
|
|
||||||
.flex(0.1, false),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Flex::column()
|
|
||||||
.with_child(Self::render_layer(100, &color_scheme.lowest, cx).flex(1., true))
|
|
||||||
.with_child(Self::render_layer(200, &color_scheme.middle, cx).flex(1., true))
|
|
||||||
.with_child(Self::render_layer(300, &color_scheme.highest, cx).flex(1., true))
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Item for ThemeTestbench {
|
|
||||||
fn tab_content<T: View>(
|
|
||||||
&self,
|
|
||||||
_: Option<usize>,
|
|
||||||
style: &theme::Tab,
|
|
||||||
_: &AppContext,
|
|
||||||
) -> AnyElement<T> {
|
|
||||||
Label::new("Theme Testbench", style.label.clone())
|
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialized_item_kind() -> Option<&'static str> {
|
|
||||||
Some("ThemeTestBench")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize(
|
|
||||||
_project: ModelHandle<Project>,
|
|
||||||
_workspace: WeakViewHandle<Workspace>,
|
|
||||||
_workspace_id: workspace::WorkspaceId,
|
|
||||||
_item_id: workspace::ItemId,
|
|
||||||
cx: &mut ViewContext<Pane>,
|
|
||||||
) -> Task<gpui::anyhow::Result<ViewHandle<Self>>> {
|
|
||||||
Task::ready(Ok(cx.add_view(|_| Self {})))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -98,3 +98,14 @@ async fn test_buffer_search(cx: &mut gpui::TestAppContext) {
|
||||||
assert_eq!(bar.query_editor.read(cx).text(cx), "jumps");
|
assert_eq!(bar.query_editor.read(cx).text(cx), "jumps");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_count_down(cx: &mut gpui::TestAppContext) {
|
||||||
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
|
|
||||||
|
cx.set_state(indoc! {"aˇa\nbb\ncc\ndd\nee"}, Mode::Normal);
|
||||||
|
cx.simulate_keystrokes(["2", "down"]);
|
||||||
|
cx.assert_editor_state("aa\nbb\ncˇc\ndd\nee");
|
||||||
|
cx.simulate_keystrokes(["9", "down"]);
|
||||||
|
cx.assert_editor_state("aa\nbb\ncc\ndd\neˇe");
|
||||||
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
|
||||||
) -> gpui::AnyElement<Picker<Self>> {
|
) -> gpui::AnyElement<Picker<Self>> {
|
||||||
let theme = &theme::current(cx);
|
let theme = &theme::current(cx);
|
||||||
let keymap_match = &self.matches[ix];
|
let keymap_match = &self.matches[ix];
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
Label::new(keymap_match.string.clone(), style.label.clone())
|
Label::new(keymap_match.string.clone(), style.label.clone())
|
||||||
.with_highlights(keymap_match.positions.clone())
|
.with_highlights(keymap_match.positions.clone())
|
||||||
|
|
|
@ -498,7 +498,9 @@ impl View for PanelButtons {
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Self, _>::new(panel_ix, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(panel_ix, cx, |state, cx| {
|
||||||
let style = button_style.style_for(state, is_active);
|
let style = button_style.in_state(is_active);
|
||||||
|
|
||||||
|
let style = style.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Svg::new(view.icon_path(cx))
|
Svg::new(view.icon_path(cx))
|
||||||
|
|
|
@ -291,7 +291,7 @@ pub mod simple_message_notification {
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -323,7 +323,7 @@ pub mod simple_message_notification {
|
||||||
0,
|
0,
|
||||||
cx,
|
cx,
|
||||||
|state, _| {
|
|state, _| {
|
||||||
let style = theme.action_message.style_for(state, false);
|
let style = theme.action_message.style_for(state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
|
|
@ -1410,7 +1410,7 @@ impl Pane {
|
||||||
pub fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
|
pub fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
|
||||||
index: usize,
|
index: usize,
|
||||||
icon: &'static str,
|
icon: &'static str,
|
||||||
active: bool,
|
is_active: bool,
|
||||||
tooltip: Option<(String, Option<Box<dyn Action>>)>,
|
tooltip: Option<(String, Option<Box<dyn Action>>)>,
|
||||||
cx: &mut ViewContext<Pane>,
|
cx: &mut ViewContext<Pane>,
|
||||||
on_click: F,
|
on_click: F,
|
||||||
|
@ -1420,7 +1420,7 @@ impl Pane {
|
||||||
|
|
||||||
let mut button = MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
|
let mut button = MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
|
||||||
let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar;
|
let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar;
|
||||||
let style = theme.pane_button.style_for(mouse_state, active);
|
let style = theme.pane_button.in_state(is_active).style_for(mouse_state);
|
||||||
Svg::new(icon)
|
Svg::new(icon)
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
|
|
@ -231,7 +231,7 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
|
||||||
) -> AnyElement<Toolbar> {
|
) -> AnyElement<Toolbar> {
|
||||||
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
||||||
let style = if enabled {
|
let style = if enabled {
|
||||||
style.style_for(state, false)
|
style.style_for(state)
|
||||||
} else {
|
} else {
|
||||||
style.disabled_style()
|
style.disabled_style()
|
||||||
};
|
};
|
||||||
|
|
|
@ -140,9 +140,11 @@ pub struct OpenPaths {
|
||||||
#[derive(Clone, Deserialize, PartialEq)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct ActivatePane(pub usize);
|
pub struct ActivatePane(pub usize);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
pub struct Toast {
|
pub struct Toast {
|
||||||
id: usize,
|
id: usize,
|
||||||
msg: Cow<'static, str>,
|
msg: Cow<'static, str>,
|
||||||
|
#[serde(skip)]
|
||||||
on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
|
on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,9 +185,9 @@ impl Clone for Toast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WorkspaceId = i64;
|
impl_actions!(workspace, [ActivatePane, Toast]);
|
||||||
|
|
||||||
impl_actions!(workspace, [ActivatePane]);
|
pub type WorkspaceId = i64;
|
||||||
|
|
||||||
pub fn init_settings(cx: &mut AppContext) {
|
pub fn init_settings(cx: &mut AppContext) {
|
||||||
settings::register::<WorkspaceSettings>(cx);
|
settings::register::<WorkspaceSettings>(cx);
|
||||||
|
|
13
crates/xtask/Cargo.toml
Normal file
13
crates/xtask/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "xtask"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
clap = {version = "4.0", features = ["derive"]}
|
||||||
|
theme = {path = "../theme"}
|
||||||
|
serde_json.workspace = true
|
||||||
|
schemars.workspace = true
|
23
crates/xtask/src/cli.rs
Normal file
23
crates/xtask/src/cli.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
/// Common utilities for Zed developers.
|
||||||
|
// For more information, see [matklad's repository README](https://github.com/matklad/cargo-xtask/)
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
#[command(propagate_version = true)]
|
||||||
|
pub struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Command to run.
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Commands {
|
||||||
|
/// Builds theme types for interop with Typescript.
|
||||||
|
BuildThemeTypes {
|
||||||
|
#[clap(short, long, default_value = "schemas")]
|
||||||
|
out_dir: PathBuf,
|
||||||
|
#[clap(short, long, default_value = "theme.json")]
|
||||||
|
file_name: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
29
crates/xtask/src/main.rs
Normal file
29
crates/xtask/src/main.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
mod cli;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
use schemars::schema_for;
|
||||||
|
use theme::Theme;
|
||||||
|
|
||||||
|
fn build_themes(out_dir: PathBuf, file_name: PathBuf) -> Result<()> {
|
||||||
|
let theme = schema_for!(Theme);
|
||||||
|
let output = serde_json::to_string_pretty(&theme)?;
|
||||||
|
|
||||||
|
std::fs::create_dir(&out_dir)?;
|
||||||
|
|
||||||
|
let mut file_path = out_dir;
|
||||||
|
file_path.push(file_name);
|
||||||
|
|
||||||
|
std::fs::write(file_path, output)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let args = cli::Cli::parse();
|
||||||
|
match args.command {
|
||||||
|
cli::Commands::BuildThemeTypes { out_dir, file_name } => build_themes(out_dir, file_name),
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||||
description = "The fast, collaborative code editor."
|
description = "The fast, collaborative code editor."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
name = "zed"
|
name = "zed"
|
||||||
version = "0.92.0"
|
version = "0.93.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -62,7 +62,6 @@ text = { path = "../text" }
|
||||||
terminal_view = { path = "../terminal_view" }
|
terminal_view = { path = "../terminal_view" }
|
||||||
theme = { path = "../theme" }
|
theme = { path = "../theme" }
|
||||||
theme_selector = { path = "../theme_selector" }
|
theme_selector = { path = "../theme_selector" }
|
||||||
theme_testbench = { path = "../theme_testbench" }
|
|
||||||
util = { path = "../util" }
|
util = { path = "../util" }
|
||||||
vim = { path = "../vim" }
|
vim = { path = "../vim" }
|
||||||
workspace = { path = "../workspace" }
|
workspace = { path = "../workspace" }
|
||||||
|
|
|
@ -154,7 +154,6 @@ fn main() {
|
||||||
search::init(cx);
|
search::init(cx);
|
||||||
vim::init(cx);
|
vim::init(cx);
|
||||||
terminal_view::init(cx);
|
terminal_view::init(cx);
|
||||||
theme_testbench::init(cx);
|
|
||||||
copilot::init(http.clone(), node_runtime, cx);
|
copilot::init(http.clone(), node_runtime, cx);
|
||||||
ai::init(cx);
|
ai::init(cx);
|
||||||
|
|
||||||
|
|
79
docs/zed/syntax-highlighting.md
Normal file
79
docs/zed/syntax-highlighting.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Syntax Highlighting in Zed
|
||||||
|
|
||||||
|
This doc is a work in progress!
|
||||||
|
|
||||||
|
## Defining syntax highlighting rules
|
||||||
|
|
||||||
|
We use tree-sitter queries to match certian properties to highlight.
|
||||||
|
|
||||||
|
### Simple Example:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(property_identifier) @property
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const font: FontFamily = {
|
||||||
|
weight: "normal",
|
||||||
|
underline: false,
|
||||||
|
italic: false,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Match a property identifier and highlight it using the identifier `@property`. In the above example, `weight`, `underline`, and `italic` would be highlighted.
|
||||||
|
|
||||||
|
### Complex example:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
(_
|
||||||
|
return_type: (type_annotation
|
||||||
|
[
|
||||||
|
(type_identifier) @type.return
|
||||||
|
(generic_type
|
||||||
|
name: (type_identifier) @type.return)
|
||||||
|
]))
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
function buildDefaultSyntax(colorScheme: ColorScheme): Partial<Syntax> {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Match a function return type, and highlight the type using the identifier `@type.return`. In the above example, `Partial` would be highlighted.
|
||||||
|
|
||||||
|
### Example - Typescript
|
||||||
|
|
||||||
|
Here is an example portion of our `highlights.scm` for TypeScript:
|
||||||
|
|
||||||
|
```scheme
|
||||||
|
; crates/zed/src/languages/typescript/highlights.scm
|
||||||
|
|
||||||
|
; Variables
|
||||||
|
|
||||||
|
(identifier) @variable
|
||||||
|
|
||||||
|
; Properties
|
||||||
|
|
||||||
|
(property_identifier) @property
|
||||||
|
|
||||||
|
; Function and method calls
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @function)
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (member_expression
|
||||||
|
property: (property_identifier) @function.method))
|
||||||
|
|
||||||
|
; Function and method definitions
|
||||||
|
|
||||||
|
(function
|
||||||
|
name: (identifier) @function)
|
||||||
|
(function_declaration
|
||||||
|
name: (identifier) @function)
|
||||||
|
(method_definition
|
||||||
|
name: (property_identifier) @function.method)
|
||||||
|
|
||||||
|
; ...
|
||||||
|
```
|
1
styles/.gitignore
vendored
1
styles/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
|
coverage/
|
||||||
|
|
20
styles/.zed/settings.json
Normal file
20
styles/.zed/settings.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1642
styles/package-lock.json
generated
1642
styles/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ts-node ./src/buildThemes.ts",
|
"build": "ts-node ./src/buildThemes.ts",
|
||||||
"build-licenses": "ts-node ./src/buildLicenses.ts",
|
"build-licenses": "ts-node ./src/buildLicenses.ts",
|
||||||
"build-tokens": "ts-node ./src/buildTokens.ts"
|
"build-tokens": "ts-node ./src/buildTokens.ts",
|
||||||
|
"build-types": "cd ../crates/theme && cargo test && cd ../../styles && ts-node ./src/buildTypes.ts",
|
||||||
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
@ -19,13 +21,20 @@
|
||||||
"case-anything": "^2.1.10",
|
"case-anything": "^2.1.10",
|
||||||
"chroma-js": "^2.4.2",
|
"chroma-js": "^2.4.2",
|
||||||
"deepmerge": "^4.3.0",
|
"deepmerge": "^4.3.0",
|
||||||
|
"json-schema-to-typescript": "^13.0.2",
|
||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"ts-node": "^10.9.1"
|
"ts-deepmerge": "^6.0.3",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"utility-types": "^3.10.0",
|
||||||
|
"vitest": "^0.32.0"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"htmlWhitespaceSensitivity": "strict",
|
"htmlWhitespaceSensitivity": "strict",
|
||||||
"tabWidth": 4
|
"tabWidth": 4
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitest/coverage-v8": "^0.32.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as fs from "fs";
|
import * as fs from "fs"
|
||||||
import * as path from "path";
|
import * as path from "path"
|
||||||
import { ColorScheme, createColorScheme } from "./common";
|
import { ColorScheme, createColorScheme } from "./common"
|
||||||
import { themes } from "./themes";
|
import { themes } from "./themes"
|
||||||
import { slugify } from "./utils/slugify";
|
import { slugify } from "./utils/slugify"
|
||||||
import { colorSchemeTokens } from "./theme/tokens/colorScheme";
|
import { colorSchemeTokens } from "./theme/tokens/colorScheme"
|
||||||
|
|
||||||
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens");
|
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
|
||||||
const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json");
|
const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json")
|
||||||
const METADATA_FILE = path.join(TOKENS_DIRECTORY, "$metadata.json");
|
const METADATA_FILE = path.join(TOKENS_DIRECTORY, "$metadata.json")
|
||||||
|
|
||||||
function clearTokens(tokensDirectory: string) {
|
function clearTokens(tokensDirectory: string) {
|
||||||
if (!fs.existsSync(tokensDirectory)) {
|
if (!fs.existsSync(tokensDirectory)) {
|
||||||
|
@ -22,64 +22,66 @@ function clearTokens(tokensDirectory: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenSet = {
|
type TokenSet = {
|
||||||
id: string;
|
id: string
|
||||||
name: string;
|
name: string
|
||||||
selectedTokenSets: { [key: string]: "enabled" };
|
selectedTokenSets: { [key: string]: "enabled" }
|
||||||
};
|
}
|
||||||
|
|
||||||
function buildTokenSetOrder(colorSchemes: ColorScheme[]): { tokenSetOrder: string[] } {
|
function buildTokenSetOrder(colorSchemes: ColorScheme[]): {
|
||||||
const tokenSetOrder: string[] = colorSchemes.map(
|
tokenSetOrder: string[]
|
||||||
(scheme) => scheme.name.toLowerCase().replace(/\s+/g, "_")
|
} {
|
||||||
);
|
const tokenSetOrder: string[] = colorSchemes.map((scheme) =>
|
||||||
return { tokenSetOrder };
|
scheme.name.toLowerCase().replace(/\s+/g, "_")
|
||||||
|
)
|
||||||
|
return { tokenSetOrder }
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildThemesIndex(colorSchemes: ColorScheme[]): TokenSet[] {
|
function buildThemesIndex(colorSchemes: ColorScheme[]): TokenSet[] {
|
||||||
const themesIndex: TokenSet[] = colorSchemes.map((scheme, index) => {
|
const themesIndex: TokenSet[] = colorSchemes.map((scheme, index) => {
|
||||||
const id = `${scheme.isLight ? "light" : "dark"}_${scheme.name
|
const id = `${scheme.isLight ? "light" : "dark"}_${scheme.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(/\s+/g, "_")}_${index}`;
|
.replace(/\s+/g, "_")}_${index}`
|
||||||
const selectedTokenSets: { [key: string]: "enabled" } = {};
|
const selectedTokenSets: { [key: string]: "enabled" } = {}
|
||||||
const tokenSet = scheme.name.toLowerCase().replace(/\s+/g, "_");
|
const tokenSet = scheme.name.toLowerCase().replace(/\s+/g, "_")
|
||||||
selectedTokenSets[tokenSet] = "enabled";
|
selectedTokenSets[tokenSet] = "enabled"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name: `${scheme.name} - ${scheme.isLight ? "Light" : "Dark"}`,
|
name: `${scheme.name} - ${scheme.isLight ? "Light" : "Dark"}`,
|
||||||
selectedTokenSets,
|
selectedTokenSets,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return themesIndex;
|
return themesIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTokens(colorSchemes: ColorScheme[], tokensDirectory: string) {
|
function writeTokens(colorSchemes: ColorScheme[], tokensDirectory: string) {
|
||||||
clearTokens(tokensDirectory);
|
clearTokens(tokensDirectory)
|
||||||
|
|
||||||
for (const colorScheme of colorSchemes) {
|
for (const colorScheme of colorSchemes) {
|
||||||
const fileName = slugify(colorScheme.name) + ".json";
|
const fileName = slugify(colorScheme.name) + ".json"
|
||||||
const tokens = colorSchemeTokens(colorScheme);
|
const tokens = colorSchemeTokens(colorScheme)
|
||||||
const tokensJSON = JSON.stringify(tokens, null, 2);
|
const tokensJSON = JSON.stringify(tokens, null, 2)
|
||||||
const outPath = path.join(tokensDirectory, fileName);
|
const outPath = path.join(tokensDirectory, fileName)
|
||||||
fs.writeFileSync(outPath, tokensJSON, { mode: 0o644 });
|
fs.writeFileSync(outPath, tokensJSON, { mode: 0o644 })
|
||||||
console.log(`- ${outPath} created`);
|
console.log(`- ${outPath} created`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const themeIndexData = buildThemesIndex(colorSchemes);
|
const themeIndexData = buildThemesIndex(colorSchemes)
|
||||||
|
|
||||||
const themesJSON = JSON.stringify(themeIndexData, null, 2);
|
const themesJSON = JSON.stringify(themeIndexData, null, 2)
|
||||||
fs.writeFileSync(TOKENS_FILE, themesJSON, { mode: 0o644 });
|
fs.writeFileSync(TOKENS_FILE, themesJSON, { mode: 0o644 })
|
||||||
console.log(`- ${TOKENS_FILE} created`);
|
console.log(`- ${TOKENS_FILE} created`)
|
||||||
|
|
||||||
const tokenSetOrderData = buildTokenSetOrder(colorSchemes);
|
const tokenSetOrderData = buildTokenSetOrder(colorSchemes)
|
||||||
|
|
||||||
const metadataJSON = JSON.stringify(tokenSetOrderData, null, 2);
|
const metadataJSON = JSON.stringify(tokenSetOrderData, null, 2)
|
||||||
fs.writeFileSync(METADATA_FILE, metadataJSON, { mode: 0o644 });
|
fs.writeFileSync(METADATA_FILE, metadataJSON, { mode: 0o644 })
|
||||||
console.log(`- ${METADATA_FILE} created`);
|
console.log(`- ${METADATA_FILE} created`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorSchemes: ColorScheme[] = themes.map((theme) =>
|
const colorSchemes: ColorScheme[] = themes.map((theme) =>
|
||||||
createColorScheme(theme)
|
createColorScheme(theme)
|
||||||
);
|
)
|
||||||
|
|
||||||
writeTokens(colorSchemes, TOKENS_DIRECTORY);
|
writeTokens(colorSchemes, TOKENS_DIRECTORY)
|
||||||
|
|
64
styles/src/buildTypes.ts
Normal file
64
styles/src/buildTypes.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
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() {
|
||||||
|
let schemasPath = path.join(dirname, "../../", "crates/theme/schemas")
|
||||||
|
let schemaFiles = (await fs.readdir(schemasPath)).filter((x) =>
|
||||||
|
x.endsWith(".json")
|
||||||
|
)
|
||||||
|
|
||||||
|
let compiledTypes = new Set()
|
||||||
|
|
||||||
|
for (let filename of schemaFiles) {
|
||||||
|
let filePath = path.join(schemasPath, filename)
|
||||||
|
const fileContents = await fs.readFile(filePath)
|
||||||
|
let schema = JSON.parse(fileContents.toString())
|
||||||
|
let compiled = await compile(schema, schema.title, {
|
||||||
|
bannerComment: "",
|
||||||
|
})
|
||||||
|
let eachType = compiled.split("export")
|
||||||
|
for (let type of eachType) {
|
||||||
|
if (!type) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
compiledTypes.add("export " + type.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = BANNER + Array.from(compiledTypes).join("\n\n")
|
||||||
|
let outputPath = path.join(dirname, "../../styles/src/types/zed.ts")
|
||||||
|
|
||||||
|
try {
|
||||||
|
let existing = await fs.readFile(outputPath)
|
||||||
|
if (existing.toString() == output) {
|
||||||
|
// Skip writing if it hasn't changed
|
||||||
|
console.log("Schemas are up to date")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// It's fine if there's no output from a previous run.
|
||||||
|
// @ts-ignore
|
||||||
|
if (e.code !== "ENOENT") {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const typesDic = path.dirname(outputPath)
|
||||||
|
if (!fsSync.existsSync(typesDic)) {
|
||||||
|
await fs.mkdir(typesDic)
|
||||||
|
}
|
||||||
|
await fs.writeFile(outputPath, output)
|
||||||
|
console.log(`Wrote Typescript types to ${outputPath}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
4
styles/src/element/index.ts
Normal file
4
styles/src/element/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { interactive } from "./interactive"
|
||||||
|
import { toggleable } from "./toggle"
|
||||||
|
|
||||||
|
export { interactive, toggleable }
|
56
styles/src/element/interactive.test.ts
Normal file
56
styles/src/element/interactive.test.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
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: { fontSize: 10, color: "#FFFFFF" },
|
||||||
|
state: {
|
||||||
|
hovered: { color: "#EEEEEE" },
|
||||||
|
clicked: { color: "#CCCCCC" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
default: { color: "#FFFFFF", fontSize: 10 },
|
||||||
|
hovered: { color: "#EEEEEE", fontSize: 10 },
|
||||||
|
clicked: { color: "#CCCCCC", fontSize: 10 },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates an Interactive<Element> with no base properties", () => {
|
||||||
|
const result = interactive({
|
||||||
|
state: {
|
||||||
|
default: { color: "#FFFFFF", fontSize: 10 },
|
||||||
|
hovered: { color: "#EEEEEE" },
|
||||||
|
clicked: { color: "#CCCCCC" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
default: { color: "#FFFFFF", fontSize: 10 },
|
||||||
|
hovered: { color: "#EEEEEE", fontSize: 10 },
|
||||||
|
clicked: { color: "#CCCCCC", fontSize: 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: { fontSize: 10 },
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => interactive({ state })).toThrow(NOT_ENOUGH_STATES_ERROR)
|
||||||
|
})
|
||||||
|
})
|
97
styles/src/element/interactive.ts
Normal file
97
styles/src/element/interactive.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import merge from "ts-deepmerge"
|
||||||
|
import { DeepPartial } from "utility-types"
|
||||||
|
|
||||||
|
type InteractiveState =
|
||||||
|
| "default"
|
||||||
|
| "hovered"
|
||||||
|
| "clicked"
|
||||||
|
| "selected"
|
||||||
|
| "disabled"
|
||||||
|
|
||||||
|
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 defaultState: T
|
||||||
|
|
||||||
|
if (state.default && base) {
|
||||||
|
defaultState = merge(base, state.default) as T
|
||||||
|
} else {
|
||||||
|
defaultState = base ? base : (state.default as T)
|
||||||
|
}
|
||||||
|
|
||||||
|
let interactiveObj: Interactive<T> = {
|
||||||
|
default: defaultState,
|
||||||
|
}
|
||||||
|
|
||||||
|
let stateCount = 0
|
||||||
|
|
||||||
|
if (state.hovered !== undefined) {
|
||||||
|
interactiveObj.hovered = merge(
|
||||||
|
interactiveObj.default,
|
||||||
|
state.hovered
|
||||||
|
) as T
|
||||||
|
stateCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.clicked !== undefined) {
|
||||||
|
interactiveObj.clicked = merge(
|
||||||
|
interactiveObj.default,
|
||||||
|
state.clicked
|
||||||
|
) as T
|
||||||
|
stateCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.selected !== undefined) {
|
||||||
|
interactiveObj.selected = merge(
|
||||||
|
interactiveObj.default,
|
||||||
|
state.selected
|
||||||
|
) as T
|
||||||
|
stateCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.disabled !== undefined) {
|
||||||
|
interactiveObj.disabled = merge(
|
||||||
|
interactiveObj.default,
|
||||||
|
state.disabled
|
||||||
|
) as T
|
||||||
|
stateCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateCount < 1) {
|
||||||
|
throw new Error(NOT_ENOUGH_STATES_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
return interactiveObj
|
||||||
|
}
|
52
styles/src/element/toggle.test.ts
Normal file
52
styles/src/element/toggle.test.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
})
|
47
styles/src/element/toggle.ts
Normal file
47
styles/src/element/toggle.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import merge from "ts-deepmerge"
|
||||||
|
import { DeepPartial } from "utility-types"
|
||||||
|
|
||||||
|
type ToggleState = "inactive" | "active"
|
||||||
|
|
||||||
|
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 inactiveState = base
|
||||||
|
? ((state.inactive ? merge(base, state.inactive) : base) as T)
|
||||||
|
: (state.inactive as T)
|
||||||
|
|
||||||
|
const toggleObj: Toggleable<T> = {
|
||||||
|
inactive: inactiveState,
|
||||||
|
active: merge(base ?? {}, state.active) as T,
|
||||||
|
}
|
||||||
|
return toggleObj
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import { text } from "./components"
|
|
||||||
import contactFinder from "./contactFinder"
|
import contactFinder from "./contactFinder"
|
||||||
import contactsPopover from "./contactsPopover"
|
import contactsPopover from "./contactsPopover"
|
||||||
import commandPalette from "./commandPalette"
|
import commandPalette from "./commandPalette"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { text, border, background, foreground } from "./components"
|
import { text, border, background, foreground } from "./components"
|
||||||
import editor from "./editor"
|
import editor from "./editor"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
|
||||||
export default function assistant(colorScheme: ColorScheme) {
|
export default function assistant(colorScheme: ColorScheme) {
|
||||||
const layer = colorScheme.highest
|
const layer = colorScheme.highest
|
||||||
|
@ -15,83 +16,104 @@ export default function assistant(colorScheme: ColorScheme) {
|
||||||
background: editor(colorScheme).background,
|
background: editor(colorScheme).background,
|
||||||
},
|
},
|
||||||
hamburgerButton: {
|
hamburgerButton: {
|
||||||
icon: {
|
icon: {
|
||||||
color: text(layer, "sans", "default", { size: "sm" }).color,
|
color: text(layer, "sans", "default", { size: "sm" }).color,
|
||||||
asset: "icons/hamburger_15.svg",
|
asset: "icons/hamburger_15.svg",
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 15,
|
width: 15,
|
||||||
height: 15,
|
height: 15,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
container: {
|
||||||
container: {
|
margin: { left: 12 },
|
||||||
margin: { left: 12 },
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
zoomInButton: {
|
zoomInButton: {
|
||||||
icon: {
|
icon: {
|
||||||
color: text(layer, "sans", "default", { size: "sm" }).color,
|
color: text(layer, "sans", "default", { size: "sm" }).color,
|
||||||
asset: "icons/maximize_8.svg",
|
asset: "icons/maximize_8.svg",
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 12,
|
width: 12,
|
||||||
height: 12,
|
height: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
container: {
|
||||||
container: {
|
margin: { right: 12 },
|
||||||
margin: { right: 12 },
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
zoomOutButton: {
|
zoomOutButton: {
|
||||||
icon: {
|
icon: {
|
||||||
color: text(layer, "sans", "default", { size: "sm" }).color,
|
color: text(layer, "sans", "default", { size: "sm" }).color,
|
||||||
asset: "icons/minimize_8.svg",
|
asset: "icons/minimize_8.svg",
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 12,
|
width: 12,
|
||||||
height: 12,
|
height: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
container: {
|
||||||
container: {
|
margin: { right: 12 },
|
||||||
margin: { right: 12 },
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
plusButton: {
|
plusButton: {
|
||||||
icon: {
|
icon: {
|
||||||
color: text(layer, "sans", "default", { size: "sm" }).color,
|
color: text(layer, "sans", "default", { size: "sm" }).color,
|
||||||
asset: "icons/plus_12.svg",
|
asset: "icons/plus_12.svg",
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 12,
|
width: 12,
|
||||||
height: 12,
|
height: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
container: {
|
||||||
container: {
|
margin: { right: 12 },
|
||||||
margin: { right: 12 },
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
margin: { left: 12 },
|
margin: { left: 12 },
|
||||||
...text(layer, "sans", "default", { size: "sm" })
|
...text(layer, "sans", "default", { size: "sm" })
|
||||||
},
|
},
|
||||||
savedConversation: {
|
savedConversation: {
|
||||||
background: background(layer, "on"),
|
container: interactive({
|
||||||
hover: {
|
base: {
|
||||||
background: background(layer, "on", "hovered"),
|
background: background(layer, "on"),
|
||||||
},
|
},
|
||||||
savedAt: {
|
state: {
|
||||||
margin: { left: 8 },
|
hovered: {
|
||||||
...text(layer, "sans", "default", { size: "xs" }),
|
background: background(layer, "on", "hovered"),
|
||||||
},
|
}
|
||||||
title: {
|
},
|
||||||
margin: { left: 8 },
|
}),
|
||||||
...text(layer, "sans", "default", { size: "sm", weight: "bold" }),
|
savedAt: {
|
||||||
}
|
margin: { left: 8 },
|
||||||
|
...text(layer, "sans", "default", { size: "xs" }),
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
margin: { left: 8 },
|
||||||
|
...text(layer, "sans", "default", { size: "sm", weight: "bold" }),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
userSender: {
|
userSender: {
|
||||||
...text(layer, "sans", "default", { size: "sm", weight: "bold" }),
|
default: {
|
||||||
|
...text(layer, "sans", "default", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
assistantSender: {
|
assistantSender: {
|
||||||
...text(layer, "sans", "accent", { size: "sm", weight: "bold" }),
|
default: {
|
||||||
|
...text(layer, "sans", "accent", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
systemSender: {
|
systemSender: {
|
||||||
...text(layer, "sans", "variant", { size: "sm", weight: "bold" }),
|
default: {
|
||||||
|
...text(layer, "sans", "variant", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
sentAt: {
|
sentAt: {
|
||||||
margin: { top: 2, left: 8 },
|
margin: { top: 2, left: 8 },
|
||||||
|
@ -100,17 +122,21 @@ export default function assistant(colorScheme: ColorScheme) {
|
||||||
modelInfoContainer: {
|
modelInfoContainer: {
|
||||||
margin: { right: 16, top: 4 },
|
margin: { right: 16, top: 4 },
|
||||||
},
|
},
|
||||||
model: {
|
model: interactive({
|
||||||
background: background(layer, "on"),
|
base: {
|
||||||
margin: { right: 8 },
|
background: background(layer, "on"),
|
||||||
padding: 4,
|
margin: { right: 8 },
|
||||||
cornerRadius: 4,
|
padding: 4,
|
||||||
...text(layer, "sans", "default", { size: "xs" }),
|
cornerRadius: 4,
|
||||||
hover: {
|
...text(layer, "sans", "default", { size: "xs" }),
|
||||||
background: background(layer, "on", "hovered"),
|
|
||||||
border: border(layer, "on", { overlay: true }),
|
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
border: border(layer, "on", { overlay: true }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
remainingTokens: {
|
remainingTokens: {
|
||||||
margin: { right: 12 },
|
margin: { right: 12 },
|
||||||
...text(layer, "sans", "positive", { size: "xs" }),
|
...text(layer, "sans", "positive", { size: "xs" }),
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { text, background } from "./components"
|
import { text, background } from "./components"
|
||||||
|
import { toggleable } from "../element"
|
||||||
|
|
||||||
export default function commandPalette(colorScheme: ColorScheme) {
|
export default function commandPalette(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.highest
|
let layer = colorScheme.highest
|
||||||
return {
|
|
||||||
keystrokeSpacing: 8,
|
const key = toggleable({
|
||||||
key: {
|
base: {
|
||||||
text: text(layer, "mono", "variant", "default", { size: "xs" }),
|
text: text(layer, "mono", "variant", "default", { size: "xs" }),
|
||||||
cornerRadius: 2,
|
cornerRadius: 2,
|
||||||
background: background(layer, "on"),
|
background: background(layer, "on"),
|
||||||
|
@ -21,10 +22,21 @@ export default function commandPalette(colorScheme: ColorScheme) {
|
||||||
bottom: 1,
|
bottom: 1,
|
||||||
left: 2,
|
left: 2,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
state: {
|
||||||
active: {
|
active: {
|
||||||
text: text(layer, "mono", "on", "default", { size: "xs" }),
|
text: text(layer, "mono", "on", "default", { size: "xs" }),
|
||||||
background: withOpacity(background(layer, "on"), 0.2),
|
background: withOpacity(background(layer, "on"), 0.2),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
keystrokeSpacing: 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,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ export function foreground(
|
||||||
return getStyle(layer, styleSetOrStyles, style).foreground
|
return getStyle(layer, styleSetOrStyles, style).foreground
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Text {
|
interface Text extends Object {
|
||||||
family: keyof typeof fontFamilies
|
family: keyof typeof fontFamilies
|
||||||
color: string
|
color: string
|
||||||
size: number
|
size: number
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, borderColor, foreground, text } from "./components"
|
import { background, border, borderColor, foreground, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
export default function contactsPanel(colorScheme: ColorScheme) {
|
export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
const nameMargin = 8
|
const nameMargin = 8
|
||||||
const sidePadding = 12
|
const sidePadding = 12
|
||||||
|
@ -71,47 +71,85 @@ export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
rowHeight: 28,
|
rowHeight: 28,
|
||||||
sectionIconSize: 8,
|
sectionIconSize: 8,
|
||||||
headerRow: {
|
headerRow: toggleable({
|
||||||
...text(layer, "mono", { size: "sm" }),
|
base: interactive({
|
||||||
margin: { top: 14 },
|
base: {
|
||||||
padding: {
|
...text(layer, "mono", { size: "sm" }),
|
||||||
left: sidePadding,
|
margin: { top: 14 },
|
||||||
right: sidePadding,
|
padding: {
|
||||||
|
left: sidePadding,
|
||||||
|
right: sidePadding,
|
||||||
|
},
|
||||||
|
background: background(layer, "default"), // posiewic: breaking change
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
|
}, // hack, we want headerRow to be interactive for whatever reason. It probably shouldn't be interactive in the first place.
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
...text(layer, "mono", "active", { size: "sm" }),
|
||||||
|
background: background(layer, "active"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
}),
|
||||||
...text(layer, "mono", "active", { size: "sm" }),
|
leaveCall: interactive({
|
||||||
background: background(layer, "active"),
|
base: {
|
||||||
|
background: background(layer),
|
||||||
|
border: border(layer),
|
||||||
|
cornerRadius: 6,
|
||||||
|
margin: {
|
||||||
|
top: 1,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
top: 1,
|
||||||
|
bottom: 1,
|
||||||
|
left: 7,
|
||||||
|
right: 7,
|
||||||
|
},
|
||||||
|
...text(layer, "sans", "variant", { size: "xs" }),
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
leaveCall: {
|
hovered: {
|
||||||
background: background(layer),
|
...text(layer, "sans", "hovered", { size: "xs" }),
|
||||||
border: border(layer),
|
background: background(layer, "hovered"),
|
||||||
cornerRadius: 6,
|
border: border(layer, "hovered"),
|
||||||
margin: {
|
},
|
||||||
top: 1,
|
|
||||||
},
|
},
|
||||||
padding: {
|
}),
|
||||||
top: 1,
|
|
||||||
bottom: 1,
|
|
||||||
left: 7,
|
|
||||||
right: 7,
|
|
||||||
},
|
|
||||||
...text(layer, "sans", "variant", { size: "xs" }),
|
|
||||||
hover: {
|
|
||||||
...text(layer, "sans", "hovered", { size: "xs" }),
|
|
||||||
background: background(layer, "hovered"),
|
|
||||||
border: border(layer, "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
contactRow: {
|
contactRow: {
|
||||||
padding: {
|
inactive: {
|
||||||
left: sidePadding,
|
default: {
|
||||||
right: sidePadding,
|
padding: {
|
||||||
|
left: sidePadding,
|
||||||
|
right: sidePadding,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
active: {
|
||||||
background: background(layer, "active"),
|
default: {
|
||||||
|
background: background(layer, "active"),
|
||||||
|
padding: {
|
||||||
|
left: sidePadding,
|
||||||
|
right: sidePadding,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
contactAvatar: {
|
contactAvatar: {
|
||||||
cornerRadius: 10,
|
cornerRadius: 10,
|
||||||
width: 18,
|
width: 18,
|
||||||
|
@ -135,12 +173,14 @@ export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
contactButtonSpacing: nameMargin,
|
contactButtonSpacing: nameMargin,
|
||||||
contactButton: {
|
contactButton: interactive({
|
||||||
...contactButton,
|
base: { ...contactButton },
|
||||||
hover: {
|
state: {
|
||||||
background: background(layer, "hovered"),
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
disabledButton: {
|
disabledButton: {
|
||||||
...contactButton,
|
...contactButton,
|
||||||
background: background(layer, "on"),
|
background: background(layer, "on"),
|
||||||
|
@ -149,34 +189,52 @@ export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
callingIndicator: {
|
callingIndicator: {
|
||||||
...text(layer, "mono", "variant", { size: "xs" }),
|
...text(layer, "mono", "variant", { size: "xs" }),
|
||||||
},
|
},
|
||||||
treeBranch: {
|
treeBranch: toggleable({
|
||||||
color: borderColor(layer),
|
base: interactive({
|
||||||
width: 1,
|
base: {
|
||||||
hover: {
|
color: borderColor(layer),
|
||||||
color: borderColor(layer),
|
width: 1,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: borderColor(layer),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
color: borderColor(layer),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
}),
|
||||||
color: borderColor(layer),
|
projectRow: toggleable({
|
||||||
|
base: interactive({
|
||||||
|
base: {
|
||||||
|
...projectRow,
|
||||||
|
background: background(layer),
|
||||||
|
icon: {
|
||||||
|
margin: { left: nameMargin },
|
||||||
|
color: foreground(layer, "variant"),
|
||||||
|
width: 12,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
...projectRow.name,
|
||||||
|
...text(layer, "mono", { size: "sm" }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: { background: background(layer, "active") },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
projectRow: {
|
|
||||||
...projectRow,
|
|
||||||
background: background(layer),
|
|
||||||
icon: {
|
|
||||||
margin: { left: nameMargin },
|
|
||||||
color: foreground(layer, "variant"),
|
|
||||||
width: 12,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
...projectRow.name,
|
|
||||||
...text(layer, "mono", { size: "sm" }),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
background: background(layer, "hovered"),
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, foreground, text } from "./components"
|
import { background, foreground, text } from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
const avatarSize = 12
|
const avatarSize = 12
|
||||||
const headerPadding = 8
|
const headerPadding = 8
|
||||||
|
|
||||||
|
@ -21,24 +21,32 @@ export default function contactNotification(colorScheme: ColorScheme): Object {
|
||||||
...text(layer, "sans", { size: "xs" }),
|
...text(layer, "sans", { size: "xs" }),
|
||||||
margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
|
margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
|
||||||
},
|
},
|
||||||
button: {
|
button: interactive({
|
||||||
...text(layer, "sans", "on", { size: "xs" }),
|
base: {
|
||||||
background: background(layer, "on"),
|
...text(layer, "sans", "on", { size: "xs" }),
|
||||||
padding: 4,
|
background: background(layer, "on"),
|
||||||
cornerRadius: 6,
|
padding: 4,
|
||||||
margin: { left: 6 },
|
cornerRadius: 6,
|
||||||
hover: {
|
margin: { left: 6 },
|
||||||
background: background(layer, "on", "hovered"),
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
dismissButton: {
|
dismissButton: {
|
||||||
color: foreground(layer, "variant"),
|
default: {
|
||||||
iconWidth: 8,
|
color: foreground(layer, "variant"),
|
||||||
iconHeight: 8,
|
iconWidth: 8,
|
||||||
buttonWidth: 8,
|
iconHeight: 8,
|
||||||
buttonHeight: 8,
|
buttonWidth: 8,
|
||||||
hover: {
|
buttonHeight: 8,
|
||||||
color: foreground(layer, "hovered"),
|
hover: {
|
||||||
|
color: foreground(layer, "hovered"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, borderColor, text } from "./components"
|
import { background, border, borderColor, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
|
|
||||||
export default function contextMenu(colorScheme: ColorScheme) {
|
export default function contextMenu(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.middle
|
let layer = colorScheme.middle
|
||||||
|
@ -10,37 +11,54 @@ export default function contextMenu(colorScheme: ColorScheme) {
|
||||||
shadow: colorScheme.popoverShadow,
|
shadow: colorScheme.popoverShadow,
|
||||||
border: border(layer),
|
border: border(layer),
|
||||||
keystrokeMargin: 30,
|
keystrokeMargin: 30,
|
||||||
item: {
|
item: toggleable({
|
||||||
iconSpacing: 8,
|
base: interactive({
|
||||||
iconWidth: 14,
|
base: {
|
||||||
padding: { left: 6, right: 6, top: 2, bottom: 2 },
|
iconSpacing: 8,
|
||||||
cornerRadius: 6,
|
iconWidth: 14,
|
||||||
label: text(layer, "sans", { size: "sm" }),
|
padding: { left: 6, right: 6, top: 2, bottom: 2 },
|
||||||
keystroke: {
|
cornerRadius: 6,
|
||||||
...text(layer, "sans", "variant", {
|
label: text(layer, "sans", { size: "sm" }),
|
||||||
size: "sm",
|
keystroke: {
|
||||||
weight: "bold",
|
...text(layer, "sans", "variant", {
|
||||||
}),
|
size: "sm",
|
||||||
padding: { left: 3, right: 3 },
|
weight: "bold",
|
||||||
},
|
}),
|
||||||
hover: {
|
padding: { left: 3, right: 3 },
|
||||||
background: background(layer, "hovered"),
|
},
|
||||||
label: text(layer, "sans", "hovered", { size: "sm" }),
|
},
|
||||||
keystroke: {
|
state: {
|
||||||
...text(layer, "sans", "hovered", {
|
hovered: {
|
||||||
size: "sm",
|
background: background(layer, "hovered"),
|
||||||
weight: "bold",
|
label: text(layer, "sans", "hovered", { size: "sm" }),
|
||||||
}),
|
keystroke: {
|
||||||
padding: { left: 3, right: 3 },
|
...text(layer, "sans", "hovered", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
padding: { left: 3, right: 3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
background: background(layer, "active"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
active: {
|
}),
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
activeHover: {
|
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
separator: {
|
separator: {
|
||||||
background: borderColor(layer),
|
background: borderColor(layer),
|
||||||
margin: { top: 2, bottom: 2 },
|
margin: { top: 2, bottom: 2 },
|
||||||
|
|
|
@ -1,60 +1,69 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, svg, text } from "./components"
|
import { background, border, foreground, svg, text } from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
export default function copilot(colorScheme: ColorScheme) {
|
export default function copilot(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.middle
|
let layer = colorScheme.middle
|
||||||
|
|
||||||
let content_width = 264
|
let content_width = 264
|
||||||
|
|
||||||
let ctaButton = {
|
let ctaButton =
|
||||||
// Copied from welcome screen. FIXME: Move this into a ZDS component
|
// Copied from welcome screen. FIXME: Move this into a ZDS component
|
||||||
background: background(layer),
|
interactive({
|
||||||
border: border(layer, "default"),
|
base: {
|
||||||
cornerRadius: 4,
|
background: background(layer),
|
||||||
margin: {
|
border: border(layer, "default"),
|
||||||
top: 4,
|
cornerRadius: 4,
|
||||||
bottom: 4,
|
margin: {
|
||||||
left: 8,
|
top: 4,
|
||||||
right: 8,
|
bottom: 4,
|
||||||
},
|
left: 8,
|
||||||
padding: {
|
right: 8,
|
||||||
top: 3,
|
},
|
||||||
bottom: 3,
|
padding: {
|
||||||
left: 7,
|
top: 3,
|
||||||
right: 7,
|
bottom: 3,
|
||||||
},
|
left: 7,
|
||||||
...text(layer, "sans", "default", { size: "sm" }),
|
right: 7,
|
||||||
hover: {
|
},
|
||||||
...text(layer, "sans", "default", { size: "sm" }),
|
...text(layer, "sans", "default", { size: "sm" }),
|
||||||
background: background(layer, "hovered"),
|
},
|
||||||
border: border(layer, "active"),
|
state: {
|
||||||
},
|
hovered: {
|
||||||
}
|
...text(layer, "sans", "default", { size: "sm" }),
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
border: border(layer, "active"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
outLinkIcon: {
|
outLinkIcon: interactive({
|
||||||
icon: svg(
|
base: {
|
||||||
foreground(layer, "variant"),
|
|
||||||
"icons/link_out_12.svg",
|
|
||||||
12,
|
|
||||||
12
|
|
||||||
),
|
|
||||||
container: {
|
|
||||||
cornerRadius: 6,
|
|
||||||
padding: { left: 6 },
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
icon: svg(
|
icon: svg(
|
||||||
foreground(layer, "hovered"),
|
foreground(layer, "variant"),
|
||||||
"icons/link_out_12.svg",
|
"icons/link_out_12.svg",
|
||||||
12,
|
12,
|
||||||
12
|
12
|
||||||
),
|
),
|
||||||
|
container: {
|
||||||
|
cornerRadius: 6,
|
||||||
|
padding: { left: 6 },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
icon: {
|
||||||
|
color: foreground(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
modal: {
|
modal: {
|
||||||
titleText: {
|
titleText: {
|
||||||
...text(layer, "sans", { size: "xs", weight: "bold" }),
|
default: {
|
||||||
|
...text(layer, "sans", { size: "xs", weight: "bold" }),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
titlebar: {
|
titlebar: {
|
||||||
background: background(colorScheme.lowest),
|
background: background(colorScheme.lowest),
|
||||||
|
@ -75,42 +84,46 @@ export default function copilot(colorScheme: ColorScheme) {
|
||||||
bottom: 8,
|
bottom: 8,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: interactive({
|
||||||
icon: svg(
|
base: {
|
||||||
foreground(layer, "variant"),
|
|
||||||
"icons/x_mark_8.svg",
|
|
||||||
8,
|
|
||||||
8
|
|
||||||
),
|
|
||||||
container: {
|
|
||||||
cornerRadius: 2,
|
|
||||||
padding: {
|
|
||||||
top: 4,
|
|
||||||
bottom: 4,
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
},
|
|
||||||
margin: {
|
|
||||||
right: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
icon: svg(
|
icon: svg(
|
||||||
foreground(layer, "on"),
|
foreground(layer, "variant"),
|
||||||
"icons/x_mark_8.svg",
|
"icons/x_mark_8.svg",
|
||||||
8,
|
8,
|
||||||
8
|
8
|
||||||
),
|
),
|
||||||
|
container: {
|
||||||
|
cornerRadius: 2,
|
||||||
|
padding: {
|
||||||
|
top: 4,
|
||||||
|
bottom: 4,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
margin: {
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
state: {
|
||||||
icon: svg(
|
hovered: {
|
||||||
foreground(layer, "base"),
|
icon: svg(
|
||||||
"icons/x_mark_8.svg",
|
foreground(layer, "on"),
|
||||||
8,
|
"icons/x_mark_8.svg",
|
||||||
8
|
8,
|
||||||
),
|
8
|
||||||
|
),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
icon: svg(
|
||||||
|
foreground(layer, "base"),
|
||||||
|
"icons/x_mark_8.svg",
|
||||||
|
8,
|
||||||
|
8
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 280,
|
width: 280,
|
||||||
height: 280,
|
height: 280,
|
||||||
|
@ -185,28 +198,32 @@ export default function copilot(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
right: (content_width * 1) / 3,
|
right: (content_width * 1) / 3,
|
||||||
rightContainer: {
|
rightContainer: interactive({
|
||||||
border: border(colorScheme.lowest, "inverted", {
|
base: {
|
||||||
bottom: false,
|
border: border(colorScheme.lowest, "inverted", {
|
||||||
right: false,
|
|
||||||
top: false,
|
|
||||||
left: true,
|
|
||||||
}),
|
|
||||||
padding: {
|
|
||||||
top: 3,
|
|
||||||
bottom: 5,
|
|
||||||
left: 8,
|
|
||||||
right: 0,
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
border: border(layer, "active", {
|
|
||||||
bottom: false,
|
bottom: false,
|
||||||
right: false,
|
right: false,
|
||||||
top: false,
|
top: false,
|
||||||
left: true,
|
left: true,
|
||||||
}),
|
}),
|
||||||
|
padding: {
|
||||||
|
top: 3,
|
||||||
|
bottom: 5,
|
||||||
|
left: 8,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
border: border(layer, "active", {
|
||||||
|
bottom: false,
|
||||||
|
right: false,
|
||||||
|
top: false,
|
||||||
|
left: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { background, border, borderColor, foreground, text } from "./components"
|
||||||
import hoverPopover from "./hoverPopover"
|
import hoverPopover from "./hoverPopover"
|
||||||
|
|
||||||
import { buildSyntax } from "../theme/syntax"
|
import { buildSyntax } from "../theme/syntax"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
|
|
||||||
export default function editor(colorScheme: ColorScheme) {
|
export default function editor(colorScheme: ColorScheme) {
|
||||||
const { isLight } = colorScheme
|
const { isLight } = colorScheme
|
||||||
|
@ -48,46 +49,76 @@ export default function editor(colorScheme: ColorScheme) {
|
||||||
// Inline autocomplete suggestions, Co-pilot suggestions, etc.
|
// Inline autocomplete suggestions, Co-pilot suggestions, etc.
|
||||||
suggestion: syntax.predictive,
|
suggestion: syntax.predictive,
|
||||||
codeActions: {
|
codeActions: {
|
||||||
indicator: {
|
indicator: toggleable({
|
||||||
color: foreground(layer, "variant"),
|
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"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
clicked: {
|
|
||||||
color: foreground(layer, "base"),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
color: foreground(layer, "on"),
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
color: foreground(layer, "on"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
verticalScale: 0.55,
|
verticalScale: 0.55,
|
||||||
},
|
},
|
||||||
folds: {
|
folds: {
|
||||||
iconMarginScale: 2.5,
|
iconMarginScale: 2.5,
|
||||||
foldedIcon: "icons/chevron_right_8.svg",
|
foldedIcon: "icons/chevron_right_8.svg",
|
||||||
foldableIcon: "icons/chevron_down_8.svg",
|
foldableIcon: "icons/chevron_down_8.svg",
|
||||||
indicator: {
|
indicator: toggleable({
|
||||||
color: foreground(layer, "variant"),
|
base: interactive({
|
||||||
|
base: {
|
||||||
clicked: {
|
color: foreground(layer, "variant"),
|
||||||
color: foreground(layer, "base"),
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: foreground(layer, "on"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
color: foreground(layer, "base"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
color: foreground(layer, "default"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
color: foreground(layer, "variant"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hover: {
|
}),
|
||||||
color: foreground(layer, "on"),
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
color: foreground(layer, "on"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ellipses: {
|
ellipses: {
|
||||||
textColor: colorScheme.ramps.neutral(0.71).hex(),
|
textColor: colorScheme.ramps.neutral(0.71).hex(),
|
||||||
cornerRadiusFactor: 0.15,
|
cornerRadiusFactor: 0.15,
|
||||||
background: {
|
background: {
|
||||||
// Copied from hover_popover highlight
|
// Copied from hover_popover highlight
|
||||||
color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
|
default: {
|
||||||
|
color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
|
||||||
|
},
|
||||||
|
|
||||||
hover: {
|
hovered: {
|
||||||
color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
|
color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -223,21 +254,26 @@ export default function editor(colorScheme: ColorScheme) {
|
||||||
color: syntax.linkUri.color,
|
color: syntax.linkUri.color,
|
||||||
underline: syntax.linkUri.underline,
|
underline: syntax.linkUri.underline,
|
||||||
},
|
},
|
||||||
jumpIcon: {
|
jumpIcon: interactive({
|
||||||
color: foreground(layer, "on"),
|
base: {
|
||||||
iconWidth: 20,
|
color: foreground(layer, "on"),
|
||||||
buttonWidth: 20,
|
iconWidth: 20,
|
||||||
cornerRadius: 6,
|
buttonWidth: 20,
|
||||||
padding: {
|
cornerRadius: 6,
|
||||||
top: 6,
|
padding: {
|
||||||
bottom: 6,
|
top: 6,
|
||||||
left: 6,
|
bottom: 6,
|
||||||
right: 6,
|
left: 6,
|
||||||
|
right: 6,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hover: {
|
state: {
|
||||||
background: background(layer, "on", "hovered"),
|
hovered: {
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
|
|
||||||
scrollbar: {
|
scrollbar: {
|
||||||
width: 12,
|
width: 12,
|
||||||
minHeightFactor: 1.0,
|
minHeightFactor: 1.0,
|
||||||
|
|
|
@ -1,35 +1,40 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
|
||||||
export default function feedback(colorScheme: ColorScheme) {
|
export default function feedback(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.highest
|
let layer = colorScheme.highest
|
||||||
|
|
||||||
return {
|
return {
|
||||||
submit_button: {
|
submit_button: interactive({
|
||||||
...text(layer, "mono", "on"),
|
base: {
|
||||||
background: background(layer, "on"),
|
...text(layer, "mono", "on"),
|
||||||
cornerRadius: 6,
|
background: background(layer, "on"),
|
||||||
border: border(layer, "on"),
|
cornerRadius: 6,
|
||||||
margin: {
|
border: border(layer, "on"),
|
||||||
right: 4,
|
margin: {
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
bottom: 2,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
top: 2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
padding: {
|
state: {
|
||||||
bottom: 2,
|
clicked: {
|
||||||
left: 10,
|
...text(layer, "mono", "on", "pressed"),
|
||||||
right: 10,
|
background: background(layer, "on", "pressed"),
|
||||||
top: 2,
|
border: border(layer, "on", "pressed"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "mono", "on", "hovered"),
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
border: border(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
}),
|
||||||
...text(layer, "mono", "on", "pressed"),
|
|
||||||
background: background(layer, "on", "pressed"),
|
|
||||||
border: border(layer, "on", "pressed"),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
...text(layer, "mono", "on", "hovered"),
|
|
||||||
background: background(layer, "on", "hovered"),
|
|
||||||
border: border(layer, "on", "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
button_margin: 8,
|
button_margin: 8,
|
||||||
info_text_default: text(layer, "sans", "default", { size: "xs" }),
|
info_text_default: text(layer, "sans", "default", { size: "xs" }),
|
||||||
link_text_default: text(layer, "sans", "default", {
|
link_text_default: text(layer, "sans", "default", {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
|
|
||||||
export default function picker(colorScheme: ColorScheme): any {
|
export default function picker(colorScheme: ColorScheme): any {
|
||||||
let layer = colorScheme.lowest
|
let layer = colorScheme.lowest
|
||||||
|
@ -38,35 +39,65 @@ export default function picker(colorScheme: ColorScheme): any {
|
||||||
...container,
|
...container,
|
||||||
padding: {},
|
padding: {},
|
||||||
},
|
},
|
||||||
item: {
|
item: toggleable({
|
||||||
padding: {
|
base: interactive({
|
||||||
bottom: 4,
|
base: {
|
||||||
left: 12,
|
padding: {
|
||||||
right: 12,
|
bottom: 4,
|
||||||
top: 4,
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
top: 4,
|
||||||
|
},
|
||||||
|
margin: {
|
||||||
|
top: 1,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
cornerRadius: 8,
|
||||||
|
text: text(layer, "sans", "variant"),
|
||||||
|
highlightText: text(layer, "sans", "accent", {
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: withOpacity(
|
||||||
|
background(layer, "hovered"),
|
||||||
|
0.5
|
||||||
|
),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: withOpacity(
|
||||||
|
background(layer, "pressed"),
|
||||||
|
0.5
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
background: withOpacity(
|
||||||
|
background(layer, "base", "active"),
|
||||||
|
0.5
|
||||||
|
),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: withOpacity(
|
||||||
|
background(layer, "hovered"),
|
||||||
|
0.5
|
||||||
|
),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: withOpacity(
|
||||||
|
background(layer, "pressed"),
|
||||||
|
0.5
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
margin: {
|
}),
|
||||||
top: 1,
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
},
|
|
||||||
cornerRadius: 8,
|
|
||||||
text: text(layer, "sans", "variant"),
|
|
||||||
highlightText: text(layer, "sans", "accent", { weight: "bold" }),
|
|
||||||
active: {
|
|
||||||
background: withOpacity(
|
|
||||||
background(layer, "base", "active"),
|
|
||||||
0.5
|
|
||||||
),
|
|
||||||
text: text(layer, "sans", "base", "active"),
|
|
||||||
highlightText: text(layer, "sans", "accent", {
|
|
||||||
weight: "bold",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
background: withOpacity(background(layer, "hovered"), 0.5),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
inputEditor,
|
inputEditor,
|
||||||
emptyInputEditor,
|
emptyInputEditor,
|
||||||
noMatches: {
|
noMatches: {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
export default function projectPanel(colorScheme: ColorScheme) {
|
export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
const { isLight } = colorScheme
|
const { isLight } = colorScheme
|
||||||
|
|
||||||
|
@ -28,48 +28,79 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry = {
|
const default_entry = interactive({
|
||||||
...baseEntry,
|
base: {
|
||||||
text: text(layer, "mono", "variant", { size: "sm" }),
|
...baseEntry,
|
||||||
hover: {
|
text: text(layer, "mono", "variant", { size: "sm" }),
|
||||||
background: background(layer, "variant", "hovered"),
|
status,
|
||||||
},
|
},
|
||||||
active: {
|
state: {
|
||||||
background: colorScheme.isLight
|
default: {
|
||||||
? withOpacity(background(layer, "active"), 0.5)
|
background: background(layer),
|
||||||
: background(layer, "active"),
|
},
|
||||||
text: text(layer, "mono", "active", { size: "sm" }),
|
hovered: {
|
||||||
|
background: background(layer, "variant", "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "variant", "pressed"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
activeHover: {
|
})
|
||||||
background: background(layer, "active"),
|
|
||||||
text: text(layer, "mono", "active", { size: "sm" }),
|
let entry = toggleable({
|
||||||
|
base: default_entry,
|
||||||
|
state: {
|
||||||
|
active: interactive({
|
||||||
|
base: {
|
||||||
|
...default_entry,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
default: {
|
||||||
|
background: background(colorScheme.lowest),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(colorScheme.lowest, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(colorScheme.lowest, "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
status,
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
openProjectButton: {
|
openProjectButton: interactive({
|
||||||
background: background(layer),
|
base: {
|
||||||
border: border(layer, "active"),
|
background: background(layer),
|
||||||
cornerRadius: 4,
|
|
||||||
margin: {
|
|
||||||
top: 16,
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
top: 3,
|
|
||||||
bottom: 3,
|
|
||||||
left: 7,
|
|
||||||
right: 7,
|
|
||||||
},
|
|
||||||
...text(layer, "sans", "default", { size: "sm" }),
|
|
||||||
hover: {
|
|
||||||
...text(layer, "sans", "default", { size: "sm" }),
|
|
||||||
background: background(layer, "hovered"),
|
|
||||||
border: border(layer, "active"),
|
border: border(layer, "active"),
|
||||||
|
cornerRadius: 4,
|
||||||
|
margin: {
|
||||||
|
top: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
top: 3,
|
||||||
|
bottom: 3,
|
||||||
|
left: 7,
|
||||||
|
right: 7,
|
||||||
|
},
|
||||||
|
...text(layer, "sans", "default", { size: "sm" }),
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "sans", "default", { size: "sm" }),
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
border: border(layer, "active"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
...text(layer, "sans", "default", { size: "sm" }),
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
border: border(layer, "active"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
background: background(layer),
|
background: background(layer),
|
||||||
padding: { left: 6, right: 6, top: 0, bottom: 6 },
|
padding: { left: 6, right: 6, top: 0, bottom: 6 },
|
||||||
indentWidth: 12,
|
indentWidth: 12,
|
||||||
|
@ -94,8 +125,12 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
...entry,
|
...entry,
|
||||||
text: text(layer, "mono", "disabled"),
|
text: text(layer, "mono", "disabled"),
|
||||||
active: {
|
active: {
|
||||||
background: background(layer, "active"),
|
...entry.active,
|
||||||
text: text(layer, "mono", "disabled", { size: "sm" }),
|
default: {
|
||||||
|
...entry.active.default,
|
||||||
|
background: background(layer, "active"),
|
||||||
|
text: text(layer, "mono", "disabled", { size: "sm" }),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
filenameEditor: {
|
filenameEditor: {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
|
|
||||||
export default function search(colorScheme: ColorScheme) {
|
export default function search(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.highest
|
let layer = colorScheme.highest
|
||||||
|
@ -35,36 +36,50 @@ export default function search(colorScheme: ColorScheme) {
|
||||||
return {
|
return {
|
||||||
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
||||||
matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
|
matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
|
||||||
optionButton: {
|
optionButton: toggleable({
|
||||||
...text(layer, "mono", "on"),
|
base: interactive({
|
||||||
background: background(layer, "on"),
|
base: {
|
||||||
cornerRadius: 6,
|
...text(layer, "mono", "on"),
|
||||||
border: border(layer, "on"),
|
background: background(layer, "on"),
|
||||||
margin: {
|
cornerRadius: 6,
|
||||||
right: 4,
|
border: border(layer, "on"),
|
||||||
|
margin: {
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
bottom: 2,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
top: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "mono", "on", "hovered"),
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
border: border(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
...text(layer, "mono", "on", "pressed"),
|
||||||
|
background: background(layer, "on", "pressed"),
|
||||||
|
border: border(layer, "on", "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
...text(layer, "mono", "accent"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "mono", "accent", "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
...text(layer, "mono", "accent", "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
padding: {
|
}),
|
||||||
bottom: 2,
|
|
||||||
left: 10,
|
|
||||||
right: 10,
|
|
||||||
top: 2,
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
...text(layer, "mono", "on", "inverted"),
|
|
||||||
background: background(layer, "on", "inverted"),
|
|
||||||
border: border(layer, "on", "inverted"),
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
...text(layer, "mono", "on", "pressed"),
|
|
||||||
background: background(layer, "on", "pressed"),
|
|
||||||
border: border(layer, "on", "pressed"),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
...text(layer, "mono", "on", "hovered"),
|
|
||||||
background: background(layer, "on", "hovered"),
|
|
||||||
border: border(layer, "on", "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
editor,
|
editor,
|
||||||
invalidEditor: {
|
invalidEditor: {
|
||||||
...editor,
|
...editor,
|
||||||
|
@ -97,17 +112,24 @@ export default function search(colorScheme: ColorScheme) {
|
||||||
...text(layer, "mono", "on"),
|
...text(layer, "mono", "on"),
|
||||||
size: 18,
|
size: 18,
|
||||||
},
|
},
|
||||||
dismissButton: {
|
dismissButton: interactive({
|
||||||
color: foreground(layer, "variant"),
|
base: {
|
||||||
iconWidth: 12,
|
color: foreground(layer, "variant"),
|
||||||
buttonWidth: 14,
|
iconWidth: 12,
|
||||||
padding: {
|
buttonWidth: 14,
|
||||||
left: 10,
|
padding: {
|
||||||
right: 10,
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hover: {
|
state: {
|
||||||
color: foreground(layer, "hovered"),
|
hovered: {
|
||||||
|
color: foreground(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
color: foreground(layer, "pressed"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
|
||||||
const headerPadding = 8
|
const headerPadding = 8
|
||||||
|
|
||||||
|
@ -12,33 +13,41 @@ export default function simpleMessageNotification(
|
||||||
...text(layer, "sans", { size: "xs" }),
|
...text(layer, "sans", { size: "xs" }),
|
||||||
margin: { left: headerPadding, right: headerPadding },
|
margin: { left: headerPadding, right: headerPadding },
|
||||||
},
|
},
|
||||||
actionMessage: {
|
actionMessage: interactive({
|
||||||
...text(layer, "sans", { size: "xs" }),
|
base: {
|
||||||
border: border(layer, "active"),
|
...text(layer, "sans", { size: "xs" }),
|
||||||
cornerRadius: 4,
|
|
||||||
padding: {
|
|
||||||
top: 3,
|
|
||||||
bottom: 3,
|
|
||||||
left: 7,
|
|
||||||
right: 7,
|
|
||||||
},
|
|
||||||
|
|
||||||
margin: { left: headerPadding, top: 6, bottom: 6 },
|
|
||||||
hover: {
|
|
||||||
...text(layer, "sans", "default", { size: "xs" }),
|
|
||||||
background: background(layer, "hovered"),
|
|
||||||
border: border(layer, "active"),
|
border: border(layer, "active"),
|
||||||
|
cornerRadius: 4,
|
||||||
|
padding: {
|
||||||
|
top: 3,
|
||||||
|
bottom: 3,
|
||||||
|
left: 7,
|
||||||
|
right: 7,
|
||||||
|
},
|
||||||
|
|
||||||
|
margin: { left: headerPadding, top: 6, bottom: 6 },
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
dismissButton: {
|
hovered: {
|
||||||
color: foreground(layer),
|
...text(layer, "sans", "default", { size: "xs" }),
|
||||||
iconWidth: 8,
|
background: background(layer, "hovered"),
|
||||||
iconHeight: 8,
|
border: border(layer, "active"),
|
||||||
buttonWidth: 8,
|
},
|
||||||
buttonHeight: 8,
|
|
||||||
hover: {
|
|
||||||
color: foreground(layer, "hovered"),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
|
dismissButton: interactive({
|
||||||
|
base: {
|
||||||
|
color: foreground(layer),
|
||||||
|
iconWidth: 8,
|
||||||
|
iconHeight: 8,
|
||||||
|
buttonWidth: 8,
|
||||||
|
buttonHeight: 8,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: foreground(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
export default function statusBar(colorScheme: ColorScheme) {
|
export default function statusBar(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.lowest
|
let layer = colorScheme.lowest
|
||||||
|
|
||||||
|
@ -25,95 +25,123 @@ export default function statusBar(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
border: border(layer, { top: true, overlay: true }),
|
border: border(layer, { top: true, overlay: true }),
|
||||||
cursorPosition: text(layer, "sans", "variant"),
|
cursorPosition: text(layer, "sans", "variant"),
|
||||||
activeLanguage: {
|
activeLanguage: interactive({
|
||||||
padding: { left: 6, right: 6 },
|
base: {
|
||||||
...text(layer, "sans", "variant"),
|
padding: { left: 6, right: 6 },
|
||||||
hover: {
|
...text(layer, "sans", "variant"),
|
||||||
...text(layer, "sans", "on"),
|
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "sans", "on"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
autoUpdateProgressMessage: text(layer, "sans", "variant"),
|
autoUpdateProgressMessage: text(layer, "sans", "variant"),
|
||||||
autoUpdateDoneMessage: text(layer, "sans", "variant"),
|
autoUpdateDoneMessage: text(layer, "sans", "variant"),
|
||||||
lspStatus: {
|
lspStatus: interactive({
|
||||||
...diagnosticStatusContainer,
|
base: {
|
||||||
iconSpacing: 4,
|
...diagnosticStatusContainer,
|
||||||
iconWidth: 14,
|
iconSpacing: 4,
|
||||||
height: 18,
|
iconWidth: 14,
|
||||||
message: text(layer, "sans"),
|
height: 18,
|
||||||
iconColor: foreground(layer),
|
|
||||||
hover: {
|
|
||||||
message: text(layer, "sans"),
|
message: text(layer, "sans"),
|
||||||
iconColor: foreground(layer),
|
iconColor: foreground(layer),
|
||||||
background: background(layer, "hovered"),
|
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
diagnosticMessage: {
|
hovered: {
|
||||||
...text(layer, "sans"),
|
message: text(layer, "sans"),
|
||||||
hover: text(layer, "sans", "hovered"),
|
iconColor: foreground(layer),
|
||||||
},
|
background: background(layer, "hovered"),
|
||||||
diagnosticSummary: {
|
},
|
||||||
height: 20,
|
|
||||||
iconWidth: 16,
|
|
||||||
iconSpacing: 2,
|
|
||||||
summarySpacing: 6,
|
|
||||||
text: text(layer, "sans", { size: "sm" }),
|
|
||||||
iconColorOk: foreground(layer, "variant"),
|
|
||||||
iconColorWarning: foreground(layer, "warning"),
|
|
||||||
iconColorError: foreground(layer, "negative"),
|
|
||||||
containerOk: {
|
|
||||||
cornerRadius: 6,
|
|
||||||
padding: { top: 3, bottom: 3, left: 7, right: 7 },
|
|
||||||
},
|
},
|
||||||
containerWarning: {
|
}),
|
||||||
...diagnosticStatusContainer,
|
diagnosticMessage: interactive({
|
||||||
background: background(layer, "warning"),
|
base: {
|
||||||
border: border(layer, "warning"),
|
...text(layer, "sans"),
|
||||||
},
|
},
|
||||||
containerError: {
|
state: { hovered: text(layer, "sans", "hovered") },
|
||||||
...diagnosticStatusContainer,
|
}),
|
||||||
background: background(layer, "negative"),
|
diagnosticSummary: interactive({
|
||||||
border: border(layer, "negative"),
|
base: {
|
||||||
},
|
height: 20,
|
||||||
hover: {
|
iconWidth: 16,
|
||||||
iconColorOk: foreground(layer, "on"),
|
iconSpacing: 2,
|
||||||
|
summarySpacing: 6,
|
||||||
|
text: text(layer, "sans", { size: "sm" }),
|
||||||
|
iconColorOk: foreground(layer, "variant"),
|
||||||
|
iconColorWarning: foreground(layer, "warning"),
|
||||||
|
iconColorError: foreground(layer, "negative"),
|
||||||
containerOk: {
|
containerOk: {
|
||||||
cornerRadius: 6,
|
cornerRadius: 6,
|
||||||
padding: { top: 3, bottom: 3, left: 7, right: 7 },
|
padding: { top: 3, bottom: 3, left: 7, right: 7 },
|
||||||
background: background(layer, "on", "hovered"),
|
|
||||||
},
|
},
|
||||||
containerWarning: {
|
containerWarning: {
|
||||||
...diagnosticStatusContainer,
|
...diagnosticStatusContainer,
|
||||||
background: background(layer, "warning", "hovered"),
|
background: background(layer, "warning"),
|
||||||
border: border(layer, "warning", "hovered"),
|
border: border(layer, "warning"),
|
||||||
},
|
},
|
||||||
containerError: {
|
containerError: {
|
||||||
...diagnosticStatusContainer,
|
...diagnosticStatusContainer,
|
||||||
background: background(layer, "negative", "hovered"),
|
background: background(layer, "negative"),
|
||||||
border: border(layer, "negative", "hovered"),
|
border: border(layer, "negative"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
iconColorOk: foreground(layer, "on"),
|
||||||
|
containerOk: {
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
|
containerWarning: {
|
||||||
|
background: background(layer, "warning", "hovered"),
|
||||||
|
border: border(layer, "warning", "hovered"),
|
||||||
|
},
|
||||||
|
containerError: {
|
||||||
|
background: background(layer, "negative", "hovered"),
|
||||||
|
border: border(layer, "negative", "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
panelButtons: {
|
panelButtons: {
|
||||||
groupLeft: {},
|
groupLeft: {},
|
||||||
groupBottom: {},
|
groupBottom: {},
|
||||||
groupRight: {},
|
groupRight: {},
|
||||||
button: {
|
button: toggleable({
|
||||||
...statusContainer,
|
base: interactive({
|
||||||
iconSize: 16,
|
base: {
|
||||||
iconColor: foreground(layer, "variant"),
|
...statusContainer,
|
||||||
label: {
|
iconSize: 16,
|
||||||
margin: { left: 6 },
|
iconColor: foreground(layer, "variant"),
|
||||||
...text(layer, "sans", { size: "sm" }),
|
label: {
|
||||||
|
margin: { left: 6 },
|
||||||
|
...text(layer, "sans", { size: "sm" }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
iconColor: foreground(layer, "hovered"),
|
||||||
|
background: background(layer, "variant"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
iconColor: foreground(layer, "active"),
|
||||||
|
background: background(layer, "active"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
iconColor: foreground(layer, "hovered"),
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
iconColor: foreground(layer, "pressed"),
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hover: {
|
}),
|
||||||
iconColor: foreground(layer, "hovered"),
|
|
||||||
background: background(layer, "variant"),
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
iconColor: foreground(layer, "active"),
|
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
badge: {
|
badge: {
|
||||||
cornerRadius: 3,
|
cornerRadius: 3,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { text, border, background, foreground } from "./components"
|
import { text, border, background, foreground } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
|
|
||||||
export default function tabBar(colorScheme: ColorScheme) {
|
export default function tabBar(colorScheme: ColorScheme) {
|
||||||
const height = 32
|
const height = 32
|
||||||
|
@ -87,17 +88,36 @@ export default function tabBar(colorScheme: ColorScheme) {
|
||||||
inactiveTab: inactivePaneInactiveTab,
|
inactiveTab: inactivePaneInactiveTab,
|
||||||
},
|
},
|
||||||
draggedTab,
|
draggedTab,
|
||||||
paneButton: {
|
paneButton: toggleable({
|
||||||
color: foreground(layer, "variant"),
|
base: interactive({
|
||||||
iconWidth: 12,
|
base: {
|
||||||
buttonWidth: activePaneActiveTab.height,
|
color: foreground(layer, "variant"),
|
||||||
hover: {
|
iconWidth: 12,
|
||||||
color: foreground(layer, "hovered"),
|
buttonWidth: activePaneActiveTab.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"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
}),
|
||||||
color: foreground(layer, "accent"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
paneButtonContainer: {
|
paneButtonContainer: {
|
||||||
background: tab.background,
|
background: tab.background,
|
||||||
border: {
|
border: {
|
||||||
|
|
47
styles/src/styleTree/toggle.ts
Normal file
47
styles/src/styleTree/toggle.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import merge from "ts-deepmerge"
|
||||||
|
|
||||||
|
type ToggleState = "inactive" | "active"
|
||||||
|
|
||||||
|
type Toggleable<T> = Record<ToggleState, T>
|
||||||
|
|
||||||
|
const NO_INACTIVE_OR_BASE_ERROR =
|
||||||
|
"A toggleable object must have an inactive state, or a base property."
|
||||||
|
const NO_ACTIVE_ERROR = "A toggleable object must have an active state."
|
||||||
|
|
||||||
|
interface ToggleableProps<T> {
|
||||||
|
base?: T
|
||||||
|
state: Partial<Record<ToggleState, 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 inactiveState = base
|
||||||
|
? ((state.inactive ? merge(base, state.inactive) : base) as T)
|
||||||
|
: (state.inactive as T)
|
||||||
|
|
||||||
|
const toggleObj: Toggleable<T> = {
|
||||||
|
inactive: inactiveState,
|
||||||
|
active: merge(base ?? {}, state.active) as T,
|
||||||
|
}
|
||||||
|
|
||||||
|
return toggleObj
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
import { interactive, toggleable } from "../element"
|
||||||
export default function dropdownMenu(colorScheme: ColorScheme) {
|
export default function dropdownMenu(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.middle
|
let layer = colorScheme.middle
|
||||||
|
|
||||||
|
@ -9,38 +9,56 @@ export default function dropdownMenu(colorScheme: ColorScheme) {
|
||||||
background: background(layer),
|
background: background(layer),
|
||||||
border: border(layer),
|
border: border(layer),
|
||||||
shadow: colorScheme.popoverShadow,
|
shadow: colorScheme.popoverShadow,
|
||||||
header: {
|
header: interactive({
|
||||||
...text(layer, "sans", { size: "sm" }),
|
base: {
|
||||||
secondaryText: text(layer, "sans", { size: "sm", color: "#aaaaaa" }),
|
...text(layer, "sans", { size: "sm" }),
|
||||||
secondaryTextSpacing: 10,
|
secondaryText: text(layer, "sans", {
|
||||||
padding: { left: 8, right: 8, top: 2, bottom: 2 },
|
size: "sm",
|
||||||
cornerRadius: 6,
|
color: "#aaaaaa",
|
||||||
background: background(layer, "on"),
|
}),
|
||||||
border: border(layer, "on", { overlay: true }),
|
secondaryTextSpacing: 10,
|
||||||
hover: {
|
padding: { left: 8, right: 8, top: 2, bottom: 2 },
|
||||||
background: background(layer, "hovered"),
|
cornerRadius: 6,
|
||||||
...text(layer, "sans", "hovered", { size: "sm" }),
|
background: background(layer, "on"),
|
||||||
}
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
sectionHeader: {
|
sectionHeader: {
|
||||||
...text(layer, "sans", { size: "sm" }),
|
...text(layer, "sans", { size: "sm" }),
|
||||||
padding: { left: 8, right: 8, top: 8, bottom: 8 },
|
padding: { left: 8, right: 8, top: 8, bottom: 8 },
|
||||||
},
|
},
|
||||||
item: {
|
item: toggleable({
|
||||||
...text(layer, "sans", { size: "sm" }),
|
base: interactive({
|
||||||
secondaryTextSpacing: 10,
|
base: {
|
||||||
secondaryText: text(layer, "sans", { size: "sm" }),
|
...text(layer, "sans", { size: "sm" }),
|
||||||
padding: { left: 18, right: 18, top: 2, bottom: 2 },
|
secondaryTextSpacing: 10,
|
||||||
hover: {
|
secondaryText: text(layer, "sans", { size: "sm" }),
|
||||||
background: background(layer, "hovered"),
|
padding: { left: 18, right: 18, top: 2, bottom: 2 },
|
||||||
...text(layer, "sans", "hovered", { size: "sm" }),
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
...text(layer, "sans", "hovered", { size: "sm" }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
background: background(layer, "active"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
}),
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
activeHover: {
|
|
||||||
background: background(layer, "active"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { foreground, text } from "./components"
|
import { foreground, text } from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
|
||||||
const headerPadding = 8
|
const headerPadding = 8
|
||||||
|
|
||||||
|
@ -10,22 +11,30 @@ export default function updateNotification(colorScheme: ColorScheme): Object {
|
||||||
...text(layer, "sans", { size: "xs" }),
|
...text(layer, "sans", { size: "xs" }),
|
||||||
margin: { left: headerPadding, right: headerPadding },
|
margin: { left: headerPadding, right: headerPadding },
|
||||||
},
|
},
|
||||||
actionMessage: {
|
actionMessage: interactive({
|
||||||
...text(layer, "sans", { size: "xs" }),
|
base: {
|
||||||
margin: { left: headerPadding, top: 6, bottom: 6 },
|
...text(layer, "sans", { size: "xs" }),
|
||||||
hover: {
|
margin: { left: headerPadding, top: 6, bottom: 6 },
|
||||||
color: foreground(layer, "hovered"),
|
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
dismissButton: {
|
hovered: {
|
||||||
color: foreground(layer),
|
color: foreground(layer, "hovered"),
|
||||||
iconWidth: 8,
|
},
|
||||||
iconHeight: 8,
|
|
||||||
buttonWidth: 8,
|
|
||||||
buttonHeight: 8,
|
|
||||||
hover: {
|
|
||||||
color: foreground(layer, "hovered"),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
|
dismissButton: interactive({
|
||||||
|
base: {
|
||||||
|
color: foreground(layer),
|
||||||
|
iconWidth: 8,
|
||||||
|
iconHeight: 8,
|
||||||
|
buttonWidth: 8,
|
||||||
|
buttonHeight: 8,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: foreground(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
TextProperties,
|
TextProperties,
|
||||||
svg,
|
svg,
|
||||||
} from "./components"
|
} from "./components"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
|
||||||
export default function welcome(colorScheme: ColorScheme) {
|
export default function welcome(colorScheme: ColorScheme) {
|
||||||
let layer = colorScheme.highest
|
let layer = colorScheme.highest
|
||||||
|
@ -63,27 +64,31 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||||
bottom: 2,
|
bottom: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
button: {
|
button: interactive({
|
||||||
background: background(layer),
|
base: {
|
||||||
border: border(layer, "active"),
|
background: background(layer),
|
||||||
cornerRadius: 4,
|
|
||||||
margin: {
|
|
||||||
top: 4,
|
|
||||||
bottom: 4,
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
top: 3,
|
|
||||||
bottom: 3,
|
|
||||||
left: 7,
|
|
||||||
right: 7,
|
|
||||||
},
|
|
||||||
...text(layer, "sans", "default", interactive_text_size),
|
|
||||||
hover: {
|
|
||||||
...text(layer, "sans", "default", interactive_text_size),
|
|
||||||
background: background(layer, "hovered"),
|
|
||||||
border: border(layer, "active"),
|
border: border(layer, "active"),
|
||||||
|
cornerRadius: 4,
|
||||||
|
margin: {
|
||||||
|
top: 4,
|
||||||
|
bottom: 4,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
top: 3,
|
||||||
|
bottom: 3,
|
||||||
|
left: 7,
|
||||||
|
right: 7,
|
||||||
|
},
|
||||||
|
...text(layer, "sans", "default", interactive_text_size),
|
||||||
},
|
},
|
||||||
},
|
state: {
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "sans", "default", interactive_text_size),
|
||||||
|
background: background(layer, "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
usageNote: {
|
usageNote: {
|
||||||
...text(layer, "sans", "variant", { size: "2xs" }),
|
...text(layer, "sans", "variant", { size: "2xs" }),
|
||||||
padding: {
|
padding: {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ColorScheme } from "../theme/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../theme/color"
|
import { withOpacity } from "../theme/color"
|
||||||
|
import { toggleable } from "../element"
|
||||||
import {
|
import {
|
||||||
background,
|
background,
|
||||||
border,
|
border,
|
||||||
|
@ -10,38 +11,53 @@ import {
|
||||||
} from "./components"
|
} from "./components"
|
||||||
import statusBar from "./statusBar"
|
import statusBar from "./statusBar"
|
||||||
import tabBar from "./tabBar"
|
import tabBar from "./tabBar"
|
||||||
|
import { interactive } from "../element"
|
||||||
|
import merge from "ts-deepmerge"
|
||||||
export default function workspace(colorScheme: ColorScheme) {
|
export default function workspace(colorScheme: ColorScheme) {
|
||||||
const layer = colorScheme.lowest
|
const layer = colorScheme.lowest
|
||||||
const isLight = colorScheme.isLight
|
const isLight = colorScheme.isLight
|
||||||
const itemSpacing = 8
|
const itemSpacing = 8
|
||||||
const titlebarButton = {
|
const titlebarButton = toggleable({
|
||||||
cornerRadius: 6,
|
base: interactive({
|
||||||
padding: {
|
base: {
|
||||||
top: 1,
|
cornerRadius: 6,
|
||||||
bottom: 1,
|
padding: {
|
||||||
left: 8,
|
top: 1,
|
||||||
right: 8,
|
bottom: 1,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
},
|
||||||
|
...text(layer, "sans", "variant", { size: "xs" }),
|
||||||
|
background: background(layer, "variant"),
|
||||||
|
border: border(layer),
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
...text(layer, "sans", "variant", "hovered", {
|
||||||
|
size: "xs",
|
||||||
|
}),
|
||||||
|
background: background(layer, "variant", "hovered"),
|
||||||
|
border: border(layer, "variant", "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
...text(layer, "sans", "variant", "pressed", {
|
||||||
|
size: "xs",
|
||||||
|
}),
|
||||||
|
background: background(layer, "variant", "pressed"),
|
||||||
|
border: border(layer, "variant", "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
...text(layer, "sans", "variant", "active", { size: "xs" }),
|
||||||
|
background: background(layer, "variant", "active"),
|
||||||
|
border: border(layer, "variant", "active"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
...text(layer, "sans", "variant", { size: "xs" }),
|
})
|
||||||
background: background(layer, "variant"),
|
|
||||||
border: border(layer),
|
|
||||||
hover: {
|
|
||||||
...text(layer, "sans", "variant", "hovered", { size: "xs" }),
|
|
||||||
background: background(layer, "variant", "hovered"),
|
|
||||||
border: border(layer, "variant", "hovered"),
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
...text(layer, "sans", "variant", "pressed", { size: "xs" }),
|
|
||||||
background: background(layer, "variant", "pressed"),
|
|
||||||
border: border(layer, "variant", "pressed"),
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
...text(layer, "sans", "variant", "active", { size: "xs" }),
|
|
||||||
background: background(layer, "variant", "active"),
|
|
||||||
border: border(layer, "variant", "active"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const avatarWidth = 18
|
const avatarWidth = 18
|
||||||
const avatarOuterWidth = avatarWidth + 4
|
const avatarOuterWidth = avatarWidth + 4
|
||||||
const followerAvatarWidth = 14
|
const followerAvatarWidth = 14
|
||||||
|
@ -78,19 +94,24 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
cornerRadius: 4,
|
cornerRadius: 4,
|
||||||
},
|
},
|
||||||
keyboardHint: {
|
keyboardHint: interactive({
|
||||||
...text(layer, "sans", "variant", { size: "sm" }),
|
base: {
|
||||||
padding: {
|
...text(layer, "sans", "variant", { size: "sm" }),
|
||||||
top: 3,
|
padding: {
|
||||||
left: 8,
|
top: 3,
|
||||||
right: 8,
|
left: 8,
|
||||||
bottom: 3,
|
right: 8,
|
||||||
|
bottom: 3,
|
||||||
|
},
|
||||||
|
cornerRadius: 8,
|
||||||
},
|
},
|
||||||
cornerRadius: 8,
|
state: {
|
||||||
hover: {
|
hovered: {
|
||||||
...text(layer, "sans", "active", { size: "sm" }),
|
...text(layer, "sans", "active", { size: "sm" }),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
|
|
||||||
keyboardHintWidth: 320,
|
keyboardHintWidth: 320,
|
||||||
},
|
},
|
||||||
joiningProjectAvatar: {
|
joiningProjectAvatar: {
|
||||||
|
@ -201,12 +222,15 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
|
|
||||||
// Sign in buttom
|
// Sign in buttom
|
||||||
// FlatButton, Variant
|
// FlatButton, Variant
|
||||||
signInPrompt: {
|
signInPrompt: merge(titlebarButton, {
|
||||||
margin: {
|
inactive: {
|
||||||
left: itemSpacing,
|
default: {
|
||||||
|
margin: {
|
||||||
|
left: itemSpacing,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
...titlebarButton,
|
}),
|
||||||
},
|
|
||||||
|
|
||||||
// Offline Indicator
|
// Offline Indicator
|
||||||
offlineIcon: {
|
offlineIcon: {
|
||||||
|
@ -234,40 +258,68 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
cornerRadius: 6,
|
cornerRadius: 6,
|
||||||
},
|
},
|
||||||
callControl: {
|
callControl: interactive({
|
||||||
cornerRadius: 6,
|
base: {
|
||||||
color: foreground(layer, "variant"),
|
cornerRadius: 6,
|
||||||
iconWidth: 12,
|
color: foreground(layer, "variant"),
|
||||||
buttonWidth: 20,
|
iconWidth: 12,
|
||||||
hover: {
|
buttonWidth: 20,
|
||||||
background: background(layer, "variant", "hovered"),
|
},
|
||||||
color: foreground(layer, "variant", "hovered"),
|
state: {
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "variant", "hovered"),
|
||||||
|
color: foreground(layer, "variant", "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
toggleContactsButton: toggleable({
|
||||||
|
base: interactive({
|
||||||
|
base: {
|
||||||
|
margin: { left: itemSpacing },
|
||||||
|
cornerRadius: 6,
|
||||||
|
color: foreground(layer, "variant"),
|
||||||
|
iconWidth: 14,
|
||||||
|
buttonWidth: 20,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "variant", "pressed"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "variant", "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
state: {
|
||||||
|
active: {
|
||||||
|
default: {
|
||||||
|
background: background(layer, "on", "default"),
|
||||||
|
},
|
||||||
|
hovered: {
|
||||||
|
background: background(layer, "on", "hovered"),
|
||||||
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "on", "pressed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
userMenuButton: merge(titlebarButton, {
|
||||||
|
inactive: {
|
||||||
|
default: {
|
||||||
|
buttonWidth: 20,
|
||||||
|
iconWidth: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
toggleContactsButton: {
|
|
||||||
margin: { left: itemSpacing },
|
|
||||||
cornerRadius: 6,
|
|
||||||
color: foreground(layer, "variant"),
|
|
||||||
iconWidth: 14,
|
|
||||||
buttonWidth: 20,
|
|
||||||
active: {
|
active: {
|
||||||
background: background(layer, "variant", "active"),
|
// posiewic: these properties are not currently set on main
|
||||||
color: foreground(layer, "variant", "active"),
|
default: {
|
||||||
|
iconWidth: 12,
|
||||||
|
button_width: 20,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
}),
|
||||||
background: background(layer, "variant", "pressed"),
|
|
||||||
color: foreground(layer, "variant", "pressed"),
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
background: background(layer, "variant", "hovered"),
|
|
||||||
color: foreground(layer, "variant", "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
userMenuButton: {
|
|
||||||
buttonWidth: 20,
|
|
||||||
iconWidth: 12,
|
|
||||||
...titlebarButton,
|
|
||||||
},
|
|
||||||
toggleContactsBadge: {
|
toggleContactsBadge: {
|
||||||
cornerRadius: 3,
|
cornerRadius: 3,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
|
@ -285,12 +337,45 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
background: background(colorScheme.highest),
|
background: background(colorScheme.highest),
|
||||||
border: border(colorScheme.highest, { bottom: true }),
|
border: border(colorScheme.highest, { bottom: true }),
|
||||||
itemSpacing: 8,
|
itemSpacing: 8,
|
||||||
navButton: {
|
navButton: interactive({
|
||||||
color: foreground(colorScheme.highest, "on"),
|
base: {
|
||||||
iconWidth: 12,
|
color: foreground(colorScheme.highest, "on"),
|
||||||
buttonWidth: 24,
|
iconWidth: 12,
|
||||||
|
buttonWidth: 24,
|
||||||
|
cornerRadius: 6,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: foreground(colorScheme.highest, "on", "hovered"),
|
||||||
|
background: background(
|
||||||
|
colorScheme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
color: foreground(
|
||||||
|
colorScheme.highest,
|
||||||
|
"on",
|
||||||
|
"disabled"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
||||||
|
},
|
||||||
|
breadcrumbHeight: 24,
|
||||||
|
breadcrumbs: interactive({
|
||||||
|
base: {
|
||||||
|
...text(colorScheme.highest, "sans", "variant"),
|
||||||
cornerRadius: 6,
|
cornerRadius: 6,
|
||||||
hover: {
|
padding: {
|
||||||
|
left: 6,
|
||||||
|
right: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
color: foreground(colorScheme.highest, "on", "hovered"),
|
color: foreground(colorScheme.highest, "on", "hovered"),
|
||||||
background: background(
|
background: background(
|
||||||
colorScheme.highest,
|
colorScheme.highest,
|
||||||
|
@ -298,25 +383,8 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
"hovered"
|
"hovered"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
disabled: {
|
|
||||||
color: foreground(colorScheme.highest, "on", "disabled"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
}),
|
||||||
},
|
|
||||||
breadcrumbHeight: 24,
|
|
||||||
breadcrumbs: {
|
|
||||||
...text(colorScheme.highest, "sans", "variant"),
|
|
||||||
cornerRadius: 6,
|
|
||||||
padding: {
|
|
||||||
left: 6,
|
|
||||||
right: 6,
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
color: foreground(colorScheme.highest, "on", "hovered"),
|
|
||||||
background: background(colorScheme.highest, "on", "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
disconnectedOverlay: {
|
disconnectedOverlay: {
|
||||||
...text(layer, "sans"),
|
...text(layer, "sans"),
|
||||||
background: withOpacity(background(layer), 0.8),
|
background: withOpacity(background(layer), 0.8),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue