startx 1.0.2 → 1.0.4
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/.dockerignore +4 -0
- package/apps/cli/src/commands/index.ts +1 -1
- package/apps/cli/src/commands/{common → test}/test.ts +4 -2
- package/apps/cli/tsconfig.json +0 -1
- package/apps/core-server/Dockerfile +5 -4
- package/apps/core-server/package.json +1 -1
- package/apps/core-server/tsconfig.json +1 -1
- package/apps/queue-worker/package.json +1 -1
- package/apps/queue-worker/tsconfig.json +1 -1
- package/apps/startx-cli/dist/index.mjs +68 -53
- package/apps/startx-cli/src/commands/package.ts +453 -0
- package/apps/startx-cli/src/configs/scripts.ts +18 -2
- package/apps/startx-cli/src/index.ts +2 -4
- package/apps/startx-cli/src/types.ts +2 -4
- package/apps/startx-cli/src/utils/inquirer.ts +8 -1
- package/apps/web-client/.dockerignore +4 -0
- package/apps/web-client/app/app.css +1 -0
- package/apps/web-client/app/components.json +23 -0
- package/apps/web-client/app/config/auth/auth-state.ts +59 -0
- package/apps/web-client/app/config/axios-client.ts +87 -0
- package/apps/web-client/app/config/env.ts +5 -0
- package/apps/web-client/app/entry.client.tsx +7 -0
- package/apps/web-client/app/eslint.config.ts +4 -0
- package/apps/web-client/app/root.tsx +77 -0
- package/apps/web-client/app/routes/home.tsx +12 -0
- package/apps/web-client/app/routes.ts +3 -0
- package/apps/web-client/eslint.config.ts +4 -0
- package/apps/web-client/package.json +55 -0
- package/apps/web-client/react-router.config.ts +7 -0
- package/apps/web-client/tsconfig.json +22 -0
- package/apps/web-client/vite-env.d.ts +8 -0
- package/apps/web-client/vite.config.ts +30 -0
- package/biome.json +5 -0
- package/configs/eslint-config/eslint.config.ts +1 -0
- package/configs/eslint-config/src/configs/base.ts +2 -1
- package/configs/eslint-config/src/configs/frontend.ts +1 -1
- package/configs/eslint-config/tsconfig.json +1 -1
- package/configs/typescript-config/tsconfig.frontend.json +1 -1
- package/configs/vitest-config/tsconfig.json +1 -1
- package/package.json +1 -1
- package/packages/@db/drizzle/tsconfig.json +1 -1
- package/packages/@db/sqlite/tsconfig.json +1 -1
- package/packages/@repo/env/package.json +1 -2
- package/packages/@repo/env/src/utils.ts +17 -11
- package/packages/@repo/env/tsconfig.json +1 -1
- package/packages/@repo/lib/package.json +3 -1
- package/packages/@repo/lib/src/session-module/i-session.ts +108 -0
- package/packages/@repo/lib/src/session-module/index.ts +8 -111
- package/packages/@repo/lib/src/session-module/redis-session.ts +44 -0
- package/packages/@repo/lib/tsconfig.json +0 -1
- package/packages/@repo/logger/package.json +0 -1
- package/packages/@repo/logger/tsconfig.json +1 -1
- package/packages/@repo/mail/tsconfig.json +1 -1
- package/packages/@repo/redis/tsconfig.json +1 -1
- package/packages/aix/package.json +2 -0
- package/packages/aix/src/providers/ai-interface.ts +4 -4
- package/packages/aix/src/providers/bedrock/bedrock.ts +261 -0
- package/packages/aix/src/providers/default-models.ts +65 -0
- package/packages/aix/src/providers/openai/openai.ts +2 -2
- package/packages/aix/src/providers/providers.ts +11 -0
- package/packages/aix/src/providers/types.ts +1 -1
- package/packages/{constants → common}/package.json +4 -2
- package/packages/{constants/src/index.ts → common/src/constants.ts} +0 -5
- package/packages/common/src/types/users.ts +10 -0
- package/packages/{constants → common}/tsconfig.json +0 -3
- package/packages/ui/components.json +15 -8
- package/packages/ui/package.json +24 -36
- package/packages/ui/src/api/axios/i-client.ts +40 -0
- package/packages/ui/src/api/index.ts +6 -0
- package/packages/ui/src/api/query-provider.tsx +34 -0
- package/packages/ui/src/api/use-api/api-builder.ts +139 -0
- package/packages/ui/src/api/use-api/api-helpers.ts +165 -0
- package/packages/ui/src/api/use-api/api-types.ts +138 -0
- package/packages/ui/src/api/use-api/query-factory.ts +66 -0
- package/packages/ui/src/api/use-api/react-query/types.ts +64 -0
- package/packages/ui/src/api/use-api/react-query/use-api-client.ts +56 -0
- package/packages/ui/src/api/use-api/react-query/use-api.ts +297 -0
- package/packages/ui/src/components/custom/form-wrapper.tsx +113 -160
- package/packages/ui/src/components/custom/grid-component.tsx +4 -4
- package/packages/ui/src/components/custom/hover-tool.tsx +1 -1
- package/packages/ui/src/components/custom/image-picker.tsx +18 -20
- package/packages/ui/src/components/custom/no-content.tsx +6 -16
- package/packages/ui/src/components/custom/page-section.tsx +14 -17
- package/packages/ui/src/components/custom/simple-popover.tsx +5 -9
- package/packages/ui/src/components/custom/theme-provider.tsx +117 -42
- package/packages/ui/src/components/custom/typography.tsx +20 -22
- package/packages/ui/src/components/extensions/timeline.tsx +100 -0
- package/packages/ui/src/components/ui/alert-dialog.tsx +46 -108
- package/packages/ui/src/components/ui/avatar.tsx +79 -42
- package/packages/ui/src/components/ui/badge.tsx +29 -34
- package/packages/ui/src/components/ui/breadcrumb.tsx +65 -81
- package/packages/ui/src/components/ui/button.tsx +80 -80
- package/packages/ui/src/components/ui/card.tsx +48 -69
- package/packages/ui/src/components/ui/carousel.tsx +184 -211
- package/packages/ui/src/components/ui/checkbox.tsx +21 -24
- package/packages/ui/src/components/ui/command.tsx +121 -102
- package/packages/ui/src/components/ui/dialog.tsx +45 -32
- package/packages/ui/src/components/ui/dropdown-menu.tsx +45 -33
- package/packages/ui/src/components/ui/field.tsx +218 -0
- package/packages/ui/src/components/ui/form.tsx +63 -76
- package/packages/ui/src/components/ui/input-group.tsx +137 -0
- package/packages/ui/src/components/ui/input-otp.tsx +60 -50
- package/packages/ui/src/components/ui/input.tsx +16 -15
- package/packages/ui/src/components/ui/label.tsx +14 -17
- package/packages/ui/src/components/ui/multiple-select.tsx +22 -33
- package/packages/ui/src/components/ui/popover.tsx +20 -8
- package/packages/ui/src/components/ui/select.tsx +33 -34
- package/packages/ui/src/components/ui/separator.tsx +8 -8
- package/packages/ui/src/components/ui/sheet.tsx +32 -59
- package/packages/ui/src/components/ui/sidebar.tsx +654 -0
- package/packages/ui/src/components/ui/skeleton.tsx +2 -8
- package/packages/ui/src/components/ui/sonner.tsx +39 -0
- package/packages/ui/src/components/ui/spinner.tsx +6 -13
- package/packages/ui/src/components/ui/switch.tsx +15 -10
- package/packages/ui/src/components/ui/table.tsx +48 -89
- package/packages/ui/src/components/ui/tabs.tsx +37 -15
- package/packages/ui/src/components/ui/textarea.tsx +13 -13
- package/packages/ui/src/components/ui/tooltip.tsx +37 -23
- package/packages/ui/src/{components/hooks → hooks}/event/use-click.tsx +6 -10
- package/packages/ui/src/hooks/time/use-timer.tsx +51 -0
- package/packages/ui/src/hooks/use-media-query.tsx +19 -0
- package/packages/ui/src/hooks/use-mobile.tsx +17 -0
- package/packages/ui/src/{components/hooks → hooks}/use-update-effect.tsx +2 -2
- package/packages/ui/src/lib/utils.ts +113 -0
- package/packages/ui/src/styles/globals.css +314 -0
- package/packages/ui/src/styles/tailwind.css +89 -0
- package/packages/ui/tsconfig.json +7 -9
- package/pnpm-workspace.yaml +74 -64
- package/packages/ui/postcss.config.mjs +0 -9
- package/packages/ui/src/components/extensions/carousel.tsx +0 -392
- package/packages/ui/src/components/hooks/time/useTimer.tsx +0 -51
- package/packages/ui/src/components/hooks/use-media-query.tsx +0 -19
- package/packages/ui/src/components/lib/utils.ts +0 -242
- package/packages/ui/src/components/ui/timeline.tsx +0 -118
- package/packages/ui/src/components/util/n-formattor.ts +0 -22
- package/packages/ui/src/components/util/storage.ts +0 -37
- package/packages/ui/src/globals.css +0 -87
- package/packages/ui/tailwind.config.ts +0 -94
- /package/packages/{constants → common}/eslint.config.ts +0 -0
- /package/packages/{constants → common}/src/api.ts +0 -0
- /package/packages/{constants → common}/src/time.ts +0 -0
- /package/packages/{constants → common}/vitest.config.ts +0 -0
- /package/packages/ui/src/{components/hooks/time/useDebounce.tsx → hooks/time/use-debounce.tsx} +0 -0
- /package/packages/ui/src/{components/hooks/time/useInterval.tsx → hooks/time/use-interval.tsx} +0 -0
- /package/packages/ui/src/{components/hooks/time/useTimeout.tsx → hooks/time/use-timeout.tsx} +0 -0
- /package/packages/ui/src/{components/hooks → hooks}/use-persistent-storage.tsx +0 -0
- /package/packages/ui/src/{components/hooks → hooks}/use-window-dimension.tsx +0 -0
- /package/packages/ui/src/{components/sonner.tsx → sonner.ts} +0 -0
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Loader2Icon } from "lucide-react";
|
|
2
2
|
|
|
3
|
-
import { cn } from
|
|
3
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
'animate-spin rounded-full border-2 border-current border-t-transparent h-4 w-4',
|
|
9
|
-
className,
|
|
10
|
-
);
|
|
5
|
+
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
6
|
+
return <Loader2Icon role="status" aria-label="Loading" className={cn("size-4 animate-spin", className)} {...props} />;
|
|
7
|
+
}
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
Spinner.displayName = 'Spinner';
|
|
9
|
+
export { Spinner };
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { Switch as SwitchPrimitive } from "radix-ui";
|
|
4
|
+
import * as React from "react";
|
|
5
5
|
|
|
6
|
-
import { cn } from
|
|
6
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
7
7
|
|
|
8
|
-
function Switch({
|
|
8
|
+
function Switch({
|
|
9
|
+
className,
|
|
10
|
+
size = "default",
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof SwitchPrimitive.Root> & {
|
|
13
|
+
size?: "sm" | "default";
|
|
14
|
+
}) {
|
|
9
15
|
return (
|
|
10
16
|
<SwitchPrimitive.Root
|
|
11
17
|
data-slot="switch"
|
|
18
|
+
data-size={size}
|
|
12
19
|
className={cn(
|
|
13
|
-
|
|
14
|
-
className
|
|
20
|
+
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
21
|
+
className
|
|
15
22
|
)}
|
|
16
23
|
{...props}
|
|
17
24
|
>
|
|
18
25
|
<SwitchPrimitive.Thumb
|
|
19
26
|
data-slot="switch-thumb"
|
|
20
|
-
className=
|
|
21
|
-
'bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0',
|
|
22
|
-
)}
|
|
27
|
+
className="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
|
|
23
28
|
/>
|
|
24
29
|
</SwitchPrimitive.Root>
|
|
25
30
|
);
|
|
@@ -1,116 +1,75 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import * as React from "react";
|
|
4
4
|
|
|
5
|
-
import { cn } from "
|
|
5
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
6
6
|
|
|
7
7
|
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<table
|
|
14
|
-
data-slot="table"
|
|
15
|
-
className={cn("w-full caption-bottom text-sm", className)}
|
|
16
|
-
{...props}
|
|
17
|
-
/>
|
|
18
|
-
</div>
|
|
19
|
-
);
|
|
8
|
+
return (
|
|
9
|
+
<div data-slot="table-container" className="relative w-full overflow-x-auto">
|
|
10
|
+
<table data-slot="table" className={cn("w-full caption-bottom text-sm", className)} {...props} />
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
20
13
|
}
|
|
21
14
|
|
|
22
15
|
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|
23
|
-
|
|
24
|
-
<thead
|
|
25
|
-
data-slot="table-header"
|
|
26
|
-
className={cn("[&_tr]:border-b", className)}
|
|
27
|
-
{...props}
|
|
28
|
-
/>
|
|
29
|
-
);
|
|
16
|
+
return <thead data-slot="table-header" className={cn("[&_tr]:border-b", className)} {...props} />;
|
|
30
17
|
}
|
|
31
18
|
|
|
32
19
|
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|
33
|
-
|
|
34
|
-
<tbody
|
|
35
|
-
data-slot="table-body"
|
|
36
|
-
className={cn("[&_tr:last-child]:border-0", className)}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
20
|
+
return <tbody data-slot="table-body" className={cn("[&_tr:last-child]:border-0", className)} {...props} />;
|
|
40
21
|
}
|
|
41
22
|
|
|
42
23
|
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{...props}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
24
|
+
return (
|
|
25
|
+
<tfoot
|
|
26
|
+
data-slot="table-footer"
|
|
27
|
+
className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
53
31
|
}
|
|
54
32
|
|
|
55
33
|
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
34
|
+
return (
|
|
35
|
+
<tr
|
|
36
|
+
data-slot="table-row"
|
|
37
|
+
className={cn(
|
|
38
|
+
"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
66
44
|
}
|
|
67
45
|
|
|
68
46
|
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
47
|
+
return (
|
|
48
|
+
<th
|
|
49
|
+
data-slot="table-head"
|
|
50
|
+
className={cn(
|
|
51
|
+
"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
|
|
52
|
+
className
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
79
57
|
}
|
|
80
58
|
|
|
81
59
|
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
{...props}
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
60
|
+
return (
|
|
61
|
+
<td
|
|
62
|
+
data-slot="table-cell"
|
|
63
|
+
className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className)}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
92
67
|
}
|
|
93
68
|
|
|
94
|
-
function TableCaption({
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return (
|
|
99
|
-
<caption
|
|
100
|
-
data-slot="table-caption"
|
|
101
|
-
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
|
102
|
-
{...props}
|
|
103
|
-
/>
|
|
104
|
-
);
|
|
69
|
+
function TableCaption({ className, ...props }: React.ComponentProps<"caption">) {
|
|
70
|
+
return (
|
|
71
|
+
<caption data-slot="table-caption" className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />
|
|
72
|
+
);
|
|
105
73
|
}
|
|
106
74
|
|
|
107
|
-
export {
|
|
108
|
-
Table,
|
|
109
|
-
TableHeader,
|
|
110
|
-
TableBody,
|
|
111
|
-
TableFooter,
|
|
112
|
-
TableHead,
|
|
113
|
-
TableRow,
|
|
114
|
-
TableCell,
|
|
115
|
-
TableCaption,
|
|
116
|
-
};
|
|
75
|
+
export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
|
|
@@ -1,28 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { Tabs as TabsPrimitive } from "radix-ui";
|
|
5
|
+
import * as React from "react";
|
|
5
6
|
|
|
6
|
-
import { cn } from
|
|
7
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
7
8
|
|
|
8
|
-
function Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
9
|
+
function Tabs({ className, orientation = "horizontal", ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
9
10
|
return (
|
|
10
11
|
<TabsPrimitive.Root
|
|
11
12
|
data-slot="tabs"
|
|
12
|
-
|
|
13
|
+
data-orientation={orientation}
|
|
14
|
+
className={cn("group/tabs flex gap-2 data-horizontal:flex-col", className)}
|
|
13
15
|
{...props}
|
|
14
16
|
/>
|
|
15
17
|
);
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
const tabsListVariants = cva(
|
|
21
|
+
"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
|
|
22
|
+
{
|
|
23
|
+
variants: {
|
|
24
|
+
variant: {
|
|
25
|
+
default: "bg-muted",
|
|
26
|
+
line: "gap-1 bg-transparent",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: "default",
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
function TabsList({
|
|
36
|
+
className,
|
|
37
|
+
variant = "default",
|
|
38
|
+
...props
|
|
39
|
+
}: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {
|
|
19
40
|
return (
|
|
20
41
|
<TabsPrimitive.List
|
|
21
42
|
data-slot="tabs-list"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
43
|
+
data-variant={variant}
|
|
44
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
26
45
|
{...props}
|
|
27
46
|
/>
|
|
28
47
|
);
|
|
@@ -33,8 +52,11 @@ function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPr
|
|
|
33
52
|
<TabsPrimitive.Trigger
|
|
34
53
|
data-slot="tabs-trigger"
|
|
35
54
|
className={cn(
|
|
36
|
-
"
|
|
37
|
-
|
|
55
|
+
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
56
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
|
|
57
|
+
"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
|
|
58
|
+
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
|
|
59
|
+
className
|
|
38
60
|
)}
|
|
39
61
|
{...props}
|
|
40
62
|
/>
|
|
@@ -45,10 +67,10 @@ function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPr
|
|
|
45
67
|
return (
|
|
46
68
|
<TabsPrimitive.Content
|
|
47
69
|
data-slot="tabs-content"
|
|
48
|
-
className={cn(
|
|
70
|
+
className={cn("flex-1 text-sm outline-none", className)}
|
|
49
71
|
{...props}
|
|
50
72
|
/>
|
|
51
73
|
);
|
|
52
74
|
}
|
|
53
75
|
|
|
54
|
-
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
76
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
2
4
|
|
|
3
|
-
import { cn } from "../lib/utils";
|
|
4
|
-
export type TextAreaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
5
5
|
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
return (
|
|
7
|
+
<textarea
|
|
8
|
+
data-slot="textarea"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export { Textarea };
|
|
@@ -1,30 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import * as React from
|
|
3
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
4
|
+
import * as React from "react";
|
|
5
5
|
|
|
6
|
-
import { cn } from
|
|
6
|
+
import { cn } from "@repo/ui/lib/utils";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
function TooltipProvider({ delayDuration = 0, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
9
|
+
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />;
|
|
10
|
+
}
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
13
|
+
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;
|
|
14
|
+
}
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
17
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
|
|
18
|
+
}
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
function TooltipContent({
|
|
21
|
+
className,
|
|
22
|
+
sideOffset = 0,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
26
|
+
return (
|
|
27
|
+
<TooltipPrimitive.Portal>
|
|
28
|
+
<TooltipPrimitive.Content
|
|
29
|
+
data-slot="tooltip-content"
|
|
30
|
+
sideOffset={sideOffset}
|
|
31
|
+
className={cn(
|
|
32
|
+
"z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 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 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" />
|
|
39
|
+
</TooltipPrimitive.Content>
|
|
40
|
+
</TooltipPrimitive.Portal>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
29
43
|
|
|
30
|
-
export { Tooltip,
|
|
44
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { type RefObject, useEffect } from 'react';
|
|
1
|
+
import { type RefObject, useEffect } from "react";
|
|
3
2
|
|
|
4
|
-
function useOutsideClick<T extends HTMLElement>(
|
|
5
|
-
ref: RefObject<T | null>,
|
|
6
|
-
callback: () => void,
|
|
7
|
-
): void {
|
|
3
|
+
function useOutsideClick<T extends HTMLElement>(ref: RefObject<T | null>, callback: () => void): void {
|
|
8
4
|
useEffect(() => {
|
|
9
5
|
const handleClickOrTouch = (event: Event) => {
|
|
10
6
|
if (ref.current && !ref.current.contains(event.target as Node)) {
|
|
@@ -12,10 +8,10 @@ function useOutsideClick<T extends HTMLElement>(
|
|
|
12
8
|
}
|
|
13
9
|
};
|
|
14
10
|
|
|
15
|
-
document.addEventListener(
|
|
11
|
+
document.addEventListener("mousedown", handleClickOrTouch);
|
|
16
12
|
|
|
17
13
|
return () => {
|
|
18
|
-
document.removeEventListener(
|
|
14
|
+
document.removeEventListener("mousedown", handleClickOrTouch);
|
|
19
15
|
};
|
|
20
16
|
}, [ref, callback]);
|
|
21
17
|
}
|
|
@@ -28,10 +24,10 @@ function useInsideClick<T extends HTMLElement>(ref: RefObject<T>, callback: () =
|
|
|
28
24
|
}
|
|
29
25
|
};
|
|
30
26
|
|
|
31
|
-
document.addEventListener(
|
|
27
|
+
document.addEventListener("mousedown", handleClickOrTouch);
|
|
32
28
|
|
|
33
29
|
return () => {
|
|
34
|
-
document.removeEventListener(
|
|
30
|
+
document.removeEventListener("mousedown", handleClickOrTouch);
|
|
35
31
|
};
|
|
36
32
|
}, [ref, callback]);
|
|
37
33
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
type TimerHook = {
|
|
4
|
+
counter: number;
|
|
5
|
+
start: () => void;
|
|
6
|
+
reset: () => void;
|
|
7
|
+
clear: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function useTimer(initialSeconds: number): TimerHook {
|
|
11
|
+
const [counter, setCounter] = useState(initialSeconds);
|
|
12
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// Cleanup on component unmount or when counter changes
|
|
16
|
+
return () => {
|
|
17
|
+
if (timerRef.current) {
|
|
18
|
+
clearTimeout(timerRef.current);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
const start = () => {
|
|
24
|
+
if (timerRef.current) {
|
|
25
|
+
clearTimeout(timerRef.current);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
timerRef.current = setTimeout(() => {
|
|
29
|
+
setCounter(prev => (prev > 0 ? prev - 1 : 0));
|
|
30
|
+
}, 1000);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const reset = () => {
|
|
34
|
+
setCounter(initialSeconds);
|
|
35
|
+
clear();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const clear = () => {
|
|
39
|
+
if (timerRef.current) {
|
|
40
|
+
clearTimeout(timerRef.current);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (counter > 0) {
|
|
46
|
+
start();
|
|
47
|
+
}
|
|
48
|
+
}, [counter]);
|
|
49
|
+
|
|
50
|
+
return { counter, start, reset, clear };
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
export function useMediaQuery(query: string) {
|
|
4
|
+
const [value, setValue] = React.useState(false);
|
|
5
|
+
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
function onChange(event: MediaQueryListEvent) {
|
|
8
|
+
setValue(event.matches);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const result = matchMedia(query);
|
|
12
|
+
result.addEventListener("change", onChange);
|
|
13
|
+
setValue(result.matches);
|
|
14
|
+
|
|
15
|
+
return () => result.removeEventListener("change", onChange);
|
|
16
|
+
}, [query]);
|
|
17
|
+
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
export function useIsMobile(mobileBreakpoint = 768) {
|
|
4
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
|
|
5
|
+
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
const mql = window.matchMedia(`(max-width: ${mobileBreakpoint - 1}px)`);
|
|
8
|
+
const onChange = () => {
|
|
9
|
+
setIsMobile(window.innerWidth < mobileBreakpoint);
|
|
10
|
+
};
|
|
11
|
+
mql.addEventListener("change", onChange);
|
|
12
|
+
setIsMobile(window.innerWidth < mobileBreakpoint);
|
|
13
|
+
return () => mql.removeEventListener("change", onChange);
|
|
14
|
+
}, [mobileBreakpoint]);
|
|
15
|
+
|
|
16
|
+
return !!isMobile;
|
|
17
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type React from
|
|
2
|
-
import { useEffect, useRef } from
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
3
|
|
|
4
4
|
const useDidMountEffect = (func: React.EffectCallback, deps: React.DependencyList) => {
|
|
5
5
|
const didMount = useRef(false);
|