Showing preview only (4,470K chars total). Download the full file or copy to clipboard to get everything.
Repository: longbridge/gpui-component
Branch: main
Commit: 311c7e0d104d
Files: 547
Total size: 4.2 MB
Directory structure:
gitextract_xlkzxety/
├── .cargo/
│ └── config.toml
├── .claude/
│ ├── COMPONENT_TEST_RULES.md
│ └── skills/
│ ├── generate-component-documentation/
│ │ └── SKILL.md
│ ├── generate-component-story/
│ │ └── SKILL.md
│ ├── github-pull-request-description/
│ │ └── SKILL.md
│ ├── gpui-action/
│ │ └── SKILL.md
│ ├── gpui-async/
│ │ └── SKILL.md
│ ├── gpui-context/
│ │ └── SKILL.md
│ ├── gpui-element/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced-patterns.md
│ │ ├── api-reference.md
│ │ ├── best-practices.md
│ │ ├── examples.md
│ │ └── patterns.md
│ ├── gpui-entity/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced.md
│ │ ├── api-reference.md
│ │ ├── best-practices.md
│ │ └── patterns.md
│ ├── gpui-event/
│ │ └── SKILL.md
│ ├── gpui-focus-handle/
│ │ └── SKILL.md
│ ├── gpui-global/
│ │ └── SKILL.md
│ ├── gpui-layout-and-style/
│ │ └── SKILL.md
│ ├── gpui-style-guide/
│ │ └── SKILL.md
│ ├── gpui-test/
│ │ ├── SKILL.md
│ │ ├── examples.md
│ │ └── reference.md
│ └── new-component/
│ └── SKILL.md
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── 01_bug.md
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── ci.yml
│ ├── release-docs.yml
│ ├── release.yml
│ └── test-docs.yml
├── .gitignore
├── .rustfmt.toml
├── .theme-schema.json
├── CLAUDE.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── Makefile
├── README.md
├── crates/
│ ├── assets/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── assets/
│ │ │ └── .gitkeep
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── native_assets.rs
│ │ └── wasm_assets.rs
│ ├── macros/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── derive_into_plot.rs
│ │ └── lib.rs
│ ├── story/
│ │ ├── Cargo.toml
│ │ ├── examples/
│ │ │ ├── brush.rs
│ │ │ ├── dock.rs
│ │ │ ├── editor.rs
│ │ │ ├── fixtures/
│ │ │ │ ├── completion_items.json
│ │ │ │ ├── test.astro
│ │ │ │ ├── test.c
│ │ │ │ ├── test.go
│ │ │ │ ├── test.html
│ │ │ │ ├── test.js
│ │ │ │ ├── test.json
│ │ │ │ ├── test.kt
│ │ │ │ ├── test.lua
│ │ │ │ ├── test.md
│ │ │ │ ├── test.nv
│ │ │ │ ├── test.php
│ │ │ │ ├── test.py
│ │ │ │ ├── test.rb
│ │ │ │ ├── test.rs
│ │ │ │ ├── test.sql
│ │ │ │ ├── test.svelte
│ │ │ │ ├── test.ts
│ │ │ │ └── test.zig
│ │ │ ├── html.rs
│ │ │ ├── large-text.rs
│ │ │ ├── markdown.rs
│ │ │ ├── stream_markdown.rs
│ │ │ └── tiles.rs
│ │ └── src/
│ │ ├── app_menus.rs
│ │ ├── embedded_themes.rs
│ │ ├── fixtures/
│ │ │ ├── counters.json
│ │ │ ├── countries.json
│ │ │ ├── daily-devices.json
│ │ │ ├── monthly-devices.json
│ │ │ └── stock-prices.json
│ │ ├── gallery.rs
│ │ ├── lib.rs
│ │ ├── main.rs
│ │ ├── stories/
│ │ │ ├── accordion_story.rs
│ │ │ ├── alert_dialog_story.rs
│ │ │ ├── alert_story.rs
│ │ │ ├── avatar_story.rs
│ │ │ ├── badge_story.rs
│ │ │ ├── breadcrumb_story.rs
│ │ │ ├── button_story.rs
│ │ │ ├── calendar_story.rs
│ │ │ ├── chart_story/
│ │ │ │ ├── chart_story.rs
│ │ │ │ └── stacked_bar_chart.rs
│ │ │ ├── chart_story.rs
│ │ │ ├── checkbox_story.rs
│ │ │ ├── clipboard_story.rs
│ │ │ ├── collapsible_story.rs
│ │ │ ├── color_picker_story.rs
│ │ │ ├── data_table_story.rs
│ │ │ ├── date_picker_story.rs
│ │ │ ├── description_list_story.rs
│ │ │ ├── dialog_story.rs
│ │ │ ├── divider_story.rs
│ │ │ ├── dropdown_button_story.rs
│ │ │ ├── editor_story.rs
│ │ │ ├── form_story.rs
│ │ │ ├── group_box_story.rs
│ │ │ ├── hover_card_story.rs
│ │ │ ├── icon_story.rs
│ │ │ ├── image_story.rs
│ │ │ ├── input_story.rs
│ │ │ ├── kbd_story.rs
│ │ │ ├── label_story.rs
│ │ │ ├── list_story.rs
│ │ │ ├── menu_story.rs
│ │ │ ├── mod.rs
│ │ │ ├── notification_story.rs
│ │ │ ├── number_input_story.rs
│ │ │ ├── otp_input_story.rs
│ │ │ ├── pagination_story.rs
│ │ │ ├── popover_story.rs
│ │ │ ├── progress_story.rs
│ │ │ ├── radio_story.rs
│ │ │ ├── rating_story.rs
│ │ │ ├── resizable_story.rs
│ │ │ ├── scrollbar_story.rs
│ │ │ ├── select_story.rs
│ │ │ ├── settings_story.rs
│ │ │ ├── sheet_story.rs
│ │ │ ├── sidebar_story.rs
│ │ │ ├── skeleton_story.rs
│ │ │ ├── slider_story.rs
│ │ │ ├── spinner_story.rs
│ │ │ ├── stepper_story.rs
│ │ │ ├── switch_story.rs
│ │ │ ├── table_story.rs
│ │ │ ├── tabs_story.rs
│ │ │ ├── tag_story.rs
│ │ │ ├── textarea_story.rs
│ │ │ ├── theme_story/
│ │ │ │ ├── checkerboard.rs
│ │ │ │ ├── color_theme_story.rs
│ │ │ │ ├── mapper.rs
│ │ │ │ └── mod.rs
│ │ │ ├── toggle_story.rs
│ │ │ ├── tooltip_story.rs
│ │ │ ├── tree_story.rs
│ │ │ ├── virtual_list_story.rs
│ │ │ └── welcome_story.rs
│ │ ├── themes.rs
│ │ └── title_bar.rs
│ ├── story-web/
│ │ ├── .cargo/
│ │ │ └── config.toml
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── rust-toolchain.toml
│ │ ├── scripts/
│ │ │ └── build-wasm.sh
│ │ ├── src/
│ │ │ └── lib.rs
│ │ └── www/
│ │ ├── .gitignore
│ │ ├── .prettierrc
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── main.js
│ │ └── vite.config.js
│ ├── ui/
│ │ ├── Cargo.toml
│ │ ├── LICENSE-APACHE
│ │ ├── build.rs
│ │ ├── locales/
│ │ │ └── ui.yml
│ │ └── src/
│ │ ├── accordion.rs
│ │ ├── actions.rs
│ │ ├── alert.rs
│ │ ├── anchored.rs
│ │ ├── animation.rs
│ │ ├── async_util.rs
│ │ ├── avatar/
│ │ │ ├── avatar.rs
│ │ │ ├── avatar_group.rs
│ │ │ └── mod.rs
│ │ ├── badge.rs
│ │ ├── breadcrumb.rs
│ │ ├── button/
│ │ │ ├── button.rs
│ │ │ ├── button_group.rs
│ │ │ ├── button_icon.rs
│ │ │ ├── dropdown_button.rs
│ │ │ ├── mod.rs
│ │ │ └── toggle.rs
│ │ ├── chart/
│ │ │ ├── area_chart.rs
│ │ │ ├── bar_chart.rs
│ │ │ ├── candlestick_chart.rs
│ │ │ ├── line_chart.rs
│ │ │ ├── mod.rs
│ │ │ └── pie_chart.rs
│ │ ├── checkbox.rs
│ │ ├── clipboard.rs
│ │ ├── collapsible.rs
│ │ ├── color_picker.rs
│ │ ├── description_list.rs
│ │ ├── dialog/
│ │ │ ├── alert_dialog.rs
│ │ │ ├── content.rs
│ │ │ ├── description.rs
│ │ │ ├── dialog.rs
│ │ │ ├── footer.rs
│ │ │ ├── header.rs
│ │ │ ├── mod.rs
│ │ │ └── title.rs
│ │ ├── divider.rs
│ │ ├── dock/
│ │ │ ├── dock.rs
│ │ │ ├── invalid_panel.rs
│ │ │ ├── mod.rs
│ │ │ ├── panel.rs
│ │ │ ├── stack_panel.rs
│ │ │ ├── state.rs
│ │ │ ├── tab_panel.rs
│ │ │ └── tiles.rs
│ │ ├── element_ext.rs
│ │ ├── event.rs
│ │ ├── fixtures/
│ │ │ └── layout.json
│ │ ├── focus_trap.rs
│ │ ├── form/
│ │ │ ├── field.rs
│ │ │ ├── form.rs
│ │ │ └── mod.rs
│ │ ├── geometry.rs
│ │ ├── global_state.rs
│ │ ├── group_box.rs
│ │ ├── highlighter/
│ │ │ ├── diagnostics.rs
│ │ │ ├── highlighter.rs
│ │ │ ├── languages/
│ │ │ │ ├── go/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── html/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── javascript/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── json/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── kotlin/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── lua/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── markdown/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── markdown_inline/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── php/
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── rust/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── typescript/
│ │ │ │ │ └── highlights.scm
│ │ │ │ └── zig/
│ │ │ │ ├── highlights.scm
│ │ │ │ └── injections.scm
│ │ │ ├── languages.rs
│ │ │ ├── mod.rs
│ │ │ ├── registry.rs
│ │ │ └── wasm_stub.rs
│ │ ├── history.rs
│ │ ├── hover_card.rs
│ │ ├── icon.rs
│ │ ├── index_path.rs
│ │ ├── input/
│ │ │ ├── blink_cursor.rs
│ │ │ ├── change.rs
│ │ │ ├── clear_button.rs
│ │ │ ├── cursor.rs
│ │ │ ├── display_map/
│ │ │ │ ├── README.md
│ │ │ │ ├── display_map.rs
│ │ │ │ ├── fold_map.rs
│ │ │ │ ├── folding.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── text_wrapper.rs
│ │ │ │ └── wrap_map.rs
│ │ │ ├── element.rs
│ │ │ ├── indent.rs
│ │ │ ├── input.rs
│ │ │ ├── lsp/
│ │ │ │ ├── code_actions.rs
│ │ │ │ ├── completions.rs
│ │ │ │ ├── definitions.rs
│ │ │ │ ├── document_colors.rs
│ │ │ │ ├── hover.rs
│ │ │ │ └── mod.rs
│ │ │ ├── mask_pattern.rs
│ │ │ ├── mod.rs
│ │ │ ├── mode.rs
│ │ │ ├── movement.rs
│ │ │ ├── number_input.rs
│ │ │ ├── otp_input.rs
│ │ │ ├── popovers/
│ │ │ │ ├── code_action_menu.rs
│ │ │ │ ├── completion_menu.rs
│ │ │ │ ├── context_menu.rs
│ │ │ │ ├── diagnostic_popover.rs
│ │ │ │ ├── hover_popover.rs
│ │ │ │ └── mod.rs
│ │ │ ├── rope_ext.rs
│ │ │ ├── search.rs
│ │ │ ├── selection.rs
│ │ │ └── state.rs
│ │ ├── inspector.rs
│ │ ├── kbd.rs
│ │ ├── label.rs
│ │ ├── lib.rs
│ │ ├── link.rs
│ │ ├── list/
│ │ │ ├── cache.rs
│ │ │ ├── delegate.rs
│ │ │ ├── list.rs
│ │ │ ├── list_item.rs
│ │ │ ├── loading.rs
│ │ │ ├── mod.rs
│ │ │ └── separator_item.rs
│ │ ├── menu/
│ │ │ ├── app_menu_bar.rs
│ │ │ ├── context_menu.rs
│ │ │ ├── dropdown_menu.rs
│ │ │ ├── menu_item.rs
│ │ │ ├── mod.rs
│ │ │ └── popup_menu.rs
│ │ ├── notification.rs
│ │ ├── pagination.rs
│ │ ├── plot/
│ │ │ ├── axis.rs
│ │ │ ├── grid.rs
│ │ │ ├── label.rs
│ │ │ ├── mod.rs
│ │ │ ├── scale/
│ │ │ │ ├── band.rs
│ │ │ │ ├── linear.rs
│ │ │ │ ├── ordinal.rs
│ │ │ │ ├── point.rs
│ │ │ │ └── sealed.rs
│ │ │ ├── scale.rs
│ │ │ ├── shape/
│ │ │ │ ├── arc.rs
│ │ │ │ ├── area.rs
│ │ │ │ ├── bar.rs
│ │ │ │ ├── line.rs
│ │ │ │ ├── pie.rs
│ │ │ │ └── stack.rs
│ │ │ ├── shape.rs
│ │ │ └── tooltip.rs
│ │ ├── popover.rs
│ │ ├── progress/
│ │ │ ├── mod.rs
│ │ │ ├── progress.rs
│ │ │ └── progress_circle.rs
│ │ ├── radio.rs
│ │ ├── rating.rs
│ │ ├── resizable/
│ │ │ ├── mod.rs
│ │ │ ├── panel.rs
│ │ │ └── resize_handle.rs
│ │ ├── root.rs
│ │ ├── scroll/
│ │ │ ├── mod.rs
│ │ │ ├── scrollable.rs
│ │ │ ├── scrollable_mask.rs
│ │ │ └── scrollbar.rs
│ │ ├── select.rs
│ │ ├── setting/
│ │ │ ├── fields/
│ │ │ │ ├── bool.rs
│ │ │ │ ├── dropdown.rs
│ │ │ │ ├── element.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── number.rs
│ │ │ │ └── string.rs
│ │ │ ├── group.rs
│ │ │ ├── item.rs
│ │ │ ├── mod.rs
│ │ │ ├── page.rs
│ │ │ └── settings.rs
│ │ ├── sheet.rs
│ │ ├── sidebar/
│ │ │ ├── footer.rs
│ │ │ ├── group.rs
│ │ │ ├── header.rs
│ │ │ ├── menu.rs
│ │ │ └── mod.rs
│ │ ├── skeleton.rs
│ │ ├── slider.rs
│ │ ├── spinner.rs
│ │ ├── stepper/
│ │ │ ├── item.rs
│ │ │ ├── mod.rs
│ │ │ ├── stepper.rs
│ │ │ └── trigger.rs
│ │ ├── styled.rs
│ │ ├── switch.rs
│ │ ├── tab/
│ │ │ ├── mod.rs
│ │ │ ├── tab.rs
│ │ │ └── tab_bar.rs
│ │ ├── table/
│ │ │ ├── column.rs
│ │ │ ├── data_table.rs
│ │ │ ├── delegate.rs
│ │ │ ├── loading.rs
│ │ │ ├── mod.rs
│ │ │ ├── state.rs
│ │ │ └── table.rs
│ │ ├── tag.rs
│ │ ├── text/
│ │ │ ├── document.rs
│ │ │ ├── format/
│ │ │ │ ├── html.rs
│ │ │ │ ├── html5minify/
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── markdown.rs
│ │ │ │ └── mod.rs
│ │ │ ├── inline.rs
│ │ │ ├── mod.rs
│ │ │ ├── node.rs
│ │ │ ├── state.rs
│ │ │ ├── style.rs
│ │ │ ├── text_view.rs
│ │ │ └── utils.rs
│ │ ├── theme/
│ │ │ ├── color.rs
│ │ │ ├── default-colors.json
│ │ │ ├── default-theme.json
│ │ │ ├── mod.rs
│ │ │ ├── registry.rs
│ │ │ ├── schema.rs
│ │ │ └── theme_color.rs
│ │ ├── time/
│ │ │ ├── calendar.rs
│ │ │ ├── date_picker.rs
│ │ │ ├── mod.rs
│ │ │ └── utils.rs
│ │ ├── title_bar.rs
│ │ ├── tooltip.rs
│ │ ├── tree.rs
│ │ ├── virtual_list.rs
│ │ ├── window_border.rs
│ │ └── window_ext.rs
│ └── webview/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ └── lib.rs
├── docs/
│ ├── .gitignore
│ ├── .vitepress/
│ │ ├── config.mts
│ │ ├── language.ts
│ │ └── theme/
│ │ ├── components/
│ │ │ └── GitHubStar.vue
│ │ ├── index.ts
│ │ └── style.css
│ ├── README.md
│ ├── contributors.md
│ ├── contributors.vue
│ ├── data/
│ │ ├── contributors.data.js
│ │ ├── repo.data.js
│ │ └── skills.data.js
│ ├── docs/
│ │ ├── assets.md
│ │ ├── components/
│ │ │ ├── accordion.md
│ │ │ ├── alert-dialog.md
│ │ │ ├── alert.md
│ │ │ ├── avatar.md
│ │ │ ├── badge.md
│ │ │ ├── button.md
│ │ │ ├── calendar.md
│ │ │ ├── chart.md
│ │ │ ├── checkbox.md
│ │ │ ├── clipboard.md
│ │ │ ├── collapsible.md
│ │ │ ├── color-picker.md
│ │ │ ├── data-table.md
│ │ │ ├── date-picker.md
│ │ │ ├── description-list.md
│ │ │ ├── dialog.md
│ │ │ ├── dropdown_button.md
│ │ │ ├── editor.md
│ │ │ ├── focus-trap.md
│ │ │ ├── form.md
│ │ │ ├── group-box.md
│ │ │ ├── hover-card.md
│ │ │ ├── icon.md
│ │ │ ├── image.md
│ │ │ ├── index.md
│ │ │ ├── input.md
│ │ │ ├── kbd.md
│ │ │ ├── label.md
│ │ │ ├── list.md
│ │ │ ├── menu.md
│ │ │ ├── notification.md
│ │ │ ├── number-input.md
│ │ │ ├── otp-input.md
│ │ │ ├── pagination.md
│ │ │ ├── plot.md
│ │ │ ├── popover.md
│ │ │ ├── progress.md
│ │ │ ├── radio.md
│ │ │ ├── rating.md
│ │ │ ├── resizable.md
│ │ │ ├── scrollable.md
│ │ │ ├── select.md
│ │ │ ├── settings.md
│ │ │ ├── sheet.md
│ │ │ ├── sidebar.md
│ │ │ ├── skeleton.md
│ │ │ ├── slider.md
│ │ │ ├── spinner.md
│ │ │ ├── stepper.md
│ │ │ ├── switch.md
│ │ │ ├── table.md
│ │ │ ├── tabs.md
│ │ │ ├── tag.md
│ │ │ ├── title-bar.md
│ │ │ ├── toggle.md
│ │ │ ├── tooltip.md
│ │ │ ├── tree.md
│ │ │ └── virtual-list.md
│ │ ├── context.md
│ │ ├── element_id.md
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ ├── installation.md
│ │ ├── root.md
│ │ └── theme.md
│ ├── index.md
│ ├── index.vue
│ ├── package.json
│ ├── postcss.config.mjs
│ ├── skills.md
│ ├── skills.vue
│ └── src/
│ ├── dark.theme.json
│ └── light.theme.json
├── examples/
│ ├── README.md
│ ├── app_assets/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ └── src/
│ │ └── main.rs
│ ├── color_mix_oklab.rs
│ ├── dialog_overlay/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── focus_trap/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── hello_world/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── input/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── system_monitor/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── webview/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── window_title/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── flake.nix
├── script/
│ ├── bootstrap
│ ├── bump-version.sh
│ ├── install-linux.sh
│ └── install-window.ps1
└── themes/
├── adventure.json
├── alduin.json
├── asciinema.json
├── ayu.json
├── catppuccin.json
├── everforest.json
├── fahrenheit.json
├── flexoki.json
├── gruvbox.json
├── harper.json
├── hybrid.json
├── jellybeans.json
├── kibble.json
├── macos-classic.json
├── matrix.json
├── mellifluous.json
├── molokai.json
├── solarized.json
├── spaceduck.json
├── tokyonight.json
└── twilight.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .cargo/config.toml
================================================
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-arg=/STACK:8000000"]
================================================
FILE: .claude/COMPONENT_TEST_RULES.md
================================================
# GPUI Component Testing Rules
## Testing Principles
### 1. **Simplicity First**
- Avoid excessive simple tests
- Focus on complex logic and core functionality
### 2. **Builder Pattern Testing**
- Every component should have a `test_*_builder` test for coverage of the builder pattern
- Tests should cover all major configuration options
- Use method chaining to demonstrate complete API usage
#### Example:
```rust
#[gpui::test]
fn test_button_builder(_cx: &mut gpui::TestAppContext) {
let button = Button::new("complex-button")
.label("Save Changes")
.primary()
.outline()
.large()
.tooltip("Click to save")
.compact()
.loading(false)
.disabled(false)
.selected(false)
.on_click(|_, _, _| {});
// Assert all key properties
assert_eq!(button.label, Some("Save Changes".into()));
assert_eq!(button.variant, ButtonVariant::Primary);
assert!(button.outline);
assert_eq!(button.size, Size::Large);
}
```
### 3. **Complex Logic Testing**
- Test conditional branching logic
- Test state transitions and interactions
- Test edge cases
#### Example:
```rust
#[gpui::test]
fn test_button_clickable_logic(_cx: &mut gpui::TestAppContext) {
// Test behavior under multiple conditions
let clickable = Button::new("test").on_click(|_, _, _| {});
assert!(clickable.clickable());
let disabled = Button::new("test").disabled(true).on_click(|_, _, _| {});
assert!(!disabled.clickable());
let loading = Button::new("test").loading(true).on_click(|_, _, _| {});
assert!(!loading.clickable());
}
```
### 4. **Helper Method Testing**
- Test component helper methods and validation logic
- Combine related tests into a single function
#### Example:
```rust
#[gpui::test]
fn test_button_variant_methods(_cx: &mut gpui::TestAppContext) {
// Test variant check methods
assert!(ButtonVariant::Link.is_link());
assert!(ButtonVariant::Text.is_text());
assert!(ButtonVariant::Ghost.is_ghost());
// Test related logic
assert!(ButtonVariant::Link.no_padding());
assert!(ButtonVariant::Text.no_padding());
}
```
## What NOT to Test
### ❌ Anti-patterns to Avoid
1. **Simple getter/setter tests**
```rust
// ❌ Don't write tests like this
#[gpui::test]
fn test_button_with_label(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").label("Click Me");
assert_eq!(button.label, Some("Click Me".into()));
}
```
2. **Individual property tests**
```rust
// ❌ Don't write separate tests for each property
#[gpui::test]
fn test_button_disabled(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").disabled(true);
assert!(button.disabled);
}
#[gpui::test]
fn test_button_selected(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").selected(true);
assert!(button.selected);
}
```
_These should be merged into the builder pattern test_
3. **Individual size/variant tests**
```rust
// ❌ Don't write separate tests for each size
#[gpui::test]
fn test_button_xsmall(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").xsmall();
assert_eq!(button.size, Size::XSmall);
}
#[gpui::test]
fn test_button_small(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").small();
assert_eq!(button.size, Size::Small);
}
```
## Test File Structure
```rust
#[cfg(test)]
mod tests {
use super::*;
// 1. Builder pattern test (required)
#[gpui::test]
fn test_component_builder(_cx: &mut gpui::TestAppContext) {
// Test complete method chaining
}
// 2. Complex logic test (if applicable)
#[gpui::test]
fn test_component_complex_logic(_cx: &mut gpui::TestAppContext) {
// Test conditional branches, state transitions, etc.
}
// 3. Helper method test (if applicable)
#[gpui::test]
fn test_component_helper_methods(_cx: &mut gpui::TestAppContext) {
// Test helper methods
}
}
```
## Test Count Guidelines
| Component Type | Recommended Tests | Notes |
| ----------------- | ----------------- | -------------------------------- |
| Simple component | 1-2 tests | Builder + complex logic (if any) |
| Medium component | 2-3 tests | Builder + logic + helper methods |
| Complex component | 3-5 tests | Based on actual complexity |
## Real-world Examples
### Button Component (3 tests)
- `test_button_builder` - Complete configuration test
- `test_button_clickable_logic` - Click logic test
- `test_button_variant_methods` - Variant method test
### ButtonIcon Component (2 tests)
- `test_button_icon_builder` - Complete configuration test
- `test_button_icon_variant_types` - Variant type test
### ButtonGroup Component (1 test)
- `test_button_group_builder` - Complete configuration test (covers all important features)
### DropdownButton Component (1 test)
- `test_dropdown_button_builder` - Complete configuration test
### Toggle Component (2 tests)
- `test_toggle_builder` - Toggle configuration test
- `test_toggle_group_builder` - ToggleGroup configuration test
## GPUI Test Usage
### When to Use `#[gpui::test]`
- When testing UI component rendering
- When testing window-dependent behavior
- When testing interactive elements that require event handling
### When NOT to Use `#[gpui::test]`
- For pure logic tests that don't involve rendering
- For utility function tests
- For simple data structure tests
- For validation logic that doesn't require app context
#### Example:
```rust
// ✅ Use regular Rust test for simple logic
#[test]
fn test_button_variant_conversion() {
let rounded: ButtonRounded = px(5.0).into();
assert!(matches!(rounded, ButtonRounded::Size(_)));
}
// ✅ Use gpui::test for component behavior
#[gpui::test]
fn test_button_builder(_cx: &mut gpui::TestAppContext) {
let button = Button::new("test").large();
assert_eq!(button.size, Size::Large);
}
```
## Summary
✅ **DO**:
- Test complete builder patterns
- Test complex business logic
- Test conditional branches and state transitions
- Combine related tests
- Use regular `#[test]` when GPUI context is not needed
❌ **DON'T**:
- Test simple property setters
- Write separate tests for each property/size/variant
- Test obvious functionality
- Over-fragment tests
- Use `#[gpui::test]` unnecessarily
**Goal**: Cover the most critical functionality with minimal tests while keeping code clean and maintainable.
================================================
FILE: .claude/skills/generate-component-documentation/SKILL.md
================================================
---
name: generate-component-documentation
description: Generate documentation for new components. Use when writing docs, documenting components, or creating component documentation.
---
## Instructions
When generating documentation for a new component:
1. **Follow existing patterns**: Use the documentation styles found in the `docs` folder (examples: `button.md`, `accordion.md`, etc.)
2. **Reference implementations**: Base the documentation on the same-named story implementation in `crates/story/src/stories`
3. **API references**: Use markdown `code` blocks with links to docs.rs for component API references when applicable
## Examples
The generated documentation should include:
- Component description and purpose
- Props/API documentation
- Usage examples
- Visual examples (if applicable)
================================================
FILE: .claude/skills/generate-component-story/SKILL.md
================================================
---
name: generate-component-story
description: Create story examples for components. Use when writing stories, creating examples, or demonstrating component usage.
---
## Instructions
When creating component stories:
1. **Follow existing patterns**: Base stories on the styles found in `crates/story/src/stories` (examples: `tabs_story.rs`, `group_box_story.rs`, etc.)
2. **Use sections**: Organize the story with `section!` calls for each major part
3. **Comprehensive coverage**: Include all options, variants, and usage examples of the component
## Examples
A typical story structure includes:
- Basic usage examples
- Different variants and states
- Interactive examples
- Edge cases and error states
================================================
FILE: .claude/skills/github-pull-request-description/SKILL.md
================================================
---
name: github-pull-request-description
description: Write a description to description GitHub Pull Request.
---
## Description
We less than 150 words description for a PR changes, including new features, bug fixes, and improvements. And if there have APIs break changes (Only `crates/ui` changes) we should have a section called `## Breaking Changes` to list them clearly.
## Breaking changes description
When a pull request introduces breaking changes to a codebase, it's important to clearly communicate these changes to users and developers who rely on the code. A well-written breaking changes description helps ensure that everyone understands what has changed, why it has changed, and how to adapt to the new version.
We can get the changes from the PR diff and summarize them in a clear and concise manner. Aim to provide a clear APIs changes for users to follow.
### Format
We pefer the following format for breaking changes descriptions:
1. Use bullet list for each breaking change item.
2. Each item should have title and a code block showing the old and new usage by use `diff`.
3. Use `## Breaking Changes` as the section title.
4. Use english language.
**For example:**
````md
## Breaking Changes
- Added `id` parameter to `Sidebar::new`.
```diff
- Sidebar::new()
+ Sidebar::new("sidebar")
```
- Removed the `left` and `right` methods; use `side` instead.
> Default is left.
```diff
- Sidebar::right()
+ Sidebar::new("sidebar").side(Side::Right)
```
````
================================================
FILE: .claude/skills/gpui-action/SKILL.md
================================================
---
name: gpui-action
description: Action definitions and keyboard shortcuts in GPUI. Use when implementing actions, keyboard shortcuts, or key bindings.
---
## Overview
Actions provide declarative keyboard-driven UI interactions in GPUI.
**Key Concepts:**
- Define actions with `actions!` macro or `#[derive(Action)]`
- Bind keys with `cx.bind_keys()`
- Handle with `.on_action()` on elements
- Context-aware via `key_context()`
## Quick Start
### Simple Actions
```rust
use gpui::actions;
actions!(editor, [MoveUp, MoveDown, Save, Quit]);
const CONTEXT: &str = "Editor";
pub fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("up", MoveUp, Some(CONTEXT)),
KeyBinding::new("down", MoveDown, Some(CONTEXT)),
KeyBinding::new("cmd-s", Save, Some(CONTEXT)),
KeyBinding::new("cmd-q", Quit, Some(CONTEXT)),
]);
}
impl Render for Editor {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.key_context(CONTEXT)
.on_action(cx.listener(Self::move_up))
.on_action(cx.listener(Self::move_down))
.on_action(cx.listener(Self::save))
}
}
impl Editor {
fn move_up(&mut self, _: &MoveUp, cx: &mut Context<Self>) {
// Handle move up
cx.notify();
}
fn move_down(&mut self, _: &MoveDown, cx: &mut Context<Self>) {
cx.notify();
}
fn save(&mut self, _: &Save, cx: &mut Context<Self>) {
// Save logic
cx.notify();
}
}
```
### Actions with Parameters
```rust
#[derive(Clone, PartialEq, Action, Deserialize)]
#[action(namespace = editor)]
pub struct InsertText {
pub text: String,
}
#[derive(Action, Clone, PartialEq, Eq, Deserialize)]
#[action(namespace = editor, no_json)]
pub struct Digit(pub u8);
cx.bind_keys([
KeyBinding::new("0", Digit(0), Some(CONTEXT)),
KeyBinding::new("1", Digit(1), Some(CONTEXT)),
// ...
]);
impl Editor {
fn on_digit(&mut self, action: &Digit, cx: &mut Context<Self>) {
self.insert_digit(action.0, cx);
}
}
```
## Key Formats
```rust
// Modifiers
"cmd-s" // Command (macOS) / Ctrl (Windows/Linux)
"ctrl-c" // Control
"alt-f" // Alt
"shift-tab" // Shift
"cmd-ctrl-f" // Multiple modifiers
// Keys
"a-z", "0-9" // Letters and numbers
"f1-f12" // Function keys
"up", "down", "left", "right"
"enter", "escape", "space", "tab"
"backspace", "delete"
"-", "=", "[", "]", etc. // Special characters
```
## Action Naming
Prefer verb-noun pattern:
```rust
actions!([
OpenFile, // ✅ Good
CloseWindow, // ✅ Good
ToggleSidebar, // ✅ Good
Save, // ✅ Good (common exception)
]);
```
## Context-Aware Bindings
```rust
const EDITOR_CONTEXT: &str = "Editor";
const MODAL_CONTEXT: &str = "Modal";
// Same key, different contexts
cx.bind_keys([
KeyBinding::new("escape", CloseModal, Some(MODAL_CONTEXT)),
KeyBinding::new("escape", ClearSelection, Some(EDITOR_CONTEXT)),
]);
// Set context on element
div()
.key_context(EDITOR_CONTEXT)
.child(editor_content)
```
## Best Practices
### ✅ Use Contexts
```rust
// ✅ Good: Context-aware
div()
.key_context("MyComponent")
.on_action(cx.listener(Self::handle))
```
### ✅ Name Actions Clearly
```rust
// ✅ Good: Clear intent
actions!([
SaveDocument,
CloseTab,
TogglePreview,
]);
```
### ✅ Handle with Listeners
```rust
// ✅ Good: Proper handler naming
impl MyComponent {
fn on_action_save(&mut self, _: &Save, cx: &mut Context<Self>) {
// Handle save
cx.notify();
}
}
div().on_action(cx.listener(Self::on_action_save))
```
## Reference Documentation
- **Complete Guide**: See [reference.md](references/reference.md)
- Action definition, keybinding, dispatch
- Focus-based routing, best practices
- Performance, accessibility
================================================
FILE: .claude/skills/gpui-async/SKILL.md
================================================
---
name: gpui-async
description: Async operations and background tasks in GPUI. Use when working with async, spawn, background tasks, or concurrent operations. Essential for handling async I/O, long-running computations, and coordinating between foreground UI updates and background work.
---
## Overview
GPUI provides integrated async runtime for foreground UI updates and background computation.
**Key Concepts:**
- **Foreground tasks**: UI thread, can update entities (`cx.spawn`)
- **Background tasks**: Worker threads, CPU-intensive work (`cx.background_spawn`)
- All entity updates happen on foreground thread
## Quick Start
### Foreground Tasks (UI Updates)
```rust
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
// Runs on UI thread, can await and update entities
let data = fetch_from_api().await;
entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
}).ok();
}).detach();
}
}
```
### Background Tasks (Heavy Work)
```rust
impl MyComponent {
fn process_file(&mut self, cx: &mut Context<Self>) {
let entity = cx.entity().downgrade();
cx.background_spawn(async move {
// Runs on background thread, CPU-intensive
let result = heavy_computation().await;
result
})
.then(cx.spawn(move |result, cx| {
// Back to foreground to update UI
entity.update(cx, |state, cx| {
state.result = result;
cx.notify();
}).ok();
}))
.detach();
}
}
```
### Task Management
```rust
struct MyView {
_task: Task<()>, // Prefix with _ if stored but not accessed
}
impl MyView {
fn new(cx: &mut Context<Self>) -> Self {
let entity = cx.entity().downgrade();
let _task = cx.spawn(async move |cx| {
// Task automatically cancelled when dropped
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
entity.update(cx, |state, cx| {
state.tick();
cx.notify();
}).ok();
}
});
Self { _task }
}
}
```
## Core Patterns
### 1. Async Data Fetching
```rust
cx.spawn(async move |cx| {
let data = fetch_data().await?;
entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
})?;
Ok::<_, anyhow::Error>(())
}).detach();
```
### 2. Background Computation + UI Update
```rust
cx.background_spawn(async move {
heavy_work()
})
.then(cx.spawn(move |result, cx| {
entity.update(cx, |state, cx| {
state.result = result;
cx.notify();
}).ok();
}))
.detach();
```
### 3. Periodic Tasks
```rust
cx.spawn(async move |cx| {
loop {
tokio::time::sleep(Duration::from_secs(5)).await;
// Update every 5 seconds
}
}).detach();
```
### 4. Task Cancellation
Tasks are automatically cancelled when dropped. Store in struct to keep alive.
## Common Pitfalls
### ❌ Don't: Update entities from background tasks
```rust
// ❌ Wrong: Can't update entities from background thread
cx.background_spawn(async move {
entity.update(cx, |state, cx| { // Compile error!
state.data = data;
});
});
```
### ✅ Do: Use foreground task or chain
```rust
// ✅ Correct: Chain with foreground task
cx.background_spawn(async move { data })
.then(cx.spawn(move |data, cx| {
entity.update(cx, |state, cx| {
state.data = data;
cx.notify();
}).ok();
}))
.detach();
```
## Reference Documentation
### Complete Guides
- **API Reference**: See [api-reference.md](references/api-reference.md)
- Task types, spawning methods, contexts
- Executors, cancellation, error handling
- **Patterns**: See [patterns.md](references/patterns.md)
- Data fetching, background processing
- Polling, debouncing, parallel tasks
- Pattern selection guide
- **Best Practices**: See [best-practices.md](references/best-practices.md)
- Error handling, cancellation
- Performance optimization, testing
- Common pitfalls and solutions
================================================
FILE: .claude/skills/gpui-context/SKILL.md
================================================
---
name: gpui-context
description: Context management in GPUI including App, Window, and AsyncApp. Use when working with contexts, entity updates, or window operations. Different context types provide different capabilities for UI rendering, entity management, and async operations.
---
## Overview
GPUI uses different context types for different scenarios:
**Context Types:**
- **`App`**: Global app state, entity creation
- **`Window`**: Window-specific operations, painting, layout
- **`Context<T>`**: Entity-specific context for component `T`
- **`AsyncApp`**: Async context for foreground tasks
- **`AsyncWindowContext`**: Async context with window access
## Quick Start
### Context<T> - Component Context
```rust
impl MyComponent {
fn update_state(&mut self, cx: &mut Context<Self>) {
self.value = 42;
cx.notify(); // Trigger re-render
// Spawn async task
cx.spawn(async move |cx| {
// Async work
}).detach();
// Get current entity
let entity = cx.entity();
}
}
```
### App - Global Context
```rust
fn main() {
let app = Application::new();
app.run(|cx: &mut App| {
// Create entities
let entity = cx.new(|cx| MyState::default());
// Open windows
cx.open_window(WindowOptions::default(), |window, cx| {
cx.new(|cx| Root::new(view, window, cx))
});
});
}
```
### Window - Window Context
```rust
impl Render for MyView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
// Window operations
let is_focused = window.is_window_focused();
let bounds = window.bounds();
div().child("Content")
}
}
```
### AsyncApp - Async Context
```rust
cx.spawn(async move |cx: &mut AsyncApp| {
let data = fetch_data().await;
entity.update(cx, |state, inner_cx| {
state.data = data;
inner_cx.notify();
}).ok();
}).detach();
```
## Common Operations
### Entity Operations
```rust
// Create entity
let entity = cx.new(|cx| MyState::default());
// Update entity
entity.update(cx, |state, cx| {
state.value = 42;
cx.notify();
});
// Read entity
let value = entity.read(cx).value;
```
### Notifications and Events
```rust
// Trigger re-render
cx.notify();
// Emit event
cx.emit(MyEvent::Updated);
// Observe entity
cx.observe(&entity, |this, observed, cx| {
// React to changes
}).detach();
// Subscribe to events
cx.subscribe(&entity, |this, source, event, cx| {
// Handle event
}).detach();
```
### Window Operations
```rust
// Window state
let focused = window.is_window_focused();
let bounds = window.bounds();
let scale = window.scale_factor();
// Close window
window.remove_window();
```
### Async Operations
```rust
// Spawn foreground task
cx.spawn(async move |cx| {
// Async work with entity access
}).detach();
// Spawn background task
cx.background_spawn(async move {
// Heavy computation
}).detach();
```
## Context Hierarchy
```
App (Global)
└─ Window (Per-window)
└─ Context<T> (Per-component)
└─ AsyncApp (In async tasks)
└─ AsyncWindowContext (Async + Window)
```
## Reference Documentation
- **API Reference**: See [api-reference.md](references/api-reference.md)
- Complete context API, methods, conversions
- Entity operations, window operations
- Async contexts, best practices
================================================
FILE: .claude/skills/gpui-element/SKILL.md
================================================
---
name: gpui-element
description: Implementing custom elements using GPUI's low-level Element API (vs. high-level Render/RenderOnce APIs). Use when you need maximum control over layout, prepaint, and paint phases for complex, performance-critical custom UI components that cannot be achieved with Render/RenderOnce traits.
---
## When to Use
Use the low-level `Element` trait when:
- Need fine-grained control over layout calculation
- Building complex, performance-critical components
- Implementing custom layout algorithms (masonry, circular, etc.)
- High-level `Render`/`RenderOnce` APIs are insufficient
**Prefer `Render`/`RenderOnce` for:** Simple components, standard layouts, declarative UI
## Quick Start
The `Element` trait provides direct control over three rendering phases:
```rust
impl Element for MyElement {
type RequestLayoutState = MyLayoutState; // Data passed to later phases
type PrepaintState = MyPaintState; // Data for painting
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
// Phase 1: Calculate sizes and positions
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Self::RequestLayoutState)
{
let layout_id = window.request_layout(
Style { size: size(px(200.), px(100.)), ..default() },
vec![],
cx
);
(layout_id, MyLayoutState { /* ... */ })
}
// Phase 2: Create hitboxes, prepare for painting
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
window: &mut Window, cx: &mut App) -> Self::PrepaintState
{
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
MyPaintState { hitbox }
}
// Phase 3: Render and handle interactions
fn paint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
paint_state: &mut Self::PrepaintState, window: &mut Window, cx: &mut App)
{
window.paint_quad(paint_quad(bounds, Corners::all(px(4.)), cx.theme().background));
window.on_mouse_event({
let hitbox = paint_state.hitbox.clone();
move |event: &MouseDownEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Handle interaction
cx.stop_propagation();
}
}
});
}
}
// Enable element to be used as child
impl IntoElement for MyElement {
type Element = Self;
fn into_element(self) -> Self::Element { self }
}
```
## Core Concepts
### Three-Phase Rendering
1. **request_layout**: Calculate sizes and positions, return layout ID and state
2. **prepaint**: Create hitboxes, compute final bounds, prepare for painting
3. **paint**: Render element, set up interactions (mouse events, cursor styles)
### State Flow
```
RequestLayoutState → PrepaintState → paint
```
State flows in one direction through associated types, passed as mutable references between phases.
### Key Operations
- **Layout**: `window.request_layout(style, children, cx)` - Create layout node
- **Hitboxes**: `window.insert_hitbox(bounds, behavior)` - Create interaction area
- **Painting**: `window.paint_quad(...)` - Render visual content
- **Events**: `window.on_mouse_event(handler)` - Handle user input
## Reference Documentation
### Complete API Documentation
- **Element Trait API**: See [api-reference.md](references/api-reference.md)
- Associated types, methods, parameters, return values
- Hitbox system, event handling, cursor styles
### Implementation Guides
- **Examples**: See [examples.md](references/examples.md)
- Simple text element with highlighting
- Interactive element with selection
- Complex element with child management
- **Best Practices**: See [best-practices.md](references/best-practices.md)
- State management, performance optimization
- Interaction handling, layout strategies
- Error handling, testing, common pitfalls
- **Common Patterns**: See [patterns.md](references/patterns.md)
- Text rendering, container, interactive, composite, scrollable patterns
- Pattern selection guide
- **Advanced Patterns**: See [advanced-patterns.md](references/advanced-patterns.md)
- Custom layout algorithms (masonry, circular)
- Element composition with traits
- Async updates, memoization, virtual lists
================================================
FILE: .claude/skills/gpui-element/references/advanced-patterns.md
================================================
# Advanced Element Patterns
Advanced techniques and patterns for implementing sophisticated GPUI elements.
## Custom Layout Algorithms
Implementing custom layout algorithms not supported by GPUI's built-in layouts.
### Masonry Layout (Pinterest-Style)
```rust
pub struct MasonryLayout {
id: ElementId,
columns: usize,
gap: Pixels,
children: Vec<AnyElement>,
}
struct MasonryLayoutState {
column_layouts: Vec<Vec<LayoutId>>,
column_heights: Vec<Pixels>,
}
struct MasonryPaintState {
child_bounds: Vec<Bounds<Pixels>>,
}
impl Element for MasonryLayout {
type RequestLayoutState = MasonryLayoutState;
type PrepaintState = MasonryPaintState;
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, MasonryLayoutState) {
// Initialize columns
let mut columns: Vec<Vec<LayoutId>> = vec![Vec::new(); self.columns];
let mut column_heights = vec![px(0.); self.columns];
// Distribute children across columns
for child in &mut self.children {
let (child_layout_id, _) = child.request_layout(
global_id,
inspector_id,
window,
cx
);
let child_size = window.layout_bounds(child_layout_id).size;
// Find shortest column
let min_column_idx = column_heights
.iter()
.enumerate()
.min_by(|a, b| a.1.partial_cmp(b.1).unwrap())
.unwrap()
.0;
// Add child to shortest column
columns[min_column_idx].push(child_layout_id);
column_heights[min_column_idx] += child_size.height + self.gap;
}
// Calculate total layout size
let column_width = px(200.); // Fixed column width
let total_width = column_width * self.columns as f32
+ self.gap * (self.columns - 1) as f32;
let total_height = column_heights.iter()
.max_by(|a, b| a.partial_cmp(b).unwrap())
.copied()
.unwrap_or(px(0.));
let layout_id = window.request_layout(
Style {
size: size(total_width, total_height),
..default()
},
columns.iter().flatten().copied().collect(),
cx
);
(layout_id, MasonryLayoutState {
column_layouts: columns,
column_heights,
})
}
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
layout_state: &mut MasonryLayoutState,
window: &mut Window,
cx: &mut App
) -> MasonryPaintState {
let column_width = px(200.);
let mut child_bounds = Vec::new();
// Position children in columns
for (col_idx, column) in layout_state.column_layouts.iter().enumerate() {
let x_offset = bounds.left()
+ (column_width + self.gap) * col_idx as f32;
let mut y_offset = bounds.top();
for (child_idx, layout_id) in column.iter().enumerate() {
let child_size = window.layout_bounds(*layout_id).size;
let child_bound = Bounds::new(
point(x_offset, y_offset),
size(column_width, child_size.height)
);
self.children[child_idx].prepaint(
global_id,
inspector_id,
child_bound,
window,
cx
);
child_bounds.push(child_bound);
y_offset += child_size.height + self.gap;
}
}
MasonryPaintState { child_bounds }
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_layout_state: &mut MasonryLayoutState,
paint_state: &mut MasonryPaintState,
window: &mut Window,
cx: &mut App
) {
for (child, bounds) in self.children.iter_mut().zip(&paint_state.child_bounds) {
child.paint(global_id, inspector_id, *bounds, window, cx);
}
}
}
```
### Circular Layout
```rust
pub struct CircularLayout {
id: ElementId,
radius: Pixels,
children: Vec<AnyElement>,
}
impl Element for CircularLayout {
type RequestLayoutState = Vec<LayoutId>;
type PrepaintState = Vec<Bounds<Pixels>>;
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, Vec<LayoutId>) {
let child_layouts: Vec<_> = self.children
.iter_mut()
.map(|child| child.request_layout(global_id, inspector_id, window, cx).0)
.collect();
let diameter = self.radius * 2.;
let layout_id = window.request_layout(
Style {
size: size(diameter, diameter),
..default()
},
child_layouts.clone(),
cx
);
(layout_id, child_layouts)
}
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
layout_ids: &mut Vec<LayoutId>,
window: &mut Window,
cx: &mut App
) -> Vec<Bounds<Pixels>> {
let center = bounds.center();
let angle_step = 2.0 * std::f32::consts::PI / self.children.len() as f32;
let mut child_bounds = Vec::new();
for (i, (child, layout_id)) in self.children.iter_mut()
.zip(layout_ids.iter())
.enumerate()
{
let angle = angle_step * i as f32;
let child_size = window.layout_bounds(*layout_id).size;
// Position child on circle
let x = center.x + self.radius * angle.cos() - child_size.width / 2.;
let y = center.y + self.radius * angle.sin() - child_size.height / 2.;
let child_bound = Bounds::new(point(x, y), child_size);
child.prepaint(global_id, inspector_id, child_bound, window, cx);
child_bounds.push(child_bound);
}
child_bounds
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_layout_ids: &mut Vec<LayoutId>,
child_bounds: &mut Vec<Bounds<Pixels>>,
window: &mut Window,
cx: &mut App
) {
for (child, bounds) in self.children.iter_mut().zip(child_bounds) {
child.paint(global_id, inspector_id, *bounds, window, cx);
}
}
}
```
## Element Composition with Traits
Create reusable behaviors via traits for element composition.
### Hoverable Trait
```rust
pub trait Hoverable: Element {
fn on_hover<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut Window, &mut App) + 'static;
fn on_hover_end<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut Window, &mut App) + 'static;
}
// Implementation for custom element
pub struct HoverableElement {
id: ElementId,
content: AnyElement,
hover_handlers: Vec<Box<dyn Fn(&mut Window, &mut App)>>,
hover_end_handlers: Vec<Box<dyn Fn(&mut Window, &mut App)>>,
was_hovered: bool,
}
impl Hoverable for HoverableElement {
fn on_hover<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut Window, &mut App) + 'static
{
self.hover_handlers.push(Box::new(f));
self
}
fn on_hover_end<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&mut Window, &mut App) + 'static
{
self.hover_end_handlers.push(Box::new(f));
self
}
}
impl Element for HoverableElement {
type RequestLayoutState = LayoutId;
type PrepaintState = Hitbox;
fn paint(
&mut self,
_global_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_layout: &mut LayoutId,
hitbox: &mut Hitbox,
window: &mut Window,
cx: &mut App
) {
let is_hovered = hitbox.is_hovered(window);
// Trigger hover events
if is_hovered && !self.was_hovered {
for handler in &self.hover_handlers {
handler(window, cx);
}
} else if !is_hovered && self.was_hovered {
for handler in &self.hover_end_handlers {
handler(window, cx);
}
}
self.was_hovered = is_hovered;
// Paint content
self.content.paint(bounds, window, cx);
}
// ... other methods
}
```
### Clickable Trait
```rust
pub trait Clickable: Element {
fn on_click<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&MouseUpEvent, &mut Window, &mut App) + 'static;
fn on_double_click<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&MouseUpEvent, &mut Window, &mut App) + 'static;
}
pub struct ClickableElement {
id: ElementId,
content: AnyElement,
click_handlers: Vec<Box<dyn Fn(&MouseUpEvent, &mut Window, &mut App)>>,
double_click_handlers: Vec<Box<dyn Fn(&MouseUpEvent, &mut Window, &mut App)>>,
last_click_time: Option<Instant>,
}
impl Clickable for ClickableElement {
fn on_click<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&MouseUpEvent, &mut Window, &mut App) + 'static
{
self.click_handlers.push(Box::new(f));
self
}
fn on_double_click<F>(&mut self, f: F) -> &mut Self
where
F: Fn(&MouseUpEvent, &mut Window, &mut App) + 'static
{
self.double_click_handlers.push(Box::new(f));
self
}
}
```
## Async Element Updates
Elements that update based on async operations.
```rust
pub struct AsyncElement {
id: ElementId,
state: Entity<AsyncState>,
loading: bool,
data: Option<String>,
}
pub struct AsyncState {
loading: bool,
data: Option<String>,
}
impl Element for AsyncElement {
type RequestLayoutState = ();
type PrepaintState = Hitbox;
fn paint(
&mut self,
_global_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_layout: &mut (),
hitbox: &mut Hitbox,
window: &mut Window,
cx: &mut App
) {
// Display loading or data
if self.loading {
// Paint loading indicator
self.paint_loading(bounds, window, cx);
} else if let Some(data) = &self.data {
// Paint data
self.paint_data(data, bounds, window, cx);
}
// Trigger async update on click
window.on_mouse_event({
let state = self.state.clone();
let hitbox = hitbox.clone();
move |event: &MouseUpEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Spawn async task
cx.spawn({
let state = state.clone();
async move {
// Perform async operation
let result = fetch_data_async().await;
// Update state on completion
state.update(cx, |state, cx| {
state.loading = false;
state.data = Some(result);
cx.notify();
});
}
}).detach();
// Set loading state immediately
state.update(cx, |state, cx| {
state.loading = true;
cx.notify();
});
cx.stop_propagation();
}
}
});
}
// ... other methods
}
async fn fetch_data_async() -> String {
// Simulate async operation
tokio::time::sleep(Duration::from_secs(1)).await;
"Data loaded!".to_string()
}
```
## Element Memoization
Optimize performance by memoizing expensive element computations.
```rust
pub struct MemoizedElement<T: PartialEq + Clone + 'static> {
id: ElementId,
value: T,
render_fn: Box<dyn Fn(&T) -> AnyElement>,
cached_element: Option<AnyElement>,
last_value: Option<T>,
}
impl<T: PartialEq + Clone + 'static> MemoizedElement<T> {
pub fn new<F>(id: ElementId, value: T, render_fn: F) -> Self
where
F: Fn(&T) -> AnyElement + 'static,
{
Self {
id,
value,
render_fn: Box::new(render_fn),
cached_element: None,
last_value: None,
}
}
}
impl<T: PartialEq + Clone + 'static> Element for MemoizedElement<T> {
type RequestLayoutState = LayoutId;
type PrepaintState = ();
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, LayoutId) {
// Check if value changed
if self.last_value.as_ref() != Some(&self.value) || self.cached_element.is_none() {
// Recompute element
self.cached_element = Some((self.render_fn)(&self.value));
self.last_value = Some(self.value.clone());
}
// Request layout for cached element
let (layout_id, _) = self.cached_element
.as_mut()
.unwrap()
.request_layout(global_id, inspector_id, window, cx);
(layout_id, layout_id)
}
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_layout_id: &mut LayoutId,
window: &mut Window,
cx: &mut App
) -> () {
self.cached_element
.as_mut()
.unwrap()
.prepaint(global_id, inspector_id, bounds, window, cx);
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_layout_id: &mut LayoutId,
_: &mut (),
window: &mut Window,
cx: &mut App
) {
self.cached_element
.as_mut()
.unwrap()
.paint(global_id, inspector_id, bounds, window, cx);
}
}
// Usage
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
MemoizedElement::new(
ElementId::Name("memoized".into()),
self.expensive_value.clone(),
|value| {
// Expensive rendering function only called when value changes
div().child(format!("Computed: {}", value))
}
)
}
```
## Virtual List Pattern
Efficiently render large lists by only rendering visible items.
```rust
pub struct VirtualList {
id: ElementId,
item_count: usize,
item_height: Pixels,
viewport_height: Pixels,
scroll_offset: Pixels,
render_item: Box<dyn Fn(usize) -> AnyElement>,
}
struct VirtualListState {
visible_range: Range<usize>,
visible_item_layouts: Vec<LayoutId>,
}
impl Element for VirtualList {
type RequestLayoutState = VirtualListState;
type PrepaintState = Hitbox;
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, VirtualListState) {
// Calculate visible range
let start_idx = (self.scroll_offset / self.item_height).floor() as usize;
let end_idx = ((self.scroll_offset + self.viewport_height) / self.item_height)
.ceil() as usize;
let visible_range = start_idx..end_idx.min(self.item_count);
// Request layout only for visible items
let visible_item_layouts: Vec<_> = visible_range.clone()
.map(|i| {
let mut item = (self.render_item)(i);
item.request_layout(global_id, inspector_id, window, cx).0
})
.collect();
let total_height = self.item_height * self.item_count as f32;
let layout_id = window.request_layout(
Style {
size: size(relative(1.0), self.viewport_height),
overflow: Overflow::Hidden,
..default()
},
visible_item_layouts.clone(),
cx
);
(layout_id, VirtualListState {
visible_range,
visible_item_layouts,
})
}
fn prepaint(
&mut self,
_global_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
state: &mut VirtualListState,
window: &mut Window,
_cx: &mut App
) -> Hitbox {
// Prepaint visible items at correct positions
for (i, layout_id) in state.visible_item_layouts.iter().enumerate() {
let item_idx = state.visible_range.start + i;
let y = item_idx as f32 * self.item_height - self.scroll_offset;
let item_bounds = Bounds::new(
point(bounds.left(), bounds.top() + y),
size(bounds.width(), self.item_height)
);
// Prepaint if visible
if item_bounds.intersects(&bounds) {
// Prepaint item...
}
}
window.insert_hitbox(bounds, HitboxBehavior::Normal)
}
fn paint(
&mut self,
_global_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
state: &mut VirtualListState,
hitbox: &mut Hitbox,
window: &mut Window,
cx: &mut App
) {
// Paint visible items
for (i, _layout_id) in state.visible_item_layouts.iter().enumerate() {
let item_idx = state.visible_range.start + i;
let y = item_idx as f32 * self.item_height - self.scroll_offset;
let item_bounds = Bounds::new(
point(bounds.left(), bounds.top() + y),
size(bounds.width(), self.item_height)
);
if item_bounds.intersects(&bounds) {
let mut item = (self.render_item)(item_idx);
item.paint(item_bounds, window, cx);
}
}
// Handle scroll
window.on_mouse_event({
let hitbox = hitbox.clone();
let total_height = self.item_height * self.item_count as f32;
move |event: &ScrollWheelEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
self.scroll_offset -= event.delta.y;
self.scroll_offset = self.scroll_offset
.max(px(0.))
.min(total_height - self.viewport_height);
cx.notify();
cx.stop_propagation();
}
}
});
}
}
// Usage: Efficiently render 10,000 items
let virtual_list = VirtualList {
id: ElementId::Name("large-list".into()),
item_count: 10_000,
item_height: px(40.),
viewport_height: px(400.),
scroll_offset: px(0.),
render_item: Box::new(|index| {
div().child(format!("Item {}", index))
}),
};
```
These advanced patterns enable sophisticated element implementations while maintaining performance and code quality.
================================================
FILE: .claude/skills/gpui-element/references/api-reference.md
================================================
# Element API Reference
Complete API documentation for GPUI's low-level Element trait.
## Element Trait Structure
The `Element` trait requires implementing three associated types and five methods:
```rust
pub trait Element: 'static + IntoElement {
type RequestLayoutState: 'static;
type PrepaintState: 'static;
fn id(&self) -> Option<ElementId>;
fn source_location(&self) -> Option<&'static std::panic::Location<'static>>;
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState);
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) -> Self::PrepaintState;
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
);
}
```
## Associated Types
### RequestLayoutState
Data passed from `request_layout` to `prepaint` and `paint` phases.
**Usage:**
- Store layout calculations (styled text, child layout IDs)
- Cache expensive computations
- Pass child state between phases
**Examples:**
```rust
// Simple: no state needed
type RequestLayoutState = ();
// Single value
type RequestLayoutState = StyledText;
// Multiple values
type RequestLayoutState = (StyledText, Vec<ChildLayout>);
// Complex struct
pub struct MyLayoutState {
pub styled_text: StyledText,
pub child_layouts: Vec<(LayoutId, ChildState)>,
pub computed_bounds: Bounds<Pixels>,
}
type RequestLayoutState = MyLayoutState;
```
### PrepaintState
Data passed from `prepaint` to `paint` phase.
**Usage:**
- Store hitboxes for interaction
- Cache visual bounds
- Store prepaint results
**Examples:**
```rust
// Simple: just a hitbox
type PrepaintState = Hitbox;
// Optional hitbox
type PrepaintState = Option<Hitbox>;
// Multiple values
type PrepaintState = (Hitbox, Vec<Bounds<Pixels>>);
// Complex struct
pub struct MyPaintState {
pub hitbox: Hitbox,
pub child_bounds: Vec<Bounds<Pixels>>,
pub visible_range: Range<usize>,
}
type PrepaintState = MyPaintState;
```
## Methods
### id()
Returns optional unique identifier for debugging and inspection.
```rust
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
// Or if no ID needed
fn id(&self) -> Option<ElementId> {
None
}
```
### source_location()
Returns source location for debugging. Usually returns `None` unless debugging is needed.
```rust
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
```
### request_layout()
Calculates sizes and positions for the element tree.
**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `window`: Mutable window reference
- `cx`: Mutable app context
**Returns:**
- `(LayoutId, Self::RequestLayoutState)`: Layout ID and state for next phases
**Responsibilities:**
1. Calculate child layouts by calling `child.request_layout()`
2. Create own layout using `window.request_layout()`
3. Return layout ID and state to pass to next phases
**Example:**
```rust
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
// 1. Calculate child layouts
let child_layout_id = self.child.request_layout(
global_id,
inspector_id,
window,
cx
).0;
// 2. Create own layout
let layout_id = window.request_layout(
Style {
size: size(px(200.), px(100.)),
..default()
},
vec![child_layout_id],
cx
);
// 3. Return layout ID and state
(layout_id, MyLayoutState { child_layout_id })
}
```
### prepaint()
Prepares for painting by creating hitboxes and computing final bounds.
**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `bounds`: Final bounds calculated by layout engine
- `request_layout`: Mutable reference to layout state
- `window`: Mutable window reference
- `cx`: Mutable app context
**Returns:**
- `Self::PrepaintState`: State for paint phase
**Responsibilities:**
1. Compute final child bounds based on layout bounds
2. Call `child.prepaint()` for all children
3. Create hitboxes using `window.insert_hitbox()`
4. Return state for paint phase
**Example:**
```rust
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) -> Self::PrepaintState {
// 1. Compute child bounds
let child_bounds = bounds; // or calculated subset
// 2. Prepaint children
self.child.prepaint(
global_id,
inspector_id,
child_bounds,
&mut request_layout.child_state,
window,
cx
);
// 3. Create hitboxes
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
// 4. Return paint state
MyPaintState { hitbox }
}
```
### paint()
Renders the element and handles interactions.
**Parameters:**
- `global_id`: Global element identifier (optional)
- `inspector_id`: Inspector element identifier (optional)
- `bounds`: Final bounds for rendering
- `request_layout`: Mutable reference to layout state
- `prepaint`: Mutable reference to prepaint state
- `window`: Mutable window reference
- `cx`: Mutable app context
**Responsibilities:**
1. Paint children first (bottom to top)
2. Paint own content (backgrounds, borders, etc.)
3. Set up interactions (mouse events, cursor styles)
**Example:**
```rust
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
request_layout: &mut Self::RequestLayoutState,
prepaint: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
) {
// 1. Paint children first
self.child.paint(
global_id,
inspector_id,
child_bounds,
&mut request_layout.child_state,
&mut prepaint.child_paint_state,
window,
cx
);
// 2. Paint own content
window.paint_quad(paint_quad(
bounds,
Corners::all(px(4.)),
cx.theme().background,
));
// 3. Set up interactions
window.on_mouse_event({
let hitbox = prepaint.hitbox.clone();
move |event: &MouseDownEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Handle click
cx.stop_propagation();
}
}
});
window.set_cursor_style(CursorStyle::PointingHand, &prepaint.hitbox);
}
```
## IntoElement Integration
Elements must also implement `IntoElement` to be used as children:
```rust
impl IntoElement for MyElement {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
```
This allows your custom element to be used directly in the element tree:
```rust
div()
.child(MyElement::new()) // Works because of IntoElement
```
## Common Parameters
### Global and Inspector IDs
Both are optional identifiers used for debugging and inspection:
- `global_id`: Unique identifier across entire app
- `inspector_id`: Identifier for dev tools/inspector
Usually passed through to children without modification.
### Window and Context
- `window: &mut Window`: Window-specific operations (painting, hitboxes, events)
- `cx: &mut App`: App-wide operations (spawning tasks, accessing globals)
## Layout System Integration
### window.request_layout()
Creates a layout node with specified style and children:
```rust
let layout_id = window.request_layout(
Style {
size: size(px(200.), px(100.)),
flex: Flex::Column,
gap: px(8.),
..default()
},
vec![child1_layout_id, child2_layout_id],
cx
);
```
### Bounds<Pixels>
Represents rectangular region:
```rust
pub struct Bounds<T> {
pub origin: Point<T>,
pub size: Size<T>,
}
// Create bounds
let bounds = Bounds::new(
point(px(10.), px(20.)),
size(px(100.), px(50.))
);
// Access properties
bounds.left() // origin.x
bounds.top() // origin.y
bounds.right() // origin.x + size.width
bounds.bottom() // origin.y + size.height
bounds.center() // center point
```
## Hitbox System
### Creating Hitboxes
```rust
// Normal hitbox (blocks events)
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
// Transparent hitbox (passes events through)
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Transparent);
```
### Using Hitboxes
```rust
// Check if hovered
if hitbox.is_hovered(window) {
// ...
}
// Set cursor style
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);
// Use in event handlers
window.on_mouse_event(move |event, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Handle event
}
});
```
## Event Handling
### Mouse Events
```rust
// Mouse down
window.on_mouse_event(move |event: &MouseDownEvent, phase, window, cx| {
if phase.bubble() && bounds.contains(&event.position) {
// Handle mouse down
cx.stop_propagation(); // Prevent bubbling
}
});
// Mouse up
window.on_mouse_event(move |event: &MouseUpEvent, phase, window, cx| {
// Handle mouse up
});
// Mouse move
window.on_mouse_event(move |event: &MouseMoveEvent, phase, window, cx| {
// Handle mouse move
});
// Scroll
window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| {
// Handle scroll
});
```
### Event Phase
Events go through two phases:
- **Capture**: Top-down (parent → child)
- **Bubble**: Bottom-up (child → parent)
```rust
move |event, phase, window, cx| {
if phase.capture() {
// Handle in capture phase
} else if phase.bubble() {
// Handle in bubble phase
}
cx.stop_propagation(); // Stop event from continuing
}
```
## Cursor Styles
Available cursor styles:
```rust
CursorStyle::Arrow
CursorStyle::IBeam // Text selection
CursorStyle::PointingHand // Clickable
CursorStyle::ResizeLeft
CursorStyle::ResizeRight
CursorStyle::ResizeUp
CursorStyle::ResizeDown
CursorStyle::ResizeLeftRight
CursorStyle::ResizeUpDown
CursorStyle::Crosshair
CursorStyle::OperationNotAllowed
```
Usage:
```rust
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);
```
================================================
FILE: .claude/skills/gpui-element/references/best-practices.md
================================================
# Element Best Practices
Guidelines and best practices for implementing high-quality GPUI elements.
## State Management
### Using Associated Types Effectively
**Good:** Use associated types to pass meaningful data between phases
```rust
// Good: Structured state with type safety
type RequestLayoutState = (StyledText, Vec<ChildLayout>);
type PrepaintState = (Hitbox, Vec<ChildBounds>);
```
**Bad:** Using empty state when you need data
```rust
// Bad: No state when you need to pass data
type RequestLayoutState = ();
type PrepaintState = ();
// Now you can't pass layout info to paint phase!
```
### Managing Complex State
For elements with complex state, create dedicated structs:
```rust
// Good: Dedicated struct for complex state
pub struct TextElementState {
pub styled_text: StyledText,
pub text_layout: TextLayout,
pub child_states: Vec<ChildState>,
}
type RequestLayoutState = TextElementState;
```
**Benefits:**
- Clear documentation of state structure
- Easy to extend
- Type-safe access
### State Lifecycle
**Golden Rule:** State flows in one direction through the phases
```
request_layout → RequestLayoutState →
prepaint → PrepaintState →
paint
```
**Don't:**
- Store state in the element struct that should be in associated types
- Try to mutate element state in paint phase (use `cx.notify()` to schedule re-render)
- Pass mutable references across phase boundaries
## Performance Considerations
### Minimize Allocations in Paint Phase
**Critical:** Paint phase is called every frame during animations. Minimize allocations.
**Good:** Pre-allocate in `request_layout` or `prepaint`
```rust
impl Element for MyElement {
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Vec<StyledText>)
{
// Allocate once during layout
let styled_texts = self.children
.iter()
.map(|child| StyledText::new(child.text.clone()))
.collect();
(layout_id, styled_texts)
}
fn paint(&mut self, .., styled_texts: &mut Vec<StyledText>, ..) {
// Just use pre-allocated styled_texts
for text in styled_texts {
text.paint(..);
}
}
}
```
**Bad:** Allocate in `paint` phase
```rust
fn paint(&mut self, ..) {
// Bad: Allocation in paint phase!
let styled_texts: Vec<_> = self.children
.iter()
.map(|child| StyledText::new(child.text.clone()))
.collect();
}
```
### Cache Expensive Computations
Use memoization for expensive operations:
```rust
pub struct CachedElement {
// Cache key
last_text: Option<SharedString>,
last_width: Option<Pixels>,
// Cached result
cached_layout: Option<TextLayout>,
}
impl Element for CachedElement {
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, TextLayout)
{
let current_width = window.bounds().width();
// Check if cache is valid
if self.last_text.as_ref() != Some(&self.text)
|| self.last_width != Some(current_width)
|| self.cached_layout.is_none()
{
// Recompute expensive layout
self.cached_layout = Some(self.compute_text_layout(current_width));
self.last_text = Some(self.text.clone());
self.last_width = Some(current_width);
}
// Use cached layout
let layout = self.cached_layout.as_ref().unwrap();
(layout_id, layout.clone())
}
}
```
### Lazy Child Rendering
Only render visible children in scrollable containers:
```rust
fn paint(&mut self, .., bounds: Bounds<Pixels>, paint_state: &mut Self::PrepaintState, ..) {
for (i, child) in self.children.iter_mut().enumerate() {
let child_bounds = paint_state.child_bounds[i];
// Only paint visible children
if self.is_visible(&child_bounds, &bounds) {
child.paint(..);
}
}
}
fn is_visible(&self, child_bounds: &Bounds<Pixels>, container_bounds: &Bounds<Pixels>) -> bool {
child_bounds.bottom() >= container_bounds.top() &&
child_bounds.top() <= container_bounds.bottom()
}
```
## Interaction Handling
### Proper Event Bubbling
Always check phase and bounds before handling events:
```rust
fn paint(&mut self, .., window: &mut Window, cx: &mut App) {
window.on_mouse_event({
let hitbox = self.hitbox.clone();
move |event: &MouseDownEvent, phase, window, cx| {
// Check phase first
if !phase.bubble() {
return;
}
// Check if event is within bounds
if !hitbox.is_hovered(window) {
return;
}
// Handle event
self.handle_click(event);
// Stop propagation if handled
cx.stop_propagation();
}
});
}
```
**Don't forget:**
- Check `phase.bubble()` or `phase.capture()` as appropriate
- Check hitbox hover state or bounds
- Call `cx.stop_propagation()` if you handle the event
### Hitbox Management
Create hitboxes in `prepaint` phase, not `paint`:
**Good:**
```rust
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, window: &mut Window, ..) -> Hitbox {
// Create hitbox in prepaint
window.insert_hitbox(bounds, HitboxBehavior::Normal)
}
fn paint(&mut self, .., hitbox: &mut Hitbox, window: &mut Window, ..) {
// Use hitbox in paint
window.set_cursor_style(CursorStyle::PointingHand, hitbox);
}
```
**Hitbox Behaviors:**
```rust
// Normal: Blocks events from passing through
HitboxBehavior::Normal
// Transparent: Allows events to pass through to elements below
HitboxBehavior::Transparent
```
### Cursor Style Guidelines
Set appropriate cursor styles for interactivity cues:
```rust
// Text selection
window.set_cursor_style(CursorStyle::IBeam, &hitbox);
// Clickable elements (desktop convention: use default, not pointing hand)
window.set_cursor_style(CursorStyle::Arrow, &hitbox);
// Links (web convention: use pointing hand)
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);
// Resizable edges
window.set_cursor_style(CursorStyle::ResizeLeftRight, &hitbox);
```
**Desktop vs Web Convention:**
- Desktop apps: Use `Arrow` for buttons
- Web apps: Use `PointingHand` for links only
## Layout Strategies
### Fixed Size Elements
For elements with known, unchanging size:
```rust
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App) -> (LayoutId, ()) {
let layout_id = window.request_layout(
Style {
size: size(px(200.), px(100.)),
..default()
},
vec![], // No children
cx
);
(layout_id, ())
}
```
### Content-Based Sizing
For elements sized by their content:
```rust
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Size<Pixels>)
{
// Measure content
let text_bounds = self.measure_text(window);
let padding = px(16.);
let layout_id = window.request_layout(
Style {
size: size(
text_bounds.width() + padding * 2.,
text_bounds.height() + padding * 2.,
),
..default()
},
vec![],
cx
);
(layout_id, text_bounds)
}
```
### Flexible Layouts
For elements that adapt to available space:
```rust
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Vec<LayoutId>)
{
let mut child_layout_ids = Vec::new();
for child in &mut self.children {
let (layout_id, _) = child.request_layout(window, cx);
child_layout_ids.push(layout_id);
}
let layout_id = window.request_layout(
Style {
flex_direction: FlexDirection::Row,
gap: px(8.),
size: Size {
width: relative(1.0), // Fill parent width
height: auto(), // Auto height
},
..default()
},
child_layout_ids.clone(),
cx
);
(layout_id, child_layout_ids)
}
```
## Error Handling
### Graceful Degradation
Handle errors gracefully, don't panic:
```rust
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Option<TextLayout>)
{
// Try to create styled text
match StyledText::new(self.text.clone()).request_layout(None, None, window, cx) {
Ok((layout_id, text_layout)) => {
(layout_id, Some(text_layout))
}
Err(e) => {
// Log error
eprintln!("Failed to layout text: {}", e);
// Fallback to simple text
let fallback_text = StyledText::new("(Error loading text)".into());
let (layout_id, _) = fallback_text.request_layout(None, None, window, cx);
(layout_id, None)
}
}
}
```
### Defensive Bounds Checking
Always validate bounds and indices:
```rust
fn paint_selection(&self, selection: &Selection, text_layout: &TextLayout, ..) {
// Validate selection bounds
let start = selection.start.min(self.text.len());
let end = selection.end.min(self.text.len());
if start >= end {
return; // Invalid selection
}
let rects = text_layout.rects_for_range(start..end);
// Paint selection...
}
```
## Testing Element Implementations
### Layout Tests
Test that layout calculations are correct:
```rust
#[cfg(test)]
mod tests {
use super::*;
use gpui::TestAppContext;
#[gpui::test]
fn test_element_layout(cx: &mut TestAppContext) {
cx.update(|cx| {
let mut window = cx.open_window(Default::default(), |_, _| ()).unwrap();
window.update(cx, |window, cx| {
let mut element = MyElement::new();
let (layout_id, layout_state) = element.request_layout(
None,
None,
window,
cx
);
// Assert layout properties
let bounds = window.layout_bounds(layout_id);
assert_eq!(bounds.size.width, px(200.));
assert_eq!(bounds.size.height, px(100.));
});
});
}
}
```
### Interaction Tests
Test that interactions work correctly:
```rust
#[gpui::test]
fn test_element_click(cx: &mut TestAppContext) {
cx.update(|cx| {
let mut window = cx.open_window(Default::default(), |_, cx| {
cx.new(|_| MyElement::new())
}).unwrap();
window.update(cx, |window, cx| {
let view = window.root_view().unwrap();
// Simulate click
let position = point(px(10.), px(10.));
window.dispatch_event(MouseDownEvent {
position,
button: MouseButton::Left,
modifiers: Modifiers::default(),
});
// Assert element responded
view.read(cx).assert_clicked();
});
});
}
```
## Common Pitfalls
### ❌ Storing Layout State in Element Struct
**Bad:**
```rust
pub struct MyElement {
id: ElementId,
// Bad: This should be in RequestLayoutState
cached_layout: Option<TextLayout>,
}
```
**Good:**
```rust
pub struct MyElement {
id: ElementId,
text: SharedString,
}
type RequestLayoutState = TextLayout; // Good: State in associated type
```
### ❌ Mutating Element in Paint Phase
**Bad:**
```rust
fn paint(&mut self, ..) {
self.counter += 1; // Bad: Mutating element in paint
}
```
**Good:**
```rust
fn paint(&mut self, .., window: &mut Window, cx: &mut App) {
window.on_mouse_event(move |event, phase, window, cx| {
if phase.bubble() {
self.counter += 1;
cx.notify(); // Schedule re-render
}
});
}
```
### ❌ Creating Hitboxes in Paint Phase
**Bad:**
```rust
fn paint(&mut self, .., bounds: Bounds<Pixels>, window: &mut Window, ..) {
// Bad: Creating hitbox in paint
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
}
```
**Good:**
```rust
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, window: &mut Window, ..) -> Hitbox {
// Good: Creating hitbox in prepaint
window.insert_hitbox(bounds, HitboxBehavior::Normal)
}
```
### ❌ Ignoring Event Phase
**Bad:**
```rust
window.on_mouse_event(move |event, phase, window, cx| {
// Bad: Not checking phase
self.handle_click(event);
});
```
**Good:**
```rust
window.on_mouse_event(move |event, phase, window, cx| {
// Good: Checking phase
if !phase.bubble() {
return;
}
self.handle_click(event);
});
```
## Performance Checklist
Before shipping an element implementation, verify:
- [ ] No allocations in `paint` phase (except event handlers)
- [ ] Expensive computations are cached/memoized
- [ ] Only visible children are rendered in scrollable containers
- [ ] Hitboxes created in `prepaint`, not `paint`
- [ ] Event handlers check phase and bounds
- [ ] Layout state is passed through associated types, not stored in element
- [ ] Element implements proper error handling with fallbacks
- [ ] Tests cover layout calculations and interactions
================================================
FILE: .claude/skills/gpui-element/references/examples.md
================================================
# Element Implementation Examples
Complete examples of implementing custom elements for various scenarios.
## Table of Contents
1. [Simple Text Element](#simple-text-element)
2. [Interactive Element with Selection](#interactive-element-with-selection)
3. [Complex Element with Child Management](#complex-element-with-child-management)
## Simple Text Element
A basic text element with syntax highlighting support.
```rust
pub struct SimpleText {
id: ElementId,
text: SharedString,
highlights: Vec<(Range<usize>, HighlightStyle)>,
}
impl IntoElement for SimpleText {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
impl Element for SimpleText {
type RequestLayoutState = StyledText;
type PrepaintState = Hitbox;
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, Self::RequestLayoutState) {
// Create styled text with highlights
let mut runs = Vec::new();
let mut ix = 0;
for (range, highlight) in &self.highlights {
// Add unstyled text before highlight
if ix < range.start {
runs.push(window.text_style().to_run(range.start - ix));
}
// Add highlighted text
runs.push(
window.text_style()
.highlight(*highlight)
.to_run(range.len())
);
ix = range.end;
}
// Add remaining unstyled text
if ix < self.text.len() {
runs.push(window.text_style().to_run(self.text.len() - ix));
}
let styled_text = StyledText::new(self.text.clone()).with_runs(runs);
let (layout_id, _) = styled_text.request_layout(
global_id,
inspector_id,
window,
cx
);
(layout_id, styled_text)
}
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
styled_text: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App
) -> Self::PrepaintState {
// Prepaint the styled text
styled_text.prepaint(
global_id,
inspector_id,
bounds,
&mut (),
window,
cx
);
// Create hitbox for interaction
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
hitbox
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
styled_text: &mut Self::RequestLayoutState,
hitbox: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App
) {
// Paint the styled text
styled_text.paint(
global_id,
inspector_id,
bounds,
&mut (),
&mut (),
window,
cx
);
// Set cursor style for text
window.set_cursor_style(CursorStyle::IBeam, hitbox);
}
}
```
## Interactive Element with Selection
A text element that supports text selection via mouse interaction.
```rust
#[derive(Clone)]
pub struct Selection {
pub start: usize,
pub end: usize,
}
pub struct SelectableText {
id: ElementId,
text: SharedString,
selectable: bool,
selection: Option<Selection>,
}
impl IntoElement for SelectableText {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
impl Element for SelectableText {
type RequestLayoutState = TextLayout;
type PrepaintState = Option<Hitbox>;
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, Self::RequestLayoutState) {
let styled_text = StyledText::new(self.text.clone());
let (layout_id, _) = styled_text.request_layout(
global_id,
inspector_id,
window,
cx
);
// Extract text layout for selection painting
let text_layout = styled_text.layout().clone();
(layout_id, text_layout)
}
fn prepaint(
&mut self,
_global_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_text_layout: &mut Self::RequestLayoutState,
window: &mut Window,
_cx: &mut App
) -> Self::PrepaintState {
// Only create hitbox if selectable
if self.selectable {
Some(window.insert_hitbox(bounds, HitboxBehavior::Normal))
} else {
None
}
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
text_layout: &mut Self::RequestLayoutState,
hitbox: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App
) {
// Paint text
let styled_text = StyledText::new(self.text.clone());
styled_text.paint(
global_id,
inspector_id,
bounds,
&mut (),
&mut (),
window,
cx
);
// Paint selection if any
if let Some(selection) = &self.selection {
Self::paint_selection(selection, text_layout, &bounds, window, cx);
}
// Handle mouse events for selection
if let Some(hitbox) = hitbox {
window.set_cursor_style(CursorStyle::IBeam, hitbox);
// Mouse down to start selection
window.on_mouse_event({
let bounds = bounds.clone();
move |event: &MouseDownEvent, phase, window, cx| {
if bounds.contains(&event.position) && phase.bubble() {
// Start selection at mouse position
let char_index = Self::position_to_index(
event.position,
&bounds,
text_layout
);
self.selection = Some(Selection {
start: char_index,
end: char_index,
});
cx.notify();
cx.stop_propagation();
}
}
});
// Mouse drag to extend selection
window.on_mouse_event({
let bounds = bounds.clone();
move |event: &MouseMoveEvent, phase, window, cx| {
if let Some(selection) = &mut self.selection {
if phase.bubble() {
let char_index = Self::position_to_index(
event.position,
&bounds,
text_layout
);
selection.end = char_index;
cx.notify();
}
}
}
});
}
}
}
impl SelectableText {
fn paint_selection(
selection: &Selection,
text_layout: &TextLayout,
bounds: &Bounds<Pixels>,
window: &mut Window,
cx: &mut App
) {
// Calculate selection bounds from text layout
let selection_rects = text_layout.rects_for_range(
selection.start..selection.end
);
// Paint selection background
for rect in selection_rects {
window.paint_quad(paint_quad(
Bounds::new(
point(bounds.left() + rect.origin.x, bounds.top() + rect.origin.y),
rect.size
),
Corners::default(),
cx.theme().selection_background,
));
}
}
fn position_to_index(
position: Point<Pixels>,
bounds: &Bounds<Pixels>,
text_layout: &TextLayout
) -> usize {
// Convert screen position to character index
let relative_pos = point(
position.x - bounds.left(),
position.y - bounds.top()
);
text_layout.index_for_position(relative_pos)
}
}
```
## Complex Element with Child Management
A container element that manages multiple children with scrolling support.
```rust
pub struct ComplexElement {
id: ElementId,
children: Vec<Box<dyn Element<RequestLayoutState = (), PrepaintState = ()>>>,
scrollable: bool,
scroll_offset: Point<Pixels>,
}
struct ComplexLayoutState {
child_layouts: Vec<LayoutId>,
total_height: Pixels,
}
struct ComplexPaintState {
child_bounds: Vec<Bounds<Pixels>>,
hitbox: Hitbox,
}
impl IntoElement for ComplexElement {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
impl Element for ComplexElement {
type RequestLayoutState = ComplexLayoutState;
type PrepaintState = ComplexPaintState;
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App
) -> (LayoutId, Self::RequestLayoutState) {
let mut child_layouts = Vec::new();
let mut total_height = px(0.);
// Request layout for all children
for child in &mut self.children {
let (child_layout_id, _) = child.request_layout(
global_id,
inspector_id,
window,
cx
);
child_layouts.push(child_layout_id);
// Get child size from layout
let child_size = window.layout_bounds(child_layout_id).size();
total_height += child_size.height;
}
// Create container layout
let layout_id = window.request_layout(
Style {
flex_direction: FlexDirection::Column,
gap: px(8.),
size: Size {
width: relative(1.0),
height: if self.scrollable {
// Fixed height for scrollable
px(400.)
} else {
// Auto height for non-scrollable
total_height
},
},
..default()
},
child_layouts.clone(),
cx
);
(layout_id, ComplexLayoutState {
child_layouts,
total_height,
})
}
fn prepaint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
layout_state: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App
) -> Self::PrepaintState {
let mut child_bounds = Vec::new();
let mut y_offset = self.scroll_offset.y;
// Calculate child bounds and prepaint children
for (child, layout_id) in self.children.iter_mut()
.zip(&layout_state.child_layouts)
{
let child_size = window.layout_bounds(*layout_id).size();
let child_bound = Bounds::new(
point(bounds.left(), bounds.top() + y_offset),
child_size
);
// Only prepaint visible children
if self.is_visible(&child_bound, &bounds) {
child.prepaint(
global_id,
inspector_id,
child_bound,
&mut (),
window,
cx
);
}
child_bounds.push(child_bound);
y_offset += child_size.height + px(8.); // gap
}
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
ComplexPaintState {
child_bounds,
hitbox,
}
}
fn paint(
&mut self,
global_id: Option<&GlobalElementId>,
inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
layout_state: &mut Self::RequestLayoutState,
paint_state: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App
) {
// Paint background
window.paint_quad(paint_quad(
bounds,
Corners::all(px(4.)),
cx.theme().background,
));
// Paint visible children only
for (i, child) in self.children.iter_mut().enumerate() {
let child_bounds = paint_state.child_bounds[i];
if self.is_visible(&child_bounds, &bounds) {
child.paint(
global_id,
inspector_id,
child_bounds,
&mut (),
&mut (),
window,
cx
);
}
}
// Paint scrollbar if scrollable
if self.scrollable {
self.paint_scrollbar(bounds, layout_state, window, cx);
}
// Handle scroll events
if self.scrollable {
window.on_mouse_event({
let hitbox = paint_state.hitbox.clone();
let total_height = layout_state.total_height;
let visible_height = bounds.size.height;
move |event: &ScrollWheelEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Update scroll offset
self.scroll_offset.y -= event.delta.y;
// Clamp scroll offset
let max_scroll = (total_height - visible_height).max(px(0.));
self.scroll_offset.y = self.scroll_offset.y
.max(px(0.))
.min(max_scroll);
cx.notify();
cx.stop_propagation();
}
}
});
}
}
}
impl ComplexElement {
fn is_visible(&self, child_bounds: &Bounds<Pixels>, container_bounds: &Bounds<Pixels>) -> bool {
// Check if child is within visible area
child_bounds.bottom() >= container_bounds.top() &&
child_bounds.top() <= container_bounds.bottom()
}
fn paint_scrollbar(
&self,
bounds: Bounds<Pixels>,
layout_state: &ComplexLayoutState,
window: &mut Window,
cx: &mut App
) {
let scrollbar_width = px(8.);
let visible_height = bounds.size.height;
let total_height = layout_state.total_height;
if total_height <= visible_height {
return; // No need for scrollbar
}
// Calculate scrollbar position and size
let scroll_ratio = self.scroll_offset.y / (total_height - visible_height);
let thumb_height = (visible_height / total_height) * visible_height;
let thumb_y = scroll_ratio * (visible_height - thumb_height);
// Paint scrollbar track
let track_bounds = Bounds::new(
point(bounds.right() - scrollbar_width, bounds.top()),
size(scrollbar_width, visible_height)
);
window.paint_quad(paint_quad(
track_bounds,
Corners::default(),
cx.theme().scrollbar_track,
));
// Paint scrollbar thumb
let thumb_bounds = Bounds::new(
point(bounds.right() - scrollbar_width, bounds.top() + thumb_y),
size(scrollbar_width, thumb_height)
);
window.paint_quad(paint_quad(
thumb_bounds,
Corners::all(px(4.)),
cx.theme().scrollbar_thumb,
));
}
}
```
## Usage Examples
### Using SimpleText
```rust
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.child(SimpleText {
id: ElementId::Name("code-text".into()),
text: "fn main() { println!(\"Hello\"); }".into(),
highlights: vec![
(0..2, HighlightStyle::keyword()),
(3..7, HighlightStyle::function()),
],
})
}
```
### Using SelectableText
```rust
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.child(SelectableText {
id: ElementId::Name("selectable-text".into()),
text: "Select this text with your mouse".into(),
selectable: true,
selection: self.current_selection.clone(),
})
}
```
### Using ComplexElement
```rust
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let children: Vec<Box<dyn Element<_, _>>> = self.items
.iter()
.map(|item| Box::new(div().child(item.name.clone())) as Box<_>)
.collect();
div()
.child(ComplexElement {
id: ElementId::Name("scrollable-list".into()),
children,
scrollable: true,
scroll_offset: self.scroll_offset,
})
}
```
================================================
FILE: .claude/skills/gpui-element/references/patterns.md
================================================
# Common Element Patterns
Reusable patterns for implementing common element types in GPUI.
## Text Rendering Elements
Elements that display and manipulate text content.
### Pattern Characteristics
- Use `StyledText` for text layout and rendering
- Handle text selection in `paint` phase with hitbox interaction
- Create hitboxes for text interaction in `prepaint`
- Support text highlighting and custom styling via runs
### Implementation Template
```rust
pub struct TextElement {
id: ElementId,
text: SharedString,
style: TextStyle,
}
impl Element for TextElement {
type RequestLayoutState = StyledText;
type PrepaintState = Hitbox;
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, StyledText)
{
let styled_text = StyledText::new(self.text.clone())
.with_style(self.style);
let (layout_id, _) = styled_text.request_layout(None, None, window, cx);
(layout_id, styled_text)
}
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, styled_text: &mut StyledText,
window: &mut Window, cx: &mut App) -> Hitbox
{
styled_text.prepaint(None, None, bounds, &mut (), window, cx);
window.insert_hitbox(bounds, HitboxBehavior::Normal)
}
fn paint(&mut self, .., bounds: Bounds<Pixels>, styled_text: &mut StyledText,
hitbox: &mut Hitbox, window: &mut Window, cx: &mut App)
{
styled_text.paint(None, None, bounds, &mut (), &mut (), window, cx);
window.set_cursor_style(CursorStyle::IBeam, hitbox);
}
}
```
### Use Cases
- Code editors with syntax highlighting
- Rich text displays
- Labels with custom formatting
- Selectable text areas
## Container Elements
Elements that manage and layout child elements.
### Pattern Characteristics
- Manage child element layouts and positions
- Handle scrolling and clipping when needed
- Implement flex/grid-like layouts
- Coordinate child interactions and event delegation
### Implementation Template
```rust
pub struct ContainerElement {
id: ElementId,
children: Vec<AnyElement>,
direction: FlexDirection,
gap: Pixels,
}
impl Element for ContainerElement {
type RequestLayoutState = Vec<LayoutId>;
type PrepaintState = Vec<Bounds<Pixels>>;
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Vec<LayoutId>)
{
let child_layout_ids: Vec<_> = self.children
.iter_mut()
.map(|child| child.request_layout(window, cx).0)
.collect();
let layout_id = window.request_layout(
Style {
flex_direction: self.direction,
gap: self.gap,
..default()
},
child_layout_ids.clone(),
cx
);
(layout_id, child_layout_ids)
}
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout_ids: &mut Vec<LayoutId>,
window: &mut Window, cx: &mut App) -> Vec<Bounds<Pixels>>
{
let mut child_bounds = Vec::new();
for (child, layout_id) in self.children.iter_mut().zip(layout_ids.iter()) {
let child_bound = window.layout_bounds(*layout_id);
child.prepaint(child_bound, window, cx);
child_bounds.push(child_bound);
}
child_bounds
}
fn paint(&mut self, .., child_bounds: &mut Vec<Bounds<Pixels>>,
window: &mut Window, cx: &mut App)
{
for (child, bounds) in self.children.iter_mut().zip(child_bounds.iter()) {
child.paint(*bounds, window, cx);
}
}
}
```
### Use Cases
- Panels and split views
- List containers
- Grid layouts
- Tab containers
## Interactive Elements
Elements that respond to user input (mouse, keyboard, touch).
### Pattern Characteristics
- Create appropriate hitboxes for interaction areas
- Handle mouse/keyboard/touch events properly
- Manage focus and cursor styles
- Support hover, active, and disabled states
### Implementation Template
```rust
pub struct InteractiveElement {
id: ElementId,
content: AnyElement,
on_click: Option<Box<dyn Fn(&MouseUpEvent, &mut Window, &mut App)>>,
hover_style: Option<Style>,
}
impl Element for InteractiveElement {
type RequestLayoutState = LayoutId;
type PrepaintState = (Hitbox, bool); // hitbox and is_hovered
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, LayoutId)
{
let (content_layout, _) = self.content.request_layout(window, cx);
(content_layout, content_layout)
}
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, content_layout: &mut LayoutId,
window: &mut Window, cx: &mut App) -> (Hitbox, bool)
{
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
let is_hovered = hitbox.is_hovered(window);
self.content.prepaint(bounds, window, cx);
(hitbox, is_hovered)
}
fn paint(&mut self, .., bounds: Bounds<Pixels>, content_layout: &mut LayoutId,
prepaint: &mut (Hitbox, bool), window: &mut Window, cx: &mut App)
{
let (hitbox, is_hovered) = prepaint;
// Paint hover background if hovered
if *is_hovered {
if let Some(hover_style) = &self.hover_style {
window.paint_quad(paint_quad(
bounds,
Corners::all(px(4.)),
hover_style.background_color.unwrap_or(cx.theme().hover),
));
}
}
// Paint content
self.content.paint(bounds, window, cx);
// Handle click
if let Some(on_click) = self.on_click.as_ref() {
window.on_mouse_event({
let on_click = on_click.clone();
let hitbox = hitbox.clone();
move |event: &MouseUpEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
on_click(event, window, cx);
cx.stop_propagation();
}
}
});
}
// Set cursor style
window.set_cursor_style(CursorStyle::PointingHand, hitbox);
}
}
```
### Use Cases
- Buttons
- Links
- Clickable cards
- Drag handles
- Menu items
## Composite Elements
Elements that combine multiple child elements with complex coordination.
### Pattern Characteristics
- Combine multiple child elements with different types
- Manage complex state across children
- Coordinate animations and transitions
- Handle focus delegation between children
### Implementation Template
```rust
pub struct CompositeElement {
id: ElementId,
header: AnyElement,
content: AnyElement,
footer: Option<AnyElement>,
}
struct CompositeLayoutState {
header_layout: LayoutId,
content_layout: LayoutId,
footer_layout: Option<LayoutId>,
}
struct CompositePaintState {
header_bounds: Bounds<Pixels>,
content_bounds: Bounds<Pixels>,
footer_bounds: Option<Bounds<Pixels>>,
}
impl Element for CompositeElement {
type RequestLayoutState = CompositeLayoutState;
type PrepaintState = CompositePaintState;
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, CompositeLayoutState)
{
let (header_layout, _) = self.header.request_layout(window, cx);
let (content_layout, _) = self.content.request_layout(window, cx);
let footer_layout = self.footer.as_mut()
.map(|f| f.request_layout(window, cx).0);
let mut children = vec![header_layout, content_layout];
if let Some(footer) = footer_layout {
children.push(footer);
}
let layout_id = window.request_layout(
Style {
flex_direction: FlexDirection::Column,
size: Size {
width: relative(1.0),
height: auto(),
},
..default()
},
children,
cx
);
(layout_id, CompositeLayoutState {
header_layout,
content_layout,
footer_layout,
})
}
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut CompositeLayoutState,
window: &mut Window, cx: &mut App) -> CompositePaintState
{
let header_bounds = window.layout_bounds(layout.header_layout);
let content_bounds = window.layout_bounds(layout.content_layout);
let footer_bounds = layout.footer_layout
.map(|id| window.layout_bounds(id));
self.header.prepaint(header_bounds, window, cx);
self.content.prepaint(content_bounds, window, cx);
if let (Some(footer), Some(bounds)) = (&mut self.footer, footer_bounds) {
footer.prepaint(bounds, window, cx);
}
CompositePaintState {
header_bounds,
content_bounds,
footer_bounds,
}
}
fn paint(&mut self, .., paint_state: &mut CompositePaintState,
window: &mut Window, cx: &mut App)
{
self.header.paint(paint_state.header_bounds, window, cx);
self.content.paint(paint_state.content_bounds, window, cx);
if let (Some(footer), Some(bounds)) = (&mut self.footer, paint_state.footer_bounds) {
footer.paint(bounds, window, cx);
}
}
}
```
### Use Cases
- Dialog boxes (header + content + footer)
- Cards with multiple sections
- Form layouts
- Panels with toolbars
## Scrollable Elements
Elements with scrollable content areas.
### Pattern Characteristics
- Manage scroll state (offset, velocity)
- Handle scroll events (wheel, drag, touch)
- Paint scrollbars (track and thumb)
- Clip content to visible area
### Implementation Template
```rust
pub struct ScrollableElement {
id: ElementId,
content: AnyElement,
scroll_offset: Point<Pixels>,
content_size: Size<Pixels>,
}
struct ScrollPaintState {
hitbox: Hitbox,
visible_bounds: Bounds<Pixels>,
}
impl Element for ScrollableElement {
type RequestLayoutState = (LayoutId, Size<Pixels>);
type PrepaintState = ScrollPaintState;
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, (LayoutId, Size<Pixels>))
{
let (content_layout, _) = self.content.request_layout(window, cx);
let content_size = window.layout_bounds(content_layout).size;
let layout_id = window.request_layout(
Style {
size: Size {
width: relative(1.0),
height: px(400.), // Fixed viewport height
},
overflow: Overflow::Hidden,
..default()
},
vec![content_layout],
cx
);
(layout_id, (content_layout, content_size))
}
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut (LayoutId, Size<Pixels>),
window: &mut Window, cx: &mut App) -> ScrollPaintState
{
let (content_layout, content_size) = layout;
// Calculate content bounds with scroll offset
let content_bounds = Bounds::new(
point(bounds.left(), bounds.top() - self.scroll_offset.y),
*content_size
);
self.content.prepaint(content_bounds, window, cx);
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
ScrollPaintState {
hitbox,
visible_bounds: bounds,
}
}
fn paint(&mut self, .., layout: &mut (LayoutId, Size<Pixels>),
paint_state: &mut ScrollPaintState, window: &mut Window, cx: &mut App)
{
let (_, content_size) = layout;
// Paint content
self.content.paint(paint_state.visible_bounds, window, cx);
// Paint scrollbar
self.paint_scrollbar(paint_state.visible_bounds, *content_size, window, cx);
// Handle scroll events
window.on_mouse_event({
let hitbox = paint_state.hitbox.clone();
let content_height = content_size.height;
let visible_height = paint_state.visible_bounds.size.height;
move |event: &ScrollWheelEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Update scroll offset
self.scroll_offset.y -= event.delta.y;
// Clamp to valid range
let max_scroll = (content_height - visible_height).max(px(0.));
self.scroll_offset.y = self.scroll_offset.y
.max(px(0.))
.min(max_scroll);
cx.notify();
cx.stop_propagation();
}
}
});
}
}
impl ScrollableElement {
fn paint_scrollbar(
&self,
bounds: Bounds<Pixels>,
content_size: Size<Pixels>,
window: &mut Window,
cx: &mut App
) {
let visible_height = bounds.size.height;
let content_height = content_size.height;
if content_height <= visible_height {
return; // No scrollbar needed
}
let scrollbar_width = px(8.);
// Calculate thumb position and size
let scroll_ratio = self.scroll_offset.y / (content_height - visible_height);
let thumb_height = (visible_height / content_height) * visible_height;
let thumb_y = scroll_ratio * (visible_height - thumb_height);
// Paint track
window.paint_quad(paint_quad(
Bounds::new(
point(bounds.right() - scrollbar_width, bounds.top()),
size(scrollbar_width, visible_height)
),
Corners::default(),
cx.theme().scrollbar_track,
));
// Paint thumb
window.paint_quad(paint_quad(
Bounds::new(
point(bounds.right() - scrollbar_width, bounds.top() + thumb_y),
size(scrollbar_width, thumb_height)
),
Corners::all(px(4.)),
cx.theme().scrollbar_thumb,
));
}
}
```
### Use Cases
- Scrollable lists
- Code editors with large files
- Long-form text content
- Image galleries
## Pattern Selection Guide
| Need | Pattern | Complexity |
|------|---------|------------|
| Display styled text | Text Rendering | Low |
| Layout multiple children | Container | Low-Medium |
| Handle clicks/hovers | Interactive | Medium |
| Complex multi-part UI | Composite | Medium-High |
| Large content with scrolling | Scrollable | High |
Choose the simplest pattern that meets your requirements, then extend as needed.
================================================
FILE: .claude/skills/gpui-entity/SKILL.md
================================================
---
name: gpui-entity
description: Entity management and state handling in GPUI. Use when working with entities, managing component state, coordinating between components, handling async operations with state updates, or implementing reactive patterns. Entities provide safe concurrent access to application state.
---
## Overview
An `Entity<T>` is a handle to state of type `T`, providing safe access and updates.
**Key Methods:**
- `entity.read(cx)` → `&T` - Read-only access
- `entity.read_with(cx, |state, cx| ...)` → `R` - Read with closure
- `entity.update(cx, |state, cx| ...)` → `R` - Mutable update
- `entity.downgrade()` → `WeakEntity<T>` - Create weak reference
- `entity.entity_id()` → `EntityId` - Unique identifier
**Entity Types:**
- **`Entity<T>`**: Strong reference (increases ref count)
- **`WeakEntity<T>`**: Weak reference (doesn't prevent cleanup, returns `Result`)
## Quick Start
### Creating and Using Entities
```rust
// Create entity
let counter = cx.new(|cx| Counter { count: 0 });
// Read state
let count = counter.read(cx).count;
// Update state
counter.update(cx, |state, cx| {
state.count += 1;
cx.notify(); // Trigger re-render
});
// Weak reference (for closures/callbacks)
let weak = counter.downgrade();
let _ = weak.update(cx, |state, cx| {
state.count += 1;
cx.notify();
});
```
### In Components
```rust
struct MyComponent {
shared_state: Entity<SharedData>,
}
impl MyComponent {
fn new(cx: &mut App) -> Entity<Self> {
let shared = cx.new(|_| SharedData::default());
cx.new(|cx| Self {
shared_state: shared,
})
}
fn update_shared(&mut self, cx: &mut Context<Self>) {
self.shared_state.update(cx, |state, cx| {
state.value = 42;
cx.notify();
});
}
}
```
### Async Operations
```rust
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let weak_self = cx.entity().downgrade();
cx.spawn(async move |cx| {
let data = fetch_from_api().await;
// Update entity safely
let _ = weak_self.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
});
}).detach();
}
}
```
## Core Principles
### Always Use Weak References in Closures
```rust
// ✅ Good: Weak reference prevents retain cycles
let weak = cx.entity().downgrade();
callback(move || {
let _ = weak.update(cx, |state, cx| cx.notify());
});
// ❌ Bad: Strong reference may cause memory leak
let strong = cx.entity();
callback(move || {
strong.update(cx, |state, cx| cx.notify());
});
```
### Use Inner Context
```rust
// ✅ Good: Use inner cx from closure
entity.update(cx, |state, inner_cx| {
inner_cx.notify(); // Correct
});
// ❌ Bad: Use outer cx (multiple borrow error)
entity.update(cx, |state, inner_cx| {
cx.notify(); // Wrong!
});
```
### Avoid Nested Updates
```rust
// ✅ Good: Sequential updates
entity1.update(cx, |state, cx| { /* ... */ });
entity2.update(cx, |state, cx| { /* ... */ });
// ❌ Bad: Nested updates (may panic)
entity1.update(cx, |_, cx| {
entity2.update(cx, |_, cx| { /* ... */ });
});
```
## Common Use Cases
1. **Component State**: Internal state that needs reactivity
2. **Shared State**: State shared between multiple components
3. **Parent-Child**: Coordinating between related components (use weak refs)
4. **Async State**: Managing state that changes from async operations
5. **Observations**: Reacting to changes in other entities
## Reference Documentation
### Complete API Documentation
- **Entity API**: See [api-reference.md](references/api-reference.md)
- Entity types, methods, lifecycle
- Context methods, async operations
- Error handling, type conversions
### Implementation Guides
- **Patterns**: See [patterns.md](references/patterns.md)
- Model-view separation, state management
- Cross-entity communication, async operations
- Observer pattern, event subscription
- Pattern selection guide
- **Best Practices**: See [best-practices.md](references/best-practices.md)
- Avoiding common pitfalls, memory leaks
- Performance optimization, batching updates
- Lifecycle management, cleanup
- Async best practices, testing
- **Advanced Patterns**: See [advanced.md](references/advanced.md)
- Entity collections, registry pattern
- Debounced/throttled updates, state machines
- Entity snapshots, transactions, pools
================================================
FILE: .claude/skills/gpui-entity/references/advanced.md
================================================
# Advanced Entity Patterns
Advanced techniques for sophisticated entity management scenarios.
## Entity Collections Management
### Dynamic Collection with Cleanup
```rust
struct EntityCollection<T> {
strong_refs: Vec<Entity<T>>,
weak_refs: Vec<WeakEntity<T>>,
}
impl<T> EntityCollection<T> {
fn new() -> Self {
Self {
strong_refs: Vec::new(),
weak_refs: Vec::new(),
}
}
fn add(&mut self, entity: Entity<T>, cx: &mut App) {
self.strong_refs.push(entity.clone());
self.weak_refs.push(entity.downgrade());
}
fn remove(&mut self, entity_id: EntityId, cx: &mut App) {
self.strong_refs.retain(|e| e.entity_id() != entity_id);
self.weak_refs.retain(|w| {
w.upgrade()
.map(|e| e.entity_id() != entity_id)
.unwrap_or(false)
});
}
fn cleanup_invalid(&mut self, cx: &mut App) {
self.weak_refs.retain(|weak| weak.upgrade().is_some());
}
fn for_each<F>(&self, cx: &mut App, mut f: F)
where
F: FnMut(&Entity<T>, &mut App),
{
for entity in &self.strong_refs {
f(entity, cx);
}
}
fn for_each_weak<F>(&mut self, cx: &mut App, mut f: F)
where
F: FnMut(Entity<T>, &mut App),
{
self.weak_refs.retain(|weak| {
if let Some(entity) = weak.upgrade() {
f(entity, cx);
true
} else {
false // Remove invalid weak references
}
});
}
}
```
### Entity Registry Pattern
```rust
use std::collections::HashMap;
struct EntityRegistry<T> {
entities: HashMap<EntityId, WeakEntity<T>>,
}
impl<T> EntityRegistry<T> {
fn new() -> Self {
Self {
entities: HashMap::new(),
}
}
fn register(&mut self, entity: &Entity<T>) {
self.entities.insert(entity.entity_id(), entity.downgrade());
}
fn unregister(&mut self, entity_id: EntityId) {
self.entities.remove(&entity_id);
}
fn get(&self, entity_id: EntityId) -> Option<Entity<T>> {
self.entities.get(&entity_id)?.upgrade()
}
fn cleanup(&mut self) {
self.entities.retain(|_, weak| weak.upgrade().is_some());
}
fn count(&self) -> usize {
self.entities.len()
}
fn all_entities(&self) -> Vec<Entity<T>> {
self.entities
.values()
.filter_map(|weak| weak.upgrade())
.collect()
}
}
```
## Conditional Update Patterns
### Debounced Updates
```rust
use std::time::{Duration, Instant};
struct DebouncedEntity<T> {
entity: Entity<T>,
last_update: Instant,
debounce_duration: Duration,
pending_update: Option<Box<dyn FnOnce(&mut T, &mut Context<T>)>>,
}
impl<T: 'static> DebouncedEntity<T> {
fn new(entity: Entity<T>, debounce_ms: u64) -> Self {
Self {
entity,
last_update: Instant::now(),
debounce_duration: Duration::from_millis(debounce_ms),
pending_update: None,
}
}
fn update<F>(&mut self, cx: &mut App, update_fn: F)
where
F: FnOnce(&mut T, &mut Context<T>) + 'static,
{
let now = Instant::now();
let elapsed = now.duration_since(self.last_update);
if elapsed >= self.debounce_duration {
// Execute immediately
self.entity.update(cx, update_fn);
self.last_update = now;
self.pending_update = None;
} else {
// Store for later
self.pending_update = Some(Box::new(update_fn));
// Schedule execution
let entity = self.entity.clone();
let delay = self.debounce_duration - elapsed;
cx.spawn(async move |cx| {
tokio::time::sleep(delay).await;
if let Some(update) = self.pending_update.take() {
entity.update(cx, |state, inner_cx| {
update(state, inner_cx);
});
}
}).detach();
}
}
}
```
### Throttled Updates
```rust
struct ThrottledEntity<T> {
entity: Entity<T>,
last_update: Instant,
throttle_duration: Duration,
}
impl<T: 'static> ThrottledEntity<T> {
fn new(entity: Entity<T>, throttle_ms: u64) -> Self {
Self {
entity,
last_update: Instant::now(),
throttle_duration: Duration::from_millis(throttle_ms),
}
}
fn try_update<F>(&mut self, cx: &mut App, update_fn: F) -> bool
where
F: FnOnce(&mut T, &mut Context<T>),
{
let now = Instant::now();
let elapsed = now.duration_since(self.last_update);
if elapsed >= self.throttle_duration {
self.entity.update(cx, update_fn);
self.last_update = now;
true
} else {
false // Update throttled
}
}
}
```
## Entity State Machine Pattern
```rust
enum AppState {
Idle,
Loading,
Loaded(String),
Error(String),
}
struct StateMachine {
state: AppState,
}
impl StateMachine {
fn new() -> Self {
Self {
state: AppState::Idle,
}
}
fn start_loading(&mut self, cx: &mut Context<Self>) {
if matches!(self.state, AppState::Idle | AppState::Error(_)) {
self.state = AppState::Loading;
cx.notify();
let weak_entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
let result = perform_load().await;
let _ = weak_entity.update(cx, |state, cx| {
match result {
Ok(data) => state.on_load_success(data, cx),
Err(e) => state.on_load_error(e.to_string(), cx),
}
});
}).detach();
}
}
fn on_load_success(&mut self, data: String, cx: &mut Context<Self>) {
if matches!(self.state, AppState::Loading) {
self.state = AppState::Loaded(data);
cx.notify();
}
}
fn on_load_error(&mut self, error: String, cx: &mut Context<Self>) {
if matches!(self.state, AppState::Loading) {
self.state = AppState::Error(error);
cx.notify();
}
}
fn reset(&mut self, cx: &mut Context<Self>) {
self.state = AppState::Idle;
cx.notify();
}
}
async fn perform_load() -> Result<String, anyhow::Error> {
// Actual load implementation
Ok("Data".to_string())
}
```
## Entity Proxy Pattern
```rust
struct EntityProxy<T> {
entity: WeakEntity<T>,
}
impl<T> EntityProxy<T> {
fn new(entity: &Entity<T>) -> Self {
Self {
entity: entity.downgrade(),
}
}
fn with<F, R>(&self, cx: &mut App, f: F) -> Result<R, anyhow::Error>
where
F: FnOnce(&T, &App) -> R,
{
self.entity.read_with(cx, f)
}
fn update<F, R>(&self, cx: &mut App, f: F) -> Result<R, anyhow::Error>
where
F: FnOnce(&mut T, &mut Context<T>) -> R,
{
self.entity.update(cx, f)
}
fn is_valid(&self, cx: &App) -> bool {
self.entity.upgrade().is_some()
}
}
```
## Cascading Updates Pattern
```rust
struct CascadingUpdater {
entities: Vec<WeakEntity<UpdateTarget>>,
}
impl CascadingUpdater {
fn new() -> Self {
Self {
entities: Vec::new(),
}
}
fn add_target(&mut self, entity: &Entity<UpdateTarget>) {
self.entities.push(entity.downgrade());
}
fn cascade_update<F>(&mut self, cx: &mut App, update_fn: F)
where
F: Fn(&mut UpdateTarget, &mut Context<UpdateTarget>) + Clone,
{
// Update all entities in sequence
self.entities.retain(|weak| {
if let Ok(_) = weak.update(cx, |state, inner_cx| {
update_fn.clone()(state, inner_cx);
}) {
true // Keep valid entity
} else {
false // Remove invalid entity
}
});
}
}
struct UpdateTarget {
value: i32,
}
```
## Entity Snapshot Pattern
```rust
use serde::{Serialize, Deserialize};
#[derive(Clone, Serialize, Deserialize)]
struct EntitySnapshot {
data: String,
timestamp: u64,
}
struct SnapshotableEntity {
data: String,
snapshots: Vec<EntitySnapshot>,
}
impl SnapshotableEntity {
fn new(data: String) -> Self {
Self {
data,
snapshots: Vec::new(),
}
}
fn take_snapshot(&mut self, cx: &mut Context<Self>) {
let snapshot = EntitySnapshot {
data: self.data.clone(),
timestamp: current_timestamp(),
};
self.snapshots.push(snapshot);
cx.notify();
}
fn restore_snapshot(&mut self, index: usize, cx: &mut Context<Self>) -> Result<(), String> {
if let Some(snapshot) = self.snapshots.get(index) {
self.data = snapshot.data.clone();
cx.notify();
Ok(())
} else {
Err("Invalid snapshot index".to_string())
}
}
fn clear_old_snapshots(&mut self, keep_last: usize, cx: &mut Context<Self>) {
if self.snapshots.len() > keep_last {
self.snapshots.drain(0..self.snapshots.len() - keep_last);
cx.notify();
}
}
}
fn current_timestamp() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
}
```
## Entity Transaction Pattern
```rust
struct Transaction<T> {
entity: Entity<T>,
original_state: Option<T>,
}
impl<T: Clone> Transaction<T> {
fn begin(entity: Entity<T>, cx: &mut App) -> Self {
let original_state = entity.read(cx).clone();
Self {
entity,
original_state: Some(original_state),
}
}
fn update<F>(&mut self, cx: &mut App, update_fn: F)
where
F: FnOnce(&mut T, &mut Context<T>),
{
self.entity.update(cx, update_fn);
}
fn commit(mut self, cx: &mut App) {
self.original_state = None; // Don't rollback
self.entity.update(cx, |_, cx| {
cx.notify();
});
}
fn rollback(mut self, cx: &mut App) {
if let Some(original) = self.original_state.take() {
self.entity.update(cx, |state, cx| {
*state = original;
cx.notify();
});
}
}
}
impl<T> Drop for Transaction<T> {
fn drop(&mut self) {
// Auto-rollback if not committed
if self.original_state.is_some() {
eprintln!("Warning: Transaction dropped without commit");
}
}
}
// Usage
fn perform_transaction(entity: Entity<MyState>, cx: &mut App) -> Result<(), String> {
let mut tx = Transaction::begin(entity, cx);
tx.update(cx, |state, cx| {
state.value = 42;
});
if validate_state(&tx.entity, cx)? {
tx.commit(cx);
Ok(())
} else {
tx.rollback(cx);
Err("Validation failed".to_string())
}
}
```
## Entity Pool Pattern
```rust
struct EntityPool<T> {
available: Vec<Entity<T>>,
in_use: Vec<WeakEntity<T>>,
factory: Box<dyn Fn(&mut App) -> Entity<T>>,
}
impl<T: 'static> EntityPool<T> {
fn new<F>(factory: F) -> Self
where
F: Fn(&mut App) -> Entity<T> + 'static,
{
Self {
available: Vec::new(),
in_use: Vec::new(),
factory: Box::new(factory),
}
}
fn acquire(&mut self, cx: &mut App) -> Entity<T> {
let entity = if let Some(entity) = self.available.pop() {
entity
} else {
(self.factory)(cx)
};
self.in_use.push(entity.downgrade());
entity
}
fn release(&mut self, entity: Entity<T>, cx: &mut App) {
// Reset entity state if needed
entity.update(cx, |state, cx| {
// Reset logic here
cx.notify();
});
self.available.push(entity);
self.cleanup_in_use();
}
fn cleanup_in_use(&mut self) {
self.in_use.retain(|weak| weak.upgrade().is_some());
}
fn pool_size(&self) -> (usize, usize) {
(self.available.len(), self.in_use.len())
}
}
```
These advanced patterns provide powerful abstractions for managing complex entity scenarios while maintaining code quality and performance.
================================================
FILE: .claude/skills/gpui-entity/references/api-reference.md
================================================
# Entity API Reference
Complete API documentation for GPUI's entity system.
## Entity Types
### Entity<T>
A strong reference to state of type `T`.
**Methods:**
- `entity_id()` → `EntityId` - Returns unique identifier
- `downgrade()` → `WeakEntity<T>` - Creates weak reference
- `read(cx)` → `&T` - Immutable access to state
- `read_with(cx, |state, cx| ...)` → `R` - Read with closure, returns closure result
- `update(cx, |state, cx| ...)` → `R` - Mutable update with `Context<T>`, returns closure result
- `update_in(cx, |state, window, cx| ...)` → `R` - Update with `Window` access (requires `AsyncWindowContext` or `VisualTestContext`)
**Important Notes:**
- Trying to update an entity while it's already being updated will panic
- Within closures, use the inner `cx` provided to avoid multiple borrow issues
- With async contexts, return values are wrapped in `anyhow::Result`
### WeakEntity<T>
A weak reference to state of type `T`.
**Methods:**
- `upgrade()` → `Option<Entity<T>>` - Convert to strong reference if still alive
- `read_with(cx, |state, cx| ...)` → `Result<R>` - Read if entity exists
- `update(cx, |state, cx| ...)` → `Result<R>` - Update if entity exists
- `update_in(cx, |state, window, cx| ...)` → `Result<R>` - Update with window if entity exists
**Use Cases:**
- Avoid circular dependencies between entities
- Store references in closures/callbacks without preventing cleanup
- Optional relationships between components
**Important:** All operations return `Result` since the entity may no longer exist.
### AnyEntity
Dynamically-typed entity handle for storing entities of different types.
### AnyWeakEntity
Dynamically-typed weak entity handle.
## Entity Creation
### cx.new()
Create new entity with initial state.
```rust
let entity = cx.new(|cx| MyState {
count: 0,
name: "Default".to_string(),
});
```
**Parameters:**
- `cx: &mut App` or other context type
- Closure receiving `&mut Context<T>` returning initial state `T`
**Returns:** `Entity<T>`
## Entity Operations
### Reading State
#### read()
Direct read-only access to state.
```rust
let count = my_entity.read(cx).count;
```
**Use when:** Simple field access, no context operations needed.
#### read_with()
Read with context access in closure.
```rust
let count = my_entity.read_with(cx, |state, cx| {
// Can access both state and context
state.count
});
// Return multiple values
let (count, theme) = my_entity.read_with(cx, |state, cx| {
(state.count, cx.theme().clone())
});
```
**Use when:** Need context operations, multiple return values, complex logic.
### Updating State
#### update()
Mutable update with `Context<T>`.
```rust
my_entity.update(cx, |state, cx| {
state.count += 1;
cx.notify(); // Trigger re-render
});
```
**Available Operations:**
- `cx.notify()` - Trigger re-render
- `cx.entity()` - Get current entity
- `cx.emit(event)` - Emit event
- `cx.spawn(task)` - Spawn async task
- Other `Context<T>` methods
#### update_in()
Update with both `Window` and `Context<T>` access.
```rust
my_entity.update_in(cx, |state, window, cx| {
state.focused = window.is_window_focused();
cx.notify();
});
```
**Requires:** `AsyncWindowContext` or `VisualTestContext`
**Use when:** Need window-specific operations like focus state, window bounds, etc.
## Context Methods for Entities
### cx.entity()
Get current entity being updated.
```rust
impl MyComponent {
fn some_method(&mut self, cx: &mut Context<Self>) {
let current_entity = cx.entity(); // Entity<MyComponent>
let weak = current_entity.downgrade();
}
}
```
### cx.observe()
Observe entity for changes.
```rust
cx.observe(&entity, |this, observed_entity, cx| {
// Called when observed_entity.update() calls cx.notify()
println!("Entity changed");
}).detach();
```
**Returns:** `Subscription` - Call `.detach()` to make permanent
### cx.subscribe()
Subscribe to events from entity.
```rust
cx.subscribe(&entity, |this, emitter, event: &SomeEvent, cx| {
// Called when emitter emits SomeEvent
match event {
SomeEvent::DataChanged => {
cx.notify();
}
}
}).detach();
```
**Returns:** `Subscription` - Call `.detach()` to make permanent
### cx.observe_new_entities()
Register callback for new entities of a type.
```rust
cx.observe_new_entities::<MyState>(|entity, cx| {
println!("New entity created: {:?}", entity.entity_id());
}).detach();
```
## Async Operations
### cx.spawn()
Spawn foreground task (UI thread).
```rust
cx.spawn(async move |this, cx| {
// `this`: WeakEntity<T>
// `cx`: &mut AsyncApp
let result = some_async_work().await;
// Update entity safely
let _ = this.update(cx, |state, cx| {
state.data = result;
cx.notify();
});
}).detach();
```
**Note:** Always use weak entity reference in spawned tasks to prevent retain cycles.
### cx.background_spawn()
Spawn background task (background thread).
```rust
cx.background_spawn(async move {
// Long-running computation
let result = heavy_computation().await;
// Cannot directly update entities here
// Use channels or spawn foreground task to update
}).detach();
```
## Entity Lifecycle
### Creation
Entities are created via `cx.new()` and immediately registered in the app.
### Reference Counting
- `Entity<T>` is a strong reference (increases reference count)
- `WeakEntity<T>` is a weak reference (does not increase reference count)
- Cloning `Entity<T>` increases reference count
### Disposal
Entities are automatically disposed when all strong references are dropped.
```rust
{
let entity = cx.new(|cx| MyState::default());
// entity exists
} // entity dropped here if no other strong references exist
```
**Memory Leak Prevention:**
- Use `WeakEntity` in closures/callbacks
- Use `WeakEntity` for parent-child relationships
- Avoid circular strong references
## EntityId
Every entity has a unique identifier.
```rust
let id: EntityId = entity.entity_id();
// EntityIds can be compared
if entity1.entity_id() == entity2.entity_id() {
// Same entity
}
```
**Use Cases:**
- Debugging and logging
- Entity comparison without borrowing
- Hash maps keyed by entity
## Error Handling
### WeakEntity Operations
All `WeakEntity` operations return `Result`:
```rust
let weak = entity.downgrade();
// Handle potential failure
match weak.read_with(cx, |state, cx| state.count) {
Ok(count) => println!("Count: {}", count),
Err(e) => eprintln!("Entity no longer exists: {}", e),
}
// Or use Result combinators
let _ = weak.update(cx, |state, cx| {
state.count += 1;
cx.notify();
}).ok(); // Ignore errors
```
### Update Panics
Nested updates on the same entity will panic:
```rust
// ❌ Will panic
entity.update(cx, |state1, cx| {
entity.update(cx, |state2, cx| {
// Panic: entity already borrowed
});
});
```
**Solution:** Perform updates sequentially or use different entities.
## Type Conversions
### Entity → WeakEntity
```rust
let entity: Entity<T> = cx.new(|cx| T::default());
let weak: WeakEntity<T> = entity.downgrade();
```
### WeakEntity → Entity
```rust
let weak: WeakEntity<T> = entity.downgrade();
let strong: Option<Entity<T>> = weak.upgrade();
```
### AnyEntity
```rust
let any: AnyEntity = entity.into();
let typed: Option<Entity<T>> = any.downcast::<T>();
```
## Best Practice Guidelines
### Always Use Inner cx
```rust
// ✅ Good: Use inner cx
entity.update(cx, |state, inner_cx| {
inner_cx.notify(); // Use inner_cx, not outer cx
});
// ❌ Bad: Use outer cx
entity.update(cx, |state, inner_cx| {
cx.notify(); // Wrong! Multiple borrow error
});
```
### Weak References in Closures
```rust
// ✅ Good: Weak reference
let weak = cx.entity().downgrade();
callback(move || {
let _ = weak.update(cx, |state, cx| {
cx.notify();
});
});
// ❌ Bad: Strong reference (retain cycle)
let strong = cx.entity();
callback(move || {
strong.update(cx, |state, cx| {
// May never be dropped
cx.notify();
});
});
```
### Sequential Updates
```rust
// ✅ Good: Sequential updates
entity1.update(cx, |state, cx| { /* ... */ });
entity2.update(cx, |state, cx| { /* ... */ });
// ❌ Bad: Nested updates
entity1.update(cx, |_, cx| {
entity2.update(cx, |_, cx| {
// May panic if entities are related
});
});
```
================================================
FILE: .claude/skills/gpui-entity/references/best-practices.md
================================================
# Entity Best Practices
Guidelines and best practices for effective entity management in GPUI.
## Avoiding Common Pitfalls
### Avoid Entity Borrowing Conflicts
**Problem:** Nested updates can cause borrow checker panics.
```rust
// ❌ Bad: Nested updates can panic
entity1.update(cx, |_, cx| {
entity2.update(cx, |_, cx| {
// This may panic if entities are related
});
});
```
**Solution:** Perform updates sequentially.
```rust
// ✅ Good: Sequential updates
entity1.update(cx, |state1, cx| {
// Update entity1
state1.value = 42;
cx.notify();
});
entity2.update(cx, |state2, cx| {
// Update entity2
state2.value = 100;
cx.notify();
});
```
### Use Weak References in Closures
**Problem:** Strong references in closures can create retain cycles and memory leaks.
```rust
// ❌ Bad: Strong reference creates retain cycle
impl MyComponent {
fn setup_callback(&mut self, cx: &mut Context<Self>) {
let entity = cx.entity(); // Strong reference
some_callback(move || {
entity.update(cx, |state, cx| {
// This closure holds a strong reference
// If the closure itself is retained by the entity, memory leak!
cx.notify();
});
});
}
}
```
**Solution:** Use weak references in closures.
```rust
// ✅ Good: Weak reference prevents retain cycle
impl MyComponent {
fn setup_callback(&mut self, cx: &mut Context<Self>) {
let weak_entity = cx.entity().downgrade(); // Weak reference
some_callback(move || {
// Safe: weak reference doesn't prevent cleanup
let _ = weak_entity.update(cx, |state, cx| {
cx.notify();
});
});
}
}
```
### Use Inner Context in Closures
**Problem:** Using outer context causes multiple borrow errors.
```rust
// ❌ Bad: Using outer cx causes borrow issues
entity.update(cx, |state, inner_cx| {
cx.notify(); // Wrong! Using outer cx
cx.spawn(...); // Multiple borrow error
});
```
**Solution:** Always use the inner context provided to the closure.
```rust
// ✅ Good: Use inner cx
entity.update(cx, |state, inner_cx| {
inner_cx.notify(); // Correct
inner_cx.spawn(...); // Works fine
});
```
### Entity as Props - Use Weak References
**Problem:** Strong entity references in props can create ownership issues.
```rust
// ❌ Questionable: Strong reference in child
struct ChildComponent {
parent: Entity<ParentComponent>, // Strong reference
}
```
**Better:** Use weak references for parent relationships.
```rust
// ✅ Good: Weak reference prevents issues
struct ChildComponent {
parent: WeakEntity<ParentComponent>, // Weak reference
}
impl ChildComponent {
fn notify_parent(&mut self, cx: &mut Context<Self>) {
// Check if parent still exists
if let Ok(_) = self.parent.update(cx, |parent_state, cx| {
// Update parent
cx.notify();
}) {
// Parent successfully updated
}
}
}
```
## Performance Optimization
### Minimize cx.notify() Calls
Each `cx.notify()` triggers a re-render. Batch updates when possible.
```rust
// ❌ Bad: Multiple notifications
impl MyComponent {
fn update_multiple_fields(&mut self, cx: &mut Context<Self>) {
self.field1 = new_value1;
cx.notify(); // Unnecessary intermediate notification
self.field2 = new_value2;
cx.notify(); // Unnecessary intermediate notification
self.field3 = new_value3;
cx.notify();
}
}
```
```rust
// ✅ Good: Single notification after all updates
impl MyComponent {
fn update_multiple_fields(&mut self, cx: &mut Context<Self>) {
self.field1 = new_value1;
self.field2 = new_value2;
self.field3 = new_value3;
cx.notify(); // Single notification
}
}
```
### Conditional Updates
Only notify when state actually changes.
```rust
impl MyComponent {
fn set_value(&mut self, new_value: i32, cx: &mut Context<Self>) {
if self.value != new_value {
self.value = new_value;
cx.notify(); // Only notify if changed
}
}
}
```
### Use read_with for Complex Operations
Prefer `read_with` over separate `read` calls.
```rust
// ❌ Less efficient: Multiple borrows
let state_ref = entity.read(cx);
let value1 = state_ref.field1;
let value2 = state_ref.field2;
// state_ref borrowed for entire scope
// ✅ More efficient: Single borrow with closure
let (value1, value2) = entity.read_with(cx, |state, cx| {
(state.field1, state.field2)
});
```
### Avoid Excessive Entity Creation
Creating entities has overhead. Reuse when appropriate.
```rust
// ❌ Bad: Creating entity per item in render
impl Render for MyList {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().children(
self.items.iter().map(|item| {
// Don't create entities in render!
let entity = cx.new(|_| item.clone());
ItemView { entity }
})
)
}
}
```
```rust
// ✅ Good: Create entities once, reuse
struct MyList {
item_entities: Vec<Entity<Item>>,
}
impl MyList {
fn add_item(&mut self, item: Item, cx: &mut Context<Self>) {
let entity = cx.new(|_| item);
self.item_entities.push(entity);
cx.notify();
}
}
```
## Entity Lifecycle Management
### Clean Up Weak References
Periodically clean up invalid weak references from collections.
```rust
struct Container {
weak_children: Vec<WeakEntity<Child>>,
}
impl Container {
fn cleanup_invalid_children(&mut self, cx: &mut Context<Self>) {
// Remove weak references that are no longer valid
let before_count = self.weak_children.len();
self.weak_children.retain(|weak| weak.upgrade().is_some());
let after_count = self.weak_children.len();
if before_count != after_count {
cx.notify(); // Notify if list changed
}
}
}
```
### Entity Cloning and Sharing
Understand that cloning `Entity<T>` increases reference count.
```rust
// Each clone increases the reference count
let entity1: Entity<MyState> = cx.new(|_| MyState::default());
let entity2 = entity1.clone(); // Reference count: 2
let entity3 = entity1.clone(); // Reference count: 3
// Entity is dropped only when all references are dropped
drop(entity1); // Reference count: 2
drop(entity2); // Reference count: 1
drop(entity3); // Reference count: 0, entity is deallocated
```
### Proper Resource Cleanup
Implement cleanup in `Drop` or explicit cleanup methods.
```rust
struct ManagedResource {
handle: Option<FileHandle>,
}
impl ManagedResource {
fn close(&mut self, cx: &mut Context<Self>) {
if let Some(handle) = self.handle.take() {
// Explicit cleanup
handle.close();
cx.notify();
}
}
}
impl Drop for ManagedResource {
fn drop(&mut self) {
// Automatic cleanup when entity is dropped
if let Some(handle) = self.handle.take() {
handle.close();
}
}
}
```
## Entity Observation Best Practices
### Detach Subscriptions Appropriately
Call `.detach()` on subscriptions you want to keep alive.
```rust
impl MyComponent {
fn new(other_entity: Entity<OtherComponent>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// Observer will live as long as both entities exist
cx.observe(&other_entity, |this, observed, cx| {
// Handle changes
cx.notify();
}).detach(); // Important: detach to make permanent
Self { /* fields */ }
})
}
}
```
### Avoid Observation Cycles
Don't create mutual observation between entities.
```rust
// ❌ Bad: Mutual observation can cause infinite loops
entity1.update(cx, |_, cx| {
cx.observe(&entity2, |_, _, cx| {
cx.notify(); // May trigger entity2's observer
}).detach();
});
entity2.update(cx, |_, cx| {
cx.observe(&entity1, |_, _, cx| {
cx.notify(); // May trigger entity1's observer → infinite loop
}).detach();
});
```
## Async Best Practices
### Always Use Weak References in Async Tasks
```rust
// ✅ Good: Weak reference in spawned task
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let weak_entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
let data = fetch_from_api().await;
// Entity may have been dropped during fetch
let _ = weak_entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
});
}).detach();
}
}
```
### Handle Async Errors Gracefully
```rust
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let weak_entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
match fetch_from_api().await {
Ok(data) => {
let _ = weak_entity.update(cx, |state, cx| {
state.data = Some(data);
state.error = None;
cx.notify();
});
}
Err(e) => {
let _ = weak_entity.update(cx, |state, cx| {
state.error = Some(e.to_string());
cx.notify();
});
}
}
}).detach();
}
}
```
### Cancellation Patterns
Implement cancellation for long-running tasks.
```rust
struct DataFetcher {
current_task: Option<Task<()>>,
data: Option<String>,
}
impl DataFetcher {
fn fetch_data(&mut self, url: String, cx: &mut Context<Self>) {
// Cancel previous task
self.current_task = None; // Dropping task cancels it
let weak_entity = cx.entity().downgrade();
let task = cx.spawn(async move |cx| {
let data = fetch_from_url(&url).await?;
let _ = weak_entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
});
Ok::<(), anyhow::Error>(())
});
self.current_task = Some(task);
}
}
```
## Testing Best Practices
### Use TestAppContext for Entity Tests
```rust
#[cfg(test)]
mod tests {
use super::*;
use gpui::TestAppContext;
#[gpui::test]
fn test_entity_update(cx: &mut TestAppContext) {
let entity = cx.new(|_| MyState { count: 0 });
entity.update(cx, |state, cx| {
state.count += 1;
assert_eq!(state.count, 1);
});
let count = entity.read(cx).count;
assert_eq!(count, 1);
}
}
```
### Test Entity Observation
```rust
#[gpui::test]
fn test_entity_observation(cx: &mut TestAppContext) {
let observed = cx.new(|_| MyState { value: 0 });
let observer = cx.new(|cx| Observer::new(observed.clone(), cx));
// Update observed entity
observed.update(cx, |state, cx| {
state.value = 42;
cx.notify();
});
// Verify observer was notified
observer.read(cx).assert_observed();
}
```
## Performance Checklist
Before shipping entity-based code, verify:
- [ ] No strong references in closures/callbacks (use `WeakEntity`)
- [ ] No nested entity updates (use sequential updates)
- [ ] Using inner `cx` in update closures
- [ ] Batching updates before calling `cx.notify()`
- [ ] Cleaning up invalid weak references periodically
- [ ] Using `read_with` for complex read operations
- [ ] Properly detaching subscriptions and observers
- [ ] Using weak references in async tasks
- [ ] No observation cycles between entities
- [ ] Proper error handling in async operations
- [ ] Resource cleanup in `Drop` or explicit methods
- [ ] Tests cover entity lifecycle and interactions
================================================
FILE: .claude/skills/gpui-entity/references/patterns.md
================================================
# Entity Patterns
Common patterns and use cases for entity management in GPUI.
## Application Scenarios
### Model-View Separation
Separate business logic (model) from UI (view) using entities.
```rust
struct CounterModel {
count: usize,
listeners: Vec<Box<dyn Fn(usize)>>,
}
struct CounterView {
model: Entity<CounterModel>,
}
impl CounterModel {
fn increment(&mut self, cx: &mut Context<Self>) {
self.count += 1;
// Notify listeners
for listener in &self.listeners {
listener(self.count);
}
cx.notify();
}
fn decrement(&mut self, cx: &mut Context<Self>) {
if self.count > 0 {
self.count -= 1;
cx.notify();
}
}
}
impl CounterView {
fn new(cx: &mut App) -> Entity<Self> {
let model = cx.new(|_cx| CounterModel {
count: 0,
listeners: Vec::new(),
});
cx.new(|cx| Self { model })
}
fn increment_count(&mut self, cx: &mut Context<Self>) {
self.model.update(cx, |model, cx| {
model.increment(cx);
});
}
}
impl Render for CounterView {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let count = self.model.read(cx).count;
div()
.child(format!("Count: {}", count))
.child(
Button::new("increment")
.label("Increment")
.on_click(cx.listener(|this, _, cx| {
this.increment_count(cx);
}))
)
}
}
```
### Component State Management
Managing complex component state with entities.
```rust
struct TodoList {
todos: Vec<Todo>,
filter: TodoFilter,
next_id: usize,
}
struct Todo {
id: usize,
text: String,
completed: bool,
}
enum TodoFilter {
All,
Active,
Completed,
}
impl TodoList {
fn new() -> Self {
Self {
todos: Vec::new(),
filter: TodoFilter::All,
next_id: 0,
}
}
fn add_todo(&mut self, text: String, cx: &mut Context<Self>) {
self.todos.push(Todo {
id: self.next_id,
text,
completed: false,
});
self.next_id += 1;
cx.notify();
}
fn toggle_todo(&mut self, id: usize, cx: &mut Context<Self>) {
if let Some(todo) = self.todos.iter_mut().find(|t| t.id == id) {
todo.completed = !todo.completed;
cx.notify();
}
}
fn remove_todo(&mut self, id: usize, cx: &mut Context<Self>) {
self.todos.retain(|t| t.id != id);
cx.notify();
}
fn set_filter(&mut self, filter: TodoFilter, cx: &mut Context<Self>) {
self.filter = filter;
cx.notify();
}
fn visible_todos(&self) -> impl Iterator<Item = &Todo> {
self.todos.iter().filter(move |todo| match self.filter {
TodoFilter::All => true,
TodoFilter::Active => !todo.completed,
TodoFilter::Completed => todo.completed,
})
}
}
```
### Cross-Entity Communication
Coordinating state between parent and child entities.
```rust
struct ParentComponent {
child_entities: Vec<Entity<ChildComponent>>,
global_message: String,
}
struct ChildComponent {
id: usize,
message: String,
parent: WeakEntity<ParentComponent>,
}
impl ParentComponent {
fn new(cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self {
child_entities: Vec::new(),
global_message: String::new(),
})
}
fn add_child(&mut self, cx: &mut Context<Self>) {
let parent_weak = cx.entity().downgrade();
let child_id = self.child_entities.len();
let child = cx.new(|cx| ChildComponent {
id: child_id,
message: String::new(),
parent: parent_weak,
});
self.child_entities.push(child);
cx.notify();
}
fn broadcast_message(&mut self, message: String, cx: &mut Context<Self>) {
self.global_message = message.clone();
// Update all children
for child in &self.child_entities {
child.update(cx, |child_state, cx| {
child_state.message = message.clone();
cx.notify();
});
}
cx.notify();
}
}
impl ChildComponent {
fn notify_parent(&mut self, message: String, cx: &mut Context<Self>) {
if let Ok(_) = self.parent.update(cx, |parent_state, cx| {
parent_state.global_message = format!("Child {}: {}", self.id, message);
cx.notify();
}) {
// Parent successfully notified
}
}
}
```
### Async Operations with Entities
Managing async state updates.
```rust
struct DataLoader {
loading: bool,
data: Option<String>,
error: Option<String>,
}
impl DataLoader {
fn new() -> Self {
Self {
loading: false,
data: None,
error: None,
}
}
fn load_data(&mut self, cx: &mut Context<Self>) {
// Set loading state
self.loading = true;
self.error = None;
cx.notify();
// Get weak reference for async task
let entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
// Simulate async operation
tokio::time::sleep(Duration::from_secs(2)).await;
let result = fetch_data().await;
// Update entity with result
let _ = entity.update(cx, |state, cx| {
state.loading = false;
match result {
Ok(data) => state.data = Some(data),
Err(e) => state.error = Some(e.to_string()),
}
cx.notify();
});
}).detach();
}
}
async fn fetch_data() -> Result<String, anyhow::Error> {
// Actual fetch implementation
Ok("Fetched data".to_string())
}
```
### Background Task Coordination
Using background tasks with entity updates.
```rust
struct ImageProcessor {
images: Vec<ProcessedImage>,
processing: bool,
}
struct ProcessedImage {
path: PathBuf,
thumbnail: Option<Vec<u8>>,
}
impl ImageProcessor {
fn process_images(&mut self, paths: Vec<PathBuf>, cx: &mut Context<Self>) {
self.processing = true;
cx.notify();
let entity = cx.entity().downgrade();
cx.background_spawn({
let paths = paths.clone();
async move {
let mut processed = Vec::new();
for path in paths {
// Process image on background thread
let thumbnail = generate_thumbnail(&path).await;
processed.push((path, thumbnail));
}
// Send results back to foreground
processed
}
})
.then(cx.spawn(move |processed, cx| {
// Update entity on foreground thread
let _ = entity.update(cx, |state, cx| {
for (path, thumbnail) in processed {
state.images.push(ProcessedImage {
path,
thumbnail: Some(thumbnail),
});
}
state.processing = false;
cx.notify();
});
}))
.detach();
}
}
```
## Common Patterns
### 1. Stateful Components
Use entities for components that maintain internal state.
```rust
struct StatefulComponent {
value: i32,
history: Vec<i32>,
}
impl StatefulComponent {
fn update_value(&mut self, new_value: i32, cx: &mut Context<Self>) {
self.history.push(self.value);
self.value = new_value;
cx.notify();
}
fn undo(&mut self, cx: &mut Context<Self>) {
if let Some(prev_value) = self.history.pop() {
self.value = prev_value;
cx.notify();
}
}
}
```
### 2. Shared State
Share state between multiple components using entities.
```rust
struct SharedState {
theme: Theme,
user: Option<User>,
}
struct ComponentA {
shared: Entity<SharedState>,
}
struct ComponentB {
shared: Entity<SharedState>,
}
// Both components can read/update the same shared state
impl ComponentA {
fn update_theme(&mut self, theme: Theme, cx: &mut Context<Self>) {
self.shared.update(cx, |state, cx| {
state.theme = theme;
cx.notify();
});
}
}
```
### 3. Event Coordination
Use entities to coordinate events between components.
```rust
struct EventCoordinator {
listeners: Vec<WeakEntity<dyn EventListener>>,
}
trait EventListener {
fn on_event(&mut self, event: &AppEvent, cx: &mut App);
}
impl EventCoordinator {
fn emit_event(&mut self, event: AppEvent, cx: &mut Context<Self>) {
// Notify all listeners
self.listeners.retain(|weak_listener| {
weak_listener.update(cx, |listener, cx| {
listener.on_event(&event, cx);
}).is_ok()
});
cx.notify();
}
}
```
### 4. Async State Management
Manage state that changes based on async operations.
```rust
struct AsyncState<T> {
state: AsyncValue<T>,
}
enum AsyncValue<T> {
Loading,
Loaded(T),
Error(String),
}
impl<T> AsyncState<T> {
fn is_loading(&self) -> bool {
matches!(self.state, AsyncValue::Loading)
}
fn value(&self) -> Option<&T> {
match &self.state {
AsyncValue::Loaded(v) => Some(v),
_ => None,
}
}
}
```
### 5. Parent-Child Relationships
Manage hierarchical relationships with weak references.
```rust
struct Parent {
children: Vec<Entity<Child>>,
}
struct Child {
parent: WeakEntity<Parent>,
data: String,
}
impl Child {
fn notify_parent_of_change(&mut self, cx: &mut Context<Self>) {
if let Ok(_) = self.parent.update(cx, |parent, cx| {
// Parent can react to child change
cx.notify();
}) {
// Successfully notified
}
}
}
```
### 6. Observer Pattern
React to entity state changes using observers.
```rust
struct Observable {
value: i32,
}
struct Observer {
observed: Entity<Observable>,
}
impl Observer {
fn new(observed: Entity<Observable>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// Observe the entity
cx.observe(&observed, |this, observed_entity, cx| {
// React to changes
let value = observed_entity.read(cx).value;
println!("Value changed to: {}", value);
}).detach();
Self { observed }
})
}
}
```
### 7. Event Subscription
Handle events emitted by other entities.
```rust
#[derive(Clone)]
enum DataEvent {
Updated,
Deleted,
}
struct DataSource {
data: Vec<String>,
}
impl DataSource {
fn update_data(&mut self, cx: &mut Context<Self>) {
// Update data
cx.emit(DataEvent::Updated);
cx.notify();
}
}
struct DataConsumer {
source: Entity<DataSource>,
}
impl DataConsumer {
fn new(source: Entity<DataSource>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// Subscribe to events
cx.subscribe(&source, |this, source, event: &DataEvent, cx| {
match event {
DataEvent::Updated => {
// Handle update
cx.notify();
}
DataEvent::Deleted => {
// Handle deletion
}
}
}).detach();
Self { source }
})
}
}
```
### 8. Resource Management
Manage external resources with proper cleanup.
```rust
struct FileHandle {
path: PathBuf,
file: Option<File>,
}
impl FileHandle {
fn open(&mut self, cx: &mut Context<Self>) -> Result<()> {
self.file = Some(File::open(&self.path)?);
cx.notify();
Ok(())
}
fn close(&mut self, cx: &mut Context<Self>) {
self.file = None;
cx.notify();
}
}
impl Drop for FileHandle {
fn drop(&mut self) {
// Cleanup when entity is dropped
if let Some(file) = self.file.take() {
drop(file);
}
}
}
```
## Pattern Selection Guide
| Need | Pattern | Complexity |
|------|---------|------------|
| Component with internal state | Stateful Components | Low |
| State shared by multiple components | Shared State | Low |
| Coordinate events between components | Event Coordination | Medium |
| Handle async data fetching | Async State Management | Medium |
| Parent-child component hierarchy | Parent-Child Relationships | Medium |
| React to state changes | Observer Pattern | Medium |
| Handle custom events | Event Subscription | Medium-High |
| Manage external resources | Resource Management | High |
Choose the simplest pattern that meets your requirements. Combine patterns as needed for complex scenarios.
================================================
FILE: .claude/skills/gpui-event/SKILL.md
================================================
---
name: gpui-event
description: Event handling and subscriptions in GPUI. Use when implementing events, observers, or event-driven patterns. Supports custom events, entity observations, and event subscriptions for coordinating between components.
---
## Overview
GPUI provides event system for component coordination:
**Event Mechanisms:**
- **Custom Events**: Define and emit type-safe events
- **Observations**: React to entity state changes
- **Subscriptions**: Listen to events from other entities
- **Global Events**: App-wide event handling
## Quick Start
### Define and Emit Events
```rust
#[derive(Clone)]
enum MyEvent {
DataUpdated(String),
ActionTriggered,
}
impl MyComponent {
fn update_data(&mut self, data: String, cx: &mut Context<Self>) {
self.data = data.clone();
// Emit event
cx.emit(MyEvent::DataUpdated(data));
cx.notify();
}
}
```
### Subscribe to Events
```rust
impl Listener {
fn new(source: Entity<MyComponent>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// Subscribe to events
cx.subscribe(&source, |this, emitter, event: &MyEvent, cx| {
match event {
MyEvent::DataUpdated(data) => {
this.handle_update(data.clone(), cx);
}
MyEvent::ActionTriggered => {
this.handle_action(cx);
}
}
}).detach();
Self { source }
})
}
}
```
### Observe Entity Changes
```rust
impl Observer {
fn new(target: Entity<Target>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
// Observe entity for any changes
cx.observe(&target, |this, observed, cx| {
// Called when observed.update() calls cx.notify()
println!("Target changed");
cx.notify();
}).detach();
Self { target }
})
}
}
```
## Common Patterns
### 1. Parent-Child Communication
```rust
// Parent emits events
impl Parent {
fn notify_children(&mut self, cx: &mut Context<Self>) {
cx.emit(ParentEvent::Updated);
cx.notify();
}
}
// Children subscribe
impl Child {
fn new(parent: Entity<Parent>, cx: &mut App) -> Entity<Self> {
cx.new(|cx| {
cx.subscribe(&parent, |this, parent, event, cx| {
this.handle_parent_event(event, cx);
}).detach();
Self { parent }
})
}
}
```
### 2. Global Event Broadcasting
```rust
struct EventBus {
listeners: Vec<WeakEntity<dyn Listener>>,
}
impl EventBus {
fn broadcast(&mut self, event: GlobalEvent, cx: &mut Context<Self>) {
self.listeners.retain(|weak| {
weak.update(cx, |listener, cx| {
listener.on_event(&event, cx);
}).is_ok()
});
}
}
```
### 3. Observer Pattern
```rust
cx.observe(&entity, |this, observed, cx| {
// React to any state change
let state = observed.read(cx);
this.sync_with_state(state, cx);
}).detach();
```
## Best Practices
### ✅ Detach Subscriptions
```rust
// ✅ Detach to keep alive
cx.subscribe(&entity, |this, source, event, cx| {
// Handle event
}).detach();
```
### ✅ Clean Event Types
```rust
#[derive(Clone)]
enum AppEvent {
DataChanged { id: usize, value: String },
ActionPerformed(ActionType),
Error(String),
}
```
### ❌ Avoid Event Loops
```rust
// ❌ Don't create mutual subscriptions
entity1.subscribe(entity2) → emits event
entity2.subscribe(entity1) → emits event → infinite loop!
```
## Reference Documentation
- **API Reference**: See [api-reference.md](references/api-reference.md)
- Event definition, emission, subscriptions
- Observations, global events
- Subscription lifecycle
- **Patterns**: See [patterns.md](references/patterns.md)
- Event-driven architectures
- Communication patterns
- Best practices and pitfalls
================================================
FILE: .claude/skills/gpui-focus-handle/SKILL.md
================================================
---
name: gpui-focus-handle
description: Focus management and keyboard navigation in GPUI. Use when handling focus, focus handles, or keyboard navigation. Enables keyboard-driven interfaces with proper focus tracking and navigation between focusable elements.
---
## Overview
GPUI's focus system enables keyboard navigation and focus management.
**Key Concepts:**
- **FocusHandle**: Reference to focusable element
- **Focus tracking**: Current focused element
- **Keyboard navigation**: Tab/Shift-Tab between elements
- **Focus events**: on_focus, on_blur
## Quick Start
### Creating Focus Handles
```rust
struct FocusableComponent {
focus_handle: FocusHandle,
}
impl FocusableComponent {
fn new(cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
}
}
}
```
### Making Elements Focusable
```rust
impl Render for FocusableComponent {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.track_focus(&self.focus_handle)
.on_action(cx.listener(Self::on_enter))
.child("Focusable content")
}
fn on_enter(&mut self, _: &Enter, cx: &mut Context<Self>) {
// Handle Enter key when focused
cx.notify();
}
}
```
### Focus Management
```rust
impl MyComponent {
fn focus(&mut self, cx: &mut Context<Self>) {
self.focus_handle.focus(cx);
}
fn is_focused(&self, cx: &App) -> bool {
self.focus_handle.is_focused(cx)
}
fn blur(&mut self, cx: &mut Context<Self>) {
cx.blur();
}
}
```
## Focus Events
### Handling Focus Changes
```rust
impl Render for MyInput {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let is_focused = self.focus_handle.is_focused(cx);
div()
.track_focus(&self.focus_handle)
.on_focus(cx.listener(|this, _event, cx| {
this.on_focus(cx);
}))
.on_blur(cx.listener(|this, _event, cx| {
this.on_blur(cx);
}))
.when(is_focused, |el| {
el.bg(cx.theme().focused_background)
})
.child(self.render_content())
}
}
impl MyInput {
fn on_focus(&mut self, cx: &mut Context<Self>) {
// Handle focus gained
cx.notify();
}
fn on_blur(&mut self, cx: &mut Context<Self>) {
// Handle focus lost
cx.notify();
}
}
```
## Keyboard Navigation
### Tab Order
Elements with `track_focus()` automatically participate in Tab navigation.
```rust
div()
.child(
input1.track_focus(&focus1) // Tab order: 1
)
.child(
input2.track_focus(&focus2) // Tab order: 2
)
.child(
input3.track_focus(&focus3) // Tab order: 3
)
```
### Focus Within Containers
```rust
impl Container {
fn focus_first(&mut self, cx: &mut Context<Self>) {
if let Some(first) = self.children.first() {
first.update(cx, |child, cx| {
child.focus_handle.focus(cx);
});
}
}
fn focus_next(&mut self, cx: &mut Context<Self>) {
// Custom focus navigation logic
}
}
```
## Common Patterns
### 1. Auto-focus on Mount
```rust
impl MyDialog {
fn new(cx: &mut Context<Self>) -> Self {
let focus_handle = cx.focus_handle();
// Focus when created
focus_handle.focus(cx);
Self { focus_handle }
}
}
```
### 2. Focus Trap (Modal)
```rust
impl Modal {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.track_focus(&self.focus_handle)
.on_key_down(cx.listener(|this, event: &KeyDownEvent, cx| {
if event.key == Key::Tab {
// Keep focus within modal
this.focus_next_in_modal(cx);
cx.stop_propagation();
}
}))
.child(self.render_content())
}
}
```
### 3. Conditional Focus
```rust
impl Searchable {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.track_focus(&self.focus_handle)
.when(self.search_active, |el| {
el.on_mount(cx.listener(|this, _, cx| {
this.focus_handle.focus(cx);
}))
})
.child(self.search_input())
}
}
```
## Best Practices
### ✅ Track Focus on Interactive Elements
```rust
// ✅ Good: Track focus for keyboard interaction
input()
.track_focus(&self.focus_handle)
.on_action(cx.listener(Self::on_enter))
```
### ✅ Provide Visual Focus Indicators
```rust
let is_focused = self.focus_handle.is_focused(cx);
div()
.when(is_focused, |el| {
el.border_color(cx.theme().focused_border)
})
```
### ❌ Don't: Forget to Track Focus
```rust
// ❌ Bad: No track_focus, keyboard navigation won't work
div()
.on_action(cx.listener(Self::on_enter))
```
## Reference Documentation
- **API Reference**: See [api-reference.md](references/api-reference.md)
- FocusHandle API, focus management
- Events, keyboard navigation
- Best practices
================================================
FILE: .claude/skills/gpui-global/SKILL.md
================================================
---
name: gpui-global
description: Global state management in GPUI. Use when implementing global state, app-wide configuration, or shared resources.
---
## Overview
Global state in GPUI provides app-wide shared data accessible from any context.
**Key Trait**: `Global` - Implement on types to make them globally accessible
## Quick Start
### Define Global State
```rust
use gpui::Global;
#[derive(Clone)]
struct AppSettings {
theme: Theme,
language: String,
}
impl Global for AppSettings {}
```
### Set and Access Globals
```rust
fn main() {
let app = Application::new();
app.run(|cx: &mut App| {
// Set global
cx.set_global(AppSettings {
theme: Theme::Dark,
language: "en".to_string(),
});
// Access global (read-only)
let settings = cx.global::<AppSettings>();
println!("Theme: {:?}", settings.theme);
});
}
```
### Update Globals
```rust
impl MyComponent {
fn change_theme(&mut self, new_theme: Theme, cx: &mut Context<Self>) {
cx.update_global::<AppSettings, _>(|settings, cx| {
settings.theme = new_theme;
// Global updates don't trigger automatic notifications
// Manually notify components that care
});
cx.notify(); // Re-render this component
}
}
```
## Common Use Cases
### 1. App Configuration
```rust
#[derive(Clone)]
struct AppConfig {
api_endpoint: String,
max_retries: u32,
timeout: Duration,
}
impl Global for AppConfig {}
// Set once at startup
cx.set_global(AppConfig {
api_endpoint: "https://api.example.com".to_string(),
max_retries: 3,
timeout: Duration::from_secs(30),
});
// Access anywhere
let config = cx.global::<AppConfig>();
```
### 2. Feature Flags
```rust
#[derive(Clone)]
struct FeatureFlags {
enable_beta_features: bool,
enable_analytics: bool,
}
impl Global for FeatureFlags {}
impl MyComponent {
fn render_beta_feature(&self, cx: &App) -> Option<impl IntoElement> {
let flags = cx.global::<FeatureFlags>();
if flags.enable_beta_features {
Some(div().child("Beta feature"))
} else {
None
}
}
}
```
### 3. Shared Services
```rust
#[derive(Clone)]
struct ServiceRegistry {
http_client: Arc<HttpClient>,
logger: Arc<Logger>,
}
impl Global for ServiceRegistry {}
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let registry = cx.global::<ServiceRegistry>();
let client = registry.http_client.clone();
cx.spawn(async move |cx| {
let data = client.get("api/data").await?;
// Process data...
Ok::<_, anyhow::Error>(())
}).detach();
}
}
```
## Best Practices
### ✅ Use Arc for Shared Resources
```rust
#[derive(Clone)]
struct GlobalState {
database: Arc<Database>, // Cheap to clone
cache: Arc<RwLock<Cache>>,
}
impl Global for GlobalState {}
```
### ✅ Immutable by Default
Globals are read-only by default. Use interior mutability when needed:
```rust
#[derive(Clone)]
struct Counter {
count: Arc<AtomicUsize>,
}
impl Global for Counter {}
impl Counter {
fn increment(&self) {
self.count.fetch_add(1, Ordering::SeqCst);
}
fn get(&self) -> usize {
self.count.load(Ordering::SeqCst)
}
}
```
### ❌ Don't: Overuse Globals
```rust
// ❌ Bad: Too many globals
cx.set_global(UserState { ... });
cx.set_global(CartState { ... });
cx.set_global(CheckoutState { ... });
// ✅ Good: Use entities for component state
let user_entity = cx.new(|_| UserState { ... });
```
## When to Use
**Use Globals for:**
- App-wide configuration
- Feature flags
- Shared services (HTTP client, logger)
- Read-only reference data
**Use Entities for:**
- Component-specific state
- State that changes frequently
- State that needs notifications
## Reference Documentation
- **API Reference**: See [api-reference.md](references/api-reference.md)
- Global trait, set_global, update_global
- Interior mutability patterns
- Best practices and anti-patterns
================================================
FILE: .claude/skills/gpui-layout-and-style/SKILL.md
================================================
---
name: gpui-layout-and-style
description: Layout and styling in GPUI. Use when styling components, layout systems, or CSS-like properties.
---
## Overview
GPUI provides CSS-like styling with Rust type safety.
**Key Concepts:**
- Flexbox layout system
- Styled trait for chaining styles
- Size units: `px()`, `rems()`, `relative()`
- Colors, borders, shadows
## Quick Start
### Basic Styling
```rust
use gpui::*;
div()
.w(px(200.))
.h(px(100.))
.bg(rgb(0x2196F3))
.text_color(rgb(0xFFFFFF))
.rounded(px(8.))
.p(px(16.))
.child("Styled content")
```
### Flexbox Layout
```rust
div()
.flex()
.flex_row() // or flex_col() for column
.gap(px(8.))
.items_center()
.justify_between()
.children([
div().child("Item 1"),
div().child("Item 2"),
div().child("Item 3"),
])
```
### Size Units
```rust
div()
.w(px(200.)) // Pixels
.h(rems(10.)) // Relative to font size
.w(relative(0.5)) // 50% of parent
.min_w(px(100.))
.max_w(px(400.))
```
## Common Patterns
### Centered Content
```rust
div()
.flex()
.items_center()
.justify_center()
.size_full()
.child("Centered")
```
### Card Layout
```rust
div()
.w(px(300.))
.bg(cx.theme().surface)
.rounded(px(8.))
.shadow_md()
.p(px(16.))
.gap(px(12.))
.flex()
.flex_col()
.child(heading())
.child(content())
```
### Responsive Spacing
```rust
div()
.p(px(16.)) // Padding all sides
.px(px(20.)) // Padding horizontal
.py(px(12.)) // Padding vertical
.pt(px(8.)) // Padding top
.gap(px(8.)) // Gap between children
```
## Styling Methods
### Dimensions
```rust
.w(px(200.)) // Width
.h(px(100.)) // Height
.size(px(200.)) // Width and height
.min_w(px(100.)) // Min width
.max_w(px(400.)) // Max width
```
### Colors
```rust
.bg(rgb(0x2196F3)) // Background
.text_color(rgb(0xFFFFFF)) // Text color
.border_color(rgb(0x000000)) // Border color
```
### Borders
```rust
.border(px(1.)) // Border width
.rounded(px(8.)) // Border radius
.rounded_t(px(8.)) // Top corners
.border_color(rgb(0x000000))
```
### Spacing
```rust
.p(px(16.)) // Padding
.m(px(8.)) // Margin
.gap(px(8.)) // Gap between flex children
```
### Flexbox
```rust
.flex() // Enable flexbox
.flex_row() // Row direction
.flex_col() // Column direction
.items_center() // Align items center
.justify_between() // Space between items
.flex_grow() // Grow to fill space
```
## Theme Integration
```rust
div()
.bg(cx.theme().surface)
.text_color(cx.theme().foreground)
.border_color(cx.theme().border)
.when(is_hovered, |el| {
el.bg(cx.theme().hover)
})
```
## Conditional Styling
```rust
div()
.when(is_active, |el| {
el.bg(cx.theme().primary)
})
.when_some(optional_color, |el, color| {
el.bg(color)
})
```
## Reference Documentation
- **Complete Guide**: See [reference.md](references/reference.md)
- All styling methods
- Layout strategies
- Theming, responsive design
================================================
FILE: .claude/skills/gpui-style-guide/SKILL.md
================================================
---
name: gpui-style-guide
description: GPUI Component project style guide based on gpui-component code patterns. Use when writing new components, reviewing code, or ensuring consistency with existing gpui-component implementations. Covers component structure, trait implementations, naming conventions, and API patterns observed in the actual codebase.
---
## Overview
Code style guide derived from gpui-component implementation patterns.
**Based on**: Analysis of Button, Checkbox, Input, Select, and other components in crates/ui
## Component Structure
### Basic Component Pattern
```rust
use gpui::{
div, prelude::FluentBuilder as _, AnyElement, App, Div, ElementId,
InteractiveElement, IntoElement, ParentElement, RenderOnce,
StatefulInteractiveElement, StyleRefinement, Styled, Window,
};
#[derive(IntoElement)]
pub struct MyComponent {
id: ElementId,
base: Div,
style: StyleRefinement,
// Configuration fields
size: Size,
disabled: bool,
selected: bool,
// Content fields
label: Option<Text>,
children: Vec<AnyElement>,
// Callbacks (use Rc for Clone)
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
}
impl MyComponent {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
id: id.into(),
base: div(),
style: StyleRefinement::default(),
size: Size::default(),
disabled: false,
selected: false,
label: None,
children: Vec::new(),
on_click: None,
}
}
// Builder methods
pub fn label(mut self, label: impl Into<Text>) -> Self {
self.label = Some(label.into());
self
}
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_click = Some(Rc::new(handler));
self
}
}
impl InteractiveElement for MyComponent {
fn interactivity(&mut self) -> &mut gpui::Interactivity {
self.base.interactivity()
}
}
impl StatefulInteractiveElement for MyComponent {}
impl Styled for MyComponent {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl RenderOnce for MyComponent {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
// Implementation
self.base
}
}
```
### Stateful Component Pattern
```rust
#[derive(IntoElement)]
pub struct Select {
state: Entity<SelectState>,
style: StyleRefinement,
size: Size,
// ...
}
pub struct SelectState {
open: bool,
selected_index: Option<usize>,
// ...
}
impl Select {
pub fn new(state: &Entity<SelectState>) -> Self {
Self {
state: state.clone(),
size: Size::default(),
style: StyleRefinement::default(),
}
}
}
```
## Trait Implementations
### Sizable
```rust
impl Sizable for MyComponent {
fn with_size(mut self, size: impl Into<Size>) -> Self {
self.size = size.into();
self
}
}
```
### Selectable
```rust
impl Selectable for MyComponent {
fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
fn is_selected(&self) -> bool {
self.selected
}
}
```
### Disableable
```rust
impl Disableable for MyComponent {
fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
fn is_disabled(&self) -> bool {
self.disabled
}
}
```
## Variant Patterns
### Enum Variants
```rust
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
pub enum ButtonVariant {
Primary,
#[default]
Secondary,
Danger,
Success,
Warning,
Ghost,
Link,
}
```
### Trait-Based Variant API
```rust
pub trait ButtonVariants: Sized {
fn with_variant(self, variant: ButtonVariant) -> Self;
/// With the primary style for the Button.
fn primary(self) -> Self {
self.with_variant(ButtonVariant::Primary)
}
/// With the danger style for the Button.
fn danger(self) -> Self {
self.with_variant(ButtonVariant::Danger)
}
// ... more variants
}
```
### Custom Variant Pattern
```rust
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ButtonCustomVariant {
color: Hsla,
foreground: Hsla,
border: Hsla,
hover: Hsla,
active: Hsla,
shadow: bool,
}
impl ButtonCustomVariant {
pub fn new(cx: &App) -> Self {
Self {
color: cx.theme().transparent,
foreground: cx.theme().foreground,
// ...
shadow: false,
}
}
pub fn color(mut self, color: Hsla) -> Self {
self.color = color;
self
}
// ... more builder methods
}
```
## Action and Keybinding Patterns
### Context Constant
```rust
const CONTEXT: &str = "Select";
```
### Init Function
```rust
pub(crate) fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("up", SelectUp, Some(CONTEXT)),
KeyBinding::new("down", SelectDown, Some(CONTEXT)),
KeyBinding::new("enter", Confirm { secondary: false }, Some(CONTEXT)),
KeyBinding::new("escape", Cancel, Some(CONTEXT)),
])
}
```
### Action Usage
```rust
use crate::actions::{Cancel, Confirm, SelectDown, SelectUp};
div()
.key_context(CONTEXT)
.on_action(cx.listener(Self::on_action_select_up))
.on_action(cx.listener(Self::on_action_confirm))
```
## Trait Definitions
### Item Traits
```rust
pub trait SelectItem: Clone {
type Value: Clone;
fn title(&self) -> SharedString;
fn display_title(&self) -> Option<AnyElement> {
None
}
fn render(&self, _: &mut Window, _: &mut App) -> impl IntoElement {
self.title().into_element()
}
fn value(&self) -> &Self::Value;
fn matches(&self, query: &str) -> bool {
self.title().to_lowercase().contains(&query.to_lowercase())
}
}
```
### Implement for Common Types
```rust
impl SelectItem for String {
type Value = Self;
fn title(&self) -> SharedString {
SharedString::from(self.to_string())
}
fn value(&self) -> &Self::Value {
&self
}
}
impl SelectItem for SharedString { /* ... */ }
impl SelectItem for &'static str { /* ... */ }
```
## Icon Pattern
### IconNamed Trait
```rust
pub trait IconNamed {
fn path(self) -> SharedString;
}
impl<T: IconNamed> From<T> for Icon {
fn from(value: T) -> Self {
Icon::build(value)
}
}
```
### IconName Enum
```rust
#[derive(IntoElement, Clone)]
pub enum IconName {
ArrowDown,
ArrowUp,
Check,
Close,
// ... all icon names
}
```
## Documentation Patterns
### Component Documentation
```rust
/// A Checkbox element.
#[derive(IntoElement)]
pub struct Checkbox { }
```
### Method Documentation
```rust
impl Checkbox {
/// Create a new Checkbox with the given id.
pub fn new(id: impl Into<ElementId>) -> Self { }
/// Set the label for the checkbox.
pub fn label(mut self, label: impl Into<Text>) -> Self { }
/// Set the click handler for the checkbox.
///
/// The `&bool` parameter indicates the new checked state after the click.
pub fn on_click(mut self, handler: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self { }
}
```
## Import Organization Pattern
```rust
// 1. External crate imports
use std::rc::Rc;
// 2. Crate imports
use crate::{
ActiveTheme, Disableable, FocusableExt, Icon, IconName,
Selectable, Sizable, Size, StyledExt,
};
// 3. GPUI imports
use gpui::{
div, prelude::FluentBuilder as _, px, relative, rems,
AnyElement, App, Div, ElementId, InteractiveElement,
IntoElement, ParentElement, RenderOnce,
StatefulInteractiveElement, StyleRefinement, Styled, Window,
};
```
## Field Organization
```rust
pub struct Component {
// 1. Identity
id: ElementId,
base: Div,
style: StyleRefinement,
// 2. Configuration
size: Size,
disabled: bool,
selected: bool,
tab_stop: bool,
tab_index: isize,
// 3. Content/children
label: Option<Text>,
children: Vec<AnyElement>,
prefix: Option<AnyElement>,
suffix: Option<AnyElement>,
// 4. Callbacks (last)
on_click: Option<Rc<dyn Fn(Args, &mut Window, &mut App) + 'static>>,
}
```
## Common Patterns
### Optional Elements
```rust
pub fn prefix(mut self, prefix: impl IntoElement) -> Self {
self.prefix = Some(prefix.into_any_element());
self
}
```
### Callback Patterns
```rust
// Pattern 1: Event parameter first
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_click = Some(Rc::new(handler));
self
}
// Pattern 2: State parameter
pub fn on_change(mut self, handler: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self {
self.on_change = Some(Rc::new(handler));
self
}
```
### Static Handler Functions
```rust
fn handle_click(
on_click: &Option<Rc<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
checked: bool,
window: &mut Window,
cx: &mut App,
) {
let new_checked = !checked;
if let Some(f) = on_click {
(f)(&new_checked, window, cx);
}
}
```
### Boolean Methods
```rust
// Enable/disable patterns
pub fn cleanable(mut self, cleanable: bool) -> Self {
self.cleanable = cleanable;
self
}
// Toggle methods (no parameter)
pub fn mask_toggle(mut self) -> Self {
self.mask_toggle = true;
self
}
```
## Size Methods
### Size Trait
```rust
impl Sizable for Component {
fn with_size(mut self, size: impl Into<Size>) -> Self {
self.size = size.into();
self
}
}
```
### Convenience Size Methods (from StyleSized trait)
Components get `.xsmall()`, `.small()`, `.medium()`, `.large()` automatically via `StyleSized` trait.
## Rendering Patterns
### RenderOnce Pattern
```rust
impl RenderOnce for MyComponent {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let (width, height) = self.size.input_size();
self.base
.id(self.id)
.flex()
.items_center()
.gap(px(8.))
.min_w(width)
.h(height)
.when(self.disabled, |this| {
this.opacity(0.5).cursor_not_allowed()
})
.children(self.children)
}
}
```
## Theme Usage
```rust
// Access theme colors
cx.theme().surface
cx.theme().foreground
cx.theme().border
cx.theme().primary
cx.theme().transparent
// Use in components
div()
.bg(cx.theme().surface)
.text_color(cx.theme().foreground)
.border_color(cx.theme().border)
```
## Reference Documentation
- **Component Examples**: See [component-examples.md](references/component-examples.md)
- Full component implementations
- Common patterns in action
- **Trait Patterns**: See [trait-patterns.md](references/trait-patterns.md)
- Detailed trait implementation guides
- Custom trait design patterns
## Quick Checklist
When creating a new component in crates/ui:
- [ ] `#[derive(IntoElement)]` on struct
- [ ] Include `id: ElementId`, `base: Div`, `style: StyleRefinement`
- [ ] Implement `InteractiveElement`, `StatefulInteractiveElement`, `Styled`
- [ ] Implement `RenderOnce` trait
- [ ] Implement `Sizable` if component has sizes
- [ ] Implement `Selectable` if component can be selected
- [ ] Implement `Disableable` if component can be disabled
- [ ] Use `Rc<dyn Fn>` for callbacks
- [ ] Use `Option<AnyElement>` for optional child elements
- [ ] Import `prelude::FluentBuilder as _`
- [ ] Use theme colors via `cx.theme()`
- [ ] Follow field organization pattern
================================================
FILE: .claude/skills/gpui-test/SKILL.md
================================================
---
name: gpui-test
description: Writing tests for GPUI applications. Use when testing components, async operations, or UI behavior.
---
## Overview
GPUI provides a comprehensive testing framework that allows you to test UI components, async operations, and distributed systems. Tests run on a single-threaded executor that provides deterministic execution and the ability to test complex async scenarios. GPUI tests use the `#[gpui::test]` attribute and work with `TestAppContext` for basic testing and `VisualTestContext` for window-dependent tests.
### Rules
- If test does not require windows or rendering, we can avoid use `[gpui::test]` and `TestAppContext`, just write simple rust test.
## Core Testing Infrastructure
### Test Attributes
#### Basic Test
```rust
#[gpui::test]
fn my_test(cx: &mut TestAppContext) {
// Test implementation
}
```
#### Async Test
```rust
#[gpui::test]
async fn my_async_test(cx: &mut TestAppContext) {
// Async test implementation
}
```
#### Property Test with Iterations
```rust
#[gpui::test(iterations = 10)]
fn my_property_test(cx: &mut TestAppContext, mut rng: StdRng) {
// Property testing with random data
}
```
### Test Contexts
#### TestAppContext
`TestAppContext` provides access to GPUI's core functionality without windows:
```rust
#[gpui::test]
fn test_entity_operations(cx: &mut TestAppContext) {
// Create entities
let entity = cx.new(|cx| MyComponent::new(cx));
// Update entities
entity.update(cx, |component, cx| {
component.value = 42;
cx.notify();
});
// Read entities
let value = entity.read_with(cx, |component, _| component.value);
assert_eq!(value, 42);
}
```
#### VisualTestContext
`VisualTestContext` extends `TestAppContext` with window support:
```rust
#[gpui::test]
fn test_with_window(cx: &mut TestAppContext) {
// Create window with component
let window = cx.update(|cx| {
cx.open_window(Default::default(), |_, cx| {
cx.new(|cx| MyComponent::new(cx))
}).unwrap()
});
// Convert to visual context
let mut cx = VisualTestContext::from_window(window.into(), cx);
// Access window and component
let component = window.root(&mut cx).unwrap();
}
```
## Additional Resources
- For detailed testing patterns and examples, see [reference.md](reference.md)
- For best practices and running tests, see [examples.md](examples.md)
================================================
FILE: .claude/skills/gpui-test/examples.md
================================================
## Testing Best Practices
### Test Organization
Group related tests in modules:
```rust
#[cfg(test)]
mod tests {
use super::*;
mod entity_tests {
use super::*;
#[gpui::test]
fn test_creation() { /* ... */ }
#[gpui::test]
fn test_updates() { /* ... */ }
}
mod async_tests {
use super::*;
#[gpui::test]
async fn test_async_ops() { /* ... */ }
}
mod distributed_tests {
use super::*;
#[gpui::test]
fn test_multi_app() { /* ... */ }
}
}
```
### Setup and Teardown
Use helper functions for common setup:
```rust
fn create_test_counter(cx: &mut TestAppContext) -> Entity<Counter> {
cx.new(|cx| Counter::new(cx))
}
#[gpui::test]
fn test_counter_operations(cx: &mut TestAppContext) {
let counter = create_test_counter(cx);
// Test operations
}
```
### Assertions
Use descriptive assertions:
```rust
#[gpui::test]
fn test_counter_bounds(cx: &mut TestAppContext) {
let counter = create_test_counter(cx);
// Test upper bound
for _ in 0..100 {
counter.update(cx, |counter, cx| {
counter.increment(cx);
});
}
let count = counter.read_with(cx, |counter, _| counter.count);
assert!(count <= 100, "Counter should not exceed maximum");
// Test lower bound
for _ in 0..200 {
counter.update(cx, |counter, cx| {
counter.decrement(cx);
});
}
let count = counter.read_with(cx, |counter, _| counter.count);
assert!(count >= 0, "Counter should not go below minimum");
}
```
### Performance Testing
Test performance characteristics:
```rust
#[gpui::test]
fn test_operation_performance(cx: &mut TestAppContext) {
let component = cx.new(|cx| MyComponent::new(cx));
let start = std::time::Instant::now();
// Perform many operations
for i in 0..1000 {
component.update(cx, |comp, cx| {
comp.perform_operation(i, cx);
});
}
let elapsed = start.elapsed();
assert!(elapsed < Duration::from_millis(100), "Operations should complete quickly");
}
```
## Running Tests
### Basic Test Execution
```bash
# Run all tests
cargo test
# Run specific test
cargo test test_counter_operations
# Run tests in a specific module
cargo test entity_tests::
# Run with output
cargo test -- --nocapture
```
### Test Configuration
Enable test-support feature for GPUI tests:
```toml
[features]
test-support = ["gpui/test-support"]
```
```bash
cargo test --features test-support
```
### Advanced Test Execution
```bash
# Run tests with iterations for property testing
cargo test -- --test-threads=1
# Run tests matching a pattern
cargo test test_async
# Run tests with backtrace on failure
RUST_BACKTRACE=1 cargo test
```
### CI/CD Integration
For continuous integration:
```yaml
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- name: Run tests
run: cargo test --features test-support
```
GPUI's testing framework provides deterministic, fast, and comprehensive testing capabilities that mirror real application behavior while providing the control needed for thorough testing of complex UI and async scenarios.
================================================
FILE: .claude/skills/gpui-test/reference.md
================================================
## Testing Patterns
### Basic Entity Testing
Test entity creation, updates, and reads:
```rust
#[gpui::test]
fn test_counter_entity(cx: &mut TestAppContext) {
let counter = cx.new(|cx| Counter::new(cx));
// Test initial state
let initial_count = counter.read_with(cx, |counter, _| counter.count);
assert_eq!(initial_count, 0);
// Test updates
counter.update(cx, |counter, cx| {
counter.count = 42;
cx.notify();
});
let updated_count = counter.read_with(cx, |counter, _| counter.count);
assert_eq!(updated_count, 42);
}
```
### Event Testing
Test event emission and handling:
```rust
#[derive(Clone)]
struct ValueChanged {
new_value: i32,
}
impl EventEmitter<ValueChanged> for MyComponent {}
#[gpui::test]
fn test_event_emission(cx: &mut TestAppContext) {
let component = cx.new(|cx| {
let mut comp = MyComponent::default();
// Subscribe to self
cx.subscribe_self(|this, event: &ValueChanged, cx| {
this.received_value = event.new_value;
cx.notify();
});
comp
});
// Emit event
component.update(cx, |_, cx| {
cx.emit(ValueChanged { new_value: 123 });
});
// Verify event was handled
let received = component.read_with(cx, |comp, _| comp.received_value);
assert_eq!(received, 123);
}
```
### Action Testing
Test action dispatching and handling:
```rust
actions!(my_app, [Increment, Decrement]);
#[gpui::test]
fn test_action_dispatch(cx: &mut TestAppContext) {
let window = cx.update(|cx| {
cx.open_window(Default::default(), |_, cx| {
cx.new(|cx| MyComponent::new(cx))
}).unwrap()
});
let mut cx = VisualTestContext::from_window(window.into(), cx);
let counter = window.root(&mut cx).unwrap();
// Dispatch action via focus handle
let focus_handle = counter.read_with(&cx, |counter, _| counter.focus_handle.clone());
cx.update(|window, cx| {
focus_handle.dispatch_action(&Increment, window, cx);
});
let count = counter.read_with(&cx, |counter, _| counter.count);
assert_eq!(count, 1);
}
```
### Async Testing
Test async operations and background tasks:
```rust
impl MyComponent {
fn load_data(&self, cx: &mut Context<Self>) -> Task<i32> {
cx.spawn(async move |this, cx| {
// Simulate async work
this.update(cx, |comp, _| comp.loading = true).await;
// Return result
42
})
}
fn background_update(&self, cx: &mut Context<Self>) {
cx.spawn(async move |this, cx| {
// Background work
this.update(cx, |comp, _| {
comp.value += 10;
}).await;
}).detach();
}
}
#[gpui::test]
async fn test_async_operations(cx: &mut TestAppContext) {
let component = cx.new(|cx| MyComponent::new(cx));
// Test awaited task
let result = component.update(cx, |comp, cx| comp.load_data(cx)).await;
assert_eq!(result, 42);
// Test detached task
component.update(cx, |comp, cx| comp.background_update(cx));
// Detached tasks don't run until you yield
let value_before = component.read_with(cx, |comp, _| comp.value);
assert_eq!(value_before, 0);
// Run pending tasks
cx.run_until_parked();
let value_after = component.read_with(cx, |comp, _| comp.value);
assert_eq!(value_after, 10);
}
```
### Timer Testing
Test timer-based operations:
```rust
impl MyComponent {
fn delayed_action(&self, cx: &mut Context<Self>) {
cx.spawn(async move |this, cx| {
cx.background_executor()
.timer(Duration::from_millis(100))
.await;
this.update(cx, |comp, cx| {
comp.action_performed = true;
cx.notify();
}).await;
}).detach();
}
}
#[gpui::test]
async fn test_timers(cx: &mut TestAppContext) {
let component = cx.new(|cx| MyComponent::new(cx));
component.update(cx, |comp, cx| comp.delayed_action(cx));
// Action shouldn't have completed yet
let performed = component.read_with(cx, |comp, _| comp.action_performed);
assert!(!performed);
// Run until parked (timers complete)
cx.run_until_parked();
let performed = component.read_with(cx, |comp, _| comp.action_performed);
assert!(performed);
}
```
### External I/O Testing
For tests involving external systems, use `allow_parking()`:
```rust
#[gpui::test]
async fn test_external_io(cx: &mut TestAppContext) {
// Allow parking for external I/O
cx.executor().allow_parking();
// Simulate external operation
let (tx, rx) = futures::channel::oneshot::channel();
std::thread::spawn(move || {
std::thread::sleep(Duration::from_millis(10));
tx.send(42).ok();
});
let result = rx.await.unwrap();
assert_eq!(result, 42);
}
```
## Property Testing
Use random data to test edge cases:
```rust
#[gpui::test(iterations = 10)]
fn test_counter_random_operations(cx: &mut TestAppContext, mut rng: StdRng) {
let counter = cx.new(|cx| Counter::new(cx));
let mut expected = 0i32;
for _ in 0..100 {
let delta = rng.random_range(-10..=10);
expected += delta;
counter.update(cx, |counter, cx| {
counter.count += delta;
cx.notify();
});
}
let actual = counter.read_with(cx, |counter, _| counter.count);
assert_eq!(actual, expected);
}
```
## Distributed Systems Testing
Test multiple app contexts communicating:
```rust
#[derive(Clone)]
struct NetworkMessage {
from: String,
to: String,
data: i32,
}
#[gpui::test]
fn test_distributed_apps(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
// Create components in different app contexts
let comp_a = cx_a.new(|_| MyComponent::new("A".to_string()));
let comp_b = cx_b.new(|_| MyComponent::new("B".to_string()));
// Simulate message passing
comp_a.update(cx_a, |comp, cx| {
comp.send_message("B", 42, cx);
});
// Run async operations
cx_a.run_until_parked();
// Verify message received in other context
comp_b.update(cx_b, |comp, _| {
comp.receive_messages();
});
let messages = comp_b.read_with(cx_b, |comp, _| comp.messages.clone());
assert_eq!(messages.len(), 1);
assert_eq!(messages[0].data, 42);
}
```
### Interleaving Testing
Test concurrent operations with random execution order:
```rust
#[gpui::test(iterations = 10)]
fn test_concurrent_operations(
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
mut rng: StdRng,
) {
let comp_a = cx_a.new(|_| MyComponent::new());
let comp_b = cx_b.new(|_| MyComponent::new());
// Perform random operations across contexts
for i in 0..20 {
if rng.random_bool(0.5) {
comp_a.update(cx_a, |comp, cx| {
comp.perform_operation(i, cx);
});
} else {
comp_b.update(cx_b, |comp, cx| {
comp.perform_operation(i, cx);
});
}
}
// Run all pending operations
cx_a.run_until_parked();
// Verify final state
let state_a = comp_a.read_with(cx_a, |comp, _| comp.state);
let state_b = comp_b.read_with(cx_b, |comp, _| comp.state);
// Assert invariants hold despite execution order
assert!(state_a.is_consistent());
assert!(state_b.is_consistent());
}
```
## Mocking and Isolation
### Network Mocking
Create mock networks for testing distributed features:
```rust
struct MockNetwork {
messages: Arc<Mutex<Vec<NetworkMessage>>>,
}
impl MockNetwork {
fn new() -> Self {
Self {
messages: Arc::new(Mutex::new(Vec::new())),
}
}
fn send(&self, message: NetworkMessage) {
self.messages.lock().unwrap().push(message);
}
fn receive_all(&self) -> Vec<NetworkMessage> {
self.messages.lock().unwrap().drain(..).collect()
}
}
#[gpui::test]
fn test_networked_components(cx: &mut TestAppContext) {
let network = Arc::new(MockNetwork::new());
let sender = cx.new(|_| MessageSender::new(network.clone()));
let receiver = cx.new(|_| MessageReceiver::new(network));
// Send message
sender.update(cx, |sender, _| {
sender.send("Hello");
});
// Receive message
receiver.update(cx, |r
gitextract_xlkzxety/
├── .cargo/
│ └── config.toml
├── .claude/
│ ├── COMPONENT_TEST_RULES.md
│ └── skills/
│ ├── generate-component-documentation/
│ │ └── SKILL.md
│ ├── generate-component-story/
│ │ └── SKILL.md
│ ├── github-pull-request-description/
│ │ └── SKILL.md
│ ├── gpui-action/
│ │ └── SKILL.md
│ ├── gpui-async/
│ │ └── SKILL.md
│ ├── gpui-context/
│ │ └── SKILL.md
│ ├── gpui-element/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced-patterns.md
│ │ ├── api-reference.md
│ │ ├── best-practices.md
│ │ ├── examples.md
│ │ └── patterns.md
│ ├── gpui-entity/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced.md
│ │ ├── api-reference.md
│ │ ├── best-practices.md
│ │ └── patterns.md
│ ├── gpui-event/
│ │ └── SKILL.md
│ ├── gpui-focus-handle/
│ │ └── SKILL.md
│ ├── gpui-global/
│ │ └── SKILL.md
│ ├── gpui-layout-and-style/
│ │ └── SKILL.md
│ ├── gpui-style-guide/
│ │ └── SKILL.md
│ ├── gpui-test/
│ │ ├── SKILL.md
│ │ ├── examples.md
│ │ └── reference.md
│ └── new-component/
│ └── SKILL.md
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── 01_bug.md
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── ci.yml
│ ├── release-docs.yml
│ ├── release.yml
│ └── test-docs.yml
├── .gitignore
├── .rustfmt.toml
├── .theme-schema.json
├── CLAUDE.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── Makefile
├── README.md
├── crates/
│ ├── assets/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── assets/
│ │ │ └── .gitkeep
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── native_assets.rs
│ │ └── wasm_assets.rs
│ ├── macros/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── derive_into_plot.rs
│ │ └── lib.rs
│ ├── story/
│ │ ├── Cargo.toml
│ │ ├── examples/
│ │ │ ├── brush.rs
│ │ │ ├── dock.rs
│ │ │ ├── editor.rs
│ │ │ ├── fixtures/
│ │ │ │ ├── completion_items.json
│ │ │ │ ├── test.astro
│ │ │ │ ├── test.c
│ │ │ │ ├── test.go
│ │ │ │ ├── test.html
│ │ │ │ ├── test.js
│ │ │ │ ├── test.json
│ │ │ │ ├── test.kt
│ │ │ │ ├── test.lua
│ │ │ │ ├── test.md
│ │ │ │ ├── test.nv
│ │ │ │ ├── test.php
│ │ │ │ ├── test.py
│ │ │ │ ├── test.rb
│ │ │ │ ├── test.rs
│ │ │ │ ├── test.sql
│ │ │ │ ├── test.svelte
│ │ │ │ ├── test.ts
│ │ │ │ └── test.zig
│ │ │ ├── html.rs
│ │ │ ├── large-text.rs
│ │ │ ├── markdown.rs
│ │ │ ├── stream_markdown.rs
│ │ │ └── tiles.rs
│ │ └── src/
│ │ ├── app_menus.rs
│ │ ├── embedded_themes.rs
│ │ ├── fixtures/
│ │ │ ├── counters.json
│ │ │ ├── countries.json
│ │ │ ├── daily-devices.json
│ │ │ ├── monthly-devices.json
│ │ │ └── stock-prices.json
│ │ ├── gallery.rs
│ │ ├── lib.rs
│ │ ├── main.rs
│ │ ├── stories/
│ │ │ ├── accordion_story.rs
│ │ │ ├── alert_dialog_story.rs
│ │ │ ├── alert_story.rs
│ │ │ ├── avatar_story.rs
│ │ │ ├── badge_story.rs
│ │ │ ├── breadcrumb_story.rs
│ │ │ ├── button_story.rs
│ │ │ ├── calendar_story.rs
│ │ │ ├── chart_story/
│ │ │ │ ├── chart_story.rs
│ │ │ │ └── stacked_bar_chart.rs
│ │ │ ├── chart_story.rs
│ │ │ ├── checkbox_story.rs
│ │ │ ├── clipboard_story.rs
│ │ │ ├── collapsible_story.rs
│ │ │ ├── color_picker_story.rs
│ │ │ ├── data_table_story.rs
│ │ │ ├── date_picker_story.rs
│ │ │ ├── description_list_story.rs
│ │ │ ├── dialog_story.rs
│ │ │ ├── divider_story.rs
│ │ │ ├── dropdown_button_story.rs
│ │ │ ├── editor_story.rs
│ │ │ ├── form_story.rs
│ │ │ ├── group_box_story.rs
│ │ │ ├── hover_card_story.rs
│ │ │ ├── icon_story.rs
│ │ │ ├── image_story.rs
│ │ │ ├── input_story.rs
│ │ │ ├── kbd_story.rs
│ │ │ ├── label_story.rs
│ │ │ ├── list_story.rs
│ │ │ ├── menu_story.rs
│ │ │ ├── mod.rs
│ │ │ ├── notification_story.rs
│ │ │ ├── number_input_story.rs
│ │ │ ├── otp_input_story.rs
│ │ │ ├── pagination_story.rs
│ │ │ ├── popover_story.rs
│ │ │ ├── progress_story.rs
│ │ │ ├── radio_story.rs
│ │ │ ├── rating_story.rs
│ │ │ ├── resizable_story.rs
│ │ │ ├── scrollbar_story.rs
│ │ │ ├── select_story.rs
│ │ │ ├── settings_story.rs
│ │ │ ├── sheet_story.rs
│ │ │ ├── sidebar_story.rs
│ │ │ ├── skeleton_story.rs
│ │ │ ├── slider_story.rs
│ │ │ ├── spinner_story.rs
│ │ │ ├── stepper_story.rs
│ │ │ ├── switch_story.rs
│ │ │ ├── table_story.rs
│ │ │ ├── tabs_story.rs
│ │ │ ├── tag_story.rs
│ │ │ ├── textarea_story.rs
│ │ │ ├── theme_story/
│ │ │ │ ├── checkerboard.rs
│ │ │ │ ├── color_theme_story.rs
│ │ │ │ ├── mapper.rs
│ │ │ │ └── mod.rs
│ │ │ ├── toggle_story.rs
│ │ │ ├── tooltip_story.rs
│ │ │ ├── tree_story.rs
│ │ │ ├── virtual_list_story.rs
│ │ │ └── welcome_story.rs
│ │ ├── themes.rs
│ │ └── title_bar.rs
│ ├── story-web/
│ │ ├── .cargo/
│ │ │ └── config.toml
│ │ ├── Cargo.toml
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── rust-toolchain.toml
│ │ ├── scripts/
│ │ │ └── build-wasm.sh
│ │ ├── src/
│ │ │ └── lib.rs
│ │ └── www/
│ │ ├── .gitignore
│ │ ├── .prettierrc
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── main.js
│ │ └── vite.config.js
│ ├── ui/
│ │ ├── Cargo.toml
│ │ ├── LICENSE-APACHE
│ │ ├── build.rs
│ │ ├── locales/
│ │ │ └── ui.yml
│ │ └── src/
│ │ ├── accordion.rs
│ │ ├── actions.rs
│ │ ├── alert.rs
│ │ ├── anchored.rs
│ │ ├── animation.rs
│ │ ├── async_util.rs
│ │ ├── avatar/
│ │ │ ├── avatar.rs
│ │ │ ├── avatar_group.rs
│ │ │ └── mod.rs
│ │ ├── badge.rs
│ │ ├── breadcrumb.rs
│ │ ├── button/
│ │ │ ├── button.rs
│ │ │ ├── button_group.rs
│ │ │ ├── button_icon.rs
│ │ │ ├── dropdown_button.rs
│ │ │ ├── mod.rs
│ │ │ └── toggle.rs
│ │ ├── chart/
│ │ │ ├── area_chart.rs
│ │ │ ├── bar_chart.rs
│ │ │ ├── candlestick_chart.rs
│ │ │ ├── line_chart.rs
│ │ │ ├── mod.rs
│ │ │ └── pie_chart.rs
│ │ ├── checkbox.rs
│ │ ├── clipboard.rs
│ │ ├── collapsible.rs
│ │ ├── color_picker.rs
│ │ ├── description_list.rs
│ │ ├── dialog/
│ │ │ ├── alert_dialog.rs
│ │ │ ├── content.rs
│ │ │ ├── description.rs
│ │ │ ├── dialog.rs
│ │ │ ├── footer.rs
│ │ │ ├── header.rs
│ │ │ ├── mod.rs
│ │ │ └── title.rs
│ │ ├── divider.rs
│ │ ├── dock/
│ │ │ ├── dock.rs
│ │ │ ├── invalid_panel.rs
│ │ │ ├── mod.rs
│ │ │ ├── panel.rs
│ │ │ ├── stack_panel.rs
│ │ │ ├── state.rs
│ │ │ ├── tab_panel.rs
│ │ │ └── tiles.rs
│ │ ├── element_ext.rs
│ │ ├── event.rs
│ │ ├── fixtures/
│ │ │ └── layout.json
│ │ ├── focus_trap.rs
│ │ ├── form/
│ │ │ ├── field.rs
│ │ │ ├── form.rs
│ │ │ └── mod.rs
│ │ ├── geometry.rs
│ │ ├── global_state.rs
│ │ ├── group_box.rs
│ │ ├── highlighter/
│ │ │ ├── diagnostics.rs
│ │ │ ├── highlighter.rs
│ │ │ ├── languages/
│ │ │ │ ├── go/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── html/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── javascript/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── json/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── kotlin/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── lua/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── markdown/
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── markdown_inline/
│ │ │ │ │ └── highlights.scm
│ │ │ │ ├── php/
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── rust/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── highlights.scm
│ │ │ │ │ └── injections.scm
│ │ │ │ ├── typescript/
│ │ │ │ │ └── highlights.scm
│ │ │ │ └── zig/
│ │ │ │ ├── highlights.scm
│ │ │ │ └── injections.scm
│ │ │ ├── languages.rs
│ │ │ ├── mod.rs
│ │ │ ├── registry.rs
│ │ │ └── wasm_stub.rs
│ │ ├── history.rs
│ │ ├── hover_card.rs
│ │ ├── icon.rs
│ │ ├── index_path.rs
│ │ ├── input/
│ │ │ ├── blink_cursor.rs
│ │ │ ├── change.rs
│ │ │ ├── clear_button.rs
│ │ │ ├── cursor.rs
│ │ │ ├── display_map/
│ │ │ │ ├── README.md
│ │ │ │ ├── display_map.rs
│ │ │ │ ├── fold_map.rs
│ │ │ │ ├── folding.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── text_wrapper.rs
│ │ │ │ └── wrap_map.rs
│ │ │ ├── element.rs
│ │ │ ├── indent.rs
│ │ │ ├── input.rs
│ │ │ ├── lsp/
│ │ │ │ ├── code_actions.rs
│ │ │ │ ├── completions.rs
│ │ │ │ ├── definitions.rs
│ │ │ │ ├── document_colors.rs
│ │ │ │ ├── hover.rs
│ │ │ │ └── mod.rs
│ │ │ ├── mask_pattern.rs
│ │ │ ├── mod.rs
│ │ │ ├── mode.rs
│ │ │ ├── movement.rs
│ │ │ ├── number_input.rs
│ │ │ ├── otp_input.rs
│ │ │ ├── popovers/
│ │ │ │ ├── code_action_menu.rs
│ │ │ │ ├── completion_menu.rs
│ │ │ │ ├── context_menu.rs
│ │ │ │ ├── diagnostic_popover.rs
│ │ │ │ ├── hover_popover.rs
│ │ │ │ └── mod.rs
│ │ │ ├── rope_ext.rs
│ │ │ ├── search.rs
│ │ │ ├── selection.rs
│ │ │ └── state.rs
│ │ ├── inspector.rs
│ │ ├── kbd.rs
│ │ ├── label.rs
│ │ ├── lib.rs
│ │ ├── link.rs
│ │ ├── list/
│ │ │ ├── cache.rs
│ │ │ ├── delegate.rs
│ │ │ ├── list.rs
│ │ │ ├── list_item.rs
│ │ │ ├── loading.rs
│ │ │ ├── mod.rs
│ │ │ └── separator_item.rs
│ │ ├── menu/
│ │ │ ├── app_menu_bar.rs
│ │ │ ├── context_menu.rs
│ │ │ ├── dropdown_menu.rs
│ │ │ ├── menu_item.rs
│ │ │ ├── mod.rs
│ │ │ └── popup_menu.rs
│ │ ├── notification.rs
│ │ ├── pagination.rs
│ │ ├── plot/
│ │ │ ├── axis.rs
│ │ │ ├── grid.rs
│ │ │ ├── label.rs
│ │ │ ├── mod.rs
│ │ │ ├── scale/
│ │ │ │ ├── band.rs
│ │ │ │ ├── linear.rs
│ │ │ │ ├── ordinal.rs
│ │ │ │ ├── point.rs
│ │ │ │ └── sealed.rs
│ │ │ ├── scale.rs
│ │ │ ├── shape/
│ │ │ │ ├── arc.rs
│ │ │ │ ├── area.rs
│ │ │ │ ├── bar.rs
│ │ │ │ ├── line.rs
│ │ │ │ ├── pie.rs
│ │ │ │ └── stack.rs
│ │ │ ├── shape.rs
│ │ │ └── tooltip.rs
│ │ ├── popover.rs
│ │ ├── progress/
│ │ │ ├── mod.rs
│ │ │ ├── progress.rs
│ │ │ └── progress_circle.rs
│ │ ├── radio.rs
│ │ ├── rating.rs
│ │ ├── resizable/
│ │ │ ├── mod.rs
│ │ │ ├── panel.rs
│ │ │ └── resize_handle.rs
│ │ ├── root.rs
│ │ ├── scroll/
│ │ │ ├── mod.rs
│ │ │ ├── scrollable.rs
│ │ │ ├── scrollable_mask.rs
│ │ │ └── scrollbar.rs
│ │ ├── select.rs
│ │ ├── setting/
│ │ │ ├── fields/
│ │ │ │ ├── bool.rs
│ │ │ │ ├── dropdown.rs
│ │ │ │ ├── element.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── number.rs
│ │ │ │ └── string.rs
│ │ │ ├── group.rs
│ │ │ ├── item.rs
│ │ │ ├── mod.rs
│ │ │ ├── page.rs
│ │ │ └── settings.rs
│ │ ├── sheet.rs
│ │ ├── sidebar/
│ │ │ ├── footer.rs
│ │ │ ├── group.rs
│ │ │ ├── header.rs
│ │ │ ├── menu.rs
│ │ │ └── mod.rs
│ │ ├── skeleton.rs
│ │ ├── slider.rs
│ │ ├── spinner.rs
│ │ ├── stepper/
│ │ │ ├── item.rs
│ │ │ ├── mod.rs
│ │ │ ├── stepper.rs
│ │ │ └── trigger.rs
│ │ ├── styled.rs
│ │ ├── switch.rs
│ │ ├── tab/
│ │ │ ├── mod.rs
│ │ │ ├── tab.rs
│ │ │ └── tab_bar.rs
│ │ ├── table/
│ │ │ ├── column.rs
│ │ │ ├── data_table.rs
│ │ │ ├── delegate.rs
│ │ │ ├── loading.rs
│ │ │ ├── mod.rs
│ │ │ ├── state.rs
│ │ │ └── table.rs
│ │ ├── tag.rs
│ │ ├── text/
│ │ │ ├── document.rs
│ │ │ ├── format/
│ │ │ │ ├── html.rs
│ │ │ │ ├── html5minify/
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── markdown.rs
│ │ │ │ └── mod.rs
│ │ │ ├── inline.rs
│ │ │ ├── mod.rs
│ │ │ ├── node.rs
│ │ │ ├── state.rs
│ │ │ ├── style.rs
│ │ │ ├── text_view.rs
│ │ │ └── utils.rs
│ │ ├── theme/
│ │ │ ├── color.rs
│ │ │ ├── default-colors.json
│ │ │ ├── default-theme.json
│ │ │ ├── mod.rs
│ │ │ ├── registry.rs
│ │ │ ├── schema.rs
│ │ │ └── theme_color.rs
│ │ ├── time/
│ │ │ ├── calendar.rs
│ │ │ ├── date_picker.rs
│ │ │ ├── mod.rs
│ │ │ └── utils.rs
│ │ ├── title_bar.rs
│ │ ├── tooltip.rs
│ │ ├── tree.rs
│ │ ├── virtual_list.rs
│ │ ├── window_border.rs
│ │ └── window_ext.rs
│ └── webview/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ └── lib.rs
├── docs/
│ ├── .gitignore
│ ├── .vitepress/
│ │ ├── config.mts
│ │ ├── language.ts
│ │ └── theme/
│ │ ├── components/
│ │ │ └── GitHubStar.vue
│ │ ├── index.ts
│ │ └── style.css
│ ├── README.md
│ ├── contributors.md
│ ├── contributors.vue
│ ├── data/
│ │ ├── contributors.data.js
│ │ ├── repo.data.js
│ │ └── skills.data.js
│ ├── docs/
│ │ ├── assets.md
│ │ ├── components/
│ │ │ ├── accordion.md
│ │ │ ├── alert-dialog.md
│ │ │ ├── alert.md
│ │ │ ├── avatar.md
│ │ │ ├── badge.md
│ │ │ ├── button.md
│ │ │ ├── calendar.md
│ │ │ ├── chart.md
│ │ │ ├── checkbox.md
│ │ │ ├── clipboard.md
│ │ │ ├── collapsible.md
│ │ │ ├── color-picker.md
│ │ │ ├── data-table.md
│ │ │ ├── date-picker.md
│ │ │ ├── description-list.md
│ │ │ ├── dialog.md
│ │ │ ├── dropdown_button.md
│ │ │ ├── editor.md
│ │ │ ├── focus-trap.md
│ │ │ ├── form.md
│ │ │ ├── group-box.md
│ │ │ ├── hover-card.md
│ │ │ ├── icon.md
│ │ │ ├── image.md
│ │ │ ├── index.md
│ │ │ ├── input.md
│ │ │ ├── kbd.md
│ │ │ ├── label.md
│ │ │ ├── list.md
│ │ │ ├── menu.md
│ │ │ ├── notification.md
│ │ │ ├── number-input.md
│ │ │ ├── otp-input.md
│ │ │ ├── pagination.md
│ │ │ ├── plot.md
│ │ │ ├── popover.md
│ │ │ ├── progress.md
│ │ │ ├── radio.md
│ │ │ ├── rating.md
│ │ │ ├── resizable.md
│ │ │ ├── scrollable.md
│ │ │ ├── select.md
│ │ │ ├── settings.md
│ │ │ ├── sheet.md
│ │ │ ├── sidebar.md
│ │ │ ├── skeleton.md
│ │ │ ├── slider.md
│ │ │ ├── spinner.md
│ │ │ ├── stepper.md
│ │ │ ├── switch.md
│ │ │ ├── table.md
│ │ │ ├── tabs.md
│ │ │ ├── tag.md
│ │ │ ├── title-bar.md
│ │ │ ├── toggle.md
│ │ │ ├── tooltip.md
│ │ │ ├── tree.md
│ │ │ └── virtual-list.md
│ │ ├── context.md
│ │ ├── element_id.md
│ │ ├── getting-started.md
│ │ ├── index.md
│ │ ├── installation.md
│ │ ├── root.md
│ │ └── theme.md
│ ├── index.md
│ ├── index.vue
│ ├── package.json
│ ├── postcss.config.mjs
│ ├── skills.md
│ ├── skills.vue
│ └── src/
│ ├── dark.theme.json
│ └── light.theme.json
├── examples/
│ ├── README.md
│ ├── app_assets/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ └── src/
│ │ └── main.rs
│ ├── color_mix_oklab.rs
│ ├── dialog_overlay/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── focus_trap/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── hello_world/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── input/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── system_monitor/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── webview/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── window_title/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── flake.nix
├── script/
│ ├── bootstrap
│ ├── bump-version.sh
│ ├── install-linux.sh
│ └── install-window.ps1
└── themes/
├── adventure.json
├── alduin.json
├── asciinema.json
├── ayu.json
├── catppuccin.json
├── everforest.json
├── fahrenheit.json
├── flexoki.json
├── gruvbox.json
├── harper.json
├── hybrid.json
├── jellybeans.json
├── kibble.json
├── macos-classic.json
├── matrix.json
├── mellifluous.json
├── molokai.json
├── solarized.json
├── spaceduck.json
├── tokyonight.json
└── twilight.json
Showing preview only (521K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (5571 symbols across 312 files)
FILE: crates/assets/src/native_assets.rs
type Assets (line 9) | pub struct Assets;
method new (line 13) | pub fn new(_endpoint: impl Into<SharedString>) -> Self {
method load (line 19) | fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
method list (line 29) | fn list(&self, path: &str) -> Result<Vec<SharedString>> {
FILE: crates/assets/src/wasm_assets.rs
type Assets (line 9) | pub struct Assets {
method new (line 16) | pub fn new(endpoint: impl Into<SharedString>) -> Self {
method default (line 26) | fn default() -> Self {
method load (line 32) | fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
method list (line 104) | fn list(&self, path: &str) -> Result<Vec<SharedString>> {
FILE: crates/macros/src/derive_into_plot.rs
function derive_into_plot (line 5) | pub fn derive_into_plot(input: TokenStream) -> TokenStream {
FILE: crates/macros/src/lib.rs
type IconNameInput (line 8) | struct IconNameInput {
method parse (line 19) | fn parse(input: ParseStream) -> syn::Result<Self> {
function derive_into_plot (line 45) | pub fn derive_into_plot(input: TokenStream) -> TokenStream {
function pascal_case (line 61) | fn pascal_case(filename: &str) -> String {
function icon_named (line 98) | pub fn icon_named(input: TokenStream) -> TokenStream {
function test_pascal_case_basic (line 175) | fn test_pascal_case_basic() {
FILE: crates/story-web/src/lib.rs
function run (line 8) | pub fn run() -> Result<(), JsValue> {
FILE: crates/story-web/www/src/main.js
function init (line 1) | async function init() {
FILE: crates/story-web/www/vite.config.js
method configureServer (line 22) | configureServer(server) {
FILE: crates/story/examples/brush.rs
type BrushStory (line 15) | pub struct BrushStory {
method new (line 35) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method handle_mouse_down (line 65) | fn handle_mouse_down(
method handle_mouse_move (line 95) | fn handle_mouse_move(
method handle_mouse_up (line 139) | fn handle_mouse_up(&mut self, _event: &MouseUpEvent, _: &mut Window, c...
method clear_canvas (line 153) | fn clear_canvas(&mut self, cx: &mut Context<Self>) {
method set_brush_color (line 160) | fn set_brush_color(&mut self, color: Hsla, cx: &mut Context<Self>) {
method color_button (line 173) | fn color_button(&self, color: Hsla, _label: &str, cx: &Context<Self>) ...
method render_canvas (line 196) | fn render_canvas(&mut self, cx: &Context<Self>) -> impl IntoElement {
method build_stroke_path (line 286) | fn build_stroke_path(stroke: &Stroke, bounds: &Bounds<Pixels>) -> Opti...
type Stroke (line 28) | struct Stroke {
method focus_handle (line 167) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 309) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
function section (line 416) | fn section(title: impl Into<SharedString>) -> GroupBox {
type Example (line 429) | pub struct Example {
method new (line 434) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 439) | fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method render (line 445) | fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> i...
function main (line 450) | fn main() {
FILE: crates/story/examples/dock.rs
type AddPanel (line 22) | pub struct AddPanel(DockPlacement);
type TogglePanelVisible (line 26) | pub struct TogglePanelVisible(SharedString);
constant MAIN_DOCK_AREA (line 30) | const MAIN_DOCK_AREA: DockAreaTab = DockAreaTab {
constant STATE_FILE (line 36) | const STATE_FILE: &str = "target/docks.json";
constant STATE_FILE (line 38) | const STATE_FILE: &str = "docks.json";
function init (line 40) | pub fn init(cx: &mut App) {
type StoryWorkspace (line 52) | pub struct StoryWorkspace {
method new (line 66) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method save_layout (line 178) | fn save_layout(
method save_state (line 206) | fn save_state(state: &DockAreaState) -> Result<()> {
method load_layout (line 213) | fn load_layout(
method reset_default_layout (line 261) | fn reset_default_layout(dock_area: WeakEntity<DockArea>, window: &mut ...
method init_default_layout (line 334) | fn init_default_layout(
method new_local (line 372) | pub fn new_local(cx: &mut App) -> Task<anyhow::Result<WindowHandle<Roo...
method on_action_add_panel (line 420) | fn on_action_add_panel(
method on_action_toggle_panel_visible (line 453) | fn on_action_toggle_panel_visible(
method on_action_toggle_dock_toggle_button (line 472) | fn on_action_toggle_dock_toggle_button(
type DockAreaTab (line 60) | struct DockAreaTab {
function open_new (line 486) | pub fn open_new(
method render (line 501) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
function main (line 523) | fn main() {
FILE: crates/story/examples/editor.rs
type Lang (line 34) | enum Lang {
method name (line 40) | fn name(&self) -> &str {
method from_str (line 47) | fn from_str(s: &str) -> Self {
function init (line 55) | fn init() {
type Example (line 69) | pub struct Example {
method new (line 690) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method load_files (line 741) | fn load_files(state: Entity<TreeState>, path: PathBuf, cx: &mut App) {
method go_to_line (line 752) | fn go_to_line(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut...
method lint_document (line 799) | fn lint_document(&mut self, cx: &mut Context<Self>) {
method on_action_open (line 860) | fn on_action_open(&mut self, _: &Open, window: &mut Window, cx: &mut C...
method open_file (line 879) | fn open_file(
method render_file_tree (line 909) | fn render_file_tree(&self, _: &mut Window, cx: &mut Context<Self>) -> ...
method render_line_number_button (line 959) | fn render_line_number_button(
method render_soft_wrap_button (line 978) | fn render_soft_wrap_button(&self, _: &mut Window, cx: &mut Context<Sel...
method render_show_whitespaces_button (line 993) | fn render_show_whitespaces_button(
method render_indent_guides_button (line 1012) | fn render_indent_guides_button(
method render_folding_button (line 1031) | fn render_folding_button(&self, _: &mut Window, cx: &mut Context<Self>...
method render_go_to_line_button (line 1046) | fn render_go_to_line_button(&self, _: &mut Window, cx: &mut Context<Se...
type ExampleLspStore (line 85) | pub struct ExampleLspStore {
method new (line 93) | pub fn new() -> Self {
method diagnostics (line 107) | fn diagnostics(&self) -> Vec<Diagnostic> {
method update_diagnostics (line 112) | fn update_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
method code_actions (line 118) | fn code_actions(&self) -> Vec<(Range<usize>, CodeAction)> {
method update_code_actions (line 123) | fn update_code_actions(&self, code_actions: Vec<(Range<usize>, CodeAct...
method is_dirty (line 129) | fn is_dirty(&self) -> bool {
function completion_item (line 135) | fn completion_item(
method completions (line 156) | fn completions(
method inline_completion (line 214) | fn inline_completion(
method is_completion_trigger (line 253) | fn is_completion_trigger(
method id (line 264) | fn id(&self) -> SharedString {
method code_actions (line 268) | fn code_actions(
method perform_code_action (line 287) | fn perform_code_action(
method hover (line 319) | fn hover(
constant RUST_DOC_URLS (line 353) | const RUST_DOC_URLS: &[(&str, &str)] = &[
method definitions (line 368) | fn definitions(
type TextConvertor (line 430) | struct TextConvertor;
method id (line 433) | fn id(&self) -> SharedString {
method code_actions (line 437) | fn code_actions(
method perform_code_action (line 591) | fn perform_code_action(
method document_colors (line 623) | fn document_colors(
function build_file_items (line 655) | fn build_file_items(ignorer: &Ignorer, root: &PathBuf, path: &PathBuf) -...
method render (line 1064) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
function main (line 1129) | fn main() {
FILE: crates/story/examples/fixtures/test.c
type HelloWorld (line 23) | typedef struct {
function HelloWorld (line 30) | HelloWorld* hello_world_create(const char* name) {
function hello_world_destroy (line 43) | void hello_world_destroy(HelloWorld* hw) {
function hello_world_greet (line 49) | void hello_world_greet(HelloWorld* hw, const char** names, int count) {
function hello_world_configure (line 55) | void hello_world_configure(HelloWorld* hw, int timeout, int retries) {
function main (line 78) | int main() {
FILE: crates/story/examples/fixtures/test.go
constant timeout (line 12) | timeout = 5 * time.Second
type HelloWorld (line 26) | type HelloWorld struct
method Greet (line 49) | func (h *HelloWorld) Greet(ctx context.Context, names ...string) error {
method Configure (line 61) | func (h *HelloWorld) Configure(cfg Config) {
method generateReport (line 67) | func (h *HelloWorld) generateReport() string {
type Config (line 32) | type Config struct
function NewHelloWorld (line 38) | func NewHelloWorld(name string) *HelloWorld {
function main (line 78) | func main() {
FILE: crates/story/examples/fixtures/test.js
class HelloWorld (line 12) | class HelloWorld {
method constructor (line 28) | constructor(name = "World", options = {}) {
method getInstanceCount (line 35) | static getInstanceCount() {
method name (line 39) | get name() {
method name (line 43) | set name(value) {
method greet (line 47) | async greet(...names) {
method configure (line 58) | configure(options = {}) {
method generateSequence (line 62) | *generateSequence(start = 0, end = 10) {
method processNames (line 66) | processNames(names) {
FILE: crates/story/examples/fixtures/test.php
class HelloWorld (line 8) | final class HelloWorld
method __construct (line 12) | public function __construct(private string $name = 'World')
method greet (line 16) | public function greet(string ...$names): array
method report (line 21) | public function report(): string
function is_valid_email (line 27) | function is_valid_email(string $email): bool
FILE: crates/story/examples/fixtures/test.py
class Config (line 10) | class Config:
class HelloWorld (line 28) | class HelloWorld:
method __init__ (line 32) | def __init__(self, name: str = "World", options: Optional[Dict[str, An...
method name (line 40) | def name(self) -> str:
method name (line 44) | def name(self, value: str) -> None:
method get_instance_count (line 50) | def get_instance_count(cls) -> int:
method greet (line 53) | async def greet(self, *names: str) -> None:
method process_names (line 61) | def process_names(self, names: List[str] = None) -> List[str]:
method _generate_report (line 66) | def _generate_report(self) -> str:
method __str__ (line 75) | def __str__(self) -> str:
function main (line 78) | async def main():
FILE: crates/story/examples/fixtures/test.rb
type Logging (line 5) | module Logging
class HelloWorld (line 17) | class HelloWorld < Object
method initialize (line 26) | def initialize(name: 'World', options: {})
method instance_count (line 34) | def self.instance_count(format: :short)
method greet (line 41) | def greet(*names)
method configure (line 47) | def configure(timeout: 5000, retries: 3)
method configured? (line 51) | def configured?
method process_names (line 55) | def process_names(names)
method generate_report (line 61) | def generate_report
FILE: crates/story/examples/fixtures/test.rs
constant VERSION (line 7) | const VERSION: &str = "1.0.0";
type HelloWorld (line 18) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 26) | pub enum HelloError {
type Result (line 35) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 66) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 82) | async fn main() -> Result<()> {
constant VERSION (line 104) | const VERSION: &str = "1.0.0";
type HelloWorld (line 114) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 122) | pub enum HelloError {
type Result (line 129) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 157) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 173) | async fn main() -> Result<()> {
constant VERSION (line 195) | const VERSION: &str = "1.0.0";
type HelloWorld (line 205) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 213) | pub enum HelloError {
type Result (line 220) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 248) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 264) | async fn main() -> Result<()> {
constant VERSION (line 286) | const VERSION: &str = "1.0.0";
type HelloWorld (line 296) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 304) | pub enum HelloError {
type Result (line 311) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 339) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 355) | async fn main() -> Result<()> {
constant VERSION (line 377) | const VERSION: &str = "1.0.0";
type HelloWorld (line 387) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 395) | pub enum HelloError {
type Result (line 402) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 430) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 446) | async fn main() -> Result<()> {
constant VERSION (line 468) | const VERSION: &str = "1.0.0";
type HelloWorld (line 478) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 486) | pub enum HelloError {
type Result (line 493) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 521) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 537) | async fn main() -> Result<()> {
constant VERSION (line 559) | const VERSION: &str = "1.0.0";
type HelloWorld (line 569) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 577) | pub enum HelloError {
type Result (line 584) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 612) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 628) | async fn main() -> Result<()> {
constant VERSION (line 650) | const VERSION: &str = "1.0.0";
type HelloWorld (line 660) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 668) | pub enum HelloError {
type Result (line 675) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 703) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 719) | async fn main() -> Result<()> {
constant VERSION (line 741) | const VERSION: &str = "1.0.0";
type HelloWorld (line 751) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 759) | pub enum HelloError {
type Result (line 766) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 794) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 810) | async fn main() -> Result<()> {
constant VERSION (line 832) | const VERSION: &str = "1.0.0";
type HelloWorld (line 842) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 850) | pub enum HelloError {
type Result (line 857) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 885) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 901) | async fn main() -> Result<()> {
constant VERSION (line 923) | const VERSION: &str = "1.0.0";
type HelloWorld (line 933) | pub struct HelloWorld {
method new (line 38) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 50) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 58) | fn generate_report(&self) -> String {
method new (line 132) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 141) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 149) | fn generate_report(&self) -> String {
method new (line 223) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 232) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 240) | fn generate_report(&self) -> String {
method new (line 314) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 323) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 331) | fn generate_report(&self) -> String {
method new (line 405) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 414) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 422) | fn generate_report(&self) -> String {
method new (line 496) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 505) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 513) | fn generate_report(&self) -> String {
method new (line 587) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 596) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 604) | fn generate_report(&self) -> String {
method new (line 678) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 687) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 695) | fn generate_report(&self) -> String {
method new (line 769) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 778) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 786) | fn generate_report(&self) -> String {
method new (line 860) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 869) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 877) | fn generate_report(&self) -> String {
method new (line 951) | pub fn new(name: impl Into<String>) -> Self {
method greet (line 960) | pub async fn greet<T: AsRef<str>>(&self, names: &[T]) -> Result<()> {
method generate_report (line 968) | fn generate_report(&self) -> String {
type HelloError (line 941) | pub enum HelloError {
type Result (line 948) | type Result<T> = std::result::Result<T, HelloError>;
type Configurable (line 976) | trait Configurable {
method configure (line 67) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 68) | fn is_configured(&self) -> bool;
method configure (line 72) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 76) | fn is_configured(&self) -> bool {
method configure (line 158) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 159) | fn is_configured(&self) -> bool;
method configure (line 163) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 167) | fn is_configured(&self) -> bool {
method configure (line 249) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 250) | fn is_configured(&self) -> bool;
method configure (line 254) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 258) | fn is_configured(&self) -> bool {
method configure (line 340) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 341) | fn is_configured(&self) -> bool;
method configure (line 345) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 349) | fn is_configured(&self) -> bool {
method configure (line 431) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 432) | fn is_configured(&self) -> bool;
method configure (line 436) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 440) | fn is_configured(&self) -> bool {
method configure (line 522) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 523) | fn is_configured(&self) -> bool;
method configure (line 527) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 531) | fn is_configured(&self) -> bool {
method configure (line 613) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 614) | fn is_configured(&self) -> bool;
method configure (line 618) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 622) | fn is_configured(&self) -> bool {
method configure (line 704) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 705) | fn is_configured(&self) -> bool;
method configure (line 709) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 713) | fn is_configured(&self) -> bool {
method configure (line 795) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 796) | fn is_configured(&self) -> bool;
method configure (line 800) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 804) | fn is_configured(&self) -> bool {
method configure (line 886) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 887) | fn is_configured(&self) -> bool;
method configure (line 891) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 895) | fn is_configured(&self) -> bool {
method configure (line 977) | fn configure(&mut self, options: HashMap<String, serde_json::Value>);
method is_configured (line 978) | fn is_configured(&self) -> bool;
method configure (line 982) | fn configure(&mut self, options: HashMap<String, serde_json::Value>) {
method is_configured (line 986) | fn is_configured(&self) -> bool {
function main (line 992) | async fn main() -> Result<()> {
FILE: crates/story/examples/fixtures/test.ts
constant VERSION (line 3) | const VERSION = "1.0.0";
class HelloWorld (line 5) | class HelloWorld {
method constructor (line 10) | constructor(name: string) {
method greet (line 16) | greet(names: string[]): void {
method configure (line 22) | configure(cfg: { timeout: number; retries: number; debug: boolean }): ...
method generateReport (line 28) | generateReport(): string {
function main (line 41) | function main() {
FILE: crates/story/examples/html.rs
type Example (line 11) | pub struct Example {
method new (line 19) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 44) | fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
constant EXAMPLE (line 16) | const EXAMPLE: &str = include_str!("./fixtures/test.html");
method render (line 50) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
function main (line 76) | fn main() {
FILE: crates/story/examples/large-text.rs
type Example (line 11) | pub struct Example {
method new (line 19) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 40) | fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method go_to_line (line 44) | fn go_to_line(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut...
method toggle_soft_wrap (line 89) | fn toggle_soft_wrap(&mut self, _: &ClickEvent, window: &mut Window, cx...
method render (line 99) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
function main (line 139) | fn main() {
FILE: crates/story/examples/markdown.rs
type Example (line 15) | pub struct Example {
method new (line 23) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_action_open (line 45) | fn on_action_open(&mut self, _: &Open, window: &mut Window, cx: &mut C...
method view (line 72) | fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
constant EXAMPLE (line 20) | const EXAMPLE: &str = include_str!("./fixtures/test.md");
method render (line 78) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
function main (line 142) | fn main() {
FILE: crates/story/examples/stream_markdown.rs
type Example (line 10) | pub struct Example {
method new (line 21) | pub fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 51) | fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method replay (line 58) | fn replay(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
constant EXAMPLE (line 18) | const EXAMPLE: &str = include_str!("./fixtures/test.md");
method render (line 79) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
function main (line 110) | fn main() {
FILE: crates/story/examples/tiles.rs
constant TILES_DOCK_AREA (line 19) | const TILES_DOCK_AREA: DockAreaTab = DockAreaTab {
type ContainerPanel (line 29) | struct ContainerPanel {
method init (line 55) | fn init(cx: &mut App) {
method new (line 80) | fn new(panel: Arc<dyn PanelView>, window: &mut Window, cx: &mut App) -...
type ContainerPanelState (line 35) | struct ContainerPanelState {
method new (line 41) | fn new(child: PanelState) -> Self {
method to_value (line 45) | fn to_value(&self) -> serde_json::Value {
method from_value (line 49) | fn from_value(value: serde_json::Value) -> Result<Self> {
method panel_name (line 93) | fn panel_name(&self) -> &'static str {
method title (line 97) | fn title(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl...
method title_suffix (line 101) | fn title_suffix(&mut self, _: &mut Window, cx: &mut Context<Self>) -> Op...
method dump (line 115) | fn dump(&self, cx: &App) -> PanelState {
method focus_handle (line 126) | fn focus_handle(&self, cx: &App) -> FocusHandle {
method render (line 132) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
function init (line 139) | pub fn init(cx: &mut App) {
type StoryTiles (line 146) | pub struct StoryTiles {
method new (line 158) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method save_layout (line 210) | fn save_layout(
method save_tiles (line 239) | fn save_tiles(state: &DockAreaState) -> Result<()> {
method set_scrollbar_show (line 246) | fn set_scrollbar_show(dock_area: &mut DockArea, cx: &mut App) {
method load_tiles (line 257) | fn load_tiles(
method reset_default_layout (line 296) | fn reset_default_layout(
method init_default_layout (line 311) | fn init_default_layout(
method new_local (line 354) | pub fn new_local(cx: &mut App) -> Task<anyhow::Result<WindowHandle<Roo...
type DockAreaTab (line 152) | struct DockAreaTab {
function open_new (line 400) | pub fn open_new(
method render (line 415) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
function main (line 436) | fn main() {
function quit (line 459) | fn quit(_: &Quit, cx: &mut App) {
FILE: crates/story/src/app_menus.rs
function init (line 11) | pub fn init(title: impl Into<SharedString>, cx: &mut App) -> Entity<AppM...
function update_app_menu (line 38) | fn update_app_menu(title: impl Into<SharedString>, app_menu_bar: Entity<...
function build_menus (line 53) | fn build_menus(title: impl Into<SharedString>, cx: &App) -> Vec<Menu> {
function language_menu (line 113) | fn language_menu(_: &App) -> MenuItem {
function theme_menu (line 124) | fn theme_menu(cx: &App) -> MenuItem {
FILE: crates/story/src/embedded_themes.rs
function embedded_themes (line 5) | pub fn embedded_themes() -> HashMap<&'static str, &'static str> {
FILE: crates/story/src/gallery.rs
type Gallery (line 12) | pub struct Gallery {
method new (line 22) | pub fn new(init_story: Option<&str>, window: &mut Window, cx: &mut Con...
method set_active_story (line 118) | fn set_active_story(&mut self, name: &str, window: &mut Window, cx: &m...
method view (line 125) | pub fn view(init_story: Option<&str>, window: &mut Window, cx: &mut Ap...
method render (line 131) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/lib.rs
type SelectScrollbarShow (line 34) | pub struct SelectScrollbarShow(ScrollbarShow);
type SelectLocale (line 38) | pub struct SelectLocale(SharedString);
type SelectFont (line 42) | pub struct SelectFont(usize);
type SelectRadius (line 46) | pub struct SelectRadius(usize);
constant PANEL_NAME (line 63) | const PANEL_NAME: &str = "StoryContainer";
type AppState (line 65) | pub struct AppState {
method init (line 69) | fn init(cx: &mut App) {
method global (line 76) | pub fn global(cx: &App) -> &Self {
method global_mut (line 80) | pub fn global_mut(cx: &mut App) -> &mut Self {
function create_new_window (line 85) | pub fn create_new_window<F, E>(title: &str, crate_view_fn: F, cx: &mut App)
function create_new_window_with_size (line 93) | pub fn create_new_window_with_size<F, E>(
function init (line 154) | pub fn init(cx: &mut App) {
type StorySection (line 277) | struct StorySection {
method sub_title (line 285) | pub fn sub_title(mut self, sub_title: impl IntoElement) -> Self {
method max_w_md (line 291) | fn max_w_md(mut self) -> Self {
method max_w_lg (line 297) | fn max_w_lg(mut self) -> Self {
method max_w_xl (line 303) | fn max_w_xl(mut self) -> Self {
method max_w_2xl (line 309) | fn max_w_2xl(mut self) -> Self {
method extend (line 316) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method style (line 322) | fn style(&mut self) -> &mut gpui::StyleRefinement {
method render (line 328) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
function section (line 351) | pub(crate) fn section(title: impl Into<SharedString>) -> StorySection {
type StoryContainer (line 365) | pub struct StoryContainer {
method new (line 388) | pub fn new(_window: &mut Window, cx: &mut App) -> Self {
method panel (line 407) | pub fn panel<S: Story>(window: &mut Window, cx: &mut App) -> Entity<Se...
method width (line 430) | pub fn width(mut self, width: gpui::Pixels) -> Self {
method height (line 435) | pub fn height(mut self, height: gpui::Pixels) -> Self {
method story (line 440) | pub fn story(mut self, story: AnyView, story_klass: impl Into<SharedSt...
method on_active (line 446) | pub fn on_active(mut self, on_active: fn(AnyView, bool, &mut Window, &...
type ContainerEvent (line 381) | pub enum ContainerEvent {
type StoryState (line 453) | pub struct StoryState {
method to_value (line 458) | fn to_value(&self) -> serde_json::Value {
method from_value (line 464) | fn from_value(value: serde_json::Value) -> Self {
method to_story (line 468) | fn to_story(
method panel_name (line 526) | fn panel_name(&self) -> &'static str {
method title (line 530) | fn title(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> im...
method title_style (line 534) | fn title_style(&self, cx: &App) -> Option<TitleStyle> {
method closable (line 545) | fn closable(&self, _cx: &App) -> bool {
method zoomable (line 549) | fn zoomable(&self, _cx: &App) -> Option<PanelControl> {
method visible (line 553) | fn visible(&self, cx: &App) -> bool {
method set_zoomed (line 560) | fn set_zoomed(&mut self, zoomed: bool, _window: &mut Window, _cx: &mut C...
method set_active (line 564) | fn set_active(&mut self, active: bool, _window: &mut Window, cx: &mut Co...
method dropdown_menu (line 573) | fn dropdown_menu(
method toolbar_buttons (line 582) | fn toolbar_buttons(
method dump (line 601) | fn dump(&self, _cx: &App) -> PanelState {
method focus_handle (line 613) | fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
method render (line 618) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
type StoryRoot (line 630) | pub struct StoryRoot {
method new (line 637) | pub fn new(
method on_action_panel_info (line 651) | fn on_action_panel_info(
method on_action_toggle_search (line 664) | fn on_action_toggle_search(
method focus_handle (line 684) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 690) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
FILE: crates/story/src/main.rs
function main (line 4) | fn main() {
FILE: crates/story/src/stories/accordion_story.rs
type AccordionStory (line 17) | pub struct AccordionStory {
method title (line 28) | fn title() -> &'static str {
method description (line 32) | fn description() -> &'static str {
method new_view (line 36) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 42) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 46) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method toggle_accordion (line 58) | fn toggle_accordion(&mut self, open_ixs: Vec<usize>, _: &mut Window, c...
method set_size (line 63) | fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Se...
method focus_handle (line 70) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 76) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/alert_dialog_story.rs
type AlertDialogStory (line 18) | pub struct AlertDialogStory {
method title (line 23) | fn title() -> &'static str {
method description (line 27) | fn description() -> &'static str {
method new_view (line 31) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 37) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 41) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 49) | fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
method render (line 55) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/alert_story.rs
type AlertStory (line 16) | pub struct AlertStory {
method new (line 23) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 27) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method set_size (line 31) | fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Se...
method title (line 38) | fn title() -> &'static str {
method description (line 42) | fn description() -> &'static str {
method new_view (line 46) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 50) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 56) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 62) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/avatar_story.rs
type AvatarStory (line 14) | pub struct AvatarStory {
method new (line 19) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 25) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 31) | fn title() -> &'static str {
method description (line 35) | fn description() -> &'static str {
method new_view (line 39) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 43) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 49) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 55) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/badge_story.rs
type BadgeStory (line 12) | pub struct BadgeStory {
method new (line 17) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 23) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 29) | fn title() -> &'static str {
method description (line 33) | fn description() -> &'static str {
method new_view (line 37) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 41) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 47) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 53) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/breadcrumb_story.rs
type BreadcrumbStory (line 13) | pub struct BreadcrumbStory {
method new (line 19) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 26) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 32) | fn title() -> &'static str {
method description (line 36) | fn description() -> &'static str {
method new_view (line 40) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 46) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 52) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/button_story.rs
type ButtonAction (line 20) | enum ButtonAction {
type ButtonStory (line 27) | pub struct ButtonStory {
method view (line 37) | pub fn view(_: &mut Window, cx: &mut App) -> Entity<Self> {
method on_click (line 48) | fn on_click(ev: &ClickEvent, _: &mut Window, _: &mut App) {
method on_hover (line 52) | fn on_hover(hovered: &bool, _: &mut Window, _: &mut App) {
method title (line 58) | fn title() -> &'static str {
method description (line 62) | fn description() -> &'static str {
method closable (line 66) | fn closable() -> bool {
method new_view (line 70) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 76) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 82) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/calendar_story.rs
type CalendarStory (line 12) | pub struct CalendarStory {
method title (line 20) | fn title() -> &'static str {
method description (line 24) | fn description() -> &'static str {
method new_view (line 28) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 34) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 38) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 54) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 60) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/chart_story/chart_story.rs
type MonthlyDevice (line 19) | struct MonthlyDevice {
method color (line 26) | pub fn color(&self, color: Hsla) -> Hsla {
type DailyDevice (line 32) | pub struct DailyDevice {
type StockPrice (line 41) | pub struct StockPrice {
type ChartStory (line 49) | pub struct ChartStory {
method new (line 57) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 79) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 85) | fn title() -> &'static str {
method description (line 89) | fn description() -> &'static str {
method new_view (line 93) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 97) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 103) | fn focus_handle(&self, _: &App) -> FocusHandle {
function chart_container (line 108) | fn chart_container(
method render (line 152) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/chart_story/stacked_bar_chart.rs
type StackedBarChart (line 16) | pub struct StackedBarChart {
method new (line 22) | pub fn new(data: Vec<DailyDevice>) -> Self {
method paint (line 41) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/story/src/stories/checkbox_story.rs
type CheckboxStory (line 12) | pub struct CheckboxStory {
method title (line 22) | fn title() -> &'static str {
method description (line 26) | fn description() -> &'static str {
method new_view (line 30) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 36) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 40) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 53) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 59) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/clipboard_story.rs
type ClipboardStory (line 17) | pub struct ClipboardStory {
method title (line 24) | fn title() -> &'static str {
method description (line 28) | fn description() -> &'static str {
method new_view (line 32) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 38) | pub(crate) fn new(window: &mut Window, cx: &mut App) -> Self {
method view (line 49) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 54) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 59) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/collapsible_story.rs
type CollapsibleStory (line 20) | pub struct CollapsibleStory {
method title (line 27) | fn title() -> &'static str {
method description (line 31) | fn description() -> &'static str {
method new_view (line 35) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 41) | pub(crate) fn new(_: &mut Window, cx: &mut App) -> Self {
method view (line 49) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 55) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 61) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/color_picker_story.rs
type ColorPickerStory (line 13) | pub struct ColorPickerStory {
method title (line 20) | fn title() -> &'static str {
method description (line 24) | fn description() -> &'static str {
method new_view (line 28) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 34) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 38) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 57) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 63) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/data_table_story.rs
type ChangeSize (line 30) | struct ChangeSize(Size);
type OpenDetail (line 34) | struct OpenDetail(usize);
type Counter (line 37) | struct Counter {
method random (line 48) | fn random() -> Self {
method symbol_code (line 54) | fn symbol_code(&self) -> SharedString {
type Stock (line 60) | struct Stock {
method random_update (line 107) | fn random_update(&mut self) {
function random_stocks (line 127) | fn random_stocks(size: usize) -> Vec<Stock> {
type StockTableDelegate (line 185) | struct StockTableDelegate {
method new (line 201) | fn new(size: usize) -> Self {
method update_stocks (line 273) | fn update_stocks(&mut self, size: usize) {
method render_percent (line 286) | fn render_percent(&self, col: &Column, val: f64, cx: &mut App) -> AnyE...
method render_value_cell (line 306) | fn render_value_cell(&self, col: &Column, val: f64, cx: &mut App) -> A...
method columns_count (line 326) | fn columns_count(&self, _: &App) -> usize {
method rows_count (line 330) | fn rows_count(&self, _: &App) -> usize {
method column (line 334) | fn column(&self, col_ix: usize, _cx: &App) -> Column {
method render_th (line 338) | fn render_th(
method context_menu (line 353) | fn context_menu(
method render_tr (line 368) | fn render_tr(
method render_td (line 390) | fn render_td(
method move_column (line 462) | fn move_column(
method perform_sort (line 473) | fn perform_sort(
method loading (line 501) | fn loading(&self, _: &App) -> bool {
method has_more (line 505) | fn has_more(&self, _: &App) -> bool {
method load_more_threshold (line 516) | fn load_more_threshold(&self) -> usize {
method load_more (line 520) | fn load_more(&mut self, _: &mut Window, cx: &mut Context<TableState<Self...
method visible_rows_changed (line 541) | fn visible_rows_changed(
method visible_columns_changed (line 550) | fn visible_columns_changed(
method cell_text (line 559) | fn cell_text(&self, row_ix: usize, col_ix: usize, _cx: &App) -> String {
type DataTableStory (line 618) | pub struct DataTableStory {
method title (line 630) | fn title() -> &'static str {
method description (line 634) | fn description() -> &'static str {
method new_view (line 638) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method closable (line 642) | fn closable() -> bool {
method view (line 654) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 658) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_num_stocks_input_change (line 715) | fn on_num_stocks_input_change(
method toggle_loop_selection (line 741) | fn toggle_loop_selection(&mut self, checked: &bool, _: &mut Window, cx...
method toggle_col_resize (line 748) | fn toggle_col_resize(&mut self, checked: &bool, _: &mut Window, cx: &m...
method toggle_col_order (line 755) | fn toggle_col_order(&mut self, checked: &bool, _: &mut Window, cx: &mu...
method toggle_col_sort (line 762) | fn toggle_col_sort(&mut self, checked: &bool, _: &mut Window, cx: &mut...
method toggle_col_fixed (line 769) | fn toggle_col_fixed(&mut self, checked: &bool, _: &mut Window, cx: &mu...
method toggle_col_selection (line 776) | fn toggle_col_selection(&mut self, checked: &bool, _: &mut Window, cx:...
method toggle_row_selection (line 783) | fn toggle_row_selection(&mut self, checked: &bool, _: &mut Window, cx:...
method toggle_cell_selection (line 790) | fn toggle_cell_selection(&mut self, checked: &bool, _: &mut Window, cx...
method toggle_stripe (line 797) | fn toggle_stripe(&mut self, checked: &bool, _: &mut Window, cx: &mut C...
method on_change_size (line 802) | fn on_change_size(&mut self, a: &ChangeSize, _: &mut Window, cx: &mut ...
method toggle_refresh_data (line 807) | fn toggle_refresh_data(&mut self, checked: &bool, _: &mut Window, cx: ...
method on_table_event (line 812) | fn on_table_event(
method dump_csv (line 845) | fn dump_csv(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut C...
method write_csv (line 875) | fn write_csv(&mut self, cx: &mut Context<Self>) -> anyhow::Result<Stri...
method focus_handle (line 648) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 899) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl gpu...
FILE: crates/story/src/stories/date_picker_story.rs
type DatePickerStory (line 14) | pub struct DatePickerStory {
method title (line 27) | fn title() -> &'static str {
method description (line 31) | fn description() -> &'static str {
method new_view (line 35) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 41) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 45) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 126) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 132) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/description_list_story.rs
type ChangeSize (line 20) | struct ChangeSize(Size);
type DescriptionListStory (line 22) | pub struct DescriptionListStory {
method new (line 31) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 74) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method set_layout (line 78) | fn set_layout(&mut self, layout: Axis, cx: &mut Context<Self>) {
method set_bordered (line 83) | fn set_bordered(&mut self, bordered: bool, cx: &mut Context<Self>) {
method on_change_size (line 88) | fn on_change_size(&mut self, a: &ChangeSize, _: &mut Window, cx: &mut ...
method title (line 95) | fn title() -> &'static str {
method description (line 99) | fn description() -> &'static str {
method new_view (line 103) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 107) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 113) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 119) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/dialog_story.rs
type DialogStory (line 25) | pub struct DialogStory {
method title (line 87) | fn title() -> &'static str {
method description (line 91) | fn description() -> &'static str {
method new_view (line 95) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 101) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 105) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_action_test_action (line 137) | fn on_action_test_action(
method render_basic_dialog (line 146) | fn render_basic_dialog(&self, cx: &mut Context<Self>) -> impl IntoElem...
method render_focus_back_test (line 241) | fn render_focus_back_test(&self, _cx: &mut Context<Self>) -> impl Into...
method render_dialog_without_title (line 258) | fn render_dialog_without_title(&self, cx: &mut Context<Self>) -> impl ...
method render_custom_buttons (line 276) | fn render_custom_buttons(&self, cx: &mut Context<Self>) -> impl IntoEl...
method render_scrollable_dialog (line 334) | fn render_scrollable_dialog(&self, cx: &mut Context<Self>) -> impl Int...
method render_table_in_dialog (line 368) | fn render_table_in_dialog(&self, cx: &mut Context<Self>) -> impl IntoE...
method render_custom_paddings (line 398) | fn render_custom_paddings(&self, cx: &mut Context<Self>) -> impl IntoE...
method render_custom_style (line 414) | fn render_custom_style(&self, cx: &mut Context<Self>) -> impl IntoElem...
method render_dialog_with_content (line 431) | fn render_dialog_with_content(&self, cx: &mut Context<Self>) -> impl I...
type MyTable (line 39) | struct MyTable {
method new (line 43) | fn new(_: &mut App) -> Self {
method columns_count (line 56) | fn columns_count(&self, _: &App) -> usize {
method rows_count (line 60) | fn rows_count(&self, _: &App) -> usize {
method column (line 64) | fn column(&self, col_ix: usize, _: &App) -> Column {
method render_td (line 68) | fn render_td(
method focus_handle (line 482) | fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
method render (line 488) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/divider_story.rs
constant DESCRIPTION (line 8) | const DESCRIPTION: &str = "GPUI Component is a Rust GUI components for b...
type DividerStory (line 10) | pub struct DividerStory {
method title (line 15) | fn title() -> &'static str {
method description (line 19) | fn description() -> &'static str {
method new_view (line 23) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 29) | pub fn view(_window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 37) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 43) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/dropdown_button_story.rs
type ButtonAction (line 17) | enum ButtonAction {
type DropdownButtonStory (line 24) | pub struct DropdownButtonStory {
method view (line 33) | pub fn view(_: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 45) | fn title() -> &'static str {
method description (line 49) | fn description() -> &'static str {
method closable (line 53) | fn closable() -> bool {
method new_view (line 57) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 63) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 69) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/editor_story.rs
constant EXAMPLE_CODE (line 5) | const EXAMPLE_CODE: &str = include_str!("./editor_story.rs");
type EditorStory (line 7) | pub struct EditorStory {
method title (line 12) | fn title() -> &'static str {
method description (line 16) | fn description() -> &'static str {
method closable (line 20) | fn closable() -> bool {
method new_view (line 24) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 30) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 34) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method render (line 51) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/form_story.rs
type FormStory (line 20) | pub struct FormStory {
method title (line 35) | fn title() -> &'static str {
method description (line 39) | fn description() -> &'static str {
method closable (line 43) | fn closable() -> bool {
method new_view (line 47) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 53) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 57) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 102) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 108) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/group_box_story.rs
type GroupBoxStory (line 20) | pub struct GroupBoxStory {
method title (line 25) | fn title() -> &'static str {
method description (line 29) | fn description() -> &'static str {
method new_view (line 34) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 40) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 44) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 52) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 58) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/hover_card_story.rs
type HoverCardStory (line 13) | pub struct HoverCardStory {}
method new (line 16) | fn new(_: &mut Window, _: &mut Context<Self>) -> Self {
method view (line 20) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method render_basic_example (line 38) | fn render_basic_example(&self, cx: &mut Context<Self>) -> impl IntoEle...
method render_user_profile_example (line 68) | fn render_user_profile_example(&self, cx: &mut Context<Self>) -> impl ...
method render_custom_timing_example (line 109) | fn render_custom_timing_example(&self, _: &mut Context<Self>) -> impl ...
method render_positioning_examples (line 131) | fn render_positioning_examples(&self, _: &mut Context<Self>) -> impl I...
method render (line 26) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
method title (line 187) | fn title() -> &'static str {
method description (line 191) | fn description() -> &'static str {
method new_view (line 195) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
FILE: crates/story/src/stories/icon_story.rs
type IconStory (line 13) | pub struct IconStory {
method new (line 18) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 24) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 30) | fn title() -> &'static str {
method description (line 34) | fn description() -> &'static str {
method new_view (line 38) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 42) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 48) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 54) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/image_story.rs
type ImageStory (line 8) | pub struct ImageStory {
method title (line 13) | fn title() -> &'static str {
method description (line 17) | fn description() -> &'static str {
method new_view (line 21) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 25) | fn zoomable() -> Option<PanelControl> {
method new (line 31) | pub fn new(_: &mut Window, cx: &mut App) -> Self {
method view (line 37) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 43) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 49) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/input_story.rs
constant CODE_EXAMPLE (line 9) | const CODE_EXAMPLE: &str = r#"{"single_line":"code editor"}"#;
function init (line 11) | pub fn init(_: &mut App) {}
type InputStory (line 13) | pub struct InputStory {
method title (line 36) | fn title() -> &'static str {
method closable (line 40) | fn closable() -> bool {
method new_view (line 44) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 50) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 54) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_input_event (line 150) | fn on_input_event(
method on_click_reset (line 175) | fn on_click_reset(&mut self, _: &ClickEvent, window: &mut Window, cx: ...
method render (line 183) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
FILE: crates/story/src/stories/kbd_story.rs
type KbdStory (line 10) | pub struct KbdStory {
method title (line 15) | fn title() -> &'static str {
method description (line 19) | fn description() -> &'static str {
method new_view (line 23) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 29) | pub(crate) fn new(_: &mut Window, cx: &mut App) -> Self {
method view (line 35) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 40) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 45) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/label_story.rs
type LabelStory (line 18) | pub struct LabelStory {
method title (line 28) | fn title() -> &'static str {
method description (line 32) | fn description() -> &'static str {
method new_view (line 36) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 42) | pub(crate) fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 69) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method on_click (line 74) | fn on_click(checked: &bool, window: &mut Window, cx: &mut App) {
method highlights_text (line 78) | fn highlights_text(&self) -> HighlightsMatch {
method focus_handle (line 87) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 92) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/list_story.rs
type Company (line 23) | struct Company {
method prepare (line 37) | fn prepare(mut self) -> Self {
type CompanyListItem (line 47) | struct CompanyListItem {
method new (line 54) | pub fn new(id: impl Into<ElementId>, company: Rc<Company>, selected: b...
method selected (line 64) | fn selected(mut self, selected: bool) -> Self {
method is_selected (line 69) | fn is_selected(&self) -> bool {
method render (line 75) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
type CompanyListDelegate (line 137) | struct CompanyListDelegate {
method prepare (line 150) | fn prepare(&mut self, query: impl Into<SharedString>) {
method extend_more (line 173) | fn extend_more(&mut self, len: usize) {
method selected_company (line 179) | fn selected_company(&self) -> Option<Rc<Company>> {
type Item (line 192) | type Item = CompanyListItem;
method sections_count (line 194) | fn sections_count(&self, _: &App) -> usize {
method items_count (line 198) | fn items_count(&self, section: usize, _: &App) -> usize {
method perform_search (line 207) | fn perform_search(
method confirm (line 217) | fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Con...
method set_selected_index (line 222) | fn set_selected_index(
method set_right_clicked_index (line 232) | fn set_right_clicked_index(
method render_section_header (line 241) | fn render_section_header(
method render_section_footer (line 264) | fn render_section_footer(
method render_item (line 288) | fn render_item(
method loading (line 302) | fn loading(&self, _: &App) -> bool {
method has_more (line 306) | fn has_more(&self, _: &App) -> bool {
method load_more_threshold (line 314) | fn load_more_threshold(&self) -> usize {
method load_more (line 318) | fn load_more(&mut self, window: &mut Window, cx: &mut Context<ListState<...
type ListStory (line 341) | pub struct ListStory {
method title (line 351) | fn title() -> &'static str {
method description (line 355) | fn description() -> &'static str {
method new_view (line 359) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 365) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 369) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method selected_company (line 432) | fn selected_company(&mut self, _: &SelectedCompany, _: &mut Window, cx...
method toggle_selectable (line 439) | fn toggle_selectable(&mut self, selectable: bool, _: &mut Window, cx: ...
method toggle_searchable (line 446) | fn toggle_searchable(&mut self, searchable: bool, _: &mut Window, cx: ...
function random_company (line 454) | fn random_company() -> Company {
method focus_handle (line 471) | fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
method render (line 477) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/menu_story.rs
type Info (line 18) | struct Info(usize);
constant CONTEXT (line 22) | const CONTEXT: &str = "menu_story";
function init (line 23) | pub fn init(cx: &mut App) {
type MenuStory (line 45) | pub struct MenuStory {
method title (line 51) | fn title() -> &'static str {
method description (line 55) | fn description() -> &'static str {
method new_view (line 59) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 65) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 69) | fn new(_: &mut Window, _: &mut Context<Self>) -> Self {
method on_copy (line 76) | fn on_copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
method on_cut (line 81) | fn on_cut(&mut self, _: &Cut, _: &mut Window, cx: &mut Context<Self>) {
method on_paste (line 86) | fn on_paste(&mut self, _: &Paste, _: &mut Window, cx: &mut Context<Sel...
method on_search_all (line 91) | fn on_search_all(&mut self, _: &SearchAll, _: &mut Window, cx: &mut Co...
method on_action_info (line 96) | fn on_action_info(&mut self, info: &Info, _: &mut Window, cx: &mut Con...
method on_action_toggle_check (line 101) | fn on_action_toggle_check(&mut self, _: &ToggleCheck, _: &mut Window, ...
method render (line 116) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/mod.rs
function init (line 125) | pub(crate) fn init(cx: &mut App) {
type Story (line 138) | pub trait Story: Render + Sized {
method klass (line 139) | fn klass() -> &'static str {
method title (line 143) | fn title() -> &'static str;
method description (line 145) | fn description() -> &'static str {
method closable (line 149) | fn closable() -> bool {
method zoomable (line 153) | fn zoomable() -> Option<PanelControl> {
method title_bg (line 157) | fn title_bg() -> Option<Hsla> {
method paddings (line 161) | fn paddings() -> Pixels {
method new_view (line 165) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render>;
method on_active (line 167) | fn on_active(&mut self, active: bool, window: &mut Window, cx: &mut Ap...
method on_active_any (line 173) | fn on_active_any(view: AnyView, active: bool, window: &mut Window, cx:...
FILE: crates/story/src/stories/notification_story.rs
constant NOTIFICATION_MARKDOWN (line 18) | const NOTIFICATION_MARKDOWN: &str = r#"
type NotificationStory (line 25) | pub struct NotificationStory {
method title (line 30) | fn title() -> &'static str {
method description (line 34) | fn description() -> &'static str {
method new_view (line 38) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 44) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 48) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 56) | fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
method render (line 62) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/number_input_story.rs
function init (line 15) | pub fn init(_: &mut App) {}
type NumberInputStory (line 17) | pub struct NumberInputStory {
method title (line 32) | fn title() -> &'static str {
method description (line 36) | fn description() -> &'static str {
method closable (line 40) | fn closable() -> bool {
method new_view (line 44) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 50) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 54) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_input_event (line 119) | fn on_input_event(
method on_number_input_event (line 152) | fn on_number_input_event(
method focus_handle (line 213) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 219) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/otp_input_story.rs
function init (line 15) | pub fn init(_: &mut App) {}
type OtpInputStory (line 17) | pub struct OtpInputStory {
method title (line 30) | fn title() -> &'static str {
method description (line 34) | fn description() -> &'static str {
method closable (line 38) | fn closable() -> bool {
method new_view (line 42) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 48) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 52) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method toggle_opt_masked (line 94) | fn toggle_opt_masked(&mut self, _: &bool, window: &mut Window, cx: &mu...
method focus_handle (line 115) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 121) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/pagination_story.rs
type PaginationStory (line 14) | pub struct PaginationStory {
method title (line 23) | fn title() -> &'static str {
method description (line 27) | fn description() -> &'static str {
method new_view (line 31) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 37) | pub fn view(_window: &mut Window, cx: &mut App) -> Entity<Self> {
method set_size (line 47) | fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Se...
method focus_handle (line 54) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 60) | fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> im...
FILE: crates/story/src/stories/popover_story.rs
type Info (line 22) | struct Info(usize);
constant CONTEXT (line 25) | const CONTEXT: &str = "popover-story";
function init (line 26) | pub fn init(cx: &mut App) {
type Form (line 47) | struct Form {
method new (line 53) | fn new(parent: Entity<PopoverStory>, window: &mut Window, cx: &mut App...
method focus_handle (line 62) | fn focus_handle(&self, cx: &App) -> FocusHandle {
type DropdownListDelegate (line 67) | struct DropdownListDelegate {
type Item (line 71) | type Item = ListItem;
method items_count (line 73) | fn items_count(&self, _: usize, _: &App) -> usize {
method render_item (line 77) | fn render_item(
method set_selected_index (line 86) | fn set_selected_index(
method confirm (line 94) | fn confirm(&mut self, _: bool, _: &mut Window, cx: &mut Context<ListStat...
method cancel (line 101) | fn cancel(&mut self, _: &mut Window, cx: &mut Context<ListState<Self>>) {
method render (line 112) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
type PopoverStory (line 135) | pub struct PopoverStory {
method title (line 146) | fn title() -> &'static str {
method description (line 150) | fn description() -> &'static str {
method new_view (line 154) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 160) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 164) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_copy (line 183) | fn on_copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
method on_cut (line 188) | fn on_cut(&mut self, _: &Cut, _: &mut Window, cx: &mut Context<Self>) {
method on_paste (line 193) | fn on_paste(&mut self, _: &Paste, _: &mut Window, cx: &mut Context<Sel...
method on_search_all (line 198) | fn on_search_all(&mut self, _: &SearchAll, _: &mut Window, cx: &mut Co...
method on_action_info (line 203) | fn on_action_info(&mut self, info: &Info, _: &mut Window, cx: &mut Con...
method on_action_toggle_check (line 208) | fn on_action_toggle_check(&mut self, _: &ToggleCheck, _: &mut Window, ...
method focus_handle (line 216) | fn focus_handle(&self, _cx: &App) -> FocusHandle {
method render (line 222) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/progress_story.rs
type ProgressStory (line 16) | pub struct ProgressStory {
method title (line 23) | fn title() -> &'static str {
method description (line 27) | fn description() -> &'static str {
method new_view (line 31) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 37) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 41) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method set_value (line 49) | pub fn set_value(&mut self, value: f32) {
method start_animation (line 53) | fn start_animation(&mut self, cx: &mut Context<Self>) {
method focus_handle (line 85) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 91) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/radio_story.rs
type RadioStory (line 14) | pub struct RadioStory {
method title (line 22) | fn title() -> &'static str {
method description (line 26) | fn description() -> &'static str {
method new_view (line 30) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 36) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 40) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 51) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 57) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/rating_story.rs
type RatingStory (line 14) | pub struct RatingStory {
method title (line 21) | fn title() -> &'static str {
method description (line 25) | fn description() -> &'static str {
method new_view (line 29) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 35) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 39) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 49) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
function init (line 54) | pub fn init(_cx: &mut App) {
method render (line 59) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/resizable_story.rs
type ResizableStory (line 11) | pub struct ResizableStory {
method title (line 16) | fn title() -> &'static str {
method description (line 20) | fn description() -> &'static str {
method new_view (line 24) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 36) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 40) | fn new(_: &mut Window, cx: &mut App) -> Self {
method focus_handle (line 30) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
function panel_box (line 47) | fn panel_box(content: impl Into<SharedString>, _: &App) -> AnyElement {
method render (line 56) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/scrollbar_story.rs
type ScrollbarStory (line 15) | pub struct ScrollbarStory {
method new (line 27) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 45) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method change_test_cases (line 49) | pub fn change_test_cases(&mut self, n: usize, cx: &mut Context<Self>) {
method render_buttons (line 74) | fn render_buttons(&mut self, cx: &mut Context<Self>) -> impl IntoEleme...
method title (line 117) | fn title() -> &'static str {
method description (line 121) | fn description() -> &'static str {
method new_view (line 125) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
constant ITEM_HEIGHT (line 24) | const ITEM_HEIGHT: Pixels = px(50.);
method focus_handle (line 131) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 137) | fn render(
FILE: crates/story/src/stories/select_story.rs
function init (line 8) | pub fn init(_: &mut App) {}
type Country (line 11) | struct Country {
method letter_prefix (line 17) | pub fn letter_prefix(&self) -> char {
type Value (line 23) | type Value = SharedString;
method title (line 25) | fn title(&self) -> SharedString {
method display_title (line 29) | fn display_title(&self) -> Option<gpui::AnyElement> {
method value (line 33) | fn value(&self) -> &Self::Value {
type SelectStory (line 38) | pub struct SelectStory {
method title (line 51) | fn title() -> &'static str {
method description (line 55) | fn description() -> &'static str {
method new_view (line 59) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 71) | fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
method view (line 158) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method on_select_event (line 162) | fn on_select_event(
method toggle_disabled (line 174) | fn toggle_disabled(&mut self, disabled: bool, _: &mut Window, cx: &mut...
method focus_handle (line 65) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 181) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/settings_story.rs
type AppSettings (line 20) | struct AppSettings {
method global (line 49) | fn global(cx: &App) -> &AppSettings {
method global_mut (line 53) | pub fn global_mut(cx: &mut App) -> &mut AppSettings {
method default (line 32) | fn default() -> Self {
type SettingsStory (line 58) | pub struct SettingsStory {
method title (line 93) | fn title() -> &'static str {
method description (line 97) | fn description() -> &'static str {
method new_view (line 101) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method paddings (line 105) | fn paddings() -> gpui::Pixels {
method view (line 111) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 115) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method setting_pages (line 125) | fn setting_pages(&self, _: &mut Window, cx: &mut Context<Self>) -> Vec...
type OpenURLSettingField (line 64) | struct OpenURLSettingField {
method new (line 70) | fn new(label: impl Into<SharedString>, url: impl Into<SharedString>) -...
type Element (line 79) | type Element = Button;
method render_field (line 80) | fn render_field(&self, options: &RenderOptions, _: &mut Window, _: &mut ...
method focus_handle (line 423) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 429) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
FILE: crates/story/src/stories/sheet_story.rs
type ListItemDeletegate (line 24) | pub struct ListItemDeletegate {
type Item (line 33) | type Item = ListItem;
method items_count (line 35) | fn items_count(&self, _: usize, _: &App) -> usize {
method perform_search (line 39) | fn perform_search(
method render_item (line 65) | fn render_item(
method render_empty (line 97) | fn render_empty(
method cancel (line 113) | fn cancel(&mut self, window: &mut Window, cx: &mut Context<ListState<Sel...
method confirm (line 119) | fn confirm(&mut self, _secondary: bool, _: &mut Window, cx: &mut Context...
method set_selected_index (line 130) | fn set_selected_index(
type SheetStory (line 144) | pub struct SheetStory {
method view (line 171) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 175) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method open_sheet_at (line 259) | fn open_sheet_at(&mut self, placement: Placement, window: &mut Window,...
method close_sheet (line 335) | fn close_sheet(&mut self, _: &mut Window, cx: &mut Context<Self>) {
method on_action_test_action (line 340) | fn on_action_test_action(
method title (line 157) | fn title() -> &'static str {
method description (line 161) | fn description() -> &'static str {
method new_view (line 165) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 351) | fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
method render (line 357) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/sidebar_story.rs
type SelectCompany (line 26) | pub struct SelectCompany(SharedString);
type SidebarStory (line 28) | pub struct SidebarStory {
method view (line 40) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 44) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method render_content (line 60) | fn render_content(&mut self, _: &mut Window, cx: &mut Context<Self>) -...
method switch_checked_handler (line 85) | fn switch_checked_handler(
method title (line 244) | fn title() -> &'static str {
method description (line 248) | fn description() -> &'static str {
method new_view (line 252) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
type Item (line 96) | enum Item {
method label (line 125) | pub fn label(&self) -> &'static str {
method is_disabled (line 137) | pub fn is_disabled(&self) -> bool {
method icon (line 144) | pub fn icon(&self) -> IconName {
method handler (line 156) | pub fn handler(
method items (line 174) | pub fn items(&self) -> Vec<SubItem> {
type SubItem (line 107) | enum SubItem {
method label (line 196) | pub fn label(&self) -> &'static str {
method is_disabled (line 215) | pub fn is_disabled(&self) -> bool {
method handler (line 222) | pub fn handler(
method focus_handle (line 258) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 264) | fn render(
FILE: crates/story/src/stories/skeleton_story.rs
type SkeletonStory (line 9) | pub struct SkeletonStory {
method title (line 15) | fn title() -> &'static str {
method description (line 19) | fn description() -> &'static str {
method new_view (line 23) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 29) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 33) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method set_value (line 40) | pub fn set_value(&mut self, value: f32) {
method focus_handle (line 46) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 52) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/slider_story.rs
type SliderStory (line 16) | pub struct SliderStory {
method title (line 32) | fn title() -> &'static str {
method description (line 36) | fn description() -> &'static str {
method new_view (line 40) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 46) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 50) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 178) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 184) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/spinner_story.rs
type SpinnerStory (line 9) | pub struct SpinnerStory {
method title (line 15) | fn title() -> &'static str {
method description (line 19) | fn description() -> &'static str {
method new_view (line 23) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 29) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 33) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method set_value (line 40) | pub fn set_value(&mut self, value: f32) {
method focus_handle (line 46) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 52) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/stepper_story.rs
type StepperStory (line 16) | pub struct StepperStory {
method title (line 28) | fn title() -> &'static str {
method description (line 32) | fn description() -> &'static str {
method new_view (line 36) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 42) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 46) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 61) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 67) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/switch_story.rs
type SwitchStory (line 12) | pub struct SwitchStory {
method title (line 20) | fn title() -> &'static str {
method description (line 24) | fn description() -> &'static str {
method new_view (line 28) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 34) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 38) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method focus_handle (line 49) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 55) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/table_story.rs
type TableStory (line 18) | pub struct TableStory {
method new (line 24) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 31) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method set_size (line 35) | fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Se...
method title (line 42) | fn title() -> &'static str {
method description (line 46) | fn description() -> &'static str {
method new_view (line 50) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 56) | fn focus_handle(&self, _: &App) -> FocusHandle {
function status_tag (line 61) | fn status_tag(status: &str) -> Tag {
method render (line 72) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/tabs_story.rs
type TabsStory (line 17) | pub struct TabsStory {
method title (line 25) | fn title() -> &'static str {
method description (line 29) | fn description() -> &'static str {
method new_view (line 33) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 39) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 43) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method set_active_tab (line 52) | fn set_active_tab(&mut self, ix: usize, _: &mut Window, cx: &mut Conte...
method set_size (line 57) | fn set_size(&mut self, size: Size, _: &mut Window, cx: &mut Context<Se...
method focus_handle (line 64) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 70) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/tag_story.rs
type TagStory (line 10) | pub struct TagStory {
method title (line 15) | fn title() -> &'static str {
method description (line 19) | fn description() -> &'static str {
method new_view (line 23) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method new (line 29) | pub(crate) fn new(_: &mut Window, cx: &mut App) -> Self {
method view (line 35) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method focus_handle (line 40) | fn focus_handle(&self, _: &App) -> FocusHandle {
method render (line 45) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
FILE: crates/story/src/stories/textarea_story.rs
function init (line 15) | pub fn init(_: &mut App) {}
type TextareaStory (line 17) | pub struct TextareaStory {
method title (line 25) | fn title() -> &'static str {
method description (line 29) | fn description() -> &'static str {
method closable (line 33) | fn closable() -> bool {
method new_view (line 37) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 43) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 47) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method on_insert_text_to_textarea (line 119) | fn on_insert_text_to_textarea(
method on_replace_text_to_textarea (line 130) | fn on_replace_text_to_textarea(
method focus_handle (line 143) | fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
method render (line 149) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/theme_story/checkerboard.rs
type Checkerboard (line 5) | pub struct Checkerboard {
method new (line 11) | pub fn new(is_dark: bool) -> Self {
method extend (line 20) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method render (line 26) | fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/story/src/stories/theme_story/color_theme_story.rs
type ColorEntry (line 21) | struct ColorEntry {
type ColorCategory (line 29) | struct ColorCategory {
type ThemeItem (line 35) | struct ThemeItem {
method new (line 41) | fn new(name: impl Into<SharedString>, is_active: bool) -> Self {
type Value (line 50) | type Value = SharedString;
method title (line 52) | fn title(&self) -> SharedString {
method value (line 56) | fn value(&self) -> &Self::Value {
method render (line 60) | fn render(&self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
type ThemeColorsStory (line 81) | pub struct ThemeColorsStory {
method title (line 94) | fn title() -> &'static str {
method description (line 98) | fn description() -> &'static str {
method new_view (line 104) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method view (line 110) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 114) | fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method get_theme_colors (line 172) | fn get_theme_colors(&self, cx: &Context<Self>) -> ThemeColor {
method get_isolated_theme (line 195) | fn get_isolated_theme(&self, cx: &App) -> (ThemeColor, bool) {
method compute_categories (line 227) | fn compute_categories(&mut self, cx: &Context<Self>) {
method render_color_swatch (line 287) | fn render_color_swatch(
method render_left_panel (line 372) | fn render_left_panel(&self, _: &mut Window, cx: &mut Context<Self>) ->...
method render_right_panel (line 489) | fn render_right_panel(&self, window: &mut Window, cx: &mut Context<Sel...
function format_colors (line 565) | fn format_colors(
function hsla_to_hex (line 643) | fn hsla_to_hex(color: Hsla) -> String {
function colors_equal_u8 (line 664) | fn colors_equal_u8(c1: Hsla, c2: Hsla) -> bool {
function filter_categories (line 672) | fn filter_categories(
method render (line 698) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
FILE: crates/story/src/stories/theme_story/mapper.rs
type ParsedKey (line 29) | pub struct ParsedKey {
function parse_theme_key (line 36) | pub fn parse_theme_key(key: &str) -> ParsedKey {
function to_title_case (line 199) | fn to_title_case(s: &str) -> String {
function to_title_case_full (line 207) | fn to_title_case_full(s: &str) -> String {
FILE: crates/story/src/stories/toggle_story.rs
type ToggleStory (line 14) | pub struct ToggleStory {
method view (line 21) | pub fn view(_: &mut Window, cx: &mut App) -> Entity<Self> {
method title (line 31) | fn title() -> &'static str {
method description (line 35) | fn description() -> &'static str {
method closable (line 39) | fn closable() -> bool {
method new_view (line 43) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method focus_handle (line 49) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 55) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/story/src/stories/tooltip_story.rs
function init (line 22) | pub fn init(cx: &mut App) {
type TooltipStory (line 26) | pub struct TooltipStory {
method view (line 31) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 35) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method title (line 43) | fn title() -> &'static str {
method new_view (line 47) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 51) | fn zoomable() -> Option<PanelControl> {
method focus_handle (line 57) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 63) | fn render(
FILE: crates/story/src/stories/tree_story.rs
constant CONTEXT (line 25) | const CONTEXT: &str = "TreeStory";
function init (line 26) | pub(crate) fn init(cx: &mut App) {
type TreeStory (line 30) | pub struct TreeStory {
method view (line 69) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method load_files (line 73) | fn load_files(state: Entity<TreeState>, path: PathBuf, cx: &mut Contex...
method new (line 89) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method on_action_rename (line 100) | fn on_action_rename(&mut self, _: &Rename, _: &mut Window, cx: &mut gp...
function build_file_items (line 35) | fn build_file_items(ignorer: &Ignorer, root: &PathBuf, path: &PathBuf) -...
method title (line 110) | fn title() -> &'static str {
method new_view (line 114) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 118) | fn zoomable() -> Option<PanelControl> {
method render (line 124) | fn render(
FILE: crates/story/src/stories/virtual_list_story.rs
type VirtualListStory (line 16) | pub struct VirtualListStory {
method new (line 30) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method view (line 46) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method change_test_cases (line 50) | pub fn change_test_cases(&mut self, n: usize, cx: &mut Context<Self>) {
method change_axis (line 72) | pub fn change_axis(&mut self, axis: ScrollbarAxis, cx: &mut Context<Se...
method render_buttons (line 77) | fn render_buttons(&mut self, cx: &mut Context<Self>) -> impl IntoEleme...
method title (line 205) | fn title() -> &'static str {
method description (line 209) | fn description() -> &'static str {
method new_view (line 214) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
constant ITEM_SIZE (line 27) | const ITEM_SIZE: Size<Pixels> = size(px(100.), px(30.));
method focus_handle (line 220) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 226) | fn render(
FILE: crates/story/src/stories/welcome_story.rs
type WelcomeStory (line 9) | pub struct WelcomeStory {
method view (line 14) | pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
method new (line 18) | fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method title (line 26) | fn title() -> &'static str {
method description (line 30) | fn description() -> &'static str {
method new_view (line 34) | fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
method zoomable (line 38) | fn zoomable() -> Option<PanelControl> {
method paddings (line 42) | fn paddings() -> gpui::Pixels {
method focus_handle (line 48) | fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
method render (line 54) | fn render(
FILE: crates/story/src/themes.rs
constant STATE_FILE (line 11) | const STATE_FILE: &str = "target/state.json";
type State (line 14) | struct State {
method default (line 20) | fn default() -> Self {
function init (line 28) | pub fn init(cx: &mut App) {
type SwitchTheme (line 101) | pub(crate) struct SwitchTheme(pub(crate) SharedString);
type SwitchThemeMode (line 105) | pub(crate) struct SwitchThemeMode(pub(crate) ThemeMode);
FILE: crates/story/src/title_bar.rs
type AppTitleBar (line 19) | pub struct AppTitleBar {
method new (line 27) | pub fn new(
method child (line 43) | pub fn child<F, E>(mut self, f: F) -> Self
method render (line 54) | fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> imp...
type FontSizeSelector (line 99) | struct FontSizeSelector {
method new (line 104) | pub fn new(_: &mut Window, cx: &mut Context<Self>) -> Self {
method on_select_font (line 110) | fn on_select_font(
method on_select_radius (line 120) | fn on_select_radius(
method on_select_scrollbar_show (line 135) | fn on_select_scrollbar_show(
method on_toggle_list_active_highlight (line 145) | fn on_toggle_list_active_highlight(
method render (line 158) | fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl Int...
FILE: crates/ui/build.rs
function main (line 3) | fn main() {
FILE: crates/ui/src/accordion.rs
type Accordion (line 13) | pub struct Accordion {
method new (line 25) | pub fn new(id: impl Into<ElementId>) -> Self {
method multiple (line 38) | pub fn multiple(mut self, multiple: bool) -> Self {
method bordered (line 44) | pub fn bordered(mut self, bordered: bool) -> Self {
method disabled (line 50) | pub fn disabled(mut self, disabled: bool) -> Self {
method item (line 56) | pub fn item<F>(mut self, child: F) -> Self
method on_toggle_click (line 68) | pub fn on_toggle_click(
method with_size (line 78) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method render (line 85) | fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
type AccordionItem (line 139) | pub struct AccordionItem {
method new (line 153) | pub fn new() -> Self {
method icon (line 168) | pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
method title (line 174) | pub fn title(mut self, title: impl IntoElement) -> Self {
method bordered (line 179) | pub fn bordered(mut self, bordered: bool) -> Self {
method open (line 184) | pub fn open(mut self, open: bool) -> Self {
method disabled (line 189) | pub fn disabled(mut self, disabled: bool) -> Self {
method index (line 194) | fn index(mut self, index: usize) -> Self {
method on_toggle_click (line 199) | fn on_toggle_click(
method extend (line 209) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method with_size (line 215) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method render (line 222) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/actions.rs
type Confirm (line 6) | pub struct Confirm {
FILE: crates/ui/src/alert.rs
type AlertVariant (line 16) | pub enum AlertVariant {
method fg (line 26) | fn fg(&self, cx: &App) -> Hsla {
method bg (line 36) | fn bg(&self, cx: &App) -> Hsla {
method border_color (line 46) | fn border_color(&self, cx: &App) -> Hsla {
type Alert (line 59) | pub struct Alert {
method new (line 74) | pub fn new(id: impl Into<ElementId>, message: impl Into<Text>) -> Self {
method info (line 90) | pub fn info(id: impl Into<ElementId>, message: impl Into<Text>) -> Self {
method success (line 97) | pub fn success(id: impl Into<ElementId>, message: impl Into<Text>) -> ...
method warning (line 104) | pub fn warning(id: impl Into<ElementId>, message: impl Into<Text>) -> ...
method error (line 111) | pub fn error(id: impl Into<ElementId>, message: impl Into<Text>) -> Se...
method with_variant (line 118) | pub fn with_variant(mut self, variant: AlertVariant) -> Self {
method icon (line 124) | pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
method title (line 130) | pub fn title(mut self, title: impl Into<SharedString>) -> Self {
method banner (line 139) | pub fn banner(mut self) -> Self {
method visible (line 145) | pub fn visible(mut self, visible: bool) -> Self {
method on_close (line 151) | pub fn on_close(
method with_size (line 161) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 168) | fn style(&mut self) -> &mut gpui::StyleRefinement {
method render (line 174) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/anchored.rs
type AnchoredState (line 13) | pub struct AnchoredState {
type Anchored (line 19) | pub(crate) struct Anchored {
method anchor (line 44) | pub fn anchor(mut self, anchor: Anchor) -> Self {
method position (line 51) | pub fn position(mut self, anchor: Point<Pixels>) -> Self {
method offset (line 58) | pub fn offset(mut self, offset: Point<Pixels>) -> Self {
method position_mode (line 66) | pub fn position_mode(mut self, mode: AnchoredPositionMode) -> Self {
method snap_to_window (line 72) | pub fn snap_to_window(mut self) -> Self {
method snap_to_window_with_margin (line 78) | pub fn snap_to_window_with_margin(mut self, edges: impl Into<Edges<Pix...
function anchored (line 30) | pub(crate) fn anchored() -> Anchored {
method extend (line 85) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
type RequestLayoutState (line 91) | type RequestLayoutState = AnchoredState;
type PrepaintState (line 92) | type PrepaintState = ();
method id (line 94) | fn id(&self) -> Option<gpui::ElementId> {
method source_location (line 98) | fn source_location(&self) -> Option<&'static core::panic::Location<'stat...
method request_layout (line 102) | fn request_layout(
method prepaint (line 126) | fn prepaint(
method paint (line 225) | fn paint(
type Element (line 242) | type Element = Self;
method into_element (line 244) | fn into_element(self) -> Self::Element {
type AnchoredFitMode (line 252) | pub enum AnchoredFitMode {
type AnchoredPositionMode (line 264) | pub enum AnchoredPositionMode {
method get_position_and_bounds (line 272) | fn get_position_and_bounds(
method from_corner_and_size (line 302) | fn from_corner_and_size(
FILE: crates/ui/src/animation.rs
function cubic_bezier (line 6) | pub fn cubic_bezier(x1: f32, y1: f32, x2: f32, y2: f32) -> impl Fn(f32) ...
FILE: crates/ui/src/avatar/avatar.rs
type Avatar (line 16) | pub struct Avatar {
method new (line 27) | pub fn new() -> Self {
method src (line 40) | pub fn src(mut self, source: impl Into<ImageSource>) -> Self {
method name (line 46) | pub fn name(mut self, name: impl Into<SharedString>) -> Self {
method placeholder (line 56) | pub fn placeholder(mut self, icon: impl Into<Icon>) -> Self {
method with_size (line 63) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 70) | fn style(&mut self) -> &mut StyleRefinement {
method interactivity (line 76) | fn interactivity(&mut self) -> &mut Interactivity {
method render (line 82) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
function extract_text_initials (line 131) | fn extract_text_initials(text: &str) -> String {
function test_avatar_text_initials (line 151) | fn test_avatar_text_initials() {
function test_avatar_builder (line 158) | fn test_avatar_builder(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/avatar/avatar_group.rs
type AvatarGroup (line 10) | pub struct AvatarGroup {
method new (line 21) | pub fn new() -> Self {
method child (line 33) | pub fn child(mut self, avatar: Avatar) -> Self {
method children (line 39) | pub fn children(mut self, avatars: impl IntoIterator<Item = Avatar>) -...
method limit (line 45) | pub fn limit(mut self, limit: usize) -> Self {
method ellipsis (line 51) | pub fn ellipsis(mut self) -> Self {
method with_size (line 58) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 65) | fn style(&mut self) -> &mut StyleRefinement {
method interactivity (line 71) | fn interactivity(&mut self) -> &mut Interactivity {
method render (line 77) | fn render(self, _: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoEl...
function test_avatar_group_builder (line 116) | fn test_avatar_group_builder(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/avatar/mod.rs
function avatar_size (line 11) | pub(super) fn avatar_size(size: Size) -> Pixels {
type AvatarSized (line 22) | pub(super) trait AvatarSized: IntoElement + Styled {
method avatar_size (line 23) | fn avatar_size(self, size: Size) -> Self {
method avatar_text_size (line 27) | fn avatar_text_size(self, size: Size) -> Self {
FILE: crates/ui/src/badge.rs
type BadgeVariant (line 9) | enum BadgeVariant {
method is_icon (line 19) | fn is_icon(&self) -> bool {
method is_number (line 24) | fn is_number(&self) -> bool {
type Badge (line 31) | pub struct Badge {
method new (line 43) | pub fn new() -> Self {
method dot (line 56) | pub fn dot(mut self) -> Self {
method count (line 64) | pub fn count(mut self, count: usize) -> Self {
method icon (line 70) | pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
method max (line 76) | pub fn max(mut self, max: usize) -> Self {
method color (line 82) | pub fn color(mut self, color: impl Into<Hsla>) -> Self {
method extend (line 89) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method with_size (line 95) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method render (line 102) | fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/breadcrumb.rs
type Breadcrumb (line 13) | pub struct Breadcrumb {
method new (line 114) | pub fn new() -> Self {
method child (line 122) | pub fn child(mut self, item: impl Into<BreadcrumbItem>) -> Self {
method children (line 128) | pub fn children(mut self, items: impl IntoIterator<Item = impl Into<Br...
type BreadcrumbItem (line 20) | pub struct BreadcrumbItem {
method new (line 31) | pub fn new(label: impl Into<SharedString>) -> Self {
method disabled (line 42) | pub fn disabled(mut self, disabled: bool) -> Self {
method on_click (line 47) | pub fn on_click(
method id (line 55) | fn id(mut self, id: impl Into<ElementId>) -> Self {
method is_last (line 61) | fn is_last(mut self, is_last: bool) -> Self {
method from (line 74) | fn from(value: &'static str) -> Self {
method from (line 80) | fn from(value: String) -> Self {
method from (line 86) | fn from(value: SharedString) -> Self {
method style (line 68) | fn style(&mut self) -> &mut StyleRefinement {
method render (line 92) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
type BreadcrumbSeparator (line 135) | struct BreadcrumbSeparator;
method render (line 137) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
method style (line 146) | fn style(&mut self) -> &mut StyleRefinement {
method render (line 152) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/button/button.rs
type ButtonRounded (line 15) | pub enum ButtonRounded {
method from (line 25) | fn from(px: Pixels) -> Self {
type ButtonCustomVariant (line 31) | pub struct ButtonCustomVariant {
method new (line 94) | pub fn new(cx: &App) -> Self {
method color (line 105) | pub fn color(mut self, color: Hsla) -> Self {
method foreground (line 111) | pub fn foreground(mut self, color: Hsla) -> Self {
method hover (line 117) | pub fn hover(mut self, color: Hsla) -> Self {
method active (line 123) | pub fn active(mut self, color: Hsla) -> Self {
method shadow (line 129) | pub fn shadow(mut self, shadow: bool) -> Self {
type ButtonVariants (line 39) | pub trait ButtonVariants: Sized {
method with_variant (line 40) | fn with_variant(self, variant: ButtonVariant) -> Self;
method primary (line 43) | fn primary(self) -> Self {
method secondary (line 48) | fn secondary(self) -> Self {
method danger (line 53) | fn danger(self) -> Self {
method warning (line 58) | fn warning(self) -> Self {
method success (line 63) | fn success(self) -> Self {
method info (line 68) | fn info(self) -> Self {
method ghost (line 73) | fn ghost(self) -> Self {
method link (line 78) | fn link(self) -> Self {
method text (line 83) | fn text(self) -> Self {
method custom (line 88) | fn custom(self, style: ButtonCustomVariant) -> Self {
method with_variant (line 403) | fn with_variant(mut self, variant: ButtonVariant) -> Self {
type ButtonVariant (line 137) | pub enum ButtonVariant {
method is_link (line 154) | pub fn is_link(&self) -> bool {
method is_text (line 159) | pub fn is_text(&self) -> bool {
method is_ghost (line 164) | pub fn is_ghost(&self) -> bool {
method no_padding (line 169) | fn no_padding(&self) -> bool {
method is_default (line 174) | fn is_default(&self) -> bool {
method bg_color (line 638) | fn bg_color(&self, outline: bool, cx: &mut App) -> Hsla {
method text_color (line 656) | fn text_color(&self, outline: bool, cx: &mut App) -> Hsla {
method border_color (line 677) | fn border_color(&self, _bg: Hsla, outline: bool, cx: &mut App) -> Hsla {
method underline (line 721) | fn underline(&self, _: &App) -> bool {
method shadow (line 728) | fn shadow(&self, outline: bool, _: &App) -> bool {
method normal (line 737) | fn normal(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
method hovered (line 753) | fn hovered(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
method active (line 830) | fn active(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
method selected (line 876) | fn selected(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
method disabled (line 908) | fn disabled(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
type Button (line 181) | pub struct Button {
method new (line 218) | pub fn new(id: impl Into<ElementId>) -> Self {
method outline (line 251) | pub fn outline(mut self) -> Self {
method rounded (line 257) | pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
method border_corners (line 263) | pub(crate) fn border_corners(mut self, corners: impl Into<Corners<bool...
method border_edges (line 269) | pub(crate) fn border_edges(mut self, edges: impl Into<Edges<bool>>) ->...
method label (line 275) | pub fn label(mut self, label: impl Into<SharedString>) -> Self {
method icon (line 281) | pub fn icon(mut self, icon: impl Into<ButtonIcon>) -> Self {
method tooltip (line 287) | pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
method tooltip_with_action (line 293) | pub fn tooltip_with_action(
method loading (line 310) | pub fn loading(mut self, loading: bool) -> Self {
method compact (line 316) | pub fn compact(mut self) -> Self {
method on_click (line 322) | pub fn on_click(
method on_hover (line 331) | pub fn on_hover(mut self, handler: impl Fn(&bool, &mut Window, &mut Ap...
method loading_icon (line 339) | pub fn loading_icon(mut self, icon: impl Into<Icon>) -> Self {
method tab_index (line 347) | pub fn tab_index(mut self, tab_index: isize) -> Self {
method tab_stop (line 355) | pub fn tab_stop(mut self, tab_stop: bool) -> Self {
method dropdown_caret (line 361) | pub fn dropdown_caret(mut self, dropdown_caret: bool) -> Self {
method clickable (line 367) | fn clickable(&self) -> bool {
method hoverable (line 372) | fn hoverable(&self) -> bool {
method from (line 212) | fn from(button: Button) -> Self {
method disabled (line 378) | fn disabled(mut self, disabled: bool) -> Self {
method selected (line 385) | fn selected(mut self, selected: bool) -> Self {
method is_selected (line 390) | fn is_selected(&self) -> bool {
method with_size (line 396) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 410) | fn style(&mut self) -> &mut StyleRefinement {
method extend (line 416) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method interactivity (line 422) | fn interactivity(&mut self) -> &mut Interactivity {
method render (line 428) | fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
type ButtonVariantStyle (line 629) | struct ButtonVariantStyle {
function test_button_builder (line 952) | fn test_button_builder(_cx: &mut gpui::TestAppContext) {
function test_button_clickable_logic (line 985) | fn test_button_clickable_logic(_cx: &mut gpui::TestAppContext) {
function test_button_variant_methods (line 1000) | fn test_button_variant_methods(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/button/button_group.rs
type ButtonGroup (line 15) | pub struct ButtonGroup {
method new (line 41) | pub fn new(id: impl Into<ElementId>) -> Self {
method child (line 58) | pub fn child(mut self, child: Button) -> Self {
method children (line 64) | pub fn children(mut self, children: impl IntoIterator<Item = Button>) ...
method multiple (line 70) | pub fn multiple(mut self, multiple: bool) -> Self {
method layout (line 76) | pub fn layout(mut self, layout: Axis) -> Self {
method compact (line 84) | pub fn compact(mut self) -> Self {
method outline (line 92) | pub fn outline(mut self) -> Self {
method on_click (line 120) | pub fn on_click(
method disabled (line 33) | fn disabled(mut self, disabled: bool) -> Self {
method with_size (line 130) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 137) | fn style(&mut self) -> &mut gpui::StyleRefinement {
method with_variant (line 143) | fn with_variant(mut self, variant: ButtonVariant) -> Self {
method render (line 150) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
function test_button_group_builder (line 262) | fn test_button_group_builder(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/button/button_icon.rs
type ButtonIcon (line 7) | pub struct ButtonIcon {
method from (line 18) | fn from(icon: T) -> Self {
method new (line 25) | pub fn new(icon: impl Into<ButtonIconVariant>) -> Self {
method loading_icon (line 34) | pub(crate) fn loading_icon(mut self, icon: Option<Icon>) -> Self {
method loading (line 39) | pub(crate) fn loading(mut self, loading: bool) -> Self {
method with_size (line 46) | fn with_size(mut self, size: impl Into<crate::Size>) -> Self {
type ButtonIconVariant (line 55) | pub enum ButtonIconVariant {
method from (line 65) | fn from(icon: T) -> Self {
method from (line 71) | fn from(spinner: Spinner) -> Self {
method from (line 77) | fn from(progress: ProgressCircle) -> Self {
method is_spinner (line 85) | pub(crate) fn is_spinner(&self) -> bool {
method is_progress (line 91) | pub(crate) fn is_progress(&self) -> bool {
method with_size (line 97) | fn with_size(self, size: impl Into<crate::Size>) -> Self {
method render (line 107) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
method render (line 117) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
function test_button_icon_builder (line 139) | fn test_button_icon_builder(_cx: &mut gpui::TestAppContext) {
function test_button_icon_variant_types (line 152) | fn test_button_icon_variant_types(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/button/dropdown_button.rs
type DropdownButton (line 14) | pub struct DropdownButton {
method new (line 34) | pub fn new(id: impl Into<ElementId>) -> Self {
method button (line 53) | pub fn button(mut self, button: Button) -> Self {
method dropdown_menu (line 59) | pub fn dropdown_menu(
method dropdown_menu_with_anchor (line 68) | pub fn dropdown_menu_with_anchor(
method rounded (line 79) | pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
method compact (line 87) | pub fn compact(mut self) -> Self {
method outline (line 95) | pub fn outline(mut self) -> Self {
method loading (line 101) | pub fn loading(mut self, loading: bool) -> Self {
method disabled (line 108) | fn disabled(mut self, disabled: bool) -> Self {
method style (line 115) | fn style(&mut self) -> &mut gpui::StyleRefinement {
method with_size (line 121) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method with_variant (line 128) | fn with_variant(mut self, variant: ButtonVariant) -> Self {
method selected (line 135) | fn selected(mut self, selected: bool) -> Self {
method is_selected (line 140) | fn is_selected(&self) -> bool {
method render (line 146) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
function test_dropdown_button_builder (line 213) | fn test_dropdown_button_builder(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/button/toggle.rs
type ToggleVariant (line 13) | pub enum ToggleVariant {
type ToggleVariants (line 19) | pub trait ToggleVariants: Sized {
method with_variant (line 21) | fn with_variant(self, variant: ToggleVariant) -> Self;
method ghost (line 23) | fn ghost(self) -> Self {
method outline (line 27) | fn outline(self) -> Self {
method with_variant (line 89) | fn with_variant(mut self, variant: ToggleVariant) -> Self {
method with_variant (line 224) | fn with_variant(mut self, variant: ToggleVariant) -> Self {
type Toggle (line 33) | pub struct Toggle {
method new (line 46) | pub fn new(id: impl Into<ElementId>) -> Self {
method label (line 60) | pub fn label(mut self, label: impl Into<SharedString>) -> Self {
method icon (line 67) | pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
method checked (line 74) | pub fn checked(mut self, checked: bool) -> Self {
method on_click (line 82) | pub fn on_click(mut self, handler: impl Fn(&bool, &mut Window, &mut Ap...
method extend (line 96) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method disabled (line 102) | fn disabled(mut self, disabled: bool) -> Self {
method with_size (line 109) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method style (line 116) | fn style(&mut self) -> &mut StyleRefinement {
method render (line 122) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
type ToggleGroup (line 168) | pub struct ToggleGroup {
method new (line 180) | pub fn new(id: impl Into<ElementId>) -> Self {
method child (line 193) | pub fn child(mut self, toggle: impl Into<Toggle>) -> Self {
method children (line 199) | pub fn children(mut self, children: impl IntoIterator<Item = impl Into...
method on_click (line 207) | pub fn on_click(
method with_size (line 217) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method disabled (line 231) | fn disabled(mut self, disabled: bool) -> Self {
method style (line 238) | fn style(&mut self) -> &mut StyleRefinement {
method render (line 244) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
function test_toggle_builder (line 288) | fn test_toggle_builder(_cx: &mut gpui::TestAppContext) {
function test_toggle_group_builder (line 307) | fn test_toggle_group_builder(_cx: &mut gpui::TestAppContext) {
FILE: crates/ui/src/chart/area_chart.rs
type AreaChart (line 19) | pub struct AreaChart<T, X, Y>
function new (line 41) | pub fn new<I>(data: I) -> Self
function x (line 58) | pub fn x(mut self, x: impl Fn(&T) -> X + 'static) -> Self {
function y (line 63) | pub fn y(mut self, y: impl Fn(&T) -> Y + 'static) -> Self {
function stroke (line 68) | pub fn stroke(mut self, stroke: impl Into<Hsla>) -> Self {
function fill (line 73) | pub fn fill(mut self, fill: impl Into<Background>) -> Self {
function natural (line 78) | pub fn natural(mut self) -> Self {
function linear (line 83) | pub fn linear(mut self) -> Self {
function step_after (line 88) | pub fn step_after(mut self) -> Self {
function tick_margin (line 93) | pub fn tick_margin(mut self, tick_margin: usize) -> Self {
function x_axis (line 101) | pub fn x_axis(mut self, x_axis: bool) -> Self {
function grid (line 106) | pub fn grid(mut self, grid: bool) -> Self {
method paint (line 117) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/ui/src/chart/bar_chart.rs
type BarChart (line 20) | pub struct BarChart<T, X, Y>
function new (line 41) | pub fn new<I>(data: I) -> Self
function x (line 57) | pub fn x(mut self, x: impl Fn(&T) -> X + 'static) -> Self {
function y (line 62) | pub fn y(mut self, y: impl Fn(&T) -> Y + 'static) -> Self {
function fill (line 67) | pub fn fill<H>(mut self, fill: impl Fn(&T) -> H + 'static) -> Self
function tick_margin (line 75) | pub fn tick_margin(mut self, tick_margin: usize) -> Self {
function label (line 80) | pub fn label<S>(mut self, label: impl Fn(&T) -> S + 'static) -> Self
function x_axis (line 91) | pub fn x_axis(mut self, x_axis: bool) -> Self {
function grid (line 96) | pub fn grid(mut self, grid: bool) -> Self {
method paint (line 107) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/ui/src/chart/candlestick_chart.rs
type CandlestickChart (line 18) | pub struct CandlestickChart<T, X, Y>
function new (line 41) | pub fn new<I>(data: I) -> Self
function x (line 59) | pub fn x(mut self, x: impl Fn(&T) -> X + 'static) -> Self {
function open (line 64) | pub fn open(mut self, open: impl Fn(&T) -> Y + 'static) -> Self {
function high (line 69) | pub fn high(mut self, high: impl Fn(&T) -> Y + 'static) -> Self {
function low (line 74) | pub fn low(mut self, low: impl Fn(&T) -> Y + 'static) -> Self {
function close (line 79) | pub fn close(mut self, close: impl Fn(&T) -> Y + 'static) -> Self {
function tick_margin (line 84) | pub fn tick_margin(mut self, tick_margin: usize) -> Self {
function body_width_ratio (line 89) | pub fn body_width_ratio(mut self, ratio: f32) -> Self {
function x_axis (line 97) | pub fn x_axis(mut self, x_axis: bool) -> Self {
function grid (line 102) | pub fn grid(mut self, grid: bool) -> Self {
method paint (line 113) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/ui/src/chart/line_chart.rs
type LineChart (line 19) | pub struct LineChart<T, X, Y>
function new (line 41) | pub fn new<I>(data: I) -> Self
function x (line 58) | pub fn x(mut self, x: impl Fn(&T) -> X + 'static) -> Self {
function y (line 63) | pub fn y(mut self, y: impl Fn(&T) -> Y + 'static) -> Self {
function stroke (line 68) | pub fn stroke(mut self, stroke: impl Into<Hsla>) -> Self {
function natural (line 73) | pub fn natural(mut self) -> Self {
function linear (line 78) | pub fn linear(mut self) -> Self {
function step_after (line 83) | pub fn step_after(mut self) -> Self {
function dot (line 88) | pub fn dot(mut self) -> Self {
function tick_margin (line 93) | pub fn tick_margin(mut self, tick_margin: usize) -> Self {
function x_axis (line 101) | pub fn x_axis(mut self, x_axis: bool) -> Self {
function grid (line 106) | pub fn grid(mut self, grid: bool) -> Self {
method paint (line 117) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/ui/src/chart/mod.rs
function build_point_x_labels (line 24) | pub(crate) fn build_point_x_labels<T, X>(
function build_band_x_labels (line 59) | pub(crate) fn build_band_x_labels<T, X>(
FILE: crates/ui/src/chart/pie_chart.rs
type PieChart (line 16) | pub struct PieChart<T: 'static> {
function new (line 28) | pub fn new<I>(data: I) -> Self
function inner_radius (line 45) | pub fn inner_radius(mut self, inner_radius: f32) -> Self {
function inner_radius_fn (line 51) | pub fn inner_radius_fn(
function get_inner_radius (line 59) | fn get_inner_radius(&self, arc: &ArcData<T>) -> f32 {
function outer_radius (line 68) | pub fn outer_radius(mut self, outer_radius: f32) -> Self {
function outer_radius_fn (line 74) | pub fn outer_radius_fn(
function get_outer_radius (line 82) | fn get_outer_radius(&self, arc: &ArcData<T>) -> f32 {
function pad_angle (line 91) | pub fn pad_angle(mut self, pad_angle: f32) -> Self {
function value (line 96) | pub fn value(mut self, value: impl Fn(&T) -> f32 + 'static) -> Self {
function color (line 102) | pub fn color<H>(mut self, color: impl Fn(&T) -> H + 'static) -> Self
method paint (line 112) | fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mu...
FILE: crates/ui/src/checkbox.rs
type Checkbox (line 15) | pub struct Checkbox {
method new (line 31) | pub fn new(id: impl Into<ElementId>) -> Self {
method label (line 48) | pub fn label(mut self, label: impl Into<Text>) -> Self {
method checked (line 54) | pub fn checked(mut self, checked: bool) -> Self {
method on_click (line 62) | pub fn on_click(mut self, handler: impl Fn(&bool, &mut Window, &mut Ap...
method tab_stop (line 68) | pub fn tab_stop(mut self, tab_stop: bool) -> Self {
method tab_index (line 74) | pub fn tab_index(mut self, tab_index: isize) -> Self {
method handle_click (line 79) | fn handle_click(
method interactivity (line 93) | fn interactivity(&mut self) -> &mut gpui::Interactivity {
method style (line 100) | fn style(&mut self) -> &mut gpui::StyleRefinement {
method disabled (line 106) | fn disabled(mut self, disabled: bool) -> Self {
method selected (line 113) | fn selected(self, selected: bool) -> Self {
method is_selected (line 117) | fn is_selected(&self) -> bool {
method extend (line 123) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method with_size (line 129) | fn with_size(mut self, size: impl Into<Size>) -> Self {
function checkbox_check_icon (line 135) | pub(crate) fn checkbox_check_icon(
method render (line 193) | fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/clipboard.rs
type Clipboard (line 15) | pub struct Clipboard {
method new (line 24) | pub fn new(id: impl Into<ElementId>) -> Self {
method value (line 34) | pub fn value(mut self, value: impl Into<SharedString>) -> Self {
method value_fn (line 42) | pub fn value_fn(
method on_copied (line 51) | pub fn on_copied<F>(mut self, handler: F) -> Self
method render (line 61) | fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
type ClipboardState (line 114) | struct ClipboardState {
FILE: crates/ui/src/collapsible.rs
type CollapsibleChild (line 7) | enum CollapsibleChild {
method is_content (line 13) | fn is_content(&self) -> bool {
type Collapsible (line 20) | pub struct Collapsible {
method new (line 28) | pub fn new() -> Self {
method open (line 37) | pub fn open(mut self, open: bool) -> Self {
method content (line 45) | pub fn content(mut self, content: impl IntoElement) -> Self {
method style (line 53) | fn style(&mut self) -> &mut StyleRefinement {
method extend (line 59) | fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
method render (line 66) | fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
FILE: crates/ui/src/color_picker.rs
constant CONTEXT (line 22) | const CONTEXT: &'static str = "ColorPicker";
function init (line 23) | pub(crate) fn init(cx: &mut App) {
type ColorPickerEvent (line 33) | pub enum ColorPickerEvent {
function color_palettes (line 37) | fn color_palettes() -> Vec<Vec<Hsla>> {
type HslaSliders (line 66) | struct HslaSliders {
method new (line 74) | fn new(cx: &mut App) -> Self {
method read (line 107) | fn read(&self, cx: &App) -> Hsla {
method update (line 116) | fn update(&self, new_color: Hsla, window: &mut Window, cx: &mut App) {
type ColorPickerState (line 133) | pub struct ColorPickerState {
method new (line 148) | pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
method default_value (line 228) | pub fn default_value(mut self, value: impl Into<Hsla>) -> Self {
method set_value (line 237) | pub fn set_value(
method value (line 247) | pub fn value(&self) -> Option<Hsla> {
method on_confirm (line 251) | fn on_confirm(&mut self, _: &Confirm, _: &mut Window, cx: &mut Context...
method update_value (line 256) | fn update_value(
method update_value_from_slider (line 279) | fn update_value_from_slider(
method sync_sliders (line 295) | fn sync_sliders(&mut self, color: Option<Hsla>, window: &mut Window, c...
method render (line 305) | fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl Into...
method focus_handle (line 311) | fn focus_handle(&self, _: &App) -> FocusHandle {
type ColorPicker (line 318) | pub struct ColorPicker {
method new (line 331) | pub fn new(state: &Entity<ColorPickerState>) -> Self {
method featured_colors (line 348) | pub fn featured_colors(mut self, colors: Vec<Hsla>) -> Self {
method icon (line 357) | pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
method label (line 365) | pub fn label(mut self, label: impl Into<SharedString>) -> Self {
method anchor (line 373) | pub fn anchor(mut self, anchor: Corner) -> Self {
method render_item (line 378) | fn render_item(
method render_colors (line 418) | fn render_colors(&self, window: &mut Window, cx: &mut App) -> impl Int...
method render_palette_panel (line 478) | fn render_palette_panel(&self, window: &mut Window, cx: &mut App) -> i...
method render_slider_tab_panel (line 518) | fn render_slider_tab_panel(&self, slider_color: Hsla, cx: &mut App) ->...
method render_slider_track (line 684) | fn render_slider_track(&self, colors: Vec<Hsla>, _: &App) -> impl Into...
method render_slider_track_gradient (line 698) | fn render_slider_track_gradient(&self, start: Hsla, end: Hsla, _: &App...
method with_size (line 714) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method focus_handle (line 721) | fn focus_handle(&self, cx: &App) -> FocusHandle {
method style (line 727) | fn style(&mut self) -> &mut StyleRefinement {
method render (line 733) | fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
type ColorPickerButton (line 778) | struct ColorPickerButton {
method selected (line 789) | fn selected(mut self, selected: bool) -> Self {
method is_selected (line 794) | fn is_selected(&self) -> bool {
method with_size (line 800) | fn with_size(mut self, size: impl Into<Size>) -> Self {
method render (line 807) | fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
FILE: crates/ui/src/description_list.rs
type DescriptionList (line 10) | pub struct DescriptionList {
method new (line 126) | pub fn new() -> Self {
method vertical (line 138) | pub fn vertical() -> Self {
method horizontal (line 143) | pub fn horizontal() -> Self {
method label_width (line 150) | pub fn label_width(mut self, label_width: impl Into<DefiniteLength>) -...
method layout (line 156) | pub fn layout(mut self, layout: Axis) -> Self {
method bordered (line 164) | pub fn bordered(mut self, bordered: bool) -> Self {
method columns (line 172) | pub fn columns(mut self, columns: usize) -> Self {
method item (line 178) | pub fn item(
method child (line 193) | pub fn child(mut self, child: impl Into<DescriptionItem>) -> Self {
method children (line 199) | pub fn children(
method divider (line 209) | pub fn divider(mut self) -> Self {
method group_item_rows (line 214) | fn group_item_rows(items: Vec<DescriptionItem>, columns: usize) -> Vec...
type DescriptionItem (line 20) | pub enum DescriptionItem {
method new (line 81) | pub fn new(label: impl Into<DescriptionText>) -> Self {
method value (line 90) | pub fn value(mut self, value: impl Into<DescriptionText>) -> Self {
method span (line 101) | pub fn span(mut self, span: usize) -> Self {
method _label (line 109) | fn _label(&self) -> Option<&DescriptionText> {
method _span (line 116) | fn _span(&self) -> Option<usize> {
type DescriptionText (line 31) | pub enum DescriptionText {
method from (line 38) | fn from(text: &str) -> Self {
method from (line 44) | fn from(text: Text) -> Self {
method from (line 50) | fn from(element: AnyElement) -> Self {
method from (line 56) | fn from
Condensed preview — 547 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,607K chars).
[
{
"path": ".cargo/config.toml",
"chars": 78,
"preview": "[target.x86_64-pc-windows-msvc]\nrustflags = [\"-C\", \"link-arg=/STACK:8000000\"]\n"
},
{
"path": ".claude/COMPONENT_TEST_RULES.md",
"chars": 6503,
"preview": "# GPUI Component Testing Rules\n\n## Testing Principles\n\n### 1. **Simplicity First**\n\n- Avoid excessive simple tests\n- Foc"
},
{
"path": ".claude/skills/generate-component-documentation/SKILL.md",
"chars": 806,
"preview": "---\nname: generate-component-documentation\ndescription: Generate documentation for new components. Use when writing docs"
},
{
"path": ".claude/skills/generate-component-story/SKILL.md",
"chars": 711,
"preview": "---\nname: generate-component-story\ndescription: Create story examples for components. Use when writing stories, creating"
},
{
"path": ".claude/skills/github-pull-request-description/SKILL.md",
"chars": 1487,
"preview": "---\nname: github-pull-request-description\ndescription: Write a description to description GitHub Pull Request.\n---\n\n## D"
},
{
"path": ".claude/skills/gpui-action/SKILL.md",
"chars": 3874,
"preview": "---\nname: gpui-action\ndescription: Action definitions and keyboard shortcuts in GPUI. Use when implementing actions, key"
},
{
"path": ".claude/skills/gpui-async/SKILL.md",
"chars": 4293,
"preview": "---\nname: gpui-async\ndescription: Async operations and background tasks in GPUI. Use when working with async, spawn, bac"
},
{
"path": ".claude/skills/gpui-context/SKILL.md",
"chars": 3430,
"preview": "---\nname: gpui-context\ndescription: Context management in GPUI including App, Window, and AsyncApp. Use when working wit"
},
{
"path": ".claude/skills/gpui-element/SKILL.md",
"chars": 4534,
"preview": "---\nname: gpui-element\ndescription: Implementing custom elements using GPUI's low-level Element API (vs. high-level Rend"
},
{
"path": ".claude/skills/gpui-element/references/advanced-patterns.md",
"chars": 20323,
"preview": "# Advanced Element Patterns\n\nAdvanced techniques and patterns for implementing sophisticated GPUI elements.\n\n## Custom L"
},
{
"path": ".claude/skills/gpui-element/references/api-reference.md",
"chars": 10988,
"preview": "# Element API Reference\n\nComplete API documentation for GPUI's low-level Element trait.\n\n## Element Trait Structure\n\nThe"
},
{
"path": ".claude/skills/gpui-element/references/best-practices.md",
"chars": 13132,
"preview": "# Element Best Practices\n\nGuidelines and best practices for implementing high-quality GPUI elements.\n\n## State Managemen"
},
{
"path": ".claude/skills/gpui-element/references/examples.md",
"chars": 18091,
"preview": "# Element Implementation Examples\n\nComplete examples of implementing custom elements for various scenarios.\n\n## Table of"
},
{
"path": ".claude/skills/gpui-element/references/patterns.md",
"chars": 14802,
"preview": "# Common Element Patterns\n\nReusable patterns for implementing common element types in GPUI.\n\n## Text Rendering Elements\n"
},
{
"path": ".claude/skills/gpui-entity/SKILL.md",
"chars": 4472,
"preview": "---\nname: gpui-entity\ndescription: Entity management and state handling in GPUI. Use when working with entities, managin"
},
{
"path": ".claude/skills/gpui-entity/references/advanced.md",
"chars": 12514,
"preview": "# Advanced Entity Patterns\n\nAdvanced techniques for sophisticated entity management scenarios.\n\n## Entity Collections Ma"
},
{
"path": ".claude/skills/gpui-entity/references/api-reference.md",
"chars": 8391,
"preview": "# Entity API Reference\n\nComplete API documentation for GPUI's entity system.\n\n## Entity Types\n\n### Entity<T>\n\nA strong r"
},
{
"path": ".claude/skills/gpui-entity/references/best-practices.md",
"chars": 11892,
"preview": "# Entity Best Practices\n\nGuidelines and best practices for effective entity management in GPUI.\n\n## Avoiding Common Pitf"
},
{
"path": ".claude/skills/gpui-entity/references/patterns.md",
"chars": 13114,
"preview": "# Entity Patterns\n\nCommon patterns and use cases for entity management in GPUI.\n\n## Application Scenarios\n\n### Model-Vie"
},
{
"path": ".claude/skills/gpui-event/SKILL.md",
"chars": 3998,
"preview": "---\nname: gpui-event\ndescription: Event handling and subscriptions in GPUI. Use when implementing events, observers, or "
},
{
"path": ".claude/skills/gpui-focus-handle/SKILL.md",
"chars": 5238,
"preview": "---\nname: gpui-focus-handle\ndescription: Focus management and keyboard navigation in GPUI. Use when handling focus, focu"
},
{
"path": ".claude/skills/gpui-global/SKILL.md",
"chars": 4109,
"preview": "---\nname: gpui-global\ndescription: Global state management in GPUI. Use when implementing global state, app-wide configu"
},
{
"path": ".claude/skills/gpui-layout-and-style/SKILL.md",
"chars": 3327,
"preview": "---\nname: gpui-layout-and-style\ndescription: Layout and styling in GPUI. Use when styling components, layout systems, or"
},
{
"path": ".claude/skills/gpui-style-guide/SKILL.md",
"chars": 11680,
"preview": "---\nname: gpui-style-guide\ndescription: GPUI Component project style guide based on gpui-component code patterns. Use wh"
},
{
"path": ".claude/skills/gpui-test/SKILL.md",
"chars": 2426,
"preview": "---\nname: gpui-test\ndescription: Writing tests for GPUI applications. Use when testing components, async operations, or "
},
{
"path": ".claude/skills/gpui-test/examples.md",
"chars": 3351,
"preview": "## Testing Best Practices\n\n### Test Organization\n\nGroup related tests in modules:\n\n```rust\n#[cfg(test)]\nmod tests {\n "
},
{
"path": ".claude/skills/gpui-test/reference.md",
"chars": 8572,
"preview": "## Testing Patterns\n\n### Basic Entity Testing\n\nTest entity creation, updates, and reads:\n\n```rust\n#[gpui::test]\nfn test_"
},
{
"path": ".claude/skills/new-component/SKILL.md",
"chars": 6557,
"preview": "---\nname: new-component\ndescription: Create new GPUI components. Use when building components, writing UI elements, or c"
},
{
"path": ".github/ISSUE_TEMPLATE/01_bug.md",
"chars": 767,
"preview": "---\nname: Bug report\nabout: Report a problem or unexpected behavior\ntitle: \"\"\nassignees:\n---\n\n## Description\n\nUse Englis"
},
{
"path": ".github/dependabot.yml",
"chars": 211,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"cargo\"\n directory: \"/\" # Location of package manifests\n schedule:\n "
},
{
"path": ".github/pull_request_template.md",
"chars": 1140,
"preview": "Closes #[issue number]\n\n## Description\n\nDescribe in English for the changes made in this pull request and the problem it"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2014,
"preview": "name: CI\non:\n pull_request:\n push:\n branches:\n - main\n tags:\n - \"*\"\n\nconcurrency:\n group: ${{ github."
},
{
"path": ".github/workflows/release-docs.yml",
"chars": 1782,
"preview": "name: Release Docs\non:\n workflow_run:\n workflows: [\"Release Crate\"]\n types:\n - completed\n workflow_dispatch"
},
{
"path": ".github/workflows/release.yml",
"chars": 355,
"preview": "name: \"Release Crate\"\non:\n push:\n tags:\n - \"v*\"\njobs:\n publish_crate:\n name: Publish Crate\n runs-on: ubu"
},
{
"path": ".github/workflows/test-docs.yml",
"chars": 386,
"preview": "name: Test Docs\non:\n pull_request:\n paths:\n - \"docs/**\"\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n "
},
{
"path": ".gitignore",
"chars": 340,
"preview": "target/\n.DS_Store\n/docks.json\n/profile.json\n.vscode\nindex.scip\n*.log\nnode_modules/\n\n# WASM build artifacts\ncrates/story-"
},
{
"path": ".rustfmt.toml",
"chars": 40,
"preview": "edition = \"2024\"\nstyle_edition = \"2024\"\n"
},
{
"path": ".theme-schema.json",
"chars": 32613,
"preview": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"title\": \"ThemeSet\",\n \"description\": \"Represents a theme co"
},
{
"path": "CLAUDE.md",
"chars": 7194,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "CONTRIBUTING.md",
"chars": 3974,
"preview": "# Contributing Guide\n\nContributions are welcome, if you find some bugs or have some ideas, please open an issue or submi"
},
{
"path": "Cargo.toml",
"chars": 3761,
"preview": "[workspace]\ndefault-members = [\"crates/ui\", \"crates/story\", \"crates/assets\"]\nmembers = [\n \"crates/macros\",\n \"crate"
},
{
"path": "LICENSE-APACHE",
"chars": 10305,
"preview": "Copyright 2024 - 2025 Longbridge <https://longbridge.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "Makefile",
"chars": 42,
"preview": "dev-web:\n\tcd crates/story-web && make dev\n"
},
{
"path": "README.md",
"chars": 9005,
"preview": "# GPUI Component\n\n[](htt"
},
{
"path": "crates/assets/Cargo.toml",
"chars": 816,
"preview": "[package]\nname = \"gpui-component-assets\"\ndescription = \"Default bundled assets for GPUI Component.\"\nkeywords = [\"desktop"
},
{
"path": "crates/assets/README.md",
"chars": 143,
"preview": "# GPUI Component Assets\n\nThe default assets bundle for [GPUI Component](https://github.com/longbridge/gpui-component).\n\n"
},
{
"path": "crates/assets/assets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "crates/assets/src/lib.rs",
"chars": 929,
"preview": "/// Embed application assets for GPUI Component.\n///\n/// This assets provides icons svg files for [IconName](https://doc"
},
{
"path": "crates/assets/src/native_assets.rs",
"chars": 926,
"preview": "use anyhow::anyhow;\nuse gpui::{AssetSource, Result, SharedString};\nuse std::borrow::Cow;\n\n/// Native implementation usin"
},
{
"path": "crates/assets/src/wasm_assets.rs",
"chars": 3726,
"preview": "use anyhow::anyhow;\nuse gpui::{AssetSource, Result, SharedString};\nuse std::borrow::Cow;\nuse std::collections::HashMap;\n"
},
{
"path": "crates/macros/Cargo.toml",
"chars": 351,
"preview": "[package]\nname = \"gpui-component-macros\"\ndescription = \"Macros for GPUI Component.\"\nversion = \"0.5.1\"\nlicense = \"Apache-"
},
{
"path": "crates/macros/src/derive_into_plot.rs",
"chars": 2400,
"preview": "use proc_macro::TokenStream;\nuse quote::quote;\nuse syn::{parse_macro_input, DeriveInput};\n\npub fn derive_into_plot(input"
},
{
"path": "crates/macros/src/lib.rs",
"chars": 6602,
"preview": "use proc_macro::TokenStream;\nuse quote::quote;\nuse syn::parse::{Parse, ParseStream};\n\nmod derive_into_plot;\n\n/// Input f"
},
{
"path": "crates/story/Cargo.toml",
"chars": 1202,
"preview": "[package]\nname = \"gpui-component-story\"\nversion = \"0.5.1\"\npublish = false\nedition.workspace = true\n\n[features]\ninspector"
},
{
"path": "crates/story/examples/brush.rs",
"chars": 16653,
"preview": "use std::rc::Rc;\n\nuse gpui::{StyleRefinement, prelude::FluentBuilder, *};\nuse gpui_component::{\n ActiveTheme, Coloriz"
},
{
"path": "crates/story/examples/dock.rs",
"chars": 20077,
"preview": "use anyhow::{Context as _, Result};\nuse gpui::*;\nuse gpui_component::{\n IconName, Root, Sizable,\n button::{Button,"
},
{
"path": "crates/story/examples/editor.rs",
"chars": 39205,
"preview": "use std::{\n ops::Range,\n path::PathBuf,\n rc::Rc,\n str::FromStr,\n sync::{Arc, RwLock},\n time::Duration,"
},
{
"path": "crates/story/examples/fixtures/completion_items.json",
"chars": 5479,
"preview": "[\n {\n \"label\": \"as\",\n \"detail\": \"as TYPE\",\n \"documentation\": \"Perform a safe type cast.\\n\\n## Example:\\n```rus"
},
{
"path": "crates/story/examples/fixtures/test.astro",
"chars": 2710,
"preview": "---\n// @ts-nocheck\n// This file demonstrates Astro 5 syntax highlighting features.\n// Frontmatter: TypeScript/JavaScript"
},
{
"path": "crates/story/examples/fixtures/test.c",
"chars": 2323,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define MAX_NAME_LENGTH 100\n#define BUFFER"
},
{
"path": "crates/story/examples/fixtures/test.go",
"chars": 1873,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Default timeout duration for operations\n"
},
{
"path": "crates/story/examples/fixtures/test.html",
"chars": 4080,
"preview": "<article>\n <h1>A simple HTML document</h1>\n <div>\n Here is a test in div.\n <p>\n This is a"
},
{
"path": "crates/story/examples/fixtures/test.js",
"chars": 1791,
"preview": "const fs = require(\"fs\");\n\nconst getName = function () {\n return \"John Doe\";\n};\n\n/**\n * A class representing a HelloWor"
},
{
"path": "crates/story/examples/fixtures/test.json",
"chars": 446,
"preview": "[\n {\n \"name\": \"GPUI Component\",\n \"description\": \"UI components for building fantastic desktop application by usin"
},
{
"path": "crates/story/examples/fixtures/test.kt",
"chars": 2755,
"preview": "package hello\n\nimport kotlin.math.roundToInt\n\nconst val VERSION = \"1.0.0\"\n\ndata class Config(\n val timeout: Int = 500"
},
{
"path": "crates/story/examples/fixtures/test.lua",
"chars": 3307,
"preview": "--[[\n HelloWorld module demonstrating Lua syntax highlighting\n Version: 1.0.0\n--]]\n\nlocal VERSION = \"1.0.0\"\n\n-- Mo"
},
{
"path": "crates/story/examples/fixtures/test.md",
"chars": 5474,
"preview": "# Hello, **World**!\n\nBuild Status [ throws {\n let client = HttpClient.new("
},
{
"path": "crates/story/examples/fixtures/test.php",
"chars": 1623,
"preview": "<?php\n\n// This file is only used for syntax highlighting fixtures.\n// Intentionally small and dependency-free.\n\ndeclare("
},
{
"path": "crates/story/examples/fixtures/test.py",
"chars": 2327,
"preview": "from __future__ import annotations\nfrom typing import Optional, List, Dict, Any\nfrom dataclasses import dataclass\nfrom d"
},
{
"path": "crates/story/examples/fixtures/test.rb",
"chars": 1918,
"preview": "require 'json'\nrequire 'date'\n\n# Module for logging functionality\nmodule Logging\n LOG_LEVELS = %i[debug info warn error"
},
{
"path": "crates/story/examples/fixtures/test.rs",
"chars": 27299,
"preview": "use serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\nuse std::time::Duration;\nuse tokio::time;\n\n// Versio"
},
{
"path": "crates/story/examples/fixtures/test.sql",
"chars": 85,
"preview": "SELECT *\nFROM users\nWHERE email ilike '%test%'\n AND deleted_at IS NOT NULL\nLIMIT 1;\n"
},
{
"path": "crates/story/examples/fixtures/test.svelte",
"chars": 2973,
"preview": "<script lang=\"ts\">\n\t// Keep the following line to suppress type checking errors in this example\n\t// @ts-nocheck\n\timport "
},
{
"path": "crates/story/examples/fixtures/test.ts",
"chars": 1102,
"preview": "import fs, { readFile } from \"fs\";\n\nconst VERSION = \"1.0.0\";\n\nclass HelloWorld {\n private name: string;\n private creat"
},
{
"path": "crates/story/examples/fixtures/test.zig",
"chars": 2273,
"preview": "const std = @import(\"std\");\nconst json = std.json;\nconst time = std.time;\nconst HashMap = std.HashMap;\n\npub const VERSIO"
},
{
"path": "crates/story/examples/html.rs",
"chars": 2373,
"preview": "use gpui::*;\nuse gpui_component::{\n ActiveTheme as _,\n highlighter::Language,\n input::{Input, InputState, TabSi"
},
{
"path": "crates/story/examples/large-text.rs",
"chars": 5475,
"preview": "use gpui::*;\nuse gpui_component::{\n ActiveTheme, Selectable, Sizable, WindowExt,\n button::{Button, ButtonVariants "
},
{
"path": "crates/story/examples/markdown.rs",
"chars": 5773,
"preview": "use gpui::{prelude::FluentBuilder as _, *};\nuse gpui_component::{\n ActiveTheme as _, IconName, Sizable as _,\n butt"
},
{
"path": "crates/story/examples/stream_markdown.rs",
"chars": 4010,
"preview": "use gpui::*;\nuse gpui_component::{\n button::Button,\n h_flex,\n text::{TextView, TextViewState},\n v_flex,\n};\nu"
},
{
"path": "crates/story/examples/tiles.rs",
"chars": 14572,
"preview": "use anyhow::{Context as _, Result};\nuse gpui::*;\nuse gpui_component::{\n ActiveTheme, Root, Sizable, TitleBar,\n doc"
},
{
"path": "crates/story/src/app_menus.rs",
"chars": 4876,
"preview": "use gpui::{App, Entity, Menu, MenuItem, SharedString};\nuse gpui_component::{\n ActiveTheme as _, GlobalState, Theme, T"
},
{
"path": "crates/story/src/embedded_themes.rs",
"chars": 2019,
"preview": "#[cfg(target_family = \"wasm\")]\nuse std::collections::HashMap;\n\n#[cfg(target_family = \"wasm\")]\npub fn embedded_themes() -"
},
{
"path": "crates/story/src/fixtures/counters.json",
"chars": 30820,
"preview": "[\n { \"symbol\": \"AAPL\", \"name\": \"Apple Inc.\", \"market\": \"US\" },\n { \"symbol\": \"MSFT\", \"name\": \"Microsoft Corp.\", \"market"
},
{
"path": "crates/story/src/fixtures/countries.json",
"chars": 10406,
"preview": "[\n { \"name\": \"Afghanistan\", \"code\": \"AF\" },\n { \"name\": \"Åland Islands\", \"code\": \"AX\" },\n { \"name\": \"Albania\", \"code\":"
},
{
"path": "crates/story/src/fixtures/daily-devices.json",
"chars": 9429,
"preview": "[\n {\n \"date\": \"Apr 1\",\n \"desktop\": 222,\n \"mobile\": 111,\n \"tablet\": 67,\n \"watch\": 28\n },\n {\n \"date\":"
},
{
"path": "crates/story/src/fixtures/monthly-devices.json",
"chars": 450,
"preview": "[\n {\n \"month\": \"Jan\",\n \"desktop\": 186.0,\n \"color_alpha\": 0.5\n },\n {\n \"month\": \"Feb\",\n \"desktop\": 305.0"
},
{
"path": "crates/story/src/fixtures/stock-prices.json",
"chars": 620,
"preview": "[\n {\n \"date\": \"Jan\",\n \"open\": 100.0,\n \"high\": 112.0,\n \"low\": 95.0,\n \"close\": 110.0\n },\n {\n \"date\": "
},
{
"path": "crates/story/src/gallery.rs",
"chars": 15456,
"preview": "use gpui::{prelude::*, *};\nuse gpui_component::{\n ActiveTheme as _, Icon, IconName, h_flex,\n input::{Input, InputE"
},
{
"path": "crates/story/src/lib.rs",
"chars": 21601,
"preview": "use gpui::{\n Action, AnyElement, AnyView, App, AppContext, Bounds, Context, Div, Entity, EventEmitter,\n FocusHandl"
},
{
"path": "crates/story/src/main.rs",
"chars": 495,
"preview": "use gpui_component_assets::Assets;\nuse gpui_component_story::{Gallery, init, create_new_window};\n\nfn main() {\n let ap"
},
{
"path": "crates/story/src/stories/accordion_story.rs",
"chars": 8496,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement as _,\n Render, S"
},
{
"path": "crates/story/src/stories/alert_dialog_story.rs",
"chars": 17414,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, InteractiveElement as _, IntoElement,\n Pare"
},
{
"path": "crates/story/src/stories/alert_story.rs",
"chars": 8351,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/avatar_story.rs",
"chars": 10459,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/badge_story.rs",
"chars": 6489,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/breadcrumb_story.rs",
"chars": 3257,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/button_story.rs",
"chars": 41884,
"preview": "use gpui::{\n Action, App, AppContext as _, Axis, ClickEvent, Context, Entity, Focusable, InteractiveElement,\n Into"
},
{
"path": "crates/story/src/stories/calendar_story.rs",
"chars": 2282,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement as _,\n Render, S"
},
{
"path": "crates/story/src/stories/chart_story/chart_story.rs",
"chars": 14198,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, Hsla, IntoElement, ParentElement,\n Render, "
},
{
"path": "crates/story/src/stories/chart_story/stacked_bar_chart.rs",
"chars": 3598,
"preview": "// You can draw any chart you want by using the `Plot`.\n\nuse gpui::{App, Bounds, Pixels, TextAlign, Window, px};\nuse gpu"
},
{
"path": "crates/story/src/stories/chart_story.rs",
"chars": 109,
"preview": "mod chart_story;\nmod stacked_bar_chart;\n\npub use chart_story::*;\npub use stacked_bar_chart::StackedBarChart;\n"
},
{
"path": "crates/story/src/stories/checkbox_story.rs",
"chars": 6109,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,\n Window, div"
},
{
"path": "crates/story/src/stories/clipboard_story.rs",
"chars": 3240,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, SharedString,\n Style"
},
{
"path": "crates/story/src/stories/collapsible_story.rs",
"chars": 7833,
"preview": "use gpui::div;\nuse gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Ren"
},
{
"path": "crates/story/src/stories/color_picker_story.rs",
"chars": 2068,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, Hsla, IntoElement, ParentElement as _, Render,\n Styled a"
},
{
"path": "crates/story/src/stories/data_table_story.rs",
"chars": 45498,
"preview": "use std::{\n ops::Range,\n sync::LazyLock,\n time::{self, Duration},\n};\n\nuse fake::Fake;\nuse gpui::{\n Action, A"
},
{
"path": "crates/story/src/stories/date_picker_story.rs",
"chars": 8124,
"preview": "use chrono::{Datelike, Days, Duration, Utc};\nuse gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, P"
},
{
"path": "crates/story/src/stories/description_list_story.rs",
"chars": 6678,
"preview": "use gpui::*;\nuse gpui::{\n Action, App, AppContext, Axis, Context, Entity, FocusHandle, Focusable, IntoElement,\n Pa"
},
{
"path": "crates/story/src/stories/dialog_story.rs",
"chars": 23390,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, InteractiveElement as _, IntoElement,\n Pare"
},
{
"path": "crates/story/src/stories/divider_story.rs",
"chars": 3219,
"preview": "use crate::section;\nuse gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Sty"
},
{
"path": "crates/story/src/stories/dropdown_button_story.rs",
"chars": 9123,
"preview": "use gpui::{\n Action, App, AppContext as _, Context, Corner, Entity, Focusable, IntoElement,\n ParentElement as _, R"
},
{
"path": "crates/story/src/stories/editor_story.rs",
"chars": 1373,
"preview": "use gpui::{App, AppContext as _, Context, Entity, IntoElement, Render, Styled, Window};\n\nuse gpui_component::input::*;\n\n"
},
{
"path": "crates/story/src/stories/form_story.rs",
"chars": 11569,
"preview": "use gpui::{\n App, AppContext, Axis, Context, Entity, FocusHandle, Focusable, InteractiveElement,\n IntoElement, Par"
},
{
"path": "crates/story/src/stories/group_box_story.rs",
"chars": 5251,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render,\n StyleRefinement, St"
},
{
"path": "crates/story/src/stories/hover_card_story.rs",
"chars": 8120,
"preview": "use gpui::{\n App, AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render, Styled as _,\n Window,"
},
{
"path": "crates/story/src/stories/icon_story.rs",
"chars": 3980,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/image_story.rs",
"chars": 1370,
"preview": "use crate::section;\nuse gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement"
},
{
"path": "crates/story/src/stories/input_story.rs",
"chars": 11615,
"preview": "use gpui::{\n App, AppContext as _, ClickEvent, Context, Entity, InteractiveElement, IntoElement,\n ParentElement as"
},
{
"path": "crates/story/src/stories/kbd_story.rs",
"chars": 2354,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, Keystroke, ParentElement, Render,\n Styled, "
},
{
"path": "crates/story/src/stories/label_story.rs",
"chars": 7636,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, SharedString,\n Style"
},
{
"path": "crates/story/src/stories/list_story.rs",
"chars": 20111,
"preview": "use std::{rc::Rc, time::Duration};\n\nuse fake::Fake;\nuse gpui::{\n App, AppContext, Context, ElementId, Entity, FocusHa"
},
{
"path": "crates/story/src/stories/menu_story.rs",
"chars": 17278,
"preview": "use gpui::{\n Action, App, AppContext, Context, Corner, Entity, InteractiveElement, IntoElement, KeyBinding,\n Paren"
},
{
"path": "crates/story/src/stories/mod.rs",
"chars": 4857,
"preview": "use gpui::{AnyView, App, AppContext as _, Entity, Hsla, Pixels, Render, Window, px};\nuse gpui_component::dock::PanelCont"
},
{
"path": "crates/story/src/stories/notification_story.rs",
"chars": 12190,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, InteractiveElement as _, IntoElement,\n Pare"
},
{
"path": "crates/story/src/stories/number_input_story.rs",
"chars": 9578,
"preview": "use gpui::{\n App, AppContext as _, Context, Entity, Focusable, InteractiveElement, IntoElement,\n ParentElement as "
},
{
"path": "crates/story/src/stories/otp_input_story.rs",
"chars": 5012,
"preview": "use gpui::{\n prelude::FluentBuilder as _, px, App, AppContext as _, Context, Entity, Focusable,\n InteractiveElemen"
},
{
"path": "crates/story/src/stories/pagination_story.rs",
"chars": 5643,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/popover_story.rs",
"chars": 15211,
"preview": "use gpui::{\n Action, App, AppContext, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,\n Half, "
},
{
"path": "crates/story/src/stories/progress_story.rs",
"chars": 8360,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled, Task,\n Windo"
},
{
"path": "crates/story/src/stories/radio_story.rs",
"chars": 5820,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,\n Window, div"
},
{
"path": "crates/story/src/stories/rating_story.rs",
"chars": 5938,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled, Window,\n};\nuse "
},
{
"path": "crates/story/src/stories/resizable_story.rs",
"chars": 3806,
"preview": "use gpui::{\n AnyElement, App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement,\n ParentElement as "
},
{
"path": "crates/story/src/stories/scrollbar_story.rs",
"chars": 6497,
"preview": "use std::rc::Rc;\n\nuse gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, "
},
{
"path": "crates/story/src/stories/select_story.rs",
"chars": 10687,
"preview": "use gpui::*;\nuse gpui_component::{button::*, checkbox::*, divider::*, input::*, select::*, *};\nuse itertools::Itertools "
},
{
"path": "crates/story/src/stories/settings_story.rs",
"chars": 19129,
"preview": "use gpui::{\n App, AppContext, Axis, Context, Element, Entity, FocusHandle, Focusable, Global, IntoElement,\n Parent"
},
{
"path": "crates/story/src/stories/sheet_story.rs",
"chars": 17731,
"preview": "use std::{sync::Arc, time::Duration};\n\nuse fake::Fake;\nuse gpui::{\n App, AppContext, Context, Entity, FocusHandle, Fo"
},
{
"path": "crates/story/src/stories/sidebar_story.rs",
"chars": 19111,
"preview": "use std::collections::HashMap;\n\nuse gpui::{\n Action, App, AppContext, ClickEvent, Context, Entity, Focusable, IntoEle"
},
{
"path": "crates/story/src/stories/skeleton_story.rs",
"chars": 2649,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,\n Window, px,"
},
{
"path": "crates/story/src/stories/slider_story.rs",
"chars": 12087,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, Hsla, IntoElement, ParentElement, Render,\n SharedString,"
},
{
"path": "crates/story/src/stories/spinner_story.rs",
"chars": 2461,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,\n Window, px,"
},
{
"path": "crates/story/src/stories/stepper_story.rs",
"chars": 8956,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,\n Subscriptio"
},
{
"path": "crates/story/src/stories/switch_story.rs",
"chars": 4767,
"preview": "use gpui::{\n App, AppContext, Context, Div, Entity, FocusHandle, Focusable, IntoElement, ParentElement,\n Render, S"
},
{
"path": "crates/story/src/stories/table_story.rs",
"chars": 8515,
"preview": "use gpui::{\n App, AppContext as _, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement,\n Render, S"
},
{
"path": "crates/story/src/stories/tabs_story.rs",
"chars": 10889,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/tag_story.rs",
"chars": 5851,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render,\n Styled"
},
{
"path": "crates/story/src/stories/textarea_story.rs",
"chars": 7387,
"preview": "use gpui::{\n App, AppContext as _, ClickEvent, Context, Entity, Focusable, IntoElement, ParentElement as _,\n Rende"
},
{
"path": "crates/story/src/stories/theme_story/checkerboard.rs",
"chars": 2737,
"preview": "use gpui::*;\nuse gpui_component::ActiveTheme as _;\n\n#[derive(IntoElement)]\npub struct Checkerboard {\n children: Vec<A"
},
{
"path": "crates/story/src/stories/theme_story/color_theme_story.rs",
"chars": 31814,
"preview": "use gpui::{prelude::FluentBuilder, *};\nuse gpui_component::{\n ActiveTheme as _, Icon, IconName, IndexPath, StyledExt "
},
{
"path": "crates/story/src/stories/theme_story/mapper.rs",
"chars": 9371,
"preview": "/// A compatibility bridge for mapping theme color keys.\n///\n/// This module provides a way to translate between the leg"
},
{
"path": "crates/story/src/stories/theme_story/mod.rs",
"chars": 83,
"preview": "mod checkerboard;\nmod color_theme_story;\nmod mapper;\n\npub use color_theme_story::*;"
},
{
"path": "crates/story/src/stories/toggle_story.rs",
"chars": 11672,
"preview": "use gpui::{\n App, AppContext as _, Context, Entity, FocusHandle, Focusable, IntoElement, ParentElement as _,\n Rend"
},
{
"path": "crates/story/src/stories/tooltip_story.rs",
"chars": 4590,
"preview": "use gpui::{\n App, AppContext, Context, Entity, Focusable, InteractiveElement, KeyBinding, ParentElement,\n Render, "
},
{
"path": "crates/story/src/stories/tree_story.rs",
"chars": 7600,
"preview": "use std::path::PathBuf;\n\nuse autocorrect::ignorer::Ignorer;\nuse gpui::{\n App, AppContext, Context, Entity, Interactiv"
},
{
"path": "crates/story/src/stories/virtual_list_story.rs",
"chars": 12138,
"preview": "use std::{ops::Range, rc::Rc};\n\nuse gpui::{\n App, AppContext, Context, Div, Entity, FocusHandle, Focusable, Interacti"
},
{
"path": "crates/story/src/stories/welcome_story.rs",
"chars": 1439,
"preview": "use gpui::{\n App, AppContext, Context, Entity, FocusHandle, Focusable, Render, Styled as _, Window, px,\n};\n\nuse gpui_"
},
{
"path": "crates/story/src/themes.rs",
"chars": 3270,
"preview": "use gpui::{Action, App, SharedString};\nuse gpui_component::{Theme, ThemeMode, ThemeRegistry, scroll::ScrollbarShow};\nuse"
},
{
"path": "crates/story/src/title_bar.rs",
"chars": 8274,
"preview": "use std::rc::Rc;\n\nuse gpui::{\n AnyElement, App, AppContext, Context, Corner, Entity, FocusHandle, InteractiveElement "
},
{
"path": "crates/story-web/.cargo/config.toml",
"chars": 47,
"preview": "[target.wasm32-unknown-unknown]\nrustflags = []\n"
},
{
"path": "crates/story-web/Cargo.toml",
"chars": 554,
"preview": "[package]\nname = \"gpui-component-story-web\"\nversion = \"0.5.1\"\npublish = false\nedition.workspace = true\n\n[lib]\ncrate-type"
},
{
"path": "crates/story-web/Makefile",
"chars": 1533,
"preview": ".PHONY: help dev build-wasm build-web build clean install\n\nhelp: ## Show help information\n\t@echo \"GPUI Component Story W"
},
{
"path": "crates/story-web/README.md",
"chars": 1326,
"preview": "# GPUI Component Story Web\n\nWeb-based component gallery for GPUI Component library.\n\n**Live Demo**: https://longbridge.g"
},
{
"path": "crates/story-web/rust-toolchain.toml",
"chars": 104,
"preview": "[toolchain]\nchannel = \"nightly\"\ncomponents = [\"rustfmt\", \"clippy\"]\ntargets = [\"wasm32-unknown-unknown\"]\n"
},
{
"path": "crates/story-web/scripts/build-wasm.sh",
"chars": 1441,
"preview": "#!/bin/bash\nset -e\n\n# Colors for output\nRED='\\033[0;31m'\nGREEN='\\033[0;32m'\nYELLOW='\\033[1;33m'\nNC='\\033[0m' # No Color\n"
},
{
"path": "crates/story-web/src/lib.rs",
"chars": 1268,
"preview": "use gpui::{prelude::*, *};\nuse gpui_component::Root;\nuse gpui_component_assets::Assets;\nuse gpui_component_story::{Galle"
},
{
"path": "crates/story-web/www/.gitignore",
"chars": 234,
"preview": "# Dependencies\nnode_modules/\nbun.lockb\n\n# Build outputs\ndist/\n*.local\n\n# WASM generated files\nsrc/wasm/\n!src/wasm/.gitke"
},
{
"path": "crates/story-web/www/.prettierrc",
"chars": 132,
"preview": "{\n \"semi\": true,\n \"singleQuote\": true,\n \"tabWidth\": 2,\n \"trailingComma\": \"es5\",\n \"printWidth\": 100,\n \"arrowParens\""
},
{
"path": "crates/story-web/www/index.html",
"chars": 1623,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-w"
},
{
"path": "crates/story-web/www/package.json",
"chars": 530,
"preview": "{\n \"name\": \"gpui-component-story-web\",\n \"version\": \"0.5.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n "
},
{
"path": "crates/story-web/www/src/main.js",
"chars": 847,
"preview": "async function init() {\n const loadingEl = document.getElementById('loading');\n const appEl = document.getElementById("
},
{
"path": "crates/story-web/www/vite.config.js",
"chars": 1804,
"preview": "import { defineConfig } from 'vite';\nimport wasm from 'vite-plugin-wasm';\nimport { viteStaticCopy } from 'vite-plugin-st"
},
{
"path": "crates/ui/Cargo.toml",
"chars": 5074,
"preview": "[package]\ndescription = \"UI components for building fantastic desktop application by using GPUI.\"\nkeywords = [\"desktop\","
},
{
"path": "crates/ui/LICENSE-APACHE",
"chars": 10305,
"preview": "Copyright 2024 - 2025 Longbridge <https://longbridge.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "crates/ui/build.rs",
"chars": 640,
"preview": "use std::{fs, path::Path};\n\nfn main() {\n // Tell Cargo to rerun this build script if any SVG file in assets/icons cha"
},
{
"path": "crates/ui/locales/ui.yml",
"chars": 3463,
"preview": "_version: 2\nCalendar:\n week.0:\n en: Su\n zh-CN: 日\n zh-HK: 日\n it: Do\n week.1:\n en: Mo\n zh-CN: 一\n zh"
},
{
"path": "crates/ui/src/accordion.rs",
"chars": 10700,
"preview": "use std::{cell::RefCell, collections::HashSet, rc::Rc, sync::Arc};\n\nuse gpui::{\n AnyElement, App, ElementId, Interact"
},
{
"path": "crates/ui/src/actions.rs",
"chars": 389,
"preview": "use gpui::{actions, Action};\nuse serde::Deserialize;\n\n#[derive(Clone, Action, PartialEq, Eq, Deserialize)]\n#[action(name"
},
{
"path": "crates/ui/src/alert.rs",
"chars": 8459,
"preview": "use std::rc::Rc;\n\nuse gpui::{\n App, ClickEvent, ElementId, Empty, Hsla, InteractiveElement, IntoElement, ParentElemen"
},
{
"path": "crates/ui/src/anchored.rs",
"chars": 11402,
"preview": "//! This is a fork of gpui's anchored element that adds support for offsetting\n//! https://github.com/zed-industries/zed"
},
{
"path": "crates/ui/src/animation.rs",
"chars": 562,
"preview": "/// A cubic bezier function like CSS `cubic-bezier`.\n///\n/// Builder:\n///\n/// https://cubic-bezier.com\npub fn cubic_bezi"
},
{
"path": "crates/ui/src/async_util.rs",
"chars": 336,
"preview": "//! Cross-platform async utilities for both native and WASM targets.\n\n// For native targets, re-export smol's primitives"
},
{
"path": "crates/ui/src/avatar/avatar.rs",
"chars": 5065,
"preview": "use gpui::{\n App, Div, Hsla, ImageSource, InteractiveElement, Interactivity, IntoElement,\n ParentElement as _, Ren"
},
{
"path": "crates/ui/src/avatar/avatar_group.rs",
"chars": 3617,
"preview": "use gpui::{\n div, prelude::FluentBuilder as _, Div, InteractiveElement, Interactivity, IntoElement,\n ParentElement"
},
{
"path": "crates/ui/src/avatar/mod.rs",
"chars": 1154,
"preview": "mod avatar;\nmod avatar_group;\n\npub use avatar::*;\npub use avatar_group::*;\n\nuse crate::{Icon, Size, StyledExt as _};\nuse"
},
{
"path": "crates/ui/src/badge.rs",
"chars": 5215,
"preview": "use gpui::{\n div, prelude::FluentBuilder, px, relative, AnyElement, App, Hsla, IntoElement, ParentElement,\n Render"
},
{
"path": "crates/ui/src/breadcrumb.rs",
"chars": 4670,
"preview": "use std::rc::Rc;\n\nuse gpui::{\n div, prelude::FluentBuilder as _, App, ClickEvent, ElementId, InteractiveElement as _,"
},
{
"path": "crates/ui/src/button/button.rs",
"chars": 33248,
"preview": "use std::rc::Rc;\n\nuse crate::{\n ActiveTheme, Colorize as _, Disableable, FocusableExt as _, Icon, IconName, Selectabl"
},
{
"path": "crates/ui/src/button/button_group.rs",
"chars": 9910,
"preview": "use gpui::{\n div, prelude::FluentBuilder as _, App, Axis, Corners, Edges, ElementId, InteractiveElement,\n IntoElem"
},
{
"path": "crates/ui/src/button/button_icon.rs",
"chars": 4746,
"preview": "use crate::{Icon, Sizable, Size, progress::ProgressCircle, spinner::Spinner};\nuse gpui::{App, IntoElement, RenderOnce, W"
},
{
"path": "crates/ui/src/button/dropdown_button.rs",
"chars": 7429,
"preview": "use gpui::{\n App, Context, Corner, Corners, Edges, ElementId, InteractiveElement as _, IntoElement,\n ParentElement"
},
{
"path": "crates/ui/src/button/mod.rs",
"chars": 203,
"preview": "mod button;\nmod button_group;\nmod button_icon;\nmod dropdown_button;\nmod toggle;\n\npub use button::*;\npub use button_group"
},
{
"path": "crates/ui/src/button/toggle.rs",
"chars": 9606,
"preview": "use std::{cell::Cell, rc::Rc};\n\nuse gpui::{\n AnyElement, App, ElementId, InteractiveElement, IntoElement, ParentEleme"
},
{
"path": "crates/ui/src/chart/area_chart.rs",
"chars": 5256,
"preview": "use std::rc::Rc;\n\nuse gpui::{App, Background, Bounds, Hsla, Pixels, SharedString, Window, px};\nuse gpui_component_macros"
},
{
"path": "crates/ui/src/chart/bar_chart.rs",
"chars": 4937,
"preview": "use std::rc::Rc;\n\nuse gpui::{App, Bounds, Hsla, Pixels, SharedString, TextAlign, Window, px};\nuse gpui_component_macros:"
},
{
"path": "crates/ui/src/chart/candlestick_chart.rs",
"chars": 7098,
"preview": "use std::rc::Rc;\n\nuse gpui::{App, Bounds, Hsla, PathBuilder, Pixels, SharedString, Window, fill, px};\nuse gpui_component"
},
{
"path": "crates/ui/src/chart/line_chart.rs",
"chars": 4683,
"preview": "use std::rc::Rc;\n\nuse gpui::{App, Bounds, Hsla, Pixels, SharedString, Window, px};\nuse gpui_component_macros::IntoPlot;\n"
},
{
"path": "crates/ui/src/chart/mod.rs",
"chars": 2414,
"preview": "mod area_chart;\nmod bar_chart;\nmod candlestick_chart;\nmod line_chart;\nmod pie_chart;\n\npub use area_chart::AreaChart;\npub"
},
{
"path": "crates/ui/src/chart/pie_chart.rs",
"chars": 4083,
"preview": "use std::rc::Rc;\n\nuse gpui::{App, Bounds, Hsla, Pixels, Window};\nuse gpui_component_macros::IntoPlot;\nuse num_traits::Ze"
},
{
"path": "crates/ui/src/checkbox.rs",
"chars": 10200,
"preview": "use std::{rc::Rc, time::Duration};\n\nuse crate::{\n ActiveTheme, Disableable, FocusableExt, IconName, Selectable, Sizab"
},
{
"path": "crates/ui/src/clipboard.rs",
"chars": 3759,
"preview": "use std::{rc::Rc, time::Duration};\n\nuse gpui::{\n prelude::FluentBuilder, App, ClipboardItem, ElementId, IntoElement, "
}
]
// ... and 347 more files (download for full content)
About this extraction
This page contains the full source code of the longbridge/gpui-component GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 547 files (4.2 MB), approximately 1.1M tokens, and a symbol index with 5571 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.