Detailed changes
@@ -3525,6 +3525,33 @@ dependencies = [
"theme",
]
+[[package]]
+name = "component_preview"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "client",
+ "collections",
+ "component",
+ "db",
+ "fs",
+ "gpui",
+ "language",
+ "log",
+ "node_runtime",
+ "notifications",
+ "project",
+ "release_channel",
+ "reqwest_client",
+ "session",
+ "settings",
+ "theme",
+ "ui",
+ "ui_input",
+ "uuid",
+ "workspace",
+]
+
[[package]]
name = "compression-codecs"
version = "0.4.31"
@@ -20643,6 +20670,7 @@ dependencies = [
"collections",
"command_palette",
"component",
+ "component_preview",
"copilot",
"crashes",
"dap",
@@ -20748,7 +20776,6 @@ dependencies = [
"tree-sitter-md",
"tree-sitter-rust",
"ui",
- "ui_input",
"ui_prompt",
"url",
"urlencoding",
@@ -39,6 +39,7 @@ members = [
"crates/command_palette",
"crates/command_palette_hooks",
"crates/component",
+ "crates/component_preview",
"crates/context_server",
"crates/copilot",
"crates/crashes",
@@ -275,6 +276,7 @@ collections = { path = "crates/collections", version = "0.1.0" }
command_palette = { path = "crates/command_palette" }
command_palette_hooks = { path = "crates/command_palette_hooks" }
component = { path = "crates/component" }
+component_preview = { path = "crates/component_preview" }
context_server = { path = "crates/context_server" }
copilot = { path = "crates/copilot" }
crashes = { path = "crates/crashes" }
@@ -0,0 +1,45 @@
+[package]
+name = "component_preview"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "GPL-3.0-or-later"
+
+[lints]
+workspace = true
+
+[lib]
+path = "src/component_preview.rs"
+
+[features]
+default = []
+preview = []
+test-support = ["db/test-support"]
+
+[dependencies]
+anyhow.workspace = true
+client.workspace = true
+collections.workspace = true
+component.workspace = true
+db.workspace = true
+fs.workspace = true
+gpui.workspace = true
+language.workspace = true
+log.workspace = true
+node_runtime.workspace = true
+notifications.workspace = true
+project.workspace = true
+release_channel.workspace = true
+reqwest_client.workspace = true
+session.workspace = true
+settings.workspace = true
+theme.workspace = true
+ui.workspace = true
+ui_input.workspace = true
+uuid.workspace = true
+workspace.workspace = true
+
+[[example]]
+name = "component_preview"
+path = "examples/component_preview.rs"
+required-features = ["preview"]
@@ -0,0 +1 @@
+LICENSE-GPL
@@ -0,0 +1,18 @@
+//! Component Preview Example
+//!
+//! Run with: `cargo run -p component_preview --example component_preview --features="preview"`
+//!
+//! To use this in other projects, add the following to your `Cargo.toml`:
+//!
+//! ```toml
+//! [dependencies]
+//! component_preview = { path = "../component_preview", features = ["preview"] }
+//!
+//! [[example]]
+//! name = "component_preview"
+//! path = "examples/component_preview.rs"
+//! ```
+
+fn main() {
+ component_preview::run_component_preview();
+}
@@ -1,7 +1,4 @@
-//! # Component Preview
-//!
-//! A view for exploring Zed components.
-
+mod component_preview_example;
mod persistence;
use client::UserStore;
@@ -11,18 +8,21 @@ use gpui::{
App, Entity, EventEmitter, FocusHandle, Focusable, Task, WeakEntity, Window, list, prelude::*,
};
use gpui::{ListState, ScrollHandle, ScrollStrategy, UniformListScrollHandle};
-use languages::LanguageRegistry;
+use language::LanguageRegistry;
use notifications::status_toast::{StatusToast, ToastIcon};
use persistence::COMPONENT_PREVIEW_DB;
use project::Project;
use std::{iter::Iterator, ops::Range, sync::Arc};
use ui::{ButtonLike, Divider, HighlightedLabel, ListItem, ListSubHeader, Tooltip, prelude::*};
use ui_input::InputField;
+use workspace::AppState;
use workspace::{
- AppState, Item, ItemId, SerializableItem, Workspace, WorkspaceId, delete_unloaded_items,
- item::ItemEvent,
+ Item, ItemId, SerializableItem, Workspace, WorkspaceId, delete_unloaded_items, item::ItemEvent,
};
+#[allow(unused_imports)]
+pub use component_preview_example::*;
+
pub fn init(app_state: Arc<AppState>, cx: &mut App) {
workspace::register_serializable_item::<ComponentPreview>(cx);
@@ -0,0 +1,145 @@
+/// Run the component preview application.
+///
+/// This initializes the application with minimal required infrastructure
+/// and opens a workspace with the ComponentPreview item.
+#[cfg(feature = "preview")]
+pub fn run_component_preview() {
+ use fs::RealFs;
+ use gpui::{
+ AppContext as _, Application, Bounds, KeyBinding, WindowBounds, WindowOptions, actions,
+ size,
+ };
+
+ use client::{Client, UserStore};
+ use language::LanguageRegistry;
+ use node_runtime::NodeRuntime;
+ use project::Project;
+ use reqwest_client::ReqwestClient;
+ use session::{AppSession, Session};
+ use std::sync::Arc;
+ use ui::{App, px};
+ use workspace::{AppState, Workspace, WorkspaceStore};
+
+ use crate::{ComponentPreview, init};
+
+ actions!(zed, [Quit]);
+
+ fn quit(_: &Quit, cx: &mut App) {
+ cx.quit();
+ }
+
+ Application::new().run(|cx| {
+ component::init();
+
+ cx.on_action(quit);
+ cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]);
+ let version = release_channel::AppVersion::load(env!("CARGO_PKG_VERSION"), None, None);
+ release_channel::init(version, cx);
+
+ let http_client =
+ ReqwestClient::user_agent("component_preview").expect("Failed to create HTTP client");
+ cx.set_http_client(Arc::new(http_client));
+
+ let fs = Arc::new(RealFs::new(None, cx.background_executor().clone()));
+ <dyn fs::Fs>::set_global(fs.clone(), cx);
+
+ settings::init(cx);
+ theme::init(theme::LoadThemes::JustBase, cx);
+
+ let languages = Arc::new(LanguageRegistry::new(cx.background_executor().clone()));
+ let client = Client::production(cx);
+ client::init(&client, cx);
+
+ let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
+ let session_id = uuid::Uuid::new_v4().to_string();
+ let session = cx.background_executor().block(Session::new(session_id));
+ let session = cx.new(|cx| AppSession::new(session, cx));
+ let node_runtime = NodeRuntime::unavailable();
+
+ let app_state = Arc::new(AppState {
+ languages,
+ client,
+ user_store,
+ workspace_store,
+ fs,
+ build_window_options: |_, _| Default::default(),
+ node_runtime,
+ session,
+ });
+ AppState::set_global(Arc::downgrade(&app_state), cx);
+
+ workspace::init(app_state.clone(), cx);
+ init(app_state.clone(), cx);
+
+ let size = size(px(1200.), px(800.));
+ let bounds = Bounds::centered(None, size, cx);
+
+ cx.open_window(
+ WindowOptions {
+ window_bounds: Some(WindowBounds::Windowed(bounds)),
+ ..Default::default()
+ },
+ {
+ move |window, cx| {
+ let app_state = app_state;
+ theme::setup_ui_font(window, cx);
+
+ let project = Project::local(
+ app_state.client.clone(),
+ app_state.node_runtime.clone(),
+ app_state.user_store.clone(),
+ app_state.languages.clone(),
+ app_state.fs.clone(),
+ None,
+ false,
+ cx,
+ );
+
+ let workspace = cx.new(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ app_state.clone(),
+ window,
+ cx,
+ )
+ });
+
+ workspace.update(cx, |workspace, cx| {
+ let weak_workspace = cx.entity().downgrade();
+ let language_registry = app_state.languages.clone();
+ let user_store = app_state.user_store.clone();
+
+ let component_preview = cx.new(|cx| {
+ ComponentPreview::new(
+ weak_workspace,
+ project,
+ language_registry,
+ user_store,
+ None,
+ None,
+ window,
+ cx,
+ )
+ .expect("Failed to create component preview")
+ });
+
+ workspace.add_item_to_active_pane(
+ Box::new(component_preview),
+ None,
+ true,
+ window,
+ cx,
+ );
+ });
+
+ workspace
+ }
+ },
+ )
+ .expect("Failed to open component preview window");
+
+ cx.activate(true);
+ });
+}
@@ -41,6 +41,7 @@ collab_ui.workspace = true
collections.workspace = true
command_palette.workspace = true
component.workspace = true
+component_preview.workspace = true
copilot.workspace = true
crashes.workspace = true
dap_adapters.workspace = true
@@ -148,7 +149,6 @@ ztracing.workspace = true
tracing.workspace = true
toolchain_selector.workspace = true
ui.workspace = true
-ui_input.workspace = true
ui_prompt.workspace = true
url.workspace = true
urlencoding.workspace = true
@@ -774,7 +774,7 @@ fn main() {
let app_state = app_state.clone();
- crate::zed::component_preview::init(app_state.clone(), cx);
+ component_preview::init(app_state.clone(), cx);
cx.spawn(async move |cx| {
while let Some(urls) = open_rx.next().await {
@@ -1,5 +1,4 @@
mod app_menus;
-pub mod component_preview;
pub mod edit_prediction_registry;
#[cfg(target_os = "macos")]
pub(crate) mod mac_only_instance;