Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "vuer-uikit",
|
||||
"description": "Complete documentation for Vuer UIKit React component library including 38 UI components, Dial system for control panels, style guides, and layout patterns",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "Ge Yang"
|
||||
},
|
||||
"skills": [
|
||||
"./"
|
||||
]
|
||||
}
|
||||
142
COMPLETION_STATUS.md
Normal file
142
COMPLETION_STATUS.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Vuer UIKit Documentation Fetch - Completion Status
|
||||
|
||||
## Summary
|
||||
|
||||
**Total Pages:** 64
|
||||
**Fetched and Saved:** 18 pages
|
||||
**Fetched (Content Ready, Needs Saving):** 11 pages
|
||||
**Remaining to Fetch:** 35 pages
|
||||
|
||||
## Completed and Saved (18 pages)
|
||||
|
||||
### Guides (2/2)
|
||||
- ✅ guides/introduction.md
|
||||
- ✅ guides/getting-started.md
|
||||
|
||||
### Style Guide (4/4)
|
||||
- ✅ style-guide/colors.md
|
||||
- ✅ style-guide/font.md
|
||||
- ✅ style-guide/icons.md
|
||||
- ✅ style-guide/layout.md
|
||||
|
||||
### Form Inputs (4/4)
|
||||
- ✅ form-inputs/input.md
|
||||
- ✅ form-inputs/number-inputs.md
|
||||
- ✅ form-inputs/playground.md
|
||||
- ✅ form-inputs/specialized-inputs.md
|
||||
|
||||
### Dial System (2/9)
|
||||
- ✅ dial/overview.md
|
||||
- ✅ dial/getting-started.md
|
||||
|
||||
### Components (3/38)
|
||||
- ✅ components/button.md
|
||||
- ✅ components/avatar.md
|
||||
- ✅ components/badge.md
|
||||
|
||||
### Other (1/2)
|
||||
- ✅ other/hooks.md
|
||||
|
||||
## Content Fetched, Ready to Save (11 pages)
|
||||
|
||||
These pages have been successfully fetched via WebFetch and their content is available in the conversation history. They just need to be written to files:
|
||||
|
||||
### Dial System (7 pages)
|
||||
- dial/tutorial.md
|
||||
- dial/input-types.md
|
||||
- dial/type-inheritance.md
|
||||
- dial/cli-details.md
|
||||
- dial/testing.md
|
||||
- dial/controlled-dials.md
|
||||
- dial/api-notes.md
|
||||
|
||||
### Menu Tool Layouts (3 pages)
|
||||
- menu-tool-layouts/dock-layout.md
|
||||
- menu-tool-layouts/liquid-float-layout.md
|
||||
- menu-tool-layouts/toolbar.md
|
||||
|
||||
### Other (1 page)
|
||||
- other/test-codeblock.md
|
||||
|
||||
## Remaining to Fetch (35 component pages)
|
||||
|
||||
### Components List
|
||||
1. components/card.md
|
||||
2. components/checkbox.md
|
||||
3. components/collapsible.md
|
||||
4. components/cursor-display.md
|
||||
5. components/drag-selectable.md
|
||||
6. components/drawer.md
|
||||
7. components/dropdown.md
|
||||
8. components/layout.md
|
||||
9. components/modal.md
|
||||
10. components/navbar.md
|
||||
11. components/navigation.md
|
||||
12. components/pagination.md
|
||||
13. components/popover.md
|
||||
14. components/preview.md
|
||||
15. components/progress.md
|
||||
16. components/radio-group.md
|
||||
17. components/select.md
|
||||
18. components/sheet.md
|
||||
19. components/sidebar.md
|
||||
20. components/simple-tree-view.md
|
||||
21. components/slider.md
|
||||
22. components/spinner.md
|
||||
23. components/switch.md
|
||||
24. components/sync-scroll.md
|
||||
25. components/table.md
|
||||
26. components/tabs.md
|
||||
27. components/textarea.md
|
||||
28. components/toast.md
|
||||
29. components/toggle.md
|
||||
30. components/toggle-buttons.md
|
||||
31. components/toggle-group.md
|
||||
32. components/tooltip.md
|
||||
33. components/tree-view.md
|
||||
34. components/version-badge.md
|
||||
35. components/waterfall.md
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate (Save Fetched Content)
|
||||
The following files are ready to be saved from the WebFetch results in this conversation. Run Write operations for each:
|
||||
|
||||
1. Dial System files (7 files) - Content available in WebFetch results
|
||||
2. Menu Tool Layouts files (3 files) - Content available in WebFetch results
|
||||
3. test-codeblock.md (1 file) - Content available in WebFetch results
|
||||
|
||||
### Subsequent (Fetch Remaining)
|
||||
After saving the ready content, fetch the remaining 35 component pages using:
|
||||
|
||||
```bash
|
||||
# For each component, use WebFetch with pattern:
|
||||
WebFetch URL: https://uikit.vuer.ai/components/{component-name}/
|
||||
Prompt: Extract the main documentation content about the {Component} component. Include all text, usage examples, props documentation, code snippets, and explanations. Remove navigation elements, headers, and footers. Format as markdown.
|
||||
```
|
||||
|
||||
Components can be fetched in batches of 5-10 for efficiency.
|
||||
|
||||
## URLs Reference
|
||||
|
||||
Base URL: `https://uikit.vuer.ai/`
|
||||
|
||||
Pattern for components: `https://uikit.vuer.ai/components/{component-name}/`
|
||||
Pattern for other pages: `https://uikit.vuer.ai/{category}/{page-name}/`
|
||||
|
||||
## File Locations
|
||||
|
||||
All markdown files are saved to:
|
||||
`/Users/ge/fortyfive/awesome-skills/skills/vuer-uikit/docs/`
|
||||
|
||||
Directory structure:
|
||||
```
|
||||
docs/
|
||||
├── guides/
|
||||
├── style-guide/
|
||||
├── form-inputs/
|
||||
├── dial/
|
||||
├── menu-tool-layouts/
|
||||
├── components/
|
||||
└── other/
|
||||
```
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# vuer-uikit
|
||||
|
||||
Complete documentation for Vuer UIKit React component library including 38 UI components, Dial system for control panels, style guides, and layout patterns
|
||||
84
SKILL.md
Normal file
84
SKILL.md
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
name: vuer-uikit
|
||||
description: Expert knowledge of Vuer UIKit, a React component library for building interactive 3D and UI applications with 38 components and a powerful Dial system
|
||||
---
|
||||
|
||||
# Vuer UIKit Documentation Skill
|
||||
|
||||
Expert knowledge of Vuer UIKit, a React component library for building interactive 3D and UI applications.
|
||||
|
||||
## What is Vuer UIKit?
|
||||
|
||||
Vuer UIKit is a comprehensive React component library designed for building modern user interfaces, particularly for 3D visualization and interactive applications. It provides a rich set of components including forms, layouts, data displays, and a powerful Dial system for creating control panels.
|
||||
|
||||
## Documentation Coverage
|
||||
|
||||
This skill includes complete documentation for:
|
||||
|
||||
### Getting Started
|
||||
- Introduction and overview
|
||||
- Installation and setup guide
|
||||
|
||||
### Style Guide
|
||||
- Color system and theming
|
||||
- Typography and fonts
|
||||
- Icon library
|
||||
- Layout principles
|
||||
|
||||
### Form Inputs
|
||||
- Standard input components
|
||||
- Number inputs with specialized controls
|
||||
- Interactive playground
|
||||
- Specialized input types
|
||||
|
||||
### Dial System
|
||||
The Dial system is a powerful feature for creating control panels:
|
||||
- Overview and concepts
|
||||
- Getting started guide
|
||||
- Step-by-step tutorial
|
||||
- Comprehensive input type reference
|
||||
- Type inheritance patterns
|
||||
- CLI tooling reference
|
||||
- Testing strategies
|
||||
- Controlled dial patterns
|
||||
- API design notes
|
||||
|
||||
### Menu & Tool Layouts
|
||||
- Dock layout for panels
|
||||
- Liquid float layout for dynamic positioning
|
||||
- Toolbar components
|
||||
|
||||
### Components (38 total)
|
||||
Complete documentation for all UI components including:
|
||||
- Navigation: Navbar, Navigation, Sidebar, Tabs
|
||||
- Data Display: Avatar, Badge, Card, Table, Waterfall
|
||||
- Overlays: Modal, Drawer, Popover, Sheet, Toast, Tooltip
|
||||
- Inputs: Button, Checkbox, Radio Group, Select, Slider, Switch, Textarea, Toggle components
|
||||
- Feedback: Progress, Spinner, Version Badge
|
||||
- Advanced: Tree View, Collapsible, Cursor Display, Drag Selectable, Sync Scroll, Preview
|
||||
|
||||
### Hooks
|
||||
Custom React hooks for common patterns
|
||||
|
||||
## Usage
|
||||
|
||||
When helping with Vuer UIKit:
|
||||
1. Reference the specific component documentation in `docs/components/`
|
||||
2. For Dial-related questions, check the comprehensive Dial system docs in `docs/dial/`
|
||||
3. For styling and theming, refer to `docs/style-guide/`
|
||||
4. For layout patterns, see `docs/menu-tool-layouts/`
|
||||
|
||||
## Official Resources
|
||||
|
||||
- Documentation Site: https://uikit.vuer.ai/
|
||||
- GitHub Repository: https://github.com/vuer-ai/vuer-uikit
|
||||
|
||||
## Skills
|
||||
|
||||
This skill helps you:
|
||||
- Build UIs with Vuer UIKit components
|
||||
- Create control panels using the Dial system
|
||||
- Apply consistent styling and theming
|
||||
- Implement complex layouts and interactions
|
||||
- Use specialized form inputs and controls
|
||||
- Test Dial-annotated components
|
||||
105
docs/README.md
Normal file
105
docs/README.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Vuer UIKit Documentation
|
||||
|
||||
This directory contains the complete documentation for Vuer UIKit, fetched from https://uikit.vuer.ai/
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
### Guides (2/2 complete)
|
||||
- [Introduction](guides/introduction.md) - Overview and quick start
|
||||
- [Getting Started](guides/getting-started.md) - Installation and setup
|
||||
|
||||
### Style Guide (4/4 complete)
|
||||
- [Colors](style-guide/colors.md) - Color system and variables
|
||||
- [Font](style-guide/font.md) - Typography scale
|
||||
- [Icons](style-guide/icons.md) - Icon system using Lucide
|
||||
- [Layout](style-guide/layout.md) - Spacing and border radius
|
||||
|
||||
### Form Inputs (4/4 complete)
|
||||
- [Input](form-inputs/input.md) - Basic input component
|
||||
- [Number Inputs](form-inputs/number-inputs.md) - Numeric inputs with drag functionality
|
||||
- [Playground](form-inputs/playground.md) - Interactive playground
|
||||
- [Specialized Inputs](form-inputs/specialized-inputs.md) - Unit-specific inputs (cm, rad, vector3, etc.)
|
||||
|
||||
### Dial System (2/9 fetched)
|
||||
- [Overview](dial/overview.md) - Dial system introduction
|
||||
- [Getting Started](dial/getting-started.md) - Installation and basic workflow
|
||||
- Tutorial - *Fetched, needs saving*
|
||||
- Input Types - *Fetched, needs saving*
|
||||
- Type Inheritance - *Fetched, needs saving*
|
||||
- CLI Reference - *Fetched, needs saving*
|
||||
- Testing - *Fetched, needs saving*
|
||||
- Controlled Dials - *Fetched, needs saving*
|
||||
- API Notes - *Fetched, needs saving*
|
||||
|
||||
### Menu Tool Layouts (0/3 - fetched, needs saving)
|
||||
- Dock Layout - *Fetched, needs saving*
|
||||
- Liquid Float Layout - *Fetched, needs saving*
|
||||
- Toolbar - *Fetched, needs saving*
|
||||
|
||||
### Components (3/38 - 3 fetched, 35 remaining)
|
||||
#### Fetched (needs saving):
|
||||
- Avatar - *Fetched, needs saving*
|
||||
- Badge - *Fetched, needs saving*
|
||||
- Button - *Fetched, needs saving*
|
||||
|
||||
#### Remaining to fetch (35 components):
|
||||
- Card
|
||||
- Checkbox
|
||||
- Collapsible
|
||||
- Cursor Display
|
||||
- Drag Selectable
|
||||
- Drawer
|
||||
- Dropdown
|
||||
- Layout
|
||||
- Modal
|
||||
- Navbar
|
||||
- Navigation
|
||||
- Pagination
|
||||
- Popover
|
||||
- Preview
|
||||
- Progress
|
||||
- Radio Group
|
||||
- Select
|
||||
- Sheet
|
||||
- Sidebar
|
||||
- Simple Tree View
|
||||
- Slider
|
||||
- Spinner
|
||||
- Switch
|
||||
- Sync Scroll
|
||||
- Table
|
||||
- Tabs
|
||||
- Textarea
|
||||
- Toast
|
||||
- Toggle
|
||||
- Toggle Buttons
|
||||
- Toggle Group
|
||||
- Tooltip
|
||||
- Tree View
|
||||
- Version Badge
|
||||
- Waterfall
|
||||
|
||||
### Other (1/2 complete)
|
||||
- [Hooks](other/hooks.md) - React hooks documentation
|
||||
- Test Codeblock - *Fetched, needs saving*
|
||||
|
||||
## Fetch Status Summary
|
||||
|
||||
**Completed and Saved:** 15 pages
|
||||
**Fetched (needs saving):** 14 pages
|
||||
**Remaining to fetch:** 35 pages
|
||||
**Total:** 64 pages
|
||||
|
||||
## Next Steps
|
||||
|
||||
To complete the documentation:
|
||||
|
||||
1. Save the 14 already-fetched pages (see list above)
|
||||
2. Fetch the remaining 35 component pages
|
||||
3. Verify all links and cross-references
|
||||
|
||||
## Source
|
||||
|
||||
All documentation fetched from: https://uikit.vuer.ai/
|
||||
Version: v0.0.117
|
||||
Dial CLI Version: v0.0.22
|
||||
77
docs/components/avatar.md
Normal file
77
docs/components/avatar.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Avatar Component Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Avatar component presents a circular image element designed for representing users, with built-in fallback functionality. It extends Radix UI's Avatar primitive and includes server-side rendering support plus enhanced features for grouping multiple avatars.
|
||||
|
||||
## Component Parts
|
||||
|
||||
### Avatar (Root)
|
||||
The main container for displaying user avatars.
|
||||
|
||||
**Props:**
|
||||
- `className` (string): Additional CSS classes
|
||||
- `children` (ReactNode): AvatarImage and AvatarFallback components
|
||||
- Supports all Radix UI Avatar.Root props
|
||||
|
||||
### AvatarImage
|
||||
Renders the user's profile image with automatic fallback handling.
|
||||
|
||||
**Props:**
|
||||
- `src` (string): Image source URL
|
||||
- `alt` (string): Alternative text for accessibility
|
||||
- `className` (string): Custom CSS classes
|
||||
- Inherits all Radix UI Avatar.Image props
|
||||
|
||||
### AvatarFallback
|
||||
Shows fallback content when the image fails to load.
|
||||
|
||||
**Props:**
|
||||
- `className` (string): Custom styling
|
||||
- `children` (ReactNode): Fallback content, typically initials
|
||||
- Supports all Radix UI Avatar.Fallback props
|
||||
|
||||
### AvatarGroup
|
||||
Groups multiple avatars in a stacked arrangement with configurable spacing.
|
||||
|
||||
**Props:**
|
||||
- `children` (ReactNode): Avatar components to display
|
||||
- `className` (string): Custom CSS classes
|
||||
- `spacing` ("tight" | "normal" | "loose"): Controls avatar spacing
|
||||
- `max` (number): Maximum avatars shown before displaying "+N" indicator
|
||||
|
||||
**Spacing Options:**
|
||||
- **tight**: Closest together (`-space-x-1.5`)
|
||||
- **normal**: Default spacing (`-space-x-1`)
|
||||
- **loose**: Most space between (`-space-x-0.45`)
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Avatar
|
||||
```jsx
|
||||
<Avatar>
|
||||
<AvatarImage src="/images/shadcn.png" alt="@shadcn" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
```
|
||||
|
||||
### Custom Sizes
|
||||
```jsx
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className="size-8">
|
||||
<AvatarImage src="/images/shadcn.png" alt="@shadcn" />
|
||||
<AvatarFallback className="text-xs">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar className="size-12">
|
||||
<AvatarImage src="/images/shadcn.png" alt="@shadcn" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar className="size-16">
|
||||
<AvatarImage src="/images/shadcn.png" alt="@shadcn" />
|
||||
<AvatarFallback className="text-lg">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Avatar Groups with Spacing Variants
|
||||
Groups can implement tight, normal, or loose spacing configurations by adjusting the `spacing` prop on the `AvatarGroup` component.
|
||||
68
docs/components/badge.md
Normal file
68
docs/components/badge.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Badge Component Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Badge component displays a badge or badge-like visual element. It extends standard span functionality with customizable variants and shapes.
|
||||
|
||||
## Type Definition
|
||||
|
||||
```typescript
|
||||
interface BadgeProps extends ComponentProps<"span">, VariantProps<typeof badgeVariants> {
|
||||
asChild?: boolean;
|
||||
variant?: "default" | "secondary" | "destructive" | "success" | "warning" | "accent";
|
||||
type?: "default" | "circle" | "dot";
|
||||
}
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Default | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `variant` | `'default' \| 'secondary' \| 'destructive' \| 'success' \| 'warning' \| 'accent'` | `'default'` | Determines the visual styling |
|
||||
| `type` | `'default' \| 'circle' \| 'dot'` | `'default'` | Controls shape and layout presentation |
|
||||
| `asChild` | `boolean` | `false` | Enables `Slot` rendering for child element styling |
|
||||
| span props | `ComponentProps<'span'>` | — | All native HTML span attributes supported |
|
||||
|
||||
## Basic Examples
|
||||
|
||||
Simple badge variants:
|
||||
```jsx
|
||||
<Badge>Default</Badge>
|
||||
<Badge variant="success">Deployed</Badge>
|
||||
<Badge type="circle">3</Badge>
|
||||
<Badge type="dot" />
|
||||
```
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
**Variant showcase:**
|
||||
```jsx
|
||||
<Badge>Badge</Badge>
|
||||
<Badge variant="secondary">Secondary</Badge>
|
||||
<Badge variant="destructive">Destructive</Badge>
|
||||
<Badge variant="success">Success</Badge>
|
||||
<Badge variant="warning">warning</Badge>
|
||||
```
|
||||
|
||||
**Circular badge indicators:**
|
||||
```jsx
|
||||
<Badge type="circle">3</Badge>
|
||||
<Badge variant="secondary" type="circle">3</Badge>
|
||||
<Badge variant="destructive" type="circle">3</Badge>
|
||||
<Badge variant="success" type="circle">3</Badge>
|
||||
<Badge variant="warning" type="circle">3</Badge>
|
||||
```
|
||||
|
||||
**Dot indicators:**
|
||||
```jsx
|
||||
<Badge type="dot" />
|
||||
<Badge variant="secondary" type="dot" />
|
||||
<Badge variant="destructive" type="dot" />
|
||||
<Badge variant="success" type="dot" />
|
||||
<Badge variant="warning" type="dot" />
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Radix UI Badge Documentation](https://www.radix-ui.com/primitives/docs/components/badge)
|
||||
- [API Reference](https://www.radix-ui.com/primitives/docs/components/badge#api-reference)
|
||||
144
docs/components/button.md
Normal file
144
docs/components/button.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Button Component Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Button component is a fundamental UI element used to trigger actions or events. It supports multiple visual styles, sizes, and states for different use cases like form submission, dialog opening, action cancellation, and delete operations.
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `variant` | `'primary' \| 'secondary' \| 'destructive' \| 'ghost' \| 'link'` | `'primary'` | Visual appearance style |
|
||||
| `size` | `'sm' \| 'base' \| 'lg'` | `'base'` | Button dimensions |
|
||||
| `icon` | `boolean` | `false` | Optimizes spacing for icon-only buttons |
|
||||
| `asChild` | `boolean` | `false` | Uses Slot to render as child component |
|
||||
| ...button props | `ComponentProps<'button'>` | — | All standard HTML button attributes supported |
|
||||
|
||||
## Variants
|
||||
|
||||
### Primary
|
||||
The default style for main actions:
|
||||
```jsx
|
||||
<Button>Primary</Button>
|
||||
<Button>Primary Action</Button>
|
||||
<Button icon aria-label="Primary action">
|
||||
<Plus className="size-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
### Secondary
|
||||
Alternative action style:
|
||||
```jsx
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="secondary">
|
||||
<Plus className="size-4 mr-2" />
|
||||
Add Item
|
||||
</Button>
|
||||
```
|
||||
|
||||
### Destructive
|
||||
For dangerous operations like deletion:
|
||||
```jsx
|
||||
<Button variant="destructive">Destructive</Button>
|
||||
<Button variant="destructive">
|
||||
<Trash className="size-4 mr-2" />
|
||||
Delete
|
||||
</Button>
|
||||
```
|
||||
|
||||
### Ghost
|
||||
Subtle action style:
|
||||
```jsx
|
||||
<Button variant="ghost">Ghost</Button>
|
||||
<Button variant="ghost" icon>
|
||||
<Settings className="size-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
### Small
|
||||
```jsx
|
||||
<Button size="sm">Small</Button>
|
||||
<Button size="sm" variant="secondary">
|
||||
<Plus className="size-3 mr-1" />
|
||||
Add
|
||||
</Button>
|
||||
```
|
||||
|
||||
### Default
|
||||
```jsx
|
||||
<Button>Default</Button>
|
||||
<Button>
|
||||
<Save className="size-4 mr-2" />
|
||||
Save Changes
|
||||
</Button>
|
||||
```
|
||||
|
||||
### Large
|
||||
```jsx
|
||||
<Button size="lg">Large</Button>
|
||||
<Button size="lg" className="px-8">
|
||||
<ArrowRight className="size-5 mr-2" />
|
||||
Get Started
|
||||
</Button>
|
||||
```
|
||||
|
||||
## Icon Buttons
|
||||
|
||||
Use the `icon` prop to properly space icon-only buttons across different sizes and variants:
|
||||
|
||||
```jsx
|
||||
<Button icon size="sm" aria-label="Settings">
|
||||
<Settings className="size-3" />
|
||||
</Button>
|
||||
|
||||
<Button icon variant="secondary" aria-label="Edit">
|
||||
<Edit className="size-4" />
|
||||
</Button>
|
||||
|
||||
<Button icon variant="destructive" aria-label="Delete">
|
||||
<Trash2 className="size-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
## States
|
||||
|
||||
### Disabled
|
||||
```jsx
|
||||
<Button disabled>Disabled</Button>
|
||||
<Button disabled title="Complete required fields first">
|
||||
<Lock className="size-4 mr-2" />
|
||||
Submit Form
|
||||
</Button>
|
||||
```
|
||||
|
||||
## Type Definition
|
||||
|
||||
```typescript
|
||||
interface ButtonProps extends ComponentProps<"button">, VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
variant?: "primary" | "secondary" | "destructive" | "ghost" | "link";
|
||||
size?: "sm" | "md" | "lg";
|
||||
icon?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
```jsx
|
||||
import { Button } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
return (
|
||||
<div>
|
||||
<Button>Primary Button</Button>
|
||||
<Button variant="secondary">Secondary Button</Button>
|
||||
<Button variant="destructive">Destructive Button</Button>
|
||||
<Button size="sm">Small Button</Button>
|
||||
<Button size="lg">Large Button</Button>
|
||||
<Button disabled>Disabled Button</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
208
docs/components/card.md
Normal file
208
docs/components/card.md
Normal file
@@ -0,0 +1,208 @@
|
||||
- Home
|
||||
- Components
|
||||
- Card
|
||||
|
||||
# Card
|
||||
|
||||
Displays a card with header, content, and footer.
|
||||
|
||||
## Props
|
||||
|
||||
This component group provides styled containers. All parts accept standard div props.
|
||||
|
||||
- Card: root container with size variants (sm, md, lg, xl) for padding
|
||||
- CardHeader: header row with optional actions, supports size variants for gap spacing
|
||||
- CardTitle: title text
|
||||
- CardDescription: subdued description text
|
||||
- CardAction: right-aligned action area in header
|
||||
- CardContent: main content area
|
||||
- CardFooter: footer area (flex container)
|
||||
|
||||
## Types
|
||||
|
||||
```
|
||||
// Card component with size variants
|
||||
interface CardProps extends ComponentProps<"div"> {
|
||||
size?: "sm" | "md" | "lg" | "xl";
|
||||
}
|
||||
|
||||
// CardHeader also supports size variants for gap spacing
|
||||
interface CardHeaderProps extends ComponentProps<"div"> {
|
||||
size?: "sm" | "md" | "lg" | "xl";
|
||||
}
|
||||
|
||||
// All other Card components extend ComponentProps<"div">
|
||||
interface CardTitleProps extends ComponentProps<"div"> {}
|
||||
interface CardDescriptionProps extends ComponentProps<"div"> {}
|
||||
interface CardActionProps extends ComponentProps<"div"> {}
|
||||
interface CardContentProps extends ComponentProps<"div"> {}
|
||||
interface CardFooterProps extends ComponentProps<"div"> {}
|
||||
```
|
||||
|
||||
```
|
||||
<Card className="w-[300px]">
|
||||
<CardHeader>
|
||||
<CardTitle>Card Title</CardTitle>
|
||||
<CardAction>
|
||||
<Button variant="link">action</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col my-4">
|
||||
<div>CardContent...</div>
|
||||
<div>CardContent...</div>
|
||||
<div>CardContent...</div>
|
||||
<div>CardContent...</div>
|
||||
<div>CardContent...</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button className="w-full">Footer</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
The Card component supports different padding sizes, and CardHeader adjusts gap spacing accordingly:
|
||||
|
||||
```
|
||||
// Small card with reduced padding and gap spacing
|
||||
<Card size="sm" className="w-50">
|
||||
<CardHeader size="sm">
|
||||
<CardTitle>Small Card</CardTitle>
|
||||
<CardAction>
|
||||
<Settings className="size-4" />
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="text-uk-sm">
|
||||
Compact content with smaller padding and gap.
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
// Large card with increased padding and gap spacing (default)
|
||||
<Card size="lg" className="w-50">
|
||||
<CardHeader size="lg">
|
||||
<CardTitle>Large Card</CardTitle>
|
||||
<CardAction>
|
||||
<Settings className="size-4" />
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="text-uk-md">
|
||||
More spacious content with larger padding and gap.
|
||||
</CardContent>
|
||||
</Card>
|
||||
```
|
||||
|
||||
## Login Form Example
|
||||
|
||||
```
|
||||
import { Button } from "@vuer-ai/vuer-uikit"
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@vuer-ai/vuer-uikit"
|
||||
import { Input, Label } from "@vuer-ai/vuer-uikit"
|
||||
|
||||
<Card className="w-80">
|
||||
<CardHeader>
|
||||
<CardTitle>Login to your account</CardTitle>
|
||||
<CardAction>
|
||||
<Button variant="link">Sign Up</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-lg pb-lg">
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
<form>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<a
|
||||
href="#"
|
||||
className="ml-auto inline-block text-uk-xs underline-offset-4 hover:underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button type="submit" className="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
```
|
||||
|
||||
## Examples with Icons and Buttons
|
||||
|
||||
```
|
||||
import { Settings, User, Bell, Plus, ChevronRight } from 'lucide-react';
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="size-5 text-text-secondary" />
|
||||
<CardTitle>User Profile</CardTitle>
|
||||
</div>
|
||||
<CardAction>
|
||||
<Button variant="ghost" size="sm">
|
||||
<Settings className="size-4" />
|
||||
</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="py-lg">
|
||||
Manage your account settings and preferences
|
||||
</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button variant="secondary" className="flex-1">
|
||||
<ChevronRight className="size-4 ml-auto" />
|
||||
View Details
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
<Card size="sm">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Bell className="size-4 text-text-secondary" />
|
||||
<CardTitle>Notifications</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="py-lg">3 new updates available</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button size="sm" className="w-full">
|
||||
<Plus className="size-4 mr-2" />
|
||||
View All
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
```
|
||||
|
||||
62
docs/components/checkbox.md
Normal file
62
docs/components/checkbox.md
Normal file
@@ -0,0 +1,62 @@
|
||||
- Home
|
||||
- Components
|
||||
- Checkbox
|
||||
|
||||
# Checkbox
|
||||
|
||||
A control that allows the user to toggle between checked and not checked.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
checkall boolean false Renders a square fill style for "select all" semantics
|
||||
...Radix props ComponentProps<typeof CheckboxPrimitive.Root> - All Radix checkbox props
|
||||
|
||||
## Types
|
||||
|
||||
```
|
||||
interface CheckboxProps extends ComponentProps<typeof CheckboxPrimitive.Root> {
|
||||
checkall?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="Checkbox" />
|
||||
<label htmlFor="Checkbox">Checkbox</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="Checkbox disabled" disabled />
|
||||
<label htmlFor="Checkbox disabled">Checkbox disabled</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="Checkbox disabled checked" disabled defaultChecked />
|
||||
<label htmlFor="Checkbox disabled checked">Checkbox disabled checked</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="checkall" checkall />
|
||||
<label htmlFor="checkall">Check all</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="Check all disabled" checkall disabled />
|
||||
<label htmlFor="Check all disabled">Check all disabled</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="Check all disabled checked" defaultChecked disabled checkall />
|
||||
<label htmlFor="Check all disabled checked">Check all disabled checked</label>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
<Checkbox id="opt-in" />
|
||||
<Checkbox id="select-all" checkall />
|
||||
```
|
||||
|
||||
58
docs/components/collapsible.md
Normal file
58
docs/components/collapsible.md
Normal file
@@ -0,0 +1,58 @@
|
||||
- Home
|
||||
- Components
|
||||
- Collapsible
|
||||
|
||||
# Collapsible
|
||||
|
||||
An interactive component which expands/collapses a panel.
|
||||
|
||||
## Props
|
||||
|
||||
All parts mirror Radix Collapsible props:
|
||||
|
||||
- Collapsible: root container
|
||||
- CollapsibleTrigger: toggles state (supports asChild)
|
||||
- CollapsibleContent: animated content area
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<Collapsible>
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button variant="ghost">Toggle</Button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>Hidden content</CollapsibleContent>
|
||||
</Collapsible>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
#### @peduarte starred 3 repositories
|
||||
|
||||
```
|
||||
<Collapsible className="flex w-[350px] flex-col gap-2">
|
||||
<div className="flex items-center justify-between gap-4 px-4">
|
||||
<h4 className="text-sm font-semibold">
|
||||
@peduarte starred 3 repositories
|
||||
</h4>
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button title="This is a collapsible trigger" variant="ghost" size="icon" className="size-8">
|
||||
<ChevronsUpDown/>
|
||||
<span className="sr-only">Toggle</span>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
<div className="rounded-md px-4 py-2 text-sm hover:bg-bg-secondary">
|
||||
@radix-ui/primitives
|
||||
</div>
|
||||
<CollapsibleContent className="flex flex-col gap-2">
|
||||
<div className="rounded-md px-4 py-2 text-sm hover:bg-bg-secondary">
|
||||
@radix-ui/colors
|
||||
</div>
|
||||
<div className="rounded-md px-4 py-2 text-sm hover:bg-bg-secondary">
|
||||
@stitches/react
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
```
|
||||
|
||||
59
docs/components/cursor-display.md
Normal file
59
docs/components/cursor-display.md
Normal file
@@ -0,0 +1,59 @@
|
||||
- Home
|
||||
- Components
|
||||
- Cursor Display
|
||||
|
||||
# Cursor Display
|
||||
|
||||
Built-in components with Cursor highlighting
|
||||
|
||||
## CursorButton
|
||||
|
||||
```
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="space-x-2">
|
||||
<CursorButton>CursorButton</CursorButton>
|
||||
<CursorButton variant="secondary">CursorButton</CursorButton>
|
||||
<CursorButton variant="destructive">CursorButton</CursorButton>
|
||||
<CursorButton variant="ghost">CursorButton</CursorButton>
|
||||
</div>
|
||||
<div className="space-x-2">
|
||||
<Button>Button</Button>
|
||||
<Button variant="secondary">Button</Button>
|
||||
<Button variant="destructive">Button</Button>
|
||||
<Button variant="ghost">Button</Button>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## CursorInputRoot
|
||||
|
||||
```
|
||||
<CursorInputRoot size="sm" placeholder="CursorInputRoot" / >
|
||||
<CursorInputRoot size="sm" placeholder="CursorInputRoot" state="error"/ >
|
||||
<CursorInputRoot size="sm" placeholder="CursorInputRoot" disabled/>
|
||||
```
|
||||
|
||||
## CursorSelectTrigger
|
||||
|
||||
```
|
||||
<CursorSelectTrigger size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="CursorSelectTrigger"/>
|
||||
</CursorSelectTrigger>
|
||||
<CursorSelectTrigger disabled size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="CursorSelectTrigger"/>
|
||||
</CursorSelectTrigger>
|
||||
<CursorSelectTrigger state="error" size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="CursorSelectTrigger"/>
|
||||
</CursorSelectTrigger>
|
||||
```
|
||||
|
||||
## CursorTextarea
|
||||
|
||||
```
|
||||
<CursorTextarea size="base" placeholder="Type your message here." />
|
||||
|
||||
<CursorTextarea disabled placeholder="Type your message here." />
|
||||
|
||||
<CursorTextarea state="error" placeholder="Type your message here." />
|
||||
```
|
||||
|
||||
82
docs/components/drag-selectable.md
Normal file
82
docs/components/drag-selectable.md
Normal file
@@ -0,0 +1,82 @@
|
||||
- Home
|
||||
- Components
|
||||
- Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
```
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage: Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
|
||||
81
docs/components/drawer.md
Normal file
81
docs/components/drawer.md
Normal file
@@ -0,0 +1,81 @@
|
||||
- Home
|
||||
- Components
|
||||
- Drawer
|
||||
|
||||
# Drawer
|
||||
|
||||
A drawer component for React.
|
||||
|
||||
## Props
|
||||
|
||||
### Drawer
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
...Vaul props ComponentProps<typeof DrawerPrimitive.Root> - All Vaul drawer root props
|
||||
|
||||
### Drawer Root
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
direction 'top' | 'right' | 'bottom' | 'left' 'bottom' Which edge to slide from
|
||||
...Vaul props ComponentProps<typeof DrawerPrimitive.Root> - All Vaul root props
|
||||
|
||||
### DrawerContent
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
...Vaul props ComponentProps<typeof DrawerPrimitive.Content> - All Vaul content props
|
||||
|
||||
Other parts (DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerHeader, DrawerFooter, DrawerTitle, DrawerDescription, DrawerClose) are styled wrappers around Vaul components.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Edit profile</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<div className="grid flex-1 auto-rows-min gap-4">
|
||||
<div className="grid gap-3">
|
||||
<label className="text-[12px]" htmlFor="sheet-demo-name">Name</label>
|
||||
<InputRoot id="sheet-demo-name" defaultValue="Pedro Duarte" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<label className="text-[12px]" htmlFor="sheet-demo-username">Username</label>
|
||||
<InputRoot id="sheet-demo-username" defaultValue="@peduarte" />
|
||||
</div>
|
||||
</div>
|
||||
<DrawerFooter>
|
||||
<Button variant="primary">Save</Button>
|
||||
<SheetClose asChild>
|
||||
<Button variant="secondary">Close</Button>
|
||||
</SheetClose>
|
||||
</DrawerFooter>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild><Button>Open</Button></DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Title</DrawerTitle>
|
||||
<DrawerDescription>Description</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
```
|
||||
|
||||
147
docs/components/dropdown.md
Normal file
147
docs/components/dropdown.md
Normal file
@@ -0,0 +1,147 @@
|
||||
- Home
|
||||
- Components
|
||||
- Dropdown
|
||||
|
||||
# Dropdown Menu
|
||||
|
||||
Displays a menu to the user — such as a set of actions or functions — triggered by a button.
|
||||
|
||||
## Props
|
||||
|
||||
All primitives mirror Radix Dropdown Menu props.
|
||||
|
||||
- DropdownMenu: root provider
|
||||
- DropdownMenuTrigger: trigger element (supports asChild)
|
||||
- DropdownMenuContent: menu content, accepts align, sideOffset
|
||||
- DropdownMenuGroup, DropdownMenuLabel, DropdownMenuSeparator
|
||||
- DropdownMenuItem: accepts inset?: boolean, variant?: 'default' | 'destructive'
|
||||
- DropdownMenuCheckboxItem: controlled/unchecked states via checked
|
||||
- DropdownMenuRadioGroup and DropdownMenuRadioItem
|
||||
- DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent
|
||||
- DropdownMenuShortcut: right-aligned shortcut text
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline">Dropdown Menu</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56" align="start">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
Profile
|
||||
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
Billing
|
||||
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
Settings
|
||||
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
Keyboard shortcuts
|
||||
<DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>Team</DropdownMenuItem>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem>Email</DropdownMenuItem>
|
||||
<DropdownMenuItem>Message</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>More...</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuItem>
|
||||
New Team
|
||||
<DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem className="mb-xs">GitHub</DropdownMenuItem>
|
||||
<DropdownMenuItem className="mb-xs">Support</DropdownMenuItem>
|
||||
<DropdownMenuItem disabled>API</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
Log out
|
||||
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
```
|
||||
|
||||
## Checkboxes
|
||||
|
||||
```
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={true}
|
||||
>
|
||||
Status Bar
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={true}
|
||||
disabled
|
||||
>
|
||||
Activity Bar
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={false}
|
||||
>
|
||||
Panel
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
```
|
||||
|
||||
## Radio Group
|
||||
|
||||
```
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
<DropdownMenuLabel>Panel Position</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuRadioGroup value={"top"}>
|
||||
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
|
||||
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
|
||||
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
|
||||
</DropdownMenuRadioGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem inset>New File</DropdownMenuItem>
|
||||
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem checked>Show Hidden</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
```
|
||||
|
||||
70
docs/components/layout.md
Normal file
70
docs/components/layout.md
Normal file
@@ -0,0 +1,70 @@
|
||||
- Home
|
||||
- Components
|
||||
- Layout
|
||||
|
||||
#FormLayout
|
||||
|
||||
A layout component for organizing content with flexible orientation and alignment options.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
orientation 'horizontal' | 'vertical' 'horizontal' Layout direction
|
||||
align 'start' | 'center' | 'end' 'start' Cross-axis alignment
|
||||
asChild boolean false Render with Slot to style a child element
|
||||
...div props ComponentProps<'div'> - All native div props
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
<FormLayout asChild orientation="label-left" align="end">
|
||||
<label>
|
||||
<span>Email</span>
|
||||
<InputRoot type="email" placeholder="you@example.com" />
|
||||
</label>
|
||||
</FormLayout>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Number
|
||||
|
||||
```
|
||||
<FormLayout asChild className="w-2xs">
|
||||
<label className="text-uk-md">
|
||||
<p>Number</p>
|
||||
|
||||
<InputRoot placeholder="input"/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
```
|
||||
|
||||
## vertical
|
||||
|
||||
Number
|
||||
|
||||
```
|
||||
<FormLayout asChild className="w-2xs" orientation="label-left">
|
||||
<label>
|
||||
<p className="text-uk-md">Number</p>
|
||||
|
||||
<InputRoot placeholder="input"/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
```
|
||||
|
||||
## vertical start
|
||||
|
||||
Number
|
||||
|
||||
```
|
||||
<FormLayout asChild className="w-2xs">
|
||||
<label>
|
||||
<p className="text-uk-md">Number</p>
|
||||
|
||||
<InputRoot placeholder="input"/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
```
|
||||
|
||||
88
docs/components/modal.md
Normal file
88
docs/components/modal.md
Normal file
@@ -0,0 +1,88 @@
|
||||
- Home
|
||||
- Components
|
||||
- Modal
|
||||
|
||||
# Modal
|
||||
|
||||
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
|
||||
|
||||
## Props
|
||||
|
||||
### Modal
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
...Radix props ComponentProps<typeof DialogPrimitive.Root> - All Radix Dialog root props
|
||||
|
||||
### ModalContent
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
showCloseButton boolean true Whether to render the built-in close button
|
||||
...Radix props ComponentProps<typeof DialogPrimitive.Content> - All Radix content props
|
||||
|
||||
Other parts (ModalTrigger, ModalOverlay, ModalPortal, ModalHeader, ModalTitle, ModalDescription, ModalFooter, ModalClose) are thin wrappers over corresponding Radix components with styling.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<Modal>
|
||||
<ModalTrigger asChild>
|
||||
<Button>Open</Button>
|
||||
</ModalTrigger>
|
||||
<ModalContent showCloseButton>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Title</ModalTitle>
|
||||
<ModalDescription>Description</ModalDescription>
|
||||
</ModalHeader>
|
||||
<ModalFooter>
|
||||
<ModalClose asChild><Button variant="secondary">Close</Button></ModalClose>
|
||||
<Button>Confirm</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
</Modal>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<Modal>
|
||||
<ModalTrigger asChild>
|
||||
<Button variant="primary">Open Modal</Button>
|
||||
</ModalTrigger>
|
||||
<ModalContent onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Edit Profile</ModalTitle>
|
||||
<ModalDescription>Update your personal information. Click Save to complete the changes.</ModalDescription>
|
||||
</ModalHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-6 items-center gap-2">
|
||||
<label htmlFor="name" className="text-left text-sm font-medium">Name</label>
|
||||
<InputRoot
|
||||
id="name"
|
||||
defaultValue="Jason"
|
||||
className="col-span-5 px-3 py-2"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-6 items-center gap-2">
|
||||
<label htmlFor="name" className="text-left text-sm font-medium">Mail</label>
|
||||
<InputRoot
|
||||
id="email"
|
||||
defaultValue="jason@example.com"
|
||||
className="col-span-5 px-3 py-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ModalFooter>
|
||||
<ModalClose asChild>
|
||||
<Button variant="secondary">cancel</Button>
|
||||
</ModalClose>
|
||||
<Button>save</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
```
|
||||
|
||||
164
docs/components/navbar.md
Normal file
164
docs/components/navbar.md
Normal file
@@ -0,0 +1,164 @@
|
||||
- Home
|
||||
- Components
|
||||
- Navbar
|
||||
|
||||
# Navbar
|
||||
|
||||
The Navbar component provides a consistent navigation experience across your application. It includes built-in support for search, theme switching, and mobile responsiveness.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
title string - The title/logo text to display
|
||||
onSearch (query: string) => void - Callback function for search
|
||||
showThemeToggle boolean false Whether to show the theme toggle
|
||||
currentTheme 'light' | 'dark' | 'auto' - Current theme state
|
||||
onThemeChange (theme: string) => void - Callback for theme changes
|
||||
|
||||
## Overview
|
||||
|
||||
The Navbar is a top-level navigation component that typically contains the application logo, navigation links, search functionality, and user controls like theme switching.
|
||||
|
||||
## Features
|
||||
|
||||
- Responsive Design: Automatically adapts to mobile and desktop
|
||||
- Theme Switching: Built-in light/dark mode toggle
|
||||
- Search Integration: Optional search functionality
|
||||
- Customizable: Easy to customize with props
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```
|
||||
import { Navbar } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Navbar title="My Application" />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## With Search
|
||||
|
||||
```
|
||||
import { Navbar } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function App() {
|
||||
const handleSearch = (query) => {
|
||||
console.log('Search query:', query);
|
||||
};
|
||||
|
||||
return (
|
||||
<Navbar
|
||||
title="My Application"
|
||||
onSearch={handleSearch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## With Theme Toggle
|
||||
|
||||
```
|
||||
import { Navbar } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Navbar
|
||||
title="My Application"
|
||||
showThemeToggle={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Examples
|
||||
|
||||
#### Basic Navbar
|
||||
|
||||
```
|
||||
<Navbar title="My App" />
|
||||
```
|
||||
|
||||
#### Navbar with Search
|
||||
|
||||
```
|
||||
<Navbar
|
||||
title="My App"
|
||||
onSearch={(query) => {
|
||||
// Handle search
|
||||
console.log('Searching for:', query);
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Navbar with Theme Toggle
|
||||
|
||||
```
|
||||
<Navbar
|
||||
title="My App"
|
||||
showThemeToggle={true}
|
||||
currentTheme="light"
|
||||
onThemeChange={(theme) => {
|
||||
// Handle theme change
|
||||
console.log('Theme changed to:', theme);
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Mobile Behavior
|
||||
|
||||
On mobile devices, the navbar automatically adapts:
|
||||
|
||||
- Search bar collapses into a mobile-friendly interface
|
||||
- Theme toggle remains accessible
|
||||
- Touch targets are appropriately sized
|
||||
- Responsive breakpoints ensure good UX
|
||||
|
||||
## Customization
|
||||
|
||||
### Styling
|
||||
|
||||
You can customize the navbar appearance using CSS custom properties:
|
||||
|
||||
```
|
||||
.vuer-navbar {
|
||||
--navbar-bg: var(--neutral-50);
|
||||
--navbar-border: var(--neutral-200);
|
||||
--navbar-height: 4rem;
|
||||
--navbar-padding: 1rem;
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Content
|
||||
|
||||
For more complex navigation needs, you can extend the navbar with custom content:
|
||||
|
||||
```
|
||||
<Navbar title="My App">
|
||||
<div className="custom-nav-content">
|
||||
<a href="/dashboard">Dashboard</a>
|
||||
<a href="/profile">Profile</a>
|
||||
</div>
|
||||
</Navbar>
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Proper semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader announcements
|
||||
- Focus management
|
||||
- ARIA labels and descriptions
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep the title concise and recognizable
|
||||
- Provide meaningful search functionality
|
||||
- Use theme toggle for better user experience
|
||||
- Ensure mobile responsiveness
|
||||
- Test with keyboard navigation
|
||||
|
||||
54
docs/components/navigation.md
Normal file
54
docs/components/navigation.md
Normal file
@@ -0,0 +1,54 @@
|
||||
- Home
|
||||
- Components
|
||||
- Navigation
|
||||
|
||||
# Navigation
|
||||
|
||||
A navigation component with back/forward buttons and title display.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
title string - The title text to display
|
||||
onBack () => void - Callback for back button click
|
||||
onForward () => void - Callback for forward button click
|
||||
canGoBack boolean true Whether the back button should be enabled
|
||||
canGoForward boolean true Whether the forward button should be enabled
|
||||
size "sm" | "md" | "lg" "md" Size variant for buttons and title
|
||||
className string - Additional CSS class names
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```
|
||||
<Navigation
|
||||
title="Community"
|
||||
/>
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
```
|
||||
<Navigation size="sm" title="Small Navigation" />
|
||||
<Navigation size="md" title="Medium Navigation" />
|
||||
<Navigation size="lg" title="Large Navigation" />
|
||||
```
|
||||
|
||||
## Disabled States
|
||||
|
||||
```
|
||||
<Navigation
|
||||
title="Cannot Go Back"
|
||||
canGoBack={false}
|
||||
/>
|
||||
<Navigation
|
||||
title="Cannot Go Forward"
|
||||
canGoForward={false}
|
||||
/>
|
||||
<Navigation
|
||||
title="Both Disabled"
|
||||
canGoBack={false}
|
||||
canGoForward={false}
|
||||
/>
|
||||
```
|
||||
|
||||
44
docs/components/pagination.md
Normal file
44
docs/components/pagination.md
Normal file
@@ -0,0 +1,44 @@
|
||||
- Home
|
||||
- Components
|
||||
- Pagination
|
||||
|
||||
## Pagination
|
||||
|
||||
Pagination with page navigation, next and previous links.
|
||||
|
||||
## Usage
|
||||
|
||||
- Previous
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- More pages
|
||||
- Next
|
||||
|
||||
```
|
||||
<Pagination>
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious href="#" />
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#">1</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#" isActive>
|
||||
2
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationLink href="#">3</PaginationLink>
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationEllipsis />
|
||||
</PaginationItem>
|
||||
<PaginationItem>
|
||||
<PaginationNext href="#" />
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
```
|
||||
|
||||
95
docs/components/popover.md
Normal file
95
docs/components/popover.md
Normal file
@@ -0,0 +1,95 @@
|
||||
- Home
|
||||
- Components
|
||||
- Popover
|
||||
|
||||
# Popover
|
||||
|
||||
Displays rich content in a portal, triggered by a button.
|
||||
|
||||
## Props
|
||||
|
||||
### Popover
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
...Radix props ComponentProps<typeof PopoverPrimitive.Root> - All Radix Popover root props
|
||||
|
||||
### PopoverContent
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
align 'start' | 'center' | 'end' 'center' Content alignment relative to trigger
|
||||
sideOffset number 4 Offset in pixels from the trigger
|
||||
...Radix props ComponentProps<typeof PopoverPrimitive.Content> - All Radix content props
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline">Open popover</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80" align="start" onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<div>
|
||||
<div className="space-y-2 mb-2">
|
||||
<h4 className="leading-none font-medium">Dimensions</h4>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Set the dimensions for the layer.
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<FormLayout asChild className="w-2xs" orientation="label-left">
|
||||
<label>
|
||||
<p className="text-uk-md text-left">Width</p>
|
||||
<InputRoot
|
||||
id="width"
|
||||
defaultValue="300px"
|
||||
/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
<FormLayout asChild className="w-2xs" orientation="label-left">
|
||||
<label>
|
||||
<p className="text-uk-md text-left">Max width</p>
|
||||
<InputRoot
|
||||
id="maxWidth"
|
||||
defaultValue="300px"
|
||||
/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
<FormLayout asChild className="w-2xs" orientation="label-left">
|
||||
<label>
|
||||
<p className="text-uk-md text-left">Height</p>
|
||||
<InputRoot
|
||||
id="height"
|
||||
defaultValue="300px"
|
||||
/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
<FormLayout asChild className="w-2xs" orientation="label-left">
|
||||
<label>
|
||||
<p className="text-uk-md text-left">Max height</p>
|
||||
<InputRoot
|
||||
id="maxHeight"
|
||||
defaultValue="300px"
|
||||
/>
|
||||
</label>
|
||||
</FormLayout>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" sideOffset={8}>Content</PopoverContent>
|
||||
</Popover>
|
||||
```
|
||||
|
||||
97
docs/components/preview.md
Normal file
97
docs/components/preview.md
Normal file
@@ -0,0 +1,97 @@
|
||||
- Home
|
||||
- Components
|
||||
- Preview
|
||||
|
||||
# Preview
|
||||
|
||||
The Preview component is used throughout the documentation to display components alongside their code examples. It supports flexible layouts for showcasing components in different arrangements.
|
||||
|
||||
## FormLayout Options
|
||||
|
||||
## Default Layout
|
||||
|
||||
By default, the Preview component displays components horizontally with code below:
|
||||
|
||||
```
|
||||
<Button>Default Layout</Button>
|
||||
```
|
||||
|
||||
### Left Layout
|
||||
|
||||
Use left prop to position the component on the left side with a fixed width:
|
||||
|
||||
```
|
||||
<Button>Left Layout</Button>
|
||||
```
|
||||
|
||||
### Right Layout
|
||||
|
||||
Use right prop to position the component on the right side with a fixed width:
|
||||
|
||||
```
|
||||
<Button>Right Layout</Button>
|
||||
```
|
||||
|
||||
### Custom Width
|
||||
|
||||
You can specify custom widths for left or right layouts:
|
||||
|
||||
```
|
||||
<Button>Custom Width (300px)</Button>
|
||||
```
|
||||
|
||||
```
|
||||
<Button>Custom Width (150px)</Button>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### Required Props
|
||||
|
||||
|
||||
Prop Type Description
|
||||
children ReactNode Required. The code example content to display. Typically contains a markdown code block with syntax highlighting.
|
||||
component ReactNode Required. The actual component or JSX element to render in the preview panel.
|
||||
|
||||
### Layout Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
left boolean | number undefined Positions the component on the left side with code on the right. If true, uses default width of 200px. If a number, uses that value as width in pixels.
|
||||
right boolean | number undefined Positions the component on the right side with code on the left. If true, uses default width of 200px. If a number, uses that value as width in pixels.
|
||||
|
||||
### Code Block Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
lines number undefined Fixed height in lines. If collapsed=true, shows this many lines when collapsed. If collapsed=false, uses this as max height with scroll.
|
||||
collapsed boolean false Enable collapse/expand button functionality.
|
||||
startCollapsed boolean false Start in collapsed state (requires collapsed=true).
|
||||
maxLines number undefined When expanded, max lines before adding scroll. Only works with collapsed=true.
|
||||
|
||||
### Default Values
|
||||
|
||||
The Preview component uses these constants for default widths:
|
||||
|
||||
- Default left width: 200px (when left={true})
|
||||
- Default right width: 200px (when right={true})
|
||||
|
||||
### Layout Behavior
|
||||
|
||||
- Default layout (no left or right prop): Component displays above the code block in a horizontal stack
|
||||
- Left layout (left prop): Component panel on left (fixed width), code panel on right (flexible width)
|
||||
- Right layout (right prop): Code panel on left (flexible width), component panel on right (fixed width)
|
||||
- Mutual exclusivity: Only use either left OR right, never both simultaneously
|
||||
|
||||
## Usage Notes
|
||||
|
||||
- Only use either left OR right prop, not both
|
||||
- When no layout prop is provided, uses the default horizontal layout
|
||||
- The Preview component handles responsive behavior and code block styling automatically
|
||||
- Default widths are 200px for both left and right layouts
|
||||
- Code blocks automatically include copy buttons
|
||||
- Use collapsed={true} to enable collapse/expand functionality
|
||||
- Use lines={n} for fixed height or collapsed display height
|
||||
- Use maxLines={n} with collapsed={true} to control expanded height
|
||||
- Use startCollapsed={true} to begin in collapsed state
|
||||
|
||||
65
docs/components/progress.md
Normal file
65
docs/components/progress.md
Normal file
@@ -0,0 +1,65 @@
|
||||
- Home
|
||||
- Components
|
||||
- Progress
|
||||
|
||||
# Progress
|
||||
|
||||
Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
value number 0 The progress value (0-100)
|
||||
max number 100 The maximum value
|
||||
className string - Additional CSS classes
|
||||
...progress props ComponentProps<typeof ProgressPrimitive.Root> - All Radix Progress props are supported
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```
|
||||
<div className="w-60 space-y-6">
|
||||
<div className="flex flex-col gap-1 items-end">
|
||||
<span className="text-uk-md text-text-secondary">0%</span>
|
||||
<Progress value={0} />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 items-end">
|
||||
<span className="text-uk-md text-text-secondary">50%</span>
|
||||
<Progress value={50} />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 items-end">
|
||||
<span className="text-uk-md text-text-secondary">100%</span>
|
||||
<Progress value={100} />
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Animated Progress
|
||||
|
||||
```
|
||||
function AnimatedProgress() {
|
||||
const [progress, setProgress] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setProgress((prev) => {
|
||||
if (prev >= 100) return 0;
|
||||
return prev + 10;
|
||||
});
|
||||
}, 500);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="w-60 space-y-4">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm font-medium">Animated Progress</span>
|
||||
<span className="text-sm text-muted-foreground">{progress}%</span>
|
||||
</div>
|
||||
<Progress value={progress} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
61
docs/components/radio-group.md
Normal file
61
docs/components/radio-group.md
Normal file
@@ -0,0 +1,61 @@
|
||||
- Home
|
||||
- Components
|
||||
- Radio Group
|
||||
|
||||
# RadioGroup
|
||||
|
||||
A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
|
||||
|
||||
## Props
|
||||
|
||||
|
||||
Component Notes
|
||||
RadioGroup Pass-through wrapper over Radix RadioGroup.Root with layout classes
|
||||
RadioGroupItem Pass-through wrapper over Radix RadioGroup.Item with styles
|
||||
|
||||
All Radix props are supported.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<RadioGroup defaultValue="a">
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="a" id="a" />
|
||||
<label htmlFor="a">Option A</label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<RadioGroup defaultValue="r2">
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r1" id="r1" />
|
||||
<label htmlFor="r1">Radio 1</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r2" id="r2" />
|
||||
<label htmlFor="r2">Radio 2</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r3" id="r3" disabled />
|
||||
<label htmlFor="r3">Radio 3 disabled</label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
<RadioGroup defaultValue="r3">
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r1" id="r1" />
|
||||
<label htmlFor="r1">Radio 1</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r2" id="r2" />
|
||||
<label htmlFor="r2">Radio 2</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="r3" id="r3" disabled />
|
||||
<label htmlFor="r3">Radio 3 disabled</label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
```
|
||||
|
||||
241
docs/components/select.md
Normal file
241
docs/components/select.md
Normal file
@@ -0,0 +1,241 @@
|
||||
- Home
|
||||
- Components
|
||||
- Select
|
||||
|
||||
# Select
|
||||
|
||||
Displays a list of options for the user to pick from—triggered by a button.
|
||||
|
||||
## Types
|
||||
|
||||
```
|
||||
interface SelectTriggerProps extends ComponentProps<typeof SelectPrimitive.Trigger>, VariantProps<typeof selectTriggerVariants> {
|
||||
state?: "default" | "disabled" | "error";
|
||||
size?: "sm" | "md" | "lg";
|
||||
font?: "standard" | "mono";
|
||||
align?: "left" | "center" | "right";
|
||||
}
|
||||
|
||||
interface SelectItemProps extends ComponentProps<typeof SelectPrimitive.Item> {
|
||||
prefix?: ReactNode;
|
||||
suffix?: ReactNode;
|
||||
}
|
||||
|
||||
// Other select components use Radix primitives:
|
||||
// SelectRoot, SelectGroup, SelectValue, SelectContent,
|
||||
// SelectLabel, SelectSeparator - all extend Radix component props
|
||||
```
|
||||
|
||||
## In Toolbar
|
||||
|
||||
```
|
||||
<Toolbar>
|
||||
<ToolbarGroup>
|
||||
<Button icon variant="ghost" size="sm">
|
||||
<Settings className="size-4" />
|
||||
</Button>
|
||||
<Select defaultValue="medium">
|
||||
<SelectTrigger size="sm" className="w-20">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="small">S</SelectItem>
|
||||
<SelectItem value="medium">M</SelectItem>
|
||||
<SelectItem value="large">L</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button icon variant="ghost" size="sm">
|
||||
<Download className="size-4" />
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### Select
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
font 'standard' | 'mono' 'mono' Font family applied to trigger and items
|
||||
align 'left' | 'center' | 'right' 'left' Text alignment applied to trigger and items
|
||||
...Radix props ComponentProps<typeof SelectPrimitive.Root> - All Radix Select root props
|
||||
|
||||
### SelectTrigger
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
size 'sm' | 'md' | 'lg' 'md' Trigger size
|
||||
state 'default' | 'error' 'default' Visual state
|
||||
...Radix props ComponentProps<typeof SelectPrimitive.Trigger> - All Radix trigger props
|
||||
|
||||
### SelectContent
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
position 'item-aligned' | 'popper' 'item-aligned' Positioning strategy
|
||||
...Radix props ComponentProps<typeof SelectPrimitive.Content> - All Radix content props
|
||||
|
||||
### SelectItem
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
prefix ReactNode - Element rendered before the label
|
||||
suffix ReactNode - Element rendered after the label
|
||||
...Radix props ComponentProps<typeof SelectPrimitive.Item> - All Radix item props
|
||||
|
||||
### SelectLabel, SelectGroup, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, SelectValue
|
||||
|
||||
Pass-through wrappers for corresponding Radix components.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<Select defaultValue="apple">
|
||||
<SelectTrigger size="sm" className="w-[180px]">
|
||||
<SelectValue placeholder="Select a fruit"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Fruits</SelectLabel>
|
||||
<SelectItem value="apple">Apple</SelectItem>
|
||||
<SelectItem value="banana" prefix={<Plus/>}>Banana</SelectItem>
|
||||
<SelectItem disabled value="blueberry">Blueberry</SelectItem>
|
||||
<SelectItem value="grapes" suffix={<>Suffix<Minus/></>}>Grapes</SelectItem>
|
||||
<SelectItem value="pineapple">Pineapple</SelectItem>
|
||||
</SelectGroup>
|
||||
|
||||
<SelectSeparator/>
|
||||
|
||||
<SelectGroup>
|
||||
<SelectLabel>Vegetables</SelectLabel>
|
||||
<SelectItem value="aubergine">Aubergine</SelectItem>
|
||||
<SelectItem value="broccoli">Broccoli</SelectItem>
|
||||
<SelectItem disabled value="carrot">Carrot</SelectItem>
|
||||
<SelectItem value="courgette">Courgette</SelectItem>
|
||||
<SelectItem value="leek">Leek</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## State
|
||||
|
||||
```
|
||||
<Select>
|
||||
<SelectTrigger disabled size="sm" className="w-[180px]">
|
||||
<SelectValue placeholder="Disabled"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Fruits</SelectLabel>
|
||||
<SelectItem value="apple">Apple</SelectItem>
|
||||
<SelectItem value="banana">Banana</SelectItem>
|
||||
<SelectItem value="blueberry">Blueberry</SelectItem>
|
||||
<SelectItem value="grapes">Grapes</SelectItem>
|
||||
<SelectItem value="pineapple">Pineapple</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## Sides
|
||||
|
||||
Left
|
||||
|
||||
Top
|
||||
|
||||
Bottom
|
||||
|
||||
Right
|
||||
|
||||
```
|
||||
<p className="text-sm font-medium mb-2">Left</p>
|
||||
<Select>
|
||||
<SelectTrigger size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="Left"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent side="<left | top | bottom | right>" position="popper">
|
||||
<SelectGroup>
|
||||
<SelectItem value="left1">Left 1</SelectItem>
|
||||
<SelectItem value="left2">Left 2</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## Font Styles
|
||||
|
||||
Standard Font
|
||||
|
||||
Mono Font
|
||||
|
||||
```
|
||||
{/* Standard font */}
|
||||
<Select font="standard">
|
||||
<SelectTrigger size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="Standard"/>
|
||||
</SelectTrigger>
|
||||
</Select>
|
||||
|
||||
{/* Monospace font (default) */}
|
||||
<Select font="mono">
|
||||
<SelectTrigger size="sm" className="w-[120px]">
|
||||
<SelectValue placeholder="Mono"/>
|
||||
</SelectTrigger>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## Text Alignment
|
||||
|
||||
Left Aligned
|
||||
|
||||
Center Aligned
|
||||
|
||||
Right Aligned
|
||||
|
||||
```
|
||||
{/* Left aligned (default) */}
|
||||
<Select align="left">
|
||||
<SelectTrigger size="sm" className="w-[140px]">
|
||||
<SelectValue placeholder="Left aligned"/>
|
||||
</SelectTrigger>
|
||||
</Select>
|
||||
|
||||
{/* Center aligned */}
|
||||
<Select align="center">
|
||||
<SelectTrigger size="sm" className="w-[140px]">
|
||||
<SelectValue placeholder="Center aligned"/>
|
||||
</SelectTrigger>
|
||||
</Select>
|
||||
|
||||
{/* Right aligned */}
|
||||
<Select align="right">
|
||||
<SelectTrigger size="sm" className="w-[140px]">
|
||||
<SelectValue placeholder="Right aligned"/>
|
||||
</SelectTrigger>
|
||||
</Select>
|
||||
```
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
<Select>
|
||||
<SelectTrigger state="error" size="sm" className="w-[180px]">
|
||||
<SelectValue placeholder="Error"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Fruits</SelectLabel>
|
||||
<SelectItem value="apple">Apple</SelectItem>
|
||||
<SelectItem value="banana">Banana</SelectItem>
|
||||
<SelectItem value="blueberry">Blueberry</SelectItem>
|
||||
<SelectItem value="grapes">Grapes</SelectItem>
|
||||
<SelectItem value="pineapple">Pineapple</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
```
|
||||
|
||||
77
docs/components/sheet.md
Normal file
77
docs/components/sheet.md
Normal file
@@ -0,0 +1,77 @@
|
||||
- Home
|
||||
- Components
|
||||
- Sheet
|
||||
|
||||
# Sheet
|
||||
|
||||
Extends the Dialog component to display content that complements the main content of the screen.
|
||||
|
||||
## Props
|
||||
|
||||
### Sheet
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
...Radix props ComponentProps<typeof SheetPrimitive.Root> - All Radix Dialog root props
|
||||
|
||||
### SheetContent
|
||||
|
||||
|
||||
Prop Type Default Description
|
||||
side 'top' | 'right' | 'bottom' | 'left' 'right' Which edge to slide from
|
||||
...Radix props ComponentProps<typeof SheetPrimitive.Content> - All Radix content props
|
||||
|
||||
Other parts (SheetTrigger, SheetClose, SheetHeader, SheetFooter, SheetTitle, SheetDescription) are styled wrappers around Radix components.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button>Open</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left">
|
||||
<SheetHeader>
|
||||
<SheetTitle>Title</SheetTitle>
|
||||
<SheetDescription>Optional description</SheetDescription>
|
||||
</SheetHeader>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="outline">Open</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<SheetHeader>
|
||||
<SheetTitle>Edit profile</SheetTitle>
|
||||
<SheetDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
<div className="grid flex-1 auto-rows-min gap-4">
|
||||
<div className="grid gap-3">
|
||||
<label className="text-[12px]" htmlFor="sheet-demo-name">Name</label>
|
||||
<InputRoot id="sheet-demo-name" defaultValue="Pedro Duarte" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<label className="text-[12px]" htmlFor="sheet-demo-username">Username</label>
|
||||
<InputRoot id="sheet-demo-username" defaultValue="@peduarte" />
|
||||
</div>
|
||||
</div>
|
||||
<SheetFooter>
|
||||
<Button variant="primary">Save</Button>
|
||||
<SheetClose asChild>
|
||||
<Button variant="secondary">Close</Button>
|
||||
</SheetClose>
|
||||
</SheetFooter>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
```
|
||||
|
||||
156
docs/components/sidebar.md
Normal file
156
docs/components/sidebar.md
Normal file
@@ -0,0 +1,156 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Sidebar
|
||||
|
||||
# Sidebar
|
||||
|
||||
A composable, themeable and customizable sidebar component.
|
||||
|
||||
## Usage
|
||||
|
||||
Ge's Team - Documents
|
||||
- Team
|
||||
- Communication
|
||||
- SidebarMenuAction
|
||||
- SidebarMenuBadge24
|
||||
|
||||
Toggle Sidebar ```jsx
|
||||
import { ChevronDown, ChevronRight, Folder, FileText, Users, Mail, Bell } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
|
||||
const collapsibleItems = [
|
||||
{
|
||||
title: "Documents",
|
||||
icon: Folder,
|
||||
items: [
|
||||
{ title: "Reports", url: "#", icon: FileText },
|
||||
{ title: "Invoices", url: "#", icon: FileText },
|
||||
{ title: "Contracts", url: "#", icon: FileText },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Team",
|
||||
icon: Users,
|
||||
items: [
|
||||
{ title: "Members", url: "#", icon: Users },
|
||||
{ title: "Roles", url: "#", icon: Users },
|
||||
{ title: "Permissions", url: "#", icon: Users },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Communication",
|
||||
icon: Mail,
|
||||
items: [
|
||||
{ title: "Messages", url: "#", icon: Mail },
|
||||
{ title: "Notifications", url: "#", icon: Bell },
|
||||
{ title: "Announcements", url: "#", icon: Bell },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
function CollapsibleMenuItem({ item }) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton onClick={() => setIsOpen(!isOpen)} className="pl-lg">
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
{isOpen ? <ChevronDown className="ml-auto" /> : <ChevronRight className="ml-auto" />}
|
||||
</SidebarMenuButton>
|
||||
{isOpen && (
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((subItem) => (
|
||||
<SidebarMenuSubItem key={subItem.title}>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<a href={subItem.url}>
|
||||
<subItem.icon />
|
||||
<span>{subItem.title}</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
)}
|
||||
</SidebarMenuItem>
|
||||
<SidebarSeparator />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
<SidebarProvider>
|
||||
<Sidebar collapsible="offcanvas" className="relative">
|
||||
<SidebarHeader>
|
||||
<DropdownMenu className="w-full">
|
||||
<DropdownMenuTrigger asChild>
|
||||
<div className="flex items-center gap-md">
|
||||
<Avatar>
|
||||
<AvatarImage
|
||||
src="https://github.com/shadcn.png"
|
||||
alt="Team Avatar"
|
||||
/>
|
||||
<AvatarFallback>GT</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex items-center gap-sm">
|
||||
Ge's Team
|
||||
<ChevronDown size={16} />
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-[var(--radix-dropdown-menu-trigger-width)]">
|
||||
<DropdownMenuItem>
|
||||
<span>Menu item1</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<span>Menu item2</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<span>Menu item3</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarInput placeholder="Search for anything" />
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{collapsibleItems.map((item) => (
|
||||
<CollapsibleMenuItem key={item.title} item={item} />
|
||||
))}
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuSubButton asChild>
|
||||
<div>SidebarMenuAction</div>
|
||||
</SidebarMenuSubButton>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<SidebarMenuAction>
|
||||
<MoreHorizontal />
|
||||
</SidebarMenuAction>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="right" align="start">
|
||||
<DropdownMenuItem>
|
||||
<span>Edit Project</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<span>Delete Project</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem className="group-data-[collapsible=icon]:hidden">
|
||||
<SidebarMenuSubButton>
|
||||
<div>SidebarMenuBadge</div>
|
||||
</SidebarMenuSubButton>
|
||||
<SidebarMenuBadge>24</SidebarMenuBadge>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
<SidebarTrigger />
|
||||
</SidebarProvider>
|
||||
```
|
||||
98
docs/components/simple-tree-view.md
Normal file
98
docs/components/simple-tree-view.md
Normal file
@@ -0,0 +1,98 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Simple Tree View
|
||||
|
||||
# SimpleTreeView
|
||||
|
||||
## Types
|
||||
|
||||
```typescript
|
||||
interface TreeDataItem {
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: IconComponent;
|
||||
selectedIcon?: IconComponent;
|
||||
openIcon?: IconComponent;
|
||||
children?: TreeDataItem[];
|
||||
actions?: ReactNode;
|
||||
onClick?: () => void;
|
||||
draggable?: boolean;
|
||||
droppable?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
type IconComponent = React.ComponentType<{ className?: string }>;
|
||||
```
|
||||
|
||||
# Simple Tree View
|
||||
|
||||
## Props
|
||||
|
||||
### SimpleTreeView
|
||||
|
||||
| Prop | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| data | `TreeDataItem[] | TreeDataItem` |
|
||||
| initialSelectedItemId | string | Preselect an item and auto-expand ancestors |
|
||||
| onSelectChange | (item?: TreeDataItem) => void | Callback when selection changes |
|
||||
| expandAll | boolean | Expand all nodes initially |
|
||||
| defaultNodeIcon | IconComponent | Default icon for nodes |
|
||||
| defaultLeafIcon | IconComponent | Default icon for leaves |
|
||||
| onDocumentDrag | (source: TreeDataItem, target: TreeDataItem) => void | Drag and drop callback |
|
||||
|
||||
### TreeDataItem
|
||||
|
||||
```ts
|
||||
type TreeDataItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
selectedIcon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
openIcon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
children?: TreeDataItem[];
|
||||
actions?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
draggable?: boolean;
|
||||
droppable?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 3
|
||||
|
||||
```jsx
|
||||
const data = [
|
||||
{ id: '1', name: 'Item 1', icon: ArrowRight,
|
||||
children: [
|
||||
{ id: '2', name: 'Item 1.1', icon: AlarmClock,
|
||||
children: [
|
||||
{ id: '3', name: 'Item 1.1.1', icon: Ambulance },
|
||||
{ id: '4', name: 'Item 1.1.2', icon: Angry },
|
||||
],
|
||||
},
|
||||
{ id: '5', name: 'Item 1.2 (disabled)', icon: Album, disabled: true },
|
||||
],
|
||||
}, {
|
||||
id: '6', name: 'Item 2',
|
||||
children: [
|
||||
{ id: '7', name: 'Item 2.1', icon: AlignCenterHorizontal },
|
||||
{ id: '8', name: 'Item 2.2', icon: Blend,
|
||||
children: [
|
||||
{ id: '9', name: 'Item 2.2.1', icon: Bird },
|
||||
{ id: '10', name: 'Item 2.2.2', icon: Biohazard,
|
||||
children: [
|
||||
{ id: '11', name: 'Item 2.2.2.1', icon: Cannabis },
|
||||
{ id: '12', name: 'Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2', icon: Cannabis }
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ id: '13', name: 'Item 3' }
|
||||
];
|
||||
|
||||
<SimpleTreeView data={treeData} className="w-[260px]" />
|
||||
```
|
||||
76
docs/components/slider.md
Normal file
76
docs/components/slider.md
Normal file
@@ -0,0 +1,76 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Slider
|
||||
|
||||
# Slider
|
||||
|
||||
An input where the user selects a value from within a given range.
|
||||
|
||||
[Docs](https://www.radix-ui.com/primitives/docs/components/slider)[API Reference](https://www.radix-ui.com/primitives/docs/components/slider#api-reference)## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| showStep | boolean | false | Visualize step marks along the track |
|
||||
| min | number | 0 | Minimum value |
|
||||
| max | number | 100 | Maximum value |
|
||||
| step | number | 1 | Step size |
|
||||
| value | number[] | - | Controlled values for one or more thumbs |
|
||||
| defaultValue | number[] | - | Uncontrolled initial values |
|
||||
| onValueChange | (value: number[]) => void | - | Callback when value changes |
|
||||
| ...Radix props | ComponentProps<typeof SliderPrimitive.Root> | - | All Radix slider props |
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[50]} max={100} step={0.01}/>
|
||||
```
|
||||
|
||||
### Create a range
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[25, 75]} max={100} step={1}/>
|
||||
```
|
||||
|
||||
### Prevent thumb overlap
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[20, 70]} max={100} step={10} minStepsBetweenThumbs={1}/>
|
||||
```
|
||||
|
||||
### Define step size
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[20]} max={100} step={10}/>
|
||||
```
|
||||
|
||||
### Define step size and show
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[20]} min={2} max={100} step={10} showStep/>
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Slider showStep/>
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```jsx
|
||||
// Single value
|
||||
<Slider defaultValue={[50]} min={0} max={100} step={1} />
|
||||
|
||||
// Range
|
||||
<Slider defaultValue={[25, 75]} min={0} max={100} step={1} />
|
||||
```
|
||||
|
||||
### Disabled
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[20]} max={100} step={10} disabled/>
|
||||
```
|
||||
|
||||
### Disabled with step
|
||||
|
||||
```jsx
|
||||
<Slider defaultValue={[20]} max={100} step={10} showStep disabled/>
|
||||
```
|
||||
46
docs/components/spinner.md
Normal file
46
docs/components/spinner.md
Normal file
@@ -0,0 +1,46 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Spinner
|
||||
|
||||
# Spinner
|
||||
|
||||
The Spinner component provides a visual loading indicator with a smooth ring animation.
|
||||
It's built using SVG animations for optimal performance and customization.
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| size | number | 24 | Size of the spinner in pixels |
|
||||
| className | string | - | Additional CSS classes |
|
||||
| style | CSSProperties | - | Inline styles |
|
||||
| ...svg props | SVGProps<SVGSVGElement> | - | All native SVG props are supported |
|
||||
|
||||
## Overview
|
||||
|
||||
Spinners are used to indicate loading states or ongoing processes. They provide visual feedback to users that the application is working on their request.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Loading... Loading... Loading... ```jsx
|
||||
// Default spinner
|
||||
<Spinner />
|
||||
|
||||
// Medium spinner
|
||||
<Spinner size={32} />
|
||||
|
||||
// Large spinner
|
||||
<Spinner size={48} />
|
||||
```
|
||||
|
||||
## Custom Styling
|
||||
|
||||
Loading... Loading... Loading... Loading... ```jsx
|
||||
// Custom colors using className
|
||||
<Spinner className="text-blue-500" />
|
||||
<Spinner className="text-green-500" size={32} />
|
||||
<Spinner className="text-red-500" size={48} />
|
||||
|
||||
// Custom color using style
|
||||
<Spinner style={{ color: '#8B5CF6' }} size={32} />
|
||||
```
|
||||
42
docs/components/switch.md
Normal file
42
docs/components/switch.md
Normal file
@@ -0,0 +1,42 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Switch
|
||||
|
||||
# Switch
|
||||
|
||||
A control that allows the user to toggle between checked and not checked.
|
||||
|
||||
[Docs](https://www.radix-ui.com/primitives/docs/components/switch)[API Reference](https://www.radix-ui.com/primitives/docs/components/switch#api-reference)[shadcn/ui](https://ui.shadcn.com/docs/components/switch)## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| ...Radix props | ComponentProps<typeof SwitchPrimitive.Root> | - | All Radix switch root props |
|
||||
|
||||
### Examples
|
||||
|
||||
```jsx
|
||||
<Switch id="notifications" defaultChecked />
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Switch Switch checked Switch disabled Switch disabled checked ```jsx
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch id="Switch" />
|
||||
<label htmlFor="Switch">Switch</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch id="Switch On" defaultChecked />
|
||||
<label htmlFor="Switch On">Switch checked</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch id="Switch disabled" disabled />
|
||||
<label htmlFor="Switch disabled">Switch disabled</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch id="Switch disabled checked" defaultChecked disabled />
|
||||
<label htmlFor="Switch disabled checked">Switch disabled checked</label>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
237
docs/components/sync-scroll.md
Normal file
237
docs/components/sync-scroll.md
Normal file
@@ -0,0 +1,237 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Sync Scroll
|
||||
|
||||
# Synchronized Scrolling Components
|
||||
|
||||
Components for creating synchronized scrolling experiences with master-slave relationships and drag-to-scroll functionality.
|
||||
|
||||
## Basic Usage with Components
|
||||
|
||||
Master Scroll Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 Slave Scroll Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 ```jsx
|
||||
import {SyncScrollProvider, SyncScroll, SyncScrollSlave} from "@vuer-ai/vuer-uikit";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<SyncScrollProvider>
|
||||
<SyncScroll className="overflow-y-auto h-96">
|
||||
{/* Master scrollable content */}
|
||||
</SyncScroll>
|
||||
|
||||
<SyncScrollSlave className="overflow-y-auto h-96">
|
||||
{/* Slave synchronized scroll area */}
|
||||
</SyncScrollSlave>
|
||||
</SyncScrollProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## With Drag Control
|
||||
|
||||
The drag components now include built-in drag-to-scroll functionality. Click and drag to scroll!
|
||||
|
||||
SyncScroll Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 SyncDrag 🖱️ Click and drag vertically to scroll all panels Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 SyncScrollSlave Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 ```jsx
|
||||
import {SyncScrollProvider, SyncScroll, SyncDrag, SyncScrollSlave} from "@vuer-ai/vuer-uikit";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<SyncScrollProvider>
|
||||
<SyncScroll className="overflow-y-auto h-96">
|
||||
{/* Master scrollable content */}
|
||||
</SyncScroll>
|
||||
|
||||
<SyncDrag className="overflow-y-auto h-96">
|
||||
{/* Draggable content with vertical drag-to-scroll */}
|
||||
</SyncDrag>
|
||||
|
||||
<SyncScrollSlave className="overflow-y-auto h-96">
|
||||
{/* Slave synchronized area */}
|
||||
</SyncScrollSlave>
|
||||
</SyncScrollProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Horizontal Drag Variants
|
||||
|
||||
Horizontal drag components allow left/right scrolling via drag gestures:
|
||||
|
||||
### Horizontal Draggable Panels - Both Can Be Dragged
|
||||
|
||||
Drag either panel to control both - Master (left) overrides Slave (right)
|
||||
|
||||
MASTER DRAG (SyncDragX) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 SLAVE DRAG (SyncDragSlaveX) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ```jsx
|
||||
import {SyncScrollProvider, SyncDragX, SyncDragSlaveX} from "@vuer-ai/vuer-uikit";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<SyncScrollProvider>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{/* Master drag - controls all */}
|
||||
<SyncDragX className="border-2 border-blue-400 rounded h-32 overflow-x-auto bg-blue-50">
|
||||
<div className="flex gap-4 p-4" style={{width: '1200px'}}>
|
||||
{/* Horizontal content */}
|
||||
</div>
|
||||
</SyncDragX>
|
||||
|
||||
{/* Slave drag - follows master but can be dragged */}
|
||||
<SyncDragSlaveX className="border-2 border-green-400 rounded h-32 bg-green-50">
|
||||
<div className="flex gap-4 p-4" style={{width: '1200px'}}>
|
||||
{/* Horizontal content */}
|
||||
</div>
|
||||
</SyncDragSlaveX>
|
||||
</div>
|
||||
</SyncScrollProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Omnidirectional Drag Variants
|
||||
|
||||
Omnidirectional drag components allow scrolling in any direction via drag gestures:
|
||||
|
||||
### Omnidirectional Draggable Panels - Both Can Be Dragged
|
||||
|
||||
Drag either panel in any direction - Master (left) overrides Slave (right)
|
||||
|
||||
MASTER DRAG (SyncDrag) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 SLAVE DRAG (SyncDragSlave) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ```jsx
|
||||
import {SyncScrollProvider, SyncDrag, SyncDragSlave} from "@vuer-ai/vuer-uikit";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<SyncScrollProvider>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{/* Master drag - controls all */}
|
||||
<SyncDrag className="border-2 border-purple-400 rounded h-64 overflow-auto bg-purple-50">
|
||||
<div style={{width: '800px', height: '600px'}} className="p-8">
|
||||
{/* Content that scrolls in both directions */}
|
||||
</div>
|
||||
</SyncDrag>
|
||||
|
||||
{/* Slave drag - follows master but can be dragged */}
|
||||
<SyncDragSlave className="border-2 border-orange-400 rounded h-64 bg-orange-50">
|
||||
<div style={{width: '800px', height: '600px'}} className="p-8">
|
||||
{/* Content that scrolls in both directions */}
|
||||
</div>
|
||||
</SyncDragSlave>
|
||||
</div>
|
||||
</SyncScrollProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Using Hooks Directly
|
||||
|
||||
For more control, you can use the hooks directly:
|
||||
|
||||
useSyncScroll Hook Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 useScrollSlave Hook Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 useSyncDrag Hook Item 1 Item 2 Item 3 Item 4 Item 5 Item 6 Item 7 Item 8 Item 9 Item 10 Item 11 Item 12 Item 13 Item 14 Item 15 Item 16 Item 17 Item 18 Item 19 Item 20 Item 21 Item 22 Item 23 Item 24 Item 25 Item 26 Item 27 Item 28 Item 29 Item 30 Item 31 Item 32 Item 33 Item 34 Item 35 Item 36 Item 37 Item 38 Item 39 Item 40 Item 41 Item 42 Item 43 Item 44 Item 45 Item 46 Item 47 Item 48 Item 49 Item 50 ```jsx
|
||||
import {SyncScrollProvider, useSyncScroll, useScrollSlave, useSyncDrag} from "@vuer-ai/vuer-uikit";
|
||||
|
||||
// Master panel - controls all other panels
|
||||
function MasterPanel() {
|
||||
const ref = useSyncScroll();
|
||||
|
||||
return (
|
||||
<div ref={ref} className="overflow-y-auto h-96">
|
||||
{/* Your scrollable content */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Slave panel - controlled by master, syncs with other slaves
|
||||
function SlavePanel() {
|
||||
const ref = useScrollSlave();
|
||||
|
||||
return (
|
||||
<div ref={ref} className="overflow-y-auto h-96">
|
||||
{/* Your scrollable content */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Drag panel - acts like master when dragged
|
||||
function DragPanel() {
|
||||
const ref = useSyncDrag();
|
||||
|
||||
return (
|
||||
<div ref={ref} className="overflow-y-auto h-96">
|
||||
{/* Your draggable content */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<SyncScrollProvider>
|
||||
<MasterPanel/>
|
||||
<SlavePanel/>
|
||||
<DragPanel/>
|
||||
</SyncScrollProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Components
|
||||
|
||||
#### <SyncScrollProvider>
|
||||
|
||||
Wraps components that need synchronized scrolling.
|
||||
|
||||
#### <SyncScroll>
|
||||
|
||||
A scrollable container that synchronizes with other scroll components. Acts as a master that controls all other synchronized elements.
|
||||
|
||||
Props: Extends HTMLAttributes<HTMLDivElement>
|
||||
|
||||
#### <SyncScrollSlave>
|
||||
|
||||
A scrollable container that is controlled by masters and syncs with other slaves.
|
||||
|
||||
Props: Extends HTMLAttributes<HTMLDivElement>
|
||||
|
||||
#### <SyncDrag>
|
||||
|
||||
A draggable container that supports both horizontal and vertical drag-to-scroll. Click and drag in any direction to scroll both horizontally and vertically. Controls synchronized scrolling.
|
||||
|
||||
Props: Extends HTMLAttributes<HTMLDivElement>
|
||||
|
||||
#### <SyncDragX>
|
||||
|
||||
A draggable container that only supports horizontal drag-to-scroll. Click and drag left/right to scroll horizontally only (vertical dragging is disabled). Controls synchronized scrolling.
|
||||
|
||||
Props: Extends HTMLAttributes<HTMLDivElement>
|
||||
|
||||
### Hooks
|
||||
|
||||
#### useSyncScroll()
|
||||
|
||||
Returns a ref for a master scroll element that controls all other elements.
|
||||
|
||||
#### useScrollSlave()
|
||||
|
||||
Returns a ref for a slave scroll element that is controlled by masters and syncs with other slaves.
|
||||
|
||||
#### useSyncDrag()
|
||||
|
||||
Returns a ref for drag-controlled scrolling that acts like a master in synchronized scrolling.
|
||||
|
||||
### Behavior Notes
|
||||
|
||||
- Master elements (SyncScroll, useSyncScroll): Control all other synchronized elements
|
||||
- Slave elements (SyncScrollSlave, useScrollSlave): Are controlled by masters and sync with other slaves
|
||||
- Drag elements (SyncDrag, SyncDragX, Drag, useSyncDrag): Act like masters with built-in drag-to-scroll functionality
|
||||
- SyncDrag: Vertical drag-to-scroll
|
||||
- SyncDragX: Horizontal drag-to-scroll
|
||||
- Drag: Omnidirectional drag-to-scroll
|
||||
|
||||
📍 SyncScroll: Master scroll control - scrolling affects all synchronized elements
|
||||
|
||||
📍 SyncScrollSlave: Controlled by masters, syncs with other slaves
|
||||
|
||||
📍 SyncDrag: Vertical drag-to-scroll that controls all synchronized elements
|
||||
|
||||
📍 SyncDragX: Horizontal drag-to-scroll that controls all synchronized elements
|
||||
|
||||
📍 Drag: Omnidirectional drag-to-scroll that controls all synchronized elements
|
||||
82
docs/components/table.md
Normal file
82
docs/components/table.md
Normal file
@@ -0,0 +1,82 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
0 item s selected Clear All Learn React hooks Build a todo app Implement drag selection Style with Tailwind CSS Add dark mode support Write unit tests Deploy to production Add keyboard shortcuts Improve accessibility Add animations ```tsx
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage:
|
||||
Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
82
docs/components/tabs.md
Normal file
82
docs/components/tabs.md
Normal file
@@ -0,0 +1,82 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
0 item s selected Clear All Learn React hooks Build a todo app Implement drag selection Style with Tailwind CSS Add dark mode support Write unit tests Deploy to production Add keyboard shortcuts Improve accessibility Add animations ```tsx
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage:
|
||||
Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
82
docs/components/textarea.md
Normal file
82
docs/components/textarea.md
Normal file
@@ -0,0 +1,82 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
0 item s selected Clear All Learn React hooks Build a todo app Implement drag selection Style with Tailwind CSS Add dark mode support Write unit tests Deploy to production Add keyboard shortcuts Improve accessibility Add animations ```tsx
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage:
|
||||
Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
82
docs/components/toast.md
Normal file
82
docs/components/toast.md
Normal file
@@ -0,0 +1,82 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
0 item s selected Clear All Learn React hooks Build a todo app Implement drag selection Style with Tailwind CSS Add dark mode support Write unit tests Deploy to production Add keyboard shortcuts Improve accessibility Add animations ```tsx
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage:
|
||||
Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
231
docs/components/toggle-buttons.md
Normal file
231
docs/components/toggle-buttons.md
Normal file
@@ -0,0 +1,231 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Toggle Buttons
|
||||
|
||||
# Toggle Buttons
|
||||
|
||||
A set of buttons where only one can be selected at a time, with smooth animated transitions between selections.
|
||||
|
||||
## Props
|
||||
|
||||
### ToggleButtons
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| value | string | - | Controlled value |
|
||||
| onValueChange | (value: string) => void | - | Callback when value changes |
|
||||
| size | 'sm' | 'base' | 'lg' | 'base' | Size of the buttons |
|
||||
| variant | 'primary' | 'secondary' | 'ghost' | 'secondary' | Visual style variant |
|
||||
| padding | boolean | true | Whether to add padding between container and buttons |
|
||||
| className | string | - | Custom CSS classes |
|
||||
| children | ReactNode | - | ToggleButton components |
|
||||
|
||||
### ToggleButton
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| value | string | - | Value for this button |
|
||||
| icon | boolean | false | If true, renders as square icon button with proper sizing |
|
||||
| asChild | boolean | false | Render as child element (using Slot) |
|
||||
| className | string | - | Custom CSS classes |
|
||||
| children | ReactNode | - | Button content |
|
||||
|
||||
## Icon Only
|
||||
|
||||
Perfect for toolbar-style interfaces with square buttons:
|
||||
|
||||
Primary
|
||||
|
||||
Secondary
|
||||
|
||||
Ghost
|
||||
|
||||
Selected: select
|
||||
|
||||
```jsx
|
||||
import { MousePointer, Hand, Scissors } from "lucide-react";
|
||||
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Primary</p>
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={false} variant="primary">
|
||||
<ToggleButton value="select" icon>
|
||||
<MousePointer className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="pick" icon>
|
||||
<Hand className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="cut" icon>
|
||||
<Scissors className="size-4" />
|
||||
</ToggleButton>
|
||||
</ToggleButtons>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Secondary</p>
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={false} variant="secondary">
|
||||
<ToggleButton value="select" icon>
|
||||
<MousePointer className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="pick" icon>
|
||||
<Hand className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="cut" icon>
|
||||
<Scissors className="size-4" />
|
||||
</ToggleButton>
|
||||
</ToggleButtons>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Ghost</p>
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={false} variant="ghost">
|
||||
<ToggleButton value="select" icon>
|
||||
<MousePointer className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="pick" icon>
|
||||
<Hand className="size-4" />
|
||||
</ToggleButton>
|
||||
<ToggleButton value="cut" icon>
|
||||
<Scissors className="size-4" />
|
||||
</ToggleButton>
|
||||
</ToggleButtons>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Select Pick Cut Selected: select
|
||||
|
||||
```jsx
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool}>
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
);
|
||||
```
|
||||
|
||||
## Padding Options
|
||||
|
||||
Control the spacing between the container and buttons:
|
||||
|
||||
With Padding (default)
|
||||
|
||||
Select Pick Cut Without Padding
|
||||
|
||||
Select Pick Cut Selected: select
|
||||
|
||||
```jsx
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* With padding (default) */}
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={true} variant="primary">
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
|
||||
{/* Without padding - buttons inherit full container size */}
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={false} variant="primary">
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
Small
|
||||
|
||||
Select Pick Cut Base
|
||||
|
||||
Select Pick Cut Large
|
||||
|
||||
Select Pick Cut Selected: select
|
||||
|
||||
```jsx
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<>
|
||||
<ToggleButtons size="sm" value={selectedTool} onValueChange={setSelectedTool}>
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
|
||||
<ToggleButtons size="base" value={selectedTool} onValueChange={setSelectedTool}>
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
|
||||
<ToggleButtons size="lg" value={selectedTool} onValueChange={setSelectedTool}>
|
||||
<ToggleButton value="select">Select</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
## Custom Styling
|
||||
|
||||
Select Pick Cut Selected: select
|
||||
|
||||
```jsx
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<ToggleButtons
|
||||
value={selectedTool}
|
||||
onValueChange={setSelectedTool}
|
||||
className="bg-blue-100 border-2 border-blue-300" // Custom container styles
|
||||
>
|
||||
<ToggleButton
|
||||
value="select"
|
||||
className="font-bold text-blue-600" // Custom item styles
|
||||
>
|
||||
Select
|
||||
</ToggleButton>
|
||||
<ToggleButton value="pick">Pick</ToggleButton>
|
||||
<ToggleButton value="cut">Cut</ToggleButton>
|
||||
</ToggleButtons>
|
||||
);
|
||||
```
|
||||
|
||||
## AsChild
|
||||
|
||||
Use asChild to render the toggle button as a different element while maintaining all functionality:
|
||||
|
||||
[Home](#home)[About](#about)[Contact](#contact)Selected: home
|
||||
|
||||
```jsx
|
||||
const [selectedPage, setSelectedPage] = useState("home");
|
||||
|
||||
return (
|
||||
<ToggleButtons value={selectedPage} onValueChange={setSelectedPage}>
|
||||
<ToggleButton value="home" asChild>
|
||||
<a href="#home">Home</a>
|
||||
</ToggleButton>
|
||||
<ToggleButton value="about" asChild>
|
||||
<a href="#about">About</a>
|
||||
</ToggleButton>
|
||||
<ToggleButton value="contact" asChild>
|
||||
<a href="#contact">Contact</a>
|
||||
</ToggleButton>
|
||||
</ToggleButtons>
|
||||
);
|
||||
```
|
||||
110
docs/components/toggle-group.md
Normal file
110
docs/components/toggle-group.md
Normal file
@@ -0,0 +1,110 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Toggle Group
|
||||
|
||||
# Toggle Group
|
||||
|
||||
A set of two-state buttons that can be toggled on or off. Toggle buttons share outer rounded corners with sharp inner corners, creating a seamless single-button appearance.
|
||||
|
||||
[Docs](https://www.radix-ui.com/primitives/docs/components/toggle-group)[API Reference](https://www.radix-ui.com/primitives/docs/components/toggle-group#api-reference)## Props
|
||||
|
||||
### ToggleGroup
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| etype | 'single' | 'multiple' | 'single' | Selection behavior |
|
||||
| variant | 'primary' | 'secondary' | 'ghost' | 'primary' | Visual style passed to items |
|
||||
| size | 'sm' | 'base' | 'lg' | 'base' | Size passed to items |
|
||||
| ...Radix props | ComponentProps<typeof ToggleGroupPrimitive.Root> | - | All Radix group props |
|
||||
|
||||
### ToggleGroupItem
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| inherits | variant, size from group | - | Styling context from parent |
|
||||
| ...Radix props | ComponentProps<typeof ToggleGroupPrimitive.Item> | - | All Radix item props |
|
||||
|
||||
Multiple buttons can be active at once with etype="multiple".
|
||||
|
||||
## Variants
|
||||
|
||||
### Primary (Default)
|
||||
|
||||
1 2 3 Selected: option-1
|
||||
|
||||
```jsx
|
||||
<ToggleGroup variant="primary" type="multiple" size="sm">
|
||||
<ToggleGroupItem value="option-1">1</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-2">2</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-3">3</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
|
||||
### Secondary
|
||||
|
||||
1 2 3 Selected: option-1
|
||||
|
||||
```jsx
|
||||
<ToggleGroup variant="secondary" type="multiple" size="sm">
|
||||
<ToggleGroupItem value="option-1">1</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-2">2</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-3">3</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
|
||||
### Ghost
|
||||
|
||||
1 2 3 Selected: option-1
|
||||
|
||||
```jsx
|
||||
<ToggleGroup variant="ghost" type="multiple" size="sm">
|
||||
<ToggleGroupItem value="option-1">1</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-2">2</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-3">3</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
|
||||
## Single Selection
|
||||
|
||||
Selected: center
|
||||
|
||||
```jsx
|
||||
const [value, setValue] = useState("center");
|
||||
|
||||
<ToggleGroup variant="primary" type="single" size="sm" value={value} onValueChange={setValue}>
|
||||
<ToggleGroupItem value="left"><AlignLeft className="size-3" /></ToggleGroupItem>
|
||||
<ToggleGroupItem value="center"><AlignCenter className="size-3" /></ToggleGroupItem>
|
||||
<ToggleGroupItem value="right"><AlignRight className="size-3" /></ToggleGroupItem>
|
||||
<ToggleGroupItem value="justify"><AlignJustify className="size-3" /></ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
|
||||
Only one button can be active at a time with etype="single".
|
||||
|
||||
## With Icons
|
||||
|
||||
Selected: list
|
||||
|
||||
```jsx
|
||||
const [value, setValue] = useState(["view-1"]);
|
||||
|
||||
<ToggleGroup variant="primary" type="multiple" size="sm" value={value} onValueChange={setValue}>
|
||||
<ToggleGroupItem value="list"><List className="size-3" /></ToggleGroupItem>
|
||||
<ToggleGroupItem value="grid"><Grid className="size-3" /></ToggleGroupItem>
|
||||
<ToggleGroupItem value="folder"><Folder className="size-3" /></ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
|
||||
Toggle group with icon content.
|
||||
|
||||
## Disabled State
|
||||
|
||||
1 2 3 Selected: None
|
||||
|
||||
```jsx
|
||||
<ToggleGroup variant="primary" type="multiple" size="sm">
|
||||
<ToggleGroupItem value="option-1">1</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-2" disabled>2</ToggleGroupItem>
|
||||
<ToggleGroupItem value="option-3">3</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
```
|
||||
82
docs/components/toggle.md
Normal file
82
docs/components/toggle.md
Normal file
@@ -0,0 +1,82 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Drag Selectable
|
||||
|
||||
# Drag Selectable
|
||||
|
||||
A React component system that enables drag selection over a vertical list of items with toggle-based multi-select behavior.
|
||||
|
||||
## Live Example
|
||||
|
||||
Try the drag selection below:
|
||||
|
||||
- Normal drag: Toggle selection
|
||||
- Ctrl/Cmd + drag: Replace selection
|
||||
- Escape: Clear all selections
|
||||
|
||||
0 item s selected Clear All Learn React hooks Build a todo app Implement drag selection Style with Tailwind CSS Add dark mode support Write unit tests Deploy to production Add keyboard shortcuts Improve accessibility Add animations ```tsx
|
||||
import React from 'react';
|
||||
import { Card, Badge, useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
const TODOS = [
|
||||
{ key: "1", title: "Learn React hooks" },
|
||||
{ key: "2", title: "Build a todo app" },
|
||||
{ key: "3", title: "Implement drag selection" },
|
||||
// ... more items
|
||||
];
|
||||
|
||||
export default function DragSelectExample() {
|
||||
const { selectedItems, getItemProps, clearSelection } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={clearSelection}>
|
||||
Clear ({selectedItems.size} selected)
|
||||
</button>
|
||||
|
||||
{TODOS.map(todo => (
|
||||
<TodoItem
|
||||
key={todo.key}
|
||||
title={todo.title}
|
||||
checked={selectedItems.has(todo.key)}
|
||||
{...getItemProps(todo.key)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Simple API
|
||||
|
||||
The useDragSelect() hook provides everything you need for drag selection:
|
||||
|
||||
Returns:
|
||||
|
||||
- selectedItems: Set<string> - Currently selected item IDs
|
||||
- getItemProps(id: string) - Props to spread on selectable items
|
||||
- clearSelection() - Function to clear all selections
|
||||
- isSelected(id: string) - Check if item is selected
|
||||
|
||||
Usage:
|
||||
Just import the hook, call it, and spread getItemProps(id) on your items. The hook handles all the complex state management, event handling, and keyboard shortcuts automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic Event Handling - Mouse and keyboard events handled internally
|
||||
- Modifier Key Support - Ctrl/Cmd for replace mode, default toggle mode
|
||||
- Global Events - Mouse up and Escape key work anywhere on page
|
||||
- TypeScript Support - Fully typed hook and props
|
||||
- Zero Dependencies - Pure React implementation
|
||||
|
||||
## Selection Modes
|
||||
|
||||
- Toggle (default): Items flip their selection state during drag
|
||||
- Replace (Ctrl/Cmd + drag): Clear existing selection, start new selection range
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
- Screen reader friendly markup
|
||||
- Clear visual feedback for selection states
|
||||
46
docs/components/tooltip.md
Normal file
46
docs/components/tooltip.md
Normal file
@@ -0,0 +1,46 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Tooltip
|
||||
|
||||
# Tooltip
|
||||
|
||||
A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
|
||||
|
||||
[Docs](https://www.radix-ui.com/primitives/docs/components/tooltip)[API Reference](https://www.radix-ui.com/primitives/docs/components/tooltip#api-reference)## Props
|
||||
|
||||
### Tooltip
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| ...Radix props | ComponentProps<typeof TooltipPrimitive.Root> | - | All Radix tooltip root props |
|
||||
|
||||
### TooltipContent
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| sideOffset | number | 0 | Offset in pixels from the trigger |
|
||||
| ...Radix props | ComponentProps<typeof TooltipPrimitive.Content> | - | All Radix content props |
|
||||
|
||||
## Usage
|
||||
|
||||
Top Left Right Bottom ```jsx
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">Top</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" align="start">
|
||||
<p>Add to library</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```jsx
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">Hover</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">Hello</TooltipContent>
|
||||
</Tooltip>
|
||||
```
|
||||
98
docs/components/tree-view.md
Normal file
98
docs/components/tree-view.md
Normal file
@@ -0,0 +1,98 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Simple Tree View
|
||||
|
||||
# SimpleTreeView
|
||||
|
||||
## Types
|
||||
|
||||
```typescript
|
||||
interface TreeDataItem {
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: IconComponent;
|
||||
selectedIcon?: IconComponent;
|
||||
openIcon?: IconComponent;
|
||||
children?: TreeDataItem[];
|
||||
actions?: ReactNode;
|
||||
onClick?: () => void;
|
||||
draggable?: boolean;
|
||||
droppable?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
type IconComponent = React.ComponentType<{ className?: string }>;
|
||||
```
|
||||
|
||||
# Simple Tree View
|
||||
|
||||
## Props
|
||||
|
||||
### SimpleTreeView
|
||||
|
||||
| Prop | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| data | `TreeDataItem[] | TreeDataItem` |
|
||||
| initialSelectedItemId | string | Preselect an item and auto-expand ancestors |
|
||||
| onSelectChange | (item?: TreeDataItem) => void | Callback when selection changes |
|
||||
| expandAll | boolean | Expand all nodes initially |
|
||||
| defaultNodeIcon | IconComponent | Default icon for nodes |
|
||||
| defaultLeafIcon | IconComponent | Default icon for leaves |
|
||||
| onDocumentDrag | (source: TreeDataItem, target: TreeDataItem) => void | Drag and drop callback |
|
||||
|
||||
### TreeDataItem
|
||||
|
||||
```ts
|
||||
type TreeDataItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
selectedIcon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
openIcon?: ComponentType<SVGProps<SVGSVGElement>>;
|
||||
children?: TreeDataItem[];
|
||||
actions?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
draggable?: boolean;
|
||||
droppable?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 3
|
||||
|
||||
```jsx
|
||||
const data = [
|
||||
{ id: '1', name: 'Item 1', icon: ArrowRight,
|
||||
children: [
|
||||
{ id: '2', name: 'Item 1.1', icon: AlarmClock,
|
||||
children: [
|
||||
{ id: '3', name: 'Item 1.1.1', icon: Ambulance },
|
||||
{ id: '4', name: 'Item 1.1.2', icon: Angry },
|
||||
],
|
||||
},
|
||||
{ id: '5', name: 'Item 1.2 (disabled)', icon: Album, disabled: true },
|
||||
],
|
||||
}, {
|
||||
id: '6', name: 'Item 2',
|
||||
children: [
|
||||
{ id: '7', name: 'Item 2.1', icon: AlignCenterHorizontal },
|
||||
{ id: '8', name: 'Item 2.2', icon: Blend,
|
||||
children: [
|
||||
{ id: '9', name: 'Item 2.2.1', icon: Bird },
|
||||
{ id: '10', name: 'Item 2.2.2', icon: Biohazard,
|
||||
children: [
|
||||
{ id: '11', name: 'Item 2.2.2.1', icon: Cannabis },
|
||||
{ id: '12', name: 'Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2 Item 2.2.2.2', icon: Cannabis }
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ id: '13', name: 'Item 3' }
|
||||
];
|
||||
|
||||
<SimpleTreeView data={treeData} className="w-[260px]" />
|
||||
```
|
||||
88
docs/components/version-badge.md
Normal file
88
docs/components/version-badge.md
Normal file
@@ -0,0 +1,88 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Version Badge
|
||||
|
||||
# Version Badge
|
||||
|
||||
Displays the package version with git commit hash. Includes both a high-level component with boolean flags and a low-level component for custom values.
|
||||
|
||||
## High-Level Component (UIKitBadge)
|
||||
|
||||
Uses boolean flags to control which parts of the badge are displayed. All flags default to false - pass them as true to enable each element.
|
||||
|
||||
vuer-uikit [v0.0.117](https://www.npmjs.com/package/@vuer-ai/vuer-uikit/v/0.0.117)[2a52049](https://github.com/vuer-ai/vuer-uikit/commit/2a52049)vuer-uikit [v0.0.117](https://www.npmjs.com/package/@vuer-ai/vuer-uikit/v/0.0.117)vuer-uikit 0.0.1172a52049v0.0.117vuer-uikit 2a520490.0.117```jsx
|
||||
// Full badge with all elements
|
||||
<UIKitBadge package version prefix hash linkable />
|
||||
|
||||
// Package, version with prefix, clickable (no hash)
|
||||
<UIKitBadge package version prefix linkable />
|
||||
|
||||
// Package, version without prefix, with hash
|
||||
<UIKitBadge package version hash />
|
||||
|
||||
// Version with prefix only
|
||||
<UIKitBadge version prefix />
|
||||
|
||||
// Package and hash only (no version)
|
||||
<UIKitBadge package hash />
|
||||
|
||||
// Version only (no prefix)
|
||||
<UIKitBadge version />
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| package | boolean | false | Show package name |
|
||||
| version | boolean | false | Show version number |
|
||||
| prefix | boolean | false | Add "v" prefix to version |
|
||||
| hash | boolean | false | Show git commit hash |
|
||||
| linkable | boolean | false | Make badge clickable (links to npm/github) |
|
||||
| className | string | - | Additional CSS classes |
|
||||
|
||||
## Low-Level Component (PackageBadge)
|
||||
|
||||
Takes explicit values for full customization.
|
||||
|
||||
custom [v1.2.3](https://www.npmjs.com/package/@org/custom-package/v/1.2.3)[abc123](https://github.com/vuer-ai/vuer-uikit/commit/abc123)mylib 2.0.0v3.0.0-beta.1[def456](https://github.com/vuer-ai/vuer-uikit/commit/def456)```jsx
|
||||
// Custom package with all values
|
||||
<PackageBadge
|
||||
packageName="custom"
|
||||
versionText="v1.2.3"
|
||||
gitHash="abc123"
|
||||
packageFullName="@org/custom-package"
|
||||
/>
|
||||
|
||||
// Non-linkable custom badge
|
||||
<PackageBadge
|
||||
packageName="mylib"
|
||||
versionText="2.0.0"
|
||||
linkable={false}
|
||||
/>
|
||||
|
||||
// Version and hash only
|
||||
<PackageBadge
|
||||
versionText="v3.0.0-beta.1"
|
||||
gitHash="def456"
|
||||
/>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| packageName | string | - | Package name to display |
|
||||
| packageFullName | string | - | Full npm package name for link |
|
||||
| versionText | string | - | Version string to display |
|
||||
| gitHash | string | - | Git commit hash to display |
|
||||
| linkable | boolean | true | Make badge clickable |
|
||||
| className | string | - | Additional CSS classes |
|
||||
|
||||
## Programmatic Access
|
||||
|
||||
```jsx
|
||||
import { PACKAGE_VERSION, GIT_HASH } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
console.log(`Version: ${PACKAGE_VERSION}, Commit: ${GIT_HASH}`);
|
||||
```
|
||||
312
docs/components/waterfall.md
Normal file
312
docs/components/waterfall.md
Normal file
@@ -0,0 +1,312 @@
|
||||
1. Home
|
||||
2. Components
|
||||
3. Waterfall
|
||||
|
||||
# Waterfall
|
||||
|
||||
A hierarchical log display component for showing time-based log data with interactive controls and custom actions.
|
||||
|
||||
```typescript
|
||||
interface WaterfallProps {
|
||||
logData: LogItemType[];
|
||||
temporalCursor?: number;
|
||||
panelWidth?: number;
|
||||
onTemporalCursorChange?: (time: number) => void;
|
||||
getIcon: (item: LogItemType) => ReactNode;
|
||||
hoveredId?: string | null;
|
||||
onItemHover?: (id: string | null) => void;
|
||||
minWindow?: number;
|
||||
maxWindow?: number;
|
||||
zoomFactor?: number;
|
||||
enabled?: boolean;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
```typescript
|
||||
type LogItemType = TreeDataItemV2 & {
|
||||
type: "task" | "attempt" | "info" | "step";
|
||||
icon?: "history" | "file-code" | "bot" | "check-circle" | "pause-circle";
|
||||
createTime?: number;
|
||||
startTime?: number;
|
||||
duration?: number;
|
||||
time?: number;
|
||||
color?: "blue" | "green" | "orange" | "gray-light" | "gray-medium" | "purple";
|
||||
isCollapsible?: boolean;
|
||||
hasStripes?: boolean;
|
||||
isHaltedStep?: boolean;
|
||||
};
|
||||
|
||||
type TreeDataItemV2 = {
|
||||
id: string;
|
||||
parentId: string | null;
|
||||
label: string;
|
||||
isCollapsible?: boolean;
|
||||
actions?: ReactNode;
|
||||
disable?: boolean;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Job registered in queue generate-report Attempt 1 Fetch database records Job halted, waiting for resources... Waiting for image renderer... Render charts Assemble PDF Fetch database records Memory checkpoint data-validation Schema validation Data integrity check Generate validation report Cache cleared email-notification Prepare email template Attach report files Send via SMTP Webhook triggered System health check cleanup-process Remove temporary files Update job status All tasks completed -10s -5s 0ms 5s 10s 15s 20s 25s 30s 20.000s 19.900s 3.000s Halted 4.600s 6.200s 3.000s 12.000s 3.500s 33.000s ```jsx
|
||||
import { Waterfall, LogItemType } from "@vuer-ai/vuer-uikit";
|
||||
import React, { useState, useMemo } from "react";
|
||||
import {
|
||||
Bot,
|
||||
CheckCircle2,
|
||||
FileCode,
|
||||
History,
|
||||
Info,
|
||||
PauseCircle,
|
||||
Eye,
|
||||
EyeClosed,
|
||||
Trash2,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@vuer-ai/vuer-uikit";
|
||||
|
||||
const logData: LogItemType[] = [
|
||||
{
|
||||
id: "0",
|
||||
parentId: null,
|
||||
indent: 0,
|
||||
etype: "info",
|
||||
label: "Job registered in queue",
|
||||
icon: "history",
|
||||
time: 0,
|
||||
color: "purple",
|
||||
},
|
||||
{
|
||||
id: "1",
|
||||
parentId: null,
|
||||
indent: 0,
|
||||
etype: "task",
|
||||
label: "generate-report",
|
||||
icon: "file-code",
|
||||
createTime: 0,
|
||||
startTime: 0,
|
||||
duration: 20,
|
||||
color: "blue",
|
||||
isCollapsible: true,
|
||||
hasStripes: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
parentId: "1",
|
||||
indent: 1,
|
||||
etype: "attempt",
|
||||
label: "Attempt 1",
|
||||
icon: "bot",
|
||||
createTime: 0.1,
|
||||
startTime: 0.1,
|
||||
duration: 19.9,
|
||||
color: "blue",
|
||||
isCollapsible: true,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
parentId: "2",
|
||||
indent: 2,
|
||||
etype: "step",
|
||||
label: "Fetch database records",
|
||||
icon: "check-circle",
|
||||
createTime: 0.2,
|
||||
startTime: 0.5,
|
||||
duration: 3,
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
parentId: "2",
|
||||
indent: 2,
|
||||
etype: "step",
|
||||
label: "Job halted, waiting for resources...",
|
||||
icon: "pause-circle",
|
||||
startTime: 4,
|
||||
duration: 2,
|
||||
color: "orange",
|
||||
isHaltedStep: true,
|
||||
},
|
||||
// ... more log items
|
||||
];
|
||||
|
||||
const getIcon = (item: LogItemType) => {
|
||||
const iconColor = (item: LogItemType) => {
|
||||
if (item.label === "generate-report" || item.label === "Assemble PDF")
|
||||
return "text-blue-500";
|
||||
if (item.icon === "file-code") return "text-muted-foreground";
|
||||
return "";
|
||||
};
|
||||
|
||||
switch (item.icon) {
|
||||
case "history":
|
||||
return <History className="size-4 text-purple-500 shrink-0" />;
|
||||
case "file-code":
|
||||
return <FileCode className={cn("size-4 shrink-0", iconColor(item))} />;
|
||||
case "bot":
|
||||
return <Bot className="size-4 text-muted-foreground shrink-0" />;
|
||||
case "check-circle":
|
||||
return <CheckCircle2 className="size-4 text-green-500 shrink-0" />;
|
||||
case "pause-circle":
|
||||
return <PauseCircle className="size-4 text-orange-500 shrink-0" />;
|
||||
default:
|
||||
return <Info className="size-4 text-muted-foreground shrink-0" />;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper functions
|
||||
const getAllChildrenIds = (parentId: string, allItems: LogItemType[]): string[] => {
|
||||
const children: string[] = [];
|
||||
const directChildren = allItems.filter(item => item.parentId === parentId);
|
||||
|
||||
for (const child of directChildren) {
|
||||
children.push(child.id);
|
||||
children.push(...getAllChildrenIds(child.id, allItems));
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
const isIndirectlyHidden = (itemId: string, hiddenItems: Set<string>, allItems: LogItemType[]): boolean => {
|
||||
const item = allItems.find(i => i.id === itemId);
|
||||
if (!item || !item.parentId) return false;
|
||||
|
||||
if (hiddenItems.has(item.parentId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isIndirectlyHidden(item.parentId, hiddenItems, allItems);
|
||||
};
|
||||
|
||||
// State management
|
||||
const [expandedItems, setExpandedItems] = useState(new Set(["1", "2"]));
|
||||
const [hoveredId, setHoveredId] = useState<string | null>(null);
|
||||
const [hiddenItems, setHiddenItems] = useState<Set<string>>(new Set());
|
||||
const [deletedItems, setDeletedItems] = useState<Set<string>>(new Set());
|
||||
|
||||
// Toggle visibility function
|
||||
const toggleItemVisibility = (itemId: string) => {
|
||||
const wasHidden = hiddenItems.has(itemId);
|
||||
|
||||
setHiddenItems(prev => {
|
||||
const newSet = new Set(prev);
|
||||
if (newSet.has(itemId)) {
|
||||
newSet.delete(itemId);
|
||||
} else {
|
||||
newSet.add(itemId);
|
||||
}
|
||||
return newSet;
|
||||
});
|
||||
|
||||
// If hiding an expanded item, collapse it
|
||||
if (!wasHidden && expandedItems.has(itemId)) {
|
||||
setExpandedItems(prev => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.delete(itemId);
|
||||
return newSet;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Delete item function
|
||||
const deleteItem = (itemId: string) => {
|
||||
const itemsToDelete = [itemId, ...getAllChildrenIds(itemId, logData)];
|
||||
|
||||
setDeletedItems(prev => {
|
||||
const newSet = new Set(prev);
|
||||
itemsToDelete.forEach(id => newSet.add(id));
|
||||
return newSet;
|
||||
});
|
||||
|
||||
setHiddenItems(prev => {
|
||||
const newSet = new Set(prev);
|
||||
itemsToDelete.forEach(id => newSet.delete(id));
|
||||
return newSet;
|
||||
});
|
||||
|
||||
setExpandedItems(prev => {
|
||||
const newSet = new Set(prev);
|
||||
itemsToDelete.forEach(id => newSet.delete(id));
|
||||
return newSet;
|
||||
});
|
||||
};
|
||||
|
||||
// Create actions for each item
|
||||
const createActions = (itemId: string, isDirectlyHidden: boolean, isIndirectlyHiddenItem: boolean, isHovered: boolean) => {
|
||||
const visibilityButton = (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleItemVisibility(itemId);
|
||||
}}
|
||||
className='hover:bg-shadow-secondary rounded p-1'
|
||||
>
|
||||
{isDirectlyHidden ? (
|
||||
<EyeClosed className='text-icon-tertiary size-3' />
|
||||
) : isIndirectlyHiddenItem ? (
|
||||
<div className='flex size-4 items-center justify-center'>
|
||||
<div className='text-icon-tertiary size-[3px] bg-current rounded-full' />
|
||||
</div>
|
||||
) : (
|
||||
<Eye className='text-icon-primary size-3' />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
|
||||
const deleteButton = (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteItem(itemId);
|
||||
}}
|
||||
className='hover:bg-shadow-secondary rounded p-1'
|
||||
>
|
||||
<Trash2 className={cn('size-3',
|
||||
(isDirectlyHidden || isIndirectlyHiddenItem) ? 'text-icon-tertiary' : 'text-icon-primary'
|
||||
)} />
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='flex gap-1'>
|
||||
{isHovered && deleteButton}
|
||||
{visibilityButton}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Process log data with actions and visibility states
|
||||
const processedLogData = useMemo(() => {
|
||||
return logData
|
||||
.filter(item => !deletedItems.has(item.id))
|
||||
.map(item => {
|
||||
const isDirectlyHidden = hiddenItems.has(item.id);
|
||||
const isIndirectlyHiddenItem = isIndirectlyHidden(item.id, hiddenItems, logData);
|
||||
const isItemHidden = isDirectlyHidden || isIndirectlyHiddenItem;
|
||||
const isHovered = hoveredId === item.id;
|
||||
|
||||
return {
|
||||
...item,
|
||||
actions: createActions(item.id, isDirectlyHidden, isIndirectlyHiddenItem, isHovered),
|
||||
disable: isItemHidden,
|
||||
isSelectable: !isItemHidden,
|
||||
};
|
||||
});
|
||||
}, [logData, deletedItems, hiddenItems, hoveredId]);
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<Waterfall
|
||||
className="h-[300px]"
|
||||
logData={processedLogData}
|
||||
getIcon={getIcon}
|
||||
hoveredId={hoveredId}
|
||||
onItemHover={setHoveredId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
197
docs/dial/api-notes.md
Normal file
197
docs/dial/api-notes.md
Normal file
@@ -0,0 +1,197 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Api Notes
|
||||
|
||||
# API Design and Building Blocks
|
||||
|
||||
|
||||
## DialPanel Component
|
||||
|
||||
|
||||
The `DialPanel` component renders dial controls based on schemas. It accepts the following props:
|
||||
|
||||
|
||||
### Props
|
||||
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| `schemas` | `DialSchema[]` | Required | Array of dial schemas to render |
|
||||
| `groups` | `DialGroupConfig[]` | `undefined` | Optional group configurations |
|
||||
| `labelLayout` | `LabelPositionT` | `undefined` | Default label position layout for all inputs ("top", "left", "right", "inline", etc.) |
|
||||
|
||||
|
||||
|
||||
### Label Position Priority
|
||||
|
||||
|
||||
The label position for inputs is determined by the following priority order:
|
||||
|
||||
|
||||
|
||||
1. **Component-specific**: Label position tags on individual properties (highest priority)
|
||||
|
||||
- `@dial-label-top`, `@dial-label-left`, `@dial-label-right`, `@dial-label-inline`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1. **Panel labelLayout**: `labelLayout` prop on DialPanel
|
||||
|
||||
1. **Component default**: Individual input component's default behavior (lowest priority)
|
||||
|
||||
|
||||
|
||||
### Example Usage
|
||||
|
||||
|
||||
```tsx
|
||||
import { DialPanel, DialProvider } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
// With default label layout for all inputs
|
||||
<DialProvider schemas={schemas}>
|
||||
<DialPanel
|
||||
schemas={schemas}
|
||||
labelLayout="top" // All inputs will have top-aligned labels by default
|
||||
/>
|
||||
</DialProvider>
|
||||
|
||||
// Without specifying (components use their own defaults)
|
||||
<DialProvider schemas={schemas}>
|
||||
<DialPanel schemas={schemas} />
|
||||
</DialProvider>
|
||||
|
||||
```
|
||||
|
||||
|
||||
Individual components can still override the panel's default label layout:
|
||||
|
||||
|
||||
```tsx
|
||||
interface Props {
|
||||
/**
|
||||
* @dial-label-left // This overrides the panel's labelLayout
|
||||
*/
|
||||
specialField: number;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Building Blocks
|
||||
|
||||
|
||||
We want to specify the property menu without duplicating the code. Here are the basic building blocks:
|
||||
|
||||
|
||||
| Control Entry | Control Group |
|
||||
| ```jsx
|
||||
const controlEntry = {
|
||||
dtype: 'number',
|
||||
value: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
| ```jsx
|
||||
const controlGroup = {
|
||||
tag: 'group',
|
||||
children: [
|
||||
controlEntry,
|
||||
],
|
||||
layout: 'row',
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
|
||||
|
||||
|
||||
|
||||
Now, let's convert this into a react schema that we can create using react.createElement:
|
||||
|
||||
|
||||
```jsx
|
||||
<Dial.Provider>
|
||||
<Dial.Row>
|
||||
<DialInput label="Position" column type="number" key="prop-name" value={10} min={0} max={100} step={1}/>
|
||||
<DialInput label="Rotation" column type="number" key="prop-name" value={10} min={0} max={100} step={1}/>
|
||||
<DialInput label="Scale" column type="number" key="prop-name" value={10} min={0} max={100} step={1}/>
|
||||
</Dial.Row>
|
||||
</Dial.Provider>
|
||||
|
||||
```
|
||||
|
||||
|
||||
this can be written via react createElement below:
|
||||
|
||||
|
||||
```jsx
|
||||
React.createElement(
|
||||
Dial.Provider,
|
||||
null,
|
||||
React.createElement(
|
||||
Dial.Row,
|
||||
null,
|
||||
React.createElement(DialInput, {
|
||||
label: "Position",
|
||||
column: true,
|
||||
type: "number",
|
||||
key: "prop-name",
|
||||
value: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1
|
||||
}),
|
||||
React.createElement(DialInput, {
|
||||
label: "Rotation",
|
||||
column: true,
|
||||
type: "number",
|
||||
key: "prop-name",
|
||||
value: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1
|
||||
}),
|
||||
React.createElement(DialInput, {
|
||||
label: "Scale",
|
||||
column: true,
|
||||
type: "number",
|
||||
key: "prop-name",
|
||||
value: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
|
||||
We can do this via a nested json object using a convenient helper function:
|
||||
|
||||
|
||||
```jsx
|
||||
function build({tag, children, ...props}) {
|
||||
return React.createElement(tag, props, children)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
We can then rewrite the schema as:
|
||||
|
||||
|
||||
```jsx
|
||||
{ name: 'position', dtype: 'vector3', value: [0, 0, 0], min: 0, max: 100, options: [10, 20, 30, 40, 50],
|
||||
tags: { grouping: 'transform', col: true } }
|
||||
{ name: 'rotation', dtype: 'euler', value: [0, 0, 0], min: 0, max: 100, options: [10, 20, 30, 40, 50],
|
||||
tags: { grouping: 'transform', col: true } }
|
||||
{ name: 'scale', dtype: 'vector3', value: [1, 1, 1], min: 0, max: 100, options: [10, 20, 30, 40, 50],
|
||||
tags: { grouping: 'transform', col: true } }
|
||||
|
||||
```
|
||||
777
docs/dial/cli-details.md
Normal file
777
docs/dial/cli-details.md
Normal file
@@ -0,0 +1,777 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Cli Details
|
||||
|
||||
# Dial CLI Reference
|
||||
|
||||
|
||||
The `dial-cli` tool is a powerful command-line utility for generating UI schemas from TypeScript interfaces with Dial annotations. This page provides a complete reference for all CLI features and options.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
The dial-cli is now available as a standalone package for cleaner installation:
|
||||
|
||||
|
||||
```bash
|
||||
# Install globally (recommended for CLI tools)
|
||||
npm install -g @vuer-ai/dial-cli
|
||||
# or
|
||||
pnpm install -g @vuer-ai/dial-cli
|
||||
|
||||
# Or install as a dev dependency
|
||||
npm install --save-dev @vuer-ai/dial-cli
|
||||
# or
|
||||
pnpm add -D @vuer-ai/dial-cli
|
||||
|
||||
```
|
||||
|
||||
|
||||
Once installed, the CLI is available directly:
|
||||
|
||||
|
||||
```bash
|
||||
# If installed globally
|
||||
dial-cli --help
|
||||
|
||||
# If installed as dev dependency
|
||||
npx dial-cli --help
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Benefits of Standalone Package
|
||||
|
||||
|
||||
|
||||
- **Minimal dependencies** - Only includes what's needed for CLI operation (typescript, react-docgen-typescript)
|
||||
|
||||
- **No peer dependency warnings** - Doesn't require React, Tailwind, or other UI dependencies
|
||||
|
||||
- **Smaller install size** - ~32KB unpacked vs entire UI kit
|
||||
|
||||
- **Independent versioning** - CLI updates don't require UI kit updates
|
||||
|
||||
|
||||
|
||||
## Command Line Options
|
||||
|
||||
|
||||
### Basic Usage
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli [options] <files...>
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Options Reference
|
||||
|
||||
|
||||
| Option | Alias | Description | Default |
|
||||
| `--output <dir>` | `-o` | Output directory for generated files | `./metadata` |
|
||||
| `--verbose` | | Enable verbose output with detailed information | `false` |
|
||||
| `--quiet` | | Suppress all output except errors | `false` |
|
||||
| `--remove` | | Remove generated metadata files | `false` |
|
||||
| `--ignore <props>` | `-i` | Comma-separated list of properties to ignore | - |
|
||||
| `--help` | `-h` | Display help information | - |
|
||||
| `--version` | `-v` | Display version information | - |
|
||||
|
||||
|
||||
|
||||
### Verbose Mode
|
||||
|
||||
|
||||
The `--verbose` flag enables detailed output and generates additional files:
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli --verbose MyComponent.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
In verbose mode, dial-cli generates:
|
||||
|
||||
|
||||
|
||||
- `schema.dial` - Combined dial schema for all components (main output)
|
||||
|
||||
- `debug/` - Debug directory containing:
|
||||
|
||||
- `component-raw.json` - Raw docgen output
|
||||
|
||||
- `component-combined.json` - Enhanced metadata
|
||||
|
||||
- `component-schemas.json` - Component schemas
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
**Note:** Debug files are organized in a `debug/` subdirectory to keep the main output clean. These files are only generated in verbose mode and are useful for debugging schema generation issues.
|
||||
|
||||
|
||||
### Quiet Mode
|
||||
|
||||
|
||||
The `--quiet` flag suppresses all output except errors, useful for CI/CD:
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli --quiet src/components/*.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Remove Mode
|
||||
|
||||
|
||||
The `--remove` flag cleans up generated metadata files:
|
||||
|
||||
|
||||
```bash
|
||||
# Remove metadata for specific component
|
||||
dial-cli --remove MyComponent.tsx
|
||||
|
||||
# Remove all metadata in output directory
|
||||
dial-cli --remove --output ./metadata
|
||||
|
||||
```
|
||||
|
||||
|
||||
**Important:** The remove command cleans up both the main `schema.dial` file and any debug files in the `debug/` directory. It supports both the current debug directory structure and legacy file locations for backward compatibility.
|
||||
|
||||
|
||||
### Ignore Properties
|
||||
|
||||
|
||||
Exclude specific properties from schema generation:
|
||||
|
||||
|
||||
```bash
|
||||
# Ignore single property
|
||||
dial-cli --ignore ref MyComponent.tsx
|
||||
|
||||
# Ignore multiple properties
|
||||
dial-cli --ignore "ref,key,children" MyComponent.tsx
|
||||
|
||||
# Using short alias
|
||||
dial-cli -i "internalProp,debugValue" Component.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Output Files
|
||||
|
||||
|
||||
### Standard Output (Default)
|
||||
|
||||
|
||||
Without verbose mode, only generates:
|
||||
|
||||
|
||||
|
||||
- `schema.dial` - Combined schema for all processed components
|
||||
|
||||
|
||||
|
||||
### Verbose Output
|
||||
|
||||
|
||||
With `--verbose` flag, generates additional files per component:
|
||||
|
||||
|
||||
|
||||
- `[component]-schemas.json` - Component-specific schema
|
||||
|
||||
- `[component]-raw.json` - Raw react-docgen output
|
||||
|
||||
- `[component]-combined.json` - Enhanced metadata with dial annotations
|
||||
|
||||
- `schema.dial` - Combined schema (always generated)
|
||||
|
||||
|
||||
|
||||
## Group-Level Configuration
|
||||
|
||||
|
||||
You can apply configuration to entire groups of properties using interface-level JSDoc comments:
|
||||
|
||||
|
||||
### Using @dial-no-wrap
|
||||
|
||||
|
||||
The `@dial-no-wrap` annotation prevents line wrapping for all properties in a group:
|
||||
|
||||
|
||||
```tsx
|
||||
interface ComponentProps {
|
||||
/**
|
||||
* Layout configuration for transform properties
|
||||
* @dial transform @dial-no-wrap
|
||||
*/
|
||||
|
||||
/** @dial transform @dial-dtype vector3 */
|
||||
position: number[];
|
||||
|
||||
/** @dial transform @dial-dtype euler */
|
||||
rotation: number[];
|
||||
|
||||
/** @dial transform @dial-dtype vector3 */
|
||||
scale: number[];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
In this example, all properties in the "transform" group (position, rotation, scale) will be displayed on a single line without wrapping.
|
||||
|
||||
|
||||
### Groups in Output Schema
|
||||
|
||||
|
||||
The CLI now generates a `groups` section in the output schema:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"component": "ExampleBox",
|
||||
"schema": [...],
|
||||
"groups": [
|
||||
{
|
||||
"name": "transform",
|
||||
"noWrap": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
This allows the UI to apply group-specific styling and layout configuration.
|
||||
|
||||
|
||||
## Excluding Properties
|
||||
|
||||
|
||||
There are two ways to exclude properties from dial schema generation:
|
||||
|
||||
|
||||
### 1. Using @dial-ignore Annotation
|
||||
|
||||
|
||||
Add `@dial-ignore` to any property's JSDoc comment to exclude it from the generated schema:
|
||||
|
||||
|
||||
```tsx
|
||||
interface ComponentProps {
|
||||
/**
|
||||
* Public property - included in schema
|
||||
* @dial transform
|
||||
* @dial-dtype vector3
|
||||
*/
|
||||
position: number[];
|
||||
|
||||
/**
|
||||
* Internal state - excluded from schema
|
||||
* @dial-ignore
|
||||
*/
|
||||
_internalCache?: any;
|
||||
|
||||
/**
|
||||
* React ref - excluded from schema
|
||||
* @dial-ignore
|
||||
*/
|
||||
ref?: React.Ref<HTMLDivElement>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 2. Using CLI --ignore Option
|
||||
|
||||
|
||||
The `-i` or `--ignore` option allows you to exclude properties by name or pattern at runtime:
|
||||
|
||||
|
||||
```bash
|
||||
# Exclude specific properties
|
||||
dial-cli -i className -i style Component.tsx
|
||||
|
||||
# Exclude using comma-separated list
|
||||
dial-cli --ignore ref,key,id Component.tsx
|
||||
|
||||
# Exclude using glob patterns
|
||||
dial-cli -i "*Style" -i "on*" -i "_*" Component.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Glob Pattern Examples
|
||||
|
||||
|
||||
| Pattern | Matches | Example Properties |
|
||||
| `*Style` | Ends with "Style" | `containerStyle`, `buttonStyle`, `textStyle` |
|
||||
| `on*` | Starts with "on" | `onClick`, `onChange`, `onSubmit` |
|
||||
| `_*` | Starts with underscore | `_internal`, `_cache`, `_private` |
|
||||
| `*Ref` | Ends with "Ref" | `inputRef`, `containerRef`, `buttonRef` |
|
||||
| `data*` | Starts with "data" | `dataSource`, `dataProvider`, `dataKey` |
|
||||
|
||||
|
||||
|
||||
## Class/Interface Level Suppression
|
||||
|
||||
|
||||
The `@dial-ignore` annotation can be used at the class or interface level to completely suppress dial schema generation for an entire component and all its properties:
|
||||
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* Internal configuration component
|
||||
* @dial-ignore
|
||||
*/
|
||||
interface InternalSettingsProps {
|
||||
apiKey: string;
|
||||
debugMode: boolean;
|
||||
serverUrl: string;
|
||||
// All properties will be excluded from dial schema
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin-only component
|
||||
* @dial-ignore
|
||||
*/
|
||||
export const AdminPanel: FC<AdminPanelProps> = ({ ... }) => {
|
||||
// This component won't appear in dial UI
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
This is useful for:
|
||||
|
||||
|
||||
|
||||
- Internal/utility components that shouldn't be exposed in the UI
|
||||
|
||||
- Admin-only or developer-only components
|
||||
|
||||
- Components that are still under development
|
||||
|
||||
- Helper components that are only used internally
|
||||
|
||||
|
||||
|
||||
When `@dial-ignore` is used at the class/interface level:
|
||||
|
||||
|
||||
|
||||
- The entire component is skipped during dial schema generation
|
||||
|
||||
- No properties from that component will appear in the dial UI
|
||||
|
||||
- Any child properties or nested interfaces are also excluded
|
||||
|
||||
|
||||
|
||||
## Custom Property Labels
|
||||
|
||||
|
||||
The `@dial-label` annotation allows you to specify custom labels for properties that will be displayed in the UI instead of the default auto-generated labels from the property name:
|
||||
|
||||
|
||||
```tsx
|
||||
interface ComponentProps {
|
||||
/**
|
||||
* Position in 3D space
|
||||
* @dial transform
|
||||
* @dial-dtype vector3
|
||||
* @dial-label 3D Position
|
||||
*/
|
||||
pos3d: [number, number, number];
|
||||
|
||||
/**
|
||||
* Background color
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
* @dial-label Background Color
|
||||
*/
|
||||
bgColor: string;
|
||||
|
||||
/**
|
||||
* Enable shadows
|
||||
* @dial-dtype boolean
|
||||
* @dial-label Enable Shadow Rendering
|
||||
*/
|
||||
shadowsOn: boolean;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
In the generated UI:
|
||||
|
||||
|
||||
|
||||
- `pos3d` will display as "3D Position" instead of "Pos3d"
|
||||
|
||||
- `bgColor` will display as "Background Color" instead of "BgColor"
|
||||
|
||||
- `shadowsOn` will display as "Enable Shadow Rendering" instead of "ShadowsOn"
|
||||
|
||||
|
||||
|
||||
This is particularly useful when property names follow coding conventions (camelCase, abbreviations) but you want more user-friendly labels in the UI.
|
||||
|
||||
|
||||
## Complete Example
|
||||
|
||||
|
||||
Here's a complete example showing exclusion methods and custom labels:
|
||||
|
||||
|
||||
### Component Definition
|
||||
|
||||
|
||||
```tsx
|
||||
// Box3D.tsx
|
||||
interface Box3DProps {
|
||||
/**
|
||||
* Box dimensions
|
||||
* @dial geometry
|
||||
* @dial-dtype vector3
|
||||
* @dial-min 0.1
|
||||
* @dial-max 10
|
||||
* @dial-step 0.1
|
||||
*/
|
||||
size: [number, number, number];
|
||||
|
||||
/**
|
||||
* Position in 3D space
|
||||
* @dial transform
|
||||
* @dial-dtype vector3
|
||||
* @dial-min -100
|
||||
* @dial-max 100
|
||||
* @dial-step 0.5
|
||||
*/
|
||||
position: [number, number, number];
|
||||
|
||||
/**
|
||||
* Material color
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
*/
|
||||
color: string;
|
||||
|
||||
/**
|
||||
* Opacity level
|
||||
* @dial appearance
|
||||
* @dial-min 0
|
||||
* @dial-max 1
|
||||
* @dial-step 0.01
|
||||
*/
|
||||
opacity: number;
|
||||
|
||||
// Properties to exclude:
|
||||
|
||||
/**
|
||||
* Internal mesh reference
|
||||
* @dial-ignore
|
||||
*/
|
||||
_meshRef?: THREE.Mesh;
|
||||
|
||||
/**
|
||||
* React className - will be excluded via CLI
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* React style - will be excluded via CLI
|
||||
*/
|
||||
style?: React.CSSProperties;
|
||||
|
||||
/**
|
||||
* Click handler - will be excluded via CLI pattern
|
||||
*/
|
||||
onClick?: () => void;
|
||||
|
||||
/**
|
||||
* Change handler - will be excluded via CLI pattern
|
||||
*/
|
||||
onChange?: (value: any) => void;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### CLI Commands
|
||||
|
||||
|
||||
```bash
|
||||
# Generate schema excluding React-specific props and handlers
|
||||
dial-cli -i className -i style -i "on*" Box3D.tsx
|
||||
|
||||
# Or using comma-separated list
|
||||
dial-cli --ignore className,style,onClick,onChange Box3D.tsx
|
||||
|
||||
# Exclude all private properties and event handlers
|
||||
dial-cli -i "_*" -i "on*" Box3D.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Generated Schema
|
||||
|
||||
|
||||
The generated schema will only include:
|
||||
|
||||
|
||||
|
||||
- `size` - Box dimensions control
|
||||
|
||||
- `position` - Position control
|
||||
|
||||
- `color` - Color picker
|
||||
|
||||
- `opacity` - Opacity slider
|
||||
|
||||
|
||||
|
||||
Excluded properties:
|
||||
|
||||
|
||||
|
||||
- `_meshRef` - Excluded by `@dial-ignore` annotation
|
||||
|
||||
- `className`, `style` - Excluded by CLI `-i` option
|
||||
|
||||
- `onClick`, `onChange` - Excluded by CLI pattern `"on*"`
|
||||
|
||||
|
||||
|
||||
## CLI Options Reference
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli [options] <files...>
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
| Option | Short | Description | Example |
|
||||
| `--output <dir>` | `-o` | Output directory for generated files | `-o ./schemas` |
|
||||
| `--ignore <prop>` | `-i` | Properties to exclude (supports glob) | `-i className -i "on*"` |
|
||||
| `--verbose` | | Enable verbose output | `--verbose` |
|
||||
| `--quiet` | | Suppress output except errors | `--quiet` |
|
||||
| `--help` | `-h` | Display help message | `--help` |
|
||||
| `--version` | `-v` | Display version | `--version` |
|
||||
|
||||
|
||||
|
||||
## Output Files
|
||||
|
||||
|
||||
The CLI generates files with a clean directory structure:
|
||||
|
||||
|
||||
**Main Output:**
|
||||
|
||||
|
||||
|
||||
- **`schema.dial`** - Combined schemas for all components, ready for UI generation
|
||||
|
||||
|
||||
|
||||
**Debug Output (verbose mode only):**
|
||||
|
||||
|
||||
|
||||
- **`debug/component-raw.json`** - Raw AST and JSDoc extraction
|
||||
|
||||
- **`debug/component-combined.json`** - Enhanced metadata with dial schemas
|
||||
|
||||
- **`debug/component-schemas.json`** - Individual component schemas
|
||||
|
||||
|
||||
|
||||
This structure keeps your main output directory clean while providing detailed debug information when needed.
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
|
||||
### 1. Combine Both Exclusion Methods
|
||||
|
||||
|
||||
Use `@dial-ignore` for properties that should never be exposed in the UI:
|
||||
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* @dial-ignore
|
||||
*/
|
||||
_internalState?: any;
|
||||
|
||||
```
|
||||
|
||||
|
||||
Use CLI `--ignore` for context-specific exclusions:
|
||||
|
||||
|
||||
```bash
|
||||
# Exclude React-specific props when generating for non-React environments
|
||||
dial-cli -i className -i style Component.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 2. Use Patterns for Consistency
|
||||
|
||||
|
||||
Create consistent naming conventions and use patterns:
|
||||
|
||||
|
||||
```bash
|
||||
# Exclude all private properties, refs, and handlers
|
||||
dial-cli -i "_*" -i "*Ref" -i "on*" Component.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 3. Create Build Scripts
|
||||
|
||||
|
||||
Add scripts to your `package.json`:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dial:generate": "dial-cli -o ./schemas -i className,style,key,ref src/components/*.tsx",
|
||||
"dial:generate:clean": "dial-cli -o ./schemas -i '_*,on*,*Ref,className,style' src/components/*.tsx"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 4. Document Excluded Properties
|
||||
|
||||
|
||||
When using `@dial-ignore`, add a comment explaining why:
|
||||
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* Internal cache for performance optimization
|
||||
* Not meant to be modified by users
|
||||
* @dial-ignore
|
||||
*/
|
||||
_cache?: Map<string, any>;
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Integration Example
|
||||
|
||||
|
||||
Here's how to use the generated schemas in your application:
|
||||
|
||||
|
||||
```tsx
|
||||
import { DialProvider, DialPanel } from '@vuer-ai/vuer-uikit';
|
||||
import allSchemas from './schemas/schema.dial';
|
||||
|
||||
function App() {
|
||||
const [props, setProps] = useState({
|
||||
size: [1, 1, 1],
|
||||
position: [0, 0, 0],
|
||||
color: '#ff0000',
|
||||
opacity: 1
|
||||
});
|
||||
|
||||
const handleValueChange = (name: string, value: any) => {
|
||||
setProps(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
// Get the specific component schema from the combined schema file
|
||||
const box3DSchema = allSchemas.find(s => s.component === 'Box3D');
|
||||
|
||||
return (
|
||||
<DialProvider schemas={[box3DSchema]} onValueChange={handleValueChange}>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Canvas>
|
||||
<Box3D {...props} />
|
||||
</Canvas>
|
||||
<DialPanel schemas={[box3DSchema]} />
|
||||
</div>
|
||||
</DialProvider>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
### Properties Not Being Excluded
|
||||
|
||||
|
||||
|
||||
1. **Check annotation syntax**: Ensure `@dial-ignore` is on its own line
|
||||
|
||||
1. **Check pattern syntax**: Use quotes for patterns with wildcards: `-i "*Style"`
|
||||
|
||||
1. **Check property names**: Property names are case-sensitive
|
||||
|
||||
|
||||
|
||||
### Generated Schema Is Empty
|
||||
|
||||
|
||||
|
||||
1. Ensure your interface has JSDoc comments with `@dial` annotations
|
||||
|
||||
1. Check that the TypeScript file exports the interface
|
||||
|
||||
1. Verify the file path is correct
|
||||
|
||||
|
||||
|
||||
### Build Errors
|
||||
|
||||
|
||||
|
||||
1. Ensure `@vuer-ai/dial-cli` is installed
|
||||
|
||||
1. Try using the full path: `node_modules/.bin/dial-cli` (if installed locally)
|
||||
|
||||
1. Check Node.js version (requires Node 14+)
|
||||
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
|
||||
The dial-cli tool provides flexible property exclusion through:
|
||||
|
||||
|
||||
|
||||
- **`@dial-ignore` annotation** - Permanent, code-level exclusion
|
||||
|
||||
- **`--ignore` CLI option** - Runtime, context-specific exclusion
|
||||
|
||||
- **Glob patterns** - Flexible pattern-based exclusion
|
||||
|
||||
|
||||
|
||||
Combine these features to create clean, focused UI schemas that expose only the properties users need to control.
|
||||
187
docs/dial/controlled-dials.md
Normal file
187
docs/dial/controlled-dials.md
Normal file
@@ -0,0 +1,187 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Controlled Dials
|
||||
|
||||
# Controlled Dials
|
||||
|
||||
|
||||
The `DialProvider` component supports both controlled and uncontrolled modes, giving you flexibility in how you manage dial state.
|
||||
|
||||
|
||||
## Simple 3D Object Example
|
||||
|
||||
|
||||
transformPositionxyzRenderOrderResetExamplePosition: [0.0, 5.0, 0.0]Render Order: 0```jsx
|
||||
const schemas = [
|
||||
{
|
||||
name: "position",
|
||||
dtype: "vector3",
|
||||
value: [1, 2, 3],
|
||||
//...
|
||||
}
|
||||
];
|
||||
|
||||
const [values, setValues] = useState({
|
||||
position: [0, 5, 0],
|
||||
renderOrder: 0
|
||||
});
|
||||
|
||||
|
||||
const handleChange = (name, value) => {
|
||||
setValues(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
return (
|
||||
<DialProvider
|
||||
schemas={schemas}
|
||||
values={values}
|
||||
onValueChange={handleChange}
|
||||
>
|
||||
<DialPanel schemas={schemas} />
|
||||
</DialProvider>
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Full Schema Example from JSON
|
||||
|
||||
|
||||
FooBar Object PropertiestransformPositionxyzRotationxyzScalexyzdisplayVisibleOpacityReset All```
|
||||
{
|
||||
"position": [
|
||||
0,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"rotation": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"scale": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"visible": true,
|
||||
"opacity": 1
|
||||
}
|
||||
```
|
||||
|
||||
```jsx
|
||||
// Schema data structure (could be loaded from JSON)
|
||||
const schemaData = {
|
||||
"FooBar": {
|
||||
"schemas": [
|
||||
{
|
||||
"name": "position",
|
||||
"dtype": "vector3",
|
||||
"value": [0, 5, 0],
|
||||
"min": -10,
|
||||
"max": 10,
|
||||
"step": 0.1,
|
||||
"tags": {
|
||||
"grouping": "transform",
|
||||
"noWrap": true
|
||||
}
|
||||
},
|
||||
// ... more schemas
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize values from schemas
|
||||
const [values, setValues] = useState(() => {
|
||||
const initial = {};
|
||||
schemaData.FooBar.schemas.forEach(schema => {
|
||||
initial[schema.name] = schema.value;
|
||||
});
|
||||
return initial;
|
||||
});
|
||||
|
||||
const handleChange = (name, value) => {
|
||||
setValues(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
return (
|
||||
<DialProvider
|
||||
schemas={schemaData.FooBar.schemas}
|
||||
values={values}
|
||||
onValueChange={handleChange}
|
||||
>
|
||||
<DialPanel schemas={schemaData.FooBar.schemas} />
|
||||
</DialProvider>
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
|
||||
### DialProvider Props
|
||||
|
||||
|
||||
| Prop | Type | Description |
|
||||
| `schemas` | `DialSchema[]` | Array of dial schemas defining the dials |
|
||||
| `values` | `Record<string, DialValue>` | Current values for controlled mode |
|
||||
| `initialValues` | `Record<string, DialValue>` | Initial values for uncontrolled mode |
|
||||
| `onValueChange` | `(name: string, value: DialValue) => void` | Callback when values change |
|
||||
| `children` | `ReactNode` | Child components |
|
||||
|
||||
|
||||
|
||||
### Schema Structure
|
||||
|
||||
|
||||
```typescript
|
||||
interface DialSchema {
|
||||
name: string; // Unique identifier
|
||||
dtype: string; // "number", "boolean", "vector3", "select", etc.
|
||||
value?: any; // Default value
|
||||
min?: number; // For number/vector inputs
|
||||
max?: number; // For number/vector inputs
|
||||
step?: number; // Step size for number/vector inputs
|
||||
options?: string[]; // For select inputs
|
||||
tags?: {
|
||||
grouping?: string; // Group related controls
|
||||
noWrap?: boolean; // Prevent wrapping in group
|
||||
// ... other tags
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Common Data Types
|
||||
|
||||
|
||||
|
||||
- **`number`**: Single numeric value
|
||||
|
||||
- **`boolean`**: True/false toggle
|
||||
|
||||
- **`vector3`**: 3D vector [x, y, z]
|
||||
|
||||
- **`select`**: Dropdown with options
|
||||
|
||||
- **`string`**: Text input
|
||||
|
||||
|
||||
|
||||
### Grouping with Tags
|
||||
|
||||
|
||||
The `tags.grouping` property allows you to organize related controls together. Controls with the same `grouping` value will be visually grouped in the UI.
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"tags": {
|
||||
"grouping": "transform",
|
||||
"noWrap": true
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
129
docs/dial/getting-started.md
Normal file
129
docs/dial/getting-started.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Getting Started with Dial
|
||||
|
||||
## Overview
|
||||
|
||||
Dial is a schema-driven system that "parses JSDoc annotations in your TypeScript/React components" and then "generates UI schemas that describe controls and their properties."
|
||||
|
||||
The system automates interactive control creation from TypeScript interfaces, supporting complex types like vectors, tuples, and nested objects.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the CLI tool using your package manager:
|
||||
|
||||
```bash
|
||||
# Global installation
|
||||
pnpm install -g @vuer-ai/dial-cli
|
||||
|
||||
# Or as a dev dependency
|
||||
pnpm add -D @vuer-ai/dial-cli
|
||||
```
|
||||
|
||||
## Basic Workflow
|
||||
|
||||
### Step 1: Annotate Your Component
|
||||
|
||||
Add JSDoc comments with `@dial` tags to your TypeScript component properties:
|
||||
|
||||
```typescript
|
||||
interface BoxProps {
|
||||
/**
|
||||
* Box dimensions
|
||||
* @dial geometry
|
||||
* @dial-dtype vector3
|
||||
* @dial-min 0.1
|
||||
* @dial-max 10
|
||||
* @dial-step 0.1
|
||||
*/
|
||||
size: [number, number, number];
|
||||
|
||||
/**
|
||||
* Material color
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
*/
|
||||
color: string;
|
||||
|
||||
/**
|
||||
* Visibility toggle
|
||||
* @dial visibility
|
||||
* @dial-dtype boolean
|
||||
*/
|
||||
visible: boolean;
|
||||
|
||||
/**
|
||||
* Opacity level
|
||||
* @dial appearance
|
||||
* @dial-dtype number
|
||||
* @dial-min 0
|
||||
* @dial-max 1
|
||||
* @dial-step 0.01
|
||||
*/
|
||||
opacity: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Generate the Schema
|
||||
|
||||
```bash
|
||||
dial-cli Box.tsx
|
||||
# Outputs: metadata/schema.dial
|
||||
```
|
||||
|
||||
### Step 3: Use the Generated Schema
|
||||
|
||||
```typescript
|
||||
import { DialProvider, DialPanel } from '@vuer-ai/vuer-uikit';
|
||||
import allSchemas from './metadata/schema.dial';
|
||||
|
||||
function App() {
|
||||
const boxSchema = allSchemas.find(s => s.component === 'Box');
|
||||
|
||||
return (
|
||||
<DialProvider schemas={[boxSchema]}>
|
||||
<DialPanel schemas={[boxSchema]} />
|
||||
</DialProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Core Annotation Tags
|
||||
|
||||
| Tag | Purpose |
|
||||
|-----|---------|
|
||||
| `@dial <group>` | Groups related properties together |
|
||||
| `@dial-dtype <type>` | Specifies control data type |
|
||||
| `@dial-min/max/step` | Sets numeric constraints |
|
||||
| `@dial-icon <name>` | Adds Lucide icon to control |
|
||||
| `@dial-ignore` | Excludes property from schema |
|
||||
|
||||
## Supported Data Types
|
||||
|
||||
| Type | Purpose | Example |
|
||||
|------|---------|---------|
|
||||
| `number` | Basic numeric input | `42` |
|
||||
| `boolean` | Toggle switch | `true/false` |
|
||||
| `string` | Text input | `"hello"` |
|
||||
| `color` | Color picker | `"#ff0000"` |
|
||||
| `vector3` | 3D vector | `[1, 2, 3]` |
|
||||
| `euler` | Rotation angles | `[0, 90, 180]` |
|
||||
| `select` | Dropdown menu | `"option1"` |
|
||||
|
||||
## Property Grouping
|
||||
|
||||
Organize properties by adding the same group name across multiple fields:
|
||||
|
||||
```typescript
|
||||
interface Props {
|
||||
/** @dial transform */
|
||||
position: [number, number, number];
|
||||
|
||||
/** @dial transform */
|
||||
rotation: [number, number, number];
|
||||
|
||||
/** @dial appearance */
|
||||
color: string;
|
||||
|
||||
/** @dial appearance */
|
||||
metalness: number;
|
||||
}
|
||||
```
|
||||
1113
docs/dial/input-types.md
Normal file
1113
docs/dial/input-types.md
Normal file
File diff suppressed because it is too large
Load Diff
60
docs/dial/overview.md
Normal file
60
docs/dial/overview.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Dial: A Schema-Driven Menu System
|
||||
|
||||
## Overview
|
||||
|
||||
Dial represents a system that generates user interface controls automatically from TypeScript interfaces using JSDoc annotations. This approach eliminates manual UI creation by defining control properties directly in code comments.
|
||||
|
||||
## Core Annotation Syntax
|
||||
|
||||
The system uses JSDoc comments to specify UI behavior:
|
||||
|
||||
**Grouping Controls:**
|
||||
- `@dial <grouping>` organizes related properties
|
||||
- `@dial <grouping> @dial-no-wrap` applies group-level settings
|
||||
|
||||
**Property Configuration:**
|
||||
- `@dial-<property> <value>` sets control attributes using hyphen notation
|
||||
- `@dial-col-<n>` arranges elements in n-column layouts
|
||||
- `@dial-dtype <type>` specifies data types (vector3, euler, boolean, int, etc.)
|
||||
- `@dial-min <number>` and `@dial-max <number>` establish value bounds
|
||||
- `@dial-step <number>` defines increment sizes
|
||||
- `@dial-options [...]` provides preset values
|
||||
- `@dial-icon <name>` assigns Lucide icon names
|
||||
- `@dial-label <text>` customizes property display names
|
||||
- `@dial-ignore` excludes properties from schema generation
|
||||
|
||||
## Example Implementation
|
||||
|
||||
A TypeScript interface can be annotated to define a 3D box geometry with transformation controls:
|
||||
|
||||
```typescript
|
||||
interface ExampleBoxProps {
|
||||
args: ExampleBoxArgs;
|
||||
position: number[] | null;
|
||||
rotation: number[] | null;
|
||||
scale: number[] | null;
|
||||
hide: boolean;
|
||||
alphaTest: boolean;
|
||||
depthTest: boolean;
|
||||
renderOrder: number;
|
||||
_internalState?: any;
|
||||
}
|
||||
```
|
||||
|
||||
Annotations specify constraints, groupings, and visual representation for each property.
|
||||
|
||||
## Key Features
|
||||
|
||||
**Schema-Driven Architecture:** UI controls generate automatically from annotated TypeScript code, eliminating manual interface creation.
|
||||
|
||||
**Grouped Layout System:** Properties organize automatically into sections based on their grouping annotations.
|
||||
|
||||
**Integrated State Management:** Built-in state tracking with value change callbacks enables seamless application integration.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Tutorial:** Step-by-step guide for using dial-cli
|
||||
- **Input Types:** Complete reference of supported input types
|
||||
- **Controlled Dials:** Advanced usage patterns
|
||||
- **API Notes:** Detailed API reference
|
||||
- **CLI Details:** Advanced command-line options
|
||||
443
docs/dial/testing.md
Normal file
443
docs/dial/testing.md
Normal file
@@ -0,0 +1,443 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Testing
|
||||
|
||||
# Testing Dial Annotations
|
||||
|
||||
|
||||
|
||||
Testing Guidedial-cli[v0.0.22](https://www.npmjs.com/package/@vuer-ai/dial-cli/v/0.0.22)
|
||||
This guide covers testing strategies for Dial annotations, running the dial-cli test suite, and contributing to dial-cli development.
|
||||
|
||||
|
||||
## Testing Your Dial Annotations
|
||||
|
||||
|
||||
### 1. Validate Generated Schemas
|
||||
|
||||
|
||||
After annotating your components, validate the generated schemas:
|
||||
|
||||
|
||||
```bash
|
||||
# Generate with verbose output for inspection
|
||||
dial-cli --verbose MyComponent.tsx
|
||||
|
||||
# Check the generated files
|
||||
cat metadata/schema.dial | jq '.'
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 2. Common Validation Checks
|
||||
|
||||
|
||||
#### Check Property Types
|
||||
|
||||
|
||||
Ensure properties have the correct dtype:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "position",
|
||||
"dtype": "vector3", // Should match your annotation
|
||||
"value": [0, 0, 0]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Verify Constraints
|
||||
|
||||
|
||||
Check min/max/step values are applied:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "opacity",
|
||||
"dtype": "number",
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 0.01
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Validate Grouping
|
||||
|
||||
|
||||
Ensure properties are correctly grouped:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "rotation",
|
||||
"dtype": "euler",
|
||||
"tags": {
|
||||
"grouping": "transform"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 3. Test Type Inheritance
|
||||
|
||||
|
||||
When using interface inheritance or type intersections:
|
||||
|
||||
|
||||
```bash
|
||||
# Generate schema for inherited types
|
||||
dial-cli --verbose ExtendedComponent.tsx
|
||||
|
||||
# Verify all parent properties are included
|
||||
jq '.[] | select(.component == "ExtendedComponent") | .schemas[].name' \
|
||||
metadata/schema.dial
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 4. Automated Testing
|
||||
|
||||
|
||||
Create a test script to validate your schemas:
|
||||
|
||||
|
||||
```javascript
|
||||
// test-dial-schemas.js
|
||||
const fs = require('fs');
|
||||
const schema = require('./metadata/schema.dial');
|
||||
|
||||
describe('Dial Schemas', () => {
|
||||
test('should have required properties', () => {
|
||||
const component = schema.find(c => c.component === 'MyComponent');
|
||||
expect(component).toBeDefined();
|
||||
|
||||
const propNames = component.schemas.map(s => s.name);
|
||||
expect(propNames).toContain('position');
|
||||
expect(propNames).toContain('rotation');
|
||||
expect(propNames).toContain('scale');
|
||||
});
|
||||
|
||||
test('should have correct types', () => {
|
||||
const component = schema.find(c => c.component === 'MyComponent');
|
||||
const position = component.schemas.find(s => s.name === 'position');
|
||||
|
||||
expect(position.dtype).toBe('vector3');
|
||||
expect(position.value).toHaveLength(3);
|
||||
});
|
||||
|
||||
test('should inherit group configurations', () => {
|
||||
const component = schema.find(c => c.component === 'AnimatedBox');
|
||||
const duration = component.schemas.find(s => s.name === 'duration');
|
||||
|
||||
expect(duration.tags?.noWrap).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Running Dial CLI Tests
|
||||
|
||||
|
||||
The dial-cli package includes a comprehensive test suite for validation.
|
||||
|
||||
|
||||
### Prerequisites
|
||||
|
||||
|
||||
```bash
|
||||
# Navigate to dial-cli directory
|
||||
cd packages/vuer-uikit/dial-cli
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Build the CLI
|
||||
pnpm build
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pnpm test
|
||||
|
||||
# Run tests in watch mode for development
|
||||
pnpm test:watch
|
||||
|
||||
# Run tests with coverage
|
||||
pnpm test:coverage
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Test Output
|
||||
|
||||
|
||||
Successful test run shows:
|
||||
|
||||
|
||||
```
|
||||
PASS spec/inheritance.test.ts
|
||||
dial-cli inheritance tests
|
||||
Interface Inheritance
|
||||
✓ should resolve properties from extended interfaces
|
||||
✓ should handle deep inheritance chains
|
||||
Type Inheritance
|
||||
✓ should resolve properties from type intersections
|
||||
✓ should handle utility types (Pick, Omit, Partial)
|
||||
Mixed Inheritance
|
||||
✓ should handle interface extending type
|
||||
✓ should handle type intersecting interface
|
||||
Group configurations
|
||||
✓ should inherit group-level @dial-no-wrap
|
||||
dial-cli remove functionality
|
||||
✓ should remove specific component metadata
|
||||
✓ should remove all metadata files
|
||||
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 9 passed, 9 total
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Contributing to Dial CLI
|
||||
|
||||
|
||||
### Development Setup
|
||||
|
||||
|
||||
|
||||
1. **Fork and Clone**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/vuer-uikit.git
|
||||
cd vuer-uikit/packages/vuer-uikit/dial-cli
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Install Dependencies**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Start Development Mode**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
# This watches for changes and rebuilds automatically
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Writing New Tests
|
||||
|
||||
|
||||
Tests are located in the `spec/` directory:
|
||||
|
||||
|
||||
```
|
||||
spec/
|
||||
├── inheritance.test.ts # Main test suite
|
||||
├── fixtures/ # Test TypeScript files
|
||||
│ ├── InterfaceInheritance.tsx
|
||||
│ ├── TypeInheritance.tsx
|
||||
│ └── MixedInheritance.tsx
|
||||
└── outputs/ # Expected outputs for comparison
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Adding a Test Case
|
||||
|
||||
|
||||
```typescript
|
||||
// spec/inheritance.test.ts
|
||||
test('should handle new feature', () => {
|
||||
const fixture = join(FIXTURES_DIR, 'NewFeature.tsx');
|
||||
|
||||
// Generate schema
|
||||
execSync(`node "${DIAL_CLI}" --verbose --output "${OUTPUT_DIR}" "${fixture}"`);
|
||||
|
||||
// Read and validate
|
||||
const schemaPath = join(OUTPUT_DIR, 'schema.dial');
|
||||
const schemas = JSON.parse(readFileSync(schemaPath, 'utf-8'));
|
||||
|
||||
// Assertions
|
||||
expect(schemas).toBeDefined();
|
||||
expect(schemas[0].component).toBe('NewFeature');
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Creating Test Fixtures
|
||||
|
||||
|
||||
```tsx
|
||||
// spec/fixtures/NewFeature.tsx
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Test component for new feature
|
||||
* @dial config @dial-new-feature
|
||||
*/
|
||||
interface NewFeatureProps {
|
||||
/**
|
||||
* Test property
|
||||
* @dial config
|
||||
* @dial-dtype string
|
||||
* @dial-new-annotation value
|
||||
*/
|
||||
testProp: string;
|
||||
}
|
||||
|
||||
export const NewFeature: React.FC<NewFeatureProps> = ({ testProp }) => {
|
||||
return <div>{testProp}</div>;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Running Tests During Development
|
||||
|
||||
|
||||
```bash
|
||||
# Run specific test file
|
||||
pnpm test inheritance.test.ts
|
||||
|
||||
# Run tests matching pattern
|
||||
pnpm test -- --testNamePattern="type intersection"
|
||||
|
||||
# Run with debugging
|
||||
NODE_OPTIONS="--inspect" pnpm test
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Debugging Tips
|
||||
|
||||
|
||||
|
||||
1. **Use Verbose Output**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli --verbose TestComponent.tsx
|
||||
# Check all generated files for debugging
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Inspect AST**
|
||||
Add debug logging to see TypeScript AST:
|
||||
|
||||
|
||||
|
||||
```typescript
|
||||
console.log('AST Node:', node.kind, node.getText());
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Test Individual Components**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
# Test a specific fixture
|
||||
node dist/dial-cli.js --verbose spec/fixtures/TypeInheritance.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
|
||||
### Issue: Properties Not Appearing in Schema
|
||||
|
||||
|
||||
**Cause:** Missing `@dial` annotation
|
||||
**Solution:** Ensure property has at least one `@dial` tag
|
||||
|
||||
|
||||
```tsx
|
||||
// Won't appear in schema
|
||||
/** Just a comment */
|
||||
prop: string;
|
||||
|
||||
// Will appear in schema
|
||||
/** @dial control */
|
||||
prop: string;
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Issue: Type Inheritance Not Working
|
||||
|
||||
|
||||
**Cause:** Types not properly exported or resolved
|
||||
**Solution:** Ensure all types are exported and accessible
|
||||
|
||||
|
||||
```tsx
|
||||
// Export types for proper resolution
|
||||
export type BaseType = { ... };
|
||||
export interface ExtendedInterface extends BaseType { ... }
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Issue: Group Configuration Not Applied
|
||||
|
||||
|
||||
**Cause:** Group-level annotations at wrong position
|
||||
**Solution:** Place group annotations in interface/type JSDoc
|
||||
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* @dial transform @dial-no-wrap // Correct position
|
||||
*/
|
||||
interface Props {
|
||||
// Properties here inherit the configuration
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
|
||||
- Review [Type Inheritance](/dial/type-inheritance) patterns
|
||||
|
||||
- Check [CLI Reference](/dial/cli-reference) for all options
|
||||
|
||||
- See [Examples](/dial/examples) for real-world usage
|
||||
|
||||
- Read [Troubleshooting](/dial/cli-reference/troubleshooting) for common issues
|
||||
374
docs/dial/tutorial.md
Normal file
374
docs/dial/tutorial.md
Normal file
@@ -0,0 +1,374 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Tutorial
|
||||
|
||||
# Dial Tutorial: Using dial-cli
|
||||
|
||||
|
||||
|
||||
Dial CLI Tutorialdial-cli[v0.0.22](https://www.npmjs.com/package/@vuer-ai/dial-cli/v/0.0.22)
|
||||
This tutorial will guide you through using the dial-cli tool to generate UI controls from TypeScript interfaces with Dial annotations.
|
||||
|
||||
|
||||
## Using the dial-cli Tool
|
||||
|
||||
|
||||
The `dial-cli` is now available as a standalone package for generating Dial schemas from TypeScript files, providing a cleaner installation experience without UI dependencies.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
|
||||
```bash
|
||||
# Install globally (recommended for CLI tools)
|
||||
npm install -g @vuer-ai/dial-cli
|
||||
# or
|
||||
pnpm install -g @vuer-ai/dial-cli
|
||||
|
||||
# Check CLI is available
|
||||
dial-cli --help
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Basic Usage
|
||||
|
||||
|
||||
```bash
|
||||
# Generate schemas from a TypeScript file
|
||||
dial-cli <input-file> [input-file2...]
|
||||
|
||||
# Examples:
|
||||
dial-cli ./src/components/Box.tsx
|
||||
# Creates schema.dial in ./metadata directory
|
||||
|
||||
dial-cli ./src/components/Box.tsx -o ./schemas
|
||||
# Outputs to specified directory
|
||||
|
||||
# Process multiple files
|
||||
dial-cli Component1.tsx Component2.tsx
|
||||
|
||||
# Specify output directory
|
||||
dial-cli -o ./metadata MyComponent.tsx
|
||||
|
||||
```
|
||||
|
||||
|
||||
### What the CLI Does
|
||||
|
||||
|
||||
The dial-cli tool will:
|
||||
|
||||
|
||||
|
||||
1. Parse your TypeScript file using the TypeScript compiler API
|
||||
|
||||
1. Extract all interfaces and types with Dial annotations
|
||||
|
||||
1. Process JSDoc comments following the `@dial` convention
|
||||
|
||||
1. Generate JSON schema files that can be directly used with DialPanel
|
||||
|
||||
|
||||
|
||||
### Output Files
|
||||
|
||||
|
||||
The CLI generates files with a clean directory structure:
|
||||
|
||||
|
||||
**Main Output:**
|
||||
|
||||
|
||||
|
||||
- `schema.dial` - Combined schemas for all components, ready for UI generation
|
||||
|
||||
|
||||
|
||||
**Debug Output (verbose mode only):**
|
||||
|
||||
|
||||
|
||||
- `debug/component-raw.json` - Raw output from react-docgen-typescript
|
||||
|
||||
- `debug/component-combined.json` - Enhanced metadata with dial schema information
|
||||
|
||||
- `debug/component-schemas.json` - Individual component schemas for debugging
|
||||
|
||||
|
||||
|
||||
### Local Script
|
||||
|
||||
|
||||
This documentation includes a convenience script for generating metadata:
|
||||
|
||||
|
||||
```bash
|
||||
# From the dial directory
|
||||
./generate-dial-metadata.sh
|
||||
|
||||
```
|
||||
|
||||
|
||||
This will process the `BoxExample.tsx` file and output metadata to the `metadata/` directory.
|
||||
|
||||
|
||||
## Using Generated Schemas
|
||||
|
||||
|
||||
Once you've generated schemas using dial-cli, you can use them in your application.
|
||||
The Dial system consists of three main components:
|
||||
|
||||
|
||||
|
||||
1. **DialProvider** - Manages state for all controls
|
||||
|
||||
1. **DialPanel** - Converts schemas to UI components
|
||||
|
||||
1. **Input Components** - Individual control types (number, vector, boolean, etc.)
|
||||
|
||||
|
||||
|
||||
### Component API
|
||||
|
||||
|
||||
**DialPanel** accepts the following props:
|
||||
|
||||
|
||||
```tsx
|
||||
interface DialPanelProps {
|
||||
schemas: DialSchema[]; // Array of control schemas
|
||||
groups?: DialGroupConfig[]; // Optional group configurations
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
|
||||
```tsx
|
||||
// Basic usage with just schemas
|
||||
<DialPanel schemas={schemas} />
|
||||
|
||||
// With group configuration for layout control
|
||||
<DialPanel schemas={schemas} groups={groups} />
|
||||
|
||||
```
|
||||
|
||||
|
||||
### TypeScript Interfaces
|
||||
|
||||
|
||||
The Dial system uses the following main interfaces:
|
||||
|
||||
|
||||
```tsx
|
||||
// Schema for individual controls
|
||||
interface DialSchema {
|
||||
name: string;
|
||||
dtype: string;
|
||||
value?: DialValue;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
options?: Array<string | number | { label: string; value: string | number }>;
|
||||
// ... other properties
|
||||
tags?: {
|
||||
grouping?: string;
|
||||
col?: boolean | number;
|
||||
row?: number;
|
||||
layout?: string;
|
||||
labelPosition?: LabelPositionT;
|
||||
noWrap?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// Group configuration for styling and layout
|
||||
interface DialGroupConfig {
|
||||
name: string;
|
||||
noWrap?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
// Complete schema with groups (output from dial-cli)
|
||||
interface DialSchemaGroup {
|
||||
component: string;
|
||||
schema: DialSchema[];
|
||||
groups?: DialGroupConfig[];
|
||||
}
|
||||
|
||||
// Valid value types
|
||||
type DialValue = string | number | boolean | number[] | string[] | null | undefined;
|
||||
|
||||
```
|
||||
|
||||
|
||||
```tsx
|
||||
import { DialProvider, DialPanel } from './dial';
|
||||
|
||||
const schemas = [
|
||||
{
|
||||
name: 'position',
|
||||
dtype: 'vector3',
|
||||
value: [0, 0, 0],
|
||||
min: -10,
|
||||
max: 10,
|
||||
tags: { grouping: 'transform', col: true }
|
||||
},
|
||||
// ... more schemas
|
||||
];
|
||||
|
||||
function MyComponent() {
|
||||
const handleValueChange = (name, value) => {
|
||||
console.log(`${name} changed to`, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<DialProvider
|
||||
schemas={schemas}
|
||||
onValueChange={handleValueChange}
|
||||
>
|
||||
<DialPanel schemas={schemas} />
|
||||
</DialProvider>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Complete Example with dial-cli
|
||||
|
||||
|
||||
|
||||
1. **Create a TypeScript file with Dial annotations:**
|
||||
|
||||
|
||||
|
||||
```tsx
|
||||
// Box.tsx
|
||||
interface BoxProps {
|
||||
/**
|
||||
* Transform properties displayed on single line
|
||||
* @dial transform @dial-no-wrap
|
||||
*/
|
||||
|
||||
/** @dial transform @dial-dtype vector3 */
|
||||
position: [number, number, number];
|
||||
|
||||
/** @dial transform @dial-dtype euler */
|
||||
rotation: [number, number, number];
|
||||
|
||||
/**
|
||||
* Box dimensions
|
||||
* @dial geometry
|
||||
* @dial-dtype vector3
|
||||
* @dial-min 0.1
|
||||
* @dial-max 10
|
||||
* @dial-step 0.1
|
||||
*/
|
||||
size: [number, number, number];
|
||||
|
||||
/**
|
||||
* Box color
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
*/
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const Box: React.FC<BoxProps> = ({ size, position, rotation, color }) => {
|
||||
// Component implementation
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Generate the schema:**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
dial-cli Box.tsx -o ./schemas
|
||||
# Creates schemas/schema.dial with groups configuration
|
||||
|
||||
```
|
||||
|
||||
|
||||
The generated schema includes group-level settings:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"component": "Box",
|
||||
"schema": [
|
||||
{ "name": "position", "dtype": "vector3", "tags": { "grouping": "transform", "noWrap": true } },
|
||||
{ "name": "rotation", "dtype": "euler", "tags": { "grouping": "transform", "noWrap": true } },
|
||||
{ "name": "size", "dtype": "vector3", "tags": { "grouping": "geometry" } },
|
||||
{ "name": "color", "dtype": "color", "tags": { "grouping": "appearance" } }
|
||||
],
|
||||
"groups": [
|
||||
{ "name": "transform", "noWrap": true }
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
1. **Use the generated schema in your app:**
|
||||
|
||||
|
||||
|
||||
```tsx
|
||||
import { DialProvider, DialPanel, DialSchemaGroup, DialValue } from '@vuer-ai/vuer-uikit';
|
||||
import allSchemas from './schemas/schema.dial';
|
||||
|
||||
// Get the Box component schema from the combined schema file
|
||||
const boxSchema = allSchemas.find(s => s.component === 'Box');
|
||||
|
||||
function App() {
|
||||
const [boxProps, setBoxProps] = useState({
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
size: [1, 1, 1],
|
||||
color: '#ff0000'
|
||||
});
|
||||
|
||||
const handleValueChange = (name: string, value: DialValue) => {
|
||||
setBoxProps(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
return (
|
||||
<DialProvider
|
||||
schemas={[boxSchema]}
|
||||
onValueChange={handleValueChange}
|
||||
>
|
||||
<div style={{ display: 'flex' }}>
|
||||
{/* Your 3D scene */}
|
||||
<Box {...boxProps} />
|
||||
|
||||
{/* Auto-generated controls with group configuration */}
|
||||
<DialPanel schemas={[boxSchema]} />
|
||||
</div>
|
||||
</DialProvider>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
|
||||
- Learn more about [Dial Annotation Syntax](/dial/overview) in the overview
|
||||
|
||||
- Explore all [Input Types](/dial/input-types) available in Dial
|
||||
|
||||
- See [Controlled Dials](/dial/controlled-dials) for advanced usage
|
||||
|
||||
- Check out the [API Notes](/dial/api-notes) for detailed reference
|
||||
|
||||
- Read the [CLI Details](/dial/cli-details) for advanced CLI options
|
||||
352
docs/dial/type-inheritance.md
Normal file
352
docs/dial/type-inheritance.md
Normal file
@@ -0,0 +1,352 @@
|
||||
1. [Home](/)
|
||||
1. [Dial](/dial)
|
||||
1. Type Inheritance
|
||||
|
||||
# Type Inheritance in Dial
|
||||
|
||||
|
||||
|
||||
Type Inheritance & Compositiondial-cli[v0.0.22](https://www.npmjs.com/package/@vuer-ai/dial-cli/v/0.0.22)
|
||||
Dial CLI fully supports TypeScript's type system, including interface inheritance, type intersections, and utility types. This allows you to create reusable, composable type definitions while maintaining all Dial annotations and configurations.
|
||||
|
||||
|
||||
## Interface Inheritance
|
||||
|
||||
|
||||
When interfaces extend others, all properties and group configurations are inherited:
|
||||
|
||||
|
||||
### Basic Interface Extension
|
||||
|
||||
|
||||
```tsx
|
||||
// Base interface with common properties
|
||||
interface BaseProps {
|
||||
/**
|
||||
* Unique identifier
|
||||
* @dial common
|
||||
* @dial-dtype string
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Visibility control
|
||||
* @dial common
|
||||
* @dial-dtype boolean
|
||||
*/
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
// Extended interface inherits all base properties
|
||||
interface BoxProps extends BaseProps {
|
||||
/**
|
||||
* Box dimensions
|
||||
* @dial geometry
|
||||
* @dial-dtype vector3
|
||||
*/
|
||||
size: [number, number, number];
|
||||
|
||||
/**
|
||||
* Material color
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
*/
|
||||
color: string;
|
||||
}
|
||||
|
||||
// BoxProps will have: id, visible, size, color
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Deep Inheritance Chains
|
||||
|
||||
|
||||
```tsx
|
||||
interface Level1 {
|
||||
/** @dial level1 */
|
||||
prop1: string;
|
||||
}
|
||||
|
||||
interface Level2 extends Level1 {
|
||||
/** @dial level2 */
|
||||
prop2: number;
|
||||
}
|
||||
|
||||
interface Level3 extends Level2 {
|
||||
/** @dial level3 */
|
||||
prop3: boolean;
|
||||
}
|
||||
|
||||
// Level3 has all properties from Level1, Level2, and its own
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Type Intersections
|
||||
|
||||
|
||||
Type intersections combine multiple types while preserving all annotations and group configurations:
|
||||
|
||||
|
||||
### Basic Type Intersection
|
||||
|
||||
|
||||
```tsx
|
||||
type TransformType = {
|
||||
/** @dial transform @dial-dtype vector3 */
|
||||
position: [number, number, number];
|
||||
/** @dial transform @dial-dtype euler */
|
||||
rotation: [number, number, number];
|
||||
};
|
||||
|
||||
type AppearanceType = {
|
||||
/** @dial appearance @dial-dtype color */
|
||||
color: string;
|
||||
/** @dial appearance @dial-dtype number @dial-min 0 @dial-max 1 */
|
||||
opacity: number;
|
||||
};
|
||||
|
||||
// Combine multiple types
|
||||
type GameObject = TransformType & AppearanceType & {
|
||||
/** @dial metadata @dial-dtype string */
|
||||
name: string;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Group Configuration Inheritance
|
||||
|
||||
|
||||
The `@dial-no-wrap` configuration is inherited through type intersections:
|
||||
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* Animation properties that should display on one line
|
||||
* @dial animation @dial-no-wrap
|
||||
*/
|
||||
type AnimationType = {
|
||||
/** @dial animation @dial-dtype number @dial-min 0 @dial-max 10 */
|
||||
duration: number;
|
||||
|
||||
/** @dial animation @dial-dtype string */
|
||||
easing: string;
|
||||
|
||||
/** @dial animation @dial-dtype number @dial-min 0 @dial-max 5 */
|
||||
delay: number;
|
||||
};
|
||||
|
||||
// Properties from AnimationType inherit noWrap: true
|
||||
type AnimatedObject = BaseType & AnimationType & {
|
||||
/** @dial control @dial-dtype boolean */
|
||||
playing: boolean;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Utility Types
|
||||
|
||||
|
||||
Dial supports TypeScript's built-in utility types:
|
||||
|
||||
|
||||
### Pick - Select Specific Properties
|
||||
|
||||
|
||||
```tsx
|
||||
type FullTransform = {
|
||||
/** @dial position @dial-dtype number */
|
||||
x: number;
|
||||
/** @dial position @dial-dtype number */
|
||||
y: number;
|
||||
/** @dial position @dial-dtype number */
|
||||
z: number;
|
||||
/** @dial rotation @dial-dtype number-deg */
|
||||
rotationX: number;
|
||||
/** @dial rotation @dial-dtype number-deg */
|
||||
rotationY: number;
|
||||
/** @dial rotation @dial-dtype number-deg */
|
||||
rotationZ: number;
|
||||
};
|
||||
|
||||
// Only position properties
|
||||
type Position2D = Pick<FullTransform, 'x' | 'y'>;
|
||||
// Result: { x: number, y: number } with annotations
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Omit - Exclude Properties
|
||||
|
||||
|
||||
```tsx
|
||||
// Everything except rotation
|
||||
type TranslateOnly = Omit<FullTransform, 'rotationX' | 'rotationY' | 'rotationZ'>;
|
||||
// Result: { x, y, z } with all dial annotations preserved
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Partial - Make Properties Optional
|
||||
|
||||
|
||||
```tsx
|
||||
type RequiredConfig = {
|
||||
/** @dial config @dial-dtype string */
|
||||
apiKey: string;
|
||||
/** @dial config @dial-dtype string */
|
||||
endpoint: string;
|
||||
/** @dial config @dial-dtype number */
|
||||
timeout: number;
|
||||
};
|
||||
|
||||
// All properties become optional
|
||||
type OptionalConfig = Partial<RequiredConfig>;
|
||||
// Result: { apiKey?: string, endpoint?: string, timeout?: number }
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Property Override
|
||||
|
||||
|
||||
Child types can override parent property annotations:
|
||||
|
||||
|
||||
```tsx
|
||||
interface BaseComponent {
|
||||
/**
|
||||
* Base color property
|
||||
* @dial appearance
|
||||
* @dial-dtype string
|
||||
*/
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface AdvancedComponent extends BaseComponent {
|
||||
/**
|
||||
* Enhanced color with picker
|
||||
* @dial appearance
|
||||
* @dial-dtype color
|
||||
* @dial-icon Palette
|
||||
*/
|
||||
color: string; // Overrides with color picker
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Complex Example
|
||||
|
||||
|
||||
Here's a real-world example combining multiple inheritance patterns:
|
||||
|
||||
|
||||
```tsx
|
||||
// Base types with group configs
|
||||
type PhysicsProps = {
|
||||
/** @dial physics @dial-dtype number @dial-min 0 @dial-max 100 */
|
||||
mass: number;
|
||||
/** @dial physics @dial-dtype number @dial-min 0 @dial-max 1 */
|
||||
friction: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* @dial animation @dial-no-wrap
|
||||
*/
|
||||
type AnimationProps = {
|
||||
/** @dial animation */
|
||||
duration: number;
|
||||
/** @dial animation */
|
||||
loop: boolean;
|
||||
};
|
||||
|
||||
// Interface extending a type intersection
|
||||
interface GameObject extends PhysicsProps, AnimationProps {
|
||||
/** @dial metadata */
|
||||
id: string;
|
||||
/** @dial transform @dial-dtype vector3 */
|
||||
position: [number, number, number];
|
||||
}
|
||||
|
||||
// Further composition
|
||||
type InteractiveGameObject = GameObject & {
|
||||
/** @dial interaction */
|
||||
onClick: () => void;
|
||||
/** @dial interaction @dial-dtype boolean */
|
||||
hoverable: boolean;
|
||||
};
|
||||
|
||||
// Using utility types
|
||||
type StaticObject = Omit<InteractiveGameObject, 'onClick' | 'hoverable'>;
|
||||
type PreviewObject = Partial<InteractiveGameObject>;
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Generated Schema
|
||||
|
||||
|
||||
The dial-cli correctly resolves all inheritance and generates complete schemas:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"component": "InteractiveGameObject",
|
||||
"schemas": [
|
||||
{ "name": "mass", "dtype": "number", "min": 0, "max": 100, "tags": { "grouping": "physics" } },
|
||||
{ "name": "friction", "dtype": "number", "min": 0, "max": 1, "tags": { "grouping": "physics" } },
|
||||
{ "name": "duration", "dtype": "number", "tags": { "grouping": "animation", "noWrap": true } },
|
||||
{ "name": "loop", "dtype": "boolean", "tags": { "grouping": "animation", "noWrap": true } },
|
||||
{ "name": "id", "dtype": "string", "tags": { "grouping": "metadata" } },
|
||||
{ "name": "position", "dtype": "vector3", "tags": { "grouping": "transform" } },
|
||||
{ "name": "hoverable", "dtype": "boolean", "tags": { "grouping": "interaction" } }
|
||||
],
|
||||
"groups": [
|
||||
{ "name": "animation", "noWrap": true }
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
|
||||
|
||||
1. **Use Base Interfaces** for common properties across components
|
||||
|
||||
1. **Group Related Types** with type aliases for reusability
|
||||
|
||||
1. **Apply Group Configs** at the type level for consistent layout
|
||||
|
||||
1. **Document Overrides** when child types change parent behavior
|
||||
|
||||
1. **Test Inheritance** by running dial-cli with `--verbose` to see full resolution
|
||||
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
|
||||
|
||||
- Generic types with type parameters require concrete types for dial-cli to process
|
||||
|
||||
- Conditional types are not fully supported
|
||||
|
||||
- Mapped types need explicit property definitions
|
||||
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
|
||||
- Learn about [Group Configurations](/dial/annotations/grouping) for layout control
|
||||
|
||||
- Explore [Advanced Annotations](/dial/annotations/advanced) for complex types
|
||||
|
||||
- See [Complete Examples](/dial/examples) using inheritance patterns
|
||||
95
docs/form-inputs/input.md
Normal file
95
docs/form-inputs/input.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Input Component Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Input component represents a fundamental UI element within the toolkit, supporting multiple visual presentations, dimensions, and operational states.
|
||||
|
||||
## Props Configuration
|
||||
|
||||
### InputRoot Properties
|
||||
|
||||
| Property | Type | Default | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `size` | `'sm' \| 'base' \| 'lg'` | `'base'` | Adjusts input dimensions |
|
||||
| `state` | `'default' \| 'error'` | `'default'` | Visual feedback styling |
|
||||
| `side` | `'left' \| 'center' \| 'right'` | — | Text positioning and cursor placement |
|
||||
| `inputClassName` | `string` | — | Custom classes for inner input element |
|
||||
| Standard input attributes | `ComponentProps<'input'>` | — | Native HTML input properties |
|
||||
|
||||
### InputSlot Properties
|
||||
|
||||
| Property | Type | Default | Purpose |
|
||||
|----------|------|---------|---------|
|
||||
| `side` | `'left' \| 'right'` | `'left'` | Slot positioning |
|
||||
| Standard div attributes | `ComponentProps<'div'>` | — | Native HTML div properties |
|
||||
|
||||
## Type Definitions
|
||||
|
||||
```typescript
|
||||
interface InputRootProps extends ComponentProps<"div">, VariantProps<typeof inputVariants> {
|
||||
state?: "default" | "error";
|
||||
side?: "left" | "right" | "center";
|
||||
asChild?: boolean;
|
||||
inputClassName?: string;
|
||||
size?: "sm" | "base" | "lg";
|
||||
}
|
||||
|
||||
interface InputSlotProps extends ComponentProps<"div"> {
|
||||
side?: "left" | "right";
|
||||
}
|
||||
```
|
||||
|
||||
## Text Alignment Options
|
||||
|
||||
The component accommodates three alignment directions: left (default), center, and right. Slot components enable prefixes and suffixes through positioned elements.
|
||||
|
||||
## State Management
|
||||
|
||||
**Default State**: Standard appearance for typical interactions
|
||||
|
||||
**Error State**: Visual indication for validation failures and user feedback
|
||||
|
||||
**Disabled State**: Prevents user interaction and modification
|
||||
|
||||
## Input Type Examples
|
||||
|
||||
- **Text Input**: Standard character input
|
||||
- **Number Input**: Numeric values with optional currency symbols
|
||||
- **Password Input**: Masked character display
|
||||
- **Email Input**: Email-specific validation
|
||||
- **Search Input**: Search functionality with supplementary icons
|
||||
|
||||
## Interactive Examples
|
||||
|
||||
### Character Counter Implementation
|
||||
|
||||
```javascript
|
||||
const [value, setValue] = useState('');
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<InputRoot
|
||||
size="sm"
|
||||
placeholder="Type something..."
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
setCount(e.target.value.length);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Calculation Feature
|
||||
|
||||
Combines price and quantity inputs for real-time total computation:
|
||||
|
||||
```javascript
|
||||
const [price, setPrice] = useState('');
|
||||
const [quantity, setQuantity] = useState('');
|
||||
const total = (parseFloat(price) || 0) * (parseInt(quantity) || 0);
|
||||
```
|
||||
|
||||
### Form Validation Pattern
|
||||
|
||||
Implements error detection and submission handling through state management and conditional styling based on validation results.
|
||||
154
docs/form-inputs/number-inputs.md
Normal file
154
docs/form-inputs/number-inputs.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Number Inputs Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
A comprehensive collection of numeric input components with drag-to-modify functionality, specialized inputs for measurements, angles, and multi-dimensional data types.
|
||||
|
||||
## Basic Number Input (InputRoot)
|
||||
|
||||
The fundamental numeric input uses InputRoot with `etype="number"`. Mouse dragging is not supported.
|
||||
|
||||
```jsx
|
||||
const [value, setValue] = useState(42.5);
|
||||
|
||||
<InputRoot
|
||||
size="sm"
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
placeholder="Enter a number"
|
||||
/>
|
||||
```
|
||||
|
||||
## InputNumbers (Single)
|
||||
|
||||
Advanced numeric input component with drag-to-modify functionality and enhanced UX.
|
||||
|
||||
```jsx
|
||||
const [value, setValue] = useState([42.5]);
|
||||
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={value}
|
||||
onValuesChange={setValue}
|
||||
step={0.1}
|
||||
/>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `value` | `number[]` | — | Array of numbers for each input |
|
||||
| `onValuesChange` | `(value: number[]) => void` | — | Callback when values change |
|
||||
| `step` | `number` | `0.1` | Step size for drag modifications |
|
||||
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input size variant |
|
||||
| `side` | `'left' \| 'center' \| 'right'` | `'left'` | Text alignment |
|
||||
| `prefix` | `ReactNode[]` | — | Array of prefix labels/units for each input |
|
||||
| `suffix` | `ReactNode[]` | — | Array of suffix labels/units for each input |
|
||||
|
||||
### Types
|
||||
|
||||
```typescript
|
||||
interface InputNumbersProps extends Pick<InputRootProps, "size" | "side"> {
|
||||
step?: number;
|
||||
value: number[];
|
||||
prefix?: ReactNode[];
|
||||
suffix?: ReactNode[];
|
||||
onValuesChange?: (value: Array<number>) => void;
|
||||
}
|
||||
```
|
||||
|
||||
## Text Alignment Options
|
||||
|
||||
InputNumbers supports three text alignment variants:
|
||||
|
||||
**Left aligned (default)**
|
||||
```jsx
|
||||
const [leftValue, setLeftValue] = useState([123.45]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={leftValue}
|
||||
onValuesChange={setLeftValue}
|
||||
side="left"
|
||||
/>
|
||||
```
|
||||
|
||||
**Center aligned**
|
||||
```jsx
|
||||
const [centerValue, setCenterValue] = useState([123.45]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={centerValue}
|
||||
onValuesChange={setCenterValue}
|
||||
side="center"
|
||||
/>
|
||||
```
|
||||
|
||||
**Right aligned**
|
||||
```jsx
|
||||
const [rightValue, setRightValue] = useState([123.45]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={rightValue}
|
||||
onValuesChange={setRightValue}
|
||||
side="right"
|
||||
/>
|
||||
```
|
||||
|
||||
## Prefix and Suffix Usage
|
||||
|
||||
Add context to inputs with prefixes or suffixes:
|
||||
|
||||
**With prefix ($)**
|
||||
```jsx
|
||||
const [price, setPrice] = useState([299.99]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={price}
|
||||
onValuesChange={setPrice}
|
||||
prefix={["$"]}
|
||||
step={0.01}
|
||||
/>
|
||||
```
|
||||
|
||||
**With suffix (kg)**
|
||||
```jsx
|
||||
const [weight, setWeight] = useState([75.5]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={weight}
|
||||
onValuesChange={setWeight}
|
||||
suffix={["kg"]}
|
||||
step={0.1}
|
||||
/>
|
||||
```
|
||||
|
||||
## Grouped Inputs
|
||||
|
||||
Multiple numeric inputs grouped together with coordinated drag selection for multi-dimensional data:
|
||||
|
||||
```jsx
|
||||
const [position, setPosition] = useState([10.5, 20.3, -5.8]);
|
||||
<InputNumbers
|
||||
size="sm"
|
||||
value={position}
|
||||
onValuesChange={setPosition}
|
||||
prefix={["x", "y", "z"]}
|
||||
step={0.1}
|
||||
/>
|
||||
```
|
||||
|
||||
## Drag Interaction Features
|
||||
|
||||
All InputNumbers components support advanced drag interactions:
|
||||
|
||||
- **Vertical drag**: Select multiple inputs by dragging up/down
|
||||
- **Horizontal drag**: Modify selected values by dragging left/right
|
||||
- **Modifier keys**:
|
||||
- `Shift` + drag: 5x step size
|
||||
- `Alt` + drag: 0.2x step size
|
||||
|
||||
## Related Components
|
||||
|
||||
For specialized input components with built-in units and advanced data types, see the Specialized Input Components documentation.
|
||||
32
docs/form-inputs/playground.md
Normal file
32
docs/form-inputs/playground.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Form Inputs Playground
|
||||
|
||||
This page appears to be a **demonstration/showcase page** for the Vuer UIKit form components rather than a documentation article with detailed explanations.
|
||||
|
||||
## Available Components Displayed
|
||||
|
||||
The playground showcases interactive examples of:
|
||||
|
||||
- **Text Input** - with various label positioning options (left, top, with sub-labels)
|
||||
- **Toggle** - switch control
|
||||
- **Input Groups** - both vertical and horizontal layouts
|
||||
- **Textarea** - multi-line text input
|
||||
- **Selectors** - dropdown/select components
|
||||
- **Number Inputs** - including:
|
||||
- Steps (with configurable increments)
|
||||
- Interval controls
|
||||
- **Radio Groups** - both vertical and horizontal layouts
|
||||
- **Preset Inputs** - with values like 10, 20, 30
|
||||
- **Color Picker** - with hexadecimal input field
|
||||
|
||||
## Component Variations
|
||||
|
||||
Each component type is presented with multiple configurations:
|
||||
|
||||
- Different label arrangements
|
||||
- Horizontal and vertical orientations
|
||||
- Optional sublabel/helper text
|
||||
- Various state examples
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
This playground appears designed as an **interactive testing ground** rather than a reference guide. The actual implementation details and code examples would be found in the linked documentation pages for each specific input type (Input, Number Inputs, Specialized Inputs).
|
||||
115
docs/form-inputs/specialized-inputs.md
Normal file
115
docs/form-inputs/specialized-inputs.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Specialized Input Components Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
Pre-configured numeric input components for common measurement units, angles, and multi-dimensional data types.
|
||||
|
||||
## Common Props
|
||||
|
||||
All specialized input components share these properties:
|
||||
|
||||
| Prop | Type | Default | Purpose |
|
||||
|------|------|---------|---------|
|
||||
| `value` | `number` or `number[]` | — | Current value(s) |
|
||||
| `onChange` / `onValuesChange` | `(value) => void` | — | Callback when values change |
|
||||
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input size variant |
|
||||
| `step` | `number` | varies | Step size for drag modifications |
|
||||
|
||||
### Angle Input Additional Props
|
||||
|
||||
| Prop | Type | Default | Component |
|
||||
|------|------|---------|-----------|
|
||||
| `display` | `'rad' \| 'deg' \| 'pi'` | `'rad'` | `RadInput`, `EulerRadInput`, `PresetsRadInput` |
|
||||
| `presets` | `[number, number, number]` | — | `PresetsRadInput` |
|
||||
|
||||
## Measurement Unit Inputs
|
||||
|
||||
Components with built-in unit suffixes:
|
||||
|
||||
- **CmInput**: centimeters (cm)
|
||||
- **InchInput**: inches (in)
|
||||
- **TimeInput**: seconds (s)
|
||||
|
||||
Example usage:
|
||||
```javascript
|
||||
const [length, setLength] = useState(150);
|
||||
<CmInput size="sm" value={length} onChange={setLength} />
|
||||
```
|
||||
|
||||
## Angular Measurement Inputs
|
||||
|
||||
### DegInput and RadInput
|
||||
|
||||
**DegInput** displays degrees (°), while **RadInput** offers flexible display formats:
|
||||
|
||||
| Mode | Display | Example |
|
||||
|------|---------|---------|
|
||||
| `"rad"` | Radians | 1.57 rad |
|
||||
| `"deg"` | Degrees | 90° |
|
||||
| `"pi"` | π multiples | 0.5π |
|
||||
|
||||
The underlying value remains in radians regardless of display format.
|
||||
|
||||
```javascript
|
||||
const [radians, setRadians] = useState(Math.PI / 2);
|
||||
<RadInput value={radians} onChange={setRadians} display="deg" />
|
||||
```
|
||||
|
||||
### PresetsRadInput
|
||||
|
||||
Combines **RadInput** with preset buttons for common angles:
|
||||
|
||||
```javascript
|
||||
const [angle, setAngle] = useState(0);
|
||||
const commonAngles = [0, Math.PI/2, Math.PI];
|
||||
|
||||
<PresetsRadInput
|
||||
presets={commonAngles}
|
||||
value={angle}
|
||||
onChange={setAngle}
|
||||
display="deg"
|
||||
size="sm"
|
||||
/>
|
||||
```
|
||||
|
||||
## Integer Input
|
||||
|
||||
**IntInput** restricts values to integers only:
|
||||
|
||||
```javascript
|
||||
const [count, setCount] = useState(42);
|
||||
<IntInput size="sm" value={count} onChange={setCount} />
|
||||
```
|
||||
|
||||
## Vector Inputs
|
||||
|
||||
Multi-dimensional components for 3D data:
|
||||
|
||||
- **Vec3Input**: x, y, z coordinates
|
||||
- **EulerInput**: x°, y°, z° (degrees)
|
||||
- **EulerRadInput**: x, y, z (radians with flexible display)
|
||||
- **QuaternionInput**: w, x, y, z components
|
||||
|
||||
```javascript
|
||||
const [position, setPosition] = useState([1, 0, 0]);
|
||||
<Vec3Input value={position} onValuesChange={setPosition} size="sm" />
|
||||
|
||||
const [rotationRad, setRotationRad] = useState([0, Math.PI/2, Math.PI]);
|
||||
<EulerRadInput value={rotationRad} onValuesChange={setRotationRad} display="deg" />
|
||||
```
|
||||
|
||||
### Euler Angle Components Comparison
|
||||
|
||||
| Component | Storage | Display Options |
|
||||
|-----------|---------|-----------------|
|
||||
| `EulerInput` | Degrees | Always degrees |
|
||||
| `EulerRadInput` | Radians | `"rad"`, `"deg"`, `"pi"` |
|
||||
|
||||
## Drag Interaction Features
|
||||
|
||||
All specialized inputs support advanced drag interactions inherited from InputNumbers:
|
||||
|
||||
- **Vertical drag**: Select multiple inputs
|
||||
- **Horizontal drag**: Modify selected values
|
||||
- **Shift + drag**: 5× step multiplier
|
||||
- **Alt + drag**: 0.2× step multiplier
|
||||
46
docs/guides/getting-started.md
Normal file
46
docs/guides/getting-started.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Vuer UIKit Getting Started Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The VUER UI Kit is a React component library designed to integrate with VUER for controlling 3D scenes. This documentation provides guidance on setup and component usage.
|
||||
|
||||
## Installation
|
||||
|
||||
To begin using the toolkit, install the package via yarn:
|
||||
|
||||
```
|
||||
yarn add @vuer-ai/vuer-uikit
|
||||
```
|
||||
|
||||
## Quick Start Example
|
||||
|
||||
Here's a basic implementation to verify successful setup:
|
||||
|
||||
```jsx
|
||||
import { Button } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function App() {
|
||||
return <Button>Hello VUER!</Button>;
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
After installation, the documentation recommends exploring the Getting Started guide to learn project setup details and component implementation patterns.
|
||||
|
||||
## Available Components
|
||||
|
||||
The library includes over 40 components organized by category:
|
||||
|
||||
- **Form Inputs**: Input fields, number inputs, specialized controls
|
||||
- **Layout Components**: Modals, drawers, cards, sidebar, navbar
|
||||
- **Interactive Elements**: Buttons, toggles, dropdowns, tabs, sliders
|
||||
- **Display Components**: Avatars, badges, progress indicators, tooltips
|
||||
- **Advanced Features**: Tree views, tables, pagination, drag-selectable elements
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- Style guide covering colors, fonts, icons, and layout principles
|
||||
- Dial system documentation for input type handling
|
||||
- Menu and toolbar layout patterns
|
||||
- Hook utilities for React integration
|
||||
39
docs/guides/introduction.md
Normal file
39
docs/guides/introduction.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Vuer UIKit Introduction
|
||||
|
||||
## Overview
|
||||
|
||||
The Vuer UI Kit represents a comprehensive component library designed specifically for React applications. It integrates seamlessly with VUER to provide developers with the capability to manage 3D scene interactions.
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
Getting up and running with Vuer UI Kit requires just a few straightforward steps:
|
||||
|
||||
### Installation
|
||||
|
||||
Begin by installing the package using your preferred package manager:
|
||||
|
||||
```
|
||||
yarn add @vuer-ai/vuer-uikit
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Once installed, you can immediately start building components:
|
||||
|
||||
```javascript
|
||||
import { Button } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function App() {
|
||||
return <Button>Hello VUER!</Button>;
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
The documentation provides a "Getting Started" guide for developers seeking deeper knowledge about project setup and component implementation. This foundational resource helps developers understand how to leverage the full capabilities of the library in their applications.
|
||||
|
||||
## Package Information
|
||||
|
||||
- **Version**: v0.0.117
|
||||
- **Related CLI Tool**: dial-cli v0.0.22
|
||||
- **Repository**: Available on GitHub for community contributions and issue tracking
|
||||
71
docs/menu-tool-layouts/dock-layout.md
Normal file
71
docs/menu-tool-layouts/dock-layout.md
Normal file
@@ -0,0 +1,71 @@
|
||||
1. Home
|
||||
2. Menu Tool Layouts
|
||||
3. Dock Layout
|
||||
|
||||
# Dock Layout
|
||||
|
||||
A traditional docking layout system that provides fixed-positioned panels and floating controls, similar to IDE and professional software interfaces.
|
||||
|
||||
## Overview
|
||||
|
||||
The Dock Layout provides a desktop application-like interface layout system where left, right, and bottom panels are fixed and docked to the viewport edges, while the top area remains floating. This layout is particularly useful for applications that need fixed tool panels, status bars, and floating controls.
|
||||
|
||||
## Usage Recommendations
|
||||
|
||||
- Theme Compatibility: The dock-layout component is recommended for use with non-liquid themes only. It may not work optimally with liquid-based layouts.
|
||||
- Component Styling: When passing components to the left, right, or bottom props, it's recommended to remove shadow styles from these components for better visual integration (e.g., use className="shadow-none").
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Add Group 1 Group 3 Object 1 Object 2 Object 7 Group 2 Group 4 Object 3 Object 4 Group 5 Object 5 Object 6 Main Content
|
||||
|
||||
Scene Camera Render Connection
|
||||
|
||||
Background Color
|
||||
|
||||
Color
|
||||
|
||||
# World Transform
|
||||
|
||||
Position
|
||||
|
||||
X Y Z Rotation
|
||||
|
||||
X Y Z Scale
|
||||
|
||||
V HemisphereLight-[light-default-hemi]
|
||||
|
||||
skyColor
|
||||
|
||||
# groundColor
|
||||
|
||||
# Intensity
|
||||
|
||||
V Show Helper
|
||||
|
||||
Hide
|
||||
|
||||
DirectionalLight-[light-default-direct]
|
||||
|
||||
Color
|
||||
|
||||
# Intensity
|
||||
|
||||
V Show Helper
|
||||
|
||||
Hide
|
||||
|
||||
Gizmo
|
||||
|
||||
Enable
|
||||
|
||||
[0] 0 1 ✕ FPS mujoco Maxlen [0] 0 ```tsx
|
||||
<DockLayoutView
|
||||
left={<SceneGraph cardClassName="shadow-none"/>}
|
||||
right={<ControlTabs cardClassName="shadow-none"/>}
|
||||
bottom={<PlaybackControl className="shadow-none" />}
|
||||
top={<TopToolbar/>}
|
||||
>
|
||||
<MainPlaceholder/>
|
||||
</DockLayoutView>
|
||||
```
|
||||
66
docs/menu-tool-layouts/liquid-float-layout.md
Normal file
66
docs/menu-tool-layouts/liquid-float-layout.md
Normal file
@@ -0,0 +1,66 @@
|
||||
1. Home
|
||||
2. Menu Tool Layouts
|
||||
3. Liquid Float Layout
|
||||
|
||||
# Liquid Float Layout
|
||||
|
||||
A flexible floating layout system that allows elements to flow and position themselves dynamically based on content and available space.
|
||||
|
||||
## Overview
|
||||
|
||||
The Liquid Float Layout provides a fluid positioning system where elements can float and reposition themselves naturally, similar to how liquid adapts to its container. This layout is particularly useful for tool panels, menus, and dynamic content that needs to adapt to varying screen sizes and content lengths.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Main Content
|
||||
|
||||
[0] 0 1 ✕ FPS mujoco Maxlen [0] 0 Scene Camera Render Connection
|
||||
|
||||
Background Color
|
||||
|
||||
Color
|
||||
|
||||
# World Transform
|
||||
|
||||
Position
|
||||
|
||||
X Y Z Rotation
|
||||
|
||||
X Y Z Scale
|
||||
|
||||
V HemisphereLight-[light-default-hemi]
|
||||
|
||||
skyColor
|
||||
|
||||
# groundColor
|
||||
|
||||
# Intensity
|
||||
|
||||
V Show Helper
|
||||
|
||||
Hide
|
||||
|
||||
DirectionalLight-[light-default-direct]
|
||||
|
||||
Color
|
||||
|
||||
# Intensity
|
||||
|
||||
V Show Helper
|
||||
|
||||
Hide
|
||||
|
||||
Gizmo
|
||||
|
||||
Enable
|
||||
|
||||
Add Group 1 Group 3 Object 1 Object 2 Object 7 Group 2 Group 4 Object 3 Object 4 Group 5 Object 5 Object 6 ```tsx
|
||||
<LiquidLayoutView
|
||||
left={<SceneGraph cardClassName="h-full"/>}
|
||||
right={<ControlTabs/>}
|
||||
top={<TopToolbar/>}
|
||||
bottom={<PlaybackControl/>}
|
||||
>
|
||||
<MainPlaceholder/>
|
||||
</LiquidLayoutView>
|
||||
```
|
||||
197
docs/menu-tool-layouts/toolbar.md
Normal file
197
docs/menu-tool-layouts/toolbar.md
Normal file
@@ -0,0 +1,197 @@
|
||||
1. Home
|
||||
2. Menu Tool Layouts
|
||||
3. Toolbar
|
||||
|
||||
# Toolbar
|
||||
|
||||
Simple, composable toolbar components for organizing buttons and actions.
|
||||
|
||||
## Complex Example
|
||||
|
||||
Add ```jsx
|
||||
const [selectedTool, setSelectedTool] = useState("select");
|
||||
|
||||
return (
|
||||
<Toolbar size="md">
|
||||
<ToolbarGroup>
|
||||
<ToggleButtons value={selectedTool} onValueChange={setSelectedTool} padding={false} variant="primary">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<ToggleButton icon value="select" >
|
||||
<MouseCursorAltIcon strokWidth={0.5} size="md"/>
|
||||
</ToggleButton>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Select tool</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<ToggleButton value="edit" icon >
|
||||
<MouseCursorIcon strokWidth={0.5}/>
|
||||
</ToggleButton>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Edit tool</TooltipContent>
|
||||
</Tooltip>
|
||||
</ToggleButtons>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button icon variant="ghost">
|
||||
<Scissors className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Cut</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button icon variant="ghost">
|
||||
<Hand className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Hand tool</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon
|
||||
size="md"
|
||||
>
|
||||
<Hash/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Hash tool</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
icon
|
||||
size="md"
|
||||
onClick={() => toast("Type tool selected")}
|
||||
>
|
||||
<Type/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Type tool</TooltipContent>
|
||||
</Tooltip>
|
||||
</ToolbarGroup>
|
||||
<ToolbarSeparator />
|
||||
<ToolbarGroup>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="md"
|
||||
onClick={() => toast("Add item clicked")}
|
||||
>
|
||||
<Plus/> Add
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Add ```jsx
|
||||
<Toolbar>
|
||||
<ToolbarGroup>
|
||||
<Button variant="ghost" icon>
|
||||
<Hash/>
|
||||
</Button>
|
||||
<Button variant="ghost" icon>
|
||||
<Type/>
|
||||
</Button>
|
||||
<Button variant="ghost" icon>
|
||||
<Image/>
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
<ToolbarSeparator />
|
||||
<ToolbarGroup>
|
||||
<Button variant="primary">
|
||||
<Plus/> Add
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
- Toolbar - Main container with variant support (default | floating)
|
||||
- ToolbarGroup - Groups related buttons with gap spacing
|
||||
- Button - Button component with toolbar-specific styling
|
||||
- ToolbarSeparator - Short rounded visual separator
|
||||
|
||||
## Floating Variant
|
||||
|
||||
Add ```jsx
|
||||
<Toolbar variant="floating">
|
||||
<ToolbarGroup>
|
||||
<Button variant="ghost" icon>
|
||||
<Hash />
|
||||
</Button>
|
||||
<Button variant="ghost" icon>
|
||||
<Type />
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
<ToolbarSeparator />
|
||||
<ToolbarGroup>
|
||||
<Button variant="primary">
|
||||
<Plus /> Add
|
||||
</Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
```
|
||||
|
||||
## Sizes
|
||||
|
||||
```jsx
|
||||
{/* Small toolbar - compact padding */}
|
||||
<Toolbar size="sm">
|
||||
<ToolbarGroup>
|
||||
<Button variant="ghost" icon size="sm"><Hash /></Button>
|
||||
<Button variant="ghost" icon size="sm"><Type /></Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
|
||||
{/* Medium toolbar - default */}
|
||||
<Toolbar size="md">
|
||||
<ToolbarGroup>
|
||||
<Button variant="ghost" icon size="md"><Hash /></Button>
|
||||
<Button variant="ghost" icon size="md"><Type /></Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
|
||||
{/* Large toolbar - spacious padding */}
|
||||
<Toolbar size="lg">
|
||||
<ToolbarGroup>
|
||||
<Button variant="ghost" icon size="lg"><Hash /></Button>
|
||||
<Button variant="ghost" icon size="lg"><Type /></Button>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Toolbar
|
||||
|
||||
```tsx
|
||||
interface ToolbarProps {
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
variant?: "default" | "floating"
|
||||
size?: "sm" | "md" | "lg"
|
||||
}
|
||||
```
|
||||
|
||||
### Button
|
||||
|
||||
```tsx
|
||||
interface ButtonProps {
|
||||
variant?: "primary" | "secondary" | "destructive" | "ghost" | "link"
|
||||
size?: "sm" | "md" | "lg"
|
||||
icon?: boolean
|
||||
className?: string
|
||||
children: React.ReactNode
|
||||
onClick?: () => void
|
||||
disabled?: boolean
|
||||
tooltip?: string
|
||||
}
|
||||
```
|
||||
150
docs/other/hooks.md
Normal file
150
docs/other/hooks.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Vuer UIKit Hooks Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
Vuer UIKit provides a collection of React hooks designed to be SSR-safe and fully typed with TypeScript support. All hooks return `undefined` during server-side rendering and properly hydrate on the client side.
|
||||
|
||||
## Available Hooks
|
||||
|
||||
### useLocation
|
||||
|
||||
Tracks the current browser location and automatically updates when navigation occurs.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useLocation } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const location = useLocation();
|
||||
|
||||
if (!location) {
|
||||
return null; // Handle SSR or initial load
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Current path: {location.pathname}</p>
|
||||
<p>Query params: {location.search}</p>
|
||||
<p>Hash: {location.hash}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### useWindow
|
||||
|
||||
Provides safe access to the window object in server-side rendering environments.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useWindow } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const window = useWindow();
|
||||
|
||||
useEffect(() => {
|
||||
if (window) {
|
||||
console.log('Window width:', window.innerWidth);
|
||||
}
|
||||
}, [window]);
|
||||
|
||||
return <div>Component content</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### useDocument
|
||||
|
||||
Enables safe access to the document object in SSR environments.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useDocument } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const document = useDocument();
|
||||
|
||||
useEffect(() => {
|
||||
if (document) {
|
||||
const element = document.getElementById('my-element');
|
||||
}
|
||||
}, [document]);
|
||||
|
||||
return <div>Component content</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### useLocalStorage
|
||||
|
||||
Maintains a stateful value synchronized with browser local storage.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useLocalStorage } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const [theme, setTheme] = useLocalStorage('theme', 'light');
|
||||
|
||||
return (
|
||||
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
|
||||
Current theme: {theme}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### useIsMobile
|
||||
|
||||
Detects whether the current device is mobile based on viewport width. Useful for conditional rendering of mobile versus desktop layouts.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useIsMobile } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isMobile ? <MobileLayout /> : <DesktopLayout />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### useDragSelect
|
||||
|
||||
Enables drag selection functionality for selectable elements.
|
||||
|
||||
**Usage:**
|
||||
```jsx
|
||||
import { useDragSelect } from '@vuer-ai/vuer-uikit';
|
||||
|
||||
function MyComponent() {
|
||||
const { selectedKeys, setSelectedKeys } = useDragSelect();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{items.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
data-selectable={item.id}
|
||||
className={selectedKeys.has(item.id) ? 'selected' : ''}
|
||||
>
|
||||
{item.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### useQueryParams
|
||||
|
||||
Handles URL query parameter management and updates.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **SSR-Safe**: All hooks safely handle server-side rendering environments
|
||||
- **TypeScript Support**: Fully typed with automatic handling of optional values during SSR
|
||||
- **No Errors**: Browser API hooks won't throw errors on the server
|
||||
- **Client Hydration**: State properly syncs between server and client
|
||||
4
docs/save_files.sh
Executable file
4
docs/save_files.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script will be populated with file saves
|
||||
echo "Saving Dial files..."
|
||||
92
docs/style-guide/colors.md
Normal file
92
docs/style-guide/colors.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Color Guidelines
|
||||
|
||||
This documentation outlines the color system utilized in the VUER UI Kit.
|
||||
|
||||
## Brand Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--brand-primary` | rgba(0, 123, 255, 1) | rgba(0, 123, 255, 1) | rgba(0, 123, 255, 1) | rgba(0, 123, 255, 1) |
|
||||
| `--brand-hover` | rgba(41, 151, 255, 1) | rgba(41, 151, 255, 1) | rgba(41, 151, 255, 1) | rgba(41, 151, 255, 1) |
|
||||
| `--brand-pressed` | rgba(0, 74, 179, 1) | rgba(0, 74, 179, 1) | rgba(0, 74, 179, 1) | rgba(0, 74, 179, 1) |
|
||||
|
||||
## Background Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--bg-primary` | rgba(29, 29, 30, 1) | rgba(255, 255, 255, 1) | rgba(29, 29, 30, 1) | rgba(255, 255, 255, 1) |
|
||||
| `--bg-secondary` | rgba(90, 93, 98, 0.3) | rgba(227, 230, 235, 0.6) | rgba(90, 93, 98, 0.3) | rgba(227, 230, 235, 0.6) |
|
||||
| `--bg-tertiary` | rgba(75, 77, 83, 1) | rgba(220, 222, 229, 1) | rgba(75, 77, 83, 1) | rgba(220, 222, 229, 1) |
|
||||
| `--bg-quaternary` | rgba(87, 90, 96, 1) | rgba(202, 206, 217, 1) | rgba(87, 90, 96, 1) | rgba(202, 206, 217, 1) |
|
||||
| `--bg-mask` | rgba(56, 57, 59, 0.5) | rgba(56, 57, 59, 0.5) | rgba(56, 57, 59, 0.5) | rgba(246, 247, 248, 0.8) |
|
||||
|
||||
## Text Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--text-highlight` | rgba(255, 255, 255, 1) | rgba(0, 0, 0, 1) | rgba(255, 255, 255, 1) | rgba(0, 0, 0, 1) |
|
||||
| `--text-primary` | rgba(220, 222, 229, 1) | rgba(52, 53, 56, 1) | rgba(220, 222, 229, 1) | rgba(52, 53, 56, 1) |
|
||||
| `--text-secondary` | rgba(147, 150, 159, 1) | rgba(87, 90, 96, 1) | rgba(147, 150, 159, 1) | rgba(87, 90, 96, 1) |
|
||||
| `--text-tertiary` | rgba(121, 124, 131, 1) | rgba(147, 150, 159, 1) | rgba(121, 124, 131, 1) | rgba(147, 150, 159, 1) |
|
||||
| `--text-withbg` | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) |
|
||||
|
||||
## Icon Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--icon-highlight` | rgba(255, 255, 255, 1) | rgba(0, 0, 0, 1) | rgba(255, 255, 255, 1) | rgba(0, 0, 0, 1) |
|
||||
| `--icon-primary` | rgba(220, 222, 229, 1) | rgba(75, 77, 83, 1) | rgba(220, 222, 229, 1) | rgba(75, 77, 83, 1) |
|
||||
| `--icon-secondary` | rgba(147, 150, 159, 1) | rgba(121, 124, 131, 1) | rgba(147, 150, 159, 1) | rgba(121, 124, 131, 1) |
|
||||
| `--icon-tertiary` | rgba(121, 124, 131, 1) | rgba(181, 184, 196, 1) | rgba(121, 124, 131, 1) | rgba(181, 184, 196, 1) |
|
||||
| `--icon-withbg` | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) |
|
||||
|
||||
## Danger Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--danger-primary` | rgba(255, 69, 91, 1) | rgba(255, 69, 91, 1) | rgba(255, 69, 91, 1) | rgba(255, 69, 91, 1) |
|
||||
| `--danger-secondary` | rgba(255, 150, 156, 1) | rgba(255, 150, 156, 1) | rgba(255, 150, 156, 1) | rgba(255, 150, 156, 1) |
|
||||
| `--danger-tertiary` | rgba(179, 30, 58, 1) | rgba(179, 30, 58, 1) | rgba(179, 30, 58, 1) | rgba(179, 30, 58, 1) |
|
||||
|
||||
## Accent Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--accent-warning` | rgba(251, 187, 49, 1) | rgba(251, 187, 49, 1) | rgba(251, 187, 49, 1) | rgba(251, 187, 49, 1) |
|
||||
| `--accent-success` | rgba(84, 190, 125, 1) | rgba(84, 190, 125, 1) | rgba(84, 190, 125, 1) | rgba(84, 190, 125, 1) |
|
||||
|
||||
## Line Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--line-primary` | rgba(75, 77, 83, 1) | rgba(220, 222, 229, 1) | rgba(75, 77, 83, 0.5) | rgba(173, 176, 183, 0.6) |
|
||||
| `--line-secondary` | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) |
|
||||
|
||||
## Shadow Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--shadow-primary` | rgba(0, 0, 0, 0.6) | rgba(0, 0, 0, 0.1) | rgba(0, 0, 0, 0.6) | rgba(0, 0, 0, 0.1) |
|
||||
| `--shadow-secondary` | rgba(0, 0, 0, 0.2) | rgba(0, 0, 0, 0.06) | rgba(0, 0, 0, 0.2) | rgba(0, 0, 0, 0.06) |
|
||||
|
||||
## Alternative Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--alt-primary` | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) |
|
||||
| `--alt-hover` | rgba(87, 90, 96, 1) | rgba(220, 222, 229, 1) | rgba(87, 90, 96, 1) | rgba(220, 222, 229, 1) |
|
||||
| `--alt-pressed` | rgba(75, 77, 83, 1) | rgba(245, 245, 245, 1) | rgba(75, 77, 83, 1) | rgba(245, 245, 245, 1) |
|
||||
|
||||
## Group Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--group-primary` | rgba(0, 0, 0, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) | rgba(255, 255, 255, 1) |
|
||||
| `--group-hover` | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) | rgba(52, 53, 56, 1) | rgba(245, 245, 245, 1) |
|
||||
| `--group-pressed` | rgba(29, 29, 30, 1) | rgba(220, 222, 229, 1) | rgba(220, 222, 229, 1) | rgba(220, 222, 229, 1) |
|
||||
|
||||
## Select Colors
|
||||
|
||||
| Variable | Dark Mode | Light Mode | Liquid Dark | Liquid Light |
|
||||
|----------|-----------|-----------|-------------|--------------|
|
||||
| `--select-secondary` | rgba(56, 57, 59, 0.5) | rgba(227, 230, 235, 0.6) | rgba(56, 57, 59, 0.5) | rgba(227, 230, 235, 0.6) |
|
||||
26
docs/style-guide/font.md
Normal file
26
docs/style-guide/font.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Font Style Guide
|
||||
|
||||
## Font Family
|
||||
|
||||
The design system uses **Inter** as its typeface. This is a freely available font from Google Fonts optimized for on-screen readability.
|
||||
|
||||
## Typography Scale
|
||||
|
||||
The following table documents the complete font sizing system used throughout the Vuer UIKit:
|
||||
|
||||
| Style Name | Size (px) | Line Height | Weight |
|
||||
|---|---|---|---|
|
||||
| text-uk-h1 | 30 | 36 | 400 |
|
||||
| text-uk-h2 | 24 | 32 | 400 |
|
||||
| text-uk-h3 | 20 | 28 | 400 |
|
||||
| text-uk-lg | 16 | 24 | 400 |
|
||||
| text-uk-md | 14 | 20 | 400 |
|
||||
| text-uk-subtitle | 13 | 18 | 400 |
|
||||
| text-uk-sm | 12 | 16 | 400 |
|
||||
| text-uk-xs | 11 | 14 | 400 |
|
||||
| text-uk-xxs | 10 | 12 | 400 |
|
||||
| text-uk-hint | 10 | 12 | 400 |
|
||||
|
||||
## Key Information
|
||||
|
||||
All typography styles utilize the Inter typeface, with measurements specified in pixels. Font weights remain consistent at 400 (regular) across all size variants. Line heights are provided as both variable names and pixel values for implementation flexibility.
|
||||
70
docs/style-guide/icons.md
Normal file
70
docs/style-guide/icons.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Icons Style Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The VUER UI Kit utilizes Lucide icons as its foundational icon system, providing a "comprehensive collection of beautifully crafted, customizable icons that maintain consistency" across applications.
|
||||
|
||||
## Icon Sizing Guidelines
|
||||
|
||||
| Size | Use Case | Description |
|
||||
|------|----------|-------------|
|
||||
| 16px | Dense interfaces | Compact layout icons |
|
||||
| 20px | Default UI | Standard element sizing |
|
||||
| 24px | Buttons/Actions | Primary action buttons |
|
||||
| 32px | Emphasis | Large touch target icons |
|
||||
|
||||
## Color Application
|
||||
|
||||
| Type | Usage | Application |
|
||||
|------|-------|-------------|
|
||||
| Current Color | Default | Inherits parent text color |
|
||||
| Gray Scale | Secondary | Disabled states and subtle elements |
|
||||
| Accent Colors | Emphasis | Actions and highlights (use sparingly) |
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
**Best Practices:**
|
||||
- Maintain consistent sizing within interface sections
|
||||
- Scale proportionally when resizing
|
||||
- Ensure minimum 44px touch targets for mobile devices
|
||||
|
||||
### Stroke Width Options
|
||||
|
||||
| Width | Usage |
|
||||
|-------|-------|
|
||||
| 1.5 | Default |
|
||||
| 1 | Light |
|
||||
| 2 | Bold |
|
||||
|
||||
## Code Examples
|
||||
|
||||
**Standard Usage:**
|
||||
```javascript
|
||||
import { ChevronUp, Plus, Search } from 'lucide-react';
|
||||
|
||||
<ChevronUp size={24} strokeWidth={1.5} />
|
||||
```
|
||||
|
||||
**Custom Styling:**
|
||||
```javascript
|
||||
<Plus
|
||||
size={20}
|
||||
strokeWidth={2}
|
||||
className="text-blue-500 hover:text-blue-700"
|
||||
/>
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
Always provide descriptive labels for icon-only buttons:
|
||||
```javascript
|
||||
<button aria-label="Delete item">
|
||||
<Trash size={20} />
|
||||
</button>
|
||||
```
|
||||
|
||||
Hide purely decorative icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
## Responsive Implementation
|
||||
|
||||
Adjust sizes based on viewport dimensions for optimal display across devices.
|
||||
30
docs/style-guide/layout.md
Normal file
30
docs/style-guide/layout.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Layout Guidelines
|
||||
|
||||
This section presents the design tokens used throughout the VUER UI Kit, focusing on spacing and border radius values.
|
||||
|
||||
## Spacing Scale
|
||||
|
||||
The spacing system uses a 4px base unit to ensure consistent spacing across the interface.
|
||||
|
||||
| Variable | Value |
|
||||
|----------|-------|
|
||||
| `--spacing-xxs` | 2px |
|
||||
| `--spacing-xs` | 4px |
|
||||
| `--spacing-sm` | 6px |
|
||||
| `--spacing-md` | 8px |
|
||||
| `--spacing-lg` | 12px |
|
||||
| `--spacing-xl` | 16px |
|
||||
|
||||
## Border Radius Scale
|
||||
|
||||
The border radius system provides standardized rounded corners for components throughout the design system.
|
||||
|
||||
| Variable | Value |
|
||||
|----------|-------|
|
||||
| `--radius-uk-xs` | 4px |
|
||||
| `--radius-uk-sm` | 6px |
|
||||
| `--radius-uk-md` | 8px |
|
||||
| `--radius-uk-lg` | 12px |
|
||||
| `--radius-uk-xl` | 16px |
|
||||
|
||||
These design tokens serve as foundational building blocks for creating visual consistency and maintaining rhythm within VUER UI Kit components.
|
||||
91
fetch_remaining.sh
Normal file
91
fetch_remaining.sh
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to fetch remaining Vuer UIKit documentation pages
|
||||
# This script uses curl to fetch pages and saves them as markdown files
|
||||
|
||||
BASE_URL="https://uikit.vuer.ai"
|
||||
DOCS_DIR="/Users/ge/fortyfive/awesome-skills/skills/vuer-uikit/docs"
|
||||
|
||||
# Function to fetch and save a page
|
||||
fetch_page() {
|
||||
local url="$1"
|
||||
local output_file="$2"
|
||||
local description="$3"
|
||||
|
||||
echo "Fetching: $description"
|
||||
echo " URL: $url"
|
||||
echo " Output: $output_file"
|
||||
|
||||
# Create directory if it doesn't exist
|
||||
mkdir -p "$(dirname "$output_file")"
|
||||
|
||||
# Fetch the page (you'll need to use WebFetch via Claude for actual content)
|
||||
echo " Status: Ready to fetch"
|
||||
echo ""
|
||||
}
|
||||
|
||||
echo "================================"
|
||||
echo "Vuer UIKit Documentation Fetcher"
|
||||
echo "================================"
|
||||
echo ""
|
||||
|
||||
# Remaining Components (35 total)
|
||||
echo "COMPONENTS TO FETCH (35):"
|
||||
echo "------------------------"
|
||||
|
||||
components=(
|
||||
"card"
|
||||
"checkbox"
|
||||
"collapsible"
|
||||
"cursor-display"
|
||||
"drag-selectable"
|
||||
"drawer"
|
||||
"dropdown"
|
||||
"layout"
|
||||
"modal"
|
||||
"navbar"
|
||||
"navigation"
|
||||
"pagination"
|
||||
"popover"
|
||||
"preview"
|
||||
"progress"
|
||||
"radio-group"
|
||||
"select"
|
||||
"sheet"
|
||||
"sidebar"
|
||||
"simple-tree-view"
|
||||
"slider"
|
||||
"spinner"
|
||||
"switch"
|
||||
"sync-scroll"
|
||||
"table"
|
||||
"tabs"
|
||||
"textarea"
|
||||
"toast"
|
||||
"toggle"
|
||||
"toggle-buttons"
|
||||
"toggle-group"
|
||||
"tooltip"
|
||||
"tree-view"
|
||||
"version-badge"
|
||||
"waterfall"
|
||||
)
|
||||
|
||||
for comp in "${components[@]}"; do
|
||||
url="${BASE_URL}/components/${comp}/"
|
||||
output="${DOCS_DIR}/components/${comp}.md"
|
||||
fetch_page "$url" "$output" "Component: $comp"
|
||||
done
|
||||
|
||||
echo "================================"
|
||||
echo "Summary:"
|
||||
echo " Total components to fetch: ${#components[@]}"
|
||||
echo "================================"
|
||||
echo ""
|
||||
echo "Note: This script lists the pages to fetch."
|
||||
echo "Use Claude's WebFetch tool to actually retrieve the content."
|
||||
echo ""
|
||||
echo "Example Claude command for each:"
|
||||
echo " WebFetch URL: ${BASE_URL}/components/card/"
|
||||
echo " Prompt: Extract the main documentation content about the Card component..."
|
||||
echo ""
|
||||
305
plugin.lock.json
Normal file
305
plugin.lock.json
Normal file
@@ -0,0 +1,305 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:vuer-ai/vuer-skill-marketplace:skills/vuer-uikit",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "8441eb0263dad23d300dead342d6e7597a0255eb",
|
||||
"treeHash": "ccd52143480a5fe9cbe76c3abd0becd5265e41b443f7d74c2be9ea97b562d0f3",
|
||||
"generatedAt": "2025-11-28T10:28:56.900816Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "vuer-uikit",
|
||||
"description": "Complete documentation for Vuer UIKit React component library including 38 UI components, Dial system for control panels, style guides, and layout patterns",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "fetch_remaining.sh",
|
||||
"sha256": "6ab917fe5516f9e9de68d62fc3c48bd73c3aac15578afd5847f042bbd9f41d9d"
|
||||
},
|
||||
{
|
||||
"path": "COMPLETION_STATUS.md",
|
||||
"sha256": "3c0dad0b20858880f2a5586c48ba7483d38a419ae32355f7bfe1817da35d37b2"
|
||||
},
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "55b6434c981a4d715aa8499dc2fd0ee3ed2996a0b52b2067f5580fdbd1659452"
|
||||
},
|
||||
{
|
||||
"path": "SKILL.md",
|
||||
"sha256": "d2999be6b2df77672e57184a173339161ec56376b0575507b05dd0c1ebf32eb9"
|
||||
},
|
||||
{
|
||||
"path": "docs/save_files.sh",
|
||||
"sha256": "fa2cd36e5eea4fc97904a7d03ccaf4ee1f1cb465635407e31bb74f0e15e01832"
|
||||
},
|
||||
{
|
||||
"path": "docs/README.md",
|
||||
"sha256": "6782bb460a3b1080184e8a29abff7ca0f51d7efea9ba461f83665513c09d252b"
|
||||
},
|
||||
{
|
||||
"path": "docs/other/hooks.md",
|
||||
"sha256": "4201dc22aeacb1ab4747c15a23345b1a001992ebbb3e41eb51a336753785e2dd"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/controlled-dials.md",
|
||||
"sha256": "a56faf52f3cda80fd2bfeb4b0d4eb6b3948e0350e6a3f16c7f78403420a733b3"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/overview.md",
|
||||
"sha256": "62aad0eb362aef8e597888caedf0755e91266ee591231f937186b0b2d623ca00"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/api-notes.md",
|
||||
"sha256": "f6c84dc41740014f6c1071e5c8fda72db8a7dad701367abcedd7d80df3ed4f3a"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/input-types.md",
|
||||
"sha256": "fece7505d013297eb2d72429dac7378086332471d186dcbc5d5de587e321eaa6"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/testing.md",
|
||||
"sha256": "86142edd371f15432880fc7c63e551d210ac713dcf594585520359efbed69d94"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/type-inheritance.md",
|
||||
"sha256": "e90d551602033f641213391c878c1dc8a1a5137681276300a75e158c8875bc1a"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/getting-started.md",
|
||||
"sha256": "fdefc04150e9f1a589ad2e42827859a6ae75970b06b452050c811ce75cd05383"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/tutorial.md",
|
||||
"sha256": "f8f3e64b73ad0f51de476450b7ade646d3c97d207331b715976f22dfe17c8a79"
|
||||
},
|
||||
{
|
||||
"path": "docs/dial/cli-details.md",
|
||||
"sha256": "db4ebe15caccfcef234b7ff81758c746664cd4cee63641cda19c08b33c6fe0e6"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/radio-group.md",
|
||||
"sha256": "dab29bed57a2456cad273adcdb9b9b1c02624bdbe46ea2f1295aa1a3cbe0b7ef"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/modal.md",
|
||||
"sha256": "4b726e6a8f29dbcbb5364527d50f0de9674509ad49014a721bcc7bd2c8ef1d5a"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/toast.md",
|
||||
"sha256": "a57d764cb4ec01b5296b77ae69f5227ad2758b9cb0baa4b2ead6268bcb67297e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/toggle-buttons.md",
|
||||
"sha256": "11a026aedc2a8fd2458db81a4298a65f3e89bc8f40e3e718bd4ff08a1023f3bd"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/simple-tree-view.md",
|
||||
"sha256": "19be21d6a0bfabb73a9c194028df8aa36d5d626704d2eb115af8a222b4e33d37"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/waterfall.md",
|
||||
"sha256": "dd0033265db6917f1589c4949004f7ab58d0b31174edc652d7e90d097f75f207"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/slider.md",
|
||||
"sha256": "e15f8a312c0dd1d94d108eb8f9c98aebdda7817733d4b72f86960f89dcd3f713"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/card.md",
|
||||
"sha256": "f6d64af31ec7c7d53f4db9934039849b0d3c6a3e63ebdd70a0064f36c6b8e381"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/sheet.md",
|
||||
"sha256": "e82a1a80f1167b7660dabe5d80a5a5c40ac215ae12c9d733116236563fbd6613"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/button.md",
|
||||
"sha256": "309141bd8ad5e8f85bdf4a893e05243105b68f7e4497aac6c0ddfeab5d822998"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/sync-scroll.md",
|
||||
"sha256": "b65a14ad4dbb6e6eb29c9a70f52437689877ae6485dd0569e63918c551020a00"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/checkbox.md",
|
||||
"sha256": "33261e401950e845518fe7c1262f6ba7e51bb17084d60cf1d4b3d5214fc00e17"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/popover.md",
|
||||
"sha256": "7994fd8a219548b1ee3c2aa8a9887a48fbdd0626927eeb0cfa3e031201918e7c"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/pagination.md",
|
||||
"sha256": "e75e7e86280edd2bc77d6648242988d0b2c4cea7e3fb91ca4cf5114547075194"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/progress.md",
|
||||
"sha256": "c9137d75987e5b2285239b8c5cd37384ba8a992864f9dc548776049461522b70"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/select.md",
|
||||
"sha256": "6400112295217bcd91113e8e7a5a035eb5a692b9f537a5e7ffed1e6ac191e155"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/navigation.md",
|
||||
"sha256": "5b260578d35dcd48c23974438e026be8c6d0b7cf3ae81a9fcbd129d6c768abaf"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/table.md",
|
||||
"sha256": "a57d764cb4ec01b5296b77ae69f5227ad2758b9cb0baa4b2ead6268bcb67297e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/dropdown.md",
|
||||
"sha256": "4ab367300852e698f81af20f00328309f1af1ff9c405e3b5bb4a0fe26c3a65be"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/spinner.md",
|
||||
"sha256": "15d6add1a8af71ab30b662303a04787043d9136aa8b947bf64e9bb6047f6f51d"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/drag-selectable.md",
|
||||
"sha256": "66ca74d4595ffe9b0d6c1c035ef6d70decabbb4e183f90ae72546e151a599e39"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/cursor-display.md",
|
||||
"sha256": "f382ddcd30c2c90b0cbfb932ed8572e68d2ce70d383753d50e259684cfc00eb0"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/drawer.md",
|
||||
"sha256": "dadd00508d7f26d2c1108e4fa21edea1acaac6ccb18e71d545b1b5dedcdda10c"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/tabs.md",
|
||||
"sha256": "a57d764cb4ec01b5296b77ae69f5227ad2758b9cb0baa4b2ead6268bcb67297e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/sidebar.md",
|
||||
"sha256": "a2916de912b9afb33fd18649830dfd94885f6d0cf77705c272c7f2db9896b4eb"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/preview.md",
|
||||
"sha256": "b84d0149356a355ce037bdb22cb32d6904eeb401c863c38f68e0a52f153af4a4"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/toggle.md",
|
||||
"sha256": "a57d764cb4ec01b5296b77ae69f5227ad2758b9cb0baa4b2ead6268bcb67297e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/textarea.md",
|
||||
"sha256": "a57d764cb4ec01b5296b77ae69f5227ad2758b9cb0baa4b2ead6268bcb67297e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/tree-view.md",
|
||||
"sha256": "19be21d6a0bfabb73a9c194028df8aa36d5d626704d2eb115af8a222b4e33d37"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/navbar.md",
|
||||
"sha256": "75bb29e9bf7a1f46ebaecb73ee2e09c01fd1b5a5ff29e90b526aeaada541c4f8"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/switch.md",
|
||||
"sha256": "315cf2c73a3645dbeccc73cfc58da57a97b7d0bedbb9afa498f685f8bb0c9dcd"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/avatar.md",
|
||||
"sha256": "7a1760174301fdd4ac0c16a40b26d09087e232660b2c30dbbd568e62c524804d"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/toggle-group.md",
|
||||
"sha256": "ef307ed02b8ce845fc83e15e5a8fc29cf436dfcb45df2ec7085e191d77344e3a"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/tooltip.md",
|
||||
"sha256": "e5394c9c1b92e88db6bf1b9b08ec0d4be53def002b04fea30ea9d6249e25e3ad"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/badge.md",
|
||||
"sha256": "02ae7ca1770bd975ceb0490c261df817ada9e3f2976e2a100f7cfc26cb03d5e8"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/version-badge.md",
|
||||
"sha256": "fe9aae0638016b40900f1b6a9cdd960e450559e1454dfff1907ddef7b01aff4e"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/collapsible.md",
|
||||
"sha256": "0551820914c7cb53d489e1970db94f90e94e56cb96d3da2a846521f3e8435f3a"
|
||||
},
|
||||
{
|
||||
"path": "docs/components/layout.md",
|
||||
"sha256": "d8fdecf5896caa44c7f29742362d0b33e46fe117529908cc87e021d13aea09b8"
|
||||
},
|
||||
{
|
||||
"path": "docs/guides/introduction.md",
|
||||
"sha256": "73ad6caa2d7648669b361d05e847c65214a5f815a64cc3fe6502aad389ef0565"
|
||||
},
|
||||
{
|
||||
"path": "docs/guides/getting-started.md",
|
||||
"sha256": "6322473a1b0b091b28a99b430673646cb6314fa6f4e4f5c822e19df74ab617e3"
|
||||
},
|
||||
{
|
||||
"path": "docs/menu-tool-layouts/dock-layout.md",
|
||||
"sha256": "8a429c7047b728521361faf35d7ee4426589517f4579d79cfccfcf485b005cc2"
|
||||
},
|
||||
{
|
||||
"path": "docs/menu-tool-layouts/toolbar.md",
|
||||
"sha256": "6e7882dd450e4159dae2965be581184b2f93ec800d9f01772daebb9b827c805d"
|
||||
},
|
||||
{
|
||||
"path": "docs/menu-tool-layouts/liquid-float-layout.md",
|
||||
"sha256": "ba4a5c7a608cafef0fb1b0ab2ff07a9c44b7add645ae19752e958298a6dbf9a6"
|
||||
},
|
||||
{
|
||||
"path": "docs/form-inputs/input.md",
|
||||
"sha256": "ccb1a1c8d6f3e2f24febd2cfa7c3ac198f9ee04bb87981eee24b34f0c92d70c2"
|
||||
},
|
||||
{
|
||||
"path": "docs/form-inputs/playground.md",
|
||||
"sha256": "8e5b8ebd88d7ff2e714ecc07a96525fb9339f969ad8e8687559b397c2ab022cd"
|
||||
},
|
||||
{
|
||||
"path": "docs/form-inputs/number-inputs.md",
|
||||
"sha256": "1abae995121642045e3412fc8822d03aa9c3caae7dab4b753c42fb3ef9e2aedd"
|
||||
},
|
||||
{
|
||||
"path": "docs/form-inputs/specialized-inputs.md",
|
||||
"sha256": "22252deffba69c005e5af62d4f6d9f4803ef92779d7406a14a13bbe920343c94"
|
||||
},
|
||||
{
|
||||
"path": "docs/style-guide/colors.md",
|
||||
"sha256": "3eeb878b85f868887afc0f4c2ceafcf7b283b41bf6adc7e75a416055594e9d52"
|
||||
},
|
||||
{
|
||||
"path": "docs/style-guide/font.md",
|
||||
"sha256": "1c56a26075d520aa32ef588dd2cec740374c2b4bdc43bc00802707e2983fad7f"
|
||||
},
|
||||
{
|
||||
"path": "docs/style-guide/icons.md",
|
||||
"sha256": "060449051e1536b98bedc0b5200d50afd552fb512604bcc042d0027cff667425"
|
||||
},
|
||||
{
|
||||
"path": "docs/style-guide/layout.md",
|
||||
"sha256": "083bdf38669df685f5a74487d20b8d996805c944448c6b8a1fdc78eb4ffd0c56"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "a94567e37b7c8581171eba40c34489854d58b171170f561e53b866369abdc472"
|
||||
}
|
||||
],
|
||||
"dirSha256": "ccd52143480a5fe9cbe76c3abd0becd5265e41b443f7d74c2be9ea97b562d0f3"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user