rusty-replay 0.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/.eslintrc.js +10 -0
- package/.vscode/settings.json +3 -0
- package/README.md +92 -0
- package/apps/web/README.md +11 -0
- package/apps/web/api/auth/keys.ts +3 -0
- package/apps/web/api/auth/types.ts +25 -0
- package/apps/web/api/auth/use-query-profile.ts +19 -0
- package/apps/web/api/auth/use-sign-in.ts +24 -0
- package/apps/web/api/axios.ts +122 -0
- package/apps/web/api/error-code.ts +36 -0
- package/apps/web/api/event/keys.ts +14 -0
- package/apps/web/api/event/types.ts +91 -0
- package/apps/web/api/event/use-mutation-event-assignee.ts +103 -0
- package/apps/web/api/event/use-mutation-event-priority.ts +97 -0
- package/apps/web/api/event/use-mutation-event-status.ts +198 -0
- package/apps/web/api/event/use-query-event-detail.ts +25 -0
- package/apps/web/api/event/use-query-event-list.ts +42 -0
- package/apps/web/api/health-check/index.ts +21 -0
- package/apps/web/api/project/keys.ts +4 -0
- package/apps/web/api/project/types.ts +28 -0
- package/apps/web/api/project/use-create-project.ts +30 -0
- package/apps/web/api/project/use-query-project-list.ts +19 -0
- package/apps/web/api/project/use-query-project-users.ts +23 -0
- package/apps/web/api/types.ts +44 -0
- package/apps/web/app/(auth)/layout.tsx +5 -0
- package/apps/web/app/(auth)/sign-in/page.tsx +20 -0
- package/apps/web/app/(auth)/sign-up/page.tsx +5 -0
- package/apps/web/app/(project)/project/[project_id]/issues/[issue_id]/page.tsx +17 -0
- package/apps/web/app/(project)/project/[project_id]/issues/page.tsx +15 -0
- package/apps/web/app/(project)/project/[project_id]/page.tsx +10 -0
- package/apps/web/app/(project)/project/page.tsx +10 -0
- package/apps/web/app/(report)/error-list/page.tsx +7 -0
- package/apps/web/app/favicon.ico +0 -0
- package/apps/web/app/layout.tsx +35 -0
- package/apps/web/app/page.tsx +3 -0
- package/apps/web/components/.gitkeep +0 -0
- package/apps/web/components/event-list/event-detail.tsx +242 -0
- package/apps/web/components/event-list/event-list.tsx +376 -0
- package/apps/web/components/event-list/preview.tsx +573 -0
- package/apps/web/components/layouts/default-layout.tsx +59 -0
- package/apps/web/components/login-form.tsx +124 -0
- package/apps/web/components/project/create-project.tsx +130 -0
- package/apps/web/components/project/hooks/use-get-event-params.ts +9 -0
- package/apps/web/components/project/hooks/use-get-project-params.ts +10 -0
- package/apps/web/components/project/project-detail.tsx +240 -0
- package/apps/web/components/project/project-list.tsx +137 -0
- package/apps/web/components/providers.tsx +25 -0
- package/apps/web/components/ui/assignee-dropdown.tsx +176 -0
- package/apps/web/components/ui/event-status-dropdown.tsx +104 -0
- package/apps/web/components/ui/priority-dropdown.tsx +123 -0
- package/apps/web/components/widget/app-sidebar.tsx +225 -0
- package/apps/web/components/widget/nav-main.tsx +73 -0
- package/apps/web/components/widget/nav-projects.tsx +84 -0
- package/apps/web/components/widget/nav-user.tsx +113 -0
- package/apps/web/components.json +20 -0
- package/apps/web/constants/routes.ts +12 -0
- package/apps/web/eslint.config.js +4 -0
- package/apps/web/hooks/use-boolean-state.ts +13 -0
- package/apps/web/lib/.gitkeep +0 -0
- package/apps/web/next-env.d.ts +5 -0
- package/apps/web/next.config.mjs +6 -0
- package/apps/web/package.json +60 -0
- package/apps/web/postcss.config.mjs +1 -0
- package/apps/web/providers/flag-provider.tsx +35 -0
- package/apps/web/providers/query-client-provider.tsx +17 -0
- package/apps/web/providers/telemetry-provider.tsx +12 -0
- package/apps/web/tsconfig.json +24 -0
- package/apps/web/utils/avatar.ts +26 -0
- package/apps/web/utils/date.ts +26 -0
- package/apps/web/utils/front-end-tracer.ts +119 -0
- package/apps/web/utils/schema/project.schema.ts +12 -0
- package/apps/web/utils/span-processor.ts +36 -0
- package/package.json +21 -0
- package/packages/eslint-config/README.md +3 -0
- package/packages/eslint-config/base.js +32 -0
- package/packages/eslint-config/next.js +51 -0
- package/packages/eslint-config/package.json +25 -0
- package/packages/eslint-config/react-internal.js +41 -0
- package/packages/rusty-replay/README.md +165 -0
- package/packages/rusty-replay/package.json +67 -0
- package/packages/rusty-replay/src/environment.ts +27 -0
- package/packages/rusty-replay/src/error-batcher.ts +75 -0
- package/packages/rusty-replay/src/front-end-tracer.ts +86 -0
- package/packages/rusty-replay/src/handler.ts +37 -0
- package/packages/rusty-replay/src/index.ts +8 -0
- package/packages/rusty-replay/src/recorder.ts +71 -0
- package/packages/rusty-replay/src/reporter.ts +115 -0
- package/packages/rusty-replay/src/utils.ts +13 -0
- package/packages/rusty-replay/tsconfig.build.json +13 -0
- package/packages/rusty-replay/tsconfig.json +27 -0
- package/packages/rusty-replay/tsup.config.ts +39 -0
- package/packages/typescript-config/README.md +3 -0
- package/packages/typescript-config/base.json +20 -0
- package/packages/typescript-config/nextjs.json +13 -0
- package/packages/typescript-config/package.json +9 -0
- package/packages/typescript-config/react-library.json +8 -0
- package/packages/ui/components.json +20 -0
- package/packages/ui/eslint.config.js +4 -0
- package/packages/ui/package.json +60 -0
- package/packages/ui/postcss.config.mjs +6 -0
- package/packages/ui/src/components/.gitkeep +0 -0
- package/packages/ui/src/components/avatar.tsx +53 -0
- package/packages/ui/src/components/badge.tsx +46 -0
- package/packages/ui/src/components/breadcrumb.tsx +109 -0
- package/packages/ui/src/components/button.tsx +59 -0
- package/packages/ui/src/components/calendar.tsx +75 -0
- package/packages/ui/src/components/calendars/date-picker.tsx +43 -0
- package/packages/ui/src/components/calendars/date-range-picker.tsx +79 -0
- package/packages/ui/src/components/card.tsx +92 -0
- package/packages/ui/src/components/checkbox.tsx +32 -0
- package/packages/ui/src/components/collapsible.tsx +33 -0
- package/packages/ui/src/components/dialog.tsx +135 -0
- package/packages/ui/src/components/dialogs/confirmation-modal.tsx +216 -0
- package/packages/ui/src/components/dropdown-menu.tsx +261 -0
- package/packages/ui/src/components/input.tsx +30 -0
- package/packages/ui/src/components/label.tsx +24 -0
- package/packages/ui/src/components/login-form.tsx +68 -0
- package/packages/ui/src/components/mode-switcher.tsx +34 -0
- package/packages/ui/src/components/popover.tsx +48 -0
- package/packages/ui/src/components/scroll-area.tsx +58 -0
- package/packages/ui/src/components/select.tsx +185 -0
- package/packages/ui/src/components/separator.tsx +28 -0
- package/packages/ui/src/components/sheet.tsx +139 -0
- package/packages/ui/src/components/sidebar.tsx +726 -0
- package/packages/ui/src/components/skeleton.tsx +13 -0
- package/packages/ui/src/components/sonner.tsx +25 -0
- package/packages/ui/src/components/table.tsx +116 -0
- package/packages/ui/src/components/tabs.tsx +66 -0
- package/packages/ui/src/components/team-switcher.tsx +91 -0
- package/packages/ui/src/components/textarea.tsx +18 -0
- package/packages/ui/src/components/tooltip.tsx +61 -0
- package/packages/ui/src/hooks/.gitkeep +0 -0
- package/packages/ui/src/hooks/use-meta-color.ts +28 -0
- package/packages/ui/src/hooks/use-mobile.ts +19 -0
- package/packages/ui/src/lib/utils.ts +6 -0
- package/packages/ui/src/styles/globals.css +138 -0
- package/packages/ui/tsconfig.json +13 -0
- package/packages/ui/tsconfig.lint.json +8 -0
- package/pnpm-workspace.yaml +4 -0
- package/tsconfig.json +4 -0
- package/turbo.json +21 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
import { cn } from "@workspace/ui/lib/utils"
|
2
|
+
|
3
|
+
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
4
|
+
return (
|
5
|
+
<div
|
6
|
+
data-slot="skeleton"
|
7
|
+
className={cn("bg-accent animate-pulse rounded-md", className)}
|
8
|
+
{...props}
|
9
|
+
/>
|
10
|
+
)
|
11
|
+
}
|
12
|
+
|
13
|
+
export { Skeleton }
|
@@ -0,0 +1,25 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { useTheme } from 'next-themes';
|
4
|
+
import { Toaster as Sonner, ToasterProps, toast } from 'sonner';
|
5
|
+
|
6
|
+
const Toaster = ({ ...props }: ToasterProps) => {
|
7
|
+
const { theme = 'system' } = useTheme();
|
8
|
+
|
9
|
+
return (
|
10
|
+
<Sonner
|
11
|
+
theme={theme as ToasterProps['theme']}
|
12
|
+
className="toaster group"
|
13
|
+
style={
|
14
|
+
{
|
15
|
+
'--normal-bg': 'var(--popover)',
|
16
|
+
'--normal-text': 'var(--popover-foreground)',
|
17
|
+
'--normal-border': 'var(--border)',
|
18
|
+
} as React.CSSProperties
|
19
|
+
}
|
20
|
+
{...props}
|
21
|
+
/>
|
22
|
+
);
|
23
|
+
};
|
24
|
+
|
25
|
+
export { Toaster, toast };
|
@@ -0,0 +1,116 @@
|
|
1
|
+
"use client"
|
2
|
+
|
3
|
+
import * as React from "react"
|
4
|
+
|
5
|
+
import { cn } from "@workspace/ui/lib/utils"
|
6
|
+
|
7
|
+
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
8
|
+
return (
|
9
|
+
<div
|
10
|
+
data-slot="table-container"
|
11
|
+
className="relative w-full overflow-x-auto"
|
12
|
+
>
|
13
|
+
<table
|
14
|
+
data-slot="table"
|
15
|
+
className={cn("w-full caption-bottom text-sm", className)}
|
16
|
+
{...props}
|
17
|
+
/>
|
18
|
+
</div>
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
23
|
+
return (
|
24
|
+
<thead
|
25
|
+
data-slot="table-header"
|
26
|
+
className={cn("[&_tr]:border-b", className)}
|
27
|
+
{...props}
|
28
|
+
/>
|
29
|
+
)
|
30
|
+
}
|
31
|
+
|
32
|
+
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
33
|
+
return (
|
34
|
+
<tbody
|
35
|
+
data-slot="table-body"
|
36
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
37
|
+
{...props}
|
38
|
+
/>
|
39
|
+
)
|
40
|
+
}
|
41
|
+
|
42
|
+
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
43
|
+
return (
|
44
|
+
<tfoot
|
45
|
+
data-slot="table-footer"
|
46
|
+
className={cn(
|
47
|
+
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
48
|
+
className
|
49
|
+
)}
|
50
|
+
{...props}
|
51
|
+
/>
|
52
|
+
)
|
53
|
+
}
|
54
|
+
|
55
|
+
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
56
|
+
return (
|
57
|
+
<tr
|
58
|
+
data-slot="table-row"
|
59
|
+
className={cn(
|
60
|
+
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
61
|
+
className
|
62
|
+
)}
|
63
|
+
{...props}
|
64
|
+
/>
|
65
|
+
)
|
66
|
+
}
|
67
|
+
|
68
|
+
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
69
|
+
return (
|
70
|
+
<th
|
71
|
+
data-slot="table-head"
|
72
|
+
className={cn(
|
73
|
+
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
74
|
+
className
|
75
|
+
)}
|
76
|
+
{...props}
|
77
|
+
/>
|
78
|
+
)
|
79
|
+
}
|
80
|
+
|
81
|
+
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
82
|
+
return (
|
83
|
+
<td
|
84
|
+
data-slot="table-cell"
|
85
|
+
className={cn(
|
86
|
+
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
87
|
+
className
|
88
|
+
)}
|
89
|
+
{...props}
|
90
|
+
/>
|
91
|
+
)
|
92
|
+
}
|
93
|
+
|
94
|
+
function TableCaption({
|
95
|
+
className,
|
96
|
+
...props
|
97
|
+
}: React.ComponentProps<"caption">) {
|
98
|
+
return (
|
99
|
+
<caption
|
100
|
+
data-slot="table-caption"
|
101
|
+
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
102
|
+
{...props}
|
103
|
+
/>
|
104
|
+
)
|
105
|
+
}
|
106
|
+
|
107
|
+
export {
|
108
|
+
Table,
|
109
|
+
TableHeader,
|
110
|
+
TableBody,
|
111
|
+
TableFooter,
|
112
|
+
TableHead,
|
113
|
+
TableRow,
|
114
|
+
TableCell,
|
115
|
+
TableCaption,
|
116
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
"use client"
|
2
|
+
|
3
|
+
import * as React from "react"
|
4
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
5
|
+
|
6
|
+
import { cn } from "@workspace/ui/lib/utils"
|
7
|
+
|
8
|
+
function Tabs({
|
9
|
+
className,
|
10
|
+
...props
|
11
|
+
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
12
|
+
return (
|
13
|
+
<TabsPrimitive.Root
|
14
|
+
data-slot="tabs"
|
15
|
+
className={cn("flex flex-col gap-2", className)}
|
16
|
+
{...props}
|
17
|
+
/>
|
18
|
+
)
|
19
|
+
}
|
20
|
+
|
21
|
+
function TabsList({
|
22
|
+
className,
|
23
|
+
...props
|
24
|
+
}: React.ComponentProps<typeof TabsPrimitive.List>) {
|
25
|
+
return (
|
26
|
+
<TabsPrimitive.List
|
27
|
+
data-slot="tabs-list"
|
28
|
+
className={cn(
|
29
|
+
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
30
|
+
className
|
31
|
+
)}
|
32
|
+
{...props}
|
33
|
+
/>
|
34
|
+
)
|
35
|
+
}
|
36
|
+
|
37
|
+
function TabsTrigger({
|
38
|
+
className,
|
39
|
+
...props
|
40
|
+
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
41
|
+
return (
|
42
|
+
<TabsPrimitive.Trigger
|
43
|
+
data-slot="tabs-trigger"
|
44
|
+
className={cn(
|
45
|
+
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
46
|
+
className
|
47
|
+
)}
|
48
|
+
{...props}
|
49
|
+
/>
|
50
|
+
)
|
51
|
+
}
|
52
|
+
|
53
|
+
function TabsContent({
|
54
|
+
className,
|
55
|
+
...props
|
56
|
+
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
57
|
+
return (
|
58
|
+
<TabsPrimitive.Content
|
59
|
+
data-slot="tabs-content"
|
60
|
+
className={cn("flex-1 outline-none", className)}
|
61
|
+
{...props}
|
62
|
+
/>
|
63
|
+
)
|
64
|
+
}
|
65
|
+
|
66
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
@@ -0,0 +1,91 @@
|
|
1
|
+
"use client"
|
2
|
+
|
3
|
+
import * as React from "react"
|
4
|
+
import { ChevronsUpDown, Plus } from "lucide-react"
|
5
|
+
|
6
|
+
import {
|
7
|
+
DropdownMenu,
|
8
|
+
DropdownMenuContent,
|
9
|
+
DropdownMenuItem,
|
10
|
+
DropdownMenuLabel,
|
11
|
+
DropdownMenuSeparator,
|
12
|
+
DropdownMenuShortcut,
|
13
|
+
DropdownMenuTrigger,
|
14
|
+
} from "@workspace/ui/components/dropdown-menu"
|
15
|
+
import {
|
16
|
+
SidebarMenu,
|
17
|
+
SidebarMenuButton,
|
18
|
+
SidebarMenuItem,
|
19
|
+
useSidebar,
|
20
|
+
} from "@workspace/ui/components/sidebar"
|
21
|
+
|
22
|
+
export function TeamSwitcher({
|
23
|
+
teams,
|
24
|
+
}: {
|
25
|
+
teams: {
|
26
|
+
name: string
|
27
|
+
logo: React.ElementType
|
28
|
+
plan: string
|
29
|
+
}[]
|
30
|
+
}) {
|
31
|
+
const { isMobile } = useSidebar()
|
32
|
+
const [activeTeam, setActiveTeam] = React.useState(teams[0])
|
33
|
+
|
34
|
+
if (!activeTeam) {
|
35
|
+
return null
|
36
|
+
}
|
37
|
+
|
38
|
+
return (
|
39
|
+
<SidebarMenu>
|
40
|
+
<SidebarMenuItem>
|
41
|
+
<DropdownMenu>
|
42
|
+
<DropdownMenuTrigger asChild>
|
43
|
+
<SidebarMenuButton
|
44
|
+
size="lg"
|
45
|
+
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
46
|
+
>
|
47
|
+
<div className="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg">
|
48
|
+
<activeTeam.logo className="size-4" />
|
49
|
+
</div>
|
50
|
+
<div className="grid flex-1 text-left text-sm leading-tight">
|
51
|
+
<span className="truncate font-medium">{activeTeam.name}</span>
|
52
|
+
<span className="truncate text-xs">{activeTeam.plan}</span>
|
53
|
+
</div>
|
54
|
+
<ChevronsUpDown className="ml-auto" />
|
55
|
+
</SidebarMenuButton>
|
56
|
+
</DropdownMenuTrigger>
|
57
|
+
<DropdownMenuContent
|
58
|
+
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
|
59
|
+
align="start"
|
60
|
+
side={isMobile ? "bottom" : "right"}
|
61
|
+
sideOffset={4}
|
62
|
+
>
|
63
|
+
<DropdownMenuLabel className="text-muted-foreground text-xs">
|
64
|
+
Teams
|
65
|
+
</DropdownMenuLabel>
|
66
|
+
{teams.map((team, index) => (
|
67
|
+
<DropdownMenuItem
|
68
|
+
key={team.name}
|
69
|
+
onClick={() => setActiveTeam(team)}
|
70
|
+
className="gap-2 p-2"
|
71
|
+
>
|
72
|
+
<div className="flex size-6 items-center justify-center rounded-md border">
|
73
|
+
<team.logo className="size-3.5 shrink-0" />
|
74
|
+
</div>
|
75
|
+
{team.name}
|
76
|
+
<DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>
|
77
|
+
</DropdownMenuItem>
|
78
|
+
))}
|
79
|
+
<DropdownMenuSeparator />
|
80
|
+
<DropdownMenuItem className="gap-2 p-2">
|
81
|
+
<div className="flex size-6 items-center justify-center rounded-md border bg-transparent">
|
82
|
+
<Plus className="size-4" />
|
83
|
+
</div>
|
84
|
+
<div className="text-muted-foreground font-medium">Add team</div>
|
85
|
+
</DropdownMenuItem>
|
86
|
+
</DropdownMenuContent>
|
87
|
+
</DropdownMenu>
|
88
|
+
</SidebarMenuItem>
|
89
|
+
</SidebarMenu>
|
90
|
+
)
|
91
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import * as React from "react"
|
2
|
+
|
3
|
+
import { cn } from "@workspace/ui/lib/utils"
|
4
|
+
|
5
|
+
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
6
|
+
return (
|
7
|
+
<textarea
|
8
|
+
data-slot="textarea"
|
9
|
+
className={cn(
|
10
|
+
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
11
|
+
className
|
12
|
+
)}
|
13
|
+
{...props}
|
14
|
+
/>
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
export { Textarea }
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"use client"
|
2
|
+
|
3
|
+
import * as React from "react"
|
4
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
5
|
+
|
6
|
+
import { cn } from "@workspace/ui/lib/utils"
|
7
|
+
|
8
|
+
function TooltipProvider({
|
9
|
+
delayDuration = 0,
|
10
|
+
...props
|
11
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
12
|
+
return (
|
13
|
+
<TooltipPrimitive.Provider
|
14
|
+
data-slot="tooltip-provider"
|
15
|
+
delayDuration={delayDuration}
|
16
|
+
{...props}
|
17
|
+
/>
|
18
|
+
)
|
19
|
+
}
|
20
|
+
|
21
|
+
function Tooltip({
|
22
|
+
...props
|
23
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
24
|
+
return (
|
25
|
+
<TooltipProvider>
|
26
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
27
|
+
</TooltipProvider>
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
function TooltipTrigger({
|
32
|
+
...props
|
33
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
34
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
35
|
+
}
|
36
|
+
|
37
|
+
function TooltipContent({
|
38
|
+
className,
|
39
|
+
sideOffset = 0,
|
40
|
+
children,
|
41
|
+
...props
|
42
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
43
|
+
return (
|
44
|
+
<TooltipPrimitive.Portal>
|
45
|
+
<TooltipPrimitive.Content
|
46
|
+
data-slot="tooltip-content"
|
47
|
+
sideOffset={sideOffset}
|
48
|
+
className={cn(
|
49
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
50
|
+
className
|
51
|
+
)}
|
52
|
+
{...props}
|
53
|
+
>
|
54
|
+
{children}
|
55
|
+
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
56
|
+
</TooltipPrimitive.Content>
|
57
|
+
</TooltipPrimitive.Portal>
|
58
|
+
)
|
59
|
+
}
|
60
|
+
|
61
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { useTheme } from 'next-themes';
|
3
|
+
|
4
|
+
export const META_THEME_COLORS = {
|
5
|
+
light: '#ffffff',
|
6
|
+
dark: '#09090b',
|
7
|
+
};
|
8
|
+
|
9
|
+
export function useMetaColor() {
|
10
|
+
const { resolvedTheme } = useTheme();
|
11
|
+
|
12
|
+
const metaColor = React.useMemo(() => {
|
13
|
+
return resolvedTheme !== 'dark'
|
14
|
+
? META_THEME_COLORS.light
|
15
|
+
: META_THEME_COLORS.dark;
|
16
|
+
}, [resolvedTheme]);
|
17
|
+
|
18
|
+
const setMetaColor = React.useCallback((color: string) => {
|
19
|
+
document
|
20
|
+
.querySelector('meta[name="theme-color"]')
|
21
|
+
?.setAttribute('content', color);
|
22
|
+
}, []);
|
23
|
+
|
24
|
+
return {
|
25
|
+
metaColor,
|
26
|
+
setMetaColor,
|
27
|
+
};
|
28
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import * as React from "react"
|
2
|
+
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
4
|
+
|
5
|
+
export function useIsMobile() {
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
7
|
+
|
8
|
+
React.useEffect(() => {
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
10
|
+
const onChange = () => {
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
12
|
+
}
|
13
|
+
mql.addEventListener("change", onChange)
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
15
|
+
return () => mql.removeEventListener("change", onChange)
|
16
|
+
}, [])
|
17
|
+
|
18
|
+
return !!isMobile
|
19
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
@import 'tailwindcss';
|
2
|
+
@source "../../../apps/**/*.{ts,tsx}";
|
3
|
+
@source "../../../components/**/*.{ts,tsx}";
|
4
|
+
@source "../**/*.{ts,tsx}";
|
5
|
+
|
6
|
+
@import 'tw-animate-css';
|
7
|
+
|
8
|
+
@custom-variant dark (&:is(.dark *));
|
9
|
+
|
10
|
+
:root {
|
11
|
+
--background: oklch(1 0 0);
|
12
|
+
--foreground: oklch(0.145 0 0);
|
13
|
+
--card: oklch(1 0 0);
|
14
|
+
--card-foreground: oklch(0.145 0 0);
|
15
|
+
--popover: oklch(1 0 0);
|
16
|
+
--popover-foreground: oklch(0.145 0 0);
|
17
|
+
--primary: oklch(0.205 0 0);
|
18
|
+
--primary-foreground: oklch(0.985 0 0);
|
19
|
+
--secondary: oklch(0.97 0 0);
|
20
|
+
--secondary-foreground: oklch(0.205 0 0);
|
21
|
+
--muted: oklch(0.97 0 0);
|
22
|
+
--muted-foreground: oklch(0.556 0 0);
|
23
|
+
--accent: oklch(0.97 0 0);
|
24
|
+
--accent-foreground: oklch(0.205 0 0);
|
25
|
+
--destructive: oklch(0.577 0.245 27.325);
|
26
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
27
|
+
--border: oklch(0.922 0 0);
|
28
|
+
--input: oklch(0.922 0 0);
|
29
|
+
--ring: oklch(0.708 0 0);
|
30
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
31
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
32
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
33
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
34
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
35
|
+
--radius: 0.625rem;
|
36
|
+
--sidebar: oklch(0.985 0 0);
|
37
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
38
|
+
--sidebar-primary: oklch(0.205 0 0);
|
39
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
40
|
+
--sidebar-accent: oklch(0.97 0 0);
|
41
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
42
|
+
--sidebar-border: oklch(0.922 0 0);
|
43
|
+
--sidebar-ring: oklch(0.708 0 0);
|
44
|
+
}
|
45
|
+
|
46
|
+
.dark {
|
47
|
+
--background: oklch(0.145 0 0);
|
48
|
+
--foreground: oklch(0.985 0 0);
|
49
|
+
--card: oklch(0.145 0 0);
|
50
|
+
--card-foreground: oklch(0.985 0 0);
|
51
|
+
--popover: oklch(0.145 0 0);
|
52
|
+
--popover-foreground: oklch(0.985 0 0);
|
53
|
+
--primary: oklch(0.985 0 0);
|
54
|
+
--primary-foreground: oklch(0.205 0 0);
|
55
|
+
--secondary: oklch(0.269 0 0);
|
56
|
+
--secondary-foreground: oklch(0.985 0 0);
|
57
|
+
--muted: oklch(0.269 0 0);
|
58
|
+
--muted-foreground: oklch(0.708 0 0);
|
59
|
+
--accent: oklch(0.269 0 0);
|
60
|
+
--accent-foreground: oklch(0.985 0 0);
|
61
|
+
--destructive: oklch(0.396 0.141 25.723);
|
62
|
+
--destructive-foreground: oklch(0.637 0.237 25.331);
|
63
|
+
--border: oklch(0.269 0 0);
|
64
|
+
--input: oklch(0.269 0 0);
|
65
|
+
--ring: oklch(0.556 0 0);
|
66
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
67
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
68
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
69
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
70
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
71
|
+
--sidebar: oklch(0.205 0 0);
|
72
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
73
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
74
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
75
|
+
--sidebar-accent: oklch(0.269 0 0);
|
76
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
77
|
+
--sidebar-border: oklch(0.269 0 0);
|
78
|
+
--sidebar-ring: oklch(0.439 0 0);
|
79
|
+
}
|
80
|
+
|
81
|
+
@theme inline {
|
82
|
+
--color-background: var(--background);
|
83
|
+
--color-foreground: var(--foreground);
|
84
|
+
--color-card: var(--card);
|
85
|
+
--color-card-foreground: var(--card-foreground);
|
86
|
+
--color-popover: var(--popover);
|
87
|
+
--color-popover-foreground: var(--popover-foreground);
|
88
|
+
--color-primary: var(--primary);
|
89
|
+
--color-primary-foreground: var(--primary-foreground);
|
90
|
+
--color-secondary: var(--secondary);
|
91
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
92
|
+
--color-muted: var(--muted);
|
93
|
+
--color-muted-foreground: var(--muted-foreground);
|
94
|
+
--color-accent: var(--accent);
|
95
|
+
--color-accent-foreground: var(--accent-foreground);
|
96
|
+
--color-destructive: var(--destructive);
|
97
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
98
|
+
--color-border: var(--border);
|
99
|
+
--color-input: var(--input);
|
100
|
+
--color-ring: var(--ring);
|
101
|
+
--color-chart-1: var(--chart-1);
|
102
|
+
--color-chart-2: var(--chart-2);
|
103
|
+
--color-chart-3: var(--chart-3);
|
104
|
+
--color-chart-4: var(--chart-4);
|
105
|
+
--color-chart-5: var(--chart-5);
|
106
|
+
--radius-sm: calc(var(--radius) - 4px);
|
107
|
+
--radius-md: calc(var(--radius) - 2px);
|
108
|
+
--radius-lg: var(--radius);
|
109
|
+
--radius-xl: calc(var(--radius) + 4px);
|
110
|
+
--color-sidebar: var(--sidebar);
|
111
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
112
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
113
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
114
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
115
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
116
|
+
--color-sidebar-border: var(--sidebar-border);
|
117
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
118
|
+
}
|
119
|
+
|
120
|
+
@layer base {
|
121
|
+
* {
|
122
|
+
@apply border-border outline-ring/50;
|
123
|
+
}
|
124
|
+
body {
|
125
|
+
@apply bg-background text-foreground;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
.dark {
|
130
|
+
--sidebar: hsl(240 5.9% 10%);
|
131
|
+
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
132
|
+
--sidebar-primary: hsl(224.3 76.3% 48%);
|
133
|
+
--sidebar-primary-foreground: hsl(0 0% 100%);
|
134
|
+
--sidebar-accent: hsl(240 3.7% 15.9%);
|
135
|
+
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
136
|
+
--sidebar-border: hsl(240 3.7% 15.9%);
|
137
|
+
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
138
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"extends": "@workspace/typescript-config/react-library.json",
|
3
|
+
"compilerOptions": {
|
4
|
+
"module": "Preserve",
|
5
|
+
"moduleResolution": "bundler",
|
6
|
+
"baseUrl": ".",
|
7
|
+
"paths": {
|
8
|
+
"@workspace/ui/*": ["./src/*"]
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"include": ["."],
|
12
|
+
"exclude": ["node_modules", "dist"]
|
13
|
+
}
|
package/tsconfig.json
ADDED
package/turbo.json
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "https://turbo.build/schema.json",
|
3
|
+
"ui": "tui",
|
4
|
+
"tasks": {
|
5
|
+
"build": {
|
6
|
+
"dependsOn": ["^build"],
|
7
|
+
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
8
|
+
"outputs": [".next/**", "!.next/cache/**"]
|
9
|
+
},
|
10
|
+
"lint": {
|
11
|
+
"dependsOn": ["^lint"]
|
12
|
+
},
|
13
|
+
"check-types": {
|
14
|
+
"dependsOn": ["^check-types"]
|
15
|
+
},
|
16
|
+
"dev": {
|
17
|
+
"cache": false,
|
18
|
+
"persistent": true
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|