@modern-admin/ui 0.1.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.
Files changed (268) hide show
  1. package/dist/components/accordion.d.ts +7 -0
  2. package/dist/components/accordion.d.ts.map +1 -0
  3. package/dist/components/accordion.jsx +19 -0
  4. package/dist/components/accordion.jsx.map +1 -0
  5. package/dist/components/alert-dialog.d.ts +22 -0
  6. package/dist/components/alert-dialog.d.ts.map +1 -0
  7. package/dist/components/alert-dialog.jsx +27 -0
  8. package/dist/components/alert-dialog.jsx.map +1 -0
  9. package/dist/components/audit-timeline.d.ts +24 -0
  10. package/dist/components/audit-timeline.d.ts.map +1 -0
  11. package/dist/components/audit-timeline.jsx +60 -0
  12. package/dist/components/audit-timeline.jsx.map +1 -0
  13. package/dist/components/avatar.d.ts +6 -0
  14. package/dist/components/avatar.d.ts.map +1 -0
  15. package/dist/components/avatar.jsx +10 -0
  16. package/dist/components/avatar.jsx.map +1 -0
  17. package/dist/components/badge.d.ts +10 -0
  18. package/dist/components/badge.d.ts.map +1 -0
  19. package/dist/components/badge.jsx +19 -0
  20. package/dist/components/badge.jsx.map +1 -0
  21. package/dist/components/breadcrumb.d.ts +17 -0
  22. package/dist/components/breadcrumb.d.ts.map +1 -0
  23. package/dist/components/breadcrumb.jsx +27 -0
  24. package/dist/components/breadcrumb.jsx.map +1 -0
  25. package/dist/components/button.d.ts +12 -0
  26. package/dist/components/button.d.ts.map +1 -0
  27. package/dist/components/button.jsx +37 -0
  28. package/dist/components/button.jsx.map +1 -0
  29. package/dist/components/calendar.d.ts +9 -0
  30. package/dist/components/calendar.d.ts.map +1 -0
  31. package/dist/components/calendar.jsx +102 -0
  32. package/dist/components/calendar.jsx.map +1 -0
  33. package/dist/components/card.d.ts +8 -0
  34. package/dist/components/card.d.ts.map +1 -0
  35. package/dist/components/card.jsx +18 -0
  36. package/dist/components/card.jsx.map +1 -0
  37. package/dist/components/chart.d.ts +97 -0
  38. package/dist/components/chart.d.ts.map +1 -0
  39. package/dist/components/chart.jsx +233 -0
  40. package/dist/components/chart.jsx.map +1 -0
  41. package/dist/components/checkbox.d.ts +4 -0
  42. package/dist/components/checkbox.d.ts.map +1 -0
  43. package/dist/components/checkbox.jsx +11 -0
  44. package/dist/components/checkbox.jsx.map +1 -0
  45. package/dist/components/combobox.d.ts +46 -0
  46. package/dist/components/combobox.d.ts.map +1 -0
  47. package/dist/components/combobox.jsx +145 -0
  48. package/dist/components/combobox.jsx.map +1 -0
  49. package/dist/components/command.d.ts +80 -0
  50. package/dist/components/command.d.ts.map +1 -0
  51. package/dist/components/command.jsx +32 -0
  52. package/dist/components/command.jsx.map +1 -0
  53. package/dist/components/date-picker.d.ts +24 -0
  54. package/dist/components/date-picker.d.ts.map +1 -0
  55. package/dist/components/date-picker.jsx +149 -0
  56. package/dist/components/date-picker.jsx.map +1 -0
  57. package/dist/components/date-range-input.d.ts +22 -0
  58. package/dist/components/date-range-input.d.ts.map +1 -0
  59. package/dist/components/date-range-input.jsx +202 -0
  60. package/dist/components/date-range-input.jsx.map +1 -0
  61. package/dist/components/dialog.d.ts +19 -0
  62. package/dist/components/dialog.d.ts.map +1 -0
  63. package/dist/components/dialog.jsx +30 -0
  64. package/dist/components/dialog.jsx.map +1 -0
  65. package/dist/components/diff-view.d.ts +24 -0
  66. package/dist/components/diff-view.d.ts.map +1 -0
  67. package/dist/components/diff-view.jsx +69 -0
  68. package/dist/components/diff-view.jsx.map +1 -0
  69. package/dist/components/dropdown-menu.d.ts +27 -0
  70. package/dist/components/dropdown-menu.d.ts.map +1 -0
  71. package/dist/components/dropdown-menu.jsx +48 -0
  72. package/dist/components/dropdown-menu.jsx.map +1 -0
  73. package/dist/components/empty.d.ts +15 -0
  74. package/dist/components/empty.d.ts.map +1 -0
  75. package/dist/components/empty.jsx +27 -0
  76. package/dist/components/empty.jsx.map +1 -0
  77. package/dist/components/field.d.ts +23 -0
  78. package/dist/components/field.d.ts.map +1 -0
  79. package/dist/components/field.jsx +60 -0
  80. package/dist/components/field.jsx.map +1 -0
  81. package/dist/components/file-input.d.ts +50 -0
  82. package/dist/components/file-input.d.ts.map +1 -0
  83. package/dist/components/file-input.jsx +104 -0
  84. package/dist/components/file-input.jsx.map +1 -0
  85. package/dist/components/form.d.ts +20 -0
  86. package/dist/components/form.d.ts.map +1 -0
  87. package/dist/components/form.jsx +66 -0
  88. package/dist/components/form.jsx.map +1 -0
  89. package/dist/components/info-tooltip.d.ts +11 -0
  90. package/dist/components/info-tooltip.d.ts.map +1 -0
  91. package/dist/components/info-tooltip.jsx +17 -0
  92. package/dist/components/info-tooltip.jsx.map +1 -0
  93. package/dist/components/input.d.ts +13 -0
  94. package/dist/components/input.d.ts.map +1 -0
  95. package/dist/components/input.jsx +19 -0
  96. package/dist/components/input.jsx.map +1 -0
  97. package/dist/components/json-editor.d.ts +23 -0
  98. package/dist/components/json-editor.d.ts.map +1 -0
  99. package/dist/components/json-editor.jsx +143 -0
  100. package/dist/components/json-editor.jsx.map +1 -0
  101. package/dist/components/kbd.d.ts +15 -0
  102. package/dist/components/kbd.d.ts.map +1 -0
  103. package/dist/components/kbd.jsx +23 -0
  104. package/dist/components/kbd.jsx.map +1 -0
  105. package/dist/components/key-value-editor.d.ts +92 -0
  106. package/dist/components/key-value-editor.d.ts.map +1 -0
  107. package/dist/components/key-value-editor.jsx +187 -0
  108. package/dist/components/key-value-editor.jsx.map +1 -0
  109. package/dist/components/keyboard-shortcuts-help.d.ts +17 -0
  110. package/dist/components/keyboard-shortcuts-help.d.ts.map +1 -0
  111. package/dist/components/keyboard-shortcuts-help.jsx +97 -0
  112. package/dist/components/keyboard-shortcuts-help.jsx.map +1 -0
  113. package/dist/components/label.d.ts +5 -0
  114. package/dist/components/label.d.ts.map +1 -0
  115. package/dist/components/label.jsx +8 -0
  116. package/dist/components/label.jsx.map +1 -0
  117. package/dist/components/media-preview.d.ts +30 -0
  118. package/dist/components/media-preview.d.ts.map +1 -0
  119. package/dist/components/media-preview.jsx +189 -0
  120. package/dist/components/media-preview.jsx.map +1 -0
  121. package/dist/components/multi-file-input.d.ts +76 -0
  122. package/dist/components/multi-file-input.d.ts.map +1 -0
  123. package/dist/components/multi-file-input.jsx +131 -0
  124. package/dist/components/multi-file-input.jsx.map +1 -0
  125. package/dist/components/password-input.d.ts +10 -0
  126. package/dist/components/password-input.d.ts.map +1 -0
  127. package/dist/components/password-input.jsx +18 -0
  128. package/dist/components/password-input.jsx.map +1 -0
  129. package/dist/components/popover.d.ts +7 -0
  130. package/dist/components/popover.d.ts.map +1 -0
  131. package/dist/components/popover.jsx +11 -0
  132. package/dist/components/popover.jsx.map +1 -0
  133. package/dist/components/revision-timeline.d.ts +30 -0
  134. package/dist/components/revision-timeline.d.ts.map +1 -0
  135. package/dist/components/revision-timeline.jsx +42 -0
  136. package/dist/components/revision-timeline.jsx.map +1 -0
  137. package/dist/components/richtext-editor.d.ts +43 -0
  138. package/dist/components/richtext-editor.d.ts.map +1 -0
  139. package/dist/components/richtext-editor.jsx +319 -0
  140. package/dist/components/richtext-editor.jsx.map +1 -0
  141. package/dist/components/richtext-mode.d.ts +23 -0
  142. package/dist/components/richtext-mode.d.ts.map +1 -0
  143. package/dist/components/richtext-mode.js +36 -0
  144. package/dist/components/richtext-mode.js.map +1 -0
  145. package/dist/components/richtext-render.d.ts +8 -0
  146. package/dist/components/richtext-render.d.ts.map +1 -0
  147. package/dist/components/richtext-render.jsx +33 -0
  148. package/dist/components/richtext-render.jsx.map +1 -0
  149. package/dist/components/richtext-sync.d.ts +37 -0
  150. package/dist/components/richtext-sync.d.ts.map +1 -0
  151. package/dist/components/richtext-sync.js +46 -0
  152. package/dist/components/richtext-sync.js.map +1 -0
  153. package/dist/components/scroll-area.d.ts +5 -0
  154. package/dist/components/scroll-area.d.ts.map +1 -0
  155. package/dist/components/scroll-area.jsx +16 -0
  156. package/dist/components/scroll-area.jsx.map +1 -0
  157. package/dist/components/select.d.ts +36 -0
  158. package/dist/components/select.d.ts.map +1 -0
  159. package/dist/components/select.jsx +87 -0
  160. package/dist/components/select.jsx.map +1 -0
  161. package/dist/components/separator.d.ts +4 -0
  162. package/dist/components/separator.d.ts.map +1 -0
  163. package/dist/components/separator.jsx +6 -0
  164. package/dist/components/separator.jsx.map +1 -0
  165. package/dist/components/sheet.d.ts +29 -0
  166. package/dist/components/sheet.d.ts.map +1 -0
  167. package/dist/components/sheet.jsx +44 -0
  168. package/dist/components/sheet.jsx.map +1 -0
  169. package/dist/components/sidebar.d.ts +70 -0
  170. package/dist/components/sidebar.d.ts.map +1 -0
  171. package/dist/components/sidebar.jsx +245 -0
  172. package/dist/components/sidebar.jsx.map +1 -0
  173. package/dist/components/skeleton.d.ts +3 -0
  174. package/dist/components/skeleton.d.ts.map +1 -0
  175. package/dist/components/skeleton.jsx +6 -0
  176. package/dist/components/skeleton.jsx.map +1 -0
  177. package/dist/components/sonner.d.ts +6 -0
  178. package/dist/components/sonner.d.ts.map +1 -0
  179. package/dist/components/sonner.jsx +29 -0
  180. package/dist/components/sonner.jsx.map +1 -0
  181. package/dist/components/switch.d.ts +4 -0
  182. package/dist/components/switch.d.ts.map +1 -0
  183. package/dist/components/switch.jsx +8 -0
  184. package/dist/components/switch.jsx.map +1 -0
  185. package/dist/components/table.d.ts +10 -0
  186. package/dist/components/table.d.ts.map +1 -0
  187. package/dist/components/table.jsx +21 -0
  188. package/dist/components/table.jsx.map +1 -0
  189. package/dist/components/tabs.d.ts +7 -0
  190. package/dist/components/tabs.d.ts.map +1 -0
  191. package/dist/components/tabs.jsx +14 -0
  192. package/dist/components/tabs.jsx.map +1 -0
  193. package/dist/components/textarea.d.ts +4 -0
  194. package/dist/components/textarea.d.ts.map +1 -0
  195. package/dist/components/textarea.jsx +5 -0
  196. package/dist/components/textarea.jsx.map +1 -0
  197. package/dist/components/tooltip.d.ts +7 -0
  198. package/dist/components/tooltip.d.ts.map +1 -0
  199. package/dist/components/tooltip.jsx +11 -0
  200. package/dist/components/tooltip.jsx.map +1 -0
  201. package/dist/index.d.ts +52 -0
  202. package/dist/index.d.ts.map +1 -0
  203. package/dist/index.js +72 -0
  204. package/dist/index.js.map +1 -0
  205. package/dist/lib/theme.d.ts +11 -0
  206. package/dist/lib/theme.d.ts.map +1 -0
  207. package/dist/lib/theme.js +44 -0
  208. package/dist/lib/theme.js.map +1 -0
  209. package/dist/lib/utils.d.ts +3 -0
  210. package/dist/lib/utils.d.ts.map +1 -0
  211. package/dist/lib/utils.js +6 -0
  212. package/dist/lib/utils.js.map +1 -0
  213. package/dist/styles.css +242 -0
  214. package/package.json +85 -0
  215. package/src/components/accordion.tsx +48 -0
  216. package/src/components/alert-dialog.tsx +113 -0
  217. package/src/components/audit-timeline.tsx +102 -0
  218. package/src/components/avatar.tsx +42 -0
  219. package/src/components/badge.tsx +34 -0
  220. package/src/components/breadcrumb.tsx +99 -0
  221. package/src/components/button.tsx +58 -0
  222. package/src/components/calendar.tsx +176 -0
  223. package/src/components/card.tsx +60 -0
  224. package/src/components/chart.tsx +558 -0
  225. package/src/components/checkbox.tsx +23 -0
  226. package/src/components/combobox.tsx +264 -0
  227. package/src/components/command.tsx +120 -0
  228. package/src/components/date-picker.tsx +221 -0
  229. package/src/components/date-range-input.tsx +295 -0
  230. package/src/components/dialog.tsx +94 -0
  231. package/src/components/diff-view.tsx +182 -0
  232. package/src/components/dropdown-menu.tsx +165 -0
  233. package/src/components/empty.tsx +100 -0
  234. package/src/components/field.tsx +168 -0
  235. package/src/components/file-input.tsx +233 -0
  236. package/src/components/form.tsx +152 -0
  237. package/src/components/info-tooltip.tsx +40 -0
  238. package/src/components/input.tsx +55 -0
  239. package/src/components/json-editor.tsx +210 -0
  240. package/src/components/kbd.tsx +35 -0
  241. package/src/components/key-value-editor.tsx +423 -0
  242. package/src/components/keyboard-shortcuts-help.tsx +136 -0
  243. package/src/components/label.tsx +16 -0
  244. package/src/components/media-preview.tsx +278 -0
  245. package/src/components/multi-file-input.tsx +315 -0
  246. package/src/components/password-input.tsx +50 -0
  247. package/src/components/popover.tsx +26 -0
  248. package/src/components/revision-timeline.tsx +93 -0
  249. package/src/components/richtext-editor.tsx +624 -0
  250. package/src/components/richtext-mode.ts +39 -0
  251. package/src/components/richtext-render.tsx +51 -0
  252. package/src/components/richtext-sync.ts +57 -0
  253. package/src/components/scroll-area.tsx +41 -0
  254. package/src/components/select.tsx +200 -0
  255. package/src/components/separator.tsx +21 -0
  256. package/src/components/sheet.tsx +109 -0
  257. package/src/components/sidebar.tsx +660 -0
  258. package/src/components/skeleton.tsx +9 -0
  259. package/src/components/sonner.tsx +45 -0
  260. package/src/components/switch.tsx +24 -0
  261. package/src/components/table.tsx +93 -0
  262. package/src/components/tabs.tsx +57 -0
  263. package/src/components/textarea.tsx +18 -0
  264. package/src/components/tooltip.tsx +25 -0
  265. package/src/index.ts +342 -0
  266. package/src/lib/theme.ts +45 -0
  267. package/src/lib/utils.ts +6 -0
  268. package/src/styles.css +242 -0
@@ -0,0 +1,45 @@
1
+ import * as React from 'react'
2
+ import { Toaster as SonnerToaster, toast } from 'sonner'
3
+
4
+ export type ToasterProps = React.ComponentProps<typeof SonnerToaster>
5
+
6
+ const useDocumentTheme = (): 'light' | 'dark' => {
7
+ const [theme, setTheme] = React.useState<'light' | 'dark'>(() =>
8
+ typeof document !== 'undefined' && document.documentElement.classList.contains('dark')
9
+ ? 'dark'
10
+ : 'light',
11
+ )
12
+ React.useEffect(() => {
13
+ const el = document.documentElement
14
+ const observer = new MutationObserver(() => {
15
+ setTheme(el.classList.contains('dark') ? 'dark' : 'light')
16
+ })
17
+ observer.observe(el, { attributes: true, attributeFilter: ['class'] })
18
+ return () => observer.disconnect()
19
+ }, [])
20
+ return theme
21
+ }
22
+
23
+ export const Toaster = ({ ...props }: ToasterProps): React.ReactElement => {
24
+ const theme = useDocumentTheme()
25
+ return (
26
+ <SonnerToaster
27
+ theme={theme}
28
+ className="toaster group"
29
+ toastOptions={{
30
+ classNames: {
31
+ toast:
32
+ 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',
33
+ description: 'group-[.toast]:text-muted-foreground',
34
+ actionButton:
35
+ 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
36
+ cancelButton:
37
+ 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground',
38
+ },
39
+ }}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ export { toast }
@@ -0,0 +1,24 @@
1
+ import * as React from 'react'
2
+ import * as SwitchPrimitive from '@radix-ui/react-switch'
3
+ import { cn } from '../lib/utils.js'
4
+
5
+ export const Switch = React.forwardRef<
6
+ React.ElementRef<typeof SwitchPrimitive.Root>,
7
+ React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>
8
+ >(({ className, ...props }, ref) => (
9
+ <SwitchPrimitive.Root
10
+ ref={ref}
11
+ className={cn(
12
+ 'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
13
+ className,
14
+ )}
15
+ {...props}
16
+ >
17
+ <SwitchPrimitive.Thumb
18
+ className={cn(
19
+ 'pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0',
20
+ )}
21
+ />
22
+ </SwitchPrimitive.Root>
23
+ ))
24
+ Switch.displayName = SwitchPrimitive.Root.displayName
@@ -0,0 +1,93 @@
1
+ import * as React from 'react'
2
+ import { cn } from '../lib/utils.js'
3
+
4
+ export const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
5
+ ({ className, ...props }, ref) => (
6
+ <div className="relative w-full overflow-auto">
7
+ <table ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />
8
+ </div>
9
+ ),
10
+ )
11
+ Table.displayName = 'Table'
12
+
13
+ export const TableHeader = React.forwardRef<
14
+ HTMLTableSectionElement,
15
+ React.HTMLAttributes<HTMLTableSectionElement>
16
+ >(({ className, ...props }, ref) => (
17
+ <thead ref={ref} className={cn('[&_tr]:border-b [&_tr]:border-border bg-muted/40', className)} {...props} />
18
+ ))
19
+ TableHeader.displayName = 'TableHeader'
20
+
21
+ export const TableBody = React.forwardRef<
22
+ HTMLTableSectionElement,
23
+ React.HTMLAttributes<HTMLTableSectionElement>
24
+ >(({ className, ...props }, ref) => (
25
+ <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />
26
+ ))
27
+ TableBody.displayName = 'TableBody'
28
+
29
+ export const TableFooter = React.forwardRef<
30
+ HTMLTableSectionElement,
31
+ React.HTMLAttributes<HTMLTableSectionElement>
32
+ >(({ className, ...props }, ref) => (
33
+ <tfoot
34
+ ref={ref}
35
+ className={cn('border-t bg-muted/40 font-medium [&>tr]:last:border-b-0', className)}
36
+ {...props}
37
+ />
38
+ ))
39
+ TableFooter.displayName = 'TableFooter'
40
+
41
+ export const TableRow = React.forwardRef<
42
+ HTMLTableRowElement,
43
+ React.HTMLAttributes<HTMLTableRowElement>
44
+ >(({ className, ...props }, ref) => (
45
+ <tr
46
+ ref={ref}
47
+ className={cn(
48
+ 'border-b border-border transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
49
+ className,
50
+ )}
51
+ {...props}
52
+ />
53
+ ))
54
+ TableRow.displayName = 'TableRow'
55
+
56
+ export const TableHead = React.forwardRef<
57
+ HTMLTableCellElement,
58
+ React.ThHTMLAttributes<HTMLTableCellElement>
59
+ >(({ className, ...props }, ref) => (
60
+ <th
61
+ ref={ref}
62
+ className={cn(
63
+ 'h-10 px-3 text-left align-middle text-xs font-semibold uppercase tracking-wide text-muted-foreground border-r border-border last:border-r-0',
64
+ className,
65
+ )}
66
+ {...props}
67
+ />
68
+ ))
69
+ TableHead.displayName = 'TableHead'
70
+
71
+ export const TableCell = React.forwardRef<
72
+ HTMLTableCellElement,
73
+ React.TdHTMLAttributes<HTMLTableCellElement>
74
+ >(({ className, ...props }, ref) => (
75
+ <td
76
+ ref={ref}
77
+ className={cn('px-3 py-2 align-middle border-r border-border last:border-r-0', className)}
78
+ {...props}
79
+ />
80
+ ))
81
+ TableCell.displayName = 'TableCell'
82
+
83
+ export const TableCaption = React.forwardRef<
84
+ HTMLTableCaptionElement,
85
+ React.HTMLAttributes<HTMLTableCaptionElement>
86
+ >(({ className, ...props }, ref) => (
87
+ <caption
88
+ ref={ref}
89
+ className={cn('mt-4 text-sm text-muted-foreground', className)}
90
+ {...props}
91
+ />
92
+ ))
93
+ TableCaption.displayName = 'TableCaption'
@@ -0,0 +1,57 @@
1
+ import * as React from 'react'
2
+ import * as TabsPrimitive from '@radix-ui/react-tabs'
3
+ import { cn } from '../lib/utils.js'
4
+
5
+ export const Tabs = TabsPrimitive.Root
6
+
7
+ // Underline-style tab strip — works visually even with a single tab because
8
+ // the active item has a clearly drawn bottom indicator that anchors it to the
9
+ // content below.
10
+ export const TabsList = React.forwardRef<
11
+ React.ElementRef<typeof TabsPrimitive.List>,
12
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
13
+ >(({ className, ...props }, ref) => (
14
+ <TabsPrimitive.List
15
+ ref={ref}
16
+ className={cn(
17
+ 'flex h-10 w-full items-center justify-start gap-1 overflow-x-auto border-b border-border text-muted-foreground',
18
+ className,
19
+ )}
20
+ {...props}
21
+ />
22
+ ))
23
+ TabsList.displayName = TabsPrimitive.List.displayName
24
+
25
+ export const TabsTrigger = React.forwardRef<
26
+ React.ElementRef<typeof TabsPrimitive.Trigger>,
27
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
28
+ >(({ className, ...props }, ref) => (
29
+ <TabsPrimitive.Trigger
30
+ ref={ref}
31
+ className={cn(
32
+ 'relative -mb-px inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap border-b-2 border-transparent px-4 py-2 text-sm font-medium ring-offset-background transition-all',
33
+ 'hover:text-foreground',
34
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
35
+ 'disabled:pointer-events-none disabled:opacity-50',
36
+ 'data-[state=active]:border-primary data-[state=active]:text-foreground',
37
+ className,
38
+ )}
39
+ {...props}
40
+ />
41
+ ))
42
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
43
+
44
+ export const TabsContent = React.forwardRef<
45
+ React.ElementRef<typeof TabsPrimitive.Content>,
46
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
47
+ >(({ className, ...props }, ref) => (
48
+ <TabsPrimitive.Content
49
+ ref={ref}
50
+ className={cn(
51
+ 'mt-3 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
52
+ className,
53
+ )}
54
+ {...props}
55
+ />
56
+ ))
57
+ TabsContent.displayName = TabsPrimitive.Content.displayName
@@ -0,0 +1,18 @@
1
+ import * as React from 'react'
2
+ import { cn } from '../lib/utils.js'
3
+
4
+ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>
5
+
6
+ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
7
+ ({ className, ...props }, ref) => (
8
+ <textarea
9
+ ref={ref}
10
+ className={cn(
11
+ 'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
12
+ className,
13
+ )}
14
+ {...props}
15
+ />
16
+ ),
17
+ )
18
+ Textarea.displayName = 'Textarea'
@@ -0,0 +1,25 @@
1
+ import * as React from 'react'
2
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip'
3
+ import { cn } from '../lib/utils.js'
4
+
5
+ export const TooltipProvider = TooltipPrimitive.Provider
6
+ export const Tooltip = TooltipPrimitive.Root
7
+ export const TooltipTrigger = TooltipPrimitive.Trigger
8
+
9
+ export const TooltipContent = React.forwardRef<
10
+ React.ElementRef<typeof TooltipPrimitive.Content>,
11
+ React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
12
+ >(({ className, sideOffset = 4, ...props }, ref) => (
13
+ <TooltipPrimitive.Portal>
14
+ <TooltipPrimitive.Content
15
+ ref={ref}
16
+ sideOffset={sideOffset}
17
+ className={cn(
18
+ 'z-50 overflow-hidden rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2',
19
+ className,
20
+ )}
21
+ {...props}
22
+ />
23
+ </TooltipPrimitive.Portal>
24
+ ))
25
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName
package/src/index.ts ADDED
@@ -0,0 +1,342 @@
1
+ // @modern-admin/ui — shadcn-flavoured kit for the admin frontend. Built on
2
+ // Radix primitives + Tailwind 4 + the semantic CSS variables in styles.css.
3
+
4
+ export {
5
+ Accordion,
6
+ AccordionItem,
7
+ AccordionTrigger,
8
+ AccordionContent,
9
+ } from './components/accordion.js'
10
+
11
+ export { cn } from './lib/utils.js'
12
+ export {
13
+ initTheme,
14
+ readThemeMode,
15
+ setThemeMode,
16
+ type ThemeMode,
17
+ } from './lib/theme.js'
18
+
19
+ // Form-control primitives
20
+ export { Button, buttonVariants, type ButtonProps } from './components/button.js'
21
+ export { Input, type InputProps } from './components/input.js'
22
+ export { PasswordInput, type PasswordInputProps } from './components/password-input.js'
23
+ export { Textarea, type TextareaProps } from './components/textarea.js'
24
+ export { Label } from './components/label.js'
25
+ export { Checkbox } from './components/checkbox.js'
26
+ export { Switch } from './components/switch.js'
27
+ export { Calendar, type CalendarProps } from './components/calendar.js'
28
+ export {
29
+ DatePicker,
30
+ type DatePickerProps,
31
+ type DatePickerMode,
32
+ } from './components/date-picker.js'
33
+ export {
34
+ DateRangeInput,
35
+ type DateRangeInputProps,
36
+ type DateRangeInputLabels,
37
+ } from './components/date-range-input.js'
38
+ export {
39
+ Select,
40
+ SelectGroup,
41
+ SelectValue,
42
+ SelectTrigger,
43
+ SelectContent,
44
+ SelectItem,
45
+ SelectLabel,
46
+ SelectSeparator,
47
+ SelectScrollUpButton,
48
+ SelectScrollDownButton,
49
+ NativeSelect,
50
+ type NativeSelectProps,
51
+ } from './components/select.js'
52
+
53
+ // Layout / display
54
+ export {
55
+ Breadcrumb,
56
+ BreadcrumbList,
57
+ BreadcrumbItem,
58
+ BreadcrumbLink,
59
+ BreadcrumbPage,
60
+ BreadcrumbSeparator,
61
+ BreadcrumbEllipsis,
62
+ } from './components/breadcrumb.js'
63
+ export { Badge, badgeVariants, type BadgeProps } from './components/badge.js'
64
+ export {
65
+ Card,
66
+ CardHeader,
67
+ CardTitle,
68
+ CardDescription,
69
+ CardContent,
70
+ CardFooter,
71
+ } from './components/card.js'
72
+ export {
73
+ Table,
74
+ TableHeader,
75
+ TableBody,
76
+ TableFooter,
77
+ TableRow,
78
+ TableHead,
79
+ TableCell,
80
+ TableCaption,
81
+ } from './components/table.js'
82
+ export { Avatar, AvatarImage, AvatarFallback } from './components/avatar.js'
83
+ export { Separator } from './components/separator.js'
84
+ export { ScrollArea, ScrollBar } from './components/scroll-area.js'
85
+ export { Skeleton } from './components/skeleton.js'
86
+ export { Tabs, TabsList, TabsTrigger, TabsContent } from './components/tabs.js'
87
+
88
+ // Overlay / floating
89
+ export {
90
+ Dialog,
91
+ DialogTrigger,
92
+ DialogPortal,
93
+ DialogClose,
94
+ DialogOverlay,
95
+ DialogContent,
96
+ DialogHeader,
97
+ DialogFooter,
98
+ DialogTitle,
99
+ DialogDescription,
100
+ } from './components/dialog.js'
101
+ export {
102
+ AlertDialog,
103
+ AlertDialogTrigger,
104
+ AlertDialogPortal,
105
+ AlertDialogOverlay,
106
+ AlertDialogContent,
107
+ AlertDialogHeader,
108
+ AlertDialogFooter,
109
+ AlertDialogTitle,
110
+ AlertDialogDescription,
111
+ AlertDialogAction,
112
+ AlertDialogCancel,
113
+ } from './components/alert-dialog.js'
114
+ export {
115
+ DropdownMenu,
116
+ DropdownMenuTrigger,
117
+ DropdownMenuContent,
118
+ DropdownMenuItem,
119
+ DropdownMenuCheckboxItem,
120
+ DropdownMenuRadioItem,
121
+ DropdownMenuLabel,
122
+ DropdownMenuSeparator,
123
+ DropdownMenuShortcut,
124
+ DropdownMenuGroup,
125
+ DropdownMenuPortal,
126
+ DropdownMenuSub,
127
+ DropdownMenuSubContent,
128
+ DropdownMenuSubTrigger,
129
+ DropdownMenuRadioGroup,
130
+ } from './components/dropdown-menu.js'
131
+ export {
132
+ Popover,
133
+ PopoverTrigger,
134
+ PopoverContent,
135
+ PopoverAnchor,
136
+ } from './components/popover.js'
137
+ export {
138
+ Tooltip,
139
+ TooltipTrigger,
140
+ TooltipContent,
141
+ TooltipProvider,
142
+ } from './components/tooltip.js'
143
+ export { InfoTooltip, type InfoTooltipProps } from './components/info-tooltip.js'
144
+ export { Kbd, getModKeyLabel } from './components/kbd.js'
145
+ export {
146
+ KeyboardShortcutsHelp,
147
+ type KeyboardShortcutItem,
148
+ type KeyboardShortcutsHelpProps,
149
+ } from './components/keyboard-shortcuts-help.js'
150
+
151
+ // Command / Combobox base
152
+ export {
153
+ Command,
154
+ CommandDialog,
155
+ CommandInput,
156
+ CommandList,
157
+ CommandEmpty,
158
+ CommandGroup,
159
+ CommandItem,
160
+ CommandShortcut,
161
+ CommandSeparator,
162
+ } from './components/command.js'
163
+
164
+ // Form (react-hook-form bindings)
165
+ export {
166
+ Form,
167
+ FormItem,
168
+ FormLabel,
169
+ FormControl,
170
+ FormDescription,
171
+ FormMessage,
172
+ FormField,
173
+ useFormField,
174
+ } from './components/form.js'
175
+
176
+ // Field — pure-layout shadcn-style form-field primitives
177
+ export {
178
+ Field,
179
+ FieldLabel,
180
+ FieldDescription,
181
+ FieldError,
182
+ FieldGroup,
183
+ FieldSet,
184
+ FieldLegend,
185
+ FieldSeparator,
186
+ FieldContent,
187
+ type FieldProps,
188
+ } from './components/field.js'
189
+
190
+ // Sheet — side-anchored Dialog
191
+ export {
192
+ Sheet,
193
+ SheetTrigger,
194
+ SheetClose,
195
+ SheetPortal,
196
+ SheetOverlay,
197
+ SheetContent,
198
+ SheetHeader,
199
+ SheetFooter,
200
+ SheetTitle,
201
+ SheetDescription,
202
+ type SheetContentProps,
203
+ } from './components/sheet.js'
204
+
205
+ // Empty state
206
+ export {
207
+ Empty,
208
+ EmptyHeader,
209
+ EmptyMedia,
210
+ EmptyTitle,
211
+ EmptyDescription,
212
+ EmptyContent,
213
+ type EmptyMediaProps,
214
+ } from './components/empty.js'
215
+
216
+ // Sidebar
217
+ export {
218
+ SidebarProvider,
219
+ Sidebar,
220
+ SidebarTrigger,
221
+ SidebarRail,
222
+ SidebarInset,
223
+ SidebarInput,
224
+ SidebarHeader,
225
+ SidebarFooter,
226
+ SidebarSeparator,
227
+ SidebarContent,
228
+ SidebarGroup,
229
+ SidebarGroupLabel,
230
+ SidebarGroupAction,
231
+ SidebarGroupContent,
232
+ SidebarMenu,
233
+ SidebarMenuItem,
234
+ SidebarMenuButton,
235
+ SidebarMenuAction,
236
+ SidebarMenuBadge,
237
+ SidebarMenuSkeleton,
238
+ SidebarMenuSub,
239
+ SidebarMenuSubItem,
240
+ SidebarMenuSubButton,
241
+ useSidebar,
242
+ type SidebarProps,
243
+ type SidebarProviderProps,
244
+ type SidebarMenuButtonProps,
245
+ } from './components/sidebar.js'
246
+
247
+ // Richtext
248
+ export {
249
+ RichtextEditor,
250
+ type RichtextEditorProps,
251
+ type RichtextFormat,
252
+ } from './components/richtext-editor.js'
253
+ export {
254
+ RichtextRender,
255
+ type RichtextRenderProps,
256
+ } from './components/richtext-render.js'
257
+
258
+ // Media preview (Preview button + dialog with image/video + Download)
259
+ export {
260
+ MediaPreview,
261
+ detectMediaKind,
262
+ type MediaPreviewProps,
263
+ type MediaKind,
264
+ } from './components/media-preview.js'
265
+
266
+ // JSON editor + viewer
267
+ export {
268
+ JsonEditor,
269
+ JsonView,
270
+ type JsonEditorProps,
271
+ type JsonViewProps,
272
+ } from './components/json-editor.js'
273
+
274
+ // Combobox — free-text autocomplete input with optional suggestions
275
+ export {
276
+ Combobox,
277
+ type ComboboxProps,
278
+ type ComboboxLabels,
279
+ type ComboboxSuggestion,
280
+ } from './components/combobox.js'
281
+
282
+ // Key-value editor + viewer (fixed-keys alternative to JsonEditor)
283
+ export {
284
+ KeyValueEditor,
285
+ KeyValueView,
286
+ type KeyValueEditorProps,
287
+ type KeyValueEditorLabels,
288
+ type KeyValueViewProps,
289
+ type KeyValueViewLabels,
290
+ type KeyValueFieldSpec,
291
+ type KeyValueFieldType,
292
+ } from './components/key-value-editor.js'
293
+
294
+ // File input (upload drop-zone + current file display)
295
+ export { FileInput, type FileInputProps } from './components/file-input.js'
296
+ export {
297
+ MultiFileInput,
298
+ type MultiFileInputProps,
299
+ type MultiFileInputItem,
300
+ type MultiFileInputPendingItem,
301
+ } from './components/multi-file-input.js'
302
+
303
+ // Toast
304
+ export { Toaster, toast, type ToasterProps } from './components/sonner.js'
305
+
306
+ // Chart
307
+ export {
308
+ ChartPanel,
309
+ KpiCard,
310
+ TimeSeriesChart,
311
+ type ChartType,
312
+ type ChartDataPoint,
313
+ type ChartPanelLabels,
314
+ type ChartPanelProps,
315
+ type KpiCardLabels,
316
+ type KpiCardProps,
317
+ type TimeSeriesChartLabels,
318
+ type TimeSeriesChartProps,
319
+ type TimeSeriesChartSeries,
320
+ } from './components/chart.js'
321
+
322
+ // History / audit log
323
+ export {
324
+ DiffView,
325
+ type DiffField,
326
+ type DiffViewLabels,
327
+ type DiffViewProps,
328
+ } from './components/diff-view.js'
329
+ export {
330
+ RevisionTimeline,
331
+ type RevisionTimelineItem,
332
+ type RevisionTimelineLabels,
333
+ type RevisionTimelineProps,
334
+ } from './components/revision-timeline.js'
335
+ export {
336
+ AuditTimeline,
337
+ type AuditTimelineItem,
338
+ type AuditTimelineLabels,
339
+ type AuditTimelineProps,
340
+ } from './components/audit-timeline.js'
341
+
342
+ export const VERSION = '0.0.0'
@@ -0,0 +1,45 @@
1
+ // Tiny theme toggle helper — flips `.dark` on the document root and
2
+ // persists the preference. The actual tokens live in styles.css.
3
+
4
+ export type ThemeMode = 'light' | 'dark' | 'system'
5
+
6
+ const STORAGE_KEY = 'modern-admin:theme'
7
+
8
+ const prefersDark = (): boolean => {
9
+ if (typeof window === 'undefined' || !window.matchMedia) return false
10
+ return window.matchMedia('(prefers-color-scheme: dark)').matches
11
+ }
12
+
13
+ const applyClass = (dark: boolean): void => {
14
+ if (typeof document === 'undefined') return
15
+ document.documentElement.classList.toggle('dark', dark)
16
+ }
17
+
18
+ /** Returns the persisted theme, or 'system' when nothing was saved. */
19
+ export const readThemeMode = (): ThemeMode => {
20
+ if (typeof localStorage === 'undefined') return 'system'
21
+ const v = localStorage.getItem(STORAGE_KEY)
22
+ return v === 'light' || v === 'dark' || v === 'system' ? v : 'system'
23
+ }
24
+
25
+ /** Persist a theme choice and apply it immediately. */
26
+ export const setThemeMode = (mode: ThemeMode): void => {
27
+ if (typeof localStorage !== 'undefined') localStorage.setItem(STORAGE_KEY, mode)
28
+ applyClass(mode === 'dark' || (mode === 'system' && prefersDark()))
29
+ }
30
+
31
+ /**
32
+ * Initialize the theme on app boot. Call once in your client entry. The
33
+ * returned function unsubscribes from system preference changes.
34
+ */
35
+ export const initTheme = (): (() => void) => {
36
+ const mode = readThemeMode()
37
+ applyClass(mode === 'dark' || (mode === 'system' && prefersDark()))
38
+ if (typeof window === 'undefined' || !window.matchMedia) return () => {}
39
+ const media = window.matchMedia('(prefers-color-scheme: dark)')
40
+ const listener = (e: MediaQueryListEvent): void => {
41
+ if (readThemeMode() === 'system') applyClass(e.matches)
42
+ }
43
+ media.addEventListener('change', listener)
44
+ return () => media.removeEventListener('change', listener)
45
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]): string {
5
+ return twMerge(clsx(inputs))
6
+ }