startx 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.editorconfig +20 -0
  2. package/.prettierignore +24 -0
  3. package/.prettierrc.js +52 -0
  4. package/.vscode/settings.json +3 -0
  5. package/LICENSE +21 -0
  6. package/apps/core-server/.env.example +24 -0
  7. package/apps/core-server/Dockerfile +61 -0
  8. package/apps/core-server/eslint.config.mjs +47 -0
  9. package/apps/core-server/package.json +73 -0
  10. package/apps/core-server/src/config/custom-type.ts +54 -0
  11. package/apps/core-server/src/events/index.ts +37 -0
  12. package/apps/core-server/src/index.ts +19 -0
  13. package/apps/core-server/src/middlewares/auth-middleware.ts +50 -0
  14. package/apps/core-server/src/middlewares/cors-middleware.ts +6 -0
  15. package/apps/core-server/src/middlewares/error-middleware.ts +23 -0
  16. package/apps/core-server/src/middlewares/logger-middleware.ts +21 -0
  17. package/apps/core-server/src/middlewares/notfound-middleware.ts +14 -0
  18. package/apps/core-server/src/middlewares/serve-static.ts +24 -0
  19. package/apps/core-server/src/routes/files/router.ts +7 -0
  20. package/apps/core-server/src/routes/server.ts +36 -0
  21. package/apps/core-server/tsconfig.json +10 -0
  22. package/apps/core-server/tsdown.config.ts +14 -0
  23. package/biome.json +62 -0
  24. package/configs/eslint-config/package.json +60 -0
  25. package/configs/eslint-config/plugins.d.ts +1 -0
  26. package/configs/eslint-config/src/configs/base.ts +237 -0
  27. package/configs/eslint-config/src/configs/frontend.ts +62 -0
  28. package/configs/eslint-config/src/configs/node.ts +10 -0
  29. package/configs/eslint-config/src/plugin.ts +25 -0
  30. package/configs/eslint-config/src/rules/index.ts +30 -0
  31. package/configs/eslint-config/src/rules/no-argument-spread.test.ts +47 -0
  32. package/configs/eslint-config/src/rules/no-argument-spread.ts +96 -0
  33. package/configs/eslint-config/src/rules/no-dynamic-import-template.ts +32 -0
  34. package/configs/eslint-config/src/rules/no-internal-package-import.ts +40 -0
  35. package/configs/eslint-config/src/rules/no-interpolation-in-regular-string.ts +32 -0
  36. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.test.ts +34 -0
  37. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.ts +49 -0
  38. package/configs/eslint-config/src/rules/no-plain-errors.ts +50 -0
  39. package/configs/eslint-config/src/rules/no-skipped-tests.ts +61 -0
  40. package/configs/eslint-config/src/rules/no-top-level-relative-imports-in-backend-module.ts +27 -0
  41. package/configs/eslint-config/src/rules/no-type-unsafe-event-emitter.ts +33 -0
  42. package/configs/eslint-config/src/rules/no-uncaught-json-parse.test.ts +21 -0
  43. package/configs/eslint-config/src/rules/no-uncaught-json-parse.ts +45 -0
  44. package/configs/eslint-config/src/rules/no-untyped-config-class-field.ts +26 -0
  45. package/configs/eslint-config/src/rules/no-unused-param-catch-clause.ts +33 -0
  46. package/configs/eslint-config/src/rules/no-useless-catch-throw.test.ts +34 -0
  47. package/configs/eslint-config/src/rules/no-useless-catch-throw.ts +47 -0
  48. package/configs/eslint-config/src/utils/json.ts +21 -0
  49. package/configs/eslint-config/tsconfig.json +8 -0
  50. package/configs/eslint-config/tsdown.config.ts +11 -0
  51. package/configs/eslint-config/vitest.config.ts +3 -0
  52. package/configs/tsdown-config/package.json +14 -0
  53. package/configs/tsdown-config/src/config/tsdown.base.ts +13 -0
  54. package/configs/typescript-config/package.json +10 -0
  55. package/configs/typescript-config/tsconfig.common.json +32 -0
  56. package/configs/typescript-config/tsconfig.frontend.json +14 -0
  57. package/configs/typescript-config/tsconfig.node.json +9 -0
  58. package/configs/vitest-config/package.json +25 -0
  59. package/configs/vitest-config/src/base.ts +34 -0
  60. package/configs/vitest-config/src/frontend.ts +15 -0
  61. package/configs/vitest-config/src/node.ts +5 -0
  62. package/configs/vitest-config/tsconfig.json +7 -0
  63. package/package.json +47 -0
  64. package/packages/@repo/constants/eslint.config.mjs +21 -0
  65. package/packages/@repo/constants/package.json +19 -0
  66. package/packages/@repo/constants/src/api.ts +1 -0
  67. package/packages/@repo/constants/src/index.ts +8 -0
  68. package/packages/@repo/constants/src/time.ts +23 -0
  69. package/packages/@repo/constants/tsconfig.json +7 -0
  70. package/packages/@repo/db/eslint.config.mjs +21 -0
  71. package/packages/@repo/db/package.json +30 -0
  72. package/packages/@repo/db/src/functions.ts +122 -0
  73. package/packages/@repo/db/src/index.ts +20 -0
  74. package/packages/@repo/db/src/schema/common.ts +49 -0
  75. package/packages/@repo/db/src/schema/index.ts +1 -0
  76. package/packages/@repo/db/tsconfig.json +13 -0
  77. package/packages/@repo/lib/eslint.config.mjs +49 -0
  78. package/packages/@repo/lib/package.json +57 -0
  79. package/packages/@repo/lib/src/bucket-module/file-storage.ts +49 -0
  80. package/packages/@repo/lib/src/bucket-module/s3-storage.ts +114 -0
  81. package/packages/@repo/lib/src/bucket-module/utils.ts +11 -0
  82. package/packages/@repo/lib/src/command-module.ts +77 -0
  83. package/packages/@repo/lib/src/constants.ts +3 -0
  84. package/packages/@repo/lib/src/cookie-module.ts +42 -0
  85. package/packages/@repo/lib/src/custom-type.ts +54 -0
  86. package/packages/@repo/lib/src/env.ts +13 -0
  87. package/packages/@repo/lib/src/error-handlers-module/index.ts +11 -0
  88. package/packages/@repo/lib/src/file-system/index.ts +90 -0
  89. package/packages/@repo/lib/src/hashing-module.ts +9 -0
  90. package/packages/@repo/lib/src/index.ts +27 -0
  91. package/packages/@repo/lib/src/logger-module/log-config.ts +16 -0
  92. package/packages/@repo/lib/src/logger-module/logger.ts +78 -0
  93. package/packages/@repo/lib/src/logger-module/memory-profiler.ts +65 -0
  94. package/packages/@repo/lib/src/mail-module/api.ts +0 -0
  95. package/packages/@repo/lib/src/mail-module/mock.ts +8 -0
  96. package/packages/@repo/lib/src/mail-module/nodemailer.ts +45 -0
  97. package/packages/@repo/lib/src/notification-module/index.ts +172 -0
  98. package/packages/@repo/lib/src/notification-module/push-notification.ts +90 -0
  99. package/packages/@repo/lib/src/oauth2-client.ts +109 -0
  100. package/packages/@repo/lib/src/otp-module.ts +98 -0
  101. package/packages/@repo/lib/src/pagination-module.ts +49 -0
  102. package/packages/@repo/lib/src/token-module.ts +35 -0
  103. package/packages/@repo/lib/src/user-session.ts +117 -0
  104. package/packages/@repo/lib/src/utils.ts +42 -0
  105. package/packages/@repo/lib/src/validation-module.ts +187 -0
  106. package/packages/@repo/lib/tsconfig.json +7 -0
  107. package/packages/@repo/mail/package.json +29 -0
  108. package/packages/@repo/mail/src/emails/admin/OtpEmail.tsx +168 -0
  109. package/packages/@repo/mail/src/index.ts +13 -0
  110. package/packages/@repo/mail/tsconfig.build.json +14 -0
  111. package/packages/@repo/mail/tsconfig.json +13 -0
  112. package/packages/@repo/mail/tsdown.config.ts +9 -0
  113. package/packages/@repo/redis/eslint.config.mjs +8 -0
  114. package/packages/@repo/redis/package.json +31 -0
  115. package/packages/@repo/redis/src/index.ts +2 -0
  116. package/packages/@repo/redis/src/lib/redis-client.ts +23 -0
  117. package/packages/@repo/redis/src/lib/redis-module.ts +3 -0
  118. package/packages/@repo/redis/tsconfig.json +12 -0
  119. package/packages/ui/components.json +17 -0
  120. package/packages/ui/eslint.config.mjs +18 -0
  121. package/packages/ui/package.json +67 -0
  122. package/packages/ui/postcss.config.mjs +9 -0
  123. package/packages/ui/src/components/custom/form-wrapper.tsx +551 -0
  124. package/packages/ui/src/components/custom/grid-component.tsx +23 -0
  125. package/packages/ui/src/components/custom/hover-tool.tsx +38 -0
  126. package/packages/ui/src/components/custom/image-picker.tsx +109 -0
  127. package/packages/ui/src/components/custom/no-content.tsx +37 -0
  128. package/packages/ui/src/components/custom/page-container.tsx +24 -0
  129. package/packages/ui/src/components/custom/page-section.tsx +59 -0
  130. package/packages/ui/src/components/custom/simple-popover.tsx +29 -0
  131. package/packages/ui/src/components/custom/switch-component.tsx +20 -0
  132. package/packages/ui/src/components/custom/theme-provider.tsx +74 -0
  133. package/packages/ui/src/components/custom/typography.tsx +111 -0
  134. package/packages/ui/src/components/extensions/carousel.tsx +392 -0
  135. package/packages/ui/src/components/hooks/event/use-click.tsx +39 -0
  136. package/packages/ui/src/components/hooks/time/useDebounce.tsx +21 -0
  137. package/packages/ui/src/components/hooks/time/useInterval.tsx +35 -0
  138. package/packages/ui/src/components/hooks/time/useTimeout.tsx +19 -0
  139. package/packages/ui/src/components/hooks/time/useTimer.tsx +51 -0
  140. package/packages/ui/src/components/hooks/use-media-query.tsx +19 -0
  141. package/packages/ui/src/components/hooks/use-persistent-storage.tsx +52 -0
  142. package/packages/ui/src/components/hooks/use-update-effect.tsx +13 -0
  143. package/packages/ui/src/components/hooks/use-window-dimension.tsx +30 -0
  144. package/packages/ui/src/components/lib/utils.ts +242 -0
  145. package/packages/ui/src/components/lucide.tsx +3 -0
  146. package/packages/ui/src/components/sonner.tsx +1 -0
  147. package/packages/ui/src/components/ui/alert-dialog.tsx +116 -0
  148. package/packages/ui/src/components/ui/avatar.tsx +53 -0
  149. package/packages/ui/src/components/ui/badge.tsx +46 -0
  150. package/packages/ui/src/components/ui/breadcrumb.tsx +109 -0
  151. package/packages/ui/src/components/ui/button.tsx +96 -0
  152. package/packages/ui/src/components/ui/card.tsx +92 -0
  153. package/packages/ui/src/components/ui/carousel.tsx +243 -0
  154. package/packages/ui/src/components/ui/checkbox.tsx +32 -0
  155. package/packages/ui/src/components/ui/command.tsx +155 -0
  156. package/packages/ui/src/components/ui/dialog.tsx +127 -0
  157. package/packages/ui/src/components/ui/dropdown-menu.tsx +226 -0
  158. package/packages/ui/src/components/ui/form.tsx +165 -0
  159. package/packages/ui/src/components/ui/input-otp.tsx +76 -0
  160. package/packages/ui/src/components/ui/input.tsx +21 -0
  161. package/packages/ui/src/components/ui/label.tsx +24 -0
  162. package/packages/ui/src/components/ui/multiple-select.tsx +510 -0
  163. package/packages/ui/src/components/ui/popover.tsx +42 -0
  164. package/packages/ui/src/components/ui/select.tsx +170 -0
  165. package/packages/ui/src/components/ui/separator.tsx +28 -0
  166. package/packages/ui/src/components/ui/sheet.tsx +130 -0
  167. package/packages/ui/src/components/ui/skeleton.tsx +13 -0
  168. package/packages/ui/src/components/ui/spinner.tsx +16 -0
  169. package/packages/ui/src/components/ui/switch.tsx +28 -0
  170. package/packages/ui/src/components/ui/table.tsx +116 -0
  171. package/packages/ui/src/components/ui/tabs.tsx +54 -0
  172. package/packages/ui/src/components/ui/textarea.tsx +18 -0
  173. package/packages/ui/src/components/ui/timeline.tsx +118 -0
  174. package/packages/ui/src/components/ui/tooltip.tsx +30 -0
  175. package/packages/ui/src/components/util/n-formattor.ts +22 -0
  176. package/packages/ui/src/components/util/storage.ts +37 -0
  177. package/packages/ui/src/globals.css +87 -0
  178. package/packages/ui/tailwind.config.ts +94 -0
  179. package/packages/ui/tsconfig.json +12 -0
  180. package/pnpm-workspace.yaml +43 -0
  181. package/turbo.json +77 -0
@@ -0,0 +1,242 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { type ClassValue, clsx } from 'clsx';
3
+ import {
4
+ format,
5
+ isToday,
6
+ isYesterday,
7
+ isThisWeek,
8
+ differenceInDays,
9
+ formatDistance,
10
+ parseISO,
11
+ differenceInYears,
12
+ } from 'date-fns';
13
+ import { twMerge } from 'tailwind-merge';
14
+
15
+ import type { Store } from '../util/storage';
16
+
17
+ export function cn(...inputs: ClassValue[]) {
18
+ return twMerge(clsx(inputs));
19
+ }
20
+
21
+ // function isFileArray(value: any): value is File[] {
22
+ // return Array.isArray(value) && value.every(item => item instanceof File);
23
+ // }
24
+
25
+ export function getFormData(object: {
26
+ [key: string]: undefined | string | number | boolean | Blob | File | object | File[];
27
+ }): FormData {
28
+ const formData = new FormData();
29
+ Object.entries(object).forEach(([key, value]) => {
30
+ if (value instanceof Blob || value instanceof File) {
31
+ formData.append(key, value);
32
+ } else if (value instanceof FileList || (Array.isArray(value) && value[0] instanceof File)) {
33
+ Array.from(value).forEach((file: File) => {
34
+ formData.append(key, file);
35
+ });
36
+ } else {
37
+ if (!value) return;
38
+ formData.append(key, JSON.stringify(value));
39
+ }
40
+ });
41
+ return formData;
42
+ }
43
+
44
+ export function switchPath(pathname: string, tab: string) {
45
+ const fragments = pathname.split('/').filter((str) => str);
46
+ fragments[2] = tab;
47
+ const path = `/${fragments.join('/')}`;
48
+ return path;
49
+ }
50
+
51
+ export function getRelativeDate(date?: string | Date) {
52
+ const now = new Date();
53
+ if (!date) return '';
54
+ if (isToday(date)) {
55
+ return format(date, 'h:mm a');
56
+ } else if (isYesterday(date)) {
57
+ return 'yesterday';
58
+ } else if (isThisWeek(date) && differenceInDays(now, date) <= 7) {
59
+ return format(date, 'EEEE'); // EEEE gives the full name of the day like Sunday, Monday
60
+ } else {
61
+ return format(date, 'dd/MM/yy');
62
+ }
63
+ }
64
+
65
+ export function getRelativeDateWithTime(date?: string | Date) {
66
+ const now = new Date();
67
+ if (!date) return '';
68
+ return formatDistance(new Date(date), now, { addSuffix: true });
69
+ }
70
+
71
+ export function getRelativeProDate(dateString: string) {
72
+ try {
73
+ const date = parseISO(dateString);
74
+ const now = new Date();
75
+ const yearsDifference = differenceInYears(now, date);
76
+ const dateFormat = yearsDifference >= 1 ? 'dd MMM yyyy, h:mm a' : 'dd MMM, h:mm a';
77
+ const formattedDate = format(date, dateFormat);
78
+ return formattedDate;
79
+ } catch (error) {
80
+ console.error('Error formatting date:', error);
81
+ return '';
82
+ }
83
+ }
84
+ export function isValidId(str: string) {
85
+ const regex = /^[a-f0-9]{24}$/i;
86
+ return regex.test(str);
87
+ }
88
+
89
+ export function getRelativeDateOnly(date?: string | Date) {
90
+ const now = new Date();
91
+ if (!date) return '';
92
+ if (isToday(date)) {
93
+ return 'today';
94
+ } else if (isYesterday(date)) {
95
+ return 'yesterday';
96
+ } else if (isThisWeek(date) && differenceInDays(now, date) <= 7) {
97
+ return format(date, 'EEEE'); // EEEE gives the full name of the day like Sunday, Monday
98
+ } else {
99
+ return format(date, 'dd/MM/yy');
100
+ }
101
+ }
102
+ export type SocialMediaUrlMetaData = {
103
+ platform: 'youtube' | 'x' | 'instagram';
104
+ url: string;
105
+ contentId: string;
106
+ };
107
+ export function getUrlMetaData(urlString: string): SocialMediaUrlMetaData | null {
108
+ const url = new URL(urlString);
109
+ let contentId: string;
110
+ let platform: 'youtube' | 'x' | 'instagram';
111
+ switch (url.origin) {
112
+ case 'https://youtu.be':
113
+ platform = 'youtube';
114
+ contentId = url.pathname.replace('/', '');
115
+ break;
116
+ case 'https://www.youtube.com':
117
+ platform = 'youtube';
118
+ contentId = url.searchParams.get('v') as string;
119
+ break;
120
+ case 'https://x.com':
121
+ platform = 'x';
122
+ contentId = url.pathname
123
+ .split('/')
124
+ .filter((str) => str)
125
+ .at(-1) as string;
126
+ break;
127
+ case 'https://www.instagram.com':
128
+ platform = 'instagram';
129
+ contentId = url.pathname
130
+ .split('/')
131
+ .filter((str) => str)
132
+ .at(-1) as string;
133
+ break;
134
+ case 'https://instagram.com':
135
+ platform = 'instagram';
136
+ contentId = url.pathname
137
+ .split('/')
138
+ .filter((str) => str)
139
+ .at(-1) as string;
140
+ break;
141
+ default:
142
+ return null;
143
+ }
144
+ return {
145
+ platform,
146
+ url: urlString,
147
+ contentId,
148
+ };
149
+ }
150
+
151
+ export function isValidUrl(url: string) {
152
+ try {
153
+ const origin = new URL(url).origin;
154
+ return true;
155
+ } catch (error) {
156
+ return false;
157
+ }
158
+ }
159
+
160
+ export function memoize<T extends (...args: any[]) => any>(fn: T): T {
161
+ const cache: { [key: string]: ReturnType<T> } = {};
162
+
163
+ return ((...args: Parameters<T>): ReturnType<T> => {
164
+ const key = JSON.stringify(args);
165
+ if (cache[key] !== undefined) {
166
+ return cache[key];
167
+ } else {
168
+ const result = fn(...args);
169
+ cache[key] = result;
170
+ return result;
171
+ }
172
+ }) as T;
173
+ }
174
+
175
+ export function memoizeAsync<T extends (...args: any[]) => Promise<any>>(fn: T): T {
176
+ const cache: { [key: string]: ReturnType<T> } = {};
177
+
178
+ return (async (...args: Parameters<T>): Promise<ReturnType<T>> => {
179
+ const key = JSON.stringify(args);
180
+ if (cache[key] !== undefined) {
181
+ return await cache[key];
182
+ } else {
183
+ const result = await fn(...args);
184
+ cache[key] = result;
185
+ return result;
186
+ }
187
+ }) as T;
188
+ }
189
+ export function memoizePersistentAsync<T extends (...args: any[]) => Promise<any>>(
190
+ fn: T,
191
+ store: Store,
192
+ ): T {
193
+ return (async (...args: Parameters<T>): Promise<ReturnType<T>> => {
194
+ const key = JSON.stringify(args);
195
+ const cachedValue = store.get(key);
196
+ if (cachedValue !== null) {
197
+ try {
198
+ return JSON.parse(cachedValue);
199
+ } catch (error) {
200
+ console.error('Error parsing cached value:', error);
201
+ return await fn(...args);
202
+ }
203
+ } else {
204
+ const result = await fn(...args);
205
+ store.set(key, JSON.stringify(result));
206
+ return result;
207
+ }
208
+ }) as T;
209
+ }
210
+
211
+ export function formatNumberWithKMB(num: number): string {
212
+ const formatter = new Intl.NumberFormat('en-US', {
213
+ notation: 'compact',
214
+ minimumSignificantDigits: 1,
215
+ maximumSignificantDigits: 3,
216
+ });
217
+
218
+ return formatter.format(num);
219
+ }
220
+ export function currencyToNumber(formattedCurrency: string): number {
221
+ // Remove everything except digits, minus sign, and decimal point
222
+ const numericString = formattedCurrency.replace(/[^0-9.-]+/g, '');
223
+
224
+ // Convert the string back to a number
225
+ const parsedNumber = Number.parseFloat(numericString);
226
+
227
+ // Handle potential NaN if parsing fails
228
+ if (isNaN(parsedNumber)) {
229
+ throw new Error('Invalid currency format');
230
+ }
231
+
232
+ return parsedNumber;
233
+ }
234
+
235
+ export function createLabels(e: string) {
236
+ return e
237
+ .replaceAll('_', ' ')
238
+ .replace(/\b\w/g, (char) => char.toUpperCase())
239
+ .trim();
240
+ }
241
+
242
+ export { cva, type VariantProps } from 'class-variance-authority';
@@ -0,0 +1,3 @@
1
+ export * from "lucide-react";
2
+ // export * from "react-icons/fa";
3
+ export * from "react-icons/fa6";
@@ -0,0 +1 @@
1
+ export * from "sonner";
@@ -0,0 +1,116 @@
1
+ "use client";
2
+
3
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
4
+ import * as React from "react";
5
+ import { buttonVariants } from "@/components/ui/button";
6
+ import { cn } from "../lib/utils";
7
+
8
+ const AlertDialog = AlertDialogPrimitive.Root;
9
+
10
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
11
+
12
+ const AlertDialogPortal = AlertDialogPrimitive.Portal;
13
+
14
+ const AlertDialogOverlay = React.forwardRef<
15
+ React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
16
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
17
+ >(({ className, ...props }, ref) => (
18
+ <AlertDialogPrimitive.Overlay
19
+ className={cn(
20
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
21
+ className
22
+ )}
23
+ {...props}
24
+ ref={ref}
25
+ />
26
+ ));
27
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
28
+
29
+ const AlertDialogContent = React.forwardRef<
30
+ React.ElementRef<typeof AlertDialogPrimitive.Content>,
31
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
32
+ >(({ className, ...props }, ref) => (
33
+ <AlertDialogPortal>
34
+ <AlertDialogOverlay />
35
+ <AlertDialogPrimitive.Content
36
+ ref={ref}
37
+ className={cn(
38
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
39
+ className
40
+ )}
41
+ {...props}
42
+ />
43
+ </AlertDialogPortal>
44
+ ));
45
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
46
+
47
+ const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
48
+ <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
49
+ );
50
+ AlertDialogHeader.displayName = "AlertDialogHeader";
51
+
52
+ const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
53
+ <div
54
+ className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
55
+ {...props}
56
+ />
57
+ );
58
+ AlertDialogFooter.displayName = "AlertDialogFooter";
59
+
60
+ const AlertDialogTitle = React.forwardRef<
61
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
62
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
63
+ >(({ className, ...props }, ref) => (
64
+ <AlertDialogPrimitive.Title
65
+ ref={ref}
66
+ className={cn("text-lg font-semibold", className)}
67
+ {...props}
68
+ />
69
+ ));
70
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
71
+
72
+ const AlertDialogDescription = React.forwardRef<
73
+ React.ElementRef<typeof AlertDialogPrimitive.Description>,
74
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
75
+ >(({ className, ...props }, ref) => (
76
+ <AlertDialogPrimitive.Description
77
+ ref={ref}
78
+ className={cn("text-sm text-muted-foreground", className)}
79
+ {...props}
80
+ />
81
+ ));
82
+ AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
83
+
84
+ const AlertDialogAction = React.forwardRef<
85
+ React.ElementRef<typeof AlertDialogPrimitive.Action>,
86
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
87
+ >(({ className, ...props }, ref) => (
88
+ <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} />
89
+ ));
90
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
91
+
92
+ const AlertDialogCancel = React.forwardRef<
93
+ React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
94
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
95
+ >(({ className, ...props }, ref) => (
96
+ <AlertDialogPrimitive.Cancel
97
+ ref={ref}
98
+ className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
99
+ {...props}
100
+ />
101
+ ));
102
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
103
+
104
+ export {
105
+ AlertDialog,
106
+ AlertDialogPortal,
107
+ AlertDialogOverlay,
108
+ AlertDialogTrigger,
109
+ AlertDialogContent,
110
+ AlertDialogHeader,
111
+ AlertDialogFooter,
112
+ AlertDialogTitle,
113
+ AlertDialogDescription,
114
+ AlertDialogAction,
115
+ AlertDialogCancel,
116
+ };
@@ -0,0 +1,53 @@
1
+ "use client"
2
+
3
+ import * as AvatarPrimitive from "@radix-ui/react-avatar"
4
+ import * as React from "react"
5
+
6
+ import { cn } from "../lib/utils"
7
+
8
+ function Avatar({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
12
+ return (
13
+ <AvatarPrimitive.Root
14
+ data-slot="avatar"
15
+ className={cn(
16
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ )
22
+ }
23
+
24
+ function AvatarImage({
25
+ className,
26
+ ...props
27
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
28
+ return (
29
+ <AvatarPrimitive.Image
30
+ data-slot="avatar-image"
31
+ className={cn("aspect-square size-full", className)}
32
+ {...props}
33
+ />
34
+ )
35
+ }
36
+
37
+ function AvatarFallback({
38
+ className,
39
+ ...props
40
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
41
+ return (
42
+ <AvatarPrimitive.Fallback
43
+ data-slot="avatar-fallback"
44
+ className={cn(
45
+ "bg-muted flex size-full items-center justify-center rounded-full",
46
+ className
47
+ )}
48
+ {...props}
49
+ />
50
+ )
51
+ }
52
+
53
+ export { Avatar, AvatarImage, AvatarFallback }
@@ -0,0 +1,46 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import * as React from "react";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ const badgeVariants = cva(
8
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14
+ secondary:
15
+ "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16
+ destructive:
17
+ "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70",
18
+ outline:
19
+ "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ },
25
+ }
26
+ );
27
+
28
+ function Badge({
29
+ className,
30
+ variant,
31
+ asChild = false,
32
+ ...props
33
+ }: React.ComponentProps<"span"> &
34
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
35
+ const Comp = asChild ? Slot : "span";
36
+
37
+ return (
38
+ <Comp
39
+ data-slot="badge"
40
+ className={cn(badgeVariants({ variant }), className)}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ export { Badge, badgeVariants };
@@ -0,0 +1,109 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
3
+ import * as React from "react";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
9
+ }
10
+
11
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
12
+ return (
13
+ <ol
14
+ data-slot="breadcrumb-list"
15
+ className={cn(
16
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
25
+ return (
26
+ <li
27
+ data-slot="breadcrumb-item"
28
+ className={cn("inline-flex items-center gap-1.5", className)}
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function BreadcrumbLink({
35
+ asChild,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<"a"> & {
39
+ asChild?: boolean;
40
+ }) {
41
+ const Comp = asChild ? Slot : "a";
42
+
43
+ return (
44
+ <Comp
45
+ data-slot="breadcrumb-link"
46
+ className={cn("hover:text-foreground transition-colors", className)}
47
+ {...props}
48
+ />
49
+ );
50
+ }
51
+
52
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
53
+ return (
54
+ <span
55
+ data-slot="breadcrumb-page"
56
+ role="link"
57
+ aria-disabled="true"
58
+ aria-current="page"
59
+ className={cn("text-foreground font-normal", className)}
60
+ {...props}
61
+ />
62
+ );
63
+ }
64
+
65
+ function BreadcrumbSeparator({
66
+ children,
67
+ className,
68
+ ...props
69
+ }: React.ComponentProps<"li">) {
70
+ return (
71
+ <li
72
+ data-slot="breadcrumb-separator"
73
+ role="presentation"
74
+ aria-hidden="true"
75
+ className={cn("[&>svg]:size-3.5", className)}
76
+ {...props}
77
+ >
78
+ {children ?? <ChevronRight />}
79
+ </li>
80
+ );
81
+ }
82
+
83
+ function BreadcrumbEllipsis({
84
+ className,
85
+ ...props
86
+ }: React.ComponentProps<"span">) {
87
+ return (
88
+ <span
89
+ data-slot="breadcrumb-ellipsis"
90
+ role="presentation"
91
+ aria-hidden="true"
92
+ className={cn("flex size-9 items-center justify-center", className)}
93
+ {...props}
94
+ >
95
+ <MoreHorizontal className="size-4" />
96
+ <span className="sr-only">More</span>
97
+ </span>
98
+ );
99
+ }
100
+
101
+ export {
102
+ Breadcrumb,
103
+ BreadcrumbList,
104
+ BreadcrumbItem,
105
+ BreadcrumbLink,
106
+ BreadcrumbPage,
107
+ BreadcrumbSeparator,
108
+ BreadcrumbEllipsis,
109
+ };
@@ -0,0 +1,96 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import * as React from "react";
4
+ import { RiLoader3Line } from "react-icons/ri";
5
+
6
+ import { cn } from "../lib/utils";
7
+
8
+ const buttonVariants = cva(
9
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
16
+ outline:
17
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
20
+ ghost: "hover:bg-accent hover:text-accent-foreground",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ disabled: "text-gray-500 bg-gray-400 pointed-none",
23
+ minimal: "py-0 px-0 md:py-0 md:p-0 max-h-fit",
24
+ },
25
+ size: {
26
+ default: "h-10 px-4 py-2",
27
+ sm: "h-9 rounded-md px-3",
28
+ lg: "h-11 rounded-md px-8",
29
+ icon: "h-10 w-10",
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ variant: "default",
34
+ size: "default",
35
+ },
36
+ }
37
+ );
38
+
39
+ export interface ButtonProps
40
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
41
+ VariantProps<typeof buttonVariants> {
42
+ asChild?: boolean;
43
+ loading?: boolean;
44
+ disabled?: boolean;
45
+ hideChild?: boolean;
46
+ icon?: React.ReactNode;
47
+ }
48
+
49
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
50
+ (
51
+ {
52
+ className,
53
+ variant,
54
+ icon,
55
+ size,
56
+ disabled = false,
57
+ loading = false,
58
+ asChild = false,
59
+ hideChild = false,
60
+ ...props
61
+ },
62
+ ref
63
+ ) => {
64
+ const Comp = asChild ? Slot : "button";
65
+ return (
66
+ <Comp
67
+ ref={ref}
68
+ {...props}
69
+ disabled={disabled || loading}
70
+ className={`${cn(
71
+ "ease-in-out duration-75 active:scale-95",
72
+ buttonVariants({ variant, size, className }),
73
+ "transition-transform will-change-transform cursor-pointer"
74
+ )} `}
75
+ >
76
+ <RiLoader3Line
77
+ className={`${loading ? "size-6 animate-spin " : "hidden"} ${
78
+ !hideChild && "mr-2"
79
+ } transition-transform `}
80
+ />
81
+ <span
82
+ className={cn(
83
+ (!icon || (hideChild && loading)) && "hidden",
84
+ props.children && "mr-2"
85
+ )}
86
+ >
87
+ {icon}
88
+ </span>
89
+ <>{hideChild ? !loading && props.children : props.children}</>
90
+ </Comp>
91
+ );
92
+ }
93
+ );
94
+ Button.displayName = "Button";
95
+
96
+ export { Button, buttonVariants };