@djangocfg/ui-core 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -0
- package/package.json +111 -0
- package/src/components/accordion.tsx +56 -0
- package/src/components/alert-dialog.tsx +142 -0
- package/src/components/alert.tsx +59 -0
- package/src/components/aspect-ratio.tsx +7 -0
- package/src/components/avatar.tsx +50 -0
- package/src/components/badge.tsx +36 -0
- package/src/components/button-group.tsx +85 -0
- package/src/components/button.tsx +111 -0
- package/src/components/calendar.tsx +213 -0
- package/src/components/card.tsx +76 -0
- package/src/components/carousel.tsx +261 -0
- package/src/components/chart.tsx +369 -0
- package/src/components/checkbox.tsx +29 -0
- package/src/components/collapsible.tsx +11 -0
- package/src/components/combobox.tsx +182 -0
- package/src/components/command.tsx +170 -0
- package/src/components/context-menu.tsx +200 -0
- package/src/components/copy.tsx +144 -0
- package/src/components/dialog.tsx +122 -0
- package/src/components/drawer.tsx +137 -0
- package/src/components/empty.tsx +104 -0
- package/src/components/field.tsx +244 -0
- package/src/components/form.tsx +178 -0
- package/src/components/hover-card.tsx +29 -0
- package/src/components/image-with-fallback.tsx +170 -0
- package/src/components/index.ts +86 -0
- package/src/components/input-group.tsx +170 -0
- package/src/components/input-otp.tsx +81 -0
- package/src/components/input.tsx +22 -0
- package/src/components/item.tsx +195 -0
- package/src/components/kbd.tsx +28 -0
- package/src/components/label.tsx +26 -0
- package/src/components/multi-select.tsx +222 -0
- package/src/components/og-image.tsx +47 -0
- package/src/components/popover.tsx +33 -0
- package/src/components/portal.tsx +106 -0
- package/src/components/preloader.tsx +250 -0
- package/src/components/progress.tsx +28 -0
- package/src/components/radio-group.tsx +43 -0
- package/src/components/resizable.tsx +111 -0
- package/src/components/scroll-area.tsx +102 -0
- package/src/components/section.tsx +58 -0
- package/src/components/select.tsx +158 -0
- package/src/components/separator.tsx +31 -0
- package/src/components/sheet.tsx +140 -0
- package/src/components/skeleton.tsx +15 -0
- package/src/components/slider.tsx +28 -0
- package/src/components/spinner.tsx +16 -0
- package/src/components/sticky.tsx +117 -0
- package/src/components/switch.tsx +29 -0
- package/src/components/table.tsx +120 -0
- package/src/components/tabs.tsx +238 -0
- package/src/components/textarea.tsx +22 -0
- package/src/components/toast.tsx +129 -0
- package/src/components/toaster.tsx +41 -0
- package/src/components/toggle-group.tsx +61 -0
- package/src/components/toggle.tsx +45 -0
- package/src/components/token-icon.tsx +156 -0
- package/src/components/tooltip-provider-safe.tsx +43 -0
- package/src/components/tooltip.tsx +32 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/useCopy.ts +41 -0
- package/src/hooks/useCountdown.ts +73 -0
- package/src/hooks/useDebounce.ts +25 -0
- package/src/hooks/useDebouncedCallback.ts +58 -0
- package/src/hooks/useDebugTools.ts +52 -0
- package/src/hooks/useEventsBus.ts +53 -0
- package/src/hooks/useImageLoader.ts +95 -0
- package/src/hooks/useMediaQuery.ts +40 -0
- package/src/hooks/useMobile.tsx +22 -0
- package/src/hooks/useToast.ts +194 -0
- package/src/index.ts +14 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/og-image.ts +151 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/base.css +20 -0
- package/src/styles/globals.css +12 -0
- package/src/styles/index.css +25 -0
- package/src/styles/sources.css +11 -0
- package/src/styles/theme/animations.css +65 -0
- package/src/styles/theme/dark.css +49 -0
- package/src/styles/theme/light.css +50 -0
- package/src/styles/theme/tokens.css +134 -0
- package/src/styles/theme.css +22 -0
- package/src/styles/utilities.css +187 -0
- package/src/types/index.ts +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# @djangocfg/ui-core
|
|
2
|
+
|
|
3
|
+
Pure React UI library with 60+ components built on Radix UI + Tailwind CSS v4.
|
|
4
|
+
|
|
5
|
+
**No Next.js dependencies** — works with Electron, Vite, CRA, and any React environment.
|
|
6
|
+
|
|
7
|
+
**Part of [DjangoCFG](https://djangocfg.com)** — modern Django framework for production-ready SaaS applications.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @djangocfg/ui-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Why ui-core?
|
|
16
|
+
|
|
17
|
+
| Package | Use Case |
|
|
18
|
+
|---------|----------|
|
|
19
|
+
| `@djangocfg/ui-core` | Electron, Vite, CRA, any React app |
|
|
20
|
+
| `@djangocfg/ui-nextjs` | Next.js apps (extends ui-core) |
|
|
21
|
+
|
|
22
|
+
## Components (61)
|
|
23
|
+
|
|
24
|
+
### Forms (16)
|
|
25
|
+
`Label` `Button` `ButtonLink` `Input` `Checkbox` `RadioGroup` `Select` `Textarea` `Switch` `Slider` `Combobox` `MultiSelect` `InputOTP` `PhoneInput` `Form` `Field`
|
|
26
|
+
|
|
27
|
+
### Layout (8)
|
|
28
|
+
`Card` `Separator` `Skeleton` `AspectRatio` `Sticky` `ScrollArea` `Resizable` `Section`
|
|
29
|
+
|
|
30
|
+
### Overlay (7)
|
|
31
|
+
`Dialog` `AlertDialog` `Sheet` `Drawer` `Popover` `HoverCard` `Tooltip`
|
|
32
|
+
|
|
33
|
+
### Feedback (6)
|
|
34
|
+
`Toast` `Toaster` `Alert` `Progress` `Badge` `Avatar`
|
|
35
|
+
|
|
36
|
+
### Data (8)
|
|
37
|
+
`Table` `Tabs` `Accordion` `Collapsible` `Toggle` `ToggleGroup` `Calendar` `Carousel`
|
|
38
|
+
|
|
39
|
+
### Interactive (3)
|
|
40
|
+
`Command` `ContextMenu` `Chart`
|
|
41
|
+
|
|
42
|
+
### Specialized (13)
|
|
43
|
+
`ButtonGroup` `Empty` `Spinner` `Preloader` `Kbd` `TokenIcon` `InputGroup` `Item` `ImageWithFallback` `OgImage` `CopyButton` `CopyField` `StaticPagination`
|
|
44
|
+
|
|
45
|
+
## Hooks (10)
|
|
46
|
+
|
|
47
|
+
| Hook | Description |
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `useMediaQuery` | Responsive breakpoints |
|
|
50
|
+
| `useIsMobile` | Mobile detection |
|
|
51
|
+
| `useCopy` | Copy to clipboard |
|
|
52
|
+
| `useCountdown` | Countdown timer |
|
|
53
|
+
| `useDebounce` | Debounce values |
|
|
54
|
+
| `useDebouncedCallback` | Debounced callbacks |
|
|
55
|
+
| `useImageLoader` | Image loading state |
|
|
56
|
+
| `useToast` | Toast notifications |
|
|
57
|
+
| `useEventListener` | Event bus |
|
|
58
|
+
| `useDebugTools` | Debug utilities |
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { Button, Card, Input, useToast } from '@djangocfg/ui-core';
|
|
64
|
+
|
|
65
|
+
function Example() {
|
|
66
|
+
const { toast } = useToast();
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Card>
|
|
70
|
+
<Input placeholder="Email" />
|
|
71
|
+
<Button onClick={() => toast({ title: 'Saved!' })}>
|
|
72
|
+
Submit
|
|
73
|
+
</Button>
|
|
74
|
+
</Card>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Electron Usage
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// In Electron renderer process
|
|
83
|
+
import { Button, Dialog, useMediaQuery } from '@djangocfg/ui-core';
|
|
84
|
+
import '@djangocfg/ui-core/styles/globals';
|
|
85
|
+
|
|
86
|
+
function App() {
|
|
87
|
+
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Dialog>
|
|
91
|
+
<Button>Open Dialog</Button>
|
|
92
|
+
</Dialog>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Styling
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// Import global styles
|
|
101
|
+
import '@djangocfg/ui-core/styles/globals';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Exports
|
|
105
|
+
|
|
106
|
+
| Path | Content |
|
|
107
|
+
|------|---------|
|
|
108
|
+
| `@djangocfg/ui-core` | All components & hooks |
|
|
109
|
+
| `@djangocfg/ui-core/components` | Components only |
|
|
110
|
+
| `@djangocfg/ui-core/hooks` | Hooks only |
|
|
111
|
+
| `@djangocfg/ui-core/lib` | Utilities (cn, etc.) |
|
|
112
|
+
| `@djangocfg/ui-core/styles` | CSS |
|
|
113
|
+
|
|
114
|
+
## What's NOT included (use ui-nextjs)
|
|
115
|
+
|
|
116
|
+
These features require Next.js or browser storage APIs:
|
|
117
|
+
|
|
118
|
+
- `Sidebar` — uses next/link
|
|
119
|
+
- `Breadcrumb`, `BreadcrumbNavigation` — uses next/link
|
|
120
|
+
- `NavigationMenu`, `Menubar` — uses next/link
|
|
121
|
+
- `Pagination`, `SSRPagination` — uses next/link
|
|
122
|
+
- `DropdownMenu` — uses next/link
|
|
123
|
+
- `DownloadButton` — uses localStorage
|
|
124
|
+
- `useLocalStorage`, `useSessionStorage` — browser storage
|
|
125
|
+
- `useTheme` — uses next-themes
|
|
126
|
+
- `useQueryParams`, `useCfgRouter` — uses next/router
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
- React >= 18 or >= 19
|
|
131
|
+
- Tailwind CSS >= 4
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
**[Full documentation & examples](https://djangocfg.com/demo/ui/)**
|
package/package.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@djangocfg/ui-core",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ui-components",
|
|
7
|
+
"react",
|
|
8
|
+
"radix-ui",
|
|
9
|
+
"tailwindcss",
|
|
10
|
+
"design-system",
|
|
11
|
+
"component-library",
|
|
12
|
+
"typescript",
|
|
13
|
+
"electron",
|
|
14
|
+
"vite"
|
|
15
|
+
],
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "DjangoCFG",
|
|
18
|
+
"url": "https://djangocfg.com"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://djangocfg.com",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/markolofsen/django-cfg.git",
|
|
24
|
+
"directory": "packages/ui-core"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"main": "./src/index.ts",
|
|
28
|
+
"types": "./src/index.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./src/index.ts",
|
|
31
|
+
"./components": "./src/components/index.ts",
|
|
32
|
+
"./hooks": "./src/hooks/index.ts",
|
|
33
|
+
"./lib": "./src/lib/index.ts",
|
|
34
|
+
"./styles": "./src/styles/index.css",
|
|
35
|
+
"./styles/globals": "./src/styles/globals.css",
|
|
36
|
+
"./styles/theme": "./src/styles/theme.css",
|
|
37
|
+
"./styles/base": "./src/styles/base.css",
|
|
38
|
+
"./styles/utilities": "./src/styles/utilities.css"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"src",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"scripts": {
|
|
46
|
+
"lint": "eslint .",
|
|
47
|
+
"check": "tsc --noEmit"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"lucide-react": "^0.545.0",
|
|
51
|
+
"moment": "^2.30.1",
|
|
52
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
53
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
54
|
+
"react-hook-form": "^7.0.0",
|
|
55
|
+
"tailwindcss": "^4.0.0",
|
|
56
|
+
"zod": "^4.0.0"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@hookform/resolvers": "^5.2.2",
|
|
60
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
61
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
62
|
+
"@radix-ui/react-aspect-ratio": "^1.1.7",
|
|
63
|
+
"@radix-ui/react-avatar": "^1.1.10",
|
|
64
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
65
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
66
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
67
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
68
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
69
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
70
|
+
"@radix-ui/react-label": "^2.1.7",
|
|
71
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
72
|
+
"@radix-ui/react-progress": "^1.1.7",
|
|
73
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
74
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
75
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
76
|
+
"@radix-ui/react-separator": "^1.1.7",
|
|
77
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
78
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
79
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
80
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
81
|
+
"@radix-ui/react-toast": "^1.2.15",
|
|
82
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
83
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
84
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
85
|
+
"class-variance-authority": "^0.7.1",
|
|
86
|
+
"clsx": "^2.1.1",
|
|
87
|
+
"cmdk": "1.1.1",
|
|
88
|
+
"date-fns": "^4.1.0",
|
|
89
|
+
"embla-carousel-react": "8.6.0",
|
|
90
|
+
"input-otp": "1.4.2",
|
|
91
|
+
"libphonenumber-js": "^1.12.24",
|
|
92
|
+
"react-day-picker": "9.11.1",
|
|
93
|
+
"react-resizable-panels": "3.0.6",
|
|
94
|
+
"react-sticky-box": "^2.0.5",
|
|
95
|
+
"recharts": "2.15.4",
|
|
96
|
+
"sonner": "2.0.7",
|
|
97
|
+
"tailwind-merge": "^3.3.1",
|
|
98
|
+
"vaul": "1.1.2",
|
|
99
|
+
"@web3icons/react": "^4.0.26"
|
|
100
|
+
},
|
|
101
|
+
"devDependencies": {
|
|
102
|
+
"@djangocfg/typescript-config": "^1.4.45",
|
|
103
|
+
"@types/node": "^24.7.2",
|
|
104
|
+
"@types/react": "19.2.2",
|
|
105
|
+
"@types/react-dom": "19.2.1",
|
|
106
|
+
"typescript": "^5.9.3"
|
|
107
|
+
},
|
|
108
|
+
"publishConfig": {
|
|
109
|
+
"access": "public"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
|
5
|
+
import { cn } from "../lib/utils"
|
|
6
|
+
import { ChevronDownIcon } from "@radix-ui/react-icons"
|
|
7
|
+
|
|
8
|
+
const Accordion = AccordionPrimitive.Root
|
|
9
|
+
|
|
10
|
+
const AccordionItem = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> & { key?: React.Key }
|
|
13
|
+
>(({ className, ...props }, ref) => (
|
|
14
|
+
<AccordionPrimitive.Item
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn("border-b", className)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
))
|
|
20
|
+
AccordionItem.displayName = "AccordionItem"
|
|
21
|
+
|
|
22
|
+
const AccordionTrigger = React.forwardRef<
|
|
23
|
+
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
24
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
25
|
+
>(({ className, children, ...props }, ref) => (
|
|
26
|
+
<AccordionPrimitive.Header className="flex">
|
|
27
|
+
<AccordionPrimitive.Trigger
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn(
|
|
30
|
+
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
<ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
|
|
37
|
+
</AccordionPrimitive.Trigger>
|
|
38
|
+
</AccordionPrimitive.Header>
|
|
39
|
+
))
|
|
40
|
+
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
|
41
|
+
|
|
42
|
+
const AccordionContent = React.forwardRef<
|
|
43
|
+
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
44
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
45
|
+
>(({ className, children, ...props }, ref) => (
|
|
46
|
+
<AccordionPrimitive.Content
|
|
47
|
+
ref={ref}
|
|
48
|
+
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
|
49
|
+
{...props}
|
|
50
|
+
>
|
|
51
|
+
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
|
52
|
+
</AccordionPrimitive.Content>
|
|
53
|
+
))
|
|
54
|
+
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
|
55
|
+
|
|
56
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
import { buttonVariants } from "./button"
|
|
8
|
+
|
|
9
|
+
const AlertDialog = AlertDialogPrimitive.Root
|
|
10
|
+
|
|
11
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
|
12
|
+
|
|
13
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
|
14
|
+
|
|
15
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
18
|
+
>(({ className, style, ...props }, ref) => (
|
|
19
|
+
<AlertDialogPrimitive.Overlay
|
|
20
|
+
className={cn(
|
|
21
|
+
"fixed inset-0 z-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
style={{ backgroundColor: 'rgb(0 0 0 / 0.8)', ...style }}
|
|
25
|
+
{...props}
|
|
26
|
+
ref={ref}
|
|
27
|
+
/>
|
|
28
|
+
))
|
|
29
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
|
|
30
|
+
|
|
31
|
+
const AlertDialogContent = React.forwardRef<
|
|
32
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
33
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
|
34
|
+
>(({ className, ...props }, ref) => (
|
|
35
|
+
<AlertDialogPortal>
|
|
36
|
+
<AlertDialogOverlay />
|
|
37
|
+
<AlertDialogPrimitive.Content
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn(
|
|
40
|
+
"fixed left-1/2 top-1/2 z-200 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg 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",
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
</AlertDialogPortal>
|
|
46
|
+
))
|
|
47
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
|
|
48
|
+
|
|
49
|
+
const AlertDialogHeader = ({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
53
|
+
<div
|
|
54
|
+
className={cn(
|
|
55
|
+
"flex flex-col space-y-2 text-center sm:text-left",
|
|
56
|
+
className
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
AlertDialogHeader.displayName = "AlertDialogHeader"
|
|
62
|
+
|
|
63
|
+
const AlertDialogFooter = ({
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
67
|
+
<div
|
|
68
|
+
className={cn(
|
|
69
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
AlertDialogFooter.displayName = "AlertDialogFooter"
|
|
76
|
+
|
|
77
|
+
const AlertDialogTitle = React.forwardRef<
|
|
78
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
79
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
80
|
+
>(({ className, ...props }, ref) => (
|
|
81
|
+
<AlertDialogPrimitive.Title
|
|
82
|
+
ref={ref}
|
|
83
|
+
className={cn("text-lg font-semibold", className)}
|
|
84
|
+
{...props}
|
|
85
|
+
/>
|
|
86
|
+
))
|
|
87
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
|
|
88
|
+
|
|
89
|
+
const AlertDialogDescription = React.forwardRef<
|
|
90
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
91
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
92
|
+
>(({ className, ...props }, ref) => (
|
|
93
|
+
<AlertDialogPrimitive.Description
|
|
94
|
+
ref={ref}
|
|
95
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
))
|
|
99
|
+
AlertDialogDescription.displayName =
|
|
100
|
+
AlertDialogPrimitive.Description.displayName
|
|
101
|
+
|
|
102
|
+
const AlertDialogAction = React.forwardRef<
|
|
103
|
+
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
|
104
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
|
|
105
|
+
>(({ className, ...props }, ref) => (
|
|
106
|
+
<AlertDialogPrimitive.Action
|
|
107
|
+
ref={ref}
|
|
108
|
+
className={cn(buttonVariants(), className)}
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
))
|
|
112
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
|
|
113
|
+
|
|
114
|
+
const AlertDialogCancel = React.forwardRef<
|
|
115
|
+
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
|
116
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
|
|
117
|
+
>(({ className, ...props }, ref) => (
|
|
118
|
+
<AlertDialogPrimitive.Cancel
|
|
119
|
+
ref={ref}
|
|
120
|
+
className={cn(
|
|
121
|
+
buttonVariants({ variant: "outline" }),
|
|
122
|
+
"mt-2 sm:mt-0",
|
|
123
|
+
className
|
|
124
|
+
)}
|
|
125
|
+
{...props}
|
|
126
|
+
/>
|
|
127
|
+
))
|
|
128
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
AlertDialog,
|
|
132
|
+
AlertDialogPortal,
|
|
133
|
+
AlertDialogOverlay,
|
|
134
|
+
AlertDialogTrigger,
|
|
135
|
+
AlertDialogContent,
|
|
136
|
+
AlertDialogHeader,
|
|
137
|
+
AlertDialogFooter,
|
|
138
|
+
AlertDialogTitle,
|
|
139
|
+
AlertDialogDescription,
|
|
140
|
+
AlertDialogAction,
|
|
141
|
+
AlertDialogCancel,
|
|
142
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
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 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-background text-foreground",
|
|
12
|
+
destructive:
|
|
13
|
+
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const Alert = React.forwardRef<
|
|
23
|
+
HTMLDivElement,
|
|
24
|
+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
|
25
|
+
>(({ className, variant, ...props }, ref) => (
|
|
26
|
+
<div
|
|
27
|
+
ref={ref}
|
|
28
|
+
role="alert"
|
|
29
|
+
className={cn(alertVariants({ variant }), className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
))
|
|
33
|
+
Alert.displayName = "Alert"
|
|
34
|
+
|
|
35
|
+
const AlertTitle = React.forwardRef<
|
|
36
|
+
HTMLParagraphElement,
|
|
37
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
38
|
+
>(({ className, ...props }, ref) => (
|
|
39
|
+
<h5
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
))
|
|
45
|
+
AlertTitle.displayName = "AlertTitle"
|
|
46
|
+
|
|
47
|
+
const AlertDescription = React.forwardRef<
|
|
48
|
+
HTMLParagraphElement,
|
|
49
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
50
|
+
>(({ className, ...props }, ref) => (
|
|
51
|
+
<div
|
|
52
|
+
ref={ref}
|
|
53
|
+
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
))
|
|
57
|
+
AlertDescription.displayName = "AlertDescription"
|
|
58
|
+
|
|
59
|
+
export { Alert, AlertTitle, AlertDescription }
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
|
|
8
|
+
const Avatar = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
11
|
+
>(({ className, ...props }, ref) => (
|
|
12
|
+
<AvatarPrimitive.Root
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={cn(
|
|
15
|
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
))
|
|
21
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName
|
|
22
|
+
|
|
23
|
+
const AvatarImage = React.forwardRef<
|
|
24
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
25
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
26
|
+
>(({ className, ...props }, ref) => (
|
|
27
|
+
<AvatarPrimitive.Image
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
))
|
|
33
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
|
34
|
+
|
|
35
|
+
const AvatarFallback = React.forwardRef<
|
|
36
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
37
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
38
|
+
>(({ className, ...props }, ref) => (
|
|
39
|
+
<AvatarPrimitive.Fallback
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={cn(
|
|
42
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
))
|
|
48
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
|
49
|
+
|
|
50
|
+
export { Avatar, AvatarImage, AvatarFallback }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../lib/utils"
|
|
5
|
+
|
|
6
|
+
const badgeVariants = cva(
|
|
7
|
+
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default:
|
|
12
|
+
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
|
13
|
+
secondary:
|
|
14
|
+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
15
|
+
destructive:
|
|
16
|
+
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
|
17
|
+
outline: "text-foreground",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
variant: "default",
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
export interface BadgeProps
|
|
27
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
28
|
+
VariantProps<typeof badgeVariants> {}
|
|
29
|
+
|
|
30
|
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
31
|
+
return (
|
|
32
|
+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { Badge, badgeVariants }
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../lib/utils"
|
|
7
|
+
import { Separator } from "./separator"
|
|
8
|
+
|
|
9
|
+
const buttonGroupVariants = cva(
|
|
10
|
+
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
orientation: {
|
|
14
|
+
horizontal:
|
|
15
|
+
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
|
|
16
|
+
vertical:
|
|
17
|
+
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
orientation: "horizontal",
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
function ButtonGroup({
|
|
27
|
+
className,
|
|
28
|
+
orientation,
|
|
29
|
+
...props
|
|
30
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
role="group"
|
|
34
|
+
data-slot="button-group"
|
|
35
|
+
data-orientation={orientation}
|
|
36
|
+
className={cn(buttonGroupVariants({ orientation }), className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ButtonGroupText({
|
|
43
|
+
className,
|
|
44
|
+
asChild = false,
|
|
45
|
+
...props
|
|
46
|
+
}: React.ComponentProps<"div"> & {
|
|
47
|
+
asChild?: boolean
|
|
48
|
+
}) {
|
|
49
|
+
const Comp = asChild ? Slot : "div"
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Comp
|
|
53
|
+
className={cn(
|
|
54
|
+
"bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
|
|
55
|
+
className
|
|
56
|
+
)}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function ButtonGroupSeparator({
|
|
63
|
+
className,
|
|
64
|
+
orientation = "vertical",
|
|
65
|
+
...props
|
|
66
|
+
}: React.ComponentProps<typeof Separator>) {
|
|
67
|
+
return (
|
|
68
|
+
<Separator
|
|
69
|
+
data-slot="button-group-separator"
|
|
70
|
+
orientation={orientation}
|
|
71
|
+
className={cn(
|
|
72
|
+
"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
|
|
73
|
+
className
|
|
74
|
+
)}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
ButtonGroup,
|
|
82
|
+
ButtonGroupSeparator,
|
|
83
|
+
ButtonGroupText,
|
|
84
|
+
buttonGroupVariants,
|
|
85
|
+
}
|