@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,242 @@
1
+ /* Tailwind 4 CSS-first config. No tailwind.config.js — tokens live in @theme. */
2
+ @import "tailwindcss";
3
+ /* shadcn-style enter/exit/slide/zoom utilities (animate-in, fade-in-0,
4
+ slide-in-from-top-2, etc.) used by Radix primitives via data-state. */
5
+ @import "tw-animate-css";
6
+ /* `prose` long-form typography utilities for rendered HTML/Markdown
7
+ bodies (e.g. richtext fields). */
8
+ @plugin "@tailwindcss/typography";
9
+
10
+ /* Tailwind 4 only scans files inside the project that imports this CSS by
11
+ default. Our React components and shadcn primitives live in sibling
12
+ workspace packages, so we point the scanner at them explicitly. */
13
+ @source "../../react/src/**/*.{ts,tsx}";
14
+ @source "../src/**/*.{ts,tsx}";
15
+
16
+ @theme {
17
+ --animate-accordion-down: accordion-down 0.18s ease-out;
18
+ --animate-accordion-up: accordion-up 0.18s ease-out;
19
+
20
+ --color-brand-50: #f5f7ff;
21
+ --color-brand-100: #e6ebff;
22
+ --color-brand-500: #4f5af3;
23
+ --color-brand-600: #3b46d8;
24
+ --color-brand-700: #2c36b3;
25
+ --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
26
+
27
+ /* Semantic colors — bound to the `:root`/`.dark` HSL variables below.
28
+ Exposing them via @theme makes `bg-background`, `text-foreground`,
29
+ `border-border`, `bg-primary` work as utilities. */
30
+ --color-background: hsl(var(--background));
31
+ --color-foreground: hsl(var(--foreground));
32
+ --color-muted: hsl(var(--muted));
33
+ --color-muted-foreground: hsl(var(--muted-foreground));
34
+ --color-card: hsl(var(--card));
35
+ --color-card-foreground: hsl(var(--card-foreground));
36
+ --color-popover: hsl(var(--popover, var(--card)));
37
+ --color-popover-foreground: hsl(var(--popover-foreground, var(--card-foreground)));
38
+ --color-border: hsl(var(--border));
39
+ --color-input: hsl(var(--input));
40
+ --color-ring: hsl(var(--ring));
41
+ --color-primary: hsl(var(--primary));
42
+ --color-primary-foreground: hsl(var(--primary-foreground));
43
+ --color-secondary: hsl(var(--secondary));
44
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
45
+ --color-accent: hsl(var(--accent, var(--secondary)));
46
+ --color-accent-foreground: hsl(var(--accent-foreground, var(--secondary-foreground)));
47
+ --color-destructive: hsl(var(--destructive));
48
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
49
+
50
+ --radius-sm: calc(var(--radius) - 4px);
51
+ --radius-md: calc(var(--radius) - 2px);
52
+ --radius-lg: var(--radius);
53
+ --radius-xl: calc(var(--radius) + 4px);
54
+ }
55
+
56
+ /* shadcn-flavoured semantic tokens. Light theme is the default; the
57
+ `.dark` class flips them. Apps can override any variable for custom
58
+ themes — see packages/ui/themes for ready-made sets. */
59
+ :root {
60
+ --background: 0 0% 100%;
61
+ --foreground: 222 47% 11%;
62
+ --muted: 210 40% 96%;
63
+ --muted-foreground: 215 16% 47%;
64
+ --card: 0 0% 100%;
65
+ --card-foreground: 222 47% 11%;
66
+ --popover: 0 0% 100%;
67
+ --popover-foreground: 222 47% 11%;
68
+ --border: 214 32% 91%;
69
+ --input: 214 32% 91%;
70
+ --ring: 215 20% 65%;
71
+ --primary: 222 47% 11%;
72
+ --primary-foreground: 210 40% 98%;
73
+ --secondary: 210 40% 96%;
74
+ --secondary-foreground: 222 47% 11%;
75
+ --accent: 210 40% 96%;
76
+ --accent-foreground: 222 47% 11%;
77
+ --destructive: 0 84% 60%;
78
+ --destructive-foreground: 210 40% 98%;
79
+ --radius: 0.5rem;
80
+ }
81
+
82
+ .dark {
83
+ /* Near-black neutrals. Very low saturation on a slight zinc hue so the
84
+ palette reads as black/charcoal instead of navy. */
85
+ --background: 240 5% 5%;
86
+ --foreground: 0 0% 98%;
87
+ --muted: 240 4% 14%;
88
+ --muted-foreground: 240 5% 65%;
89
+ --card: 240 5% 7%;
90
+ --card-foreground: 0 0% 98%;
91
+ --popover: 240 5% 7%;
92
+ --popover-foreground: 0 0% 98%;
93
+ --border: 240 4% 18%;
94
+ --input: 240 4% 12%;
95
+ --ring: 240 5% 42%;
96
+ --primary: 0 0% 98%;
97
+ --primary-foreground: 240 6% 10%;
98
+ --secondary: 240 4% 14%;
99
+ --secondary-foreground: 0 0% 98%;
100
+ --accent: 240 4% 14%;
101
+ --accent-foreground: 0 0% 98%;
102
+ --destructive: 0 62% 40%;
103
+ --destructive-foreground: 0 0% 98%;
104
+ }
105
+
106
+ @keyframes accordion-down {
107
+ from { height: 0; }
108
+ to { height: var(--radix-accordion-content-height); }
109
+ }
110
+
111
+ @keyframes accordion-up {
112
+ from { height: var(--radix-accordion-content-height); }
113
+ to { height: 0; }
114
+ }
115
+
116
+ html, body, #root {
117
+ height: 100%;
118
+ }
119
+
120
+ body {
121
+ font-family: var(--font-sans);
122
+ color: hsl(var(--foreground));
123
+ background: hsl(var(--background));
124
+ }
125
+
126
+ /* ── Custom scrollbars ─────────────────────────────────────────────────────
127
+ Themed via the same semantic tokens as the rest of the UI so they adapt
128
+ to light/dark/custom themes automatically. Firefox uses `scrollbar-*`
129
+ props; WebKit/Blink uses `::-webkit-scrollbar*`.
130
+
131
+ Scoped to actually-scrollable containers (root, body, common overflow
132
+ utility classes, opt-in `[data-scroll]`, textarea/pre). The previous
133
+ `*` selector forced WebKit to allocate scrollbar slots on every element,
134
+ which produced tiny "dot" artifacts at the corners of small controls
135
+ (buttons, selects) during hover/transition repaints. Firefox is happy
136
+ with declaring `scrollbar-width` only on `html` — it propagates the
137
+ styling to descendants automatically. */
138
+ :where(
139
+ html,
140
+ body,
141
+ [data-scroll],
142
+ .overflow-auto,
143
+ .overflow-y-auto,
144
+ .overflow-x-auto,
145
+ .overflow-scroll,
146
+ pre,
147
+ textarea
148
+ ) {
149
+ scrollbar-width: thin;
150
+ scrollbar-color: hsl(var(--border)) transparent;
151
+ }
152
+
153
+ :where(
154
+ html,
155
+ body,
156
+ [data-scroll],
157
+ .overflow-auto,
158
+ .overflow-y-auto,
159
+ .overflow-x-auto,
160
+ .overflow-scroll,
161
+ pre,
162
+ textarea
163
+ )::-webkit-scrollbar {
164
+ width: 10px;
165
+ height: 10px;
166
+ }
167
+
168
+ :where(
169
+ html,
170
+ body,
171
+ [data-scroll],
172
+ .overflow-auto,
173
+ .overflow-y-auto,
174
+ .overflow-x-auto,
175
+ .overflow-scroll,
176
+ pre,
177
+ textarea
178
+ )::-webkit-scrollbar-track {
179
+ background: transparent;
180
+ }
181
+
182
+ :where(
183
+ html,
184
+ body,
185
+ [data-scroll],
186
+ .overflow-auto,
187
+ .overflow-y-auto,
188
+ .overflow-x-auto,
189
+ .overflow-scroll,
190
+ pre,
191
+ textarea
192
+ )::-webkit-scrollbar-thumb {
193
+ background-color: hsl(var(--border));
194
+ border: 2px solid transparent;
195
+ border-radius: 9999px;
196
+ background-clip: padding-box;
197
+ transition: background-color 150ms ease;
198
+ }
199
+
200
+ :where(
201
+ html,
202
+ body,
203
+ [data-scroll],
204
+ .overflow-auto,
205
+ .overflow-y-auto,
206
+ .overflow-x-auto,
207
+ .overflow-scroll,
208
+ pre,
209
+ textarea
210
+ )::-webkit-scrollbar-thumb:hover {
211
+ background-color: hsl(var(--muted-foreground) / 0.6);
212
+ background-clip: padding-box;
213
+ }
214
+
215
+ :where(
216
+ html,
217
+ body,
218
+ [data-scroll],
219
+ .overflow-auto,
220
+ .overflow-y-auto,
221
+ .overflow-x-auto,
222
+ .overflow-scroll,
223
+ pre,
224
+ textarea
225
+ )::-webkit-scrollbar-thumb:active {
226
+ background-color: hsl(var(--muted-foreground) / 0.85);
227
+ background-clip: padding-box;
228
+ }
229
+
230
+ :where(
231
+ html,
232
+ body,
233
+ [data-scroll],
234
+ .overflow-auto,
235
+ .overflow-y-auto,
236
+ .overflow-x-auto,
237
+ .overflow-scroll,
238
+ pre,
239
+ textarea
240
+ )::-webkit-scrollbar-corner {
241
+ background: transparent;
242
+ }
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@modern-admin/ui",
3
+ "version": "0.1.0",
4
+ "description": "i18n-unaware shadcn/ui-style React component library used by @modern-admin/react.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/modern-admin/modern-admin.git",
10
+ "directory": "packages/ui"
11
+ },
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "./styles.css": "./dist/styles.css"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src"
24
+ ],
25
+ "publishConfig": {
26
+ "registry": "https://registry.npmjs.org",
27
+ "access": "public",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./styles.css": "./dist/styles.css"
36
+ }
37
+ },
38
+ "dependencies": {
39
+ "@radix-ui/react-accordion": "^1.2.12",
40
+ "@radix-ui/react-alert-dialog": "^1.1.15",
41
+ "@radix-ui/react-avatar": "^1.1.11",
42
+ "@radix-ui/react-checkbox": "^1.3.3",
43
+ "@radix-ui/react-dialog": "^1.1.15",
44
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
45
+ "@radix-ui/react-label": "^2.1.8",
46
+ "@radix-ui/react-popover": "^1.1.15",
47
+ "@radix-ui/react-scroll-area": "^1.2.10",
48
+ "@radix-ui/react-select": "^2.2.6",
49
+ "@radix-ui/react-separator": "^1.1.8",
50
+ "@radix-ui/react-slot": "^1.2.4",
51
+ "@radix-ui/react-switch": "^1.2.6",
52
+ "@radix-ui/react-tabs": "^1.1.13",
53
+ "@radix-ui/react-tooltip": "^1.2.8",
54
+ "@tailwindcss/typography": "^0.5.19",
55
+ "@tiptap/pm": "^3.22.5",
56
+ "@tiptap/react": "^3.22.5",
57
+ "@tiptap/starter-kit": "^3.22.5",
58
+ "class-variance-authority": "^0.7.1",
59
+ "clsx": "^2.1.1",
60
+ "cmdk": "^1.1.1",
61
+ "date-fns": "^4.1.0",
62
+ "dompurify": "^3.4.2",
63
+ "lucide-react": "^1.14.0",
64
+ "marked": "^18.0.3",
65
+ "react-day-picker": "^9.14.0",
66
+ "react-hook-form": "^7.75.0",
67
+ "recharts": "^3.8.1",
68
+ "sonner": "^2.0.7",
69
+ "tailwind-merge": "^3.5.0",
70
+ "tiptap-markdown": "^0.9.0",
71
+ "tw-animate-css": "^1.4.0"
72
+ },
73
+ "devDependencies": {
74
+ "@modern-admin/tsconfig": "0.1.0",
75
+ "@types/bun": "^1.3.13",
76
+ "@types/react": "^19.2.14",
77
+ "@types/react-dom": "^19.2.3",
78
+ "tailwindcss": "^4.2.4",
79
+ "typescript": "^6.0.3"
80
+ },
81
+ "peerDependencies": {
82
+ "react": "^19.2.6",
83
+ "react-dom": "^19.2.6"
84
+ }
85
+ }
@@ -0,0 +1,48 @@
1
+ import * as AccordionPrimitive from '@radix-ui/react-accordion'
2
+ import { ChevronDown } from 'lucide-react'
3
+ import * as React from 'react'
4
+ import { cn } from '../lib/utils.js'
5
+
6
+ export const Accordion = AccordionPrimitive.Root
7
+
8
+ export const AccordionItem = React.forwardRef<
9
+ React.ElementRef<typeof AccordionPrimitive.Item>,
10
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
11
+ >(({ className, ...props }, ref) => (
12
+ <AccordionPrimitive.Item ref={ref} className={cn('border-b border-border', className)} {...props} />
13
+ ))
14
+ AccordionItem.displayName = 'AccordionItem'
15
+
16
+ export const AccordionTrigger = React.forwardRef<
17
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
18
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
19
+ >(({ className, children, ...props }, ref) => (
20
+ <AccordionPrimitive.Header className="flex">
21
+ <AccordionPrimitive.Trigger
22
+ ref={ref}
23
+ className={cn(
24
+ 'flex flex-1 cursor-pointer items-center justify-between py-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground transition-all hover:text-foreground [&[data-state=open]>svg]:rotate-180',
25
+ className,
26
+ )}
27
+ {...props}
28
+ >
29
+ {children}
30
+ <ChevronDown className="size-3.5 shrink-0 transition-transform duration-200" />
31
+ </AccordionPrimitive.Trigger>
32
+ </AccordionPrimitive.Header>
33
+ ))
34
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
35
+
36
+ export const AccordionContent = React.forwardRef<
37
+ React.ElementRef<typeof AccordionPrimitive.Content>,
38
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
39
+ >(({ className, children, ...props }, ref) => (
40
+ <AccordionPrimitive.Content
41
+ ref={ref}
42
+ className="overflow-hidden data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
43
+ {...props}
44
+ >
45
+ <div className={cn('pt-0.5 pb-1', className)}>{children}</div>
46
+ </AccordionPrimitive.Content>
47
+ ))
48
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName
@@ -0,0 +1,113 @@
1
+ import * as React from 'react'
2
+ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
3
+ import { buttonVariants } from './button.js'
4
+ import { cn } from '../lib/utils.js'
5
+
6
+ export const AlertDialog = AlertDialogPrimitive.Root
7
+ export const AlertDialogTrigger = AlertDialogPrimitive.Trigger
8
+ export const AlertDialogPortal = AlertDialogPrimitive.Portal
9
+
10
+ export const AlertDialogOverlay = React.forwardRef<
11
+ React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
12
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
13
+ >(({ className, ...props }, ref) => (
14
+ <AlertDialogPrimitive.Overlay
15
+ ref={ref}
16
+ className={cn(
17
+ 'fixed inset-0 z-50 bg-black/60 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
18
+ className,
19
+ )}
20
+ {...props}
21
+ />
22
+ ))
23
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
24
+
25
+ export const AlertDialogContent = React.forwardRef<
26
+ React.ElementRef<typeof AlertDialogPrimitive.Content>,
27
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
28
+ >(({ className, ...props }, ref) => (
29
+ <AlertDialogPortal>
30
+ <AlertDialogOverlay />
31
+ <AlertDialogPrimitive.Content
32
+ ref={ref}
33
+ className={cn(
34
+ 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-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',
35
+ className,
36
+ )}
37
+ {...props}
38
+ />
39
+ </AlertDialogPortal>
40
+ ))
41
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
42
+
43
+ export const AlertDialogHeader = ({
44
+ className,
45
+ ...props
46
+ }: React.HTMLAttributes<HTMLDivElement>): React.ReactElement => (
47
+ <div
48
+ className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
49
+ {...props}
50
+ />
51
+ )
52
+ AlertDialogHeader.displayName = 'AlertDialogHeader'
53
+
54
+ export const AlertDialogFooter = ({
55
+ className,
56
+ ...props
57
+ }: React.HTMLAttributes<HTMLDivElement>): React.ReactElement => (
58
+ <div
59
+ className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2', className)}
60
+ {...props}
61
+ />
62
+ )
63
+ AlertDialogFooter.displayName = 'AlertDialogFooter'
64
+
65
+ export const AlertDialogTitle = React.forwardRef<
66
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
67
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
68
+ >(({ className, ...props }, ref) => (
69
+ <AlertDialogPrimitive.Title
70
+ ref={ref}
71
+ className={cn('text-lg font-semibold', className)}
72
+ {...props}
73
+ />
74
+ ))
75
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
76
+
77
+ export const AlertDialogDescription = React.forwardRef<
78
+ React.ElementRef<typeof AlertDialogPrimitive.Description>,
79
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
80
+ >(({ className, ...props }, ref) => (
81
+ <AlertDialogPrimitive.Description
82
+ ref={ref}
83
+ className={cn('text-sm text-muted-foreground', className)}
84
+ {...props}
85
+ />
86
+ ))
87
+ AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName
88
+
89
+ export const AlertDialogAction = React.forwardRef<
90
+ React.ElementRef<typeof AlertDialogPrimitive.Action>,
91
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> & {
92
+ variant?: 'default' | 'destructive'
93
+ }
94
+ >(({ className, variant = 'default', ...props }, ref) => (
95
+ <AlertDialogPrimitive.Action
96
+ ref={ref}
97
+ className={cn(buttonVariants({ variant }), className)}
98
+ {...props}
99
+ />
100
+ ))
101
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
102
+
103
+ export const AlertDialogCancel = React.forwardRef<
104
+ React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
105
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
106
+ >(({ className, ...props }, ref) => (
107
+ <AlertDialogPrimitive.Cancel
108
+ ref={ref}
109
+ className={cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className)}
110
+ {...props}
111
+ />
112
+ ))
113
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
@@ -0,0 +1,102 @@
1
+ import * as React from 'react'
2
+ import { cn } from '../lib/utils.js'
3
+
4
+ export interface AuditTimelineItem {
5
+ /** Stable id for React reconciliation; falls back to `at + index`. */
6
+ id?: string
7
+ resourceId: string
8
+ action: string
9
+ recordId?: string
10
+ recordIds?: string[]
11
+ userId?: string
12
+ at: number
13
+ }
14
+
15
+ export interface AuditTimelineLabels {
16
+ unknownUser?: string
17
+ noEvents?: string
18
+ records?: string
19
+ }
20
+
21
+ export interface AuditTimelineProps {
22
+ items: ReadonlyArray<AuditTimelineItem>
23
+ labels?: AuditTimelineLabels
24
+ className?: string
25
+ formatDate?: (value: number) => string
26
+ }
27
+
28
+ const DEFAULT_LABELS: Required<AuditTimelineLabels> = {
29
+ unknownUser: 'Unknown user',
30
+ noEvents: 'No events',
31
+ records: 'records',
32
+ }
33
+
34
+ export function AuditTimeline({
35
+ items,
36
+ labels,
37
+ className,
38
+ formatDate = (v) => new Date(v).toISOString(),
39
+ }: AuditTimelineProps): React.ReactElement {
40
+ const l = { ...DEFAULT_LABELS, ...labels }
41
+ if (items.length === 0) {
42
+ return (
43
+ <div className={cn('rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground', className)}>
44
+ {l.noEvents}
45
+ </div>
46
+ )
47
+ }
48
+ return (
49
+ <ol className={cn('relative space-y-3', className)}>
50
+ {items.map((item, index) => (
51
+ <li key={item.id ?? `${item.at}:${index}`} className="relative rounded-lg border bg-card p-4 shadow-sm">
52
+ <div className="flex flex-wrap items-start justify-between gap-3">
53
+ <div className="flex min-w-0 items-start gap-3">
54
+ <span className="flex size-9 shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-semibold text-primary">
55
+ {initials(item.userId ?? l.unknownUser)}
56
+ </span>
57
+ <div className="min-w-0 space-y-1">
58
+ <p className="truncate text-sm font-medium">
59
+ {item.userId ?? l.unknownUser}
60
+ </p>
61
+ <p className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
62
+ <ActionChip action={item.action} />
63
+ <span className="rounded-full border bg-muted px-2 py-0.5 text-xs">
64
+ {item.resourceId}
65
+ </span>
66
+ {item.recordId && (
67
+ <code className="rounded bg-muted px-1.5 py-0.5 text-xs">
68
+ #{item.recordId}
69
+ </code>
70
+ )}
71
+ {!item.recordId && item.recordIds?.length ? (
72
+ <span className="text-xs">
73
+ {item.recordIds.length} {l.records}
74
+ </span>
75
+ ) : null}
76
+ </p>
77
+ </div>
78
+ </div>
79
+ <time className="shrink-0 text-xs text-muted-foreground">
80
+ {formatDate(item.at)}
81
+ </time>
82
+ </div>
83
+ </li>
84
+ ))}
85
+ </ol>
86
+ )
87
+ }
88
+
89
+ function ActionChip({ action }: { action: string }): React.ReactElement {
90
+ return (
91
+ <span className="rounded-full border border-primary/20 bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary">
92
+ {action}
93
+ </span>
94
+ )
95
+ }
96
+
97
+ function initials(value: string): string {
98
+ const parts = value.split(/\s+|[._@-]/).filter(Boolean)
99
+ if (parts.length === 0) return '?'
100
+ if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase()
101
+ return (parts[0]![0]! + parts[1]![0]!).toUpperCase()
102
+ }
@@ -0,0 +1,42 @@
1
+ import * as React from 'react'
2
+ import * as AvatarPrimitive from '@radix-ui/react-avatar'
3
+ import { cn } from '../lib/utils.js'
4
+
5
+ export const Avatar = React.forwardRef<
6
+ React.ElementRef<typeof AvatarPrimitive.Root>,
7
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
8
+ >(({ className, ...props }, ref) => (
9
+ <AvatarPrimitive.Root
10
+ ref={ref}
11
+ className={cn('relative flex h-9 w-9 shrink-0 overflow-hidden rounded-full', className)}
12
+ {...props}
13
+ />
14
+ ))
15
+ Avatar.displayName = AvatarPrimitive.Root.displayName
16
+
17
+ export const AvatarImage = React.forwardRef<
18
+ React.ElementRef<typeof AvatarPrimitive.Image>,
19
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
20
+ >(({ className, ...props }, ref) => (
21
+ <AvatarPrimitive.Image
22
+ ref={ref}
23
+ className={cn('aspect-square h-full w-full', className)}
24
+ {...props}
25
+ />
26
+ ))
27
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName
28
+
29
+ export const AvatarFallback = React.forwardRef<
30
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
31
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
32
+ >(({ className, ...props }, ref) => (
33
+ <AvatarPrimitive.Fallback
34
+ ref={ref}
35
+ className={cn(
36
+ 'flex h-full w-full items-center justify-center rounded-full bg-muted text-sm font-medium text-muted-foreground',
37
+ className,
38
+ )}
39
+ {...props}
40
+ />
41
+ ))
42
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
@@ -0,0 +1,34 @@
1
+ import * as React from 'react'
2
+ import { cva, type VariantProps } from 'class-variance-authority'
3
+ import { cn } from '../lib/utils.js'
4
+
5
+ const badgeVariants = cva(
6
+ 'inline-flex items-center rounded-full border border-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',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
11
+ secondary:
12
+ 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
13
+ destructive:
14
+ 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
15
+ outline: 'text-foreground',
16
+ success: 'border-transparent bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300',
17
+ },
18
+ },
19
+ defaultVariants: { variant: 'default' },
20
+ },
21
+ )
22
+
23
+ export interface BadgeProps
24
+ extends React.HTMLAttributes<HTMLSpanElement>,
25
+ VariantProps<typeof badgeVariants> {}
26
+
27
+ export const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
28
+ ({ className, variant, ...props }, ref) => (
29
+ <span ref={ref} className={cn(badgeVariants({ variant }), className)} {...props} />
30
+ ),
31
+ )
32
+ Badge.displayName = 'Badge'
33
+
34
+ export { badgeVariants }