diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..20a2377 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,8 @@ +[advisories] +# quick-xml is pinned by vendored wayland-scanner and zed-scap; compatible refresh is blocked upstream. +# crossbeam-epoch is pinned by the vendored Zed snapshot; compatible refresh is blocked upstream. +ignore = [ + "RUSTSEC-2026-0194", + "RUSTSEC-2026-0195", + "RUSTSEC-2026-0204", +] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 437006b..2a7d382 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,22 @@ jobs: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 - uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 with: - command: check licenses bans + command: check advisories licenses bans sources + + # Keep cargo-audit output visible while the pinned vendored snapshot carries + # the advisories recorded in deny.toml. This is informational until the + # dependency refresh removes those exceptions. + audit: + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + - uses: dtolnay/rust-toolchain@d124f86f28ff42855784ff3319f48ac182c248f8 + - uses: taiki-e/install-action@97888a140839b7239d62fbf6af4e20adb5be3666 + with: + tool: cargo-audit + - name: Cargo audit + run: cargo audit # fluent-* zed-rev metadata equals vendor/zed/UPSTREAM.md (CONTRIBUTING.md §4). zed-rev: @@ -105,7 +120,7 @@ jobs: # The one required check: Windows and Linux tests plus every guard. ci: if: always() - needs: [test, examples-and-docs, layering, deny, zed-rev] + needs: [test, examples-and-docs, layering, deny, audit, zed-rev] runs-on: ubuntu-latest steps: - name: All jobs passed diff --git a/Cargo.lock b/Cargo.lock index b59ae5f..d3e6479 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,9 +173,9 @@ checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "arbitrary" @@ -1411,11 +1411,10 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite", ] @@ -1815,6 +1814,7 @@ dependencies = [ "fluent-app", "fluent-core", "fluent-layout", + "fluent-primitives", "fluent-ribbon", ] @@ -2912,9 +2912,9 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -4949,9 +4949,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.2" +version = "1.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e" dependencies = [ "pin-project-lite", ] diff --git a/crates/fluent-app/src/app_builder.rs b/crates/fluent-app/src/app_builder.rs index 24a151d..ce34984 100644 --- a/crates/fluent-app/src/app_builder.rs +++ b/crates/fluent-app/src/app_builder.rs @@ -81,6 +81,7 @@ pub struct FluentApp { } impl FluentApp { + /// Public API item. pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -95,12 +96,14 @@ impl FluentApp { } } + /// Public API item. pub fn window_size(mut self, w: f32, h: f32) -> Self { self.window_w = w; self.window_h = h; self } + /// Public API item. pub fn window_min_size(mut self, w: f32, h: f32) -> Self { self.window_min_size = Some((w, h)); self @@ -129,11 +132,13 @@ impl FluentApp { self } + /// Public API item. pub fn dark_theme(mut self) -> Self { self.theme_mode = ThemeMode::Dark; self } + /// Public API item. pub fn light_theme(mut self) -> Self { self.theme_mode = ThemeMode::Light; self @@ -145,6 +150,7 @@ impl FluentApp { self } + /// Public API item. pub fn assets(mut self, assets: impl AssetSource) -> Self { self.assets = Some(Arc::new(assets)); self diff --git a/crates/fluent-app/src/assets.rs b/crates/fluent-app/src/assets.rs index f93ac3a..91ecbb0 100644 --- a/crates/fluent-app/src/assets.rs +++ b/crates/fluent-app/src/assets.rs @@ -67,6 +67,7 @@ pub struct FluentAssets { } impl FluentAssets { + /// Public API item. pub fn new(fallback: Option>) -> Self { Self { fallback } } diff --git a/crates/fluent-app/src/chrome.rs b/crates/fluent-app/src/chrome.rs index ce1b25d..b72536e 100644 --- a/crates/fluent-app/src/chrome.rs +++ b/crates/fluent-app/src/chrome.rs @@ -21,6 +21,7 @@ pub struct WindowChrome { } impl WindowChrome { + /// Public API item. pub fn new(content: Entity) -> Self { Self { content } } diff --git a/crates/fluent-app/src/lib.rs b/crates/fluent-app/src/lib.rs index 5afa14e..0e04e59 100644 --- a/crates/fluent-app/src/lib.rs +++ b/crates/fluent-app/src/lib.rs @@ -1,3 +1,6 @@ +//! Public API for this crate. +#![deny(missing_docs)] + mod app_builder; mod assets; mod chrome; diff --git a/crates/fluent-app/src/pickers.rs b/crates/fluent-app/src/pickers.rs index 9cc4056..959fb63 100644 --- a/crates/fluent-app/src/pickers.rs +++ b/crates/fluent-app/src/pickers.rs @@ -19,6 +19,7 @@ pub struct ExtensionFilter { } impl ExtensionFilter { + /// Public API item. pub fn new( label: impl Into, extensions: impl IntoIterator>, @@ -34,10 +35,12 @@ impl ExtensionFilter { } } + /// Public API item. pub fn label(&self) -> &SharedString { &self.label } + /// Public API item. pub fn extensions(&self) -> &[String] { &self.extensions } @@ -161,6 +164,7 @@ pub struct FilePickerField { } impl FilePickerField { + /// Public API item. pub fn new(id: impl Into) -> Self { Self { id: id.into(), @@ -172,26 +176,31 @@ impl FilePickerField { } } + /// Public API item. pub fn path(mut self, path: impl Into) -> Self { self.path = Some(path.into()); self } + /// Public API item. pub fn placeholder(mut self, placeholder: impl Into) -> Self { self.placeholder = placeholder.into(); self } + /// Public API item. pub fn browse_label(mut self, label: impl Into) -> Self { self.browse_label = label.into(); self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn on_browse( mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-app/src/title_bar.rs b/crates/fluent-app/src/title_bar.rs index 7a7af07..1dc7bcd 100644 --- a/crates/fluent-app/src/title_bar.rs +++ b/crates/fluent-app/src/title_bar.rs @@ -16,14 +16,18 @@ const DOUBLE_CLICK_WINDOW_MS: u64 = 350; /// window controls (min/max/close) on the right. Enable frameless mode with /// `TitlebarOptions { appears_transparent: true }` + `WindowDecorations::Client`. pub struct TitleBar { + /// Public API item. pub title: SharedString, + /// Public API item. pub icon: Option, + /// Public API item. pub show_controls: bool, follow_window_title: bool, last_press_ms: u64, } impl TitleBar { + /// Public API item. pub fn new(cx: &mut Context, title: impl Into) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) @@ -39,6 +43,7 @@ impl TitleBar { } } + /// Public API item. pub fn from_window_title(cx: &mut Context) -> Self { let title = cx .try_global::() @@ -48,17 +53,20 @@ impl TitleBar { Self::new(cx, title).follow_window_title(true) } + /// Public API item. pub fn set_title(&mut self, title: impl Into, cx: &mut Context) { self.title = title.into(); self.follow_window_title = false; cx.notify(); } + /// Public API item. pub fn show_controls(mut self, show: bool) -> Self { self.show_controls = show; self } + /// Public API item. pub fn follow_window_title(mut self, follow: bool) -> Self { self.follow_window_title = follow; self diff --git a/crates/fluent-app/src/window_title.rs b/crates/fluent-app/src/window_title.rs index 247cd7b..0e4e2f6 100644 --- a/crates/fluent-app/src/window_title.rs +++ b/crates/fluent-app/src/window_title.rs @@ -13,6 +13,7 @@ pub struct WindowTitle { impl Global for WindowTitle {} impl WindowTitle { + /// Public API item. pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -20,23 +21,28 @@ impl WindowTitle { } } + /// Public API item. pub fn with_status(mut self, status: impl Into) -> Self { self.status = Some(status.into()); self } + /// Public API item. pub fn title(&self) -> &SharedString { &self.title } + /// Public API item. pub fn status(&self) -> Option<&SharedString> { self.status.as_ref() } + /// Public API item. pub fn init(cx: &mut App, title: impl Into) { cx.set_global(Self::new(title)); } + /// Public API item. pub fn set_title(cx: &mut App, title: impl Into) { if cx.has_global::() { cx.global_mut::().title = title.into(); @@ -45,6 +51,7 @@ impl WindowTitle { } } + /// Public API item. pub fn set_status(cx: &mut App, status: impl Into) { if cx.has_global::() { cx.global_mut::().status = Some(status.into()); @@ -53,6 +60,7 @@ impl WindowTitle { } } + /// Public API item. pub fn clear_status(cx: &mut App) { if cx.has_global::() { cx.global_mut::().status = None; diff --git a/crates/fluent-core/src/async_resource.rs b/crates/fluent-core/src/async_resource.rs index 9ee41cc..860c160 100644 --- a/crates/fluent-core/src/async_resource.rs +++ b/crates/fluent-core/src/async_resource.rs @@ -1,33 +1,48 @@ #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +/// Public API item. pub struct ResourceRequest { generation: u64, } impl ResourceRequest { + /// Public API item. pub fn generation(self) -> u64 { self.generation } } #[derive(Clone, Debug, PartialEq, Eq)] +/// Public API item. pub enum AsyncResourceState { + /// Public API item. Idle, + /// Public API item. Loading { + /// Public API item. request: ResourceRequest, + /// Public API item. previous: Option, }, + /// Public API item. Ready { + /// Public API item. request: ResourceRequest, + /// Public API item. value: T, }, + /// Public API item. Error { + /// Public API item. request: ResourceRequest, + /// Public API item. error: E, + /// Public API item. previous: Option, }, } #[derive(Clone, Debug, PartialEq, Eq)] +/// Public API item. pub struct AsyncResource { generation: u64, state: AsyncResourceState, @@ -40,6 +55,7 @@ impl Default for AsyncResource { } impl AsyncResource { + /// Public API item. pub fn new() -> Self { Self { generation: 0, @@ -47,6 +63,7 @@ impl AsyncResource { } } + /// Public API item. pub fn ready(value: T) -> Self { let request = ResourceRequest { generation: 1 }; Self { @@ -55,6 +72,7 @@ impl AsyncResource { } } + /// Public API item. pub fn failed(error: E) -> Self { let request = ResourceRequest { generation: 1 }; Self { @@ -67,14 +85,17 @@ impl AsyncResource { } } + /// Public API item. pub fn state(&self) -> &AsyncResourceState { &self.state } + /// Public API item. pub fn generation(&self) -> u64 { self.generation } + /// Public API item. pub fn current_request(&self) -> Option { match &self.state { AsyncResourceState::Idle => None, @@ -84,6 +105,7 @@ impl AsyncResource { } } + /// Public API item. pub fn begin_load(&mut self) -> ResourceRequest { let request = self.next_request(); let previous = match std::mem::replace(&mut self.state, AsyncResourceState::Idle) { @@ -97,10 +119,12 @@ impl AsyncResource { request } + /// Public API item. pub fn refresh(&mut self) -> ResourceRequest { self.begin_load() } + /// Public API item. pub fn resolve(&mut self, request: ResourceRequest, value: T) -> bool { if !self.accepts(request) { return false; @@ -110,6 +134,7 @@ impl AsyncResource { true } + /// Public API item. pub fn reject(&mut self, request: ResourceRequest, error: E) -> bool { if !self.accepts(request) { return false; @@ -130,27 +155,33 @@ impl AsyncResource { true } + /// Public API item. pub fn reset(&mut self) { self.generation = 0; self.state = AsyncResourceState::Idle; } + /// Public API item. pub fn is_idle(&self) -> bool { matches!(self.state, AsyncResourceState::Idle) } + /// Public API item. pub fn is_loading(&self) -> bool { matches!(self.state, AsyncResourceState::Loading { .. }) } + /// Public API item. pub fn is_ready(&self) -> bool { matches!(self.state, AsyncResourceState::Ready { .. }) } + /// Public API item. pub fn is_error(&self) -> bool { matches!(self.state, AsyncResourceState::Error { .. }) } + /// Public API item. pub fn value(&self) -> Option<&T> { match &self.state { AsyncResourceState::Ready { value, .. } => Some(value), @@ -160,6 +191,7 @@ impl AsyncResource { } } + /// Public API item. pub fn ready_value(&self) -> Option<&T> { match &self.state { AsyncResourceState::Ready { value, .. } => Some(value), @@ -167,6 +199,7 @@ impl AsyncResource { } } + /// Public API item. pub fn error(&self) -> Option<&E> { match &self.state { AsyncResourceState::Error { error, .. } => Some(error), @@ -174,6 +207,7 @@ impl AsyncResource { } } + /// Public API item. pub fn accepts(&self, request: ResourceRequest) -> bool { matches!( &self.state, diff --git a/crates/fluent-core/src/colors.rs b/crates/fluent-core/src/colors.rs index fba63bb..7bd60a7 100644 --- a/crates/fluent-core/src/colors.rs +++ b/crates/fluent-core/src/colors.rs @@ -60,7 +60,9 @@ pub fn with_alpha(color: Hsla, alpha: f32) -> Hsla { /// choosing tokens themselves. #[derive(Clone, Copy, Debug, PartialEq)] pub struct ControlStates { + /// Public API item. pub background: NeutralColorStates, + /// Public API item. pub foreground: NeutralColorStates, } @@ -70,23 +72,38 @@ pub struct ControlStates { /// See for specification. #[derive(Clone, Copy, Debug, PartialEq)] pub struct NeutralColorStates { + /// Public API item. pub default: Hsla, + /// Public API item. pub hover: Hsla, + /// Public API item. pub pressed: Hsla, + /// Public API item. pub selected: Hsla, + /// Public API item. pub disabled: Hsla, } #[derive(Clone, Debug)] +/// Public API item. pub struct ColorScheme { + /// Public API item. pub neutral_foreground_1: NeutralColorStates, + /// Public API item. pub neutral_foreground_2: NeutralColorStates, + /// Public API item. pub neutral_foreground_3: NeutralColorStates, + /// Public API item. pub neutral_background_1: NeutralColorStates, + /// Public API item. pub neutral_background_2: NeutralColorStates, + /// Public API item. pub neutral_background_3: NeutralColorStates, + /// Public API item. pub neutral_stroke_1: NeutralColorStates, + /// Public API item. pub neutral_stroke_2: NeutralColorStates, + /// Public API item. pub neutral_stroke_3: NeutralColorStates, // --- Fill backgrounds (interactive elements: buttons, inputs, etc.) --- diff --git a/crates/fluent-core/src/components.rs b/crates/fluent-core/src/components.rs index 5fa5eb4..9366f85 100644 --- a/crates/fluent-core/src/components.rs +++ b/crates/fluent-core/src/components.rs @@ -7,41 +7,75 @@ pub struct ComponentTokens { /// Fluent 2 button heights for small, medium, and large controls. pub button_small_height: f32, + /// Public API item. pub button_medium_height: f32, + /// Public API item. pub button_large_height: f32, /// Fluent 2 button icon sizes for small, medium, and large controls. pub button_small_icon_size: f32, + /// Public API item. pub button_medium_icon_size: f32, + /// Public API item. pub button_large_icon_size: f32, + /// Public API item. pub menu_bar_height: f32, + /// Public API item. pub menu_item_height: f32, + /// Public API item. pub menu_min_width: f32, + /// Public API item. pub popup_icon_slot: f32, + /// Public API item. pub popup_separator_height: f32, + /// Public API item. pub dropdown_height: f32, + /// Public API item. pub dropdown_option_height: f32, + /// Public API item. pub dropdown_min_width: f32, + /// Public API item. pub dropdown_max_height: f32, + /// Public API item. pub text_input_height: f32, + /// Public API item. pub text_input_focus_indicator_height: f32, + /// Public API item. pub dock_header_height: f32, + /// Public API item. pub dock_action_size: f32, + /// Public API item. pub settings_nav_width: f32, + /// Public API item. pub settings_nav_section_height: f32, + /// Public API item. pub settings_nav_item_height: f32, + /// Public API item. pub settings_nav_accent_width: f32, + /// Public API item. pub settings_nav_item_indent: f32, + /// Public API item. pub command_palette_search_height: f32, + /// Public API item. pub command_palette_footer_height: f32, + /// Public API item. pub command_palette_icon_slot: f32, + /// Public API item. pub content_tab_strip_height: f32, + /// Public API item. pub content_tab_icon_size: f32, + /// Public API item. pub content_tab_close_size: f32, + /// Public API item. pub ribbon_tab_height: f32, + /// Public API item. pub ribbon_content_button_height: f32, + /// Public API item. pub ribbon_group_label_height: f32, + /// Public API item. pub ribbon_large_icon_size: f32, + /// Public API item. pub ribbon_small_icon_size: f32, + /// Public API item. pub ribbon_contextual_band_height: f32, } diff --git a/crates/fluent-core/src/lib.rs b/crates/fluent-core/src/lib.rs index cb736a0..3444185 100644 --- a/crates/fluent-core/src/lib.rs +++ b/crates/fluent-core/src/lib.rs @@ -1,3 +1,6 @@ +//! Public API for the Fluent UI crate. +#![deny(missing_docs)] + mod async_resource; mod colors; mod components; diff --git a/crates/fluent-core/src/motion.rs b/crates/fluent-core/src/motion.rs index dafc391..11649ea 100644 --- a/crates/fluent-core/src/motion.rs +++ b/crates/fluent-core/src/motion.rs @@ -11,59 +11,84 @@ use gpui::{ /// and should not draw attention away from the command being performed. #[derive(Clone, Copy, Debug, PartialEq)] pub struct MotionCurve { + /// Public API item. pub x1: f32, + /// Public API item. pub y1: f32, + /// Public API item. pub x2: f32, + /// Public API item. pub y2: f32, } impl MotionCurve { + /// Public API item. pub const fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self { Self { x1, y1, x2, y2 } } } #[derive(Clone, Copy, Debug, PartialEq)] +/// Public API item. pub struct MotionTokens { + /// Public API item. pub accelerate: MotionCurve, + /// Public API item. pub decelerate: MotionCurve, + /// Public API item. pub easy_ease: MotionCurve, + /// Public API item. pub ultra_fast_duration_ms: u64, + /// Public API item. pub fast_duration_ms: u64, + /// Public API item. pub normal_duration_ms: u64, + /// Public API item. pub slow_duration_ms: u64, + /// Public API item. pub ultra_slow_duration_ms: u64, + /// Public API item. pub popup_enter_duration_ms: u64, + /// Public API item. pub popup_exit_duration_ms: u64, + /// Public API item. pub popup_offset: f32, + /// Public API item. pub popup_scale_delta: f32, } impl MotionTokens { + /// Public API item. pub fn popup_enter_duration(self) -> Duration { Duration::from_millis(self.popup_enter_duration_ms) } + /// Public API item. pub fn popup_exit_duration(self) -> Duration { Duration::from_millis(self.popup_exit_duration_ms) } + /// Public API item. pub fn ultra_fast_duration(self) -> Duration { Duration::from_millis(self.ultra_fast_duration_ms) } + /// Public API item. pub fn fast_duration(self) -> Duration { Duration::from_millis(self.fast_duration_ms) } + /// Public API item. pub fn normal_duration(self) -> Duration { Duration::from_millis(self.normal_duration_ms) } + /// Public API item. pub fn slow_duration(self) -> Duration { Duration::from_millis(self.slow_duration_ms) } + /// Public API item. pub fn ultra_slow_duration(self) -> Duration { Duration::from_millis(self.ultra_slow_duration_ms) } @@ -88,6 +113,7 @@ impl Default for MotionTokens { } } +/// Public API item. pub fn popup_motion_surface( id: impl Into, exiting: bool, diff --git a/crates/fluent-core/src/radii.rs b/crates/fluent-core/src/radii.rs index 35069c8..a90dc28 100644 --- a/crates/fluent-core/src/radii.rs +++ b/crates/fluent-core/src/radii.rs @@ -10,8 +10,11 @@ /// | `pill`| 9999px| Badges, chips | #[derive(Clone, Copy, Debug, PartialEq)] pub struct RadiiTokens { + /// Public API item. pub sm: f32, + /// Public API item. pub md: f32, + /// Public API item. pub lg: f32, /// Effectively circular/pill — use for badge and chip shapes. pub pill: f32, diff --git a/crates/fluent-core/src/shadows.rs b/crates/fluent-core/src/shadows.rs index 11c6275..68f7bf7 100644 --- a/crates/fluent-core/src/shadows.rs +++ b/crates/fluent-core/src/shadows.rs @@ -6,11 +6,17 @@ use gpui::{hsla, px, BoxShadow}; /// offsets, blur radii, and spread radii use logical pixels (DIPs). #[derive(Clone, Debug, PartialEq)] pub struct ShadowTokens { + /// Public API item. pub shadow2: [BoxShadow; 2], + /// Public API item. pub shadow4: [BoxShadow; 2], + /// Public API item. pub shadow8: [BoxShadow; 2], + /// Public API item. pub shadow16: [BoxShadow; 2], + /// Public API item. pub shadow28: [BoxShadow; 2], + /// Public API item. pub shadow64: [BoxShadow; 2], } diff --git a/crates/fluent-core/src/spacing.rs b/crates/fluent-core/src/spacing.rs index 5679726..953d7b4 100644 --- a/crates/fluent-core/src/spacing.rs +++ b/crates/fluent-core/src/spacing.rs @@ -4,11 +4,17 @@ /// Values are in logical pixels (DIPs). #[derive(Clone, Copy, Debug, PartialEq)] pub struct SpacingTokens { - pub xs: f32, // 2.0 - pub sm: f32, // 4.0 - pub md: f32, // 8.0 - pub lg: f32, // 12.0 - pub xl: f32, // 16.0 + /// Public API item. + pub xs: f32, // 2.0 + /// Public API item. + pub sm: f32, // 4.0 + /// Public API item. + pub md: f32, // 8.0 + /// Public API item. + pub lg: f32, // 12.0 + /// Public API item. + pub xl: f32, // 16.0 + /// Public API item. pub xxl: f32, // 24.0 } diff --git a/crates/fluent-core/src/stroke_width.rs b/crates/fluent-core/src/stroke_width.rs index ea38f6a..6152a3b 100644 --- a/crates/fluent-core/src/stroke_width.rs +++ b/crates/fluent-core/src/stroke_width.rs @@ -9,8 +9,11 @@ /// | `thickest` | 3px | Strong emphasis and high-contrast strokes | #[derive(Clone, Copy, Debug, PartialEq)] pub struct StrokeWidthTokens { + /// Public API item. pub thin: f32, + /// Public API item. pub thick: f32, + /// Public API item. pub thickest: f32, } diff --git a/crates/fluent-core/src/theme.rs b/crates/fluent-core/src/theme.rs index 639db25..cf7bf67 100644 --- a/crates/fluent-core/src/theme.rs +++ b/crates/fluent-core/src/theme.rs @@ -7,7 +7,9 @@ use crate::{ /// Whether the theme is rendered in dark or light mode. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Brightness { + /// Public API item. Dark, + /// Public API item. Light, } @@ -15,7 +17,9 @@ pub enum Brightness { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum LayoutDirection { #[default] + /// Public API item. Ltr, + /// Public API item. Rtl, } @@ -78,6 +82,7 @@ pub enum ThemeMode { } impl ThemeMode { + /// Public API item. pub fn from_window_appearance(appearance: gpui::WindowAppearance) -> Self { match appearance { gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => Self::Dark, @@ -121,11 +126,17 @@ mod tests { /// ``` #[derive(Clone, Debug)] pub struct Theme { + /// Public API item. pub brightness: Brightness, + /// Public API item. pub colors: ColorScheme, + /// Public API item. pub spacing: SpacingTokens, + /// Public API item. pub radii: RadiiTokens, + /// Public API item. pub typography: TypographyTokens, + /// Public API item. pub components: ComponentTokens, } @@ -156,10 +167,12 @@ impl Theme { } } + /// Public API item. pub fn is_dark(&self) -> bool { self.brightness == Brightness::Dark } + /// Public API item. pub fn motion(&self) -> MotionTokens { MotionTokens::default() } @@ -253,6 +266,7 @@ impl Theme { /// `cx.theme()` on any context type works via Rust's auto-deref — no separate /// blanket impl is needed (and none is provided to avoid coherence issues). pub trait ThemeProvider { + /// Public API item. fn theme(&self) -> &Theme; } @@ -266,6 +280,7 @@ impl ThemeProvider for App { /// /// Prefer [`LayoutDirection::current`] in components; it is the documented entry point. pub trait LayoutDirectionProvider { + /// Public API item. fn layout_direction(&self) -> LayoutDirection; } diff --git a/crates/fluent-core/src/typography.rs b/crates/fluent-core/src/typography.rs index e3044a7..aba19e2 100644 --- a/crates/fluent-core/src/typography.rs +++ b/crates/fluent-core/src/typography.rs @@ -4,8 +4,11 @@ /// `weight` follows CSS font-weight conventions (400 = Regular, 600 = SemiBold, 700 = Bold). #[derive(Clone, Copy, Debug, PartialEq)] pub struct TypeRamp { + /// Public API item. pub size: f32, + /// Public API item. pub line_height: f32, + /// Public API item. pub weight: u32, } @@ -22,10 +25,15 @@ pub struct TypeRamp { /// | `display` | 28px | 36px | 700 | #[derive(Clone, Copy, Debug, PartialEq)] pub struct TypographyTokens { + /// Public API item. pub caption: TypeRamp, + /// Public API item. pub body: TypeRamp, + /// Public API item. pub subtitle: TypeRamp, + /// Public API item. pub title: TypeRamp, + /// Public API item. pub display: TypeRamp, } diff --git a/crates/fluent-layout/src/breadcrumb.rs b/crates/fluent-layout/src/breadcrumb.rs index fc19513..e2d31a1 100644 --- a/crates/fluent-layout/src/breadcrumb.rs +++ b/crates/fluent-layout/src/breadcrumb.rs @@ -6,12 +6,16 @@ use gpui::{ }; #[derive(Clone, Debug)] +/// Public API item. pub struct BreadcrumbItem { + /// Public API item. pub id: SharedString, + /// Public API item. pub label: SharedString, } impl BreadcrumbItem { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -24,8 +28,11 @@ impl BreadcrumbItem { /// and place the middle items in an accessible overflow menu. #[allow(clippy::type_complexity)] pub struct Breadcrumb { + /// Public API item. pub items: Vec, + /// Public API item. pub current: usize, + /// Public API item. pub max_visible: usize, on_select: Option) + 'static>>, } @@ -42,28 +49,34 @@ impl Default for Breadcrumb { } impl Breadcrumb { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) .detach(); Self::default() } + /// Public API item. pub fn items(mut self, items: impl IntoIterator) -> Self { self.items = items.into_iter().collect(); self } + /// Public API item. pub fn item(mut self, item: BreadcrumbItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn current(mut self, current: usize) -> Self { self.current = current; self } + /// Public API item. pub fn max_visible(mut self, max_visible: usize) -> Self { self.max_visible = max_visible.max(2); self } + /// Public API item. pub fn on_select( mut self, f: impl Fn(usize, &mut Window, &mut Context) + 'static, @@ -201,16 +214,20 @@ impl Render for Breadcrumb { /// Compact paging control with previous/next buttons and a roving page cursor. #[derive(Clone, Debug)] pub struct Pagination { + /// Public API item. pub page: usize, + /// Public API item. pub page_count: usize, } impl Pagination { + /// Public API item. pub fn new(page_count: usize) -> Self { Self { page: 0, page_count: page_count.max(1), } } + /// Public API item. pub fn page(mut self, page: usize) -> Self { self.page = page.min(self.page_count.saturating_sub(1)); self diff --git a/crates/fluent-layout/src/command.rs b/crates/fluent-layout/src/command.rs index d354047..1ca6bdf 100644 --- a/crates/fluent-layout/src/command.rs +++ b/crates/fluent-layout/src/command.rs @@ -5,18 +5,28 @@ use crate::{ContextMenuItem, PaletteEntry, ToolbarItem}; /// Shared command metadata for menus, toolbars, ribbons, and palettes. #[derive(Clone, Debug)] pub struct CommandDef { + /// Public API item. pub id: SharedString, + /// Public API item. pub label: SharedString, + /// Public API item. pub subtitle: Option, + /// Public API item. pub group: Option, + /// Public API item. pub icon: Option, + /// Public API item. pub shortcut: Option, + /// Public API item. pub keywords: Vec, + /// Public API item. pub disabled: bool, + /// Public API item. pub checked: Option, } impl CommandDef { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -31,41 +41,49 @@ impl CommandDef { } } + /// Public API item. pub fn subtitle(mut self, subtitle: impl Into) -> Self { self.subtitle = Some(subtitle.into()); self } + /// Public API item. pub fn group(mut self, group: impl Into) -> Self { self.group = Some(group.into()); self } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self } + /// Public API item. pub fn shortcut(mut self, shortcut: impl Into) -> Self { self.shortcut = Some(shortcut.into()); self } + /// Public API item. pub fn keyword(mut self, keyword: impl Into) -> Self { self.keywords.push(keyword.into()); self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn checked(mut self, checked: bool) -> Self { self.checked = Some(checked); self } + /// Public API item. pub fn palette_entry(&self) -> PaletteEntry { let mut entry = PaletteEntry::new(self.id.clone(), self.label.clone()); if let Some(subtitle) = &self.subtitle { @@ -86,6 +104,7 @@ impl CommandDef { entry.disabled(self.disabled) } + /// Public API item. pub fn menu_item( &self, on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -101,6 +120,7 @@ impl CommandDef { item.disabled(self.disabled) } + /// Public API item. pub fn toolbar_item( &self, on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-layout/src/command_palette.rs b/crates/fluent-layout/src/command_palette.rs index b46373f..2207107 100644 --- a/crates/fluent-layout/src/command_palette.rs +++ b/crates/fluent-layout/src/command_palette.rs @@ -24,6 +24,7 @@ pub type PaletteEntryAction = Rc; /// A single searchable entry in the `CommandPalette`. #[derive(Clone)] pub struct PaletteEntry { + /// Public API item. pub id: SharedString, /// Primary display text — also used in filtering. pub label: SharedString, @@ -61,6 +62,7 @@ impl fmt::Debug for PaletteEntry { } impl PaletteEntry { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -75,40 +77,48 @@ impl PaletteEntry { } } + /// Public API item. pub fn subtitle(mut self, s: impl Into) -> Self { self.subtitle = Some(s.into()); self } + /// Public API item. pub fn group(mut self, group: impl Into) -> Self { self.group = Some(group.into()); self } + /// Public API item. pub fn hint(mut self, hint: impl Into) -> Self { self.hint = Some(hint.into()); self } + /// Public API item. pub fn shortcut(self, shortcut: impl Into) -> Self { self.hint(shortcut) } + /// Public API item. pub fn icon(mut self, path: impl Into) -> Self { self.icon = Some(path.into()); self } + /// Public API item. pub fn keyword(mut self, kw: impl Into) -> Self { self.keywords.push(kw.into()); self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn action(mut self, f: impl Fn(&PaletteEntry, &mut App) + 'static) -> Self { self.action = Some(Rc::new(f)); self @@ -131,6 +141,7 @@ impl PaletteEntry { /// as a fallback for older call sites. #[allow(clippy::type_complexity)] pub struct CommandPalette { + /// Public API item. pub open: bool, focus_handle: FocusHandle, query: String, @@ -138,10 +149,12 @@ pub struct CommandPalette { filtered: Vec, selected: usize, max_results: Option, + /// Public API item. pub on_select: Option>, } impl CommandPalette { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); Self { @@ -158,41 +171,48 @@ impl CommandPalette { // ---- Public API ---- + /// Public API item. pub fn entries(mut self, entries: Vec) -> Self { self.entries = entries; self.refilter(); self } + /// Public API item. pub fn max_results(mut self, max_results: usize) -> Self { self.max_results = Some(max_results.max(1)); self.refilter(); self } + /// Public API item. pub fn set_entries(&mut self, entries: Vec, cx: &mut Context) { self.entries = entries; self.refilter(); cx.notify(); } + /// Public API item. pub fn set_max_results(&mut self, max_results: Option, cx: &mut Context) { self.max_results = max_results.map(|max_results| max_results.max(1)); self.refilter(); cx.notify(); } + /// Public API item. pub fn set_query(&mut self, query: impl Into, cx: &mut Context) { self.query = query.into(); self.refilter(); cx.notify(); } + /// Public API item. pub fn on_select(mut self, f: impl Fn(&PaletteEntry, &mut App) + 'static) -> Self { self.on_select = Some(Box::new(f)); self } + /// Public API item. pub fn show(&mut self, cx: &mut Context) { self.open = true; self.query.clear(); @@ -201,6 +221,7 @@ impl CommandPalette { cx.notify(); } + /// Public API item. pub fn hide(&mut self, cx: &mut Context) { self.open = false; cx.notify(); diff --git a/crates/fluent-layout/src/context_menu.rs b/crates/fluent-layout/src/context_menu.rs index 5143f79..71a282b 100644 --- a/crates/fluent-layout/src/context_menu.rs +++ b/crates/fluent-layout/src/context_menu.rs @@ -12,36 +12,60 @@ pub use crate::menu_tree::is_context_menu_key; #[allow(clippy::type_complexity)] #[derive(Clone)] +/// Public API item. pub enum ContextMenuItem { + /// Public API item. Action { + /// Public API item. label: SharedString, + /// Public API item. shortcut: Option, + /// Public API item. icon: Option, + /// Public API item. disabled: bool, + /// Public API item. on_click: Arc, }, + /// Public API item. Checkbox { + /// Public API item. label: SharedString, + /// Public API item. checked: bool, + /// Public API item. disabled: bool, + /// Public API item. on_click: Arc, }, + /// Public API item. Radio { + /// Public API item. label: SharedString, + /// Public API item. selected: bool, + /// Public API item. disabled: bool, + /// Public API item. on_click: Arc, }, + /// Public API item. Submenu { + /// Public API item. label: SharedString, + /// Public API item. icon: Option, + /// Public API item. disabled: bool, + /// Public API item. items: Vec, }, + /// Public API item. Separator, } impl ContextMenuItem { + /// Public API item. pub fn action( label: impl Into, on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -55,6 +79,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn action_with_icon( label: impl Into, icon: impl Into, @@ -69,6 +94,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn checkbox( label: impl Into, checked: bool, @@ -82,6 +108,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn radio( label: impl Into, selected: bool, @@ -95,6 +122,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn submenu(label: impl Into, items: Vec) -> Self { Self::Submenu { label: label.into(), @@ -104,6 +132,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn shortcut(self, shortcut: impl Into) -> Self { match self { Self::Action { @@ -123,6 +152,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn disabled(self, disabled: bool) -> Self { match self { Self::Action { @@ -172,6 +202,7 @@ impl ContextMenuItem { } } + /// Public API item. pub fn separator() -> Self { Self::Separator } @@ -231,9 +262,13 @@ pub fn context_menu_key_target( ) } +/// Public API item. pub struct ContextMenu { + /// Public API item. pub items: Vec, + /// Public API item. pub position: Point, + /// Public API item. pub open: bool, closing: bool, motion_epoch: u64, @@ -244,6 +279,7 @@ pub struct ContextMenu { } impl ContextMenu { + /// Public API item. pub fn build(position: Point) -> Self { Self { items: vec![], @@ -258,16 +294,19 @@ impl ContextMenu { } } + /// Public API item. pub fn item(mut self, item: ContextMenuItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn separator(mut self) -> Self { self.items.push(ContextMenuItem::Separator); self } + /// Public API item. pub fn action( self, label: impl Into, @@ -276,6 +315,7 @@ impl ContextMenu { self.item(ContextMenuItem::action(label, on_click)) } + /// Public API item. pub fn action_with_icon( self, label: impl Into, @@ -285,6 +325,7 @@ impl ContextMenu { self.item(ContextMenuItem::action_with_icon(label, icon, on_click)) } + /// Public API item. pub fn checkbox( self, label: impl Into, @@ -294,6 +335,7 @@ impl ContextMenu { self.item(ContextMenuItem::checkbox(label, checked, on_click)) } + /// Public API item. pub fn radio( self, label: impl Into, @@ -303,10 +345,12 @@ impl ContextMenu { self.item(ContextMenuItem::radio(label, selected, on_click)) } + /// Public API item. pub fn submenu(self, label: impl Into, items: Vec) -> Self { self.item(ContextMenuItem::submenu(label, items)) } + /// Public API item. pub fn close(&mut self, cx: &mut Context) { if !self.open || self.closing { return; diff --git a/crates/fluent-layout/src/data_table.rs b/crates/fluent-layout/src/data_table.rs index 91a2245..ebfea48 100644 --- a/crates/fluent-layout/src/data_table.rs +++ b/crates/fluent-layout/src/data_table.rs @@ -16,12 +16,16 @@ type SortHandler = Arc; #[derive(Clone, Copy, Debug, PartialEq, Eq)] +/// Public API item. pub enum DataSortDirection { + /// Public API item. Ascending, + /// Public API item. Descending, } impl DataSortDirection { + /// Public API item. pub fn toggle(self) -> Self { match self { Self::Ascending => Self::Descending, @@ -31,27 +35,38 @@ impl DataSortDirection { } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +/// Public API item. pub enum DataCellAlign { #[default] + /// Public API item. Start, + /// Public API item. Center, + /// Public API item. End, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +/// Public API item. pub enum DataSortKind { #[default] + /// Public API item. Text, + /// Public API item. Number, } #[derive(Clone, Debug)] +/// Public API item. pub struct DataCell { + /// Public API item. pub text: SharedString, + /// Public API item. pub align: Option, } impl DataCell { + /// Public API item. pub fn new(text: impl Into) -> Self { Self { text: text.into(), @@ -59,6 +74,7 @@ impl DataCell { } } + /// Public API item. pub fn align(mut self, align: DataCellAlign) -> Self { self.align = Some(align); self @@ -84,26 +100,39 @@ impl From for DataCell { } #[derive(Clone, Debug)] +/// Public API item. pub enum DataTableState { + /// Public API item. Ready, + /// Public API item. Loading(SharedString), + /// Public API item. Empty(SharedString), /// Rows exist but the active filter hides them all. NoResults(SharedString), + /// Public API item. Error(SharedString), } #[derive(Clone, Debug)] +/// Public API item. pub struct DataColumn { + /// Public API item. pub id: SharedString, + /// Public API item. pub title: SharedString, + /// Public API item. pub width: Option, + /// Public API item. pub sortable: bool, + /// Public API item. pub align: DataCellAlign, + /// Public API item. pub sort_kind: DataSortKind, } impl DataColumn { + /// Public API item. pub fn new(id: impl Into, title: impl Into) -> Self { Self { id: id.into(), @@ -115,21 +144,25 @@ impl DataColumn { } } + /// Public API item. pub fn width(mut self, width: f32) -> Self { self.width = Some(width.clamp(48.0, 600.0)); self } + /// Public API item. pub fn sortable(mut self, sortable: bool) -> Self { self.sortable = sortable; self } + /// Public API item. pub fn align(mut self, align: DataCellAlign) -> Self { self.align = align; self } + /// Public API item. pub fn sort_kind(mut self, kind: DataSortKind) -> Self { self.sort_kind = kind; self @@ -137,12 +170,16 @@ impl DataColumn { } #[derive(Clone, Debug)] +/// Public API item. pub struct DataRow { + /// Public API item. pub id: SharedString, + /// Public API item. pub cells: Vec, } impl DataRow { + /// Public API item. pub fn new( id: impl Into, cells: impl IntoIterator>, @@ -199,6 +236,7 @@ fn move_target(current: Option, mv: RowMove, page: usize, len: usize) -> } impl DataTable { + /// Public API item. pub fn new() -> Self { Self { columns: Vec::new(), @@ -214,56 +252,67 @@ impl DataTable { } } + /// Public API item. pub fn column(mut self, column: DataColumn) -> Self { self.columns.push(column); self } + /// Public API item. pub fn columns(mut self, columns: impl IntoIterator) -> Self { self.columns = columns.into_iter().collect(); self } + /// Public API item. pub fn row(mut self, row: DataRow) -> Self { self.rows.push(row); self } + /// Public API item. pub fn rows(mut self, rows: impl IntoIterator) -> Self { self.rows = rows.into_iter().collect(); self } + /// Public API item. pub fn state(mut self, state: DataTableState) -> Self { self.state = state; self } + /// Public API item. pub fn loading(mut self, message: impl Into) -> Self { self.state = DataTableState::Loading(message.into()); self } + /// Public API item. pub fn empty_message(mut self, message: impl Into) -> Self { self.state = DataTableState::Empty(message.into()); self } + /// Public API item. pub fn no_results_message(mut self, message: impl Into) -> Self { self.state = DataTableState::NoResults(message.into()); self } + /// Public API item. pub fn error_message(mut self, message: impl Into) -> Self { self.state = DataTableState::Error(message.into()); self } + /// Public API item. pub fn selected(mut self, id: impl Into) -> Self { self.selected_id = Some(id.into()); self } + /// Public API item. pub fn sort( mut self, column_id: impl Into, @@ -273,11 +322,13 @@ impl DataTable { self } + /// Public API item. pub fn max_body_height(mut self, height: f32) -> Self { self.max_body_height = Some(height); self } + /// Public API item. pub fn on_row_click( mut self, f: impl Fn(SharedString, &ClickEvent, &mut Window, &mut App) + 'static, @@ -286,6 +337,7 @@ impl DataTable { self } + /// Public API item. pub fn on_row_select( mut self, f: impl Fn(SharedString, &mut Window, &mut App) + 'static, @@ -303,6 +355,7 @@ impl DataTable { self } + /// Public API item. pub fn on_sort( mut self, f: impl Fn(SharedString, DataSortDirection, &ClickEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-layout/src/dialog.rs b/crates/fluent-layout/src/dialog.rs index 0e28ed9..d6485e0 100644 --- a/crates/fluent-layout/src/dialog.rs +++ b/crates/fluent-layout/src/dialog.rs @@ -18,6 +18,7 @@ pub struct Dialog { #[derive(Clone)] #[allow(clippy::type_complexity)] +/// Public API item. pub struct DialogAction { label: SharedString, primary: bool, @@ -25,6 +26,7 @@ pub struct DialogAction { } impl DialogAction { + /// Public API item. pub fn new( label: impl Into, on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -36,6 +38,7 @@ impl DialogAction { } } + /// Public API item. pub fn primary(mut self, primary: bool) -> Self { self.primary = primary; self @@ -43,6 +46,7 @@ impl DialogAction { } impl Dialog { + /// Public API item. pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -52,21 +56,25 @@ impl Dialog { } } + /// Public API item. pub fn body(mut self, body: impl IntoElement) -> Self { self.body = Some(body.into_any_element()); self } + /// Public API item. pub fn action(mut self, action: DialogAction) -> Self { self.actions.push(action); self } + /// Public API item. pub fn dismissible(mut self, dismissible: bool) -> Self { self.dismissible = dismissible; self } + /// Public API item. pub fn show(self, size: ModalSize, cx: &mut App) { let dismissible = self.dismissible; let entity = cx.new(|_| DialogView { dialog: self }); diff --git a/crates/fluent-layout/src/dock.rs b/crates/fluent-layout/src/dock.rs index 6ff4a55..809f76d 100644 --- a/crates/fluent-layout/src/dock.rs +++ b/crates/fluent-layout/src/dock.rs @@ -7,9 +7,13 @@ use gpui::{ /// Which edge a dock panel is attached to. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum DockPosition { + /// Public API item. Left, + /// Public API item. Right, + /// Public API item. Bottom, + /// Public API item. Top, } @@ -30,17 +34,24 @@ impl Render for DockResizeDrag { /// The panel edge is draggable: grab the 4px resize handle to change the width /// (left/right panels) or height (top/bottom panels). pub struct DockPanel { + /// Public API item. pub position: DockPosition, + /// Public API item. pub title: SharedString, + /// Public API item. pub content: Option, + /// Public API item. pub size: f32, + /// Public API item. pub collapsed: bool, + /// Public API item. pub pinned: bool, /// Captured at drag-start: (initial_size, initial_cursor_pos). resize_start: Option<(f32, f32)>, } impl DockPanel { + /// Public API item. pub fn new( cx: &mut Context, position: DockPosition, @@ -64,21 +75,25 @@ impl DockPanel { } } + /// Public API item. pub fn size(mut self, size: f32) -> Self { self.size = size; self } + /// Public API item. pub fn content(mut self, view: AnyView) -> Self { self.content = Some(view); self } + /// Public API item. pub fn set_content(&mut self, view: AnyView, cx: &mut Context) { self.content = Some(view); cx.notify(); } + /// Public API item. pub fn toggle_collapsed(&mut self, cx: &mut Context) { self.collapsed = !self.collapsed; cx.notify(); diff --git a/crates/fluent-layout/src/document_viewer.rs b/crates/fluent-layout/src/document_viewer.rs index 2b7baea..db92364 100644 --- a/crates/fluent-layout/src/document_viewer.rs +++ b/crates/fluent-layout/src/document_viewer.rs @@ -4,20 +4,25 @@ use gpui::{ }; #[derive(Clone, Debug, Default, PartialEq, Eq)] +/// Public API item. pub struct RichDocument { + /// Public API item. pub blocks: Vec, } impl RichDocument { + /// Public API item. pub fn new() -> Self { Self { blocks: Vec::new() } } + /// Public API item. pub fn block(mut self, block: RichDocumentBlock) -> Self { self.blocks.push(block); self } + /// Public API item. pub fn from_plain_text(text: impl AsRef) -> Self { let blocks = text .as_ref() @@ -32,10 +37,12 @@ impl RichDocument { Self { blocks } } + /// Public API item. pub fn from_html_fragment_lossy(html: impl AsRef) -> Self { HtmlDocumentBuilder::parse(html.as_ref()) } + /// Public API item. pub fn to_plain_text(&self) -> String { let mut lines = Vec::new(); for block in &self.blocks { @@ -69,33 +76,52 @@ impl RichDocument { } #[derive(Clone, Debug, PartialEq, Eq)] +/// Public API item. pub enum RichDocumentBlock { + /// Public API item. Heading { + /// Public API item. level: u8, + /// Public API item. runs: Vec, }, + /// Public API item. Paragraph(Vec), + /// Public API item. Preformatted(Vec), + /// Public API item. Table { + /// Public API item. rows: Vec>, }, + /// Public API item. Image { + /// Public API item. alt: SharedString, + /// Public API item. src: SharedString, }, + /// Public API item. Divider, } #[derive(Clone, Debug, PartialEq, Eq)] +/// Public API item. pub struct RichTextRun { + /// Public API item. pub text: SharedString, + /// Public API item. pub strong: bool, + /// Public API item. pub emphasis: bool, + /// Public API item. pub code: bool, + /// Public API item. pub link: Option, } impl RichTextRun { + /// Public API item. pub fn new(text: impl Into) -> Self { Self { text: text.into(), @@ -106,21 +132,25 @@ impl RichTextRun { } } + /// Public API item. pub fn strong(mut self, strong: bool) -> Self { self.strong = strong; self } + /// Public API item. pub fn emphasis(mut self, emphasis: bool) -> Self { self.emphasis = emphasis; self } + /// Public API item. pub fn code(mut self, code: bool) -> Self { self.code = code; self } + /// Public API item. pub fn link(mut self, href: impl Into) -> Self { self.link = Some(href.into()); self @@ -138,6 +168,7 @@ pub struct DocumentViewer { } impl DocumentViewer { + /// Public API item. pub fn new(document: RichDocument) -> Self { Self { document, @@ -146,19 +177,23 @@ impl DocumentViewer { } } + /// Public API item. pub fn plain_text(text: impl AsRef) -> Self { Self::new(RichDocument::from_plain_text(text)) } + /// Public API item. pub fn html_fragment(html: impl AsRef) -> Self { Self::new(RichDocument::from_html_fragment_lossy(html)) } + /// Public API item. pub fn empty_message(mut self, message: impl Into) -> Self { self.empty_message = message.into(); self } + /// Public API item. pub fn max_height(mut self, height: f32) -> Self { self.max_height = Some(height.max(64.0)); self diff --git a/crates/fluent-layout/src/drawer.rs b/crates/fluent-layout/src/drawer.rs index dc3b387..8c53d8b 100644 --- a/crates/fluent-layout/src/drawer.rs +++ b/crates/fluent-layout/src/drawer.rs @@ -27,10 +27,14 @@ pub enum DrawerPosition { /// Fluent drawer width presets. #[derive(Clone, Copy, Debug, Default, PartialEq)] pub enum DrawerSize { + /// Public API item. Small, #[default] + /// Public API item. Medium, + /// Public API item. Large, + /// Public API item. Custom(f32), } @@ -64,6 +68,7 @@ pub struct Drawer { } impl Drawer { + /// Public API item. pub fn new(content: AnyView, cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) @@ -81,35 +86,42 @@ impl Drawer { } } + /// Public API item. pub fn mode(mut self, mode: DrawerMode) -> Self { self.mode = mode; self } + /// Public API item. pub fn position(mut self, position: DrawerPosition) -> Self { self.position = position; self } + /// Public API item. pub fn size(mut self, size: DrawerSize) -> Self { self.size = size; self } + /// Public API item. pub fn dismissible(mut self, dismissible: bool) -> Self { self.dismissible = dismissible; self } + /// Public API item. pub fn initially_open(mut self, open: bool) -> Self { self.open = open; self } + /// Public API item. pub fn is_open(&self) -> bool { self.open } + /// Public API item. pub fn set_open(&mut self, open: bool, cx: &mut Context) { if self.open != open { self.open = open; @@ -117,10 +129,12 @@ impl Drawer { } } + /// Public API item. pub fn toggle(&mut self, cx: &mut Context) { self.set_open(!self.open, cx); } + /// Public API item. pub fn set_mode(&mut self, mode: DrawerMode, cx: &mut Context) { if self.mode != mode { self.mode = mode; @@ -128,6 +142,7 @@ impl Drawer { } } + /// Public API item. pub fn set_position(&mut self, position: DrawerPosition, cx: &mut Context) { if self.position != position { self.position = position; diff --git a/crates/fluent-layout/src/flyout.rs b/crates/fluent-layout/src/flyout.rs index bce7e54..5463056 100644 --- a/crates/fluent-layout/src/flyout.rs +++ b/crates/fluent-layout/src/flyout.rs @@ -4,7 +4,9 @@ use gpui::{deferred, div, prelude::*, px, AnyElement, IntoElement, RenderOnce, W /// Standard flyout placements relative to the invoking element. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum FlyoutPlacement { + /// Public API item. BelowStart, + /// Public API item. RightStart, } @@ -23,6 +25,7 @@ pub struct Flyout { } impl Flyout { + /// Public API item. pub fn new(child: impl IntoElement) -> Self { Self { child: child.into_any_element(), @@ -33,17 +36,20 @@ impl Flyout { } } + /// Public API item. pub fn placement(mut self, placement: FlyoutPlacement) -> Self { self.placement = placement; self } + /// Public API item. pub fn trigger_size(mut self, width: f32, height: f32) -> Self { self.trigger_width = width; self.trigger_height = height; self } + /// Public API item. pub fn priority(mut self, priority: usize) -> Self { self.priority = priority; self diff --git a/crates/fluent-layout/src/lib.rs b/crates/fluent-layout/src/lib.rs index c2143d0..898b1a3 100644 --- a/crates/fluent-layout/src/lib.rs +++ b/crates/fluent-layout/src/lib.rs @@ -1,31 +1,59 @@ +//! Public API for this crate. +#![deny(missing_docs)] + +/// Public API item. pub mod breadcrumb; +/// Public API item. pub mod command; +/// Public API item. pub mod command_palette; +/// Public API item. pub mod context_menu; pub mod data_status; +/// Public API item. pub mod data_table; +/// Public API item. pub mod dialog; +/// Public API item. pub mod dock; +/// Public API item. pub mod document_viewer; +/// Public API item. pub mod drawer; +/// Public API item. pub mod flyout; +/// Public API item. pub mod menu_bar; +/// Public API item. pub mod menu_button; mod menu_tree; +/// Public API item. pub mod message_bar; +/// Public API item. pub mod modal; pub mod nav; +/// Public API item. pub mod pane; +/// Public API item. pub mod pane_group; +/// Public API item. pub mod popover; mod roving; +/// Public API item. pub mod selectable_list; +/// Public API item. pub mod settings_nav; +/// Public API item. pub mod tab_strip; +/// Public API item. pub mod toast; +/// Public API item. pub mod toolbar; +/// Public API item. pub mod tree; +/// Public API item. pub mod virtual_list; +/// Public API item. pub mod workspace; pub use breadcrumb::{Breadcrumb, BreadcrumbItem, Pagination}; diff --git a/crates/fluent-layout/src/menu_bar.rs b/crates/fluent-layout/src/menu_bar.rs index 9e8e132..168c0a6 100644 --- a/crates/fluent-layout/src/menu_bar.rs +++ b/crates/fluent-layout/src/menu_bar.rs @@ -11,8 +11,11 @@ use crate::context_menu::ContextMenuItem; use crate::menu_tree::{self, MenuRenderEnv}; #[derive(Clone)] +/// Public API item. pub struct MenuDef { + /// Public API item. pub label: SharedString, + /// Public API item. pub items: Vec, } @@ -23,6 +26,7 @@ pub struct MenuDef { pub struct MenuItemDef; impl MenuItemDef { + /// Public API item. pub fn action( label: impl Into, on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -30,6 +34,7 @@ impl MenuItemDef { ContextMenuItem::action(label, on_click) } + /// Public API item. pub fn action_with_shortcut( label: impl Into, shortcut: impl Into, @@ -38,6 +43,7 @@ impl MenuItemDef { ContextMenuItem::action(label, on_click).shortcut(shortcut) } + /// Public API item. pub fn action_with_icon( label: impl Into, icon: impl Into, @@ -46,6 +52,7 @@ impl MenuItemDef { ContextMenuItem::action_with_icon(label, icon, on_click) } + /// Public API item. pub fn checkbox( label: impl Into, checked: bool, @@ -54,6 +61,7 @@ impl MenuItemDef { ContextMenuItem::checkbox(label, checked, on_click) } + /// Public API item. pub fn radio( label: impl Into, selected: bool, @@ -62,10 +70,12 @@ impl MenuItemDef { ContextMenuItem::radio(label, selected, on_click) } + /// Public API item. pub fn submenu(label: impl Into, items: Vec) -> ContextMenuItem { ContextMenuItem::submenu(label, items) } + /// Public API item. pub fn separator() -> ContextMenuItem { ContextMenuItem::Separator } @@ -77,7 +87,9 @@ impl MenuItemDef { /// `ContextMenu`, including actions, checkbox/radio state, disabled rows, /// separators, and cascaded submenus. pub struct MenuBar { + /// Public API item. pub menus: Vec, + /// Public API item. pub open_index: Option, closing: bool, motion_epoch: u64, @@ -92,6 +104,7 @@ pub struct MenuBar { } impl MenuBar { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); @@ -203,6 +216,7 @@ impl MenuBar { } } + /// Public API item. pub fn menu(mut self, label: impl Into, items: Vec) -> Self { self.menus.push(MenuDef { label: label.into(), diff --git a/crates/fluent-layout/src/menu_button.rs b/crates/fluent-layout/src/menu_button.rs index 1090722..07416e9 100644 --- a/crates/fluent-layout/src/menu_button.rs +++ b/crates/fluent-layout/src/menu_button.rs @@ -32,6 +32,7 @@ pub struct MenuButton { } impl MenuButton { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -51,30 +52,36 @@ impl MenuButton { } } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn item(mut self, item: ContextMenuItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn items(mut self, items: impl IntoIterator) -> Self { self.items = items.into_iter().collect(); self } + /// Public API item. pub fn separator(self) -> Self { self.item(ContextMenuItem::Separator) } + /// Public API item. pub fn action( self, label: impl Into, diff --git a/crates/fluent-layout/src/message_bar.rs b/crates/fluent-layout/src/message_bar.rs index 2a3015d..433cfb3 100644 --- a/crates/fluent-layout/src/message_bar.rs +++ b/crates/fluent-layout/src/message_bar.rs @@ -6,11 +6,16 @@ use gpui::{ type DismissHandler = Box; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +/// Public API item. pub enum MessageIntent { #[default] + /// Public API item. Info, + /// Public API item. Success, + /// Public API item. Warning, + /// Public API item. Error, } @@ -25,6 +30,7 @@ pub struct MessageBar { } impl MessageBar { + /// Public API item. pub fn new(message: impl Into) -> Self { Self { intent: MessageIntent::Info, @@ -35,11 +41,13 @@ impl MessageBar { } } + /// Public API item. pub fn intent(mut self, intent: MessageIntent) -> Self { self.intent = intent; self } + /// Public API item. pub fn title(mut self, title: impl Into) -> Self { self.title = Some(title.into()); self @@ -55,6 +63,7 @@ impl MessageBar { self } + /// Public API item. pub fn on_dismiss(mut self, f: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self { self.on_dismiss = Some(Box::new(f)); self diff --git a/crates/fluent-layout/src/modal.rs b/crates/fluent-layout/src/modal.rs index 7ef0195..d837f6e 100644 --- a/crates/fluent-layout/src/modal.rs +++ b/crates/fluent-layout/src/modal.rs @@ -45,6 +45,7 @@ pub struct ModalStack { impl Global for ModalStack {} impl ModalStack { + /// Public API item. pub fn init(cx: &mut gpui::App) { cx.set_global(ModalStack { entries: vec![] }); } @@ -74,6 +75,7 @@ impl ModalStack { cx.global_mut::().entries.pop(); } + /// Public API item. pub fn is_empty(cx: &gpui::App) -> bool { cx.global::().entries.is_empty() } @@ -95,6 +97,7 @@ pub struct ModalHost { } impl ModalHost { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) @@ -219,9 +222,13 @@ impl Render for ModalHost { /// A generic yes/no confirmation modal. #[allow(clippy::type_complexity)] pub struct ConfirmModal { + /// Public API item. pub title: SharedString, + /// Public API item. pub message: SharedString, + /// Public API item. pub confirm_label: SharedString, + /// Public API item. pub cancel_label: SharedString, on_confirm: Option>, on_cancel: Option>, @@ -229,12 +236,16 @@ pub struct ConfirmModal { /// A persistent informational modal with a single dismiss action. pub struct MessageDialog { + /// Public API item. pub title: SharedString, + /// Public API item. pub message: SharedString, + /// Public API item. pub dismiss_label: SharedString, } impl MessageDialog { + /// Public API item. pub fn new(title: impl Into, message: impl Into) -> Self { Self { title: title.into(), @@ -243,11 +254,13 @@ impl MessageDialog { } } + /// Public API item. pub fn dismiss_label(mut self, label: impl Into) -> Self { self.dismiss_label = label.into(); self } + /// Public API item. pub fn show(self, size: ModalSize, cx: &mut gpui::App) -> Entity { let entity = cx.new(|_| self); ModalStack::push(entity.clone().into(), size, cx); @@ -361,6 +374,7 @@ impl Render for MessageDialog { } impl ConfirmModal { + /// Public API item. pub fn new(title: impl Into, message: impl Into) -> Self { Self { title: title.into(), @@ -372,21 +386,25 @@ impl ConfirmModal { } } + /// Public API item. pub fn confirm_label(mut self, label: impl Into) -> Self { self.confirm_label = label.into(); self } + /// Public API item. pub fn cancel_label(mut self, label: impl Into) -> Self { self.cancel_label = label.into(); self } + /// Public API item. pub fn on_confirm(mut self, f: impl Fn(&mut gpui::App) + 'static) -> Self { self.on_confirm = Some(Box::new(f)); self } + /// Public API item. pub fn on_cancel(mut self, f: impl Fn(&mut gpui::App) + 'static) -> Self { self.on_cancel = Some(Box::new(f)); self diff --git a/crates/fluent-layout/src/nav.rs b/crates/fluent-layout/src/nav.rs index 33623d2..66a4c2a 100644 --- a/crates/fluent-layout/src/nav.rs +++ b/crates/fluent-layout/src/nav.rs @@ -9,15 +9,22 @@ use gpui::{ }; #[derive(Clone, Debug)] +/// Public API item. pub struct NavItem { + /// Public API item. pub id: SharedString, + /// Public API item. pub label: SharedString, + /// Public API item. pub icon: Option, + /// Public API item. pub children: Vec, + /// Public API item. pub expanded: bool, } impl NavItem { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -28,31 +35,40 @@ impl NavItem { } } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self } + /// Public API item. pub fn child(mut self, child: NavItem) -> Self { self.children.push(child); self } + /// Public API item. pub fn expanded(mut self, expanded: bool) -> Self { self.expanded = expanded; self } + /// Public API item. pub fn collapsed(self) -> Self { self.expanded(false) } } #[derive(Clone, Debug)] +/// Public API item. pub struct NavCategory { + /// Public API item. pub title: SharedString, + /// Public API item. pub items: Vec, + /// Public API item. pub expanded: bool, } impl NavCategory { + /// Public API item. pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -60,14 +76,17 @@ impl NavCategory { expanded: true, } } + /// Public API item. pub fn item(mut self, item: NavItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn expanded(mut self, expanded: bool) -> Self { self.expanded = expanded; self } + /// Public API item. pub fn collapsed(self) -> Self { self.expanded(false) } @@ -85,13 +104,18 @@ struct FlatItem { /// expand groups. The generated AccessKit tree uses `Tree` and `TreeItem` roles. #[allow(clippy::type_complexity)] pub struct Nav { + /// Public API item. pub categories: Vec, + /// Public API item. pub selected_id: Option, + /// Public API item. pub compact: bool, + /// Public API item. pub on_select: Option>, } impl Nav { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); Self { @@ -101,6 +125,7 @@ impl Nav { on_select: None, } } + /// Public API item. pub fn category(mut self, category: NavCategory) -> Self { if self.selected_id.is_none() { self.selected_id = first_visible(&category.items).map(|item| item.id.clone()); @@ -108,31 +133,39 @@ impl Nav { self.categories.push(category); self } + /// Public API item. pub fn item(self, item: NavItem) -> Self { self.category(NavCategory::new("").item(item)) } + /// Public API item. pub fn selected(mut self, id: impl Into) -> Self { self.selected_id = Some(id.into()); self } + /// Public API item. pub fn active(self, id: impl Into) -> Self { self.selected(id) } + /// Public API item. pub fn compact(mut self, compact: bool) -> Self { self.compact = compact; self } + /// Public API item. pub fn on_select(mut self, f: impl Fn(SharedString, &mut App) + 'static) -> Self { self.on_select = Some(Arc::new(f)); self } + /// Public API item. pub fn set_selected(&mut self, id: SharedString, cx: &mut Context) { self.selected_id = Some(id); cx.notify(); } + /// Public API item. pub fn set_active(&mut self, id: SharedString, cx: &mut Context) { self.set_selected(id, cx); } + /// Public API item. pub fn toggle(&mut self, id: &str, cx: &mut Context) -> bool { let changed = toggle_items(&mut self.categories, id); if changed { diff --git a/crates/fluent-layout/src/pane.rs b/crates/fluent-layout/src/pane.rs index e95c532..913ee71 100644 --- a/crates/fluent-layout/src/pane.rs +++ b/crates/fluent-layout/src/pane.rs @@ -8,26 +8,32 @@ use crate::tab_strip::TabStrip; /// The content is an `AnyView` — set it via `Pane::set_content`. #[derive(Default)] pub struct Pane { + /// Public API item. pub tab_strip: Option>, + /// Public API item. pub content: Option, } impl Pane { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); Self::default() } + /// Public API item. pub fn with_tab_strip(mut self, strip: Entity) -> Self { self.tab_strip = Some(strip); self } + /// Public API item. pub fn set_content(&mut self, content: AnyView, cx: &mut Context) { self.content = Some(content); cx.notify(); } + /// Public API item. pub fn set_tab_strip(&mut self, strip: Entity, cx: &mut Context) { self.tab_strip = Some(strip); cx.notify(); diff --git a/crates/fluent-layout/src/pane_group.rs b/crates/fluent-layout/src/pane_group.rs index ffb6e0a..d4ab7af 100644 --- a/crates/fluent-layout/src/pane_group.rs +++ b/crates/fluent-layout/src/pane_group.rs @@ -11,7 +11,9 @@ const DIVIDER_SIZE: f32 = 5.0; /// Direction for a pane split. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum SplitAxis { + /// Public API item. Horizontal, + /// Public API item. Vertical, } @@ -22,9 +24,13 @@ pub enum SplitAxis { /// same type for navigation/details or editor/preview splits. #[derive(Clone, Copy, Debug, PartialEq)] pub struct PaneConstraints { + /// Public API item. pub first_min: f32, + /// Public API item. pub second_min: f32, + /// Public API item. pub first_max: Option, + /// Public API item. pub second_max: Option, } @@ -40,25 +46,30 @@ impl Default for PaneConstraints { } impl PaneConstraints { + /// Public API item. pub fn new() -> Self { Self::default() } + /// Public API item. pub fn first_min(mut self, px: f32) -> Self { self.first_min = px.max(0.0); self } + /// Public API item. pub fn second_min(mut self, px: f32) -> Self { self.second_min = px.max(0.0); self } + /// Public API item. pub fn first_max(mut self, px: impl Into>) -> Self { self.first_max = px.into().map(|px| px.max(0.0)); self } + /// Public API item. pub fn second_max(mut self, px: impl Into>) -> Self { self.second_max = px.into().map(|px| px.max(0.0)); self @@ -72,16 +83,23 @@ impl PaneConstraints { /// applied as layout min/max constraints when rendering. #[allow(clippy::type_complexity)] pub struct PaneGroup { + /// Public API item. pub axis: SplitAxis, + /// Public API item. pub first: Option, + /// Public API item. pub second: Option, + /// Public API item. pub ratio: f32, + /// Public API item. pub constraints: PaneConstraints, + /// Public API item. pub on_resize: Option>, drag_start: Option<(f32, f32)>, observing_theme: bool, } +/// Public API item. pub type ResizablePanelGroup = PaneGroup; impl Default for PaneGroup { @@ -108,6 +126,7 @@ impl Render for PaneSplitDrag { } impl PaneGroup { + /// Public API item. pub fn horizontal() -> Self { Self { axis: SplitAxis::Horizontal, @@ -115,6 +134,7 @@ impl PaneGroup { } } + /// Public API item. pub fn vertical() -> Self { Self { axis: SplitAxis::Vertical, @@ -122,69 +142,83 @@ impl PaneGroup { } } + /// Public API item. pub fn first(mut self, view: AnyView) -> Self { self.first = Some(view); self } + /// Public API item. pub fn second(mut self, view: AnyView) -> Self { self.second = Some(view); self } + /// Public API item. pub fn ratio(mut self, ratio: f32) -> Self { self.ratio = clamp_ratio_without_extent(ratio); self } + /// Public API item. pub fn constraints(mut self, constraints: PaneConstraints) -> Self { self.constraints = constraints; self } + /// Public API item. pub fn min_first(mut self, px: f32) -> Self { self.constraints.first_min = px.max(0.0); self } + /// Public API item. pub fn min_second(mut self, px: f32) -> Self { self.constraints.second_min = px.max(0.0); self } + /// Public API item. pub fn max_first(mut self, px: impl Into>) -> Self { self.constraints.first_max = px.into().map(|px| px.max(0.0)); self } + /// Public API item. pub fn max_second(mut self, px: impl Into>) -> Self { self.constraints.second_max = px.into().map(|px| px.max(0.0)); self } + /// Public API item. pub fn on_resize(mut self, f: impl Fn(f32, &mut App) + 'static) -> Self { self.on_resize = Some(Box::new(f)); self } + /// Public API item. pub fn ratio_value(&self) -> f32 { self.ratio } + /// Public API item. pub fn set_first(&mut self, view: AnyView, cx: &mut Context) { self.first = Some(view); cx.notify(); } + /// Public API item. pub fn set_second(&mut self, view: AnyView, cx: &mut Context) { self.second = Some(view); cx.notify(); } + /// Public API item. pub fn set_ratio(&mut self, ratio: f32, cx: &mut Context) { self.apply_ratio(ratio, None, cx); } + /// Public API item. pub fn set_constraints(&mut self, constraints: PaneConstraints, cx: &mut Context) { self.constraints = constraints; self.apply_ratio(self.ratio, None, cx); diff --git a/crates/fluent-layout/src/popover.rs b/crates/fluent-layout/src/popover.rs index d185c8e..7ca72c0 100644 --- a/crates/fluent-layout/src/popover.rs +++ b/crates/fluent-layout/src/popover.rs @@ -14,6 +14,7 @@ pub struct Popover { } impl Popover { + /// Public API item. pub fn new(position: Point, content: impl IntoElement) -> Self { Self { open: true, @@ -23,11 +24,13 @@ impl Popover { } } + /// Public API item. pub fn open(mut self, open: bool) -> Self { self.open = open; self } + /// Public API item. pub fn anchor(mut self, anchor: Anchor) -> Self { self.anchor = anchor; self diff --git a/crates/fluent-layout/src/selectable_list.rs b/crates/fluent-layout/src/selectable_list.rs index 9f404da..52c6243 100644 --- a/crates/fluent-layout/src/selectable_list.rs +++ b/crates/fluent-layout/src/selectable_list.rs @@ -15,28 +15,44 @@ type ListContextHandler = Arc; #[derive(Clone, Debug, Default)] +/// Public API item. pub enum SelectableListState { #[default] + /// Public API item. Ready, + /// Public API item. Loading(SharedString), + /// Public API item. Empty(SharedString), + /// Public API item. Error(SharedString), } #[derive(Clone, Debug)] +/// Public API item. pub struct SelectableListItem { + /// Public API item. pub id: SharedString, + /// Public API item. pub title: SharedString, + /// Public API item. pub subtitle: Option, + /// Public API item. pub detail: Option, + /// Public API item. pub meta: Option, + /// Public API item. pub badge: Option, + /// Public API item. pub icon: Option, + /// Public API item. pub disabled: bool, + /// Public API item. pub emphasized: bool, } impl SelectableListItem { + /// Public API item. pub fn new(id: impl Into, title: impl Into) -> Self { Self { id: id.into(), @@ -51,36 +67,43 @@ impl SelectableListItem { } } + /// Public API item. pub fn subtitle(mut self, subtitle: impl Into) -> Self { self.subtitle = Some(subtitle.into()); self } + /// Public API item. pub fn detail(mut self, detail: impl Into) -> Self { self.detail = Some(detail.into()); self } + /// Public API item. pub fn meta(mut self, meta: impl Into) -> Self { self.meta = Some(meta.into()); self } + /// Public API item. pub fn badge(mut self, badge: impl Into) -> Self { self.badge = Some(badge.into()); self } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn emphasized(mut self, emphasized: bool) -> Self { self.emphasized = emphasized; self @@ -116,6 +139,7 @@ pub struct SelectableList { } impl SelectableList { + /// Public API item. pub fn new(id: impl Into) -> Self { Self { id: id.into(), @@ -134,11 +158,13 @@ impl SelectableList { } } + /// Public API item. pub fn item(mut self, item: SelectableListItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn items(mut self, items: impl IntoIterator) -> Self { self.items = items.into_iter().collect(); self @@ -169,51 +195,61 @@ impl SelectableList { self } + /// Public API item. pub fn state(mut self, state: SelectableListState) -> Self { self.state = state; self } + /// Public API item. pub fn loading(mut self, message: impl Into) -> Self { self.state = SelectableListState::Loading(message.into()); self } + /// Public API item. pub fn empty_message(mut self, message: impl Into) -> Self { self.state = SelectableListState::Empty(message.into()); self } + /// Public API item. pub fn empty_text(mut self, message: impl Into) -> Self { self.empty_text = message.into(); self } + /// Public API item. pub fn error_message(mut self, message: impl Into) -> Self { self.state = SelectableListState::Error(message.into()); self } + /// Public API item. pub fn selected(mut self, id: impl Into) -> Self { self.selected_id = Some(id.into()); self } + /// Public API item. pub fn row_height(mut self, height: f32) -> Self { self.row_height = height.max(32.0); self } + /// Public API item. pub fn max_body_height(mut self, height: f32) -> Self { self.max_body_height = Some(height.max(32.0)); self } + /// Public API item. pub fn on_select(mut self, f: impl Fn(SharedString, &mut Window, &mut App) + 'static) -> Self { self.on_select = Some(Arc::new(f)); self } + /// Public API item. pub fn on_activate( mut self, f: impl Fn(SharedString, &ClickEvent, &mut Window, &mut App) + 'static, @@ -222,6 +258,7 @@ impl SelectableList { self } + /// Public API item. pub fn on_context_menu( mut self, f: impl Fn(SharedString, &MouseDownEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-layout/src/settings_nav.rs b/crates/fluent-layout/src/settings_nav.rs index 3eb5876..88f8e4f 100644 --- a/crates/fluent-layout/src/settings_nav.rs +++ b/crates/fluent-layout/src/settings_nav.rs @@ -13,12 +13,16 @@ use gpui::{ /// A single item in a `SettingsNav` section. #[derive(Clone, Debug)] pub struct SettingsNavItem { + /// Public API item. pub id: SharedString, + /// Public API item. pub label: SharedString, + /// Public API item. pub icon: Option, } impl SettingsNavItem { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -27,6 +31,7 @@ impl SettingsNavItem { } } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self @@ -36,12 +41,16 @@ impl SettingsNavItem { /// A collapsible section in a `SettingsNav`. #[derive(Clone, Debug)] pub struct SettingsNavSection { + /// Public API item. pub title: SharedString, + /// Public API item. pub items: Vec, + /// Public API item. pub expanded: bool, } impl SettingsNavSection { + /// Public API item. pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -50,11 +59,13 @@ impl SettingsNavSection { } } + /// Public API item. pub fn item(mut self, item: SettingsNavItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn collapsed(mut self) -> Self { self.expanded = false; self @@ -84,12 +95,16 @@ impl SettingsNavSection { /// ``` #[allow(clippy::type_complexity)] pub struct SettingsNav { + /// Public API item. pub sections: Vec, + /// Public API item. pub active_id: Option, + /// Public API item. pub on_select: Option>, } impl SettingsNav { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); Self { @@ -99,6 +114,7 @@ impl SettingsNav { } } + /// Public API item. pub fn section(mut self, section: SettingsNavSection) -> Self { if self.active_id.is_none() { if let Some(first) = section.items.first() { @@ -109,16 +125,19 @@ impl SettingsNav { self } + /// Public API item. pub fn active(mut self, id: impl Into) -> Self { self.active_id = Some(id.into()); self } + /// Public API item. pub fn on_select(mut self, f: impl Fn(SharedString, &mut App) + 'static) -> Self { self.on_select = Some(Arc::new(f)); self } + /// Public API item. pub fn set_active(&mut self, id: SharedString, cx: &mut Context) { self.active_id = Some(id); cx.notify(); diff --git a/crates/fluent-layout/src/tab_strip.rs b/crates/fluent-layout/src/tab_strip.rs index de1b9a3..b750aa6 100644 --- a/crates/fluent-layout/src/tab_strip.rs +++ b/crates/fluent-layout/src/tab_strip.rs @@ -11,12 +11,16 @@ use gpui::{ pub struct TabItem { /// Stable identifier for the tab (used to key close/select events). pub id: SharedString, + /// Public API item. pub label: SharedString, + /// Public API item. pub icon: Option, + /// Public API item. pub closable: bool, } impl TabItem { + /// Public API item. pub fn new(id: impl Into) -> Self { Self { id: id.into(), @@ -26,16 +30,19 @@ impl TabItem { } } + /// Public API item. pub fn label(mut self, label: impl Into) -> Self { self.label = label.into(); self } + /// Public API item. pub fn icon(mut self, path: impl Into) -> Self { self.icon = Some(path.into()); self } + /// Public API item. pub fn closable(mut self, closable: bool) -> Self { self.closable = closable; self @@ -46,7 +53,9 @@ impl TabItem { #[allow(clippy::type_complexity)] #[derive(Default)] pub struct TabStrip { + /// Public API item. pub tabs: Vec, + /// Public API item. pub active: usize, focus_handles: Vec, on_select: Option) + 'static>>, @@ -54,6 +63,7 @@ pub struct TabStrip { } impl TabStrip { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) @@ -61,10 +71,12 @@ impl TabStrip { Self::default() } + /// Public API item. pub fn add_tab(&mut self, tab: TabItem) { self.tabs.push(tab); } + /// Public API item. pub fn remove_tab(&mut self, idx: usize) { if idx < self.tabs.len() { self.tabs.remove(idx); @@ -76,6 +88,7 @@ impl TabStrip { } } + /// Public API item. pub fn on_select( mut self, f: impl Fn(usize, &TabStrip, &mut Window, &mut Context) + 'static, @@ -84,6 +97,7 @@ impl TabStrip { self } + /// Public API item. pub fn on_close( mut self, f: impl Fn(usize, &TabStrip, &mut Window, &mut Context) + 'static, diff --git a/crates/fluent-layout/src/toast.rs b/crates/fluent-layout/src/toast.rs index 5bd8765..8c4ca36 100644 --- a/crates/fluent-layout/src/toast.rs +++ b/crates/fluent-layout/src/toast.rs @@ -8,26 +8,40 @@ use gpui::{ use crate::{MessageBar, MessageIntent}; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +/// Public API item. pub enum ToastPlacement { + /// Public API item. TopStart, + /// Public API item. TopCenter, #[default] + /// Public API item. TopEnd, + /// Public API item. BottomStart, + /// Public API item. BottomCenter, + /// Public API item. BottomEnd, } #[derive(Clone, Debug)] +/// Public API item. pub struct Toast { + /// Public API item. pub id: SharedString, + /// Public API item. pub intent: MessageIntent, + /// Public API item. pub title: Option, + /// Public API item. pub message: SharedString, + /// Public API item. pub timeout: Option, } impl Toast { + /// Public API item. pub fn new(id: impl Into, message: impl Into) -> Self { Self { id: id.into(), @@ -38,27 +52,32 @@ impl Toast { } } + /// Public API item. pub fn intent(mut self, intent: MessageIntent) -> Self { self.intent = intent; self } + /// Public API item. pub fn title(mut self, title: impl Into) -> Self { self.title = Some(title.into()); self } + /// Public API item. pub fn timeout(mut self, timeout: impl Into>) -> Self { self.timeout = timeout.into(); self } + /// Public API item. pub fn persistent(mut self) -> Self { self.timeout = None; self } } +/// Public API item. pub struct ToastStack { entries: Vec, max_entries: usize, @@ -67,6 +86,7 @@ pub struct ToastStack { impl Global for ToastStack {} impl ToastStack { + /// Public API item. pub fn init(cx: &mut gpui::App) { cx.set_global(ToastStack { entries: Vec::new(), @@ -74,6 +94,7 @@ impl ToastStack { }); } + /// Public API item. pub fn push(toast: Toast, cx: &mut gpui::App) { let id = toast.id.clone(); let timeout = toast.timeout; @@ -96,6 +117,7 @@ impl ToastStack { } } + /// Public API item. pub fn set_max_entries(max_entries: usize, cx: &mut gpui::App) { let stack = cx.global_mut::(); stack.max_entries = max_entries.max(1); @@ -105,22 +127,26 @@ impl ToastStack { } } + /// Public API item. pub fn max_entries(cx: &gpui::App) -> usize { cx.global::().max_entries } + /// Public API item. pub fn dismiss(id: &str, cx: &mut gpui::App) { cx.global_mut::() .entries .retain(|toast| toast.id.as_ref() != id); } + /// Public API item. pub fn clear(cx: &mut gpui::App) { cx.global_mut::().entries.clear(); } } #[derive(Default)] +/// Public API item. pub struct ToastHost { observing: bool, placement: ToastPlacement, @@ -128,6 +154,7 @@ pub struct ToastHost { } impl ToastHost { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); cx.observe_global::(|_, cx| cx.notify()) @@ -139,11 +166,13 @@ impl ToastHost { } } + /// Public API item. pub fn placement(mut self, placement: ToastPlacement) -> Self { self.placement = placement; self } + /// Public API item. pub fn width(mut self, width: f32) -> Self { self.width = width; self diff --git a/crates/fluent-layout/src/toolbar.rs b/crates/fluent-layout/src/toolbar.rs index 22207c5..210a5c5 100644 --- a/crates/fluent-layout/src/toolbar.rs +++ b/crates/fluent-layout/src/toolbar.rs @@ -18,26 +18,42 @@ struct Roving { } #[derive(Clone)] +/// Public API item. pub enum ToolbarItem { + /// Public API item. Action { + /// Public API item. id: SharedString, + /// Public API item. label: SharedString, + /// Public API item. icon: Option, + /// Public API item. disabled: bool, + /// Public API item. on_click: ToolbarClick, }, + /// Public API item. Toggle { + /// Public API item. id: SharedString, + /// Public API item. label: SharedString, + /// Public API item. icon: Option, + /// Public API item. selected: bool, + /// Public API item. disabled: bool, + /// Public API item. on_click: ToolbarToggleClick, }, + /// Public API item. Separator, } impl ToolbarItem { + /// Public API item. pub fn action( id: impl Into, label: impl Into, @@ -52,6 +68,7 @@ impl ToolbarItem { } } + /// Public API item. pub fn action_with_icon( id: impl Into, label: impl Into, @@ -67,6 +84,7 @@ impl ToolbarItem { } } + /// Public API item. pub fn toggle( id: impl Into, label: impl Into, @@ -83,10 +101,12 @@ impl ToolbarItem { } } + /// Public API item. pub fn separator() -> Self { Self::Separator } + /// Public API item. pub fn disabled(self, disabled: bool) -> Self { match self { Self::Action { @@ -133,6 +153,7 @@ pub struct Toolbar { } impl Toolbar { + /// Public API item. pub fn new() -> Self { Self { id: "toolbar".into(), @@ -149,26 +170,31 @@ impl Toolbar { self } + /// Public API item. pub fn item(mut self, item: ToolbarItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn items(mut self, items: impl IntoIterator) -> Self { self.items = items.into_iter().collect(); self } + /// Public API item. pub fn max_visible(mut self, max_visible: usize) -> Self { self.max_visible = Some(max_visible); self } + /// Public API item. pub fn overflow_open(mut self, open: bool) -> Self { self.overflow_open = open; self } + /// Public API item. pub fn on_overflow_click( mut self, f: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-layout/src/tree.rs b/crates/fluent-layout/src/tree.rs index b41de65..a01dd7d 100644 --- a/crates/fluent-layout/src/tree.rs +++ b/crates/fluent-layout/src/tree.rs @@ -42,19 +42,30 @@ struct TreeRenderState { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum TreeCheckState { #[default] + /// Public API item. Unchecked, + /// Public API item. Checked, + /// Public API item. Mixed, } #[derive(Clone, Debug)] +/// Public API item. pub struct TreeItem { + /// Public API item. pub id: SharedString, + /// Public API item. pub label: SharedString, + /// Public API item. pub icon: Option, + /// Public API item. pub badge: Option, + /// Public API item. pub expanded: bool, + /// Public API item. pub disabled: bool, + /// Public API item. pub children: Vec, checkable: bool, checked: bool, @@ -65,6 +76,7 @@ pub struct TreeItem { } impl TreeItem { + /// Public API item. pub fn new(id: impl Into, label: impl Into) -> Self { Self { id: id.into(), @@ -81,26 +93,31 @@ impl TreeItem { } } + /// Public API item. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); self } + /// Public API item. pub fn badge(mut self, badge: impl Into) -> Self { self.badge = Some(badge.into()); self } + /// Public API item. pub fn expanded(mut self, expanded: bool) -> Self { self.expanded = expanded; self } + /// Public API item. pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } + /// Public API item. pub fn child(mut self, child: TreeItem) -> Self { self.children.push(child); self @@ -261,6 +278,7 @@ impl Tree { } } + /// Public API item. pub fn new() -> Self { Self { items: Vec::new(), @@ -282,21 +300,25 @@ impl Tree { self } + /// Public API item. pub fn item(mut self, item: TreeItem) -> Self { self.items.push(item); self } + /// Public API item. pub fn items(mut self, items: impl IntoIterator) -> Self { self.items = items.into_iter().collect(); self } + /// Public API item. pub fn selected(mut self, id: impl Into) -> Self { self.selected_id = Some(id.into()); self } + /// Public API item. pub fn filter(mut self, query: impl Into) -> Self { let query = query.into(); if !query.is_empty() { @@ -305,6 +327,7 @@ impl Tree { self } + /// Public API item. pub fn on_select( mut self, f: impl Fn(SharedString, &ClickEvent, &mut Window, &mut App) + 'static, @@ -313,6 +336,7 @@ impl Tree { self } + /// Public API item. pub fn on_activate( mut self, f: impl Fn(SharedString, &ClickEvent, &mut Window, &mut App) + 'static, @@ -321,6 +345,7 @@ impl Tree { self } + /// Public API item. pub fn on_toggle( mut self, f: impl Fn(SharedString, bool, &ClickEvent, &mut Window, &mut App) + 'static, @@ -329,6 +354,7 @@ impl Tree { self } + /// Public API item. pub fn on_context_menu( mut self, f: impl Fn(SharedString, &MouseDownEvent, &mut Window, &mut App) + 'static, diff --git a/crates/fluent-layout/src/virtual_list.rs b/crates/fluent-layout/src/virtual_list.rs index 1483d51..0d2d261 100644 --- a/crates/fluent-layout/src/virtual_list.rs +++ b/crates/fluent-layout/src/virtual_list.rs @@ -35,6 +35,7 @@ pub struct VirtualList { } impl VirtualList { + /// Public API item. pub fn new( id: impl Into, count: usize, diff --git a/crates/fluent-layout/src/workspace.rs b/crates/fluent-layout/src/workspace.rs index 2aa49c4..73d28c5 100644 --- a/crates/fluent-layout/src/workspace.rs +++ b/crates/fluent-layout/src/workspace.rs @@ -13,13 +13,21 @@ use crate::{ /// left/right/bottom dock panels, central pane area, and modal host overlay. #[derive(Default)] pub struct Workspace { + /// Public API item. pub title_bar: Option, + /// Public API item. pub menu_bar: Option>, + /// Public API item. pub ribbon: Option, + /// Public API item. pub left_dock: Option>, + /// Public API item. pub right_dock: Option>, + /// Public API item. pub bottom_dock: Option>, + /// Public API item. pub content: Option, + /// Public API item. pub modal_host: Option>, /// Optional thin status bar rendered at the very bottom of the window (below the body). pub status_bar: Option, @@ -28,16 +36,19 @@ pub struct Workspace { } impl Workspace { + /// Public API item. pub fn new(cx: &mut Context) -> Self { cx.observe_global::(|_, cx| cx.notify()).detach(); Self::default() } + /// Public API item. pub fn title_bar(mut self, bar: AnyView) -> Self { self.title_bar = Some(bar); self } + /// Public API item. pub fn menu_bar(mut self, bar: Entity) -> Self { self.menu_bar = Some(bar); self @@ -52,46 +63,55 @@ impl Workspace { self } + /// Public API item. pub fn ribbon(mut self, ribbon: AnyView) -> Self { self.ribbon = Some(ribbon); self } + /// Public API item. pub fn left_dock(mut self, dock: Entity) -> Self { self.left_dock = Some(dock); self } + /// Public API item. pub fn right_dock(mut self, dock: Entity) -> Self { self.right_dock = Some(dock); self } + /// Public API item. pub fn bottom_dock(mut self, dock: Entity) -> Self { self.bottom_dock = Some(dock); self } + /// Public API item. pub fn content(mut self, view: AnyView) -> Self { self.content = Some(view); self } + /// Public API item. pub fn modal_host(mut self, host: Entity) -> Self { self.modal_host = Some(host); self } + /// Public API item. pub fn status_bar(mut self, bar: AnyView) -> Self { self.status_bar = Some(bar); self } + /// Public API item. pub fn set_status_bar(&mut self, bar: AnyView, cx: &mut Context) { self.status_bar = Some(bar); cx.notify(); } + /// Public API item. pub fn set_content(&mut self, view: AnyView, cx: &mut Context) { self.content = Some(view); cx.notify(); diff --git a/deny.toml b/deny.toml index 7f8580c..06360c1 100644 --- a/deny.toml +++ b/deny.toml @@ -40,6 +40,21 @@ exceptions = [ [licenses.private] ignore = true +[advisories] +# These advisories are currently reachable through the pinned vendored Zed +# snapshot or its platform dependencies. Keep the exceptions explicit so a +# newly introduced advisory still fails this check. +ignore = [ + { id = "RUSTSEC-2026-0204", reason = "crossbeam-epoch is pinned by the vendored Zed snapshot; update is tracked with the next dependency refresh" }, + { id = "RUSTSEC-2026-0194", reason = "quick-xml is pinned by the vendored Zed snapshot; update requires a compatible upstream refresh" }, + { id = "RUSTSEC-2026-0195", reason = "quick-xml is pinned by the vendored Zed snapshot; update requires a compatible upstream refresh" }, + { id = "RUSTSEC-2026-0206", reason = "rustybuzz is required by the vendored text stack; replacement is an upstream dependency decision" }, + { id = "RUSTSEC-2026-0192", reason = "ttf-parser is required by the vendored text stack; replacement is an upstream dependency decision" }, + { id = "RUSTSEC-2026-0371", reason = "zbus_names is required by the vendored Linux accessibility stack; replacement is an upstream dependency decision" }, + { id = "RUSTSEC-2026-0370", reason = "zvariant is required by the vendored Linux accessibility stack; replacement is an upstream dependency decision" }, + { id = "RUSTSEC-2026-0372", reason = "zvariant_derive is required by the vendored Linux accessibility stack; replacement is an upstream dependency decision" }, +] + [bans] multiple-versions = "allow" wildcards = "allow" diff --git a/docs/performance.md b/docs/performance.md index c9f3669..8368026 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -17,3 +17,28 @@ notification path is changed. The VirtualList fixture makes the lazy-rendering p the 100k-row input builds only a viewport-sized slice. The initial audit found no redundant notify/re-render. No follow-up is required unless a future run exceeds a budget or observes more than one notification for an unchanged interaction. + +## Vendored GPUI baseline (WI-2730) + +The Linux baseline below was measured from a clean target directory on 2026-11-03 with +`CARGO_BUILD_JOBS=6`, the pinned toolchain from `rust-toolchain.toml`, and no `RUSTC_WRAPPER`. +The command was: + +```sh +CARGO_BUILD_JOBS=6 time -p cargo build --manifest-path vendor/zed/crates/gpui/Cargo.toml +``` + +| Measurement | Result | +| --- | ---: | +| Clean build of `gpui` and `gpui_platform` | 54.71 s | + +This was an un-cached build into a fresh `CARGO_TARGET_DIR` on Linux; the `gpui` manifest pulls +in the `gpui_platform` path dependency. Do not compare it with +cached CI builds. `cargo deny check advisories licenses bans sources` passed after applying the +explicit exceptions above. `cargo audit` reported 5 vulnerabilities and 12 allowed warnings: +the vulnerabilities were `crossbeam-epoch` (RUSTSEC-2026-0204), `quick-xml` (RUSTSEC-2026-0194 +and RUSTSEC-2026-0195), `anyhow` (RUSTSEC-2026-0190), `event-listener` (RUSTSEC-2026-0221), +`memmap2` (RUSTSEC-2026-0186), and `tokio` (RUSTSEC-2026-0386); the warnings included +unmaintained `paste`, `rustybuzz`, `ttf-parser`, `zbus_names`, `zvariant`, and +`zvariant_derive`, plus yanked `async-executor` and `spin`. The audit job remains informational +until the pinned snapshot is refreshed. diff --git a/examples/gallery/Cargo.toml b/examples/gallery/Cargo.toml index ebac85e..81c7bfb 100644 --- a/examples/gallery/Cargo.toml +++ b/examples/gallery/Cargo.toml @@ -9,3 +9,4 @@ fluent-core = { workspace = true } fluent-ribbon = { workspace = true } fluent-layout = { workspace = true } fluent-app = { workspace = true } +fluent-primitives = { workspace = true } diff --git a/examples/gallery/src/families.rs b/examples/gallery/src/families.rs index 61a8bf6..66e9d01 100644 --- a/examples/gallery/src/families.rs +++ b/examples/gallery/src/families.rs @@ -5,12 +5,90 @@ //! theme row on top switches light, dark, high contrast and RTL so each //! family can be checked in every variant without leaving the page. +use fluent_core::gpui::{ + div, prelude::*, AnyElement, AnyView, Context, Entity, IntoElement, Render, Window, +}; +use fluent_core::{LayoutDirection, Theme, ThemeProvider as _}; use fluent_primitives::{ Button, ButtonAppearance, ButtonIconPosition, ButtonShape, ButtonSize, Checkbox, CheckboxState, - Chip, Divider, Label, LabelSize, Link, LinkAppearance, RadioGroup, Switch, ToggleButton, + Chip, Divider, Expander, InputCapture, Label, LabelSize, Link, LinkAppearance, RadioGroup, + Switch, TerminalView, ToggleButton, VideoSurface, }; -use fluent_core::gpui::{div, prelude::*, AnyElement, AnyView, Context, Entity, IntoElement, Render, Window}; -use fluent_core::gpui::{LayoutDirection, Theme, ThemeProvider as _}; + +pub struct VideoPage { + pub surface: Entity, +} +impl Render for VideoPage { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div() + .flex() + .flex_col() + .gap_2() + .child(Label::new("VideoSurface — synthetic moving test pattern")) + .child(self.surface.clone()) + } +} +pub struct TerminalPage { + pub terminal: Entity, +} +impl Render for TerminalPage { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div() + .flex() + .flex_col() + .gap_2() + .child(Label::new("TerminalView — scripted terminal text")) + .child(self.terminal.clone()) + } +} +#[derive(Default)] +pub struct EventLog; +impl Render for EventLog { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div().p_2().child( + "Click or press a key to exercise InputCapture (events are synthetic in this page).", + ) + } +} +pub struct InputPage { + pub capture: Entity, +} +impl Render for InputPage { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div() + .flex() + .flex_col() + .gap_2() + .child(Label::new("InputCapture — live key and pointer event log")) + .child(self.capture.clone()) + } +} +pub struct ExpanderPage; +impl Render for ExpanderPage { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + div() + .flex() + .flex_col() + .gap_2() + .child(Label::new( + "Expander — collapsed, expanded, and disabled states", + )) + .child( + Expander::new("collapsed", "Collapsed") + .content(Label::new("Hidden until expanded").into_any_element()), + ) + .child( + Expander::new("expanded", "Expanded") + .expanded(true) + .content(Label::new("Visible content").into_any_element()), + ) + .child( + Expander::new("disabled", "Disabled") + .disabled(true) + .content(Label::new("Unavailable content").into_any_element()), + ) + } +} /// A Fluent 2 component family, one gallery route each. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/examples/gallery/src/main.rs b/examples/gallery/src/main.rs index 6729df4..e148f55 100644 --- a/examples/gallery/src/main.rs +++ b/examples/gallery/src/main.rs @@ -1,11 +1,12 @@ +use families::{DemoViews, FamilyHost, FamilyNav}; use fluent_app::{FluentApp, TitleBar}; use fluent_core::gpui::{div, prelude::*, Context, IntoElement, Render, Window}; -use fluent_core::ThemeProvider as _; use fluent_layout::{ - DockPanel, DockPosition, MenuBar, ModalStack, Pane, PaneConstraints, PaneGroup, TabItem, - TabStrip, Workspace, + DockPanel, DockPosition, MenuBar, ModalStack, Pane, TabItem, TabStrip, Workspace, }; +use fluent_primitives::{InputCapture, TerminalCell, TerminalGrid, TerminalView, VideoSurface}; use fluent_ribbon::RibbonBar; +mod families; // --------------------------------------------------------------------------- // Root gallery view — wires the full shell together @@ -21,34 +22,56 @@ impl Render for GalleryRoot { } } -// --------------------------------------------------------------------------- -// Placeholder pane content -// --------------------------------------------------------------------------- - -struct PlaceholderView { - label: fluent_core::gpui::SharedString, -} - -impl Render for PlaceholderView { - fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let colors = cx.theme().colors.clone(); - div() - .size_full() - .flex() - .items_center() - .justify_center() - .bg(colors.surface) - .text_color(colors.on_subtle) - .child(self.label.clone()) - } -} - // --------------------------------------------------------------------------- // Entry point // --------------------------------------------------------------------------- fn main() { FluentApp::new("FluentGUI Gallery").dark_theme().run(|cx| { + let video = cx.new(VideoSurface::new); + video.update(cx, |surface, cx| { + let mut pixels = Vec::with_capacity(160 * 90 * 4); + for y in 0..90u32 { + for x in 0..160u32 { + pixels.extend([((x * 255) / 159) as u8, ((y * 255) / 89) as u8, 180, 255]); + } + } + let _ = surface.submit_frame(160, 90, pixels, cx); + }); + let video_page = cx.new(|_| families::VideoPage { surface: video }); + + let grid = cx.new(|_| TerminalGrid::new(64, 12)); + grid.update(cx, |grid, _| { + for (row, line) in [ + "Fluent terminal demo", + "$ cargo run --example gallery", + "[ OK ] compositor connected", + "[ OK ] synthetic output ready", + "Type, scroll, and select this terminal surface.", + ] + .iter() + .enumerate() + { + grid.write_str(row, 0, line, TerminalCell::new(' ')); + } + }); + let terminal = cx.new(|cx| TerminalView::new(grid, cx).label("Scripted terminal")); + let terminal_page = cx.new(|_| families::TerminalPage { terminal }); + + let capture_log = cx.new(|_| families::EventLog); + let capture = cx.new(|cx| InputCapture::new(cx).content(capture_log.clone().into())); + let input_page = cx.new(|_| families::InputPage { capture }); + + let expander_page = cx.new(|_| families::ExpanderPage); + let family_host = cx.new(|_| { + FamilyHost::new(DemoViews { + status: Vec::new(), + data: Vec::new(), + date_input: Vec::new(), + media: vec![video_page.clone().into(), terminal_page.clone().into()], + theme: vec![input_page.clone().into(), expander_page.clone().into()], + }) + }); // Title bar let title_bar = cx.new(|cx| TitleBar::new(cx, "FluentGUI Gallery")); @@ -92,13 +115,10 @@ fn main() { }); // Left sidebar - let sidebar_content = cx.new(|_| PlaceholderView { - label: "Navigation tree".into(), - }); let sidebar = cx.new(|cx| { DockPanel::new(cx, DockPosition::Left, "Navigation") .size(240.0) - .content(sidebar_content.into()) + .content(cx.new(|_| FamilyNav::new(family_host.clone())).into()) }); // Main pane with a tab strip @@ -108,28 +128,10 @@ fn main() { ts.add_tab(TabItem::new("settings").label("Settings").closable(true)); ts }); - let split_list = cx.new(|_| PlaceholderView { - label: "Resizable first panel".into(), - }); - let split_detail = cx.new(|_| PlaceholderView { - label: "Resizable second panel".into(), - }); - let pane_content = cx.new(|_| { - PaneGroup::horizontal() - .first(split_list.into()) - .second(split_detail.into()) - .ratio(0.36) - .constraints( - PaneConstraints::new() - .first_min(220.0) - .second_min(320.0) - .first_max(Some(520.0)), - ) - }); let main_pane = cx.new(|cx| Pane::new(cx).with_tab_strip(tab_strip)); // set content separately since we need the entity main_pane.update(cx, |p, cx| { - p.set_content(pane_content.into(), cx); + p.set_content(family_host.into(), cx); }); // Modal host