azamat-ui-kit-cli 0.2.2
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/README.md +8 -0
- package/dist/index.js +432 -0
- package/package.json +34 -0
- package/vendor/package.json +4 -0
- package/vendor/src/components/actions/action-bar.tsx +35 -0
- package/vendor/src/components/actions/action-menu.tsx +120 -0
- package/vendor/src/components/actions/button-group.tsx +47 -0
- package/vendor/src/components/actions/copy-button.tsx +91 -0
- package/vendor/src/components/actions/copy-field.tsx +31 -0
- package/vendor/src/components/actions/floating-action-button.tsx +33 -0
- package/vendor/src/components/actions/index.ts +7 -0
- package/vendor/src/components/actions/public.ts +5 -0
- package/vendor/src/components/actions/quick-action-grid.tsx +162 -0
- package/vendor/src/components/calendar/calendar.tsx +328 -0
- package/vendor/src/components/calendar/date-picker.tsx +78 -0
- package/vendor/src/components/calendar/date-range-picker.tsx +96 -0
- package/vendor/src/components/calendar/date-utils.ts +89 -0
- package/vendor/src/components/calendar/index.ts +4 -0
- package/vendor/src/components/charts/charts.tsx +275 -0
- package/vendor/src/components/charts/horizontal-bar-chart.tsx +46 -0
- package/vendor/src/components/charts/index.ts +4 -0
- package/vendor/src/components/charts/kpi.tsx +68 -0
- package/vendor/src/components/charts/progress-ring.tsx +45 -0
- package/vendor/src/components/charts/public.ts +1 -0
- package/vendor/src/components/command/command-palette.tsx +375 -0
- package/vendor/src/components/command/index.ts +1 -0
- package/vendor/src/components/data-table/data-table-actions-column.tsx +58 -0
- package/vendor/src/components/data-table/data-table-bulk-actions.tsx +84 -0
- package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +79 -0
- package/vendor/src/components/data-table/data-table-pagination.tsx +91 -0
- package/vendor/src/components/data-table/data-table-row-actions.tsx +48 -0
- package/vendor/src/components/data-table/data-table-select-column.tsx +59 -0
- package/vendor/src/components/data-table/data-table-sortable-header.tsx +45 -0
- package/vendor/src/components/data-table/data-table-toolbar.tsx +76 -0
- package/vendor/src/components/data-table/data-table-view-presets.tsx +128 -0
- package/vendor/src/components/data-table/data-table.tsx +507 -0
- package/vendor/src/components/data-table/index.ts +12 -0
- package/vendor/src/components/data-table/public.ts +10 -0
- package/vendor/src/components/data-table/table-export-menu.tsx +56 -0
- package/vendor/src/components/data-table/table-import-button.tsx +43 -0
- package/vendor/src/components/display/activity-feed.tsx +97 -0
- package/vendor/src/components/display/avatar.tsx +131 -0
- package/vendor/src/components/display/code-block.tsx +33 -0
- package/vendor/src/components/display/data-state.tsx +63 -0
- package/vendor/src/components/display/description-list.tsx +119 -0
- package/vendor/src/components/display/descriptions.tsx +83 -0
- package/vendor/src/components/display/entity-card.tsx +53 -0
- package/vendor/src/components/display/file-card.tsx +54 -0
- package/vendor/src/components/display/index.ts +30 -0
- package/vendor/src/components/display/kanban.tsx +104 -0
- package/vendor/src/components/display/keyboard-shortcut.tsx +31 -0
- package/vendor/src/components/display/list.tsx +100 -0
- package/vendor/src/components/display/metric-grid.tsx +86 -0
- package/vendor/src/components/display/progress.tsx +162 -0
- package/vendor/src/components/display/property-grid.tsx +54 -0
- package/vendor/src/components/display/result.tsx +90 -0
- package/vendor/src/components/display/smart-card.tsx +168 -0
- package/vendor/src/components/display/statistic.tsx +107 -0
- package/vendor/src/components/display/status-legend.tsx +108 -0
- package/vendor/src/components/display/tag-list.tsx +52 -0
- package/vendor/src/components/display/timeline.tsx +132 -0
- package/vendor/src/components/display/tree-view.tsx +116 -0
- package/vendor/src/components/feedback/alert.tsx +69 -0
- package/vendor/src/components/feedback/empty-state.tsx +56 -0
- package/vendor/src/components/feedback/index.ts +5 -0
- package/vendor/src/components/feedback/loading-state.tsx +39 -0
- package/vendor/src/components/feedback/page-state.tsx +69 -0
- package/vendor/src/components/feedback/status-badge.tsx +62 -0
- package/vendor/src/components/filters/filter-bar.tsx +89 -0
- package/vendor/src/components/filters/filter-chips.tsx +69 -0
- package/vendor/src/components/filters/index.ts +2 -0
- package/vendor/src/components/form/form-actions.tsx +53 -0
- package/vendor/src/components/form/form-async-select.tsx +26 -0
- package/vendor/src/components/form/form-date-input.tsx +19 -0
- package/vendor/src/components/form/form-date-picker.tsx +54 -0
- package/vendor/src/components/form/form-date-range-input.tsx +79 -0
- package/vendor/src/components/form/form-date-range-picker.tsx +57 -0
- package/vendor/src/components/form/form-field-shell.tsx +191 -0
- package/vendor/src/components/form/form-input.tsx +480 -0
- package/vendor/src/components/form/form-number-input.tsx +19 -0
- package/vendor/src/components/form/form-password-input.tsx +19 -0
- package/vendor/src/components/form/form-phone-input.tsx +22 -0
- package/vendor/src/components/form/form-search-input.tsx +19 -0
- package/vendor/src/components/form/form-section.tsx +29 -0
- package/vendor/src/components/form/form-select.tsx +194 -0
- package/vendor/src/components/form/form-switch.tsx +145 -0
- package/vendor/src/components/form/form-textarea.tsx +103 -0
- package/vendor/src/components/form/index.ts +17 -0
- package/vendor/src/components/form/public.ts +14 -0
- package/vendor/src/components/form/smart-form-shell.tsx +59 -0
- package/vendor/src/components/inputs/async-select.tsx +1143 -0
- package/vendor/src/components/inputs/clearable-input.tsx +78 -0
- package/vendor/src/components/inputs/color-input.tsx +47 -0
- package/vendor/src/components/inputs/combobox.tsx +89 -0
- package/vendor/src/components/inputs/date-input.tsx +32 -0
- package/vendor/src/components/inputs/date-range-input.tsx +67 -0
- package/vendor/src/components/inputs/index.ts +19 -0
- package/vendor/src/components/inputs/input-chrome.tsx +37 -0
- package/vendor/src/components/inputs/input-decorator.tsx +64 -0
- package/vendor/src/components/inputs/input-value.ts +42 -0
- package/vendor/src/components/inputs/masked-input.tsx +51 -0
- package/vendor/src/components/inputs/money-input.tsx +73 -0
- package/vendor/src/components/inputs/number-input.tsx +87 -0
- package/vendor/src/components/inputs/numeric-value.ts +39 -0
- package/vendor/src/components/inputs/otp-input.tsx +102 -0
- package/vendor/src/components/inputs/password-input.tsx +85 -0
- package/vendor/src/components/inputs/phone-input.tsx +46 -0
- package/vendor/src/components/inputs/quantity-input.tsx +116 -0
- package/vendor/src/components/inputs/quantity-stepper.tsx +49 -0
- package/vendor/src/components/inputs/rating.tsx +98 -0
- package/vendor/src/components/inputs/search-input.tsx +26 -0
- package/vendor/src/components/inputs/simple-select.tsx +72 -0
- package/vendor/src/components/inputs/slider.tsx +149 -0
- package/vendor/src/components/inputs/tag-input.tsx +104 -0
- package/vendor/src/components/layout/app-header.tsx +46 -0
- package/vendor/src/components/layout/app-shell.tsx +243 -0
- package/vendor/src/components/layout/app-sidebar.tsx +179 -0
- package/vendor/src/components/layout/breadcrumbs.tsx +72 -0
- package/vendor/src/components/layout/index.ts +11 -0
- package/vendor/src/components/layout/page-container.tsx +30 -0
- package/vendor/src/components/layout/page-header.tsx +60 -0
- package/vendor/src/components/layout/public.ts +10 -0
- package/vendor/src/components/layout/section.tsx +76 -0
- package/vendor/src/components/layout/sidebar-nav.tsx +147 -0
- package/vendor/src/components/layout/stat-card.tsx +88 -0
- package/vendor/src/components/layout/sticky-footer-bar.tsx +23 -0
- package/vendor/src/components/layout/workspace-shell.tsx +50 -0
- package/vendor/src/components/navigation/anchor-nav.tsx +44 -0
- package/vendor/src/components/navigation/index.ts +4 -0
- package/vendor/src/components/navigation/page-tabs.tsx +67 -0
- package/vendor/src/components/navigation/pagination.tsx +179 -0
- package/vendor/src/components/navigation/stepper-tabs.tsx +67 -0
- package/vendor/src/components/notifications/index.ts +1 -0
- package/vendor/src/components/notifications/toast.tsx +259 -0
- package/vendor/src/components/overlay/confirm-dialog.tsx +66 -0
- package/vendor/src/components/overlay/dialog-actions.tsx +68 -0
- package/vendor/src/components/overlay/index.ts +4 -0
- package/vendor/src/components/overlay/modal-shell.tsx +93 -0
- package/vendor/src/components/overlay/sheet-shell.tsx +212 -0
- package/vendor/src/components/patterns/action-system.tsx +116 -0
- package/vendor/src/components/patterns/crud-system.tsx +53 -0
- package/vendor/src/components/patterns/data-view.tsx +84 -0
- package/vendor/src/components/patterns/entity-details.tsx +66 -0
- package/vendor/src/components/patterns/filter-builder.tsx +113 -0
- package/vendor/src/components/patterns/form-builder-presets.ts +131 -0
- package/vendor/src/components/patterns/form-builder.tsx +334 -0
- package/vendor/src/components/patterns/index.ts +12 -0
- package/vendor/src/components/patterns/public.ts +4 -0
- package/vendor/src/components/patterns/resource-detail-page.tsx +160 -0
- package/vendor/src/components/patterns/resource-page.tsx +159 -0
- package/vendor/src/components/patterns/resource-system.tsx +61 -0
- package/vendor/src/components/patterns/settings-section.tsx +46 -0
- package/vendor/src/components/patterns/status-system.tsx +89 -0
- package/vendor/src/components/theme-provider.tsx +51 -0
- package/vendor/src/components/ui/badge.tsx +52 -0
- package/vendor/src/components/ui/button.tsx +61 -0
- package/vendor/src/components/ui/card.tsx +103 -0
- package/vendor/src/components/ui/checkbox.tsx +82 -0
- package/vendor/src/components/ui/collapse.tsx +126 -0
- package/vendor/src/components/ui/command.tsx +194 -0
- package/vendor/src/components/ui/dialog.tsx +160 -0
- package/vendor/src/components/ui/divider.tsx +46 -0
- package/vendor/src/components/ui/dropdown-menu.tsx +266 -0
- package/vendor/src/components/ui/input-group.tsx +158 -0
- package/vendor/src/components/ui/input.tsx +20 -0
- package/vendor/src/components/ui/popover.tsx +90 -0
- package/vendor/src/components/ui/segmented-control.tsx +78 -0
- package/vendor/src/components/ui/select.tsx +201 -0
- package/vendor/src/components/ui/skeleton.tsx +75 -0
- package/vendor/src/components/ui/spinner.tsx +50 -0
- package/vendor/src/components/ui/switch.tsx +71 -0
- package/vendor/src/components/ui/table.tsx +114 -0
- package/vendor/src/components/ui/tabs.tsx +55 -0
- package/vendor/src/components/ui/textarea.tsx +18 -0
- package/vendor/src/components/ui/tooltip.tsx +38 -0
- package/vendor/src/components/upload/file-upload.tsx +483 -0
- package/vendor/src/components/upload/image-upload.tsx +118 -0
- package/vendor/src/components/upload/index.ts +2 -0
- package/vendor/src/components/wizard/index.ts +2 -0
- package/vendor/src/components/wizard/stepper.tsx +53 -0
- package/vendor/src/components/wizard/wizard.tsx +60 -0
- package/vendor/src/families/card-family.ts +28 -0
- package/vendor/src/families/catalog.ts +96 -0
- package/vendor/src/families/data-table-family.ts +31 -0
- package/vendor/src/families/docs-adoption.ts +103 -0
- package/vendor/src/families/docs-groups.ts +209 -0
- package/vendor/src/families/docs-queries.ts +84 -0
- package/vendor/src/families/docs-routing.ts +89 -0
- package/vendor/src/families/form-family.ts +45 -0
- package/vendor/src/families/index.ts +17 -0
- package/vendor/src/families/input-family.ts +61 -0
- package/vendor/src/families/member-metadata.ts +466 -0
- package/vendor/src/families/member-queries.ts +28 -0
- package/vendor/src/families/member-snippet-queries.ts +54 -0
- package/vendor/src/families/member-snippets.ts +673 -0
- package/vendor/src/families/migration-map.ts +79 -0
- package/vendor/src/families/queries.ts +63 -0
- package/vendor/src/families/select-family.ts +33 -0
- package/vendor/src/families/views.ts +81 -0
- package/vendor/src/hooks/index.ts +6 -0
- package/vendor/src/hooks/use-before-unload-when-dirty.ts +21 -0
- package/vendor/src/hooks/use-data-table-view-state.ts +122 -0
- package/vendor/src/hooks/use-debounce.ts +52 -0
- package/vendor/src/hooks/use-disclosure.ts +38 -0
- package/vendor/src/hooks/use-is-mobile.ts +28 -0
- package/vendor/src/hooks/use-session-storage-state.ts +85 -0
- package/vendor/src/index.ts +38 -0
- package/vendor/src/lib/utils.ts +6 -0
- package/vendor/templates/components/button.tsx +0 -0
- package/vendor/templates/components/data-table.tsx +0 -0
- package/vendor/templates/components/input.tsx +0 -0
- package/vendor/templates/lib/utils.ts +0 -0
- package/vendor/templates/styles/globals.css +0 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
export type ActivityFeedItem = {
|
|
7
|
+
id: string
|
|
8
|
+
title: React.ReactNode
|
|
9
|
+
description?: React.ReactNode
|
|
10
|
+
time?: React.ReactNode
|
|
11
|
+
icon?: React.ReactNode
|
|
12
|
+
tone?: "default" | "success" | "warning" | "danger" | "info" | "muted"
|
|
13
|
+
actions?: React.ReactNode
|
|
14
|
+
hidden?: boolean
|
|
15
|
+
className?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ActivityFeedProps = React.ComponentProps<typeof Card> & {
|
|
19
|
+
title?: React.ReactNode
|
|
20
|
+
description?: React.ReactNode
|
|
21
|
+
actions?: React.ReactNode
|
|
22
|
+
items: ActivityFeedItem[]
|
|
23
|
+
empty?: React.ReactNode
|
|
24
|
+
compact?: boolean
|
|
25
|
+
contentClassName?: string
|
|
26
|
+
itemClassName?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const toneDotClassName: Record<NonNullable<ActivityFeedItem["tone"]>, string> = {
|
|
30
|
+
default: "bg-primary",
|
|
31
|
+
success: "bg-emerald-500",
|
|
32
|
+
warning: "bg-amber-500",
|
|
33
|
+
danger: "bg-destructive",
|
|
34
|
+
info: "bg-blue-500",
|
|
35
|
+
muted: "bg-muted-foreground",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function ActivityFeed({
|
|
39
|
+
className,
|
|
40
|
+
title,
|
|
41
|
+
description,
|
|
42
|
+
actions,
|
|
43
|
+
items,
|
|
44
|
+
empty = "No activity yet.",
|
|
45
|
+
compact = false,
|
|
46
|
+
contentClassName,
|
|
47
|
+
itemClassName,
|
|
48
|
+
...props
|
|
49
|
+
}: ActivityFeedProps) {
|
|
50
|
+
const visibleItems = items.filter((item) => !item.hidden)
|
|
51
|
+
const hasHeader = Boolean(title || description || actions)
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Card data-slot="activity-feed" className={cn("min-w-0", className)} {...props}>
|
|
55
|
+
{hasHeader && (
|
|
56
|
+
<CardHeader>
|
|
57
|
+
<div className="flex min-w-0 items-start justify-between gap-3">
|
|
58
|
+
<div className="min-w-0 space-y-1">
|
|
59
|
+
{title && <CardTitle>{title}</CardTitle>}
|
|
60
|
+
{description && <CardDescription>{description}</CardDescription>}
|
|
61
|
+
</div>
|
|
62
|
+
{actions && <div className="shrink-0">{actions}</div>}
|
|
63
|
+
</div>
|
|
64
|
+
</CardHeader>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
<CardContent className={cn("grid gap-0", contentClassName)}>
|
|
68
|
+
{visibleItems.length === 0 ? (
|
|
69
|
+
<div className="rounded-lg border border-dashed p-4 text-center text-sm text-muted-foreground">{empty}</div>
|
|
70
|
+
) : (
|
|
71
|
+
visibleItems.map((item, index) => (
|
|
72
|
+
<div
|
|
73
|
+
key={item.id}
|
|
74
|
+
data-slot="activity-feed-item"
|
|
75
|
+
className={cn("relative flex gap-3 pb-4 last:pb-0", compact && "gap-2 pb-3", itemClassName, item.className)}
|
|
76
|
+
>
|
|
77
|
+
{index < visibleItems.length - 1 && <div className="absolute left-3 top-7 h-[calc(100%-1.75rem)] w-px bg-border" />}
|
|
78
|
+
<div className="relative z-10 mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-full border bg-background">
|
|
79
|
+
{item.icon ?? <span className={cn("size-2 rounded-full", toneDotClassName[item.tone ?? "default"])} />}
|
|
80
|
+
</div>
|
|
81
|
+
<div className="min-w-0 flex-1 space-y-1">
|
|
82
|
+
<div className="flex min-w-0 items-start justify-between gap-2">
|
|
83
|
+
<div className="min-w-0 text-sm font-medium leading-5 text-foreground">{item.title}</div>
|
|
84
|
+
{item.time && <div className="shrink-0 text-xs text-muted-foreground">{item.time}</div>}
|
|
85
|
+
</div>
|
|
86
|
+
{item.description && <div className="text-sm leading-5 text-muted-foreground">{item.description}</div>}
|
|
87
|
+
{item.actions && <div className="pt-1">{item.actions}</div>}
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
))
|
|
91
|
+
)}
|
|
92
|
+
</CardContent>
|
|
93
|
+
</Card>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { ActivityFeed }
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
export type AvatarSize = "xs" | "sm" | "default" | "lg" | "xl"
|
|
6
|
+
export type AvatarShape = "circle" | "rounded" | "square"
|
|
7
|
+
|
|
8
|
+
export type AvatarProps = React.ComponentProps<"span"> & {
|
|
9
|
+
src?: string
|
|
10
|
+
alt?: string
|
|
11
|
+
name?: string
|
|
12
|
+
fallback?: React.ReactNode
|
|
13
|
+
size?: AvatarSize
|
|
14
|
+
shape?: AvatarShape
|
|
15
|
+
status?: "online" | "offline" | "busy" | "away"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type AvatarGroupItem = AvatarProps & {
|
|
19
|
+
key: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AvatarGroupProps = React.ComponentProps<"div"> & {
|
|
23
|
+
items: AvatarGroupItem[]
|
|
24
|
+
max?: number
|
|
25
|
+
size?: AvatarSize
|
|
26
|
+
shape?: AvatarShape
|
|
27
|
+
stacked?: boolean
|
|
28
|
+
overflowLabel?: (count: number) => React.ReactNode
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const sizeClassName: Record<AvatarSize, string> = {
|
|
32
|
+
xs: "size-6 text-[10px]",
|
|
33
|
+
sm: "size-8 text-xs",
|
|
34
|
+
default: "size-10 text-sm",
|
|
35
|
+
lg: "size-12 text-base",
|
|
36
|
+
xl: "size-16 text-lg",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const shapeClassName: Record<AvatarShape, string> = {
|
|
40
|
+
circle: "rounded-full",
|
|
41
|
+
rounded: "rounded-xl",
|
|
42
|
+
square: "rounded-md",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const statusClassName = {
|
|
46
|
+
online: "bg-emerald-500",
|
|
47
|
+
offline: "bg-muted-foreground",
|
|
48
|
+
busy: "bg-destructive",
|
|
49
|
+
away: "bg-amber-500",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getInitials(name?: string) {
|
|
53
|
+
if (!name) return "?"
|
|
54
|
+
const words = name.trim().split(/\s+/).filter(Boolean)
|
|
55
|
+
if (!words.length) return "?"
|
|
56
|
+
return words.slice(0, 2).map((word) => word[0]?.toUpperCase()).join("")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function Avatar({
|
|
60
|
+
src,
|
|
61
|
+
alt,
|
|
62
|
+
name,
|
|
63
|
+
fallback,
|
|
64
|
+
size = "default",
|
|
65
|
+
shape = "circle",
|
|
66
|
+
status,
|
|
67
|
+
className,
|
|
68
|
+
...props
|
|
69
|
+
}: AvatarProps) {
|
|
70
|
+
const [imageError, setImageError] = React.useState(false)
|
|
71
|
+
const showImage = Boolean(src && !imageError)
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<span
|
|
75
|
+
data-slot="avatar"
|
|
76
|
+
data-size={size}
|
|
77
|
+
data-shape={shape}
|
|
78
|
+
className={cn("relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden border bg-muted font-medium text-muted-foreground", sizeClassName[size], shapeClassName[shape], className)}
|
|
79
|
+
{...props}
|
|
80
|
+
>
|
|
81
|
+
{showImage ? (
|
|
82
|
+
<img src={src} alt={alt ?? name ?? "Avatar"} className="size-full object-cover" onError={() => setImageError(true)} />
|
|
83
|
+
) : (
|
|
84
|
+
<span data-slot="avatar-fallback">{fallback ?? getInitials(name)}</span>
|
|
85
|
+
)}
|
|
86
|
+
{status && (
|
|
87
|
+
<span
|
|
88
|
+
data-slot="avatar-status"
|
|
89
|
+
data-status={status}
|
|
90
|
+
className={cn("absolute bottom-0 right-0 size-2.5 rounded-full border-2 border-background", size === "xs" && "size-2", size === "xl" && "size-3.5", statusClassName[status])}
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
</span>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function AvatarGroup({
|
|
98
|
+
items,
|
|
99
|
+
max = 5,
|
|
100
|
+
size = "default",
|
|
101
|
+
shape = "circle",
|
|
102
|
+
stacked = true,
|
|
103
|
+
overflowLabel = (count) => `+${count}`,
|
|
104
|
+
className,
|
|
105
|
+
...props
|
|
106
|
+
}: AvatarGroupProps) {
|
|
107
|
+
const visibleItems = items.slice(0, max)
|
|
108
|
+
const overflowCount = Math.max(items.length - max, 0)
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div data-slot="avatar-group" className={cn("flex items-center", stacked ? "-space-x-2" : "gap-2", className)} {...props}>
|
|
112
|
+
{visibleItems.map((item) => {
|
|
113
|
+
const { key: itemKey, ...avatarProps } = item
|
|
114
|
+
return (
|
|
115
|
+
<Avatar
|
|
116
|
+
key={itemKey}
|
|
117
|
+
size={item.size ?? size}
|
|
118
|
+
shape={item.shape ?? shape}
|
|
119
|
+
className={cn(stacked && "ring-2 ring-background", item.className)}
|
|
120
|
+
{...avatarProps}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
123
|
+
})}
|
|
124
|
+
{overflowCount > 0 && (
|
|
125
|
+
<Avatar size={size} shape={shape} fallback={overflowLabel(overflowCount)} className={cn(stacked && "ring-2 ring-background")} />
|
|
126
|
+
)}
|
|
127
|
+
</div>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { Avatar, AvatarGroup }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { CopyButton } from "@/components/actions/copy-button"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
export type CodeBlockProps = React.ComponentProps<"div"> & {
|
|
7
|
+
code: string
|
|
8
|
+
language?: string
|
|
9
|
+
title?: React.ReactNode
|
|
10
|
+
showCopy?: boolean
|
|
11
|
+
wrap?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function CodeBlock({ code, language, title, showCopy = true, wrap = false, className, ...props }: CodeBlockProps) {
|
|
15
|
+
return (
|
|
16
|
+
<div data-slot="code-block" className={cn("overflow-hidden rounded-lg border bg-card", className)} {...props}>
|
|
17
|
+
{(title || language || showCopy) && (
|
|
18
|
+
<div className="flex items-center justify-between gap-3 border-b px-3 py-2 text-xs text-muted-foreground">
|
|
19
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
20
|
+
{title && <span className="truncate font-medium text-foreground">{title}</span>}
|
|
21
|
+
{language && <span className="rounded bg-muted px-1.5 py-0.5 font-mono">{language}</span>}
|
|
22
|
+
</div>
|
|
23
|
+
{showCopy && <CopyButton value={code} size="sm" variant="ghost" copyLabel="Copy" copiedLabel="Copied" />}
|
|
24
|
+
</div>
|
|
25
|
+
)}
|
|
26
|
+
<pre className={cn("overflow-x-auto p-3 text-sm", wrap && "whitespace-pre-wrap break-words")}>
|
|
27
|
+
<code>{code}</code>
|
|
28
|
+
</pre>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { CodeBlock }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { AlertTriangleIcon, CheckCircle2Icon, Loader2Icon, SearchXIcon } from "lucide-react"
|
|
3
|
+
|
|
4
|
+
import { Button } from "@/components/ui/button"
|
|
5
|
+
import { Card, CardContent } from "@/components/ui/card"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
export type DataStateStatus = "idle" | "loading" | "empty" | "error" | "success"
|
|
9
|
+
|
|
10
|
+
export type DataStateProps = React.ComponentProps<typeof Card> & {
|
|
11
|
+
status: DataStateStatus
|
|
12
|
+
title?: React.ReactNode
|
|
13
|
+
description?: React.ReactNode
|
|
14
|
+
actions?: React.ReactNode
|
|
15
|
+
icon?: React.ReactNode
|
|
16
|
+
compact?: boolean
|
|
17
|
+
children?: React.ReactNode
|
|
18
|
+
retryLabel?: React.ReactNode
|
|
19
|
+
onRetry?: () => void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const defaultContent: Record<DataStateStatus, { title: string; description: string; icon: React.ReactNode }> = {
|
|
23
|
+
idle: { title: "Ready", description: "No action has started yet.", icon: <CheckCircle2Icon /> },
|
|
24
|
+
loading: { title: "Loading", description: "Please wait while data is being prepared.", icon: <Loader2Icon className="animate-spin" /> },
|
|
25
|
+
empty: { title: "No data", description: "There is nothing to show yet.", icon: <SearchXIcon /> },
|
|
26
|
+
error: { title: "Something went wrong", description: "Try again or check the request.", icon: <AlertTriangleIcon /> },
|
|
27
|
+
success: { title: "Ready", description: "Data loaded successfully.", icon: <CheckCircle2Icon /> },
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function DataState({
|
|
31
|
+
status,
|
|
32
|
+
title,
|
|
33
|
+
description,
|
|
34
|
+
actions,
|
|
35
|
+
icon,
|
|
36
|
+
compact = false,
|
|
37
|
+
children,
|
|
38
|
+
retryLabel = "Retry",
|
|
39
|
+
onRetry,
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}: DataStateProps) {
|
|
43
|
+
const content = defaultContent[status]
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Card data-slot="data-state" data-status={status} className={cn("min-w-0", className)} {...props}>
|
|
47
|
+
<CardContent className={cn("flex flex-col items-center justify-center text-center", compact ? "p-4" : "min-h-52 p-8")}>
|
|
48
|
+
<div className={cn("mb-3 flex items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-5", compact ? "size-9" : "size-12")}>{icon ?? content.icon}</div>
|
|
49
|
+
<div className={cn("font-semibold", compact ? "text-sm" : "text-base")}>{title ?? content.title}</div>
|
|
50
|
+
<p className="mt-1 max-w-md text-sm text-muted-foreground">{description ?? content.description}</p>
|
|
51
|
+
{children && <div className="mt-4 w-full">{children}</div>}
|
|
52
|
+
{(actions || onRetry) && (
|
|
53
|
+
<div className="mt-4 flex flex-wrap justify-center gap-2">
|
|
54
|
+
{onRetry && <Button size="sm" variant={status === "error" ? "default" : "outline"} onClick={onRetry}>{retryLabel}</Button>}
|
|
55
|
+
{actions}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
</CardContent>
|
|
59
|
+
</Card>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { DataState }
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
export type DescriptionListColumn = 1 | 2 | 3 | 4
|
|
7
|
+
|
|
8
|
+
export type DescriptionListItem = {
|
|
9
|
+
key: string
|
|
10
|
+
label: React.ReactNode
|
|
11
|
+
value?: React.ReactNode
|
|
12
|
+
description?: React.ReactNode
|
|
13
|
+
icon?: React.ReactNode
|
|
14
|
+
span?: DescriptionListColumn
|
|
15
|
+
hidden?: boolean
|
|
16
|
+
className?: string
|
|
17
|
+
labelClassName?: string
|
|
18
|
+
valueClassName?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type DescriptionListProps = React.ComponentProps<typeof Card> & {
|
|
22
|
+
title?: React.ReactNode
|
|
23
|
+
description?: React.ReactNode
|
|
24
|
+
actions?: React.ReactNode
|
|
25
|
+
items: DescriptionListItem[]
|
|
26
|
+
columns?: DescriptionListColumn
|
|
27
|
+
bordered?: boolean
|
|
28
|
+
compact?: boolean
|
|
29
|
+
emptyValue?: React.ReactNode
|
|
30
|
+
itemClassName?: string
|
|
31
|
+
labelClassName?: string
|
|
32
|
+
valueClassName?: string
|
|
33
|
+
contentClassName?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const columnsClassName: Record<DescriptionListColumn, string> = {
|
|
37
|
+
1: "grid-cols-1",
|
|
38
|
+
2: "grid-cols-1 md:grid-cols-2",
|
|
39
|
+
3: "grid-cols-1 md:grid-cols-2 xl:grid-cols-3",
|
|
40
|
+
4: "grid-cols-1 md:grid-cols-2 xl:grid-cols-4",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const spanClassName: Record<DescriptionListColumn, string> = {
|
|
44
|
+
1: "col-span-1",
|
|
45
|
+
2: "md:col-span-2",
|
|
46
|
+
3: "xl:col-span-3",
|
|
47
|
+
4: "xl:col-span-4",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isEmptyValue(value: React.ReactNode) {
|
|
51
|
+
return value === null || value === undefined || value === ""
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function DescriptionList({
|
|
55
|
+
title,
|
|
56
|
+
description,
|
|
57
|
+
actions,
|
|
58
|
+
items,
|
|
59
|
+
columns = 2,
|
|
60
|
+
bordered = true,
|
|
61
|
+
compact = false,
|
|
62
|
+
emptyValue = "-",
|
|
63
|
+
itemClassName,
|
|
64
|
+
labelClassName,
|
|
65
|
+
valueClassName,
|
|
66
|
+
contentClassName,
|
|
67
|
+
className,
|
|
68
|
+
...props
|
|
69
|
+
}: DescriptionListProps) {
|
|
70
|
+
const visibleItems = items.filter((item) => !item.hidden)
|
|
71
|
+
const hasHeader = Boolean(title || description || actions)
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<Card data-slot="description-list" className={cn("min-w-0", className)} {...props}>
|
|
75
|
+
{hasHeader && (
|
|
76
|
+
<CardHeader>
|
|
77
|
+
<div className="flex min-w-0 items-start justify-between gap-3">
|
|
78
|
+
<div className="min-w-0 space-y-1">
|
|
79
|
+
{title && <CardTitle>{title}</CardTitle>}
|
|
80
|
+
{description && <CardDescription>{description}</CardDescription>}
|
|
81
|
+
</div>
|
|
82
|
+
{actions && <div className="shrink-0">{actions}</div>}
|
|
83
|
+
</div>
|
|
84
|
+
</CardHeader>
|
|
85
|
+
)}
|
|
86
|
+
<CardContent className={cn("grid gap-2", columnsClassName[columns], contentClassName)}>
|
|
87
|
+
{visibleItems.map((item) => (
|
|
88
|
+
<div
|
|
89
|
+
key={item.key}
|
|
90
|
+
data-slot="description-list-item"
|
|
91
|
+
className={cn(
|
|
92
|
+
"min-w-0 rounded-lg",
|
|
93
|
+
bordered && "border bg-muted/20",
|
|
94
|
+
compact ? "p-2" : "p-3",
|
|
95
|
+
item.span && item.span > 1 && spanClassName[item.span],
|
|
96
|
+
itemClassName,
|
|
97
|
+
item.className
|
|
98
|
+
)}
|
|
99
|
+
>
|
|
100
|
+
<div className="flex min-w-0 items-start gap-2">
|
|
101
|
+
{item.icon && <span className="mt-0.5 shrink-0 text-muted-foreground [&_svg]:size-4">{item.icon}</span>}
|
|
102
|
+
<div className="min-w-0 flex-1 space-y-1">
|
|
103
|
+
<div className={cn("text-xs font-medium uppercase tracking-wide text-muted-foreground", labelClassName, item.labelClassName)}>
|
|
104
|
+
{item.label}
|
|
105
|
+
</div>
|
|
106
|
+
<div className={cn("min-w-0 break-words text-sm font-medium text-foreground", valueClassName, item.valueClassName)}>
|
|
107
|
+
{isEmptyValue(item.value) ? emptyValue : item.value}
|
|
108
|
+
</div>
|
|
109
|
+
{item.description && <div className="text-xs leading-5 text-muted-foreground">{item.description}</div>}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
))}
|
|
114
|
+
</CardContent>
|
|
115
|
+
</Card>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { DescriptionList }
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
export type DescriptionItem = {
|
|
6
|
+
key: string
|
|
7
|
+
label: React.ReactNode
|
|
8
|
+
value: React.ReactNode
|
|
9
|
+
span?: 1 | 2 | 3 | 4
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type DescriptionsProps = React.ComponentProps<"div"> & {
|
|
13
|
+
items: DescriptionItem[]
|
|
14
|
+
title?: React.ReactNode
|
|
15
|
+
extra?: React.ReactNode
|
|
16
|
+
bordered?: boolean
|
|
17
|
+
columns?: 1 | 2 | 3 | 4
|
|
18
|
+
size?: "sm" | "md" | "lg"
|
|
19
|
+
labelClassName?: string
|
|
20
|
+
valueClassName?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const gapClassName = {
|
|
24
|
+
sm: "gap-2 text-sm",
|
|
25
|
+
md: "gap-3 text-sm",
|
|
26
|
+
lg: "gap-4 text-base",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function Descriptions({
|
|
30
|
+
items,
|
|
31
|
+
title,
|
|
32
|
+
extra,
|
|
33
|
+
bordered = true,
|
|
34
|
+
columns = 3,
|
|
35
|
+
size = "md",
|
|
36
|
+
labelClassName,
|
|
37
|
+
valueClassName,
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}: DescriptionsProps) {
|
|
41
|
+
return (
|
|
42
|
+
<div data-slot="descriptions" className={cn("grid gap-3", className)} {...props}>
|
|
43
|
+
{(title || extra) && (
|
|
44
|
+
<div className="flex items-center justify-between gap-3">
|
|
45
|
+
{title && <div className="text-base font-semibold text-foreground">{title}</div>}
|
|
46
|
+
{extra}
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
<div
|
|
50
|
+
className={cn(
|
|
51
|
+
"grid overflow-hidden",
|
|
52
|
+
bordered && "rounded-lg border bg-card",
|
|
53
|
+
!bordered && gapClassName[size],
|
|
54
|
+
columns === 1 && "grid-cols-1",
|
|
55
|
+
columns === 2 && "grid-cols-1 sm:grid-cols-2",
|
|
56
|
+
columns === 3 && "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
57
|
+
columns === 4 && "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
58
|
+
)}
|
|
59
|
+
>
|
|
60
|
+
{items.map((item) => (
|
|
61
|
+
<div
|
|
62
|
+
key={item.key}
|
|
63
|
+
data-slot="descriptions-item"
|
|
64
|
+
className={cn(
|
|
65
|
+
"min-w-0",
|
|
66
|
+
bordered ? "border-b border-r p-3 last:border-b-0" : "grid gap-1",
|
|
67
|
+
item.span === 2 && "sm:col-span-2",
|
|
68
|
+
item.span === 3 && "lg:col-span-3",
|
|
69
|
+
item.span === 4 && "lg:col-span-4"
|
|
70
|
+
)}
|
|
71
|
+
>
|
|
72
|
+
<div className={cn("text-xs font-medium uppercase tracking-wide text-muted-foreground", labelClassName)}>
|
|
73
|
+
{item.label}
|
|
74
|
+
</div>
|
|
75
|
+
<div className={cn("mt-1 min-w-0 break-words text-sm text-foreground", valueClassName)}>{item.value}</div>
|
|
76
|
+
</div>
|
|
77
|
+
))}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { Descriptions }
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { Card } from "@/components/ui/card"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
export type EntityCardProps = React.ComponentProps<typeof Card> & {
|
|
7
|
+
title: React.ReactNode
|
|
8
|
+
description?: React.ReactNode
|
|
9
|
+
media?: React.ReactNode
|
|
10
|
+
icon?: React.ReactNode
|
|
11
|
+
status?: React.ReactNode
|
|
12
|
+
meta?: React.ReactNode
|
|
13
|
+
actions?: React.ReactNode
|
|
14
|
+
footer?: React.ReactNode
|
|
15
|
+
selected?: boolean
|
|
16
|
+
disabled?: boolean
|
|
17
|
+
orientation?: "vertical" | "horizontal"
|
|
18
|
+
onSelect?: () => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function EntityCard({ title, description, media, icon, status, meta, actions, footer, selected = false, disabled = false, orientation = "vertical", onSelect, className, ...props }: EntityCardProps) {
|
|
22
|
+
return (
|
|
23
|
+
<Card
|
|
24
|
+
data-slot="entity-card"
|
|
25
|
+
data-selected={selected || undefined}
|
|
26
|
+
data-disabled={disabled || undefined}
|
|
27
|
+
className={cn("overflow-hidden transition-colors hover:bg-muted/35 data-[selected=true]:border-primary data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-55", onSelect && "cursor-pointer", orientation === "horizontal" && "flex", className)}
|
|
28
|
+
onClick={onSelect}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{media && <div className={cn("bg-muted", orientation === "horizontal" ? "w-32 shrink-0" : "aspect-video")}>{media}</div>}
|
|
32
|
+
<div className="grid min-w-0 flex-1 gap-3 p-4">
|
|
33
|
+
<div className="flex items-start justify-between gap-3">
|
|
34
|
+
<div className="flex min-w-0 items-start gap-3">
|
|
35
|
+
{icon && <div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">{icon}</div>}
|
|
36
|
+
<div className="grid min-w-0 gap-1">
|
|
37
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
38
|
+
<div className="truncate text-sm font-medium text-foreground">{title}</div>
|
|
39
|
+
{status}
|
|
40
|
+
</div>
|
|
41
|
+
{description && <div className="line-clamp-2 text-sm text-muted-foreground">{description}</div>}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
{actions && <div className="shrink-0" onClick={(event) => event.stopPropagation()}>{actions}</div>}
|
|
45
|
+
</div>
|
|
46
|
+
{meta && <div className="text-xs text-muted-foreground">{meta}</div>}
|
|
47
|
+
{footer && <div className="border-t pt-3 text-sm text-muted-foreground">{footer}</div>}
|
|
48
|
+
</div>
|
|
49
|
+
</Card>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { EntityCard }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { FileIcon, MoreHorizontalIcon } from "lucide-react"
|
|
3
|
+
|
|
4
|
+
import { Button } from "@/components/ui/button"
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
export type FileCardProps = React.ComponentProps<"div"> & {
|
|
8
|
+
name: React.ReactNode
|
|
9
|
+
description?: React.ReactNode
|
|
10
|
+
meta?: React.ReactNode
|
|
11
|
+
icon?: React.ReactNode
|
|
12
|
+
preview?: React.ReactNode
|
|
13
|
+
actions?: React.ReactNode
|
|
14
|
+
selected?: boolean
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
onOpen?: () => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function FileCard({ name, description, meta, icon, preview, actions, selected = false, disabled = false, onOpen, className, ...props }: FileCardProps) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
data-slot="file-card"
|
|
23
|
+
data-selected={selected || undefined}
|
|
24
|
+
data-disabled={disabled || undefined}
|
|
25
|
+
className={cn(
|
|
26
|
+
"group grid gap-3 rounded-lg border bg-card p-3 transition-colors hover:bg-muted/35 data-[selected=true]:border-primary data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-55",
|
|
27
|
+
onOpen && "cursor-pointer",
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
onClick={onOpen}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
{preview && <div className="overflow-hidden rounded-md bg-muted">{preview}</div>}
|
|
34
|
+
<div className="flex items-start gap-3">
|
|
35
|
+
<div className="flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
|
36
|
+
{icon ?? <FileIcon className="size-4" />}
|
|
37
|
+
</div>
|
|
38
|
+
<div className="min-w-0 flex-1">
|
|
39
|
+
<div className="truncate text-sm font-medium text-foreground">{name}</div>
|
|
40
|
+
{description && <div className="mt-0.5 line-clamp-2 text-xs text-muted-foreground">{description}</div>}
|
|
41
|
+
{meta && <div className="mt-2 text-xs text-muted-foreground">{meta}</div>}
|
|
42
|
+
</div>
|
|
43
|
+
{actions ?? (
|
|
44
|
+
<Button type="button" variant="ghost" size="icon-xs" onClick={(event) => event.stopPropagation()}>
|
|
45
|
+
<MoreHorizontalIcon />
|
|
46
|
+
<span className="sr-only">File actions</span>
|
|
47
|
+
</Button>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { FileCard }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export * from "./description-list"
|
|
2
|
+
export * from "./progress"
|
|
3
|
+
export * from "./result"
|
|
4
|
+
export * from "./timeline"
|
|
5
|
+
export * from "./metric-grid"
|
|
6
|
+
export * from "./activity-feed"
|
|
7
|
+
export * from "./status-legend"
|
|
8
|
+
export * from "./avatar"
|
|
9
|
+
export * from "./data-state"
|
|
10
|
+
export * from "./statistic"
|
|
11
|
+
export * from "./list"
|
|
12
|
+
export * from "./descriptions"
|
|
13
|
+
export * from "./kanban"
|
|
14
|
+
export * from "./tag-list"
|
|
15
|
+
export * from "./tree-view"
|
|
16
|
+
export * from "./keyboard-shortcut"
|
|
17
|
+
export * from "./code-block"
|
|
18
|
+
export * from "./file-card"
|
|
19
|
+
export * from "./property-grid"
|
|
20
|
+
export * from "./entity-card"
|
|
21
|
+
export {
|
|
22
|
+
SmartCard as InfoCard,
|
|
23
|
+
type SmartCardClassNames as InfoCardClassNames,
|
|
24
|
+
type SmartCardDensity as InfoCardDensity,
|
|
25
|
+
type SmartCardOrientation as InfoCardOrientation,
|
|
26
|
+
type SmartCardProps as InfoCardProps,
|
|
27
|
+
type SmartCardRenderContext as InfoCardRenderContext,
|
|
28
|
+
type SmartCardSize as InfoCardSize,
|
|
29
|
+
type SmartCardVariant as InfoCardVariant,
|
|
30
|
+
} from "./smart-card"
|