@eggspot/ui 0.0.0
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/eslint.config.js +4 -0
- package/package.json +66 -0
- package/postcss.config.mjs +1 -0
- package/src/components/Button.machine.tsx +50 -0
- package/src/components/Button.tsx +249 -0
- package/src/components/Button.variants.tsx +186 -0
- package/src/components/ButtonGroup.tsx +56 -0
- package/src/components/Calendar.tsx +275 -0
- package/src/components/Calendar.utils.tsx +22 -0
- package/src/components/Checkbox.tsx +199 -0
- package/src/components/ConfirmDialog.tsx +183 -0
- package/src/components/DashboardLayout/DashboardLayout.tsx +348 -0
- package/src/components/DashboardLayout/SidebarNav.tsx +509 -0
- package/src/components/DashboardLayout/index.ts +33 -0
- package/src/components/DataTable/DataTable.tsx +557 -0
- package/src/components/DataTable/DataTableColumnHeader.tsx +122 -0
- package/src/components/DataTable/DataTableDisplaySettings.tsx +265 -0
- package/src/components/DataTable/DataTableFloatingBar.tsx +44 -0
- package/src/components/DataTable/DataTablePagination.tsx +168 -0
- package/src/components/DataTable/DataTableStates.tsx +69 -0
- package/src/components/DataTable/DataTableToolbarContainer.tsx +47 -0
- package/src/components/DataTable/hooks/use-data-table-settings.ts +101 -0
- package/src/components/DataTable/index.ts +7 -0
- package/src/components/DataTable/types/data-table.ts +97 -0
- package/src/components/DatePicker.tsx +213 -0
- package/src/components/DatePicker.utils.tsx +38 -0
- package/src/components/Datefield.tsx +109 -0
- package/src/components/Datefield.utils.ts +10 -0
- package/src/components/Dialog.tsx +167 -0
- package/src/components/Field.tsx +49 -0
- package/src/components/Filter/Filter.store.tsx +122 -0
- package/src/components/Filter/Filter.tsx +11 -0
- package/src/components/Filter/Filter.types.ts +107 -0
- package/src/components/Filter/FilterBar.tsx +38 -0
- package/src/components/Filter/FilterBuilder.tsx +158 -0
- package/src/components/Filter/FilterField/DateModeRowValue.tsx +250 -0
- package/src/components/Filter/FilterField/FilterAsyncSelect.tsx +191 -0
- package/src/components/Filter/FilterField/FilterDateMode.tsx +241 -0
- package/src/components/Filter/FilterField/FilterDateRange.tsx +169 -0
- package/src/components/Filter/FilterField/FilterSelect.tsx +208 -0
- package/src/components/Filter/FilterField/FilterSingleDate.tsx +277 -0
- package/src/components/Filter/FilterField/OptionItem.tsx +112 -0
- package/src/components/Filter/FilterField/index.ts +6 -0
- package/src/components/Filter/FilterRow.tsx +527 -0
- package/src/components/Filter/index.ts +17 -0
- package/src/components/Form.tsx +195 -0
- package/src/components/Heading.tsx +41 -0
- package/src/components/Input.tsx +221 -0
- package/src/components/InputOTP.tsx +78 -0
- package/src/components/Label.tsx +65 -0
- package/src/components/Layout.tsx +129 -0
- package/src/components/ListBox.tsx +97 -0
- package/src/components/Menu.tsx +152 -0
- package/src/components/NativeSelect.tsx +77 -0
- package/src/components/NumberInput.tsx +114 -0
- package/src/components/Popover.tsx +44 -0
- package/src/components/Provider.tsx +22 -0
- package/src/components/RadioGroup.tsx +191 -0
- package/src/components/Resizable.tsx +71 -0
- package/src/components/ScrollArea.tsx +57 -0
- package/src/components/Select.tsx +626 -0
- package/src/components/Select.utils.tsx +64 -0
- package/src/components/Separator.tsx +25 -0
- package/src/components/Sheet.tsx +147 -0
- package/src/components/Sonner.tsx +96 -0
- package/src/components/Spinner.tsx +30 -0
- package/src/components/Switch.tsx +51 -0
- package/src/components/Text.tsx +35 -0
- package/src/components/Tooltip.tsx +58 -0
- package/src/consts/config.ts +2 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/lib/utils.ts +10 -0
- package/tsconfig.json +11 -0
- package/tsconfig.lint.json +8 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React from "react"
|
|
4
|
+
import { Button } from "@eggspot/ui/components/Button"
|
|
5
|
+
import { cn } from "@eggspot/ui/lib/utils"
|
|
6
|
+
import { X } from "lucide-react"
|
|
7
|
+
import {
|
|
8
|
+
Dialog as AriaDialog,
|
|
9
|
+
DialogProps as AriaDialogProps,
|
|
10
|
+
DialogTrigger as AriaDialogTrigger,
|
|
11
|
+
Heading as AriaHeading,
|
|
12
|
+
HeadingProps as AriaHeadingProps,
|
|
13
|
+
Modal as AriaModal,
|
|
14
|
+
ModalOverlay as AriaModalOverlay,
|
|
15
|
+
ModalOverlayProps as AriaModalOverlayProps,
|
|
16
|
+
composeRenderProps,
|
|
17
|
+
} from "react-aria-components"
|
|
18
|
+
|
|
19
|
+
const Sheet = AriaDialog
|
|
20
|
+
|
|
21
|
+
const SheetTrigger = AriaDialogTrigger
|
|
22
|
+
|
|
23
|
+
const SheetOverlay = ({
|
|
24
|
+
className,
|
|
25
|
+
isDismissable = true,
|
|
26
|
+
...props
|
|
27
|
+
}: AriaModalOverlayProps) => (
|
|
28
|
+
<AriaModalOverlay
|
|
29
|
+
isDismissable={isDismissable}
|
|
30
|
+
className={composeRenderProps(className, (className) =>
|
|
31
|
+
cn(
|
|
32
|
+
"fixed inset-0 z-50 bg-black/50 duration-300",
|
|
33
|
+
/* Exiting */
|
|
34
|
+
"data-[exiting]:animate-out data-[exiting]:fade-out-0",
|
|
35
|
+
/* Entering */
|
|
36
|
+
"data-[entering]:animate-in data-[entering]:fade-in-0",
|
|
37
|
+
className
|
|
38
|
+
)
|
|
39
|
+
)}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
interface SheetContentProps
|
|
45
|
+
extends Omit<React.ComponentProps<typeof AriaModal>, "children"> {
|
|
46
|
+
children?: AriaDialogProps["children"]
|
|
47
|
+
role?: AriaDialogProps["role"]
|
|
48
|
+
closeButton?: boolean
|
|
49
|
+
side?: "top" | "right" | "bottom" | "left"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const SheetContent = ({
|
|
53
|
+
className,
|
|
54
|
+
children,
|
|
55
|
+
role,
|
|
56
|
+
closeButton = true,
|
|
57
|
+
side = "right",
|
|
58
|
+
...props
|
|
59
|
+
}: SheetContentProps) => (
|
|
60
|
+
<SheetOverlay>
|
|
61
|
+
<AriaModal
|
|
62
|
+
className={composeRenderProps(className, (className) =>
|
|
63
|
+
cn(
|
|
64
|
+
"bg-gray-1 data-[entering]:animate-in data-[exiting]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition duration-300 ease-in-out",
|
|
65
|
+
side === "right" &&
|
|
66
|
+
"data-[exiting]:slide-out-to-right data-[entering]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
|
|
67
|
+
side === "left" &&
|
|
68
|
+
"data-[exiting]:slide-out-to-left data-[entering]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
|
|
69
|
+
side === "top" &&
|
|
70
|
+
"data-[exiting]:slide-out-to-top data-[entering]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
|
|
71
|
+
side === "bottom" &&
|
|
72
|
+
"data-[exiting]:slide-out-to-bottom data-[entering]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
|
|
73
|
+
className
|
|
74
|
+
)
|
|
75
|
+
)}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
<AriaDialog
|
|
79
|
+
role={role}
|
|
80
|
+
className={cn("grid h-full gap-4", "h-full outline-none")}
|
|
81
|
+
>
|
|
82
|
+
{composeRenderProps(children, (children, renderProps) => (
|
|
83
|
+
<>
|
|
84
|
+
{children}
|
|
85
|
+
{closeButton && (
|
|
86
|
+
<Button
|
|
87
|
+
onClick={renderProps.close}
|
|
88
|
+
mode="icon"
|
|
89
|
+
variant="ghost"
|
|
90
|
+
tooltip="Close"
|
|
91
|
+
tooltipDelay={2000}
|
|
92
|
+
className="absolute top-2.5 right-2.5"
|
|
93
|
+
>
|
|
94
|
+
<X className="text-gray-11 size-4!" />
|
|
95
|
+
<span className="sr-only">Close</span>
|
|
96
|
+
</Button>
|
|
97
|
+
)}
|
|
98
|
+
</>
|
|
99
|
+
))}
|
|
100
|
+
</AriaDialog>
|
|
101
|
+
</AriaModal>
|
|
102
|
+
</SheetOverlay>
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
const SheetHeader = ({
|
|
106
|
+
className,
|
|
107
|
+
...props
|
|
108
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
109
|
+
<div className={cn("flex flex-col gap-1.5 p-4", className)} {...props} />
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const SheetFooter = ({
|
|
113
|
+
className,
|
|
114
|
+
...props
|
|
115
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
116
|
+
<div
|
|
117
|
+
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
const SheetTitle = ({ className, ...props }: AriaHeadingProps) => (
|
|
123
|
+
<AriaHeading
|
|
124
|
+
slot="title"
|
|
125
|
+
className={cn("text-gray-11 font-semibold", className)}
|
|
126
|
+
{...props}
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
const SheetDescription = ({
|
|
131
|
+
className,
|
|
132
|
+
...props
|
|
133
|
+
}: React.HTMLAttributes<HTMLParagraphElement>) => (
|
|
134
|
+
<p className={cn("text-gray-11 text-sm", className)} {...props} />
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
Sheet,
|
|
139
|
+
SheetContent,
|
|
140
|
+
SheetDescription,
|
|
141
|
+
SheetFooter,
|
|
142
|
+
SheetHeader,
|
|
143
|
+
SheetOverlay,
|
|
144
|
+
SheetTitle,
|
|
145
|
+
SheetTrigger,
|
|
146
|
+
}
|
|
147
|
+
export type { SheetContentProps }
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Button } from "@eggspot/ui/components/Button"
|
|
4
|
+
import {
|
|
5
|
+
AlertTriangleIcon,
|
|
6
|
+
CircleCheckIcon,
|
|
7
|
+
CircleXIcon,
|
|
8
|
+
InfoIcon,
|
|
9
|
+
XIcon,
|
|
10
|
+
} from "lucide-react"
|
|
11
|
+
import { toast as sonnerToast, Toaster, ToastT } from "sonner"
|
|
12
|
+
|
|
13
|
+
interface ToastProps {
|
|
14
|
+
id: string | number
|
|
15
|
+
title: string
|
|
16
|
+
description?: React.ReactNode
|
|
17
|
+
variant?: "success" | "error" | "info" | "warning" | "neutral"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A fully custom toast that still maintains the animations and interactions. */
|
|
21
|
+
function Toast(props: ToastProps) {
|
|
22
|
+
const { title, description, id, variant = "neutral" } = props
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className="group bg-gray-2 text-gray-12 relative flex min-h-[64px] w-full items-center gap-3 rounded-xl border px-4 py-2.5 pr-7 shadow-lg md:w-[364px]">
|
|
26
|
+
<ToastIcon variant={variant} />
|
|
27
|
+
<div className="flex flex-1 items-center">
|
|
28
|
+
<div className="w-full">
|
|
29
|
+
<p className="text-gray-12 text-sm font-semibold">{title}</p>
|
|
30
|
+
{description && (
|
|
31
|
+
<div className="text-gray-11 mt-0.5 text-sm">{description}</div>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
<Button
|
|
36
|
+
size="sm"
|
|
37
|
+
mode="icon"
|
|
38
|
+
variant="ghost"
|
|
39
|
+
onClick={() => sonnerToast.dismiss(id)}
|
|
40
|
+
className="absolute top-1.5 right-1.5 opacity-0 transition-opacity group-hover:opacity-100"
|
|
41
|
+
>
|
|
42
|
+
<XIcon className="text-gray-11 h-4 w-4" />
|
|
43
|
+
</Button>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function ToastIcon({ variant }: { variant: ToastProps["variant"] }) {
|
|
49
|
+
if (variant === "neutral") {
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
{variant === "success" && (
|
|
56
|
+
<CircleCheckIcon className="text-success-9 size-5" />
|
|
57
|
+
)}
|
|
58
|
+
{variant === "error" && <CircleXIcon className="text-error-9 size-5" />}
|
|
59
|
+
{variant === "info" && <InfoIcon className="text-info-9 size-5" />}
|
|
60
|
+
{variant === "warning" && (
|
|
61
|
+
<AlertTriangleIcon className="text-warning-9 size-5" />
|
|
62
|
+
)}
|
|
63
|
+
</>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createToast(variant: ToastProps["variant"]) {
|
|
68
|
+
return (
|
|
69
|
+
props: Omit<ToastProps, "id" | "variant">,
|
|
70
|
+
options: Pick<ToastT, "position" | "duration"> = {}
|
|
71
|
+
) => {
|
|
72
|
+
return sonnerToast.custom(
|
|
73
|
+
(id) => <Toast id={id} variant={variant} {...props} />,
|
|
74
|
+
{
|
|
75
|
+
position: "bottom-right",
|
|
76
|
+
...options,
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const success = createToast("success")
|
|
83
|
+
const error = createToast("error")
|
|
84
|
+
const info = createToast("info")
|
|
85
|
+
const warning = createToast("warning")
|
|
86
|
+
const neutral = createToast("neutral")
|
|
87
|
+
|
|
88
|
+
const toast = {
|
|
89
|
+
success,
|
|
90
|
+
error,
|
|
91
|
+
info,
|
|
92
|
+
warning,
|
|
93
|
+
neutral,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { toast, Toaster }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cn } from "@eggspot/ui/lib/utils"
|
|
2
|
+
|
|
3
|
+
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
fill="none"
|
|
8
|
+
aria-hidden="true"
|
|
9
|
+
className={cn("size-5 animate-spin", className)}
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
<circle
|
|
14
|
+
cx="12"
|
|
15
|
+
cy="12"
|
|
16
|
+
r="10"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
strokeWidth="4"
|
|
19
|
+
className="opacity-25"
|
|
20
|
+
></circle>
|
|
21
|
+
<path
|
|
22
|
+
fill="currentColor"
|
|
23
|
+
d="M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12zm2 5.291A7.96 7.96 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938z"
|
|
24
|
+
className="opacity-75"
|
|
25
|
+
></path>
|
|
26
|
+
</svg>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { Spinner }
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@eggspot/ui/lib/utils"
|
|
4
|
+
import {
|
|
5
|
+
Switch as AriaSwitch,
|
|
6
|
+
SwitchProps as AriaSwitchProps,
|
|
7
|
+
composeRenderProps,
|
|
8
|
+
} from "react-aria-components"
|
|
9
|
+
|
|
10
|
+
const Switch = ({ children, className, ...props }: AriaSwitchProps) => (
|
|
11
|
+
<AriaSwitch
|
|
12
|
+
className={composeRenderProps(className, (className) =>
|
|
13
|
+
cn(
|
|
14
|
+
"group inline-flex items-center gap-2 text-sm leading-none font-medium data-[disabled]:cursor-not-allowed data-[disabled]:opacity-70",
|
|
15
|
+
className
|
|
16
|
+
)
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
{composeRenderProps(children, (children) => (
|
|
21
|
+
<>
|
|
22
|
+
<div
|
|
23
|
+
className={cn(
|
|
24
|
+
"peer border-gray-7 inline-flex h-5.5 w-11 shrink-0 cursor-pointer items-center rounded-full border transition-colors",
|
|
25
|
+
/* Focus Visible */
|
|
26
|
+
"group-data-[focus-visible]:ring-ring group-data-[focus-visible]:ring-offset-gray-1 group-data-[focus-visible]:ring-2 group-data-[focus-visible]:ring-offset-2 group-data-[focus-visible]:outline-none",
|
|
27
|
+
/* Disabled */
|
|
28
|
+
"group-data-disabled:cursor-not-allowed group-data-disabled:opacity-50",
|
|
29
|
+
/* Selected */
|
|
30
|
+
"bg-gray-3 group-data-selected:bg-accent-9 group-data-selected:border-accent-9",
|
|
31
|
+
/* Readonly */
|
|
32
|
+
"group-data-readonly:cursor-default",
|
|
33
|
+
/* Resets */
|
|
34
|
+
"focus-visible:outline-none"
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
<div
|
|
38
|
+
className={cn(
|
|
39
|
+
"bg-gray-9 pointer-events-none block size-4 rounded-full shadow-lg ring-0 transition-transform",
|
|
40
|
+
/* Selected */
|
|
41
|
+
"group-data-selected:bg-accent-contrast translate-x-[3px] group-data-selected:translate-x-[24px]"
|
|
42
|
+
)}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
{children}
|
|
46
|
+
</>
|
|
47
|
+
))}
|
|
48
|
+
</AriaSwitch>
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
export { Switch }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cn } from "@eggspot/ui/lib/utils"
|
|
2
|
+
import { cva, VariantProps } from "class-variance-authority"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
const textVariants = cva("", {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
body1: "text-base",
|
|
9
|
+
body2: "text-sm",
|
|
10
|
+
caption: "text-xs",
|
|
11
|
+
overline: "text-gray-11 text-xs",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
variant: "body1",
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
interface TextProps
|
|
19
|
+
extends React.ComponentProps<"p">,
|
|
20
|
+
VariantProps<typeof textVariants> {
|
|
21
|
+
asChild?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function Text({
|
|
25
|
+
className,
|
|
26
|
+
asChild = false,
|
|
27
|
+
variant,
|
|
28
|
+
...props
|
|
29
|
+
}: TextProps) {
|
|
30
|
+
const Comp = asChild ? Slot.Root : "p"
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Comp className={cn(textVariants({ variant, className }))} {...props} />
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React from "react"
|
|
4
|
+
import { cva } from "class-variance-authority"
|
|
5
|
+
import {
|
|
6
|
+
Tooltip as AriaTooltip,
|
|
7
|
+
TooltipProps as AriaTooltipProps,
|
|
8
|
+
TooltipTrigger as AriaTooltipTrigger,
|
|
9
|
+
composeRenderProps,
|
|
10
|
+
OverlayArrow,
|
|
11
|
+
} from "react-aria-components"
|
|
12
|
+
|
|
13
|
+
export const TooltipTrigger = AriaTooltipTrigger
|
|
14
|
+
|
|
15
|
+
export interface TooltipProps extends Omit<AriaTooltipProps, "children"> {
|
|
16
|
+
children: React.ReactNode
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const styles = cva(
|
|
20
|
+
[
|
|
21
|
+
"bg-gray-2 max-w-lg",
|
|
22
|
+
"group rounded-md border px-2 py-1 text-sm drop-shadow-lg will-change-transform",
|
|
23
|
+
],
|
|
24
|
+
{
|
|
25
|
+
variants: {
|
|
26
|
+
isEntering: {
|
|
27
|
+
true: 'animate-in fade-in data-[placement="bottom"]:slide-in-from-top-20 data-[placement="top"]:slide-in-from-bottom-20 data-[placement="left"]:slide-in-from-right-20 data-[placement="right"]:slide-in-from-left-20 duration-200 ease-out',
|
|
28
|
+
},
|
|
29
|
+
isExiting: {
|
|
30
|
+
true: 'animate-out fade-out data-[placement="bottom"]:slide-out-to-top-20 data-[placement="top"]:slide-out-to-bottom-20 data-[placement="left"]:slide-out-to-right-20 data-[placement="right"]:slide-out-to-left-20 duration-150 ease-in',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
export function Tooltip({ children, ...props }: TooltipProps) {
|
|
37
|
+
return (
|
|
38
|
+
<AriaTooltip
|
|
39
|
+
{...props}
|
|
40
|
+
offset={10}
|
|
41
|
+
className={composeRenderProps(props.className, (className, renderProps) =>
|
|
42
|
+
styles({ ...renderProps, className })
|
|
43
|
+
)}
|
|
44
|
+
>
|
|
45
|
+
<OverlayArrow>
|
|
46
|
+
<svg
|
|
47
|
+
width={8}
|
|
48
|
+
height={8}
|
|
49
|
+
viewBox="0 0 8 8"
|
|
50
|
+
className='fill-gray-2 stroke-gray-6 group-data-[placement="bottom"]:rotate-180 group-data-[placement="left"]:-rotate-90 group-data-[placement="right"]:rotate-90'
|
|
51
|
+
>
|
|
52
|
+
<path d="M0 0 L4 4 L8 0" />
|
|
53
|
+
</svg>
|
|
54
|
+
</OverlayArrow>
|
|
55
|
+
{children}
|
|
56
|
+
</AriaTooltip>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
File without changes
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { clsx, type ClassValue } from "clsx"
|
|
2
|
+
import { twMerge } from "tailwind-merge"
|
|
3
|
+
|
|
4
|
+
export function cn(...inputs: ClassValue[]) {
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function formatCount(num: number, max = 9): string {
|
|
9
|
+
return num > max ? `${max}+` : num.toString()
|
|
10
|
+
}
|
package/tsconfig.json
ADDED