@trackany-device/components 1.0.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/package.json +185 -0
- package/src/assets/logo.png +0 -0
- package/src/assets/map/arrows/map-arrow-blue.png +0 -0
- package/src/assets/map/arrows/map-arrow-green.png +0 -0
- package/src/assets/map/arrows/map-arrow-purple.png +0 -0
- package/src/assets/map/arrows/map-arrow-red.png +0 -0
- package/src/assets/map/flags/flag-blue.png +0 -0
- package/src/assets/map/flags/flag-green.png +0 -0
- package/src/assets/map/flags/flag-red.png +0 -0
- package/src/assets/map/flags/flag-yellow.png +0 -0
- package/src/assets/map/pins/map-pin-blue.png +0 -0
- package/src/assets/map/pins/map-pin-green.png +0 -0
- package/src/assets/map/pins/map-pin-purple.png +0 -0
- package/src/assets/map/pins/map-pin-red.png +0 -0
- package/src/components/Card.tsx +9 -0
- package/src/components/alert-error.tsx +24 -0
- package/src/components/app-content.tsx +22 -0
- package/src/components/app-header.tsx +153 -0
- package/src/components/app-logo-icon.tsx +13 -0
- package/src/components/app-logo.tsx +21 -0
- package/src/components/app-shell.tsx +19 -0
- package/src/components/app-sidebar-header.tsx +68 -0
- package/src/components/app-sidebar.tsx +106 -0
- package/src/components/appearance-tabs.tsx +46 -0
- package/src/components/breadcrumbs.tsx +50 -0
- package/src/components/cms/blurred-image.tsx +111 -0
- package/src/components/cms/section-bg.tsx +473 -0
- package/src/components/cms/section-button.tsx +127 -0
- package/src/components/cms/sections/banner-5050-section.tsx +135 -0
- package/src/components/cms/sections/blogs-listing-section.tsx +270 -0
- package/src/components/cms/sections/cards-grid-section.tsx +185 -0
- package/src/components/cms/sections/contact-form-section.tsx +157 -0
- package/src/components/cms/sections/cta-section.tsx +101 -0
- package/src/components/cms/sections/featured-blog-slider-section.tsx +256 -0
- package/src/components/cms/sections/featured-products-grid-section.tsx +173 -0
- package/src/components/cms/sections/featured-solutions-grid-section.tsx +183 -0
- package/src/components/cms/sections/hero-section.tsx +180 -0
- package/src/components/cms/sections/solutions-with-filter-section.tsx +234 -0
- package/src/components/cms/sections/text-section.tsx +77 -0
- package/src/components/cutout-image.tsx +228 -0
- package/src/components/devices/devices-mini-map.tsx +275 -0
- package/src/components/docs/docs-shell.tsx +280 -0
- package/src/components/fleet-hero-animated.tsx +383 -0
- package/src/components/input-error.tsx +17 -0
- package/src/components/keenicons/assets/duotone/Read Me.txt +7 -0
- package/src/components/keenicons/assets/duotone/demo-files/demo.css +160 -0
- package/src/components/keenicons/assets/duotone/demo-files/demo.js +32 -0
- package/src/components/keenicons/assets/duotone/demo.html +12424 -0
- package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.svg +1109 -0
- package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.ttf +0 -0
- package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.woff +0 -0
- package/src/components/keenicons/assets/duotone/selection.json +17313 -0
- package/src/components/keenicons/assets/duotone/style.css +4931 -0
- package/src/components/keenicons/assets/filled/Read Me.txt +7 -0
- package/src/components/keenicons/assets/filled/demo-files/demo.css +160 -0
- package/src/components/keenicons/assets/filled/demo-files/demo.js +32 -0
- package/src/components/keenicons/assets/filled/demo.html +12370 -0
- package/src/components/keenicons/assets/filled/fonts/keenicons-filled.svg +1082 -0
- package/src/components/keenicons/assets/filled/fonts/keenicons-filled.ttf +0 -0
- package/src/components/keenicons/assets/filled/fonts/keenicons-filled.woff +0 -0
- package/src/components/keenicons/assets/filled/selection.json +17096 -0
- package/src/components/keenicons/assets/filled/style.css +4769 -0
- package/src/components/keenicons/assets/outline/Read Me.txt +7 -0
- package/src/components/keenicons/assets/outline/demo-files/demo.css +160 -0
- package/src/components/keenicons/assets/outline/demo-files/demo.js +32 -0
- package/src/components/keenicons/assets/outline/demo.html +11356 -0
- package/src/components/keenicons/assets/outline/fonts/keenicons-outline.svg +575 -0
- package/src/components/keenicons/assets/outline/fonts/keenicons-outline.ttf +0 -0
- package/src/components/keenicons/assets/outline/fonts/keenicons-outline.woff +0 -0
- package/src/components/keenicons/assets/outline/selection.json +13054 -0
- package/src/components/keenicons/assets/outline/style.css +1721 -0
- package/src/components/keenicons/assets/solid/Read Me.txt +7 -0
- package/src/components/keenicons/assets/solid/demo-files/demo.css +160 -0
- package/src/components/keenicons/assets/solid/demo-files/demo.js +32 -0
- package/src/components/keenicons/assets/solid/demo.html +11356 -0
- package/src/components/keenicons/assets/solid/fonts/keenicons-solid.svg +575 -0
- package/src/components/keenicons/assets/solid/fonts/keenicons-solid.ttf +0 -0
- package/src/components/keenicons/assets/solid/fonts/keenicons-solid.woff +0 -0
- package/src/components/keenicons/assets/solid/selection.json +13048 -0
- package/src/components/keenicons/assets/solid/style.css +1721 -0
- package/src/components/keenicons/assets/styles.css +4 -0
- package/src/components/keenicons/index.ts +2 -0
- package/src/components/keenicons/keenicons.tsx +16 -0
- package/src/components/keenicons/types.ts +7 -0
- package/src/components/nav-footer.tsx +49 -0
- package/src/components/nav-main.tsx +53 -0
- package/src/components/nav-user.tsx +59 -0
- package/src/components/notification-bell.tsx +190 -0
- package/src/components/products/product-card.tsx +159 -0
- package/src/components/text-link.tsx +23 -0
- package/src/components/ui/accordion-menu.tsx +322 -0
- package/src/components/ui/accordion.tsx +133 -0
- package/src/components/ui/alert-dialog.tsx +82 -0
- package/src/components/ui/alert.tsx +63 -0
- package/src/components/ui/avatar-group.tsx +129 -0
- package/src/components/ui/avatar.tsx +67 -0
- package/src/components/ui/badge.tsx +230 -0
- package/src/components/ui/breadcrumb.tsx +88 -0
- package/src/components/ui/button.tsx +412 -0
- package/src/components/ui/calendar.tsx +56 -0
- package/src/components/ui/card.tsx +147 -0
- package/src/components/ui/chart.tsx +290 -0
- package/src/components/ui/checkbox.tsx +47 -0
- package/src/components/ui/code.tsx +45 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/command-palette.tsx +189 -0
- package/src/components/ui/command.tsx +138 -0
- package/src/components/ui/cookie-banner.tsx +220 -0
- package/src/components/ui/copy-button.tsx +60 -0
- package/src/components/ui/data-grid-column-filter.tsx +124 -0
- package/src/components/ui/data-grid-column-header.tsx +284 -0
- package/src/components/ui/data-grid-column-visibility.tsx +38 -0
- package/src/components/ui/data-grid-pagination.tsx +206 -0
- package/src/components/ui/data-grid-table-dnd-rows.tsx +147 -0
- package/src/components/ui/data-grid-table-dnd.tsx +175 -0
- package/src/components/ui/data-grid-table.tsx +500 -0
- package/src/components/ui/data-grid.tsx +193 -0
- package/src/components/ui/data-list.tsx +76 -0
- package/src/components/ui/datefield.tsx +91 -0
- package/src/components/ui/dialog.tsx +139 -0
- package/src/components/ui/divider.tsx +41 -0
- package/src/components/ui/drawer.tsx +59 -0
- package/src/components/ui/dropdown-menu.tsx +224 -0
- package/src/components/ui/empty-state.tsx +54 -0
- package/src/components/ui/file-upload.tsx +152 -0
- package/src/components/ui/form.tsx +88 -0
- package/src/components/ui/icon.tsx +14 -0
- package/src/components/ui/input-otp.tsx +71 -0
- package/src/components/ui/input.tsx +155 -0
- package/src/components/ui/kbd.tsx +26 -0
- package/src/components/ui/label.tsx +31 -0
- package/src/components/ui/navigation-menu.tsx +168 -0
- package/src/components/ui/pagination.tsx +37 -0
- package/src/components/ui/placeholder-pattern.tsx +21 -0
- package/src/components/ui/popover.tsx +50 -0
- package/src/components/ui/progress.tsx +65 -0
- package/src/components/ui/radio-group.tsx +73 -0
- package/src/components/ui/resizable.tsx +39 -0
- package/src/components/ui/scroll-area.tsx +50 -0
- package/src/components/ui/select.tsx +234 -0
- package/src/components/ui/separator.tsx +24 -0
- package/src/components/ui/sheet.tsx +147 -0
- package/src/components/ui/sidebar.tsx +721 -0
- package/src/components/ui/skeleton.tsx +15 -0
- package/src/components/ui/slider.tsx +35 -0
- package/src/components/ui/sonner.tsx +28 -0
- package/src/components/ui/sortable.tsx +724 -0
- package/src/components/ui/spinner.tsx +17 -0
- package/src/components/ui/stat-card.tsx +82 -0
- package/src/components/ui/stepper.tsx +410 -0
- package/src/components/ui/switch.tsx +68 -0
- package/src/components/ui/table.tsx +42 -0
- package/src/components/ui/tabs.tsx +196 -0
- package/src/components/ui/timeline.tsx +90 -0
- package/src/components/ui/toggle-group.tsx +73 -0
- package/src/components/ui/toggle.tsx +45 -0
- package/src/components/ui/tooltip.tsx +55 -0
- package/src/components/user-info.tsx +33 -0
- package/src/components/user-menu-content.tsx +53 -0
- package/src/components/web/SiteFooter.tsx +154 -0
- package/src/components/web/SiteHeader.tsx +159 -0
- package/src/components/workflows/workflow-canvas.tsx +321 -0
- package/src/controls/Blockquote.tsx +25 -0
- package/src/controls/Button.tsx +101 -0
- package/src/controls/Checkbox.tsx +29 -0
- package/src/controls/DateField.tsx +37 -0
- package/src/controls/FormField.tsx +20 -0
- package/src/controls/Heading.tsx +28 -0
- package/src/controls/Input.tsx +21 -0
- package/src/controls/Label.tsx +18 -0
- package/src/controls/Paragraph.tsx +39 -0
- package/src/controls/PasswordInput.tsx +40 -0
- package/src/controls/RadioGroup.tsx +70 -0
- package/src/controls/Select.tsx +24 -0
- package/src/controls/Slider.tsx +33 -0
- package/src/controls/Switch.tsx +31 -0
- package/src/controls/Textarea.tsx +22 -0
- package/src/elements/ConfirmPasswordForm.tsx +43 -0
- package/src/elements/DeviceStatusBadge.tsx +38 -0
- package/src/elements/DriverCard.tsx +67 -0
- package/src/elements/ForgotPasswordForm.tsx +64 -0
- package/src/elements/IncidentCard.tsx +67 -0
- package/src/elements/LoginForm.tsx +100 -0
- package/src/elements/OtpForm.tsx +71 -0
- package/src/elements/RegisterForm.tsx +150 -0
- package/src/elements/ResetPasswordForm.tsx +72 -0
- package/src/elements/SmsChallengeForm.tsx +104 -0
- package/src/elements/VehicleCard.tsx +73 -0
- package/src/elements/VerifyEmailForm.tsx +39 -0
- package/src/hooks/use-appearance.tsx +117 -0
- package/src/hooks/use-applied-theme.ts +98 -0
- package/src/hooks/use-clipboard.ts +34 -0
- package/src/hooks/use-current-url.ts +83 -0
- package/src/hooks/use-dark-mode.ts +48 -0
- package/src/hooks/use-flash-toast.ts +29 -0
- package/src/hooks/use-initials.tsx +24 -0
- package/src/hooks/use-mobile-navigation.ts +12 -0
- package/src/hooks/use-mobile.tsx +38 -0
- package/src/index.ts +408 -0
- package/src/layouts/AppLayout.tsx +60 -0
- package/src/layouts/AuthLayout.tsx +32 -0
- package/src/layouts/SettingsLayout.tsx +21 -0
- package/src/layouts/app/AIChatLayout.tsx +73 -0
- package/src/layouts/app/AsideSidebarLayout.tsx +3 -0
- package/src/layouts/app/CalendarSidebarLayout.tsx +69 -0
- package/src/layouts/app/CommunitiesNavbarLayout.tsx +3 -0
- package/src/layouts/app/DualNavbarSidebarLayout.tsx +3 -0
- package/src/layouts/app/FocusSidebarLayout.tsx +75 -0
- package/src/layouts/app/MailLayout.tsx +69 -0
- package/src/layouts/app/MegaMenuHeaderLayout.tsx +3 -0
- package/src/layouts/app/MegaMenuLayout.tsx +81 -0
- package/src/layouts/app/MegaMenuNavbarLayout.tsx +88 -0
- package/src/layouts/app/MegaMenuSearchNavbarLayout.tsx +3 -0
- package/src/layouts/app/NavbarCollapsibleLayout.tsx +88 -0
- package/src/layouts/app/NavbarCollapsibleLinksLayout.tsx +3 -0
- package/src/layouts/app/NavbarMinimalLayout.tsx +3 -0
- package/src/layouts/app/NavbarMinimalSidebarLayout.tsx +3 -0
- package/src/layouts/app/NavbarSidebarDashboardLayout.tsx +3 -0
- package/src/layouts/app/NavbarSidebarLayout.tsx +92 -0
- package/src/layouts/app/NavbarSimpleSidebarLayout.tsx +3 -0
- package/src/layouts/app/NavbarTitledSidebarLayout.tsx +3 -0
- package/src/layouts/app/PanelSidebarLayout.tsx +3 -0
- package/src/layouts/app/SearchNavbarSidebarLayout.tsx +3 -0
- package/src/layouts/app/SidebarBreadcrumbLayout.tsx +3 -0
- package/src/layouts/app/SidebarCleanLayout.tsx +3 -0
- package/src/layouts/app/SidebarCommunitiesLayout.tsx +3 -0
- package/src/layouts/app/SidebarContentLayout.tsx +3 -0
- package/src/layouts/app/SidebarDualMenuLayout.tsx +104 -0
- package/src/layouts/app/SidebarFixedLayout.tsx +166 -0
- package/src/layouts/app/SidebarFooterNavbarLayout.tsx +3 -0
- package/src/layouts/app/SidebarHeaderMenuLayout.tsx +3 -0
- package/src/layouts/app/SidebarMegaMenuLayout.tsx +4 -0
- package/src/layouts/app/SidebarMinimalLayout.tsx +70 -0
- package/src/layouts/app/SidebarMobileSearchLayout.tsx +3 -0
- package/src/layouts/app/SidebarMultiPanelLayout.tsx +3 -0
- package/src/layouts/app/SidebarPrimarySecondaryLayout.tsx +3 -0
- package/src/layouts/app/SidebarSearchHeaderLayout.tsx +103 -0
- package/src/layouts/app/SidebarSearchToolbarLayout.tsx +3 -0
- package/src/layouts/app/SidebarTabsDualLayout.tsx +3 -0
- package/src/layouts/app/SidebarTabsLayout.tsx +98 -0
- package/src/layouts/app/SidebarTreeLayout.tsx +3 -0
- package/src/layouts/app/SplitNavbarLayout.tsx +3 -0
- package/src/layouts/app/SplitSidebarDashboardLayout.tsx +3 -0
- package/src/layouts/app/SplitSidebarLayout.tsx +99 -0
- package/src/layouts/app/TopNavLayout.tsx +105 -0
- package/src/layouts/app/TopNavLinksLayout.tsx +3 -0
- package/src/layouts/app/WorkspaceBreadcrumbLayout.tsx +3 -0
- package/src/layouts/app/WorkspaceCommunitiesLayout.tsx +3 -0
- package/src/layouts/app/WorkspaceNavbarLayout.tsx +3 -0
- package/src/layouts/app/WorkspaceSidebarLayout.tsx +98 -0
- package/src/layouts/app/WorkspaceSidebarTitleLayout.tsx +3 -0
- package/src/layouts/app/app-header-layout.tsx +45 -0
- package/src/layouts/app/app-sidebar-layout.tsx +56 -0
- package/src/layouts/app/layout-context.tsx +44 -0
- package/src/layouts/app/layout-types.ts +47 -0
- package/src/layouts/app/partials/Footer.tsx +35 -0
- package/src/layouts/app/partials/HeaderTopbar.tsx +96 -0
- package/src/layouts/app/partials/Navbar.tsx +85 -0
- package/src/layouts/app/partials/Toolbar.tsx +47 -0
- package/src/layouts/app-layout.tsx +29 -0
- package/src/layouts/auth/AuthBrandedLayout.tsx +58 -0
- package/src/layouts/auth/AuthCardLayout.tsx +31 -0
- package/src/layouts/auth/AuthCenteredLayout.tsx +41 -0
- package/src/layouts/auth/AuthClassicLayout.tsx +41 -0
- package/src/layouts/auth/AuthSimpleLayout.tsx +33 -0
- package/src/layouts/auth/AuthSplitLayout.tsx +89 -0
- package/src/layouts/web-app-layout.tsx +162 -0
- package/src/layouts/web-layout.tsx +23 -0
- package/src/lib/datetime.ts +188 -0
- package/src/lib/google-maps-loader.ts +99 -0
- package/src/lib/location.ts +127 -0
- package/src/lib/lucide-icon-map.ts +132 -0
- package/src/lib/map-markers.ts +124 -0
- package/src/lib/map-styles.ts +351 -0
- package/src/lib/utils.ts +11 -0
- package/src/platform/adapters/default.tsx +156 -0
- package/src/platform/adapters/inertia.tsx +88 -0
- package/src/platform/adapters/nextjs.ts +86 -0
- package/src/platform/context.tsx +106 -0
- package/src/platform/index.ts +27 -0
- package/src/platform/types.ts +105 -0
- package/src/styles/layouts/sidebar-fixed.css +161 -0
- package/src/styles/themes.css +583 -0
- package/src/types/assets.d.ts +5 -0
- package/src/types/auth.ts +25 -0
- package/src/types/global.d.ts +13 -0
- package/src/types/index.ts +9 -0
- package/src/types/navigation.ts +15 -0
- package/src/types/ui.ts +32 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
5
|
+
import { ChevronDown } from 'lucide-react';
|
|
6
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
7
|
+
import { cn } from '../../lib/utils';
|
|
8
|
+
|
|
9
|
+
interface AccordionMenuContextValue {
|
|
10
|
+
matchPath: (href: string) => boolean;
|
|
11
|
+
selectedValue: string | undefined;
|
|
12
|
+
setSelectedValue: React.Dispatch<React.SetStateAction<string | undefined>>;
|
|
13
|
+
classNames?: AccordionMenuClassNames;
|
|
14
|
+
nestedStates: Record<string, string | string[]>;
|
|
15
|
+
setNestedStates: React.Dispatch<React.SetStateAction<Record<string, string | string[]>>>;
|
|
16
|
+
onItemClick?: (value: string, event: React.MouseEvent) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface AccordionMenuClassNames {
|
|
20
|
+
root?: string;
|
|
21
|
+
group?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
separator?: string;
|
|
24
|
+
item?: string;
|
|
25
|
+
sub?: string;
|
|
26
|
+
subTrigger?: string;
|
|
27
|
+
subContent?: string;
|
|
28
|
+
subWrapper?: string;
|
|
29
|
+
indicator?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface AccordionMenuProps {
|
|
33
|
+
selectedValue?: string;
|
|
34
|
+
matchPath?: (href: string) => boolean;
|
|
35
|
+
classNames?: AccordionMenuClassNames;
|
|
36
|
+
onItemClick?: (value: string, event: React.MouseEvent) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const AccordionMenuContext = React.createContext<AccordionMenuContextValue>({
|
|
40
|
+
matchPath: () => false,
|
|
41
|
+
selectedValue: '',
|
|
42
|
+
setSelectedValue: () => {},
|
|
43
|
+
nestedStates: {},
|
|
44
|
+
setNestedStates: () => {},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function AccordionMenu({
|
|
48
|
+
className,
|
|
49
|
+
matchPath = () => false,
|
|
50
|
+
classNames,
|
|
51
|
+
children,
|
|
52
|
+
selectedValue,
|
|
53
|
+
onItemClick,
|
|
54
|
+
...props
|
|
55
|
+
}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root> & AccordionMenuProps) {
|
|
56
|
+
const [internalSelectedValue, setInternalSelectedValue] = React.useState<string | undefined>(selectedValue);
|
|
57
|
+
|
|
58
|
+
React.useEffect(() => {
|
|
59
|
+
setInternalSelectedValue(selectedValue);
|
|
60
|
+
}, [selectedValue]);
|
|
61
|
+
|
|
62
|
+
const initialNestedStates = React.useMemo(() => {
|
|
63
|
+
const getActiveChain = (nodes: React.ReactNode, chain: string[] = []): string[] => {
|
|
64
|
+
let result: string[] = [];
|
|
65
|
+
React.Children.forEach(nodes, (node) => {
|
|
66
|
+
if (React.isValidElement(node)) {
|
|
67
|
+
const { value, children: nodeChildren } = node.props as {
|
|
68
|
+
value?: string;
|
|
69
|
+
children?: React.ReactNode;
|
|
70
|
+
};
|
|
71
|
+
const newChain = value ? [...chain, value] : chain;
|
|
72
|
+
if (value && (value === selectedValue || matchPath(value))) {
|
|
73
|
+
result = newChain;
|
|
74
|
+
} else if (nodeChildren) {
|
|
75
|
+
const childChain = getActiveChain(nodeChildren, newChain);
|
|
76
|
+
if (childChain.length > 0) result = childChain;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return result;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const chain = getActiveChain(children);
|
|
84
|
+
const trimmedChain = chain.length > 1 ? chain.slice(0, chain.length - 1) : chain;
|
|
85
|
+
const mapping: Record<string, string | string[]> = {};
|
|
86
|
+
if (trimmedChain.length > 0) {
|
|
87
|
+
if (props.type === 'multiple') {
|
|
88
|
+
mapping['root'] = trimmedChain;
|
|
89
|
+
} else {
|
|
90
|
+
mapping['root'] = trimmedChain[0];
|
|
91
|
+
for (let i = 0; i < trimmedChain.length - 1; i++) {
|
|
92
|
+
mapping[trimmedChain[i]] = trimmedChain[i + 1];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return mapping;
|
|
97
|
+
}, [children, matchPath, selectedValue, props.type]);
|
|
98
|
+
|
|
99
|
+
const [nestedStates, setNestedStates] = React.useState<Record<string, string | string[]>>(initialNestedStates);
|
|
100
|
+
const multipleValue = (
|
|
101
|
+
Array.isArray(nestedStates['root'])
|
|
102
|
+
? nestedStates['root']
|
|
103
|
+
: typeof nestedStates['root'] === 'string'
|
|
104
|
+
? [nestedStates['root']]
|
|
105
|
+
: []
|
|
106
|
+
) as string[];
|
|
107
|
+
const singleValue = (nestedStates['root'] ?? '') as string;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<AccordionMenuContext.Provider
|
|
111
|
+
value={{ matchPath, selectedValue: internalSelectedValue, setSelectedValue: setInternalSelectedValue, classNames, onItemClick, nestedStates, setNestedStates }}
|
|
112
|
+
>
|
|
113
|
+
{props.type === 'single' ? (
|
|
114
|
+
<AccordionPrimitive.Root
|
|
115
|
+
data-slot="accordion-menu"
|
|
116
|
+
value={singleValue}
|
|
117
|
+
className={cn('w-full', classNames?.root, className)}
|
|
118
|
+
onValueChange={(value: string) => setNestedStates((prev) => ({ ...prev, root: value }))}
|
|
119
|
+
{...props}
|
|
120
|
+
role="menu"
|
|
121
|
+
>
|
|
122
|
+
{children}
|
|
123
|
+
</AccordionPrimitive.Root>
|
|
124
|
+
) : (
|
|
125
|
+
<AccordionPrimitive.Root
|
|
126
|
+
data-slot="accordion-menu"
|
|
127
|
+
value={multipleValue}
|
|
128
|
+
className={cn('w-full', classNames?.root, className)}
|
|
129
|
+
onValueChange={(value: string[]) => setNestedStates((prev) => ({ ...prev, root: value }))}
|
|
130
|
+
{...(props as React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root> & { type: 'multiple' })}
|
|
131
|
+
role="menu"
|
|
132
|
+
>
|
|
133
|
+
{children}
|
|
134
|
+
</AccordionPrimitive.Root>
|
|
135
|
+
)}
|
|
136
|
+
</AccordionMenuContext.Provider>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function AccordionMenuGroup({ children, className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
|
|
141
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
142
|
+
return (
|
|
143
|
+
<div data-slot="accordion-menu-group" role="group" className={cn('space-y-0.5', classNames?.group, className)} {...props}>
|
|
144
|
+
{children}
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function AccordionMenuLabel({ children, className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
|
|
150
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
151
|
+
return (
|
|
152
|
+
<div data-slot="accordion-menu-label" role="presentation" className={cn('px-2 py-1.5 text-xs font-medium text-muted-foreground', classNames?.label, className)} {...props}>
|
|
153
|
+
{children}
|
|
154
|
+
</div>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function AccordionMenuSeparator({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
|
|
159
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
160
|
+
return (
|
|
161
|
+
<div data-slot="accordion-menu-separator" role="separator" className={cn('my-1 h-px bg-border', classNames?.separator, className)} {...props} />
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const itemVariants = cva(
|
|
166
|
+
'relative cursor-pointer select-none flex w-full text-start items-center text-foreground rounded-lg gap-2 px-2 py-1.5 text-sm outline-hidden transition-colors hover:bg-accent hover:text-accent-foreground data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground disabled:opacity-50 disabled:bg-transparent focus-visible:bg-accent focus-visible:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:opacity-60 [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0 [&_a]:flex [&>a]:w-full [&>a]:items-center [&>a]:gap-2',
|
|
167
|
+
{
|
|
168
|
+
variants: {
|
|
169
|
+
variant: {
|
|
170
|
+
default: '',
|
|
171
|
+
destructive: 'text-destructive hover:text-destructive focus:text-destructive hover:bg-destructive/5 focus:bg-destructive/5 data-[active=true]:bg-destructive/5',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
defaultVariants: { variant: 'default' },
|
|
175
|
+
},
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
function AccordionMenuItem({
|
|
179
|
+
className,
|
|
180
|
+
children,
|
|
181
|
+
variant,
|
|
182
|
+
asChild,
|
|
183
|
+
onClick,
|
|
184
|
+
...props
|
|
185
|
+
}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> &
|
|
186
|
+
VariantProps<typeof itemVariants> & {
|
|
187
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
188
|
+
}) {
|
|
189
|
+
const { classNames, selectedValue, matchPath, onItemClick } = React.useContext(AccordionMenuContext);
|
|
190
|
+
return (
|
|
191
|
+
<AccordionPrimitive.Item className="flex" {...props}>
|
|
192
|
+
<AccordionPrimitive.Header className="flex w-full">
|
|
193
|
+
<AccordionPrimitive.Trigger
|
|
194
|
+
asChild={asChild}
|
|
195
|
+
data-slot="accordion-menu-item"
|
|
196
|
+
className={cn(itemVariants({ variant }), classNames?.item, className)}
|
|
197
|
+
onClick={(e) => {
|
|
198
|
+
onItemClick?.(props.value, e);
|
|
199
|
+
onClick?.(e);
|
|
200
|
+
e.preventDefault();
|
|
201
|
+
}}
|
|
202
|
+
onKeyDown={(e) => {
|
|
203
|
+
if (e.key === 'Enter') {
|
|
204
|
+
e.preventDefault();
|
|
205
|
+
(e.currentTarget.firstElementChild as HTMLElement | null)?.click();
|
|
206
|
+
}
|
|
207
|
+
}}
|
|
208
|
+
data-selected={matchPath(props.value as string) || selectedValue === props.value ? 'true' : undefined}
|
|
209
|
+
>
|
|
210
|
+
{children}
|
|
211
|
+
</AccordionPrimitive.Trigger>
|
|
212
|
+
</AccordionPrimitive.Header>
|
|
213
|
+
</AccordionPrimitive.Item>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function AccordionMenuSub({ className, children, ...props }: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>) {
|
|
218
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
219
|
+
return (
|
|
220
|
+
<AccordionPrimitive.Item data-slot="accordion-menu-sub" className={cn(classNames?.sub, className)} {...props}>
|
|
221
|
+
{children}
|
|
222
|
+
</AccordionPrimitive.Item>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function AccordionMenuSubTrigger({ className, children }: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>) {
|
|
227
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
228
|
+
return (
|
|
229
|
+
<AccordionPrimitive.Header className="flex">
|
|
230
|
+
<AccordionPrimitive.Trigger
|
|
231
|
+
data-slot="accordion-menu-sub-trigger"
|
|
232
|
+
className={cn(
|
|
233
|
+
'w-full relative flex items-center cursor-pointer select-none text-start rounded-lg gap-2 px-2 py-1.5 text-sm outline-hidden text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([role=img]):not([class*=text-])]:opacity-60 [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0',
|
|
234
|
+
classNames?.subTrigger,
|
|
235
|
+
className,
|
|
236
|
+
)}
|
|
237
|
+
>
|
|
238
|
+
{children}
|
|
239
|
+
<ChevronDown
|
|
240
|
+
data-slot="accordion-menu-sub-indicator"
|
|
241
|
+
className="ms-auto size-3.5! shrink-0 text-muted-foreground transition-transform duration-200 [[data-state=open]>&]:-rotate-180"
|
|
242
|
+
/>
|
|
243
|
+
</AccordionPrimitive.Trigger>
|
|
244
|
+
</AccordionPrimitive.Header>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
type AccordionMenuSubContentProps = (
|
|
249
|
+
| (React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> & {
|
|
250
|
+
type: 'single';
|
|
251
|
+
collapsible: boolean;
|
|
252
|
+
defaultValue?: string;
|
|
253
|
+
})
|
|
254
|
+
| (React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> & {
|
|
255
|
+
type: 'multiple';
|
|
256
|
+
collapsible?: boolean;
|
|
257
|
+
defaultValue?: string | string[];
|
|
258
|
+
})
|
|
259
|
+
) & { parentValue: string };
|
|
260
|
+
|
|
261
|
+
function AccordionMenuSubContent({ className, children, type, collapsible, defaultValue, parentValue, ...props }: AccordionMenuSubContentProps) {
|
|
262
|
+
const { nestedStates, setNestedStates, classNames } = React.useContext(AccordionMenuContext);
|
|
263
|
+
let currentValue: string | string[];
|
|
264
|
+
if (type === 'multiple') {
|
|
265
|
+
const sv = nestedStates[parentValue];
|
|
266
|
+
currentValue = Array.isArray(sv) ? sv : typeof sv === 'string' ? [sv] : defaultValue ? (Array.isArray(defaultValue) ? defaultValue : [defaultValue]) : [];
|
|
267
|
+
} else {
|
|
268
|
+
currentValue = (nestedStates[parentValue] ?? defaultValue ?? '') as string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<AccordionPrimitive.Content
|
|
273
|
+
data-slot="accordion-menu-sub-content"
|
|
274
|
+
className={cn('ps-5 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down', classNames?.subContent, className)}
|
|
275
|
+
{...props}
|
|
276
|
+
>
|
|
277
|
+
{type === 'multiple' ? (
|
|
278
|
+
<AccordionPrimitive.Root
|
|
279
|
+
className={cn('w-full py-0.5', classNames?.subWrapper)}
|
|
280
|
+
type="multiple"
|
|
281
|
+
value={currentValue as string[]}
|
|
282
|
+
role="menu"
|
|
283
|
+
data-slot="accordion-menu-sub-wrapper"
|
|
284
|
+
onValueChange={(value: string[]) => setNestedStates((prev) => ({ ...prev, [parentValue]: value }))}
|
|
285
|
+
>
|
|
286
|
+
{children}
|
|
287
|
+
</AccordionPrimitive.Root>
|
|
288
|
+
) : (
|
|
289
|
+
<AccordionPrimitive.Root
|
|
290
|
+
className={cn('w-full py-0.5', classNames?.subWrapper)}
|
|
291
|
+
type="single"
|
|
292
|
+
collapsible={collapsible}
|
|
293
|
+
value={currentValue as string}
|
|
294
|
+
role="menu"
|
|
295
|
+
data-slot="accordion-menu-sub-wrapper"
|
|
296
|
+
onValueChange={(value: string) => setNestedStates((prev) => ({ ...prev, [parentValue]: value }))}
|
|
297
|
+
>
|
|
298
|
+
{children}
|
|
299
|
+
</AccordionPrimitive.Root>
|
|
300
|
+
)}
|
|
301
|
+
</AccordionPrimitive.Content>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function AccordionMenuIndicator({ className, ...props }: React.ComponentPropsWithoutRef<'span'>) {
|
|
306
|
+
const { classNames } = React.useContext(AccordionMenuContext);
|
|
307
|
+
return (
|
|
308
|
+
<span aria-hidden="true" data-slot="accordion-menu-indicator" className={cn('ms-auto flex items-center font-medium', classNames?.indicator, className)} {...props} />
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export {
|
|
313
|
+
AccordionMenu,
|
|
314
|
+
AccordionMenuGroup,
|
|
315
|
+
AccordionMenuIndicator,
|
|
316
|
+
AccordionMenuItem,
|
|
317
|
+
AccordionMenuLabel,
|
|
318
|
+
AccordionMenuSeparator,
|
|
319
|
+
AccordionMenuSub,
|
|
320
|
+
AccordionMenuSubContent,
|
|
321
|
+
AccordionMenuSubTrigger,
|
|
322
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
5
|
+
import { ChevronDown, Plus } from 'lucide-react';
|
|
6
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
7
|
+
import { cn } from '../../lib/utils';
|
|
8
|
+
|
|
9
|
+
const accordionRootVariants = cva('', {
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: '',
|
|
13
|
+
outline: 'space-y-2',
|
|
14
|
+
solid: 'space-y-2',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: { variant: 'default' },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const accordionItemVariants = cva('', {
|
|
21
|
+
variants: {
|
|
22
|
+
variant: {
|
|
23
|
+
default: 'border-b border-border',
|
|
24
|
+
outline: 'border border-border rounded-lg px-4',
|
|
25
|
+
solid: 'rounded-lg bg-accent/70 px-4',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: { variant: 'default' },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const accordionTriggerVariants = cva(
|
|
32
|
+
'flex flex-1 items-center justify-between py-4 gap-2.5 text-foreground font-medium transition-all [&[data-state=open]>svg]:rotate-180 cursor-pointer',
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
variant: { default: '', outline: '', solid: '' },
|
|
36
|
+
indicator: {
|
|
37
|
+
arrow: '',
|
|
38
|
+
plus: '[&>svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180',
|
|
39
|
+
none: '',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaultVariants: { variant: 'default', indicator: 'arrow' },
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const accordionContentVariants = cva(
|
|
47
|
+
'overflow-hidden text-sm text-accent-foreground transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
|
|
48
|
+
{
|
|
49
|
+
variants: { variant: { default: '', outline: '', solid: '' } },
|
|
50
|
+
defaultVariants: { variant: 'default' },
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
type AccordionContextType = {
|
|
55
|
+
variant?: 'default' | 'outline' | 'solid';
|
|
56
|
+
indicator?: 'arrow' | 'plus' | 'none';
|
|
57
|
+
};
|
|
58
|
+
const AccordionContext = React.createContext<AccordionContextType>({
|
|
59
|
+
variant: 'default',
|
|
60
|
+
indicator: 'arrow',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
function Accordion(
|
|
64
|
+
props: React.ComponentProps<typeof AccordionPrimitive.Root> &
|
|
65
|
+
VariantProps<typeof accordionRootVariants> & {
|
|
66
|
+
indicator?: 'arrow' | 'plus';
|
|
67
|
+
},
|
|
68
|
+
) {
|
|
69
|
+
const { className, variant = 'default', indicator = 'arrow', children, ...rest } = props;
|
|
70
|
+
return (
|
|
71
|
+
<AccordionContext.Provider value={{ variant: variant || 'default', indicator }}>
|
|
72
|
+
<AccordionPrimitive.Root
|
|
73
|
+
data-slot="accordion"
|
|
74
|
+
className={cn(accordionRootVariants({ variant }), className)}
|
|
75
|
+
{...rest}
|
|
76
|
+
>
|
|
77
|
+
{children}
|
|
78
|
+
</AccordionPrimitive.Root>
|
|
79
|
+
</AccordionContext.Provider>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function AccordionItem(props: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
|
84
|
+
const { className, children, ...rest } = props;
|
|
85
|
+
const { variant } = React.useContext(AccordionContext);
|
|
86
|
+
return (
|
|
87
|
+
<AccordionPrimitive.Item
|
|
88
|
+
data-slot="accordion-item"
|
|
89
|
+
className={cn(accordionItemVariants({ variant }), className)}
|
|
90
|
+
{...rest}
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
</AccordionPrimitive.Item>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function AccordionTrigger(props: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
|
98
|
+
const { className, children, ...rest } = props;
|
|
99
|
+
const { variant, indicator } = React.useContext(AccordionContext);
|
|
100
|
+
return (
|
|
101
|
+
<AccordionPrimitive.Header className="flex">
|
|
102
|
+
<AccordionPrimitive.Trigger
|
|
103
|
+
data-slot="accordion-trigger"
|
|
104
|
+
className={cn(accordionTriggerVariants({ variant, indicator }), className)}
|
|
105
|
+
{...rest}
|
|
106
|
+
>
|
|
107
|
+
{children}
|
|
108
|
+
{indicator === 'plus' && (
|
|
109
|
+
<Plus className="size-4 shrink-0 transition-transform duration-200" strokeWidth={1} />
|
|
110
|
+
)}
|
|
111
|
+
{indicator === 'arrow' && (
|
|
112
|
+
<ChevronDown className="size-4 shrink-0 transition-transform duration-200" strokeWidth={1} />
|
|
113
|
+
)}
|
|
114
|
+
</AccordionPrimitive.Trigger>
|
|
115
|
+
</AccordionPrimitive.Header>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function AccordionContent(props: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
|
120
|
+
const { className, children, ...rest } = props;
|
|
121
|
+
const { variant } = React.useContext(AccordionContext);
|
|
122
|
+
return (
|
|
123
|
+
<AccordionPrimitive.Content
|
|
124
|
+
data-slot="accordion-content"
|
|
125
|
+
className={cn(accordionContentVariants({ variant }), className)}
|
|
126
|
+
{...rest}
|
|
127
|
+
>
|
|
128
|
+
<div className={cn('pb-5 pt-0', className)}>{children}</div>
|
|
129
|
+
</AccordionPrimitive.Content>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
5
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { buttonVariants } from '../../controls/Button';
|
|
8
|
+
|
|
9
|
+
function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
|
|
10
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function AlertDialogTrigger({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
|
|
14
|
+
return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function AlertDialogPortal({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
|
|
18
|
+
return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function AlertDialogOverlay({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
|
|
22
|
+
return (
|
|
23
|
+
<AlertDialogPrimitive.Overlay
|
|
24
|
+
data-slot="alert-dialog-overlay"
|
|
25
|
+
className={cn(
|
|
26
|
+
'fixed inset-0 z-50 bg-black/30 [backdrop-filter:blur(4px)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function AlertDialogContent({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
|
|
35
|
+
return (
|
|
36
|
+
<AlertDialogPortal>
|
|
37
|
+
<AlertDialogOverlay />
|
|
38
|
+
<AlertDialogPrimitive.Content
|
|
39
|
+
data-slot="alert-dialog-content"
|
|
40
|
+
className={cn(
|
|
41
|
+
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg shadow-black/5 duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg',
|
|
42
|
+
className,
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
</AlertDialogPortal>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
51
|
+
<div data-slot="alert-dialog-header" className={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...props} />
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
55
|
+
<div data-slot="alert-dialog-footer" className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2.5', className)} {...props} />
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
function AlertDialogTitle({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
59
|
+
return <AlertDialogPrimitive.Title data-slot="alert-dialog-title" className={cn('text-lg font-semibold', className)} {...props} />;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function AlertDialogDescription({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
63
|
+
return <AlertDialogPrimitive.Description data-slot="alert-dialog-description" className={cn('text-sm text-muted-foreground', className)} {...props} />;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function AlertDialogAction({
|
|
67
|
+
className,
|
|
68
|
+
variant,
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Action> & VariantProps<typeof buttonVariants>) {
|
|
71
|
+
return <AlertDialogPrimitive.Action data-slot="alert-dialog-action" className={cn(buttonVariants({ variant }), className)} {...props} />;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function AlertDialogCancel({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
|
|
75
|
+
return <AlertDialogPrimitive.Cancel data-slot="alert-dialog-cancel" className={cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className)} {...props} />;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
|
|
80
|
+
AlertDialogDescription, AlertDialogFooter, AlertDialogHeader,
|
|
81
|
+
AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger,
|
|
82
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: 'bg-background text-foreground',
|
|
12
|
+
destructive:
|
|
13
|
+
'text-destructive-foreground [&>svg]:text-current *:data-[slot=alert-description]:text-destructive-foreground/80',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: 'default',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn(
|
|
42
|
+
'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AlertDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
data-slot="alert-description"
|
|
54
|
+
className={cn(
|
|
55
|
+
'text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed',
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { Alert, AlertTitle, AlertDescription };
|