startx 0.1.5 → 0.1.6
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.
- package/.editorconfig +20 -20
- package/.github/workflows/publish.yml +48 -0
- package/LICENSE +21 -21
- package/configs/eslint-config/plugins.d.ts +1 -1
- package/configs/eslint-config/src/rules/no-argument-spread.ts +96 -96
- package/configs/eslint-config/src/rules/no-internal-package-import.ts +40 -40
- package/configs/eslint-config/src/rules/no-interpolation-in-regular-string.ts +32 -32
- package/configs/eslint-config/src/rules/no-skipped-tests.ts +61 -61
- package/configs/eslint-config/src/rules/no-top-level-relative-imports-in-backend-module.ts +27 -27
- package/configs/eslint-config/src/rules/no-type-unsafe-event-emitter.ts +33 -33
- package/configs/eslint-config/src/rules/no-uncaught-json-parse.test.ts +21 -21
- package/configs/eslint-config/src/rules/no-untyped-config-class-field.ts +26 -26
- package/configs/eslint-config/src/rules/no-unused-param-catch-clause.ts +33 -33
- package/configs/eslint-config/src/rules/no-useless-catch-throw.test.ts +34 -34
- package/configs/eslint-config/src/rules/no-useless-catch-throw.ts +47 -47
- package/configs/eslint-config/src/utils/json.ts +21 -21
- package/package.json +34 -35
- package/packages/@repo/constants/src/api.ts +1 -1
- package/packages/@repo/constants/src/time.ts +23 -23
- package/packages/@repo/db/src/schema/index.ts +1 -1
- package/packages/@repo/lib/src/error-handlers-module/index.ts +11 -11
- package/packages/cli/dist/index.mjs +38 -165
- package/packages/cli/tsdown.config.ts +1 -0
- package/packages/ui/src/components/custom/grid-component.tsx +23 -23
- package/packages/ui/src/components/custom/hover-tool.tsx +38 -38
- package/packages/ui/src/components/custom/image-picker.tsx +109 -109
- package/packages/ui/src/components/custom/no-content.tsx +37 -37
- package/packages/ui/src/components/custom/page-container.tsx +24 -24
- package/packages/ui/src/components/custom/simple-popover.tsx +29 -29
- package/packages/ui/src/components/custom/switch-component.tsx +20 -20
- package/packages/ui/src/components/custom/theme-provider.tsx +74 -74
- package/packages/ui/src/components/hooks/event/use-click.tsx +39 -39
- package/packages/ui/src/components/hooks/time/useDebounce.tsx +21 -21
- package/packages/ui/src/components/hooks/time/useInterval.tsx +35 -35
- package/packages/ui/src/components/hooks/time/useTimeout.tsx +19 -19
- package/packages/ui/src/components/hooks/time/useTimer.tsx +51 -51
- package/packages/ui/src/components/hooks/use-media-query.tsx +19 -19
- package/packages/ui/src/components/hooks/use-persistent-storage.tsx +52 -52
- package/packages/ui/src/components/hooks/use-window-dimension.tsx +30 -30
- package/packages/ui/src/components/sonner.tsx +1 -1
- package/packages/ui/src/components/ui/button.tsx +96 -96
- package/packages/ui/src/components/ui/dropdown-menu.tsx +226 -226
- package/packages/ui/src/components/ui/label.tsx +24 -24
- package/packages/ui/src/components/ui/popover.tsx +42 -42
- package/packages/ui/src/components/ui/select.tsx +170 -170
- package/packages/ui/src/components/ui/separator.tsx +28 -28
- package/packages/ui/src/components/ui/sheet.tsx +130 -130
- package/packages/ui/src/components/ui/skeleton.tsx +13 -13
- package/packages/ui/src/components/ui/spinner.tsx +16 -16
- package/packages/ui/src/components/ui/switch.tsx +28 -28
- package/packages/ui/src/components/ui/tabs.tsx +54 -54
- package/packages/ui/src/components/ui/tooltip.tsx +30 -30
- package/packages/ui/src/components/util/n-formattor.ts +22 -22
- package/packages/ui/src/components/util/storage.ts +37 -37
- package/packages/ui/src/globals.css +87 -87
- package/configs/vitest-config/dist/base.mjs +0 -1
- package/configs/vitest-config/dist/frontend.mjs +0 -1
- package/configs/vitest-config/dist/node.mjs +0 -1
- package/packages/@repo/redis/dist/index.d.mts +0 -3
- package/packages/@repo/redis/dist/index.mjs +0 -5
- package/packages/@repo/redis/dist/lib/redis-client.d.mts +0 -7
- package/packages/@repo/redis/dist/lib/redis-client.mjs +0 -25
- package/packages/@repo/redis/dist/lib/redis-client.mjs.map +0 -1
- package/packages/@repo/redis/dist/lib/redis-module.d.mts +0 -5
- package/packages/@repo/redis/dist/lib/redis-module.mjs +0 -6
- package/packages/@repo/redis/dist/lib/redis-module.mjs.map +0 -1
- /package/{apps/core-server/.env.example → .env.example} +0 -0
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { cn } from '../lib/utils';
|
|
2
|
-
|
|
3
|
-
export type GridProps = {
|
|
4
|
-
children: React.ReactNode;
|
|
5
|
-
grow?: boolean;
|
|
6
|
-
className?: string;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const Grid = (props: GridProps) => {
|
|
10
|
-
return (
|
|
11
|
-
<div
|
|
12
|
-
className={cn(
|
|
13
|
-
'grid sm:grid-cols-12 gap-2 grid-cols-1',
|
|
14
|
-
props.grow ? 'min-h-[calc(100vh-60px)] py-2' : '',
|
|
15
|
-
props.className,
|
|
16
|
-
)}
|
|
17
|
-
>
|
|
18
|
-
{props.children}
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export { Grid };
|
|
1
|
+
import { cn } from '../lib/utils';
|
|
2
|
+
|
|
3
|
+
export type GridProps = {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
grow?: boolean;
|
|
6
|
+
className?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Grid = (props: GridProps) => {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className={cn(
|
|
13
|
+
'grid sm:grid-cols-12 gap-2 grid-cols-1',
|
|
14
|
+
props.grow ? 'min-h-[calc(100vh-60px)] py-2' : '',
|
|
15
|
+
props.className,
|
|
16
|
+
)}
|
|
17
|
+
>
|
|
18
|
+
{props.children}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { Grid };
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import type { ClassNameValue } from "tailwind-merge";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../lib/utils";
|
|
5
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
|
|
6
|
-
|
|
7
|
-
const HoverTool = ({
|
|
8
|
-
children,
|
|
9
|
-
side,
|
|
10
|
-
hideHover,
|
|
11
|
-
content,
|
|
12
|
-
className,
|
|
13
|
-
skipDelay,
|
|
14
|
-
delay,
|
|
15
|
-
}: {
|
|
16
|
-
delay?: number;
|
|
17
|
-
hideHover?: boolean;
|
|
18
|
-
side?: "top" | "bottom" | "left" | "right" | undefined;
|
|
19
|
-
skipDelay?: number;
|
|
20
|
-
children: ReactNode;
|
|
21
|
-
content: ReactNode;
|
|
22
|
-
className?: ClassNameValue;
|
|
23
|
-
}) => {
|
|
24
|
-
return (
|
|
25
|
-
<TooltipProvider delayDuration={delay} skipDelayDuration={skipDelay}>
|
|
26
|
-
<Tooltip>
|
|
27
|
-
<TooltipTrigger className={cn(className)}>{children}</TooltipTrigger>
|
|
28
|
-
{!hideHover && (
|
|
29
|
-
<TooltipContent className="z-50" style={{ zIndex: 999 }} side={side}>
|
|
30
|
-
{content}
|
|
31
|
-
</TooltipContent>
|
|
32
|
-
)}
|
|
33
|
-
</Tooltip>
|
|
34
|
-
</TooltipProvider>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export { HoverTool };
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ClassNameValue } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
|
|
6
|
+
|
|
7
|
+
const HoverTool = ({
|
|
8
|
+
children,
|
|
9
|
+
side,
|
|
10
|
+
hideHover,
|
|
11
|
+
content,
|
|
12
|
+
className,
|
|
13
|
+
skipDelay,
|
|
14
|
+
delay,
|
|
15
|
+
}: {
|
|
16
|
+
delay?: number;
|
|
17
|
+
hideHover?: boolean;
|
|
18
|
+
side?: "top" | "bottom" | "left" | "right" | undefined;
|
|
19
|
+
skipDelay?: number;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
content: ReactNode;
|
|
22
|
+
className?: ClassNameValue;
|
|
23
|
+
}) => {
|
|
24
|
+
return (
|
|
25
|
+
<TooltipProvider delayDuration={delay} skipDelayDuration={skipDelay}>
|
|
26
|
+
<Tooltip>
|
|
27
|
+
<TooltipTrigger className={cn(className)}>{children}</TooltipTrigger>
|
|
28
|
+
{!hideHover && (
|
|
29
|
+
<TooltipContent className="z-50" style={{ zIndex: 999 }} side={side}>
|
|
30
|
+
{content}
|
|
31
|
+
</TooltipContent>
|
|
32
|
+
)}
|
|
33
|
+
</Tooltip>
|
|
34
|
+
</TooltipProvider>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { HoverTool };
|
|
@@ -1,109 +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 };
|
|
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 };
|
|
@@ -1,37 +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
|
-
};
|
|
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
|
+
};
|
|
@@ -1,24 +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 };
|
|
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 };
|
|
@@ -1,29 +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
|
-
};
|
|
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
|
+
};
|
|
@@ -1,20 +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 };
|
|
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 };
|