Files
leptos-shadcn-ui/examples/leptire_file

404 lines
18 KiB
Plaintext

//! Enhanced lazy loading component with realistic simulation
use leptos::*;
use leptos::prelude::*;
/// Component metadata for enhanced lazy loading
#[derive(Clone)]
struct ComponentInfo {
name: String,
category: String,
estimated_size: String,
dependencies: Vec<String>,
description: String,
}
/// Enhanced lazy component wrapper with realistic simulation
#[component]
pub fn LazyComponentWrapper(
#[prop(into)] name: String,
) -> impl IntoView {
let (is_loaded, set_is_loaded) = signal(false);
let (is_loading, set_is_loading) = signal(false);
let (load_progress, set_load_progress) = signal(0.0);
// Component metadata based on name
let component_info = move || {
match name.as_str() {
"Alert" => ComponentInfo {
name: "Alert".to_string(),
category: "Form & Input".to_string(),
estimated_size: "12KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Displays important messages to users".to_string(),
},
"Badge" => ComponentInfo {
name: "Badge".to_string(),
category: "Form & Input".to_string(),
estimated_size: "8KB".to_string(),
dependencies: vec![],
description: "Small status indicators and labels".to_string(),
},
"Checkbox" => ComponentInfo {
name: "Checkbox".to_string(),
category: "Form & Input".to_string(),
estimated_size: "15KB".to_string(),
dependencies: vec![],
description: "Interactive checkbox input component".to_string(),
},
"Combobox" => ComponentInfo {
name: "Combobox".to_string(),
category: "Form & Input".to_string(),
estimated_size: "25KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Searchable dropdown with custom options".to_string(),
},
"Form" => ComponentInfo {
name: "Form".to_string(),
category: "Form & Input".to_string(),
estimated_size: "35KB".to_string(),
dependencies: vec!["leptos-hook-form".to_string()],
description: "Complete form handling with validation".to_string(),
},
"Input OTP" => ComponentInfo {
name: "Input OTP".to_string(),
category: "Form & Input".to_string(),
estimated_size: "18KB".to_string(),
dependencies: vec![],
description: "One-time password input fields".to_string(),
},
"Radio Group" => ComponentInfo {
name: "Radio Group".to_string(),
category: "Form & Input".to_string(),
estimated_size: "20KB".to_string(),
dependencies: vec![],
description: "Radio button group selection".to_string(),
},
"Select" => ComponentInfo {
name: "Select".to_string(),
category: "Form & Input".to_string(),
estimated_size: "22KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Dropdown selection component".to_string(),
},
"Slider" => ComponentInfo {
name: "Slider".to_string(),
category: "Form & Input".to_string(),
estimated_size: "16KB".to_string(),
dependencies: vec![],
description: "Range slider input component".to_string(),
},
"Switch" => ComponentInfo {
name: "Switch".to_string(),
category: "Form & Input".to_string(),
estimated_size: "14KB".to_string(),
dependencies: vec![],
description: "Toggle switch component".to_string(),
},
"Textarea" => ComponentInfo {
name: "Textarea".to_string(),
category: "Form & Input".to_string(),
estimated_size: "10KB".to_string(),
dependencies: vec![],
description: "Multi-line text input".to_string(),
},
"Toggle" => ComponentInfo {
name: "Toggle".to_string(),
category: "Form & Input".to_string(),
estimated_size: "12KB".to_string(),
dependencies: vec![],
description: "Button toggle component".to_string(),
},
"Accordion" => ComponentInfo {
name: "Accordion".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "28KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Collapsible content sections".to_string(),
},
"Breadcrumb" => ComponentInfo {
name: "Breadcrumb".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "18KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Navigation breadcrumb trail".to_string(),
},
"Collapsible" => ComponentInfo {
name: "Collapsible".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "20KB".to_string(),
dependencies: vec![],
description: "Expandable content container".to_string(),
},
"Command" => ComponentInfo {
name: "Command".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "32KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Command palette interface".to_string(),
},
"Navigation Menu" => ComponentInfo {
name: "Navigation Menu".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "40KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Complex navigation menu system".to_string(),
},
"Pagination" => ComponentInfo {
name: "Pagination".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "25KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Page navigation controls".to_string(),
},
"Scroll Area" => ComponentInfo {
name: "Scroll Area".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "15KB".to_string(),
dependencies: vec![],
description: "Custom scrollable container".to_string(),
},
"Skeleton" => ComponentInfo {
name: "Skeleton".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "12KB".to_string(),
dependencies: vec![],
description: "Loading placeholder components".to_string(),
},
"Tabs" => ComponentInfo {
name: "Tabs".to_string(),
category: "Layout & Navigation".to_string(),
estimated_size: "30KB".to_string(),
dependencies: vec![],
description: "Tabbed content interface".to_string(),
},
"Alert Dialog" => ComponentInfo {
name: "Alert Dialog".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "35KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Modal dialog with actions".to_string(),
},
"Dialog" => ComponentInfo {
name: "Dialog".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "30KB".to_string(),
dependencies: vec![],
description: "Modal dialog component".to_string(),
},
"Drawer" => ComponentInfo {
name: "Drawer".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "38KB".to_string(),
dependencies: vec![],
description: "Slide-out drawer panel".to_string(),
},
"Dropdown Menu" => ComponentInfo {
name: "Dropdown Menu".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "28KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Contextual dropdown menu".to_string(),
},
"Hover Card" => ComponentInfo {
name: "Hover Card".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "22KB".to_string(),
dependencies: vec![],
description: "Hover-triggered information card".to_string(),
},
"Menubar" => ComponentInfo {
name: "Menubar".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "45KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Horizontal menu bar".to_string(),
},
"Popover" => ComponentInfo {
name: "Popover".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "20KB".to_string(),
dependencies: vec![],
description: "Positioned popup content".to_string(),
},
"Sheet" => ComponentInfo {
name: "Sheet".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "32KB".to_string(),
dependencies: vec![],
description: "Slide-up sheet panel".to_string(),
},
"Toast" => ComponentInfo {
name: "Toast".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "25KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Notification toast messages".to_string(),
},
"Tooltip" => ComponentInfo {
name: "Tooltip".to_string(),
category: "Overlay & Feedback".to_string(),
estimated_size: "18KB".to_string(),
dependencies: vec![],
description: "Hover tooltip component".to_string(),
},
"Aspect Ratio" => ComponentInfo {
name: "Aspect Ratio".to_string(),
category: "Data & Media".to_string(),
estimated_size: "8KB".to_string(),
dependencies: vec![],
description: "Maintains aspect ratio container".to_string(),
},
"Calendar" => ComponentInfo {
name: "Calendar".to_string(),
category: "Data & Media".to_string(),
estimated_size: "50KB".to_string(),
dependencies: vec!["chrono".to_string()],
description: "Interactive calendar component".to_string(),
},
"Carousel" => ComponentInfo {
name: "Carousel".to_string(),
category: "Data & Media".to_string(),
estimated_size: "35KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Image/content carousel".to_string(),
},
"Context Menu" => ComponentInfo {
name: "Context Menu".to_string(),
category: "Data & Media".to_string(),
estimated_size: "30KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Right-click context menu".to_string(),
},
"Date Picker" => ComponentInfo {
name: "Date Picker".to_string(),
category: "Data & Media".to_string(),
estimated_size: "45KB".to_string(),
dependencies: vec!["chrono".to_string()],
description: "Date selection component".to_string(),
},
"Progress" => ComponentInfo {
name: "Progress".to_string(),
category: "Data & Media".to_string(),
estimated_size: "12KB".to_string(),
dependencies: vec![],
description: "Progress bar component".to_string(),
},
"Table" => ComponentInfo {
name: "Table".to_string(),
category: "Data & Media".to_string(),
estimated_size: "40KB".to_string(),
dependencies: vec!["lucide-leptos".to_string()],
description: "Data table with sorting".to_string(),
},
_ => ComponentInfo {
name: name.clone(),
category: "Unknown".to_string(),
estimated_size: "20KB".to_string(),
dependencies: vec![],
description: "Component description not available".to_string(),
},
}
};
let load_component = move |_| {
set_is_loading.set(true);
set_load_progress.set(0.0);
// Simulate loading progress
let progress_interval = set_interval_with_handle(
move || {
set_load_progress.update(|p| {
if *p < 100.0 {
*p += 10.0;
} else {
set_is_loading.set(false);
set_is_loaded.set(true);
}
});
},
std::time::Duration::from_millis(100),
).unwrap();
// Clean up interval after loading
spawn_local(async move {
gloo_timers::future::TimeoutFuture::new(1000).await;
progress_interval.clear();
});
};
view! {
<div class="lazy-component-wrapper">
<div class="component-header">
<h4>{name.clone()}</h4>
<div class="component-meta">
<span class="component-category">{component_info().category}</span>
<span class="component-size">{component_info().estimated_size}</span>
</div>
</div>
<div class="component-content">
<div class="lazy-component-loaded" class:hidden={move || !is_loaded.get()}>
<div class="component-success">
<div class="success-icon">"✅"</div>
<p class="success-text">"Component loaded successfully!"</p>
<div class="component-demo">
<span>"🎉 {name} is now available"</span>
</div>
<div class="component-details">
<p class="component-description">{component_info().description}</p>
<div class="component-dependencies">
<strong>"Dependencies:"</strong>
{if component_info().dependencies.is_empty() {
"None".to_string()
} else {
component_info().dependencies.join(", ")
}}
</div>
</div>
</div>
</div>
<div class="component-loading" class:hidden={move || !is_loading.get()}>
<div class="loading-content">
<div class="loading-spinner"></div>
<p>"Loading {name}..."</p>
<div class="progress-bar">
<div class="progress-fill" style={format!("width: {}%", load_progress.get())}></div>
</div>
<span class="progress-text">{move || format!("{}%", load_progress.get() as i32)}</span>
</div>
</div>
<div class="component-placeholder" class:hidden={move || is_loaded.get() || is_loading.get()}>
<div class="placeholder-content">
<p class="placeholder-text">"This component is not yet loaded. Click to load it on demand."</p>
<div class="component-preview">
<p class="preview-description">{component_info().description}</p>
<div class="preview-meta">
<span class="preview-size">"Size: {component_info().estimated_size}"</span>
<span class="preview-category">"Category: {component_info().category}"</span>
</div>
</div>
<button on:click={load_component} class="load-btn">
"Load {name}"
</button>
</div>
</div>
</div>
</div>
}
}
/// Simple lazy loading provider
#[component]
pub fn LazyLoadingProvider(
#[prop(into)] children: Children,
) -> impl IntoView {
view! {
<div class="lazy-loading-provider">
{children()}
</div>
}
}