Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:29:45.793Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

example_input.rs

122 lines · 3.9 KB · rust
1//! `Input` — a single-line text input. The shaping layer over `Editor`.
2//!
3//! Construct it two ways, depending on how much state you want to own:
4//!   * `Input::new(value: Entity<String>)`  — you hold just the string; the input
5//!     allocates the `Editor` internally via `use_state`. Value readable, cursor hidden.
6//!   * `Input::editor(editor: Entity<Editor>)` — you hold the editor; cursor/selection
7//!     are now yours to read and drive too.
8//!
9//! Either way the chrome is identical. Because the string (or editor) is the
10//! input's *identity*, the internal `use_state(Editor)` is collision-safe across
11//! any number of inputs.
12
13use gpui::{
14    App, BoxShadow, CursorStyle, Entity, EntityId, Hsla, IntoElement, Pixels, StyleRefinement,
15    Window, div, hsla, point, prelude::*, px, white,
16};
17
18use crate::example_editor::{Editor, standard_actions};
19
20enum Source {
21    Value(Entity<String>),
22    Editor(Entity<Editor>),
23}
24
25#[derive(IntoElement)]
26pub struct Input {
27    source: Source,
28    width: Option<Pixels>,
29    color: Option<Hsla>,
30}
31
32impl Input {
33    /// Backed by a bare string; the editor is allocated internally.
34    pub fn new(value: Entity<String>) -> Self {
35        Self {
36            source: Source::Value(value),
37            width: None,
38            color: None,
39        }
40    }
41
42    /// Backed by an editor you own (so you can read/drive its cursor).
43    pub fn editor(editor: Entity<Editor>) -> Self {
44        Self {
45            source: Source::Editor(editor),
46            width: None,
47            color: None,
48        }
49    }
50
51    pub fn width(mut self, width: Pixels) -> Self {
52        self.width = Some(width);
53        self
54    }
55
56    pub fn color(mut self, color: Hsla) -> Self {
57        self.color = Some(color);
58        self
59    }
60}
61
62impl gpui::View for Input {
63    fn entity_id(&self) -> Option<EntityId> {
64        Some(match &self.source {
65            Source::Value(value) => value.entity_id(),
66            Source::Editor(editor) => editor.entity_id(),
67        })
68    }
69
70    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
71        // Get the editor: use the one we were handed, or allocate it under our
72        // own (string-derived) identity so it persists and never collides.
73        let editor = match self.source {
74            Source::Value(value) => {
75                window.use_state(cx, move |window, cx| Editor::over(value, window, cx))
76            }
77            Source::Editor(editor) => editor,
78        };
79
80        let focus_handle = editor.read(cx).focus_handle.clone();
81        let is_focused = focus_handle.is_focused(window);
82        let text_color = self.color.unwrap_or(hsla(0., 0., 0.1, 1.));
83        let box_width = self.width.unwrap_or(px(300.));
84
85        let border = if is_focused {
86            hsla(220. / 360., 0.8, 0.5, 1.)
87        } else {
88            hsla(0., 0., 0.75, 1.)
89        };
90
91        div()
92            .id("input")
93            .key_context("TextInput")
94            .track_focus(&focus_handle)
95            .cursor(CursorStyle::IBeam)
96            .map(standard_actions(editor.clone()))
97            .w(box_width)
98            .h(px(36.))
99            .px(px(8.))
100            .bg(white())
101            .border_1()
102            .border_color(border)
103            .when(is_focused, |this| {
104                this.shadow(vec![BoxShadow {
105                    color: hsla(220. / 360., 0.8, 0.5, 0.3),
106                    offset: point(px(0.), px(0.)),
107                    blur_radius: px(4.),
108                    spread_radius: px(1.),
109                    inset: false,
110                }])
111            })
112            .rounded(px(4.))
113            .overflow_hidden()
114            .flex()
115            .items_center()
116            .line_height(px(20.))
117            .text_size(px(14.))
118            .text_color(text_color)
119            .child(editor.cached(StyleRefinement::default().size_full()))
120    }
121}
122
Served at tenant.openagents/omega Member data and write actions are omitted.