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,109 @@
1
+ import { GalleryHorizontal } from 'lucide-react';
2
+ import { useRef } from 'react';
3
+ import { type ChangeEvent, useState } from 'react';
4
+
5
+ import { Button } from '@/components/ui/button';
6
+ import {
7
+ Carousel,
8
+ CarouselContent,
9
+ CarouselItem,
10
+ CarouselNext,
11
+ CarouselPrevious,
12
+ } from '@/components/ui/carousel';
13
+
14
+ import { cn } from '../lib/utils.js';
15
+ const ImagePicker = ({
16
+ onChange,
17
+ defaultValue,
18
+ disabled,
19
+ className,
20
+ }: {
21
+ onChange?: (e: FileList | null) => void;
22
+ defaultValue?: Blob;
23
+ disabled?: boolean;
24
+ className?: string;
25
+ }) => {
26
+ const getDefaultImage = () => {
27
+ try {
28
+ if (!defaultValue) return '';
29
+ return URL.createObjectURL(defaultValue);
30
+ } catch (error) {
31
+ return '';
32
+ }
33
+ };
34
+ const [selectedImage, setSelectedImage] = useState<string[]>(
35
+ getDefaultImage() ? [getDefaultImage()] : [],
36
+ );
37
+
38
+ const fileInputRef = useRef<HTMLInputElement | null>(null);
39
+ const handleImageChange = (event: ChangeEvent<HTMLInputElement>) => {
40
+ if (event.target.files?.[0]) {
41
+ setSelectedImage(Array.from(event.target.files).map((file) => URL.createObjectURL(file)));
42
+ const file = event.target.files;
43
+ onChange?.(file);
44
+ }
45
+ };
46
+ return (
47
+ <div>
48
+ <div className="flex items-start w-full aspect-video flex-col gap-2">
49
+ <div
50
+ onClick={() => fileInputRef.current?.click()}
51
+ className={cn(
52
+ 'border-dashed grid place-content-center min-w-full aspect-video border border-gray-300 rounded-md overflow-hidden',
53
+ className,
54
+ )}
55
+ >
56
+ {selectedImage.length !== 0 ? (
57
+ <Carousel>
58
+ <CarouselContent>
59
+ {selectedImage.map((image) => (
60
+ <CarouselItem key={image}>
61
+ <img
62
+ alt={image}
63
+ src={image}
64
+ className="w-full h-full overflow-hidden object-contain transition-transform duration-500 ease-in-out"
65
+ ></img>
66
+ </CarouselItem>
67
+ ))}
68
+ </CarouselContent>
69
+ {selectedImage.length > 1 && (
70
+ <>
71
+ <CarouselPrevious className="left-2" />
72
+ <CarouselNext className="right-2" />
73
+ </>
74
+ )}
75
+ </Carousel>
76
+ ) : (
77
+ <div className="flex">
78
+ <input
79
+ type="file"
80
+ ref={fileInputRef}
81
+ id="imageInput"
82
+ accept="image/*"
83
+ onChange={handleImageChange}
84
+ className="hidden"
85
+ multiple
86
+ />
87
+ <GalleryHorizontal className="text-gray-500 drop-shadow-lg " size={40} />
88
+ </div>
89
+ )}
90
+ </div>
91
+ <Button
92
+ type="button"
93
+ className="px-8 border-dotted"
94
+ disabled={disabled}
95
+ onClick={(e) => {
96
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
97
+ selectedImage.length === 0 ? fileInputRef.current?.click() : setSelectedImage([]);
98
+ onChange?.(null);
99
+ }}
100
+ variant={selectedImage.length > 0 ? 'destructive' : 'outline'}
101
+ >
102
+ {selectedImage.length === 0 ? 'Upload image' : 'Remove image'}
103
+ </Button>
104
+ </div>
105
+ </div>
106
+ );
107
+ };
108
+
109
+ export { ImagePicker };
@@ -0,0 +1,37 @@
1
+ import { Loader, Scroll } from 'lucide-react';
2
+ import type { ReactNode } from 'react';
3
+
4
+ import { cn } from '../lib/utils';
5
+
6
+ type NoContentProps = {
7
+ icon?: ReactNode;
8
+ label?: string;
9
+ className?: string;
10
+ loading?: boolean;
11
+ };
12
+ export const NoContent = (props: NoContentProps) => {
13
+ if (props.loading) {
14
+ return (
15
+ <div
16
+ className={cn(
17
+ 'h-full w-full flex flex-col gap-2 justify-center items-center',
18
+ props.className ?? '',
19
+ )}
20
+ >
21
+ <Loader className="animate-spin" />
22
+ <p className="text-sm text-muted-foreground">loading</p>
23
+ </div>
24
+ );
25
+ }
26
+ return (
27
+ <div
28
+ className={cn(
29
+ 'h-full w-full flex text-sm flex-col gap-2 justify-center items-center',
30
+ props.className ?? '',
31
+ )}
32
+ >
33
+ {props.icon ?? <Scroll />}
34
+ <p className=" text-muted-foreground">{props.label ?? 'No Content'}</p>
35
+ </div>
36
+ );
37
+ };
@@ -0,0 +1,24 @@
1
+ import { type AllHTMLAttributes, forwardRef } from 'react';
2
+
3
+ const PageContainer = forwardRef<HTMLButtonElement, AllHTMLAttributes<HTMLDivElement>>(
4
+ (
5
+ {
6
+ className,
7
+
8
+ ...props
9
+ },
10
+ ref,
11
+ ) => {
12
+ return (
13
+ <main
14
+ ref={ref}
15
+ {...props}
16
+ className={` px-4 py-4 gap-8 xs:px-8 md:px-16 lg:px-32 max-w-screen-2xl m-auto ${className} `}
17
+ >
18
+ <>{props.children}</>
19
+ </main>
20
+ );
21
+ },
22
+ );
23
+ PageContainer.displayName = 'PageContainer';
24
+ export { PageContainer };
@@ -0,0 +1,59 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import type { ReactNode } from 'react';
3
+
4
+ import { cn } from '../lib/utils';
5
+ import { Separator } from '../ui/separator';
6
+ const pageSectionVariant = cva(
7
+ 'flex flex-col space-y-4 rounded-lg bg-background/70 p-6 md:px-6 px-2 w-full h-full ',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: '',
12
+ outline: 'border',
13
+ transparent: 'bg-transparent md:px-0 px-0',
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: 'default',
18
+ },
19
+ },
20
+ );
21
+ type PageSectionProps = {
22
+ icon?: ReactNode;
23
+ title: ReactNode;
24
+ description?: ReactNode;
25
+ className?: string;
26
+ children: ReactNode;
27
+ separator?: boolean;
28
+ suffixIcon?: ReactNode;
29
+ } & VariantProps<typeof pageSectionVariant>;
30
+
31
+ const PageSection = ({
32
+ icon,
33
+ title,
34
+ description,
35
+ className,
36
+ children,
37
+ separator,
38
+ suffixIcon,
39
+ ...props
40
+ }: PageSectionProps) => {
41
+ return (
42
+ <section className={cn(pageSectionVariant({ variant: props.variant }), className)} {...props}>
43
+ <div className="flex gap-1 flex-col">
44
+ <div className="flex items-center gap-2">
45
+ {icon ? <div className="h-6 w-6 text-muted-foreground">{icon}</div> : null}
46
+
47
+ <span className="text-lg font-semibold">{title}</span>
48
+ <div className="ml-auto">{suffixIcon}</div>
49
+ </div>
50
+ <p className="text-sm text-muted-foreground">{description}</p>
51
+ {separator ? <Separator className="mt-1" /> : null}
52
+ </div>
53
+
54
+ {children}
55
+ </section>
56
+ );
57
+ };
58
+
59
+ export { PageSection };
@@ -0,0 +1,29 @@
1
+ import type { ClassNameValue } from 'tailwind-merge';
2
+
3
+ import { Popover, PopoverContent, PopoverTrigger } from '../../components/ui/popover';
4
+ import { cn } from '../lib/utils';
5
+
6
+ interface SimplePopoverProps {
7
+ children: React.ReactNode;
8
+ trigger: React.ReactNode;
9
+ side?: 'top' | 'right' | 'bottom' | 'left';
10
+ sideOffset?: number;
11
+ open?: boolean;
12
+ onOpenChange?: (open: boolean) => void;
13
+ className?: ClassNameValue;
14
+ }
15
+
16
+ export const SimplePopover = (props: SimplePopoverProps) => {
17
+ return (
18
+ <Popover open={props.open} onOpenChange={props.onOpenChange}>
19
+ <PopoverTrigger asChild>{props.trigger}</PopoverTrigger>
20
+ <PopoverContent
21
+ side={props.side}
22
+ sideOffset={props.sideOffset}
23
+ className={cn(props.className)}
24
+ >
25
+ {props.children}
26
+ </PopoverContent>
27
+ </Popover>
28
+ );
29
+ };
@@ -0,0 +1,20 @@
1
+ import type React from 'react';
2
+
3
+ export type SwitchCases<T extends string> = {
4
+ [key in T]?: React.ReactNode; // Mapping of cases with the type T
5
+ };
6
+
7
+ export type SwitchProps<T extends string> = {
8
+ value: T; // The value to match against the cases
9
+ cases: SwitchCases<T>; // Cases object with keys as possible values of type T
10
+ default?: React.ReactNode; // Default component if no case matches
11
+ };
12
+
13
+ function SwitchComponent<T extends string>(props: SwitchProps<T>) {
14
+ const { value, cases, default: defaultCase } = props;
15
+
16
+ // Render the component matching the value, or the default if none matches
17
+ return <>{cases[value] ?? defaultCase ?? <div></div>}</>;
18
+ }
19
+
20
+ export { SwitchComponent };
@@ -0,0 +1,74 @@
1
+ import { createContext, useContext, useEffect, useState } from 'react';
2
+ import { Toaster } from 'sonner';
3
+ type Theme = 'dark' | 'light' | 'system';
4
+
5
+ type ThemeProviderProps = {
6
+ children: React.ReactNode;
7
+ defaultTheme?: Theme;
8
+ storageKey?: string;
9
+ };
10
+
11
+ type ThemeProviderState = {
12
+ theme: Theme;
13
+ setTheme: (theme: Theme) => void;
14
+ };
15
+
16
+ const initialState: ThemeProviderState = {
17
+ theme: 'system',
18
+ setTheme: () => null,
19
+ };
20
+
21
+ const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
22
+
23
+ export const ThemeProvider = ({
24
+ children,
25
+ defaultTheme = 'dark',
26
+ storageKey = 'vite-ui-theme',
27
+ ...props
28
+ }: ThemeProviderProps) => {
29
+ const [theme, setTheme] = useState<Theme>(
30
+ () =>
31
+ (typeof window !== 'undefined' && (localStorage.getItem(storageKey) as Theme)) ||
32
+ defaultTheme,
33
+ );
34
+
35
+ useEffect(() => {
36
+ const root = window.document.documentElement;
37
+
38
+ root.classList.remove('light', 'dark');
39
+
40
+ if (theme === 'system') {
41
+ const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
42
+ ? 'dark'
43
+ : 'light';
44
+
45
+ root.classList.add(systemTheme);
46
+ return;
47
+ }
48
+
49
+ root.classList.add(theme);
50
+ }, [theme]);
51
+
52
+ const value = {
53
+ theme,
54
+ setTheme: (theme: Theme) => {
55
+ localStorage.setItem(storageKey, theme);
56
+ setTheme(theme);
57
+ },
58
+ };
59
+
60
+ return (
61
+ <ThemeProviderContext.Provider {...props} value={value}>
62
+ <Toaster richColors />
63
+ {children}
64
+ </ThemeProviderContext.Provider>
65
+ );
66
+ };
67
+
68
+ export const useTheme = () => {
69
+ const context = useContext(ThemeProviderContext);
70
+
71
+ if (context === undefined) throw new Error('useTheme must be used within a ThemeProvider');
72
+
73
+ return context;
74
+ };
@@ -0,0 +1,111 @@
1
+ import type React from 'react';
2
+
3
+ import { cn } from '../lib/utils';
4
+
5
+ interface TypographyProps {
6
+ children: React.ReactNode; // Text content to display
7
+ className?: string; // Additional class names for styling
8
+ }
9
+
10
+ const H1: React.FC<TypographyProps> = ({ children, className }) => (
11
+ <h1 className={cn('text-4xl font-bold', className)}>{children}</h1>
12
+ );
13
+
14
+ const H2: React.FC<TypographyProps> = ({ children, className }) => (
15
+ <h2 className={cn('text-3xl font-semibold', className)}>{children}</h2>
16
+ );
17
+
18
+ const H3: React.FC<TypographyProps> = ({ children, className }) => (
19
+ <h3 className={cn('text-2xl font-medium', className)}>{children}</h3>
20
+ );
21
+
22
+ const H4: React.FC<TypographyProps> = ({ children, className }) => (
23
+ <h4 className={cn('text-xl font-semibold', className)}>{children}</h4>
24
+ );
25
+
26
+ const H5: React.FC<TypographyProps> = ({ children, className }) => (
27
+ <h5 className={cn('text-lg font-medium', className)}>{children}</h5>
28
+ );
29
+
30
+ const H6: React.FC<TypographyProps> = ({ children, className }) => (
31
+ <h6 className={cn('font-semibold', className)}>{children}</h6>
32
+ );
33
+
34
+ const Default: React.FC<TypographyProps> = ({ children, className }) => (
35
+ <p className={cn(className)}>{children}</p>
36
+ );
37
+
38
+ const Secondary: React.FC<TypographyProps> = ({ children, className }) => (
39
+ <span className={cn('text-muted-foreground', className)}>{children}</span>
40
+ );
41
+
42
+ const Primary: React.FC<TypographyProps> = ({ children, className }) => (
43
+ <span className={cn('text-primary', className)}>{children}</span>
44
+ );
45
+
46
+ const Error: React.FC<TypographyProps> = ({ children, className }) => (
47
+ <span className={cn('text-destructive text-sm', className)}>{children}</span>
48
+ );
49
+
50
+ const Warning: React.FC<TypographyProps> = ({ children, className }) => (
51
+ <span className={cn('text-yellow-500 text-sm', className)}>{children}</span>
52
+ );
53
+
54
+ const Success: React.FC<TypographyProps> = ({ children, className }) => (
55
+ <span className={cn('text-green-500 text-sm', className)}>{children}</span>
56
+ );
57
+
58
+ const Hint: React.FC<TypographyProps> = ({ children, className }) => (
59
+ <span className={cn('text-muted-foreground text-xs', className)}>{children}</span>
60
+ );
61
+
62
+ const Grayed: React.FC<TypographyProps> = ({ children, className }) => (
63
+ <p className={cn('text-gray-500', className)}>{children}</p>
64
+ );
65
+
66
+ const Muted: React.FC<TypographyProps> = ({ children, className }) => (
67
+ <p className={cn('text-muted', className)}>{children}</p>
68
+ );
69
+
70
+ const Key: React.FC<TypographyProps> = ({ children, className }) => (
71
+ <span className={cn('font-thin text-xs', className)}>{children}</span>
72
+ );
73
+
74
+ const Value: React.FC<TypographyProps> = ({ children, className }) => (
75
+ <span className={cn('text-lg', className)}>{children}</span>
76
+ );
77
+
78
+ const List: React.FC<TypographyProps & { label?: string }> = ({ children, className, label }) => (
79
+ <ul className={cn(className)}>
80
+ {label ? <span className="font-semibold">{label}</span> : null}
81
+ {children}
82
+ </ul>
83
+ );
84
+ const Item: React.FC<TypographyProps> = ({ children, className }) => (
85
+ <li className={cn('ml-6 text-sm list-disc', className)}>{children}</li>
86
+ );
87
+
88
+ // Combine all typography components into a single object
89
+ const Tp = {
90
+ h1: H1,
91
+ h2: H2,
92
+ h3: H3,
93
+ h4: H4,
94
+ h5: H5,
95
+ h6: H6,
96
+ default: Default,
97
+ secondary: Secondary,
98
+ error: Error,
99
+ warning: Warning,
100
+ success: Success,
101
+ hint: Hint,
102
+ grayed: Grayed,
103
+ muted: Muted,
104
+ key: Key,
105
+ value: Value,
106
+ list: List,
107
+ item: Item,
108
+ primary: Primary,
109
+ };
110
+
111
+ export { Tp };