@opencosmos/ui 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +239 -0
- package/README.md +161 -0
- package/dist/cli.mjs +151 -0
- package/dist/dates.d.mts +20 -0
- package/dist/dates.d.ts +20 -0
- package/dist/dates.js +240 -0
- package/dist/dates.js.map +1 -0
- package/dist/dates.mjs +203 -0
- package/dist/dates.mjs.map +1 -0
- package/dist/dnd.d.mts +126 -0
- package/dist/dnd.d.ts +126 -0
- package/dist/dnd.js +274 -0
- package/dist/dnd.js.map +1 -0
- package/dist/dnd.mjs +250 -0
- package/dist/dnd.mjs.map +1 -0
- package/dist/fontThemes-Dh8mtXES.d.mts +868 -0
- package/dist/fontThemes-Dh8mtXES.d.ts +868 -0
- package/dist/forms.d.mts +38 -0
- package/dist/forms.d.ts +38 -0
- package/dist/forms.js +198 -0
- package/dist/forms.js.map +1 -0
- package/dist/forms.mjs +159 -0
- package/dist/forms.mjs.map +1 -0
- package/dist/hooks-1b8WaQf1.d.mts +225 -0
- package/dist/hooks-CKW8vE9H.d.ts +225 -0
- package/dist/hooks.d.mts +3 -0
- package/dist/hooks.d.ts +3 -0
- package/dist/hooks.js +971 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hooks.mjs +943 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index-DscTIrZ2.d.mts +29 -0
- package/dist/index-DscTIrZ2.d.ts +29 -0
- package/dist/index.d.mts +3382 -0
- package/dist/index.d.ts +3382 -0
- package/dist/index.js +15146 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +14802 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers-CXPDMsl7.d.mts +30 -0
- package/dist/providers-Dn_Msjvz.d.ts +30 -0
- package/dist/providers.d.mts +3 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +1885 -0
- package/dist/providers.js.map +1 -0
- package/dist/providers.mjs +1859 -0
- package/dist/providers.mjs.map +1 -0
- package/dist/tables.d.mts +10 -0
- package/dist/tables.d.ts +10 -0
- package/dist/tables.js +248 -0
- package/dist/tables.js.map +1 -0
- package/dist/tables.mjs +218 -0
- package/dist/tables.mjs.map +1 -0
- package/dist/tokens.d.mts +1065 -0
- package/dist/tokens.d.ts +1065 -0
- package/dist/tokens.js +2637 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tokens.mjs +2555 -0
- package/dist/tokens.mjs.map +1 -0
- package/dist/utils-CIIM7dAC.d.ts +986 -0
- package/dist/utils-Cs04sxth.d.mts +986 -0
- package/dist/utils.d.mts +4 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +874 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.mjs +806 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/validation-Bj1ye-v_.d.mts +114 -0
- package/dist/validation-Bj1ye-v_.d.ts +114 -0
- package/dist/webgl.d.mts +104 -0
- package/dist/webgl.d.ts +104 -0
- package/dist/webgl.js +226 -0
- package/dist/webgl.js.map +1 -0
- package/dist/webgl.mjs +195 -0
- package/dist/webgl.mjs.map +1 -0
- package/package.json +267 -0
- package/src/cli.ts +206 -0
- package/src/component-registry.ts +183 -0
- package/src/components/actions/Button.test.tsx +61 -0
- package/src/components/actions/Button.tsx +70 -0
- package/src/components/actions/Link.tsx +78 -0
- package/src/components/actions/Magnetic.tsx +68 -0
- package/src/components/actions/Toggle.test.tsx +40 -0
- package/src/components/actions/Toggle.tsx +47 -0
- package/src/components/actions/ToggleGroup.tsx +70 -0
- package/src/components/actions/index.ts +5 -0
- package/src/components/backgrounds/FaultyTerminal.tsx +426 -0
- package/src/components/backgrounds/OrbBackground.tsx +424 -0
- package/src/components/backgrounds/WarpBackground.tsx +358 -0
- package/src/components/backgrounds/index.ts +3 -0
- package/src/components/blocks/Hero.tsx +142 -0
- package/src/components/blocks/social/OpenGraphCard.tsx +243 -0
- package/src/components/cursor/SplashCursor.tsx +1315 -0
- package/src/components/cursor/TargetCursor.tsx +187 -0
- package/src/components/cursor/index.ts +2 -0
- package/src/components/data-display/AspectImage.tsx +73 -0
- package/src/components/data-display/Avatar.test.tsx +35 -0
- package/src/components/data-display/Avatar.tsx +55 -0
- package/src/components/data-display/Badge.test.tsx +43 -0
- package/src/components/data-display/Badge.tsx +84 -0
- package/src/components/data-display/Brand.tsx +123 -0
- package/src/components/data-display/Calendar.tsx +70 -0
- package/src/components/data-display/Card.test.tsx +92 -0
- package/src/components/data-display/Card.tsx +115 -0
- package/src/components/data-display/Code.tsx +210 -0
- package/src/components/data-display/CollapsibleCodeBlock.tsx +238 -0
- package/src/components/data-display/DataTable.tsx +119 -0
- package/src/components/data-display/DescriptionList.tsx +41 -0
- package/src/components/data-display/GitHubIcon.tsx +44 -0
- package/src/components/data-display/Heading.test.tsx +36 -0
- package/src/components/data-display/Heading.tsx +83 -0
- package/src/components/data-display/StatCard.tsx +195 -0
- package/src/components/data-display/Table.tsx +133 -0
- package/src/components/data-display/Text.test.tsx +48 -0
- package/src/components/data-display/Text.tsx +144 -0
- package/src/components/data-display/Timeline.tsx +194 -0
- package/src/components/data-display/TreeView.tsx +226 -0
- package/src/components/data-display/Typewriter.tsx +119 -0
- package/src/components/data-display/VariableWeightText.tsx +130 -0
- package/src/components/data-display/index.ts +19 -0
- package/src/components/feedback/Alert.test.tsx +44 -0
- package/src/components/feedback/Alert.tsx +65 -0
- package/src/components/feedback/EmptyState.tsx +113 -0
- package/src/components/feedback/Progress.test.tsx +60 -0
- package/src/components/feedback/Progress.tsx +30 -0
- package/src/components/feedback/ProgressBar.tsx +158 -0
- package/src/components/feedback/Skeleton.test.tsx +39 -0
- package/src/components/feedback/Skeleton.tsx +45 -0
- package/src/components/feedback/Sonner.tsx +28 -0
- package/src/components/feedback/Spinner.test.tsx +33 -0
- package/src/components/feedback/Spinner.tsx +99 -0
- package/src/components/feedback/Stepper.tsx +307 -0
- package/src/components/feedback/Toast/Toast.tsx +243 -0
- package/src/components/feedback/Toast/index.ts +2 -0
- package/src/components/feedback/index.ts +9 -0
- package/src/components/forms/Checkbox.test.tsx +40 -0
- package/src/components/forms/Checkbox.tsx +31 -0
- package/src/components/forms/ColorPicker.tsx +118 -0
- package/src/components/forms/Combobox.tsx +96 -0
- package/src/components/forms/DragDrop.tsx +440 -0
- package/src/components/forms/FileUpload.tsx +252 -0
- package/src/components/forms/FilterButton.tsx +65 -0
- package/src/components/forms/Form.tsx +197 -0
- package/src/components/forms/Input.test.tsx +46 -0
- package/src/components/forms/Input.tsx +43 -0
- package/src/components/forms/InputOTP.tsx +81 -0
- package/src/components/forms/Label.test.tsx +20 -0
- package/src/components/forms/Label.tsx +25 -0
- package/src/components/forms/RadioGroup.tsx +51 -0
- package/src/components/forms/SearchBar.tsx +215 -0
- package/src/components/forms/Select.test.tsx +118 -0
- package/src/components/forms/Select.tsx +274 -0
- package/src/components/forms/Slider.tsx +29 -0
- package/src/components/forms/Switch.test.tsx +76 -0
- package/src/components/forms/Switch.tsx +30 -0
- package/src/components/forms/TextField.tsx +152 -0
- package/src/components/forms/Textarea.test.tsx +41 -0
- package/src/components/forms/Textarea.tsx +29 -0
- package/src/components/forms/ThemeSwitcher.tsx +290 -0
- package/src/components/forms/ThemeToggle.tsx +151 -0
- package/src/components/forms/index.ts +19 -0
- package/src/components/layout/Accordion.test.tsx +66 -0
- package/src/components/layout/Accordion.tsx +64 -0
- package/src/components/layout/AspectRatio.tsx +7 -0
- package/src/components/layout/Carousel.tsx +277 -0
- package/src/components/layout/Collapsible.test.tsx +40 -0
- package/src/components/layout/Collapsible.tsx +31 -0
- package/src/components/layout/Container.test.tsx +45 -0
- package/src/components/layout/Container.tsx +99 -0
- package/src/components/layout/CustomizerPanel.tsx +400 -0
- package/src/components/layout/DatePicker.tsx +57 -0
- package/src/components/layout/Footer/Footer.tsx +175 -0
- package/src/components/layout/Footer/index.ts +2 -0
- package/src/components/layout/GlassSurface.tsx +82 -0
- package/src/components/layout/Grid.test.tsx +31 -0
- package/src/components/layout/Grid.tsx +130 -0
- package/src/components/layout/Header/Header.tsx +450 -0
- package/src/components/layout/Header/index.ts +2 -0
- package/src/components/layout/PageLayout.tsx +180 -0
- package/src/components/layout/PageTemplate.tsx +158 -0
- package/src/components/layout/Resizable.tsx +48 -0
- package/src/components/layout/ScrollArea.tsx +53 -0
- package/src/components/layout/Separator.test.tsx +28 -0
- package/src/components/layout/Separator.tsx +29 -0
- package/src/components/layout/Sidebar.tsx +171 -0
- package/src/components/layout/Stack.test.tsx +41 -0
- package/src/components/layout/Stack.tsx +89 -0
- package/src/components/layout/glass-surface.css +60 -0
- package/src/components/layout/index.ts +18 -0
- package/src/components/motion/AnimatedBeam.tsx +159 -0
- package/src/components/navigation/Breadcrumb.test.tsx +57 -0
- package/src/components/navigation/Breadcrumb.tsx +119 -0
- package/src/components/navigation/Breadcrumbs.tsx +221 -0
- package/src/components/navigation/Command.tsx +159 -0
- package/src/components/navigation/Menubar.tsx +115 -0
- package/src/components/navigation/NavLink.tsx +55 -0
- package/src/components/navigation/NavigationMenu.tsx +125 -0
- package/src/components/navigation/Pagination.tsx +121 -0
- package/src/components/navigation/SecondaryNav.tsx +100 -0
- package/src/components/navigation/Tabs.test.tsx +47 -0
- package/src/components/navigation/Tabs.tsx +60 -0
- package/src/components/navigation/TertiaryNav.tsx +90 -0
- package/src/components/navigation/index.ts +10 -0
- package/src/components/overlays/AlertDialog.test.tsx +69 -0
- package/src/components/overlays/AlertDialog.tsx +166 -0
- package/src/components/overlays/ContextMenu.tsx +243 -0
- package/src/components/overlays/Dialog.test.tsx +79 -0
- package/src/components/overlays/Dialog.tsx +158 -0
- package/src/components/overlays/Drawer.tsx +128 -0
- package/src/components/overlays/Dropdown.tsx +253 -0
- package/src/components/overlays/DropdownMenu.tsx +242 -0
- package/src/components/overlays/HoverCard.tsx +32 -0
- package/src/components/overlays/Modal.tsx +250 -0
- package/src/components/overlays/NotificationCenter.tsx +364 -0
- package/src/components/overlays/Popover.test.tsx +40 -0
- package/src/components/overlays/Popover.tsx +46 -0
- package/src/components/overlays/Sheet.tsx +163 -0
- package/src/components/overlays/Tooltip.test.tsx +33 -0
- package/src/components/overlays/Tooltip.tsx +32 -0
- package/src/components/overlays/index.ts +12 -0
- package/src/dates.ts +2 -0
- package/src/dnd.ts +1 -0
- package/src/forms.ts +1 -0
- package/src/globals.css +187 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useForm.ts +247 -0
- package/src/hooks/useMotionPreference.test.ts +102 -0
- package/src/hooks/useMotionPreference.ts +78 -0
- package/src/hooks/useTheme.ts +58 -0
- package/src/hooks.ts +9 -0
- package/src/index.ts +168 -0
- package/src/lib/animations.ts +356 -0
- package/src/lib/breadcrumbs.ts +94 -0
- package/src/lib/colors.ts +493 -0
- package/src/lib/store/customizer.ts +482 -0
- package/src/lib/store/index.ts +3 -0
- package/src/lib/store/theme.ts +55 -0
- package/src/lib/syntax-parser/index.ts +50 -0
- package/src/lib/syntax-parser/patterns.ts +64 -0
- package/src/lib/syntax-parser/tokenizer.ts +117 -0
- package/src/lib/syntax-parser/types.ts +27 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/validation.ts +204 -0
- package/src/lib/webgl/Color.ts +11 -0
- package/src/lib/webgl/Mesh.ts +41 -0
- package/src/lib/webgl/Program.ts +118 -0
- package/src/lib/webgl/Renderer.ts +51 -0
- package/src/lib/webgl/Triangle.ts +27 -0
- package/src/lib/webgl/Vec3.ts +18 -0
- package/src/lib/webgl/index.ts +13 -0
- package/src/nativewind-env.d.ts +1 -0
- package/src/providers/ThemeProvider.tsx +461 -0
- package/src/providers/index.ts +1 -0
- package/src/providers.ts +7 -0
- package/src/tables.ts +1 -0
- package/src/test/setup.ts +39 -0
- package/src/theme.css +158 -0
- package/src/tokens.ts +7 -0
- package/src/utils.ts +12 -0
- package/src/webgl.ts +1 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# @thesage/ui — AI Context
|
|
2
|
+
|
|
3
|
+
> 100 accessible React components | Radix UI + Tailwind CSS | 3 themes | TypeScript strict mode | MIT
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @thesage/ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Provider Hierarchy (Required)
|
|
12
|
+
|
|
13
|
+
Wrap your app root in this exact order:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers'
|
|
17
|
+
import { Toaster } from '@thesage/ui'
|
|
18
|
+
import '@thesage/ui/globals.css'
|
|
19
|
+
|
|
20
|
+
export default function RootLayout({ children }) {
|
|
21
|
+
return (
|
|
22
|
+
<ThemeProvider defaultTheme="studio" defaultMode="system">
|
|
23
|
+
<TooltipProvider>
|
|
24
|
+
{children}
|
|
25
|
+
<Toaster />
|
|
26
|
+
</TooltipProvider>
|
|
27
|
+
</ThemeProvider>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Import Patterns
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// Main exports (most common)
|
|
36
|
+
import { Button, Card, Input, Dialog, Badge } from '@thesage/ui'
|
|
37
|
+
|
|
38
|
+
// Subpath exports
|
|
39
|
+
import { useMotionPreference, useTheme } from '@thesage/ui/hooks'
|
|
40
|
+
import { ThemeProvider, TooltipProvider } from '@thesage/ui/providers'
|
|
41
|
+
import { cn } from '@thesage/ui/utils'
|
|
42
|
+
import { spacing, typography } from '@thesage/ui/tokens'
|
|
43
|
+
|
|
44
|
+
// Heavy/optional features (require peer dependencies)
|
|
45
|
+
import { Form, FormField, FormItem } from '@thesage/ui/forms' // react-hook-form + zod
|
|
46
|
+
import { Calendar, DatePicker } from '@thesage/ui/dates' // date-fns + react-day-picker
|
|
47
|
+
import { DataTable } from '@thesage/ui/tables' // @tanstack/react-table
|
|
48
|
+
import { DragDrop } from '@thesage/ui/dnd' // @dnd-kit/*
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Themes
|
|
52
|
+
|
|
53
|
+
Three themes, each with light and dark modes:
|
|
54
|
+
- **Studio** — Professional, balanced (default)
|
|
55
|
+
- **Terra** — Calm, organic, warm earth tones
|
|
56
|
+
- **Volt** — Bold, electric, cyberpunk neon
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { useTheme } from '@thesage/ui/hooks'
|
|
60
|
+
const { theme, setTheme, mode, setMode } = useTheme()
|
|
61
|
+
setTheme('volt')
|
|
62
|
+
setMode('dark')
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Styling Rules
|
|
66
|
+
|
|
67
|
+
- Use CSS variables: `bg-background`, `text-foreground`, `border-border`
|
|
68
|
+
- NEVER hardcode colors: no `bg-white`, `text-black`, `bg-neutral-100`
|
|
69
|
+
- All components accept `className` for Tailwind overrides
|
|
70
|
+
- Merge classes with `cn()`: `import { cn } from '@thesage/ui/utils'`
|
|
71
|
+
|
|
72
|
+
## Motion
|
|
73
|
+
|
|
74
|
+
Every animation MUST respect user preferences:
|
|
75
|
+
```tsx
|
|
76
|
+
import { useMotionPreference } from '@thesage/ui/hooks'
|
|
77
|
+
const { shouldAnimate, scale } = useMotionPreference()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Component Categories
|
|
81
|
+
|
|
82
|
+
| Category | Count | Import | Examples |
|
|
83
|
+
|----------|-------|--------|----------|
|
|
84
|
+
| Actions | 5 | `@thesage/ui` | Button, Toggle, ToggleGroup, Link, Magnetic |
|
|
85
|
+
| Forms | 18 | `@thesage/ui` | Input, Textarea, Select, Checkbox, Switch, Slider, Combobox, RadioGroup, Label, SearchBar |
|
|
86
|
+
| Navigation | 7 | `@thesage/ui` | Tabs, Breadcrumb, Pagination, NavigationMenu, Menubar, Command |
|
|
87
|
+
| Overlays | 8 | `@thesage/ui` | Dialog, AlertDialog, Popover, Tooltip, HoverCard, ContextMenu, DropdownMenu, Drawer |
|
|
88
|
+
| Feedback | 6 | `@thesage/ui` | Alert, Toaster/toast, Progress, Skeleton, Spinner |
|
|
89
|
+
| Data Display | 14 | `@thesage/ui` | Card, Badge, Avatar, Table, Carousel, AspectRatio, Collapsible, CodeBlock |
|
|
90
|
+
| Layout | 8 | `@thesage/ui` | Accordion, Separator, ScrollArea, ResizablePanel, Sheet |
|
|
91
|
+
| Features | 3 | `@thesage/ui` | CustomizerPanel, ThemeSwitcher |
|
|
92
|
+
|
|
93
|
+
## High-Frequency Component Quick Reference
|
|
94
|
+
|
|
95
|
+
### Button
|
|
96
|
+
```tsx
|
|
97
|
+
<Button variant="default|destructive|outline|secondary|ghost|link" size="sm|default|lg|icon">
|
|
98
|
+
Label
|
|
99
|
+
</Button>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Card
|
|
103
|
+
```tsx
|
|
104
|
+
<Card>
|
|
105
|
+
<CardHeader><CardTitle>Title</CardTitle><CardDescription>Desc</CardDescription></CardHeader>
|
|
106
|
+
<CardContent>Body</CardContent>
|
|
107
|
+
<CardFooter>Actions</CardFooter>
|
|
108
|
+
</Card>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Dialog
|
|
112
|
+
```tsx
|
|
113
|
+
<Dialog>
|
|
114
|
+
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
|
|
115
|
+
<DialogContent>
|
|
116
|
+
<DialogHeader><DialogTitle>Title</DialogTitle><DialogDescription>Desc</DialogDescription></DialogHeader>
|
|
117
|
+
Body
|
|
118
|
+
<DialogFooter><Button>Confirm</Button></DialogFooter>
|
|
119
|
+
</DialogContent>
|
|
120
|
+
</Dialog>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Input
|
|
124
|
+
```tsx
|
|
125
|
+
<Input type="email" placeholder="Enter email" disabled={false} />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Select
|
|
129
|
+
```tsx
|
|
130
|
+
<Select value={val} onValueChange={setVal}>
|
|
131
|
+
<SelectTrigger><SelectValue placeholder="Pick one" /></SelectTrigger>
|
|
132
|
+
<SelectContent>
|
|
133
|
+
<SelectItem value="a">Option A</SelectItem>
|
|
134
|
+
<SelectItem value="b">Option B</SelectItem>
|
|
135
|
+
</SelectContent>
|
|
136
|
+
</Select>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Tabs
|
|
140
|
+
```tsx
|
|
141
|
+
<Tabs defaultValue="tab1">
|
|
142
|
+
<TabsList>
|
|
143
|
+
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
144
|
+
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
145
|
+
</TabsList>
|
|
146
|
+
<TabsContent value="tab1">Content 1</TabsContent>
|
|
147
|
+
<TabsContent value="tab2">Content 2</TabsContent>
|
|
148
|
+
</Tabs>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Badge
|
|
152
|
+
```tsx
|
|
153
|
+
<Badge variant="default|secondary|destructive|outline">Label</Badge>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Alert
|
|
157
|
+
```tsx
|
|
158
|
+
<Alert variant="default|destructive">
|
|
159
|
+
<AlertTitle>Heading</AlertTitle>
|
|
160
|
+
<AlertDescription>Message</AlertDescription>
|
|
161
|
+
</Alert>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Form (react-hook-form integration)
|
|
165
|
+
```tsx
|
|
166
|
+
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@thesage/ui/forms'
|
|
167
|
+
|
|
168
|
+
<Form {...form}>
|
|
169
|
+
<FormField control={form.control} name="email" render={({ field }) => (
|
|
170
|
+
<FormItem>
|
|
171
|
+
<FormLabel>Email</FormLabel>
|
|
172
|
+
<FormControl><Input {...field} /></FormControl>
|
|
173
|
+
<FormMessage />
|
|
174
|
+
</FormItem>
|
|
175
|
+
)} />
|
|
176
|
+
</Form>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Bundle Size (minified + brotli)
|
|
180
|
+
|
|
181
|
+
| Entrypoint | Size | Peer Deps Required |
|
|
182
|
+
|------------|------|--------------------|
|
|
183
|
+
| `@thesage/ui` (core) | 146 KB | None |
|
|
184
|
+
| `@thesage/ui/dates` | 29 KB | date-fns, react-day-picker |
|
|
185
|
+
| `@thesage/ui/tokens` | 11 KB | None |
|
|
186
|
+
| `@thesage/ui/utils` | 10 KB | None |
|
|
187
|
+
| `@thesage/ui/forms` | 9 KB | react-hook-form, zod |
|
|
188
|
+
| `@thesage/ui/tables` | 8 KB | @tanstack/react-table |
|
|
189
|
+
| `@thesage/ui/dnd` | 8 KB | @dnd-kit/* |
|
|
190
|
+
| `@thesage/ui/providers` | 8 KB | None |
|
|
191
|
+
| `@thesage/ui/hooks` | 6 KB | None |
|
|
192
|
+
| `@thesage/ui/webgl` | 1 KB | framer-motion |
|
|
193
|
+
|
|
194
|
+
`sideEffects: false` enables tree-shaking. Heavy features isolated behind subpath exports.
|
|
195
|
+
|
|
196
|
+
## Third-Party Pairings
|
|
197
|
+
|
|
198
|
+
For gaps SDE doesn't cover, these libraries integrate well:
|
|
199
|
+
|
|
200
|
+
| Need | Library | Install |
|
|
201
|
+
|------|---------|---------|
|
|
202
|
+
| Rich Text Editor | Tiptap | `@tiptap/react @tiptap/starter-kit` |
|
|
203
|
+
| File Upload | react-dropzone | `react-dropzone` |
|
|
204
|
+
| Charts | Recharts | `recharts` |
|
|
205
|
+
| Color Picker | react-colorful | `react-colorful` |
|
|
206
|
+
| Markdown | react-markdown | `react-markdown remark-gfm` |
|
|
207
|
+
| Virtualized Lists | @tanstack/react-virtual | `@tanstack/react-virtual` |
|
|
208
|
+
| State Machines | XState | `xstate @xstate/react` |
|
|
209
|
+
|
|
210
|
+
**Already integrated as optional peer deps:** @tanstack/react-table (`/tables`), react-hook-form + zod (`/forms`), date-fns + react-day-picker (`/dates`), @dnd-kit (`/dnd`), framer-motion, lucide-react.
|
|
211
|
+
|
|
212
|
+
**Integration pattern:** Wrap in SDE Card/Dialog, use `cn()` for class merging, pull colors from CSS variables (`var(--color-primary)`) to stay theme-aware.
|
|
213
|
+
|
|
214
|
+
## Eject (Full Customization)
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npx @thesage/ui eject Button # copies to src/components/ui/Button.tsx
|
|
218
|
+
npx @thesage/ui eject Dialog --dir my/dir # custom target
|
|
219
|
+
npx @thesage/ui eject --list # list all components
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Imports are automatically rewritten:
|
|
223
|
+
- `../../lib/utils` → `./utils` (auto-scaffolded)
|
|
224
|
+
- `../../hooks/*` → `@thesage/ui/hooks`
|
|
225
|
+
- `../category/*` → `@thesage/ui`
|
|
226
|
+
|
|
227
|
+
Ejected components keep working with SDE themes and CSS variables. Also available via MCP tool `eject_component` and web UI at thesage.dev.
|
|
228
|
+
|
|
229
|
+
## Full API Reference
|
|
230
|
+
|
|
231
|
+
For complete props, variants, and examples for all 100 components:
|
|
232
|
+
- Web: https://thesage.dev/llms-full.txt
|
|
233
|
+
- MCP Server: `npx @thesage/mcp` (tools: list_components, search_components, get_component)
|
|
234
|
+
|
|
235
|
+
## Resources
|
|
236
|
+
|
|
237
|
+
- Docs: https://thesage.dev/docs
|
|
238
|
+
- GitHub: https://github.com/shalomormsby/sage-design-engine
|
|
239
|
+
- NPM: https://www.npmjs.com/package/@thesage/ui
|
package/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Sage Design Engine (@thesage/ui)
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@thesage/ui)
|
|
6
|
+
[](https://github.com/shalomormsby/sage-design-engine/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/@thesage/ui)
|
|
8
|
+
|
|
9
|
+
**Sage — Make it Lovable.**
|
|
10
|
+
|
|
11
|
+
Components that feel alive. Themes with real personality. Motion your users control. Designed for humans. Fluent with AI.
|
|
12
|
+
|
|
13
|
+
[Documentation](https://thesage.dev) | [Components](https://thesage.dev/components) | [GitHub](https://github.com/shalomormsby/sage-design-engine)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
**Sage Design Engine** is a component library and design system built on **Radix UI** primitives and **Tailwind CSS**. 100 accessible components across 11 functional categories, three distinct themes with runtime switching, and a user-controlled motion system — all wired through a 4-layer design token architecture.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Accessible by default** — Built on WAI-ARIA standards via Radix UI. Keyboard navigable, screen reader compatible, WCAG AA contrast.
|
|
24
|
+
- **Three themes, real personality** — Studio (professional), Terra (organic), Volt (electric). Runtime switching via CSS variables, light and dark modes each.
|
|
25
|
+
- **User-controlled motion** — A 0–10 intensity scale that respects `prefers-reduced-motion`. Intensity 0 works perfectly — no degraded experience.
|
|
26
|
+
- **Modular imports** — Core stays lean. Heavy features (forms, dates, tables, drag-and-drop, WebGL) ship as optional subpath exports — install only what you use.
|
|
27
|
+
- **Type safe** — Written in TypeScript with full type inference. React 19 ref-as-prop pattern throughout.
|
|
28
|
+
- **Design token system** — Colors, typography, spacing, motion, and syntax tokens. Change one primary color, everything updates.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @thesage/ui
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Sage requires **Tailwind CSS** as a styling engine:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm add -D tailwindcss@^3.4 postcss autoprefixer
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Optional subpath exports
|
|
43
|
+
|
|
44
|
+
Install peer dependencies only for the features you need:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Forms (react-hook-form + zod validation)
|
|
48
|
+
pnpm add react-hook-form @hookform/resolvers zod
|
|
49
|
+
|
|
50
|
+
# Date picker
|
|
51
|
+
pnpm add react-day-picker date-fns
|
|
52
|
+
|
|
53
|
+
# Data tables
|
|
54
|
+
pnpm add @tanstack/react-table
|
|
55
|
+
|
|
56
|
+
# Drag and drop
|
|
57
|
+
pnpm add @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Configure Tailwind
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
/** @type {import('tailwindcss').Config} */
|
|
64
|
+
module.exports = {
|
|
65
|
+
content: [
|
|
66
|
+
"./src/**/*.{ts,tsx}",
|
|
67
|
+
"./node_modules/@thesage/ui/dist/**/*.{js,ts,jsx,tsx}"
|
|
68
|
+
],
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Import styles
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import '@thesage/ui/globals.css';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { Button, Card, ThemeProvider } from '@thesage/ui';
|
|
82
|
+
|
|
83
|
+
export default function App() {
|
|
84
|
+
return (
|
|
85
|
+
<ThemeProvider theme="studio" defaultMode="system">
|
|
86
|
+
<Card className="max-w-md p-6">
|
|
87
|
+
<h3 className="mb-2 text-lg font-semibold">Welcome to Sage</h3>
|
|
88
|
+
<p className="mb-4 text-muted-foreground">
|
|
89
|
+
Build beautifully with components that feel premium out of the box.
|
|
90
|
+
</p>
|
|
91
|
+
<div className="flex gap-2">
|
|
92
|
+
<Button>Get Started</Button>
|
|
93
|
+
<Button variant="ghost">Documentation</Button>
|
|
94
|
+
</div>
|
|
95
|
+
</Card>
|
|
96
|
+
</ThemeProvider>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Subpath imports
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { useMotionPreference, useTheme } from '@thesage/ui/hooks'
|
|
105
|
+
import { ThemeProvider } from '@thesage/ui/providers'
|
|
106
|
+
import { cn } from '@thesage/ui/utils'
|
|
107
|
+
|
|
108
|
+
// Optional feature imports
|
|
109
|
+
import { Form, FormField } from '@thesage/ui/forms'
|
|
110
|
+
import { DatePicker } from '@thesage/ui/dates'
|
|
111
|
+
import { DataTable } from '@thesage/ui/tables'
|
|
112
|
+
import { SortableList } from '@thesage/ui/dnd'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Component categories
|
|
116
|
+
|
|
117
|
+
| Category | Examples |
|
|
118
|
+
|----------|----------|
|
|
119
|
+
| **Actions** | Button, Toggle, ToggleGroup |
|
|
120
|
+
| **Forms** | Input, Select, Checkbox, Switch, Slider, SearchBar |
|
|
121
|
+
| **Navigation** | Tabs, Menubar, Breadcrumb, Pagination, NavigationMenu |
|
|
122
|
+
| **Overlays** | Dialog, Sheet, Popover, Tooltip, ContextMenu, HoverCard |
|
|
123
|
+
| **Data Display** | Card, Avatar, Badge, Table, ScrollArea, Carousel |
|
|
124
|
+
| **Feedback** | Alert, Progress, Skeleton, Toast (Sonner) |
|
|
125
|
+
| **Layout** | Accordion, Separator, ResizablePanels, Collapsible |
|
|
126
|
+
| **Features** | Customizer, ThemeSwitcher |
|
|
127
|
+
|
|
128
|
+
## Eject — full customization
|
|
129
|
+
|
|
130
|
+
Need to deeply customize a component? Eject it into your project for full ownership:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx @thesage/ui eject Button
|
|
134
|
+
npx @thesage/ui eject Dialog --dir components/sage
|
|
135
|
+
npx @thesage/ui eject --list # see all available components
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
This copies the component source into your project with imports automatically rewritten. The ejected component still works with Sage themes and CSS variables — you just own the code now.
|
|
139
|
+
|
|
140
|
+
You can also eject from [thesage.dev](https://thesage.dev) — every component page has an **Eject** button that lets you copy or download the source directly.
|
|
141
|
+
|
|
142
|
+
## Bundle size
|
|
143
|
+
|
|
144
|
+
Core and optional entry points are independently tracked via [size-limit](https://github.com/ai/size-limit):
|
|
145
|
+
|
|
146
|
+
| Entry point | Brotli size |
|
|
147
|
+
|-------------|-------------|
|
|
148
|
+
| Core | ~146 KB |
|
|
149
|
+
| Hooks | ~40 KB |
|
|
150
|
+
| Providers | ~60 KB |
|
|
151
|
+
| Tokens | ~70 KB |
|
|
152
|
+
| Utils | ~25 KB |
|
|
153
|
+
| Forms | ~9.4 KB |
|
|
154
|
+
| Dates | ~29 KB |
|
|
155
|
+
| Tables | ~8.3 KB |
|
|
156
|
+
| DnD | ~8.3 KB |
|
|
157
|
+
| WebGL | ~1.1 KB |
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT © [Shalom Ormsby](https://github.com/shalomormsby)
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, dirname, resolve } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
var __filename_ = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
|
|
8
|
+
var PKG_ROOT = resolve(dirname(__filename_), "..");
|
|
9
|
+
function transformImports(source) {
|
|
10
|
+
return source.replace(/from\s+['"]\.\.\/\.\.\/lib\/utils['"]/g, `from './utils'`).replace(/from\s+['"]\.\.\/\.\.\/lib\/[^'"]+['"]/g, `from '@opencosmos/ui/utils'`).replace(/from\s+['"]\.\.\/\.\.\/hooks\/[^'"]+['"]/g, `from '@opencosmos/ui/hooks'`).replace(/from\s+['"]\.\.\/[^.][^'"]*['"]/g, `from '@opencosmos/ui'`);
|
|
11
|
+
}
|
|
12
|
+
var CN_UTILS_SOURCE = `import { type ClassValue, clsx } from "clsx";
|
|
13
|
+
import { twMerge } from "tailwind-merge";
|
|
14
|
+
|
|
15
|
+
export function cn(...inputs: ClassValue[]) {
|
|
16
|
+
return twMerge(clsx(inputs));
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
function findComponent(name) {
|
|
20
|
+
const srcDir = join(PKG_ROOT, "src", "components");
|
|
21
|
+
if (!existsSync(srcDir)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const lowerName = name.toLowerCase();
|
|
25
|
+
for (const category of readdirSync(srcDir)) {
|
|
26
|
+
const categoryPath = join(srcDir, category);
|
|
27
|
+
if (!statSync(categoryPath).isDirectory()) continue;
|
|
28
|
+
for (const file of readdirSync(categoryPath)) {
|
|
29
|
+
if (file.toLowerCase() === `${lowerName}.tsx` || file.toLowerCase() === `${lowerName}.ts`) {
|
|
30
|
+
return { filePath: join(categoryPath, file), category };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function listComponents() {
|
|
37
|
+
const srcDir = join(PKG_ROOT, "src", "components");
|
|
38
|
+
if (!existsSync(srcDir)) {
|
|
39
|
+
console.error("Error: Could not find component source directory.");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.log("\n @opencosmos/ui \u2014 Available Components\n");
|
|
43
|
+
for (const category of readdirSync(srcDir).sort()) {
|
|
44
|
+
const categoryPath = join(srcDir, category);
|
|
45
|
+
if (!statSync(categoryPath).isDirectory()) continue;
|
|
46
|
+
const components = readdirSync(categoryPath).filter((f) => f.endsWith(".tsx") && !f.startsWith("index") && !f.includes(".test.")).map((f) => f.replace(/\.tsx$/, ""));
|
|
47
|
+
if (components.length === 0) continue;
|
|
48
|
+
console.log(` ${category}/`);
|
|
49
|
+
for (const comp of components.sort()) {
|
|
50
|
+
console.log(` ${comp}`);
|
|
51
|
+
}
|
|
52
|
+
console.log();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function ejectComponent(name, targetDir) {
|
|
56
|
+
const found = findComponent(name);
|
|
57
|
+
if (!found) {
|
|
58
|
+
console.error(`
|
|
59
|
+
Error: Component "${name}" not found.
|
|
60
|
+
`);
|
|
61
|
+
console.error(" Run `npx @opencosmos/ui eject --list` to see available components.\n");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
const source = readFileSync(found.filePath, "utf-8");
|
|
65
|
+
const transformed = transformImports(source);
|
|
66
|
+
const resolvedDir = resolve(process.cwd(), targetDir);
|
|
67
|
+
mkdirSync(resolvedDir, { recursive: true });
|
|
68
|
+
const fileName = found.filePath.split("/").pop();
|
|
69
|
+
const destPath = join(resolvedDir, fileName);
|
|
70
|
+
writeFileSync(destPath, transformed, "utf-8");
|
|
71
|
+
const utilsPath = join(resolvedDir, "utils.ts");
|
|
72
|
+
if (!existsSync(utilsPath)) {
|
|
73
|
+
writeFileSync(utilsPath, CN_UTILS_SOURCE, "utf-8");
|
|
74
|
+
}
|
|
75
|
+
const deps = /* @__PURE__ */ new Set();
|
|
76
|
+
const importRegex = /from\s+['"](@[^/'"]+\/[^'"]+|[^.@/'"][^'"]*)['"]/g;
|
|
77
|
+
let match;
|
|
78
|
+
while ((match = importRegex.exec(source)) !== null) {
|
|
79
|
+
const pkg = match[1];
|
|
80
|
+
if (pkg.startsWith("@opencosmos/") || pkg === "react") continue;
|
|
81
|
+
const pkgName = pkg.startsWith("@") ? pkg.split("/").slice(0, 2).join("/") : pkg.split("/")[0];
|
|
82
|
+
deps.add(pkgName);
|
|
83
|
+
}
|
|
84
|
+
console.log(`
|
|
85
|
+
Ejected ${name} successfully!
|
|
86
|
+
`);
|
|
87
|
+
console.log(` ${destPath}`);
|
|
88
|
+
if (!existsSync(join(resolvedDir, "utils.ts"))) {
|
|
89
|
+
}
|
|
90
|
+
console.log(` ${utilsPath} (cn utility)
|
|
91
|
+
`);
|
|
92
|
+
if (deps.size > 0) {
|
|
93
|
+
console.log(" Required dependencies:");
|
|
94
|
+
console.log(` pnpm add ${[...deps].sort().join(" ")}
|
|
95
|
+
`);
|
|
96
|
+
}
|
|
97
|
+
console.log(" Update your imports:");
|
|
98
|
+
console.log(` import { ${name} } from './${targetDir}/${name}'
|
|
99
|
+
`);
|
|
100
|
+
console.log(" The ejected component still works with @opencosmos/ui themes and CSS variables.");
|
|
101
|
+
console.log(" You now own it \u2014 modify freely.\n");
|
|
102
|
+
}
|
|
103
|
+
function main() {
|
|
104
|
+
const args = process.argv.slice(2);
|
|
105
|
+
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
106
|
+
console.log(`
|
|
107
|
+
@opencosmos/ui eject \u2014 Copy component source into your project
|
|
108
|
+
|
|
109
|
+
Usage:
|
|
110
|
+
npx @opencosmos/ui eject <ComponentName> [--dir <path>]
|
|
111
|
+
npx @opencosmos/ui eject --list
|
|
112
|
+
|
|
113
|
+
Options:
|
|
114
|
+
--dir <path> Target directory (default: src/components/ui)
|
|
115
|
+
--list List all available components
|
|
116
|
+
--help Show this help message
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
npx @opencosmos/ui eject Button
|
|
120
|
+
npx @opencosmos/ui eject Dialog --dir components/sage
|
|
121
|
+
`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (args.includes("--list")) {
|
|
125
|
+
listComponents();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const command = args[0];
|
|
129
|
+
if (command !== "eject") {
|
|
130
|
+
console.error(`
|
|
131
|
+
Unknown command: ${command}
|
|
132
|
+
Run with --help for usage.
|
|
133
|
+
`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const componentName = args[1];
|
|
137
|
+
if (!componentName || componentName.startsWith("--")) {
|
|
138
|
+
console.error("\n Error: Component name is required.\n Usage: npx @opencosmos/ui eject <ComponentName>\n");
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
let targetDir = "src/components/ui";
|
|
142
|
+
const dirIdx = args.indexOf("--dir");
|
|
143
|
+
if (dirIdx !== -1 && args[dirIdx + 1]) {
|
|
144
|
+
targetDir = args[dirIdx + 1];
|
|
145
|
+
}
|
|
146
|
+
ejectComponent(componentName, targetDir);
|
|
147
|
+
}
|
|
148
|
+
main();
|
|
149
|
+
export {
|
|
150
|
+
transformImports
|
|
151
|
+
};
|
package/dist/dates.d.mts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { DayPicker } from 'react-day-picker';
|
|
4
|
+
|
|
5
|
+
type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
|
6
|
+
declare function Calendar({ className, classNames, showOutsideDays, ...props }: CalendarProps): react_jsx_runtime.JSX.Element;
|
|
7
|
+
declare namespace Calendar {
|
|
8
|
+
var displayName: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface DatePickerProps {
|
|
12
|
+
date?: Date;
|
|
13
|
+
onDateChange?: (date: Date | undefined) => void;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare function DatePicker({ date, onDateChange, placeholder, className, disabled, }: DatePickerProps): react_jsx_runtime.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { Calendar, type CalendarProps, DatePicker, type DatePickerProps };
|
package/dist/dates.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { DayPicker } from 'react-day-picker';
|
|
4
|
+
|
|
5
|
+
type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
|
6
|
+
declare function Calendar({ className, classNames, showOutsideDays, ...props }: CalendarProps): react_jsx_runtime.JSX.Element;
|
|
7
|
+
declare namespace Calendar {
|
|
8
|
+
var displayName: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface DatePickerProps {
|
|
12
|
+
date?: Date;
|
|
13
|
+
onDateChange?: (date: Date | undefined) => void;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare function DatePicker({ date, onDateChange, placeholder, className, disabled, }: DatePickerProps): react_jsx_runtime.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { Calendar, type CalendarProps, DatePicker, type DatePickerProps };
|