@carefully-built/cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +148 -7
  2. package/dist/index.mjs +71 -11
  3. package/dist/index.mjs.map +1 -1
  4. package/package.json +4 -3
  5. package/registry/ui/avatar/manifest.json +33 -0
  6. package/registry/ui/avatar/primitives/avatar.tsx +64 -0
  7. package/registry/ui/avatar/utils/cn.ts +6 -0
  8. package/registry/ui/button/manifest.json +24 -5
  9. package/registry/ui/button/utils/cn.ts +6 -0
  10. package/registry/ui/calendar/manifest.json +35 -0
  11. package/registry/ui/calendar/primitives/button.tsx +89 -0
  12. package/registry/ui/calendar/primitives/calendar.tsx +68 -0
  13. package/registry/ui/calendar/utils/cn.ts +6 -0
  14. package/registry/ui/card/manifest.json +36 -0
  15. package/registry/ui/card/primitives/card.tsx +80 -0
  16. package/registry/ui/card/utils/cn.ts +6 -0
  17. package/registry/ui/chip/manifest.json +36 -0
  18. package/registry/ui/chip/primitives/chip-utils.ts +10 -0
  19. package/registry/ui/chip/primitives/chip.tsx +74 -0
  20. package/registry/ui/chip/utils/cn.ts +6 -0
  21. package/registry/ui/chip-utils/manifest.json +33 -0
  22. package/registry/ui/chip-utils/primitives/chip-utils.ts +10 -0
  23. package/registry/ui/chip-utils/utils/cn.ts +6 -0
  24. package/registry/ui/date-display/manifest.json +33 -0
  25. package/registry/ui/date-display/utils/cn.ts +6 -0
  26. package/registry/ui/date-display/utils/date-display.ts +61 -0
  27. package/registry/ui/dialog/manifest.json +43 -0
  28. package/registry/ui/dialog/primitives/button.tsx +89 -0
  29. package/registry/ui/dialog/primitives/dialog.tsx +147 -0
  30. package/registry/ui/dialog/utils/cn.ts +6 -0
  31. package/registry/ui/display-date/manifest.json +36 -0
  32. package/registry/ui/display-date/primitives/display-date.tsx +20 -0
  33. package/registry/ui/display-date/utils/cn.ts +6 -0
  34. package/registry/ui/display-date/utils/date-display.ts +61 -0
  35. package/registry/ui/drawer/manifest.json +37 -0
  36. package/registry/ui/drawer/primitives/drawer.tsx +99 -0
  37. package/registry/ui/drawer/utils/cn.ts +6 -0
  38. package/registry/ui/dropdown-menu/manifest.json +37 -0
  39. package/registry/ui/dropdown-menu/primitives/dropdown-menu.tsx +140 -0
  40. package/registry/ui/dropdown-menu/utils/cn.ts +6 -0
  41. package/registry/ui/empty-state/empty-state/collection-empty-state.ts +29 -0
  42. package/registry/ui/empty-state/empty-state/empty-state-card.tsx +72 -0
  43. package/registry/ui/empty-state/empty-state/index.ts +8 -0
  44. package/registry/ui/empty-state/empty-state/initial-empty-state.tsx +36 -0
  45. package/registry/ui/empty-state/empty-state/no-results-state.tsx +20 -0
  46. package/registry/ui/empty-state/manifest.json +63 -0
  47. package/registry/ui/empty-state/primitives/button.tsx +89 -0
  48. package/registry/ui/empty-state/primitives/card.tsx +80 -0
  49. package/registry/ui/empty-state/utils/cn.ts +6 -0
  50. package/registry/ui/error-page/error-page/error-code.tsx +16 -0
  51. package/registry/ui/error-page/error-page/error-page-content.ts +75 -0
  52. package/registry/ui/error-page/error-page/index.ts +19 -0
  53. package/registry/ui/error-page/error-page/posthog-error-capture.ts +83 -0
  54. package/registry/ui/error-page/error-page/saas-error-page.tsx +146 -0
  55. package/registry/ui/error-page/manifest.json +64 -0
  56. package/registry/ui/error-page/primitives/button.tsx +89 -0
  57. package/registry/ui/error-page/utils/cn.ts +6 -0
  58. package/registry/ui/field-detail-row/manifest.json +32 -0
  59. package/registry/ui/field-detail-row/primitives/field-detail-row.tsx +28 -0
  60. package/registry/ui/field-detail-row/utils/cn.ts +6 -0
  61. package/registry/ui/file-dropzone/manifest.json +35 -0
  62. package/registry/ui/file-dropzone/primitives/button.tsx +89 -0
  63. package/registry/ui/file-dropzone/primitives/file-dropzone.tsx +236 -0
  64. package/registry/ui/file-dropzone/utils/cn.ts +6 -0
  65. package/registry/ui/help-info-button/manifest.json +72 -0
  66. package/registry/ui/help-info-button/overlays/responsive-sheet.footer.tsx +88 -0
  67. package/registry/ui/help-info-button/overlays/responsive-sheet.layouts.tsx +207 -0
  68. package/registry/ui/help-info-button/overlays/responsive-sheet.shortcuts.ts +103 -0
  69. package/registry/ui/help-info-button/overlays/responsive-sheet.tsx +132 -0
  70. package/registry/ui/help-info-button/primitives/button.tsx +89 -0
  71. package/registry/ui/help-info-button/primitives/drawer.tsx +99 -0
  72. package/registry/ui/help-info-button/primitives/help-info-button.tsx +63 -0
  73. package/registry/ui/help-info-button/primitives/keyboard-shortcut-hint.tsx +40 -0
  74. package/registry/ui/help-info-button/primitives/sheet.tsx +103 -0
  75. package/registry/ui/help-info-button/primitives/tooltip.tsx +57 -0
  76. package/registry/ui/help-info-button/utils/cn.ts +6 -0
  77. package/registry/ui/help-info-button/utils/use-media-query.ts +28 -0
  78. package/registry/ui/input/manifest.json +31 -0
  79. package/registry/ui/input/primitives/input.tsx +19 -0
  80. package/registry/ui/input/utils/cn.ts +6 -0
  81. package/registry/ui/keyboard-shortcut-hint/manifest.json +32 -0
  82. package/registry/ui/keyboard-shortcut-hint/primitives/keyboard-shortcut-hint.tsx +40 -0
  83. package/registry/ui/keyboard-shortcut-hint/utils/cn.ts +6 -0
  84. package/registry/ui/label/manifest.json +31 -0
  85. package/registry/ui/label/primitives/label.tsx +21 -0
  86. package/registry/ui/label/utils/cn.ts +6 -0
  87. package/registry/ui/pagination/manifest.json +36 -0
  88. package/registry/ui/pagination/primitives/button.tsx +89 -0
  89. package/registry/ui/pagination/primitives/pagination.tsx +143 -0
  90. package/registry/ui/pagination/utils/cn.ts +6 -0
  91. package/registry/ui/popover/manifest.json +33 -0
  92. package/registry/ui/popover/primitives/popover.tsx +46 -0
  93. package/registry/ui/popover/utils/cn.ts +6 -0
  94. package/registry/ui/responsive-sheet/manifest.json +66 -0
  95. package/registry/ui/responsive-sheet/overlays/responsive-sheet.footer.tsx +88 -0
  96. package/registry/ui/responsive-sheet/overlays/responsive-sheet.layouts.tsx +207 -0
  97. package/registry/ui/responsive-sheet/overlays/responsive-sheet.shortcuts.ts +103 -0
  98. package/registry/ui/responsive-sheet/overlays/responsive-sheet.tsx +132 -0
  99. package/registry/ui/responsive-sheet/primitives/button.tsx +89 -0
  100. package/registry/ui/responsive-sheet/primitives/drawer.tsx +99 -0
  101. package/registry/ui/responsive-sheet/primitives/keyboard-shortcut-hint.tsx +40 -0
  102. package/registry/ui/responsive-sheet/primitives/sheet.tsx +103 -0
  103. package/registry/ui/responsive-sheet/utils/cn.ts +6 -0
  104. package/registry/ui/responsive-sheet/utils/use-media-query.ts +28 -0
  105. package/registry/ui/responsive-sheet.footer/manifest.json +40 -0
  106. package/registry/ui/responsive-sheet.footer/overlays/responsive-sheet.footer.tsx +88 -0
  107. package/registry/ui/responsive-sheet.footer/primitives/button.tsx +89 -0
  108. package/registry/ui/responsive-sheet.footer/primitives/keyboard-shortcut-hint.tsx +40 -0
  109. package/registry/ui/responsive-sheet.footer/utils/cn.ts +6 -0
  110. package/registry/ui/responsive-sheet.shortcuts/manifest.json +34 -0
  111. package/registry/ui/responsive-sheet.shortcuts/overlays/responsive-sheet.shortcuts.ts +103 -0
  112. package/registry/ui/responsive-sheet.shortcuts/utils/cn.ts +6 -0
  113. package/registry/ui/scroll-fade-area/manifest.json +31 -0
  114. package/registry/ui/scroll-fade-area/primitives/scroll-fade-area.tsx +295 -0
  115. package/registry/ui/scroll-fade-area/utils/cn.ts +6 -0
  116. package/registry/ui/search/manifest.json +35 -0
  117. package/registry/ui/search/utils/cn.ts +6 -0
  118. package/registry/ui/search/utils/search.ts +227 -0
  119. package/registry/ui/searchable-select/manifest.json +48 -0
  120. package/registry/ui/searchable-select/primitives/input.tsx +19 -0
  121. package/registry/ui/searchable-select/search/searchable-select-position.ts +95 -0
  122. package/registry/ui/searchable-select/search/searchable-select.tsx +431 -0
  123. package/registry/ui/searchable-select/utils/cn.ts +6 -0
  124. package/registry/ui/searchable-select/utils/search.ts +227 -0
  125. package/registry/ui/searchable-select-position/manifest.json +32 -0
  126. package/registry/ui/searchable-select-position/search/searchable-select-position.ts +95 -0
  127. package/registry/ui/searchable-select-position/utils/cn.ts +6 -0
  128. package/registry/ui/segmented-toggle/manifest.json +41 -0
  129. package/registry/ui/segmented-toggle/primitives/scroll-fade-area.tsx +295 -0
  130. package/registry/ui/segmented-toggle/primitives/segmented-toggle.tsx +106 -0
  131. package/registry/ui/segmented-toggle/primitives/tabs.tsx +97 -0
  132. package/registry/ui/segmented-toggle/utils/cn.ts +6 -0
  133. package/registry/ui/select/manifest.json +37 -0
  134. package/registry/ui/select/primitives/select.tsx +142 -0
  135. package/registry/ui/select/utils/cn.ts +6 -0
  136. package/registry/ui/sheet/manifest.json +39 -0
  137. package/registry/ui/sheet/primitives/button.tsx +89 -0
  138. package/registry/ui/sheet/primitives/sheet.tsx +103 -0
  139. package/registry/ui/sheet/utils/cn.ts +6 -0
  140. package/registry/ui/skeleton/manifest.json +31 -0
  141. package/registry/ui/skeleton/primitives/skeleton.tsx +13 -0
  142. package/registry/ui/skeleton/utils/cn.ts +6 -0
  143. package/registry/ui/smart-table/manifest.json +115 -0
  144. package/registry/ui/smart-table/primitives/button.tsx +89 -0
  145. package/registry/ui/smart-table/primitives/card.tsx +80 -0
  146. package/registry/ui/smart-table/primitives/display-date.tsx +20 -0
  147. package/registry/ui/smart-table/primitives/pagination.tsx +143 -0
  148. package/registry/ui/smart-table/primitives/skeleton.tsx +13 -0
  149. package/registry/ui/smart-table/primitives/table.tsx +92 -0
  150. package/registry/ui/smart-table/primitives/tooltip.tsx +57 -0
  151. package/registry/ui/smart-table/smart-table/DesktopView.tsx +343 -0
  152. package/registry/ui/smart-table/smart-table/MobileView.tsx +170 -0
  153. package/registry/ui/smart-table/smart-table/SmartTable.tsx +85 -0
  154. package/registry/ui/smart-table/smart-table/SmartTableActions.tsx +71 -0
  155. package/registry/ui/smart-table/smart-table/TruncatedContent.tsx +147 -0
  156. package/registry/ui/smart-table/smart-table/index.ts +15 -0
  157. package/registry/ui/smart-table/smart-table/sorting.ts +148 -0
  158. package/registry/ui/smart-table/smart-table/truncated-content.utils.ts +22 -0
  159. package/registry/ui/smart-table/smart-table/types.ts +95 -0
  160. package/registry/ui/smart-table/smart-table/utils.ts +150 -0
  161. package/registry/ui/smart-table/utils/cn.ts +6 -0
  162. package/registry/ui/smart-table/utils/date-display.ts +61 -0
  163. package/registry/ui/smart-table/utils/use-media-query.ts +28 -0
  164. package/registry/ui/switch/manifest.json +31 -0
  165. package/registry/ui/switch/primitives/switch.tsx +31 -0
  166. package/registry/ui/switch/utils/cn.ts +6 -0
  167. package/registry/ui/table/manifest.json +38 -0
  168. package/registry/ui/table/primitives/table.tsx +92 -0
  169. package/registry/ui/table/utils/cn.ts +6 -0
  170. package/registry/ui/table-toolbar/manifest.json +93 -0
  171. package/registry/ui/table-toolbar/overlays/responsive-sheet.footer.tsx +88 -0
  172. package/registry/ui/table-toolbar/overlays/responsive-sheet.layouts.tsx +207 -0
  173. package/registry/ui/table-toolbar/overlays/responsive-sheet.shortcuts.ts +103 -0
  174. package/registry/ui/table-toolbar/overlays/responsive-sheet.tsx +132 -0
  175. package/registry/ui/table-toolbar/primitives/button.tsx +89 -0
  176. package/registry/ui/table-toolbar/primitives/drawer.tsx +99 -0
  177. package/registry/ui/table-toolbar/primitives/input.tsx +19 -0
  178. package/registry/ui/table-toolbar/primitives/keyboard-shortcut-hint.tsx +40 -0
  179. package/registry/ui/table-toolbar/primitives/sheet.tsx +103 -0
  180. package/registry/ui/table-toolbar/search/searchable-select-position.ts +95 -0
  181. package/registry/ui/table-toolbar/search/searchable-select.tsx +431 -0
  182. package/registry/ui/table-toolbar/table-toolbar/index.ts +9 -0
  183. package/registry/ui/table-toolbar/table-toolbar/table-toolbar.tsx +552 -0
  184. package/registry/ui/table-toolbar/utils/cn.ts +6 -0
  185. package/registry/ui/table-toolbar/utils/search.ts +227 -0
  186. package/registry/ui/table-toolbar/utils/use-media-query.ts +28 -0
  187. package/registry/ui/tabs/manifest.json +40 -0
  188. package/registry/ui/tabs/primitives/scroll-fade-area.tsx +295 -0
  189. package/registry/ui/tabs/primitives/tabs.tsx +97 -0
  190. package/registry/ui/tabs/utils/cn.ts +6 -0
  191. package/registry/ui/textarea/manifest.json +31 -0
  192. package/registry/ui/textarea/primitives/textarea.tsx +18 -0
  193. package/registry/ui/textarea/utils/cn.ts +6 -0
  194. package/registry/ui/tooltip/manifest.json +34 -0
  195. package/registry/ui/tooltip/primitives/tooltip.tsx +57 -0
  196. package/registry/ui/tooltip/utils/cn.ts +6 -0
  197. package/registry/ui/use-media-query/manifest.json +32 -0
  198. package/registry/ui/use-media-query/utils/cn.ts +6 -0
  199. package/registry/ui/use-media-query/utils/use-media-query.ts +28 -0
  200. package/registry/ui/user-picker/manifest.json +52 -0
  201. package/registry/ui/user-picker/primitives/avatar.tsx +64 -0
  202. package/registry/ui/user-picker/primitives/button.tsx +89 -0
  203. package/registry/ui/user-picker/primitives/input.tsx +19 -0
  204. package/registry/ui/user-picker/primitives/popover.tsx +46 -0
  205. package/registry/ui/user-picker/primitives/user-picker-utils.ts +113 -0
  206. package/registry/ui/user-picker/primitives/user-picker.tsx +226 -0
  207. package/registry/ui/user-picker/utils/cn.ts +6 -0
  208. package/registry/ui/user-picker-utils/manifest.json +38 -0
  209. package/registry/ui/user-picker-utils/primitives/user-picker-utils.ts +113 -0
  210. package/registry/ui/user-picker-utils/utils/cn.ts +6 -0
  211. package/registry/ui/button/cn.ts +0 -6
  212. /package/registry/ui/button/{button.tsx → primitives/button.tsx} +0 -0
@@ -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
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "smart-table",
3
+ "description": "Editable source registry entry for smart-table.",
4
+ "importPath": "@carefully-built/ui",
5
+ "exports": [
6
+ "ActionHandlers",
7
+ "ActionType",
8
+ "Column",
9
+ "ColumnAlign",
10
+ "PaginationConfig",
11
+ "SmartTable",
12
+ "SmartTableActions",
13
+ "SmartTableProps",
14
+ "SortDirection",
15
+ "SortState",
16
+ "SortValue",
17
+ "TruncatedContent",
18
+ "useTableSorting"
19
+ ],
20
+ "dependencies": [
21
+ "class-variance-authority",
22
+ "clsx",
23
+ "tailwind-merge"
24
+ ],
25
+ "peerDependencies": [
26
+ "react",
27
+ "react-dom",
28
+ "radix-ui",
29
+ "lucide-react",
30
+ "react-day-picker",
31
+ "vaul"
32
+ ],
33
+ "files": [
34
+ {
35
+ "source": "primitives/button.tsx",
36
+ "target": "components/ui/button.tsx"
37
+ },
38
+ {
39
+ "source": "primitives/card.tsx",
40
+ "target": "components/ui/card.tsx"
41
+ },
42
+ {
43
+ "source": "primitives/display-date.tsx",
44
+ "target": "components/ui/display-date.tsx"
45
+ },
46
+ {
47
+ "source": "primitives/pagination.tsx",
48
+ "target": "components/ui/pagination.tsx"
49
+ },
50
+ {
51
+ "source": "primitives/skeleton.tsx",
52
+ "target": "components/ui/skeleton.tsx"
53
+ },
54
+ {
55
+ "source": "primitives/table.tsx",
56
+ "target": "components/ui/table.tsx"
57
+ },
58
+ {
59
+ "source": "primitives/tooltip.tsx",
60
+ "target": "components/ui/tooltip.tsx"
61
+ },
62
+ {
63
+ "source": "smart-table/DesktopView.tsx",
64
+ "target": "components/ui/smart-table/DesktopView.tsx"
65
+ },
66
+ {
67
+ "source": "smart-table/MobileView.tsx",
68
+ "target": "components/ui/smart-table/MobileView.tsx"
69
+ },
70
+ {
71
+ "source": "smart-table/SmartTable.tsx",
72
+ "target": "components/ui/smart-table/SmartTable.tsx"
73
+ },
74
+ {
75
+ "source": "smart-table/SmartTableActions.tsx",
76
+ "target": "components/ui/smart-table/SmartTableActions.tsx"
77
+ },
78
+ {
79
+ "source": "smart-table/TruncatedContent.tsx",
80
+ "target": "components/ui/smart-table/TruncatedContent.tsx"
81
+ },
82
+ {
83
+ "source": "smart-table/index.ts",
84
+ "target": "components/ui/smart-table/index.ts"
85
+ },
86
+ {
87
+ "source": "smart-table/sorting.ts",
88
+ "target": "components/ui/smart-table/sorting.ts"
89
+ },
90
+ {
91
+ "source": "smart-table/truncated-content.utils.ts",
92
+ "target": "components/ui/smart-table/truncated-content.utils.ts"
93
+ },
94
+ {
95
+ "source": "smart-table/types.ts",
96
+ "target": "components/ui/smart-table/types.ts"
97
+ },
98
+ {
99
+ "source": "smart-table/utils.ts",
100
+ "target": "components/ui/smart-table/utils.ts"
101
+ },
102
+ {
103
+ "source": "utils/cn.ts",
104
+ "target": "lib/utils.ts"
105
+ },
106
+ {
107
+ "source": "utils/date-display.ts",
108
+ "target": "components/ui/date-display.ts"
109
+ },
110
+ {
111
+ "source": "utils/use-media-query.ts",
112
+ "target": "components/ui/use-media-query.ts"
113
+ }
114
+ ]
115
+ }
@@ -0,0 +1,89 @@
1
+ import * as React from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { Slot } from "radix-ui";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "bg-primary text-primary-foreground hover:brightness-90 [a]:hover:bg-primary/80",
14
+ outline:
15
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
16
+ secondary:
17
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
18
+ ghost:
19
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
20
+ destructive:
21
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default:
26
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
27
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
28
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
29
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
30
+ icon: "size-8",
31
+ "icon-xs":
32
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
33
+ "icon-sm":
34
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
35
+ "icon-lg": "size-9",
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ variant: "default",
40
+ size: "default",
41
+ },
42
+ },
43
+ );
44
+
45
+ type ButtonVariant =
46
+ | "default"
47
+ | "outline"
48
+ | "secondary"
49
+ | "ghost"
50
+ | "destructive"
51
+ | "link";
52
+ type ButtonSize =
53
+ | "default"
54
+ | "xs"
55
+ | "sm"
56
+ | "lg"
57
+ | "icon"
58
+ | "icon-xs"
59
+ | "icon-sm"
60
+ | "icon-lg";
61
+
62
+ interface ButtonProps extends React.ComponentProps<"button"> {
63
+ readonly asChild?: boolean;
64
+ readonly size?: ButtonSize;
65
+ readonly variant?: ButtonVariant;
66
+ }
67
+
68
+ function Button({
69
+ className,
70
+ variant = "default",
71
+ size = "default",
72
+ asChild = false,
73
+ ...props
74
+ }: ButtonProps) {
75
+ const Comp = asChild ? Slot.Root : "button";
76
+
77
+ return (
78
+ <Comp
79
+ data-slot="button"
80
+ data-variant={variant}
81
+ data-size={size}
82
+ className={cn(buttonVariants({ variant, size, className }))}
83
+ {...props}
84
+ />
85
+ );
86
+ }
87
+
88
+ export { Button, buttonVariants };
89
+ export type { ButtonProps, ButtonSize, ButtonVariant };
@@ -0,0 +1,80 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Card({
6
+ className,
7
+ size = "default",
8
+ ...props
9
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
10
+ return (
11
+ <div
12
+ data-slot="card"
13
+ data-size={size}
14
+ className={cn("ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
21
+ return (
22
+ <div
23
+ data-slot="card-header"
24
+ className={cn(
25
+ "gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
26
+ className
27
+ )}
28
+ {...props}
29
+ />
30
+ )
31
+ }
32
+
33
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
34
+ return (
35
+ <div
36
+ data-slot="card-title"
37
+ className={cn("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm", className)}
38
+ {...props}
39
+ />
40
+ )
41
+ }
42
+
43
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
44
+ return (
45
+ <div
46
+ data-slot="card-description"
47
+ className={cn("text-muted-foreground text-sm", className)}
48
+ {...props}
49
+ />
50
+ )
51
+ }
52
+
53
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
54
+ return (
55
+ <div
56
+ data-slot="card-content"
57
+ className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
58
+ {...props}
59
+ />
60
+ )
61
+ }
62
+
63
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
64
+ return (
65
+ <div
66
+ data-slot="card-footer"
67
+ className={cn("bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center", className)}
68
+ {...props}
69
+ />
70
+ )
71
+ }
72
+
73
+ export {
74
+ Card,
75
+ CardHeader,
76
+ CardFooter,
77
+ CardTitle,
78
+ CardDescription,
79
+ CardContent,
80
+ }
@@ -0,0 +1,20 @@
1
+ import {
2
+ formatAbsoluteDate,
3
+ formatDisplayDate,
4
+ type DateDisplayValue,
5
+ } from "@/components/ui/date-display";
6
+
7
+ export interface DisplayDateProps {
8
+ readonly value: DateDisplayValue;
9
+ readonly className?: string;
10
+ }
11
+
12
+ export function DisplayDate({ value, className }: DisplayDateProps): React.ReactElement {
13
+ const date = value instanceof Date ? value : new Date(value);
14
+
15
+ return (
16
+ <time dateTime={date.toISOString()} title={formatAbsoluteDate(date)} className={className}>
17
+ {formatDisplayDate(date)}
18
+ </time>
19
+ );
20
+ }
@@ -0,0 +1,143 @@
1
+ 'use client';
2
+
3
+ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react';
4
+
5
+ import { Button } from '@/components/ui/button';
6
+ import { cn } from '@/lib/utils';
7
+
8
+ export interface PaginationProps {
9
+ /** Current page (1-indexed) */
10
+ currentPage: number;
11
+ /** Total number of pages */
12
+ totalPages: number;
13
+ /** Total number of items */
14
+ totalItems: number;
15
+ /** Items per page */
16
+ pageSize: number;
17
+ /** Start index of current page items (1-indexed for display) */
18
+ startIndex: number;
19
+ /** End index of current page items */
20
+ endIndex: number;
21
+ /** Go to specific page */
22
+ onPageChange: (page: number) => void;
23
+ /** Optional: page size options */
24
+ pageSizeOptions?: number[];
25
+ /** Optional: callback when page size changes */
26
+ onPageSizeChange?: (size: number) => void;
27
+ /** Optional: custom className */
28
+ className?: string;
29
+ }
30
+
31
+ export function Pagination({
32
+ currentPage,
33
+ totalPages,
34
+ totalItems,
35
+ pageSize,
36
+ startIndex,
37
+ endIndex,
38
+ onPageChange,
39
+ pageSizeOptions,
40
+ onPageSizeChange,
41
+ className,
42
+ }: PaginationProps): React.ReactElement | null {
43
+ if (totalPages <= 1) {
44
+ return null;
45
+ }
46
+
47
+ const hasPrevPage = currentPage > 1;
48
+ const hasNextPage = currentPage < totalPages;
49
+
50
+ return (
51
+ <div className={cn('flex items-center justify-between gap-3 py-3', className)}>
52
+ {/* Items info */}
53
+ <div className="text-xs text-muted-foreground">
54
+ {totalItems === 0 ? (
55
+ 'No items'
56
+ ) : (
57
+ <>
58
+ Showing <span className="font-medium">{startIndex + 1}</span> -{' '}
59
+ <span className="font-medium">{endIndex}</span> of{' '}
60
+ <span className="font-medium">{totalItems}</span>
61
+ </>
62
+ )}
63
+ </div>
64
+
65
+ <div className="flex items-center gap-1.5">
66
+ {/* Page size selector */}
67
+ {pageSizeOptions && onPageSizeChange && (
68
+ <div className="hidden items-center gap-1.5 sm:flex">
69
+ <span className="text-xs text-muted-foreground">Rows:</span>
70
+ <select
71
+ value={String(pageSize)}
72
+ onChange={(event) => {
73
+ onPageSizeChange(Number(event.target.value));
74
+ }}
75
+ className="border-input bg-background h-7 w-[64px] rounded-md border px-2 text-xs"
76
+ >
77
+ {pageSizeOptions.map((size) => (
78
+ <option key={size} value={String(size)}>
79
+ {size}
80
+ </option>
81
+ ))}
82
+ </select>
83
+ </div>
84
+ )}
85
+
86
+ {/* Page info */}
87
+ <div className="hidden text-xs text-muted-foreground sm:block">
88
+ Page {currentPage} of {totalPages}
89
+ </div>
90
+
91
+ {/* Navigation buttons */}
92
+ <div className="flex items-center gap-0.5">
93
+ <Button
94
+ variant="outline"
95
+ size="icon"
96
+ className="size-7"
97
+ onClick={() => { onPageChange(1); }}
98
+ disabled={!hasPrevPage}
99
+ >
100
+ <ChevronsLeft className="size-3.5" />
101
+ <span className="sr-only">First page</span>
102
+ </Button>
103
+ <Button
104
+ variant="outline"
105
+ size="icon"
106
+ className="size-7"
107
+ onClick={() => { onPageChange(currentPage - 1); }}
108
+ disabled={!hasPrevPage}
109
+ >
110
+ <ChevronLeft className="size-3.5" />
111
+ <span className="sr-only">Previous page</span>
112
+ </Button>
113
+
114
+ {/* Mobile page indicator */}
115
+ <span className="px-1.5 text-xs sm:hidden">
116
+ {currentPage}/{totalPages}
117
+ </span>
118
+
119
+ <Button
120
+ variant="outline"
121
+ size="icon"
122
+ className="size-7"
123
+ onClick={() => { onPageChange(currentPage + 1); }}
124
+ disabled={!hasNextPage}
125
+ >
126
+ <ChevronRight className="size-3.5" />
127
+ <span className="sr-only">Next page</span>
128
+ </Button>
129
+ <Button
130
+ variant="outline"
131
+ size="icon"
132
+ className="size-7"
133
+ onClick={() => { onPageChange(totalPages); }}
134
+ disabled={!hasNextPage}
135
+ >
136
+ <ChevronsRight className="size-3.5" />
137
+ <span className="sr-only">Last page</span>
138
+ </Button>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ );
143
+ }
@@ -0,0 +1,13 @@
1
+ import { cn } from "@/lib/utils"
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("bg-muted rounded-md animate-pulse", className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ export { Skeleton }
@@ -0,0 +1,92 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ import { cn } from '@/lib/utils';
6
+
7
+ function Table({ className, ...props }: React.ComponentProps<'table'>) {
8
+ return (
9
+ <div data-slot="table-container" className="relative w-full min-w-0 overflow-x-auto">
10
+ <table
11
+ data-slot="table"
12
+ className={cn('w-full min-w-0 caption-bottom text-sm', className)}
13
+ {...props}
14
+ />
15
+ </div>
16
+ );
17
+ }
18
+
19
+ function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
20
+ return <thead data-slot="table-header" className={cn('[&_tr]:border-b', className)} {...props} />;
21
+ }
22
+
23
+ function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
24
+ return (
25
+ <tbody
26
+ data-slot="table-body"
27
+ className={cn('[&_tr:last-child]:border-0', className)}
28
+ {...props}
29
+ />
30
+ );
31
+ }
32
+
33
+ function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {
34
+ return (
35
+ <tfoot
36
+ data-slot="table-footer"
37
+ className={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
38
+ {...props}
39
+ />
40
+ );
41
+ }
42
+
43
+ function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
44
+ return (
45
+ <tr
46
+ data-slot="table-row"
47
+ className={cn(
48
+ 'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
49
+ className,
50
+ )}
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
57
+ return (
58
+ <th
59
+ data-slot="table-head"
60
+ className={cn(
61
+ 'text-foreground h-10 overflow-hidden px-2 text-left align-middle font-medium text-ellipsis whitespace-nowrap [&:has([role=checkbox])]:pr-0',
62
+ className,
63
+ )}
64
+ {...props}
65
+ />
66
+ );
67
+ }
68
+
69
+ function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
70
+ return (
71
+ <td
72
+ data-slot="table-cell"
73
+ className={cn(
74
+ 'overflow-hidden p-2 align-middle text-ellipsis whitespace-nowrap [&:has([role=checkbox])]:pr-0',
75
+ className,
76
+ )}
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ function TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {
83
+ return (
84
+ <caption
85
+ data-slot="table-caption"
86
+ className={cn('text-muted-foreground mt-4 text-sm', className)}
87
+ {...props}
88
+ />
89
+ );
90
+ }
91
+
92
+ export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
@@ -0,0 +1,57 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Tooltip as TooltipPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function Tooltip({
22
+ ...props
23
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
24
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ }
26
+
27
+ function TooltipTrigger({
28
+ ...props
29
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
30
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
31
+ }
32
+
33
+ function TooltipContent({
34
+ className,
35
+ sideOffset = 0,
36
+ children,
37
+ ...props
38
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
39
+ return (
40
+ <TooltipPrimitive.Portal>
41
+ <TooltipPrimitive.Content
42
+ data-slot="tooltip-content"
43
+ sideOffset={sideOffset}
44
+ className={cn(
45
+ "data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 rounded-md bg-foreground px-3 py-1.5 text-xs text-background z-50 w-fit max-w-[min(20rem,calc(100vw-1.5rem))] whitespace-normal break-words origin-(--radix-tooltip-content-transform-origin)",
46
+ className
47
+ )}
48
+ {...props}
49
+ >
50
+ {children}
51
+ <TooltipPrimitive.Arrow className="size-2.5 rotate-45 rounded-[2px] bg-foreground fill-foreground z-50 translate-y-[calc(-50%_-_2px)]" />
52
+ </TooltipPrimitive.Content>
53
+ </TooltipPrimitive.Portal>
54
+ )
55
+ }
56
+
57
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }