@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,147 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Dialog as DialogPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { Button } from "@/components/ui/button"
8
+ import { X } from "lucide-react"
9
+
10
+ function Dialog({
11
+ ...props
12
+ }: React.ComponentProps<typeof DialogPrimitive.Root>) {
13
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
14
+ }
15
+
16
+ function DialogTrigger({
17
+ ...props
18
+ }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
19
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
20
+ }
21
+
22
+ function DialogPortal({
23
+ ...props
24
+ }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
25
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
26
+ }
27
+
28
+ function DialogOverlay({
29
+ className,
30
+ ...props
31
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
32
+ return (
33
+ <DialogPrimitive.Overlay
34
+ data-slot="dialog-overlay"
35
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50", className)}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function DialogContent({
42
+ className,
43
+ children,
44
+ showCloseButton = true,
45
+ ...props
46
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
47
+ showCloseButton?: boolean
48
+ }) {
49
+ return (
50
+ <DialogPortal>
51
+ <DialogOverlay />
52
+ <DialogPrimitive.Content
53
+ data-slot="dialog-content"
54
+ className={cn(
55
+ "bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
56
+ className
57
+ )}
58
+ {...props}
59
+ >
60
+ {children}
61
+ {showCloseButton && (
62
+ <DialogPrimitive.Close data-slot="dialog-close" asChild>
63
+ <Button variant="ghost" className="absolute top-2 right-2" size="icon-sm">
64
+ <X />
65
+ <span className="sr-only">Close</span>
66
+ </Button>
67
+ </DialogPrimitive.Close>
68
+ )}
69
+ </DialogPrimitive.Content>
70
+ </DialogPortal>
71
+ )
72
+ }
73
+
74
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="dialog-header"
78
+ className={cn("gap-2 flex flex-col", className)}
79
+ {...props}
80
+ />
81
+ )
82
+ }
83
+
84
+ function DialogFooter({
85
+ className,
86
+ showCloseButton = false,
87
+ children,
88
+ ...props
89
+ }: React.ComponentProps<"div"> & {
90
+ showCloseButton?: boolean
91
+ }) {
92
+ return (
93
+ <div
94
+ data-slot="dialog-footer"
95
+ className={cn(
96
+ "bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
97
+ className
98
+ )}
99
+ {...props}
100
+ >
101
+ {children}
102
+ {showCloseButton && (
103
+ <DialogPrimitive.Close asChild>
104
+ <Button variant="outline">Close</Button>
105
+ </DialogPrimitive.Close>
106
+ )}
107
+ </div>
108
+ )
109
+ }
110
+
111
+ function DialogTitle({
112
+ className,
113
+ ...props
114
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
115
+ return (
116
+ <DialogPrimitive.Title
117
+ data-slot="dialog-title"
118
+ className={cn("text-base leading-none font-medium", className)}
119
+ {...props}
120
+ />
121
+ )
122
+ }
123
+
124
+ function DialogDescription({
125
+ className,
126
+ ...props
127
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
128
+ return (
129
+ <DialogPrimitive.Description
130
+ data-slot="dialog-description"
131
+ className={cn("text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3", className)}
132
+ {...props}
133
+ />
134
+ )
135
+ }
136
+
137
+ export {
138
+ Dialog,
139
+ DialogContent,
140
+ DialogDescription,
141
+ DialogFooter,
142
+ DialogHeader,
143
+ DialogOverlay,
144
+ DialogPortal,
145
+ DialogTitle,
146
+ DialogTrigger,
147
+ }
@@ -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,36 @@
1
+ {
2
+ "name": "display-date",
3
+ "description": "Editable source registry entry for display-date.",
4
+ "importPath": "@carefully-built/ui",
5
+ "exports": [
6
+ "DisplayDate",
7
+ "DisplayDateProps"
8
+ ],
9
+ "dependencies": [
10
+ "class-variance-authority",
11
+ "clsx",
12
+ "tailwind-merge"
13
+ ],
14
+ "peerDependencies": [
15
+ "react",
16
+ "react-dom",
17
+ "radix-ui",
18
+ "lucide-react",
19
+ "react-day-picker",
20
+ "vaul"
21
+ ],
22
+ "files": [
23
+ {
24
+ "source": "primitives/display-date.tsx",
25
+ "target": "components/ui/display-date.tsx"
26
+ },
27
+ {
28
+ "source": "utils/cn.ts",
29
+ "target": "lib/utils.ts"
30
+ },
31
+ {
32
+ "source": "utils/date-display.ts",
33
+ "target": "components/ui/date-display.ts"
34
+ }
35
+ ]
36
+ }
@@ -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,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,61 @@
1
+ export type DateDisplayValue = Date | number | string;
2
+
3
+ function getDate(value: DateDisplayValue): Date {
4
+ return value instanceof Date ? value : new Date(value);
5
+ }
6
+
7
+ function startOfDay(date: Date): Date {
8
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
9
+ }
10
+
11
+ function getDayDifference(from: Date, to: Date): number {
12
+ const millisecondsPerDay = 24 * 60 * 60 * 1000;
13
+ return Math.round((startOfDay(to).getTime() - startOfDay(from).getTime()) / millisecondsPerDay);
14
+ }
15
+
16
+ function capitalizeMonthLabel(value: string): string {
17
+ return value
18
+ .split(' ')
19
+ .map((part, index) => {
20
+ if (index !== 1 || part.length === 0) {
21
+ return part;
22
+ }
23
+
24
+ const [firstCharacter = '', ...restCharacters] = part;
25
+ return `${firstCharacter.toUpperCase()}${restCharacters.join('')}`;
26
+ })
27
+ .join(' ');
28
+ }
29
+
30
+ export function formatAbsoluteDate(value: DateDisplayValue): string {
31
+ const date = getDate(value);
32
+ const currentYear = new Date().getFullYear();
33
+ const includesYear = date.getFullYear() !== currentYear;
34
+
35
+ return capitalizeMonthLabel(
36
+ new Intl.DateTimeFormat('it-IT', {
37
+ day: 'numeric',
38
+ month: 'short',
39
+ ...(includesYear ? { year: 'numeric' } : {}),
40
+ }).format(date)
41
+ );
42
+ }
43
+
44
+ export function formatDisplayDate(value: DateDisplayValue): string {
45
+ const date = getDate(value);
46
+ const dayDifference = getDayDifference(date, new Date());
47
+
48
+ if (dayDifference === 0) {
49
+ return 'Oggi';
50
+ }
51
+
52
+ if (dayDifference === 1) {
53
+ return 'Ieri';
54
+ }
55
+
56
+ if (dayDifference >= 2 && dayDifference <= 10) {
57
+ return `${String(dayDifference)} giorni fa`;
58
+ }
59
+
60
+ return formatAbsoluteDate(date);
61
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "drawer",
3
+ "description": "Editable source registry entry for drawer.",
4
+ "importPath": "@carefully-built/ui",
5
+ "exports": [
6
+ "Drawer",
7
+ "DrawerContent",
8
+ "DrawerDescription",
9
+ "DrawerHeader",
10
+ "DrawerOverlay",
11
+ "DrawerPortal",
12
+ "DrawerTitle"
13
+ ],
14
+ "dependencies": [
15
+ "class-variance-authority",
16
+ "clsx",
17
+ "tailwind-merge"
18
+ ],
19
+ "peerDependencies": [
20
+ "react",
21
+ "react-dom",
22
+ "radix-ui",
23
+ "lucide-react",
24
+ "react-day-picker",
25
+ "vaul"
26
+ ],
27
+ "files": [
28
+ {
29
+ "source": "primitives/drawer.tsx",
30
+ "target": "components/ui/drawer.tsx"
31
+ },
32
+ {
33
+ "source": "utils/cn.ts",
34
+ "target": "lib/utils.ts"
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Drawer as DrawerPrimitive } from 'vaul';
5
+
6
+ import { cn } from '@/lib/utils';
7
+
8
+ function Drawer({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
9
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
10
+ }
11
+
12
+ function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
13
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
14
+ }
15
+
16
+ function DrawerOverlay({
17
+ className,
18
+ ...props
19
+ }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
20
+ return (
21
+ <DrawerPrimitive.Overlay
22
+ data-slot="drawer-overlay"
23
+ className={cn(
24
+ 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 z-50 bg-black/10 backdrop-blur-xs',
25
+ className,
26
+ )}
27
+ {...props}
28
+ />
29
+ );
30
+ }
31
+
32
+ function DrawerContent({
33
+ className,
34
+ children,
35
+ ...props
36
+ }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
37
+ return (
38
+ <DrawerPortal data-slot="drawer-portal">
39
+ <DrawerOverlay />
40
+ <DrawerPrimitive.Content
41
+ data-slot="drawer-content"
42
+ className={cn(
43
+ 'bg-background group/drawer-content fixed z-50 flex h-auto flex-col overflow-visible text-sm data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm',
44
+ className,
45
+ )}
46
+ {...props}
47
+ >
48
+ <div className="bg-muted mx-auto mt-4 hidden h-1 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
49
+ {children}
50
+ </DrawerPrimitive.Content>
51
+ </DrawerPortal>
52
+ );
53
+ }
54
+
55
+ function DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {
56
+ return (
57
+ <div
58
+ data-slot="drawer-header"
59
+ className={cn(
60
+ 'flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-0.5 md:text-left',
61
+ className,
62
+ )}
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ function DrawerTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
69
+ return (
70
+ <DrawerPrimitive.Title
71
+ data-slot="drawer-title"
72
+ className={cn('text-foreground text-base font-medium', className)}
73
+ {...props}
74
+ />
75
+ );
76
+ }
77
+
78
+ function DrawerDescription({
79
+ className,
80
+ ...props
81
+ }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
82
+ return (
83
+ <DrawerPrimitive.Description
84
+ data-slot="drawer-description"
85
+ className={cn('text-muted-foreground text-sm', className)}
86
+ {...props}
87
+ />
88
+ );
89
+ }
90
+
91
+ export {
92
+ Drawer,
93
+ DrawerContent,
94
+ DrawerDescription,
95
+ DrawerHeader,
96
+ DrawerOverlay,
97
+ DrawerPortal,
98
+ DrawerTitle,
99
+ };
@@ -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,37 @@
1
+ {
2
+ "name": "dropdown-menu",
3
+ "description": "Editable source registry entry for dropdown-menu.",
4
+ "importPath": "@carefully-built/ui",
5
+ "exports": [
6
+ "DropdownMenu",
7
+ "DropdownMenuCheckboxItem",
8
+ "DropdownMenuContent",
9
+ "DropdownMenuItem",
10
+ "DropdownMenuLabel",
11
+ "DropdownMenuSeparator",
12
+ "DropdownMenuTrigger"
13
+ ],
14
+ "dependencies": [
15
+ "class-variance-authority",
16
+ "clsx",
17
+ "tailwind-merge"
18
+ ],
19
+ "peerDependencies": [
20
+ "react",
21
+ "react-dom",
22
+ "radix-ui",
23
+ "lucide-react",
24
+ "react-day-picker",
25
+ "vaul"
26
+ ],
27
+ "files": [
28
+ {
29
+ "source": "primitives/dropdown-menu.tsx",
30
+ "target": "components/ui/dropdown-menu.tsx"
31
+ },
32
+ {
33
+ "source": "utils/cn.ts",
34
+ "target": "lib/utils.ts"
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,140 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Check } from "lucide-react"
5
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ function DropdownMenu({
10
+ modal = false,
11
+ ...props
12
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
13
+ return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" modal={modal} {...props} />
14
+ }
15
+
16
+ function DropdownMenuTrigger({
17
+ ...props
18
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
19
+ return (
20
+ <DropdownMenuPrimitive.Trigger
21
+ data-slot="dropdown-menu-trigger"
22
+ {...props}
23
+ />
24
+ )
25
+ }
26
+
27
+ function DropdownMenuContent({
28
+ className,
29
+ align = "start",
30
+ sideOffset = 4,
31
+ ...props
32
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
33
+ return (
34
+ <DropdownMenuPrimitive.Portal>
35
+ <DropdownMenuPrimitive.Content
36
+ data-slot="dropdown-menu-content"
37
+ sideOffset={sideOffset}
38
+ align={align}
39
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto data-[state=closed]:overflow-hidden", className )}
40
+ {...props}
41
+ />
42
+ </DropdownMenuPrimitive.Portal>
43
+ )
44
+ }
45
+
46
+ function DropdownMenuItem({
47
+ className,
48
+ inset,
49
+ variant = "default",
50
+ ...props
51
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
52
+ inset?: boolean
53
+ variant?: "default" | "destructive"
54
+ }) {
55
+ return (
56
+ <DropdownMenuPrimitive.Item
57
+ data-slot="dropdown-menu-item"
58
+ data-inset={inset}
59
+ data-variant={variant}
60
+ className={cn(
61
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-pointer items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
62
+ className
63
+ )}
64
+ {...props}
65
+ />
66
+ )
67
+ }
68
+
69
+ function DropdownMenuCheckboxItem({
70
+ className,
71
+ children,
72
+ checked,
73
+ inset,
74
+ ...props
75
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {
76
+ inset?: boolean
77
+ }) {
78
+ return (
79
+ <DropdownMenuPrimitive.CheckboxItem
80
+ data-slot="dropdown-menu-checkbox-item"
81
+ data-inset={inset}
82
+ className={cn(
83
+ "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-pointer items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
84
+ className
85
+ )}
86
+ checked={checked}
87
+ {...props}
88
+ >
89
+ <span
90
+ className="absolute right-2 flex items-center justify-center pointer-events-none"
91
+ data-slot="dropdown-menu-checkbox-item-indicator"
92
+ >
93
+ <DropdownMenuPrimitive.ItemIndicator>
94
+ <Check className="size-4" />
95
+ </DropdownMenuPrimitive.ItemIndicator>
96
+ </span>
97
+ {children}
98
+ </DropdownMenuPrimitive.CheckboxItem>
99
+ )
100
+ }
101
+
102
+ function DropdownMenuLabel({
103
+ className,
104
+ inset,
105
+ ...props
106
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
107
+ inset?: boolean
108
+ }) {
109
+ return (
110
+ <DropdownMenuPrimitive.Label
111
+ data-slot="dropdown-menu-label"
112
+ data-inset={inset}
113
+ className={cn("text-muted-foreground px-1.5 py-1 text-xs font-medium data-inset:pl-7", className)}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ function DropdownMenuSeparator({
120
+ className,
121
+ ...props
122
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
123
+ return (
124
+ <DropdownMenuPrimitive.Separator
125
+ data-slot="dropdown-menu-separator"
126
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
127
+ {...props}
128
+ />
129
+ )
130
+ }
131
+
132
+ export {
133
+ DropdownMenu,
134
+ DropdownMenuTrigger,
135
+ DropdownMenuContent,
136
+ DropdownMenuLabel,
137
+ DropdownMenuItem,
138
+ DropdownMenuCheckboxItem,
139
+ DropdownMenuSeparator
140
+ }
@@ -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,29 @@
1
+ export type CollectionEmptyState = "none" | "initial" | "no-results";
2
+
3
+ export interface ResolveCollectionEmptyStateOptions {
4
+ readonly totalCount: number;
5
+ readonly filteredCount: number;
6
+ readonly hasSearch?: boolean;
7
+ readonly hasFilters?: boolean;
8
+ }
9
+
10
+ export function resolveCollectionEmptyState({
11
+ totalCount,
12
+ filteredCount,
13
+ hasSearch = false,
14
+ hasFilters = false,
15
+ }: ResolveCollectionEmptyStateOptions): CollectionEmptyState {
16
+ if (filteredCount > 0) {
17
+ return "none";
18
+ }
19
+
20
+ if (totalCount === 0) {
21
+ return "initial";
22
+ }
23
+
24
+ if (hasSearch || hasFilters) {
25
+ return "no-results";
26
+ }
27
+
28
+ return "initial";
29
+ }