@object-ui/components 0.3.0
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/CHANGELOG.md +46 -0
- package/LICENSE +21 -0
- package/README.md +170 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +46186 -0
- package/dist/index.umd.cjs +92 -0
- package/dist/src/hooks/use-mobile.d.ts +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.test.d.ts +1 -0
- package/dist/src/lib/utils.d.ts +4 -0
- package/dist/src/new-components.test.d.ts +1 -0
- package/dist/src/renderers/basic/div.d.ts +1 -0
- package/dist/src/renderers/basic/html.d.ts +1 -0
- package/dist/src/renderers/basic/icon.d.ts +1 -0
- package/dist/src/renderers/basic/image.d.ts +1 -0
- package/dist/src/renderers/basic/index.d.ts +0 -0
- package/dist/src/renderers/basic/separator.d.ts +1 -0
- package/dist/src/renderers/basic/span.d.ts +1 -0
- package/dist/src/renderers/basic/text.d.ts +1 -0
- package/dist/src/renderers/complex/__tests__/data-table.test.d.ts +0 -0
- package/dist/src/renderers/complex/calendar-view.d.ts +1 -0
- package/dist/src/renderers/complex/carousel.d.ts +1 -0
- package/dist/src/renderers/complex/chatbot.d.ts +1 -0
- package/dist/src/renderers/complex/chatbot.test.d.ts +1 -0
- package/dist/src/renderers/complex/data-table.d.ts +1 -0
- package/dist/src/renderers/complex/filter-builder.d.ts +1 -0
- package/dist/src/renderers/complex/index.d.ts +0 -0
- package/dist/src/renderers/complex/resizable.d.ts +1 -0
- package/dist/src/renderers/complex/scroll-area.d.ts +1 -0
- package/dist/src/renderers/complex/table.d.ts +1 -0
- package/dist/src/renderers/complex/timeline.d.ts +1 -0
- package/dist/src/renderers/data-display/alert.d.ts +1 -0
- package/dist/src/renderers/data-display/avatar.d.ts +1 -0
- package/dist/src/renderers/data-display/badge.d.ts +1 -0
- package/dist/src/renderers/data-display/index.d.ts +0 -0
- package/dist/src/renderers/data-display/list.d.ts +1 -0
- package/dist/src/renderers/data-display/statistic.d.ts +1 -0
- package/dist/src/renderers/data-display/tree-view.d.ts +1 -0
- package/dist/src/renderers/disclosure/accordion.d.ts +1 -0
- package/dist/src/renderers/disclosure/collapsible.d.ts +1 -0
- package/dist/src/renderers/disclosure/index.d.ts +0 -0
- package/dist/src/renderers/feedback/index.d.ts +0 -0
- package/dist/src/renderers/feedback/loading.d.ts +1 -0
- package/dist/src/renderers/feedback/progress.d.ts +1 -0
- package/dist/src/renderers/feedback/skeleton.d.ts +1 -0
- package/dist/src/renderers/feedback/toaster.d.ts +1 -0
- package/dist/src/renderers/form/button.d.ts +1 -0
- package/dist/src/renderers/form/calendar.d.ts +1 -0
- package/dist/src/renderers/form/checkbox.d.ts +1 -0
- package/dist/src/renderers/form/date-picker.d.ts +1 -0
- package/dist/src/renderers/form/file-upload.d.ts +1 -0
- package/dist/src/renderers/form/form.d.ts +1 -0
- package/dist/src/renderers/form/index.d.ts +0 -0
- package/dist/src/renderers/form/input-otp.d.ts +1 -0
- package/dist/src/renderers/form/input.d.ts +1 -0
- package/dist/src/renderers/form/label.d.ts +1 -0
- package/dist/src/renderers/form/radio-group.d.ts +1 -0
- package/dist/src/renderers/form/select.d.ts +1 -0
- package/dist/src/renderers/form/slider.d.ts +1 -0
- package/dist/src/renderers/form/switch.d.ts +1 -0
- package/dist/src/renderers/form/textarea.d.ts +1 -0
- package/dist/src/renderers/form/toggle.d.ts +1 -0
- package/dist/src/renderers/index.d.ts +0 -0
- package/dist/src/renderers/layout/card.d.ts +1 -0
- package/dist/src/renderers/layout/container.d.ts +1 -0
- package/dist/src/renderers/layout/flex.d.ts +1 -0
- package/dist/src/renderers/layout/grid.d.ts +1 -0
- package/dist/src/renderers/layout/index.d.ts +0 -0
- package/dist/src/renderers/layout/page.d.ts +7 -0
- package/dist/src/renderers/layout/semantic.d.ts +1 -0
- package/dist/src/renderers/layout/stack.d.ts +1 -0
- package/dist/src/renderers/layout/tabs.d.ts +1 -0
- package/dist/src/renderers/navigation/header-bar.d.ts +1 -0
- package/dist/src/renderers/navigation/index.d.ts +0 -0
- package/dist/src/renderers/navigation/sidebar.d.ts +1 -0
- package/dist/src/renderers/overlay/alert-dialog.d.ts +1 -0
- package/dist/src/renderers/overlay/context-menu.d.ts +1 -0
- package/dist/src/renderers/overlay/dialog.d.ts +1 -0
- package/dist/src/renderers/overlay/drawer.d.ts +1 -0
- package/dist/src/renderers/overlay/dropdown-menu.d.ts +1 -0
- package/dist/src/renderers/overlay/hover-card.d.ts +1 -0
- package/dist/src/renderers/overlay/index.d.ts +0 -0
- package/dist/src/renderers/overlay/popover.d.ts +1 -0
- package/dist/src/renderers/overlay/sheet.d.ts +1 -0
- package/dist/src/renderers/overlay/tooltip.d.ts +1 -0
- package/dist/src/ui/accordion.d.ts +7 -0
- package/dist/src/ui/alert-dialog.d.ts +14 -0
- package/dist/src/ui/alert.d.ts +9 -0
- package/dist/src/ui/aspect-ratio.d.ts +3 -0
- package/dist/src/ui/avatar.d.ts +6 -0
- package/dist/src/ui/badge.d.ts +9 -0
- package/dist/src/ui/breadcrumb.d.ts +11 -0
- package/dist/src/ui/button-group.d.ts +11 -0
- package/dist/src/ui/button.d.ts +13 -0
- package/dist/src/ui/calendar-view.d.ts +21 -0
- package/dist/src/ui/calendar.d.ts +8 -0
- package/dist/src/ui/card.d.ts +9 -0
- package/dist/src/ui/carousel.d.ts +19 -0
- package/dist/src/ui/chatbot.d.ts +36 -0
- package/dist/src/ui/checkbox.d.ts +4 -0
- package/dist/src/ui/collapsible.d.ts +5 -0
- package/dist/src/ui/command.d.ts +18 -0
- package/dist/src/ui/context-menu.d.ts +25 -0
- package/dist/src/ui/dialog.d.ts +15 -0
- package/dist/src/ui/drawer.d.ts +13 -0
- package/dist/src/ui/dropdown-menu.d.ts +25 -0
- package/dist/src/ui/empty.d.ts +11 -0
- package/dist/src/ui/field.d.ts +24 -0
- package/dist/src/ui/filter-builder.d.ts +31 -0
- package/dist/src/ui/form.d.ts +24 -0
- package/dist/src/ui/hover-card.d.ts +6 -0
- package/dist/src/ui/index.d.ts +56 -0
- package/dist/src/ui/input-group.d.ts +16 -0
- package/dist/src/ui/input-otp.d.ts +11 -0
- package/dist/src/ui/input.d.ts +3 -0
- package/dist/src/ui/item.d.ts +23 -0
- package/dist/src/ui/kbd.d.ts +3 -0
- package/dist/src/ui/label.d.ts +4 -0
- package/dist/src/ui/menubar.d.ts +26 -0
- package/dist/src/ui/navigation-menu.d.ts +14 -0
- package/dist/src/ui/pagination.d.ts +13 -0
- package/dist/src/ui/popover.d.ts +7 -0
- package/dist/src/ui/progress.d.ts +4 -0
- package/dist/src/ui/radio-group.d.ts +5 -0
- package/dist/src/ui/resizable.d.ts +10 -0
- package/dist/src/ui/scroll-area.d.ts +5 -0
- package/dist/src/ui/select.d.ts +15 -0
- package/dist/src/ui/separator.d.ts +4 -0
- package/dist/src/ui/sheet.d.ts +13 -0
- package/dist/src/ui/sidebar.d.ts +69 -0
- package/dist/src/ui/skeleton.d.ts +2 -0
- package/dist/src/ui/slider.d.ts +4 -0
- package/dist/src/ui/sonner.d.ts +3 -0
- package/dist/src/ui/spinner.d.ts +3 -0
- package/dist/src/ui/switch.d.ts +4 -0
- package/dist/src/ui/table.d.ts +10 -0
- package/dist/src/ui/tabs.d.ts +7 -0
- package/dist/src/ui/textarea.d.ts +3 -0
- package/dist/src/ui/timeline.d.ts +25 -0
- package/dist/src/ui/toggle-group.d.ts +9 -0
- package/dist/src/ui/toggle.d.ts +9 -0
- package/dist/src/ui/tooltip.d.ts +7 -0
- package/docs/FilterBuilder.md +268 -0
- package/metadata/Chart.component.yml +30 -0
- package/metadata/FilterBuilder.component.yml +39 -0
- package/metadata/GridLayout.component.yml +27 -0
- package/metadata/Menu.component.yml +31 -0
- package/metadata/ObjectForm.component.yml +34 -0
- package/metadata/ObjectTable.component.yml +41 -0
- package/metadata/Page.component.yml +24 -0
- package/package.json +87 -0
- package/postcss.config.js +6 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/index.css +76 -0
- package/src/index.test.ts +7 -0
- package/src/index.ts +10 -0
- package/src/lib/utils.tsx +27 -0
- package/src/new-components.test.ts +74 -0
- package/src/renderers/basic/div.tsx +41 -0
- package/src/renderers/basic/html.tsx +34 -0
- package/src/renderers/basic/icon.tsx +25 -0
- package/src/renderers/basic/image.tsx +37 -0
- package/src/renderers/basic/index.ts +7 -0
- package/src/renderers/basic/separator.tsx +48 -0
- package/src/renderers/basic/span.tsx +44 -0
- package/src/renderers/basic/text.tsx +42 -0
- package/src/renderers/complex/README-KANBAN.md +208 -0
- package/src/renderers/complex/TIMELINE.md +353 -0
- package/src/renderers/complex/__tests__/data-table.test.ts +52 -0
- package/src/renderers/complex/calendar-view.tsx +219 -0
- package/src/renderers/complex/carousel.tsx +60 -0
- package/src/renderers/complex/chatbot.test.ts +44 -0
- package/src/renderers/complex/chatbot.tsx +185 -0
- package/src/renderers/complex/data-table.tsx +650 -0
- package/src/renderers/complex/filter-builder.tsx +68 -0
- package/src/renderers/complex/index.ts +10 -0
- package/src/renderers/complex/resizable.tsx +54 -0
- package/src/renderers/complex/scroll-area.tsx +32 -0
- package/src/renderers/complex/table.tsx +86 -0
- package/src/renderers/complex/timeline.tsx +466 -0
- package/src/renderers/data-display/alert.tsx +37 -0
- package/src/renderers/data-display/avatar.tsx +29 -0
- package/src/renderers/data-display/badge.tsx +46 -0
- package/src/renderers/data-display/index.ts +6 -0
- package/src/renderers/data-display/list.tsx +95 -0
- package/src/renderers/data-display/statistic.tsx +98 -0
- package/src/renderers/data-display/tree-view.tsx +180 -0
- package/src/renderers/disclosure/accordion.tsx +60 -0
- package/src/renderers/disclosure/collapsible.tsx +44 -0
- package/src/renderers/disclosure/index.ts +2 -0
- package/src/renderers/feedback/index.ts +4 -0
- package/src/renderers/feedback/loading.tsx +69 -0
- package/src/renderers/feedback/progress.tsx +20 -0
- package/src/renderers/feedback/skeleton.tsx +22 -0
- package/src/renderers/feedback/toaster.tsx +26 -0
- package/src/renderers/form/button.tsx +61 -0
- package/src/renderers/form/calendar.tsx +25 -0
- package/src/renderers/form/checkbox.tsx +41 -0
- package/src/renderers/form/date-picker.tsx +75 -0
- package/src/renderers/form/file-upload.tsx +175 -0
- package/src/renderers/form/form.tsx +417 -0
- package/src/renderers/form/index.ts +16 -0
- package/src/renderers/form/input-otp.tsx +31 -0
- package/src/renderers/form/input.tsx +79 -0
- package/src/renderers/form/label.tsx +36 -0
- package/src/renderers/form/radio-group.tsx +54 -0
- package/src/renderers/form/select.tsx +66 -0
- package/src/renderers/form/slider.tsx +45 -0
- package/src/renderers/form/switch.tsx +39 -0
- package/src/renderers/form/textarea.tsx +45 -0
- package/src/renderers/form/toggle.tsx +76 -0
- package/src/renderers/index.ts +9 -0
- package/src/renderers/layout/card.tsx +69 -0
- package/src/renderers/layout/container.tsx +113 -0
- package/src/renderers/layout/flex.tsx +123 -0
- package/src/renderers/layout/grid.tsx +155 -0
- package/src/renderers/layout/index.ts +10 -0
- package/src/renderers/layout/page.tsx +82 -0
- package/src/renderers/layout/semantic.tsx +39 -0
- package/src/renderers/layout/stack.tsx +123 -0
- package/src/renderers/layout/tabs.tsx +63 -0
- package/src/renderers/navigation/header-bar.tsx +50 -0
- package/src/renderers/navigation/index.ts +2 -0
- package/src/renderers/navigation/sidebar.tsx +189 -0
- package/src/renderers/overlay/alert-dialog.tsx +63 -0
- package/src/renderers/overlay/context-menu.tsx +91 -0
- package/src/renderers/overlay/dialog.tsx +68 -0
- package/src/renderers/overlay/drawer.tsx +68 -0
- package/src/renderers/overlay/dropdown-menu.tsx +90 -0
- package/src/renderers/overlay/hover-card.tsx +46 -0
- package/src/renderers/overlay/index.ts +9 -0
- package/src/renderers/overlay/popover.tsx +47 -0
- package/src/renderers/overlay/sheet.tsx +68 -0
- package/src/renderers/overlay/tooltip.tsx +58 -0
- package/src/ui/accordion.tsx +64 -0
- package/src/ui/alert-dialog.tsx +155 -0
- package/src/ui/alert.tsx +78 -0
- package/src/ui/aspect-ratio.tsx +11 -0
- package/src/ui/avatar.tsx +51 -0
- package/src/ui/badge.tsx +46 -0
- package/src/ui/breadcrumb.tsx +109 -0
- package/src/ui/button-group.tsx +83 -0
- package/src/ui/button.tsx +65 -0
- package/src/ui/calendar-view.tsx +503 -0
- package/src/ui/calendar.tsx +237 -0
- package/src/ui/card.tsx +138 -0
- package/src/ui/carousel.tsx +239 -0
- package/src/ui/chatbot.tsx +240 -0
- package/src/ui/checkbox.tsx +32 -0
- package/src/ui/collapsible.tsx +31 -0
- package/src/ui/command.tsx +182 -0
- package/src/ui/context-menu.tsx +247 -0
- package/src/ui/dialog.tsx +141 -0
- package/src/ui/drawer.tsx +135 -0
- package/src/ui/dropdown-menu.tsx +254 -0
- package/src/ui/empty.tsx +104 -0
- package/src/ui/field.tsx +246 -0
- package/src/ui/filter-builder.tsx +359 -0
- package/src/ui/form.tsx +167 -0
- package/src/ui/hover-card.tsx +44 -0
- package/src/ui/index.ts +56 -0
- package/src/ui/input-group.tsx +170 -0
- package/src/ui/input-otp.tsx +81 -0
- package/src/ui/input.tsx +24 -0
- package/src/ui/item.tsx +193 -0
- package/src/ui/kbd.tsx +28 -0
- package/src/ui/label.tsx +24 -0
- package/src/ui/menubar.tsx +274 -0
- package/src/ui/navigation-menu.tsx +168 -0
- package/src/ui/pagination.tsx +127 -0
- package/src/ui/popover.tsx +48 -0
- package/src/ui/progress.tsx +41 -0
- package/src/ui/radio-group.tsx +45 -0
- package/src/ui/resizable.tsx +55 -0
- package/src/ui/scroll-area.tsx +58 -0
- package/src/ui/select.tsx +188 -0
- package/src/ui/separator.tsx +31 -0
- package/src/ui/sheet.tsx +137 -0
- package/src/ui/sidebar.tsx +726 -0
- package/src/ui/skeleton.tsx +20 -0
- package/src/ui/slider.tsx +63 -0
- package/src/ui/sonner.tsx +43 -0
- package/src/ui/spinner.tsx +38 -0
- package/src/ui/switch.tsx +31 -0
- package/src/ui/table.tsx +120 -0
- package/src/ui/tabs.tsx +86 -0
- package/src/ui/textarea.tsx +18 -0
- package/src/ui/timeline.tsx +266 -0
- package/src/ui/toggle-group.tsx +87 -0
- package/src/ui/toggle.tsx +50 -0
- package/src/ui/tooltip.tsx +61 -0
- package/tailwind.config.js +75 -0
- package/tsconfig.json +18 -0
- package/vite.config.ts +44 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cn } from "../lib/utils"
|
|
2
|
+
|
|
3
|
+
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
4
|
+
return (
|
|
5
|
+
<div
|
|
6
|
+
data-slot="skeleton"
|
|
7
|
+
className={cn(
|
|
8
|
+
"relative overflow-hidden rounded-md bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm",
|
|
9
|
+
"after:absolute after:inset-0 after:-translate-x-full after:animate-[shimmer_1.5s_infinite] after:bg-linear-to-r after:from-transparent after:via-cyan-900/20 after:to-transparent",
|
|
10
|
+
className
|
|
11
|
+
)}
|
|
12
|
+
{...props}
|
|
13
|
+
>
|
|
14
|
+
{/* Optional tech pattern overlay for large skeletons */}
|
|
15
|
+
<div className="absolute inset-0 bg-[linear-gradient(45deg,transparent_25%,rgba(6,182,212,0.02)_50%,transparent_75%,transparent_100%)] bg-[size:8px_8px] opacity-50" />
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { Skeleton }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SliderPrimitive from "@radix-ui/react-slider"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
|
|
8
|
+
function Slider({
|
|
9
|
+
className,
|
|
10
|
+
defaultValue,
|
|
11
|
+
value,
|
|
12
|
+
min = 0,
|
|
13
|
+
max = 100,
|
|
14
|
+
...props
|
|
15
|
+
}: React.ComponentProps<typeof SliderPrimitive.Root>) {
|
|
16
|
+
const _values = React.useMemo(
|
|
17
|
+
() =>
|
|
18
|
+
Array.isArray(value)
|
|
19
|
+
? value
|
|
20
|
+
: Array.isArray(defaultValue)
|
|
21
|
+
? defaultValue
|
|
22
|
+
: [min, max],
|
|
23
|
+
[value, defaultValue, min, max]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<SliderPrimitive.Root
|
|
28
|
+
data-slot="slider"
|
|
29
|
+
defaultValue={defaultValue}
|
|
30
|
+
value={value}
|
|
31
|
+
min={min}
|
|
32
|
+
max={max}
|
|
33
|
+
className={cn(
|
|
34
|
+
"relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
|
|
35
|
+
className
|
|
36
|
+
)}
|
|
37
|
+
{...props}
|
|
38
|
+
>
|
|
39
|
+
<SliderPrimitive.Track
|
|
40
|
+
data-slot="slider-track"
|
|
41
|
+
className={cn(
|
|
42
|
+
"bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
|
|
43
|
+
)}
|
|
44
|
+
>
|
|
45
|
+
<SliderPrimitive.Range
|
|
46
|
+
data-slot="slider-range"
|
|
47
|
+
className={cn(
|
|
48
|
+
"bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
|
|
49
|
+
)}
|
|
50
|
+
/>
|
|
51
|
+
</SliderPrimitive.Track>
|
|
52
|
+
{Array.from({ length: _values.length }, (_, index) => (
|
|
53
|
+
<SliderPrimitive.Thumb
|
|
54
|
+
data-slot="slider-thumb"
|
|
55
|
+
key={index}
|
|
56
|
+
className="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
|
|
57
|
+
/>
|
|
58
|
+
))}
|
|
59
|
+
</SliderPrimitive.Root>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { Slider }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CircleCheckIcon,
|
|
3
|
+
InfoIcon,
|
|
4
|
+
Loader2Icon,
|
|
5
|
+
OctagonXIcon,
|
|
6
|
+
TriangleAlertIcon,
|
|
7
|
+
} from "lucide-react"
|
|
8
|
+
import { useTheme } from "next-themes"
|
|
9
|
+
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
|
10
|
+
|
|
11
|
+
const Toaster = ({ ...props }: ToasterProps) => {
|
|
12
|
+
const { theme = "system" } = useTheme()
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Sonner
|
|
16
|
+
theme={theme as ToasterProps["theme"]}
|
|
17
|
+
className="toaster group"
|
|
18
|
+
toastOptions={{
|
|
19
|
+
classNames: {
|
|
20
|
+
toast:
|
|
21
|
+
"group toast group-[.toaster]:bg-slate-950/90 group-[.toaster]:backdrop-blur-xl group-[.toaster]:text-cyan-100 group-[.toaster]:border-slate-800 group-[.toaster]:shadow-[0_0_30px_-10px_rgba(0,0,0,0.5)] transition-all duration-30 data-[type=success]:border-emerald-500/50 data-[type=success]:shadow-[0_0_20px_-5px_rgba(16,185,129,0.2)] data-[type=error]:border-red-500/50 data-[type=error]:shadow-[0_0_20px_-5px_rgba(239,68,68,0.2)] data-[type=info]:border-cyan-500/50 data-[type=info]:shadow-[0_0_20px_-5px_rgba(6,182,212,0.2)] data-[type=warning]:border-amber-500/50 data-[type=warning]:shadow-[0_0_20px_-5px_rgba(245,158,11,0.2)]",
|
|
22
|
+
description: "group-[.toast]:text-slate-400 group-[.toast]:font-mono group-[.toast]:text-xs",
|
|
23
|
+
actionButton:
|
|
24
|
+
"group-[.toast]:bg-cyan-600 group-[.toast]:text-white group-[.toast]:font-bold group-[.toast]:rounded-sm group-[.toast]:shadow-[0_0_10px_cyan]",
|
|
25
|
+
cancelButton:
|
|
26
|
+
"group-[.toast]:bg-slate-800 group-[.toast]:text-slate-400 group-[.toast]:rounded-sm",
|
|
27
|
+
title: "group-[.toast]:font-mono group-[.toast]:uppercase group-[.toast]:tracking-widest group-[.toast]:font-bold group-[.toast]:text-cyan-300 group-[.toast]:text-xs group-[.toast]:data-[type=error]:text-red-400 group-[.toast]:data-[type=success]:text-emerald-400",
|
|
28
|
+
icon: "group-[.toast]:data-[type=success]:text-emerald-400 group-[.toast]:data-[type=error]:text-red-400 group-[.toast]:data-[type=info]:text-cyan-400 group-[.toast]:data-[type=warning]:text-amber-400",
|
|
29
|
+
},
|
|
30
|
+
}}
|
|
31
|
+
icons={{
|
|
32
|
+
success: <CircleCheckIcon className="size-5 drop-shadow-[0_0_8px_rgba(16,185,129,0.5)]" />,
|
|
33
|
+
info: <InfoIcon className="size-5 drop-shadow-[0_0_8px_rgba(6,182,212,0.5)]" />,
|
|
34
|
+
warning: <TriangleAlertIcon className="size-5 drop-shadow-[0_0_8px_rgba(245,158,11,0.5)]" />,
|
|
35
|
+
error: <OctagonXIcon className="size-5 drop-shadow-[0_0_8px_rgba(239,68,68,0.5)]" />,
|
|
36
|
+
loading: <Loader2Icon className="size-5 animate-spin text-cyan-500" />,
|
|
37
|
+
}}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { Toaster }
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cn } from "../lib/utils"
|
|
3
|
+
|
|
4
|
+
function Spinner({ className, ...props }: React.ComponentProps<"div">) {
|
|
5
|
+
return (
|
|
6
|
+
<div
|
|
7
|
+
role="status"
|
|
8
|
+
aria-label="Loading"
|
|
9
|
+
className={cn("relative flex items-center justify-center shrink-0", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
>
|
|
12
|
+
<div className="relative aspect-square h-full w-full min-w-[1em] min-h-[1em]">
|
|
13
|
+
{/* Outer Atmosphere / Fire (Fast Spin) */}
|
|
14
|
+
<div className="absolute inset-0 rounded-full border-[15%] border-transparent border-t-orange-500 border-r-red-600 animate-[spin_0.8s_linear_infinite] shadow-[0_0_15px_-4px_rgba(234,88,12,0.8)]"
|
|
15
|
+
style={{ borderWidth: "2px" }}
|
|
16
|
+
/>
|
|
17
|
+
|
|
18
|
+
{/* Turbulence Layer (Reverse Spin) */}
|
|
19
|
+
<div className="absolute inset-[10%] rounded-full border-[15%] border-transparent border-b-yellow-400/80 border-l-orange-500/80 animate-[spin_1.5s_ease-in-out_infinite_reverse]"
|
|
20
|
+
style={{ borderWidth: "2px" }}
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
{/* Core Planet (Internal) */}
|
|
24
|
+
<div className="absolute inset-[25%] rounded-full overflow-hidden bg-slate-950 shadow-[inset_0_0_4px_rgba(0,0,0,0.8)]">
|
|
25
|
+
{/* Molten Core Texture (Rotating) */}
|
|
26
|
+
<div className="absolute top-[-50%] left-[-50%] w-[200%] h-[200%] animate-[spin_3s_linear_infinite]">
|
|
27
|
+
<div className="w-full h-full bg-[conic-gradient(from_180deg,#1e293b_0deg,#0e7490_80deg,#7c3aed_160deg,#be123c_240deg,#ea580c_300deg,#1e293b_360deg)] opacity-90 blur-[1px]" />
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
{/* Surface Reflection & Shadow (Spherical look) */}
|
|
31
|
+
<div className="absolute inset-0 bg-[radial-gradient(circle_at_30%_30%,rgba(255,255,255,0.4)_0%,transparent_50%,rgba(0,0,0,0.9)_100%)] z-10" />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { Spinner }
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
|
|
8
|
+
function Switch({
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<SwitchPrimitive.Root
|
|
14
|
+
data-slot="switch"
|
|
15
|
+
className={cn(
|
|
16
|
+
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
<SwitchPrimitive.Thumb
|
|
22
|
+
data-slot="switch-thumb"
|
|
23
|
+
className={cn(
|
|
24
|
+
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
|
25
|
+
)}
|
|
26
|
+
/>
|
|
27
|
+
</SwitchPrimitive.Root>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { Switch }
|
package/src/ui/table.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../lib/utils"
|
|
4
|
+
|
|
5
|
+
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="table-container"
|
|
9
|
+
className="relative w-full overflow-x-auto rounded-md border border-slate-800/60 bg-slate-950/40 backdrop-blur-sm shadow-[0_0_20px_-10px_rgba(6,182,212,0.1)]"
|
|
10
|
+
>
|
|
11
|
+
{/* Decorative lines */}
|
|
12
|
+
<div className="absolute top-0 left-0 w-full h-[1px] bg-linear-to-r from-transparent via-cyan-500/50 to-transparent opacity-50" />
|
|
13
|
+
<div className="absolute bottom-0 left-0 w-full h-[1px] bg-linear-to-r from-transparent via-cyan-500/50 to-transparent opacity-50" />
|
|
14
|
+
|
|
15
|
+
<table
|
|
16
|
+
data-slot="table"
|
|
17
|
+
className={cn("w-full caption-bottom text-sm border-collapse", className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|
25
|
+
return (
|
|
26
|
+
<thead
|
|
27
|
+
data-slot="table-header"
|
|
28
|
+
className={cn("[&_tr]:border-b [&_tr]:border-slate-800", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|
35
|
+
return (
|
|
36
|
+
<tbody
|
|
37
|
+
data-slot="table-body"
|
|
38
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|
45
|
+
return (
|
|
46
|
+
<tfoot
|
|
47
|
+
data-slot="table-footer"
|
|
48
|
+
className={cn(
|
|
49
|
+
"bg-slate-900/80 border-t border-slate-800 font-medium [&>tr]:last:border-b-0 text-cyan-200",
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
58
|
+
return (
|
|
59
|
+
<tr
|
|
60
|
+
data-slot="table-row"
|
|
61
|
+
className={cn(
|
|
62
|
+
"border-b border-slate-800/60 transition-colors duration-200",
|
|
63
|
+
"hover:bg-cyan-950/20 hover:shadow-[inset_0_0_10px_-5px_cyan]",
|
|
64
|
+
"data-[state=selected]:bg-cyan-950/40 data-[state=selected]:border-cyan-500/30",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
73
|
+
return (
|
|
74
|
+
<th
|
|
75
|
+
data-slot="table-head"
|
|
76
|
+
className={cn(
|
|
77
|
+
"h-10 px-4 text-left align-middle font-mono text-xs font-bold uppercase tracking-widest text-cyan-500/80 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|
86
|
+
return (
|
|
87
|
+
<td
|
|
88
|
+
data-slot="table-cell"
|
|
89
|
+
className={cn(
|
|
90
|
+
"p-4 align-middle whitespace-nowrap text-slate-400 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
91
|
+
className
|
|
92
|
+
)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function TableCaption({
|
|
99
|
+
className,
|
|
100
|
+
...props
|
|
101
|
+
}: React.ComponentProps<"caption">) {
|
|
102
|
+
return (
|
|
103
|
+
<caption
|
|
104
|
+
data-slot="table-caption"
|
|
105
|
+
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
Table,
|
|
113
|
+
TableHeader,
|
|
114
|
+
TableBody,
|
|
115
|
+
TableFooter,
|
|
116
|
+
TableHead,
|
|
117
|
+
TableRow,
|
|
118
|
+
TableCell,
|
|
119
|
+
TableCaption,
|
|
120
|
+
}
|
package/src/ui/tabs.tsx
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
|
|
8
|
+
const Tabs = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof TabsPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
|
|
11
|
+
>(({ className, ...props }, ref) => (
|
|
12
|
+
<TabsPrimitive.Root
|
|
13
|
+
ref={ref}
|
|
14
|
+
data-slot="tabs"
|
|
15
|
+
className={cn("flex flex-col gap-2", className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
))
|
|
19
|
+
Tabs.displayName = TabsPrimitive.Root.displayName
|
|
20
|
+
|
|
21
|
+
const TabsList = React.forwardRef<
|
|
22
|
+
React.ElementRef<typeof TabsPrimitive.List>,
|
|
23
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
24
|
+
>(({ className, ...props }, ref) => (
|
|
25
|
+
<TabsPrimitive.List
|
|
26
|
+
ref={ref}
|
|
27
|
+
data-slot="tabs-list"
|
|
28
|
+
className={cn(
|
|
29
|
+
"bg-muted/50 border border-white/5 backdrop-blur-sm inline-flex h-10 items-center justify-center rounded-lg p-1 relative overflow-hidden",
|
|
30
|
+
className
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
))
|
|
35
|
+
TabsList.displayName = TabsPrimitive.List.displayName
|
|
36
|
+
|
|
37
|
+
const TabsTrigger = React.forwardRef<
|
|
38
|
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
39
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
40
|
+
>(({ className, children, ...props }, ref) => (
|
|
41
|
+
<TabsPrimitive.Trigger
|
|
42
|
+
ref={ref}
|
|
43
|
+
data-slot="tabs-trigger"
|
|
44
|
+
className={cn(
|
|
45
|
+
"relative z-10 inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
46
|
+
"data-[state=active]:text-cyan-500 dark:data-[state=active]:text-cyan-400",
|
|
47
|
+
"text-muted-foreground hover:text-foreground/80",
|
|
48
|
+
"group overflow-hidden",
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
>
|
|
53
|
+
<span className="relative z-10 flex items-center gap-2">{children}</span>
|
|
54
|
+
|
|
55
|
+
{/* Active State: Background Glow */}
|
|
56
|
+
<span className="absolute inset-0 -z-10 bg-cyan-500/10 opacity-0 transition-opacity duration-300 group-data-[state=active]:opacity-100" />
|
|
57
|
+
|
|
58
|
+
{/* Active State: Bottom Scanner Line */}
|
|
59
|
+
<span className="absolute bottom-0 left-0 h-[2px] w-full bg-cyan-500 scale-x-0 transition-transform duration-300 ease-out group-data-[state=active]:scale-x-100 shadow-[0_0_10px_#06b6d4]" />
|
|
60
|
+
|
|
61
|
+
{/* Active State: Particle/Sparkle Simulation (Two rotating glows) */}
|
|
62
|
+
<span className="absolute -top-[50%] -left-[50%] w-[200%] h-[200%] bg-[radial-gradient(circle,rgba(6,182,212,0.1)_0%,transparent_50%)] opacity-0 group-data-[state=active]:opacity-100 group-data-[state=active]:animate-[spin_4s_linear_infinite]" />
|
|
63
|
+
|
|
64
|
+
</TabsPrimitive.Trigger>
|
|
65
|
+
))
|
|
66
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
|
67
|
+
|
|
68
|
+
const TabsContent = React.forwardRef<
|
|
69
|
+
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
70
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
71
|
+
>(({ className, ...props }, ref) => (
|
|
72
|
+
<TabsPrimitive.Content
|
|
73
|
+
ref={ref}
|
|
74
|
+
data-slot="tabs-content"
|
|
75
|
+
className={cn(
|
|
76
|
+
"ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 mt-2",
|
|
77
|
+
// Add a subtle fade-in animation
|
|
78
|
+
"animate-in fade-in-0 zoom-in-95 duration-200",
|
|
79
|
+
className
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
))
|
|
84
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName
|
|
85
|
+
|
|
86
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../lib/utils"
|
|
4
|
+
|
|
5
|
+
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
6
|
+
return (
|
|
7
|
+
<textarea
|
|
8
|
+
data-slot="textarea"
|
|
9
|
+
className={cn(
|
|
10
|
+
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { Textarea }
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cn } from "../lib/utils"
|
|
3
|
+
|
|
4
|
+
const Timeline = React.forwardRef<
|
|
5
|
+
HTMLOListElement,
|
|
6
|
+
React.HTMLAttributes<HTMLOListElement>
|
|
7
|
+
>(({ className, ...props }, ref) => (
|
|
8
|
+
<ol
|
|
9
|
+
ref={ref}
|
|
10
|
+
className={cn("relative border-l border-gray-200", className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
))
|
|
14
|
+
Timeline.displayName = "Timeline"
|
|
15
|
+
|
|
16
|
+
const TimelineItem = React.forwardRef<
|
|
17
|
+
HTMLLIElement,
|
|
18
|
+
React.HTMLAttributes<HTMLLIElement>
|
|
19
|
+
>(({ className, ...props }, ref) => (
|
|
20
|
+
<li
|
|
21
|
+
ref={ref}
|
|
22
|
+
className={cn("mb-10 ml-6", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
))
|
|
26
|
+
TimelineItem.displayName = "TimelineItem"
|
|
27
|
+
|
|
28
|
+
const TimelineMarker = React.forwardRef<
|
|
29
|
+
HTMLDivElement,
|
|
30
|
+
React.HTMLAttributes<HTMLDivElement> & {
|
|
31
|
+
variant?: "default" | "success" | "warning" | "danger" | "info"
|
|
32
|
+
}
|
|
33
|
+
>(({ className, variant = "default", ...props }, ref) => {
|
|
34
|
+
const variantClasses = {
|
|
35
|
+
default: "bg-gray-200 border-gray-300",
|
|
36
|
+
success: "bg-green-200 border-green-500",
|
|
37
|
+
warning: "bg-yellow-200 border-yellow-500",
|
|
38
|
+
danger: "bg-red-200 border-red-500",
|
|
39
|
+
info: "bg-blue-200 border-blue-500",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={cn(
|
|
46
|
+
"absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center",
|
|
47
|
+
variantClasses[variant],
|
|
48
|
+
className
|
|
49
|
+
)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
TimelineMarker.displayName = "TimelineMarker"
|
|
55
|
+
|
|
56
|
+
const TimelineContent = React.forwardRef<
|
|
57
|
+
HTMLDivElement,
|
|
58
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
59
|
+
>(({ className, ...props }, ref) => (
|
|
60
|
+
<div
|
|
61
|
+
ref={ref}
|
|
62
|
+
className={className}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
))
|
|
66
|
+
TimelineContent.displayName = "TimelineContent"
|
|
67
|
+
|
|
68
|
+
const TimelineTitle = React.forwardRef<
|
|
69
|
+
HTMLHeadingElement,
|
|
70
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
71
|
+
>(({ className, ...props }, ref) => (
|
|
72
|
+
<h3
|
|
73
|
+
ref={ref}
|
|
74
|
+
className={cn("font-semibold text-lg mb-1", className)}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
))
|
|
78
|
+
TimelineTitle.displayName = "TimelineTitle"
|
|
79
|
+
|
|
80
|
+
const TimelineTime = React.forwardRef<
|
|
81
|
+
HTMLTimeElement,
|
|
82
|
+
React.TimeHTMLAttributes<HTMLTimeElement>
|
|
83
|
+
>(({ className, ...props }, ref) => (
|
|
84
|
+
<time
|
|
85
|
+
ref={ref}
|
|
86
|
+
className={cn("text-sm font-normal text-gray-500 mb-2 block", className)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
))
|
|
90
|
+
TimelineTime.displayName = "TimelineTime"
|
|
91
|
+
|
|
92
|
+
const TimelineDescription = React.forwardRef<
|
|
93
|
+
HTMLParagraphElement,
|
|
94
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
95
|
+
>(({ className, ...props }, ref) => (
|
|
96
|
+
<p
|
|
97
|
+
ref={ref}
|
|
98
|
+
className={cn("text-base text-gray-700", className)}
|
|
99
|
+
{...props}
|
|
100
|
+
/>
|
|
101
|
+
))
|
|
102
|
+
TimelineDescription.displayName = "TimelineDescription"
|
|
103
|
+
|
|
104
|
+
// Horizontal Timeline Components
|
|
105
|
+
const TimelineHorizontal = React.forwardRef<
|
|
106
|
+
HTMLDivElement,
|
|
107
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
108
|
+
>(({ className, ...props }, ref) => (
|
|
109
|
+
<div
|
|
110
|
+
ref={ref}
|
|
111
|
+
className={cn("relative flex overflow-x-auto py-8", className)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
))
|
|
115
|
+
TimelineHorizontal.displayName = "TimelineHorizontal"
|
|
116
|
+
|
|
117
|
+
const TimelineHorizontalItem = React.forwardRef<
|
|
118
|
+
HTMLDivElement,
|
|
119
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
120
|
+
>(({ className, ...props }, ref) => (
|
|
121
|
+
<div
|
|
122
|
+
ref={ref}
|
|
123
|
+
className={cn("flex-shrink-0 w-64 relative", className)}
|
|
124
|
+
{...props}
|
|
125
|
+
/>
|
|
126
|
+
))
|
|
127
|
+
TimelineHorizontalItem.displayName = "TimelineHorizontalItem"
|
|
128
|
+
|
|
129
|
+
// Gantt-style Timeline Components (Airtable-like)
|
|
130
|
+
const TimelineGantt = React.forwardRef<
|
|
131
|
+
HTMLDivElement,
|
|
132
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
133
|
+
>(({ className, ...props }, ref) => (
|
|
134
|
+
<div
|
|
135
|
+
ref={ref}
|
|
136
|
+
className={cn("relative w-full border rounded-lg overflow-hidden", className)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
))
|
|
140
|
+
TimelineGantt.displayName = "TimelineGantt"
|
|
141
|
+
|
|
142
|
+
const TimelineGanttHeader = React.forwardRef<
|
|
143
|
+
HTMLDivElement,
|
|
144
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
145
|
+
>(({ className, ...props }, ref) => (
|
|
146
|
+
<div
|
|
147
|
+
ref={ref}
|
|
148
|
+
className={cn("flex border-b bg-gray-50", className)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
))
|
|
152
|
+
TimelineGanttHeader.displayName = "TimelineGanttHeader"
|
|
153
|
+
|
|
154
|
+
const TimelineGanttRowLabels = React.forwardRef<
|
|
155
|
+
HTMLDivElement,
|
|
156
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
157
|
+
>(({ className, ...props }, ref) => (
|
|
158
|
+
<div
|
|
159
|
+
ref={ref}
|
|
160
|
+
className={cn("w-48 border-r bg-white", className)}
|
|
161
|
+
{...props}
|
|
162
|
+
/>
|
|
163
|
+
))
|
|
164
|
+
TimelineGanttRowLabels.displayName = "TimelineGanttRowLabels"
|
|
165
|
+
|
|
166
|
+
const TimelineGanttGrid = React.forwardRef<
|
|
167
|
+
HTMLDivElement,
|
|
168
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
169
|
+
>(({ className, ...props }, ref) => (
|
|
170
|
+
<div
|
|
171
|
+
ref={ref}
|
|
172
|
+
className={cn("flex-1 overflow-x-auto", className)}
|
|
173
|
+
{...props}
|
|
174
|
+
/>
|
|
175
|
+
))
|
|
176
|
+
TimelineGanttGrid.displayName = "TimelineGanttGrid"
|
|
177
|
+
|
|
178
|
+
const TimelineGanttRow = React.forwardRef<
|
|
179
|
+
HTMLDivElement,
|
|
180
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
181
|
+
>(({ className, ...props }, ref) => (
|
|
182
|
+
<div
|
|
183
|
+
ref={ref}
|
|
184
|
+
className={cn("flex items-center border-b min-h-12", className)}
|
|
185
|
+
{...props}
|
|
186
|
+
/>
|
|
187
|
+
))
|
|
188
|
+
TimelineGanttRow.displayName = "TimelineGanttRow"
|
|
189
|
+
|
|
190
|
+
const TimelineGanttLabel = React.forwardRef<
|
|
191
|
+
HTMLDivElement,
|
|
192
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
193
|
+
>(({ className, ...props }, ref) => (
|
|
194
|
+
<div
|
|
195
|
+
ref={ref}
|
|
196
|
+
className={cn("px-4 py-2 font-medium text-sm truncate", className)}
|
|
197
|
+
{...props}
|
|
198
|
+
/>
|
|
199
|
+
))
|
|
200
|
+
TimelineGanttLabel.displayName = "TimelineGanttLabel"
|
|
201
|
+
|
|
202
|
+
const TimelineGanttBar = React.forwardRef<
|
|
203
|
+
HTMLDivElement,
|
|
204
|
+
React.HTMLAttributes<HTMLDivElement> & {
|
|
205
|
+
start?: number
|
|
206
|
+
width?: number
|
|
207
|
+
variant?: "default" | "success" | "warning" | "danger" | "info"
|
|
208
|
+
}
|
|
209
|
+
>(({ className, start = 0, width = 100, variant = "default", ...props }, ref) => {
|
|
210
|
+
const variantClasses = {
|
|
211
|
+
default: "bg-blue-500 hover:bg-blue-600",
|
|
212
|
+
success: "bg-green-500 hover:bg-green-600",
|
|
213
|
+
warning: "bg-yellow-500 hover:bg-yellow-600",
|
|
214
|
+
danger: "bg-red-500 hover:bg-red-600",
|
|
215
|
+
info: "bg-purple-500 hover:bg-purple-600",
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div
|
|
220
|
+
ref={ref}
|
|
221
|
+
className={cn(
|
|
222
|
+
"absolute h-8 rounded-md transition-colors cursor-pointer",
|
|
223
|
+
variantClasses[variant],
|
|
224
|
+
className
|
|
225
|
+
)}
|
|
226
|
+
style={{
|
|
227
|
+
left: `${start}%`,
|
|
228
|
+
width: `${width}%`,
|
|
229
|
+
}}
|
|
230
|
+
{...props}
|
|
231
|
+
/>
|
|
232
|
+
)
|
|
233
|
+
})
|
|
234
|
+
TimelineGanttBar.displayName = "TimelineGanttBar"
|
|
235
|
+
|
|
236
|
+
const TimelineGanttBarContent = React.forwardRef<
|
|
237
|
+
HTMLDivElement,
|
|
238
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
239
|
+
>(({ className, ...props }, ref) => (
|
|
240
|
+
<div
|
|
241
|
+
ref={ref}
|
|
242
|
+
className={cn("px-2 py-1 text-white text-xs font-medium truncate", className)}
|
|
243
|
+
{...props}
|
|
244
|
+
/>
|
|
245
|
+
))
|
|
246
|
+
TimelineGanttBarContent.displayName = "TimelineGanttBarContent"
|
|
247
|
+
|
|
248
|
+
export {
|
|
249
|
+
Timeline,
|
|
250
|
+
TimelineItem,
|
|
251
|
+
TimelineMarker,
|
|
252
|
+
TimelineContent,
|
|
253
|
+
TimelineTitle,
|
|
254
|
+
TimelineTime,
|
|
255
|
+
TimelineDescription,
|
|
256
|
+
TimelineHorizontal,
|
|
257
|
+
TimelineHorizontalItem,
|
|
258
|
+
TimelineGantt,
|
|
259
|
+
TimelineGanttHeader,
|
|
260
|
+
TimelineGanttRowLabels,
|
|
261
|
+
TimelineGanttGrid,
|
|
262
|
+
TimelineGanttRow,
|
|
263
|
+
TimelineGanttLabel,
|
|
264
|
+
TimelineGanttBar,
|
|
265
|
+
TimelineGanttBarContent,
|
|
266
|
+
}
|