@inferencesh/ui 0.0.0-stage → 0.1.2
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/LICENSE +22 -0
- package/README.md +68 -2
- package/components.json +22 -0
- package/package.json +231 -4
- package/src/components/audio-player.tsx +549 -0
- package/src/components/button.tsx +13 -0
- package/src/components/chart.tsx +403 -0
- package/src/components/circuit.tsx +276 -0
- package/src/components/code-block/code-block.tsx +260 -0
- package/src/components/code-block/index.ts +18 -0
- package/src/components/code-block/languages.ts +311 -0
- package/src/components/code-block/styles.ts +39 -0
- package/src/components/code-block/tokenizer.ts +290 -0
- package/src/components/code-block/types.ts +38 -0
- package/src/components/code-block/utils.ts +39 -0
- package/src/components/code.tsx +48 -0
- package/src/components/cookie-consent.tsx +137 -0
- package/src/components/copy-button.tsx +44 -0
- package/src/components/country-dropdown.tsx +188 -0
- package/src/components/glow-loader-fast.tsx +32 -0
- package/src/components/glow-loader-mono.tsx +33 -0
- package/src/components/glow-loader-sm-fast.tsx +32 -0
- package/src/components/glow-loader-sm-mono.tsx +34 -0
- package/src/components/glow-loader-sm.tsx +32 -0
- package/src/components/glow-loader.tsx +32 -0
- package/src/components/glow-logo.tsx +32 -0
- package/src/components/gradient.tsx +80 -0
- package/src/components/index.ts +45 -0
- package/src/components/inline-sidebar.tsx +351 -0
- package/src/components/input-color.tsx +349 -0
- package/src/components/logo-base.tsx +213 -0
- package/src/components/logo-color.tsx +23 -0
- package/src/components/logo-full.tsx +71 -0
- package/src/components/logo-svg.tsx +23 -0
- package/src/components/menu-navigation.tsx +359 -0
- package/src/components/multi-select.tsx +721 -0
- package/src/components/pastel-gradient.tsx +25 -0
- package/src/components/pixel-symmetry.tsx +151 -0
- package/src/components/progress.tsx +28 -0
- package/src/components/scroll-more.tsx +131 -0
- package/src/components/select.tsx +85 -0
- package/src/components/shimmering-text.tsx +108 -0
- package/src/components/sidebar-light.tsx +102 -0
- package/src/components/sonner.tsx +38 -0
- package/src/components/theme-switcher-sidebar.tsx +56 -0
- package/src/components/theme-switcher-simple.tsx +110 -0
- package/src/components/theme-switcher.tsx +47 -0
- package/src/components/toggle-group.tsx +55 -0
- package/src/components/tooltip-button.tsx +91 -0
- package/src/components/tooltip.tsx +71 -0
- package/src/components/tree-view.tsx +499 -0
- package/src/components/unglow-loader.tsx +33 -0
- package/src/components/waveform.tsx +1632 -0
- package/src/components/zoomable-image.tsx +76 -0
- package/src/docs/api-docs.tsx +763 -0
- package/src/docs/callout.tsx +160 -0
- package/src/docs/code-group.tsx +215 -0
- package/src/docs/copy-menu.tsx +143 -0
- package/src/docs/doc-tabs.tsx +84 -0
- package/src/docs/index.ts +16 -0
- package/src/docs/steps.tsx +105 -0
- package/src/docs/table-of-contents.tsx +174 -0
- package/src/examples/guide-markdown.ts +129 -0
- package/src/examples/index.ts +1153 -0
- package/src/global.d.ts +1 -0
- package/src/hooks/use-copy-to-clipboard.ts +36 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/display-name.ts +15 -0
- package/src/lib/example-input.ts +130 -0
- package/src/lib/plans.ts +44 -0
- package/src/lib/safe-content.ts +137 -0
- package/src/lib/schema.ts +320 -0
- package/src/lib/storage.ts +108 -0
- package/src/markdown/docs-markdown-renderer.tsx +518 -0
- package/src/markdown/helpers.ts +95 -0
- package/src/markdown/index.ts +24 -0
- package/src/markdown/markdown-renderer.tsx +232 -0
- package/src/markdown/youtube-embed.tsx +43 -0
- package/src/og/image.ts +312 -0
- package/src/og/index.tsx +430 -0
- package/src/og/query.ts +26 -0
- package/src/shadcn/accordion.tsx +71 -0
- package/src/shadcn/alert-dialog.tsx +187 -0
- package/src/shadcn/alert.tsx +75 -0
- package/src/shadcn/aspect-ratio.tsx +22 -0
- package/src/shadcn/attachment.tsx +207 -0
- package/src/shadcn/avatar.tsx +106 -0
- package/src/shadcn/badge.tsx +51 -0
- package/src/shadcn/breadcrumb.tsx +124 -0
- package/src/shadcn/bubble.tsx +127 -0
- package/src/shadcn/button-group.tsx +87 -0
- package/src/shadcn/button.tsx +57 -0
- package/src/shadcn/calendar.tsx +219 -0
- package/src/shadcn/card.tsx +102 -0
- package/src/shadcn/carousel.tsx +242 -0
- package/src/shadcn/chart.tsx +372 -0
- package/src/shadcn/checkbox.tsx +28 -0
- package/src/shadcn/collapsible.tsx +19 -0
- package/src/shadcn/combobox.tsx +297 -0
- package/src/shadcn/command.tsx +194 -0
- package/src/shadcn/context-menu.tsx +270 -0
- package/src/shadcn/dialog.tsx +158 -0
- package/src/shadcn/direction.tsx +4 -0
- package/src/shadcn/drawer.tsx +227 -0
- package/src/shadcn/dropdown-menu.tsx +265 -0
- package/src/shadcn/empty.tsx +103 -0
- package/src/shadcn/field.tsx +238 -0
- package/src/shadcn/form.tsx +173 -0
- package/src/shadcn/hover-card.tsx +50 -0
- package/src/shadcn/index.ts +53 -0
- package/src/shadcn/input-group.tsx +156 -0
- package/src/shadcn/input-otp.tsx +84 -0
- package/src/shadcn/input.tsx +19 -0
- package/src/shadcn/item.tsx +201 -0
- package/src/shadcn/kbd.tsx +26 -0
- package/src/shadcn/label.tsx +19 -0
- package/src/shadcn/marker.tsx +70 -0
- package/src/shadcn/menubar.tsx +278 -0
- package/src/shadcn/message-scroller.tsx +131 -0
- package/src/shadcn/message.tsx +91 -0
- package/src/shadcn/native-select.tsx +60 -0
- package/src/shadcn/navigation-menu.tsx +167 -0
- package/src/shadcn/pagination.tsx +130 -0
- package/src/shadcn/popover.tsx +87 -0
- package/src/shadcn/progress.tsx +82 -0
- package/src/shadcn/radio-group.tsx +35 -0
- package/src/shadcn/resizable.tsx +49 -0
- package/src/shadcn/scroll-area.tsx +52 -0
- package/src/shadcn/select.tsx +200 -0
- package/src/shadcn/separator.tsx +22 -0
- package/src/shadcn/sheet.tsx +136 -0
- package/src/shadcn/sidebar.tsx +721 -0
- package/src/shadcn/skeleton.tsx +13 -0
- package/src/shadcn/slider.tsx +51 -0
- package/src/shadcn/sonner.tsx +49 -0
- package/src/shadcn/spinner.tsx +10 -0
- package/src/shadcn/switch.tsx +29 -0
- package/src/shadcn/table.tsx +115 -0
- package/src/shadcn/tabs.tsx +79 -0
- package/src/shadcn/textarea.tsx +17 -0
- package/src/shadcn/toggle-group.tsx +89 -0
- package/src/shadcn/toggle.tsx +44 -0
- package/src/shadcn/tooltip.tsx +63 -0
- package/src/theme/config.ts +48 -0
- package/src/theme/css/base.css +92 -0
- package/src/theme/css/bitboy.css +75 -0
- package/src/theme/css/dark.css +47 -0
- package/src/theme/css/designer.css +122 -0
- package/src/theme/css/fonts.css +33 -0
- package/src/theme/css/globals.css +14 -0
- package/src/theme/css/hackintosh.css +57 -0
- package/src/theme/css/llama.css +103 -0
- package/src/theme/css/safelist.css +39 -0
- package/src/theme/css/shadcn.css +77 -0
- package/src/theme/css/theme.css +216 -0
- package/src/theme/embed-theme.ts +146 -0
- package/src/theme/fonts/FiraCode-VF.woff2 +0 -0
- package/src/theme/fonts/Hack-Regular.woff2 +0 -0
- package/src/theme/fonts/LICENSE-FiraCode.txt +93 -0
- package/src/theme/fonts/LICENSE-Hack.txt +45 -0
- package/src/theme/fonts/LICENSE-MonaSans.txt +93 -0
- package/src/theme/fonts/Mona-Sans.woff2 +0 -0
- package/src/theme/index.ts +15 -0
- package/src/utils/cn.ts +3 -0
- package/src/utils/index.ts +2 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Popover,
|
|
5
|
+
PopoverContent,
|
|
6
|
+
PopoverTrigger
|
|
7
|
+
} from "../shadcn/popover"
|
|
8
|
+
import {
|
|
9
|
+
SidebarMenu, SidebarMenuButton, SidebarMenuItem
|
|
10
|
+
} from "../shadcn/sidebar"
|
|
11
|
+
import { cn } from "cn"
|
|
12
|
+
import { themeConfig, menuThemeNames } from "../theme"
|
|
13
|
+
import { ChevronRight } from "lucide-react"
|
|
14
|
+
import { useTheme } from "next-themes"
|
|
15
|
+
|
|
16
|
+
export function ThemeSwitcherSidebar() {
|
|
17
|
+
const { theme, setTheme } = useTheme()
|
|
18
|
+
|
|
19
|
+
const config = themeConfig[theme as keyof typeof themeConfig] || themeConfig.system
|
|
20
|
+
const Icon = config.icon
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<SidebarMenu>
|
|
24
|
+
<SidebarMenuItem>
|
|
25
|
+
<Popover>
|
|
26
|
+
<PopoverTrigger render={<SidebarMenuButton className="group w-full cursor-pointer focus:!outline-none focus:!ring-0 select-none" tooltip="theme" />}>
|
|
27
|
+
<Icon style={{ width: "24px", height: "24px", strokeWidth: "1.0" }} />
|
|
28
|
+
<span>theme</span>
|
|
29
|
+
<ChevronRight className="ml-auto h-4 w-4 text-muted-foreground/50 transition-transform group-data-popup-open:rotate-90" />
|
|
30
|
+
</PopoverTrigger>
|
|
31
|
+
<PopoverContent
|
|
32
|
+
side="right"
|
|
33
|
+
className="w-48 p-1"
|
|
34
|
+
>
|
|
35
|
+
<div className="grid gap-1">
|
|
36
|
+
{menuThemeNames.map(key => ({ key, ...themeConfig[key] })).map(({ key, icon: ThemeIcon, label, iconClassName }) => (
|
|
37
|
+
<button
|
|
38
|
+
key={key}
|
|
39
|
+
onClick={() => setTheme(key)}
|
|
40
|
+
className={cn(
|
|
41
|
+
"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
42
|
+
"hover:bg-accent hover:text-accent-foreground cursor-pointer",
|
|
43
|
+
theme === key && "bg-accent text-accent-foreground"
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<ThemeIcon className={cn("h-4 w-4", iconClassName)} />
|
|
47
|
+
{label}
|
|
48
|
+
</button>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
</PopoverContent>
|
|
52
|
+
</Popover>
|
|
53
|
+
</SidebarMenuItem>
|
|
54
|
+
</SidebarMenu>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Button } from "../shadcn/button"
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuRadioGroup,
|
|
8
|
+
DropdownMenuRadioItem,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
} from "../shadcn/dropdown-menu"
|
|
11
|
+
import { cn } from "cn"
|
|
12
|
+
import { themeConfig, menuThemeNames } from "../theme"
|
|
13
|
+
import { Laptop, Moon, Sun, SunMoon } from "lucide-react"
|
|
14
|
+
import { useTheme } from "next-themes"
|
|
15
|
+
import { useEffect, useState } from "react"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ThemeSwitcherSimple - Button-style theme switcher (for footer/standalone use)
|
|
19
|
+
* Does not require SidebarProvider
|
|
20
|
+
*/
|
|
21
|
+
export function ThemeSwitcherSimple() {
|
|
22
|
+
const [mounted, setMounted] = useState(false)
|
|
23
|
+
const { theme, setTheme } = useTheme()
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setMounted(true)
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
if (!mounted) {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const ICON_SIZE = 16
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<DropdownMenu>
|
|
37
|
+
<DropdownMenuTrigger render={<Button variant="ghost" size="sm" aria-label="Toggle theme" />}>
|
|
38
|
+
{theme === "light" ? (
|
|
39
|
+
<Sun key="light" size={ICON_SIZE} className="text-muted-foreground" />
|
|
40
|
+
) : theme === "dark" ? (
|
|
41
|
+
<Moon key="dark" size={ICON_SIZE} className="text-muted-foreground" />
|
|
42
|
+
) : (
|
|
43
|
+
<Laptop key="system" size={ICON_SIZE} className="text-muted-foreground" />
|
|
44
|
+
)}
|
|
45
|
+
</DropdownMenuTrigger>
|
|
46
|
+
<DropdownMenuContent className="w-content" align="start">
|
|
47
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
48
|
+
<DropdownMenuRadioItem className="flex gap-2" value="light">
|
|
49
|
+
<Sun size={ICON_SIZE} className="text-muted-foreground" /> <span>light</span>
|
|
50
|
+
</DropdownMenuRadioItem>
|
|
51
|
+
<DropdownMenuRadioItem className="flex gap-2" value="dark">
|
|
52
|
+
<Moon size={ICON_SIZE} className="text-muted-foreground" /> <span>dark</span>
|
|
53
|
+
</DropdownMenuRadioItem>
|
|
54
|
+
</DropdownMenuRadioGroup>
|
|
55
|
+
</DropdownMenuContent>
|
|
56
|
+
</DropdownMenu>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* ThemeSwitcherCompact - Compact icon-only theme switcher (for navbar use)
|
|
62
|
+
* Does not require SidebarProvider
|
|
63
|
+
*/
|
|
64
|
+
export function ThemeSwitcherCompact() {
|
|
65
|
+
const [mounted, setMounted] = useState(false)
|
|
66
|
+
const { theme, setTheme } = useTheme()
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
setMounted(true)
|
|
70
|
+
}, [])
|
|
71
|
+
|
|
72
|
+
if (!mounted) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
role="button"
|
|
76
|
+
tabIndex={0}
|
|
77
|
+
aria-label="Toggle theme"
|
|
78
|
+
className="w-8 h-8 flex items-center justify-center p-0 rounded-md transition-colors"
|
|
79
|
+
>
|
|
80
|
+
<div className="w-5 h-5 opacity-0" />
|
|
81
|
+
</div>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<DropdownMenu>
|
|
87
|
+
<DropdownMenuTrigger>
|
|
88
|
+
<div
|
|
89
|
+
role="button"
|
|
90
|
+
tabIndex={0}
|
|
91
|
+
aria-label="Toggle theme"
|
|
92
|
+
className="w-8 h-8 flex items-center justify-center p-0 rounded-md transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer focus:ring-0 focus:outline-none"
|
|
93
|
+
>
|
|
94
|
+
<SunMoon className="w-5 h-5" />
|
|
95
|
+
</div>
|
|
96
|
+
</DropdownMenuTrigger>
|
|
97
|
+
<DropdownMenuContent className="w-[150px]" align="start">
|
|
98
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
99
|
+
{menuThemeNames.map(key => ({ key, ...themeConfig[key] })).map(({ key, icon: Icon, label, iconClassName }) => (
|
|
100
|
+
<DropdownMenuRadioItem key={key} className="flex gap-2" value={key}>
|
|
101
|
+
<Icon className={cn("w-4 h-4", iconClassName)} />
|
|
102
|
+
<span>{label}</span>
|
|
103
|
+
</DropdownMenuRadioItem>
|
|
104
|
+
))}
|
|
105
|
+
</DropdownMenuRadioGroup>
|
|
106
|
+
</DropdownMenuContent>
|
|
107
|
+
</DropdownMenu>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DropdownMenu,
|
|
3
|
+
DropdownMenuContent,
|
|
4
|
+
DropdownMenuRadioGroup,
|
|
5
|
+
DropdownMenuRadioItem,
|
|
6
|
+
DropdownMenuTrigger
|
|
7
|
+
} from "../shadcn/dropdown-menu"
|
|
8
|
+
import { SidebarMenuButton } from "../shadcn/sidebar"
|
|
9
|
+
import { cn } from "cn"
|
|
10
|
+
import { themeConfig, menuThemeNames } from "../theme"
|
|
11
|
+
import { MoreHorizontal } from "lucide-react"
|
|
12
|
+
import { useTheme } from "next-themes"
|
|
13
|
+
|
|
14
|
+
interface ThemeSwitcherProps {
|
|
15
|
+
isMobile?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function ThemeSwitcher({ isMobile }: ThemeSwitcherProps) {
|
|
19
|
+
const { theme, setTheme } = useTheme()
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<DropdownMenu>
|
|
23
|
+
<DropdownMenuTrigger render={<SidebarMenuButton className="data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground" />}>
|
|
24
|
+
{(() => {
|
|
25
|
+
const config = themeConfig[theme as keyof typeof themeConfig] || themeConfig.system
|
|
26
|
+
const Icon = config.icon
|
|
27
|
+
return <Icon className={cn("w-4 h-4 mr-2", config.iconClassName)} />
|
|
28
|
+
})()}
|
|
29
|
+
theme <MoreHorizontal className="ml-auto" />
|
|
30
|
+
</DropdownMenuTrigger>
|
|
31
|
+
<DropdownMenuContent
|
|
32
|
+
side={isMobile ? "bottom" : "right"}
|
|
33
|
+
align={isMobile ? "end" : "start"}
|
|
34
|
+
className="min-w-56 rounded-lg"
|
|
35
|
+
>
|
|
36
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
37
|
+
{menuThemeNames.map(key => ({ key, ...themeConfig[key] })).map(({ key, icon: Icon, label, iconClassName }) => (
|
|
38
|
+
<DropdownMenuRadioItem key={key} className="flex gap-2" value={key}>
|
|
39
|
+
<Icon className={cn("w-4 h-4", iconClassName)} />
|
|
40
|
+
<span>{label}</span>
|
|
41
|
+
</DropdownMenuRadioItem>
|
|
42
|
+
))}
|
|
43
|
+
</DropdownMenuRadioGroup>
|
|
44
|
+
</DropdownMenuContent>
|
|
45
|
+
</DropdownMenu>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { ToggleGroup as ToggleGroupBase } from "../shadcn/toggle-group"
|
|
4
|
+
|
|
5
|
+
export { ToggleGroupItem } from "../shadcn/toggle-group"
|
|
6
|
+
|
|
7
|
+
// The shadcn toggle group with a `type`: "single" takes and gives one value,
|
|
8
|
+
// "multiple" an array, as the call sites here are written. Base UI's group
|
|
9
|
+
// (and so the shadcn one) always holds an array. ui/shadcn/toggle-group.tsx
|
|
10
|
+
// stays as the CLI writes it.
|
|
11
|
+
|
|
12
|
+
type BaseProps = Omit<React.ComponentProps<typeof ToggleGroupBase>, "value" | "defaultValue" | "onValueChange" | "multiple">
|
|
13
|
+
|
|
14
|
+
type ToggleGroupSingleProps<T extends string> = BaseProps & {
|
|
15
|
+
type: "single"
|
|
16
|
+
value?: T
|
|
17
|
+
defaultValue?: T
|
|
18
|
+
onValueChange?: (value: T) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type ToggleGroupMultipleProps<T extends string> = BaseProps & {
|
|
22
|
+
type?: "multiple"
|
|
23
|
+
value?: T[]
|
|
24
|
+
defaultValue?: T[]
|
|
25
|
+
onValueChange?: (value: T[]) => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ToggleGroupProps<T extends string> = ToggleGroupSingleProps<T> | ToggleGroupMultipleProps<T>
|
|
29
|
+
|
|
30
|
+
export function ToggleGroup<T extends string>({ type, value, defaultValue, onValueChange, ...props }: ToggleGroupProps<T>) {
|
|
31
|
+
const single = type === "single"
|
|
32
|
+
const groupValue = single ? (value !== undefined ? [value as T] : undefined) : (value as T[] | undefined)
|
|
33
|
+
const groupDefault = single ? (defaultValue !== undefined ? [defaultValue as T] : undefined) : (defaultValue as T[] | undefined)
|
|
34
|
+
const onGroupChange = (next: unknown[]) => {
|
|
35
|
+
if (!onValueChange) return
|
|
36
|
+
if (single) {
|
|
37
|
+
// Pressing the pressed item leaves the group empty: the single stays.
|
|
38
|
+
const last = next[next.length - 1] as T | undefined
|
|
39
|
+
if (last !== undefined) (onValueChange as (v: T) => void)(last)
|
|
40
|
+
} else {
|
|
41
|
+
;(onValueChange as (v: T[]) => void)(next as T[])
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ToggleGroupBase
|
|
47
|
+
// Without a type the group is Base UI's: one pressed item, array value.
|
|
48
|
+
multiple={type === "multiple" || undefined}
|
|
49
|
+
value={groupValue}
|
|
50
|
+
defaultValue={groupDefault}
|
|
51
|
+
onValueChange={onGroupChange}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { cn } from "cn"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import {
|
|
5
|
+
Tooltip,
|
|
6
|
+
TooltipContent,
|
|
7
|
+
TooltipProvider,
|
|
8
|
+
TooltipTrigger
|
|
9
|
+
} from "./tooltip"
|
|
10
|
+
|
|
11
|
+
const buttonVariants = cva(
|
|
12
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
13
|
+
{
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
default:
|
|
17
|
+
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
18
|
+
destructive:
|
|
19
|
+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
20
|
+
outline:
|
|
21
|
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
22
|
+
secondary:
|
|
23
|
+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
24
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
25
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
26
|
+
},
|
|
27
|
+
size: {
|
|
28
|
+
default: "h-9 px-4 py-2",
|
|
29
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
30
|
+
lg: "h-10 rounded-md px-8",
|
|
31
|
+
icon: "h-9 w-9",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: "default",
|
|
36
|
+
size: "default",
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
interface TooltipButtonBaseProps
|
|
42
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
43
|
+
VariantProps<typeof buttonVariants> {}
|
|
44
|
+
|
|
45
|
+
export interface TooltipButtonProps extends TooltipButtonBaseProps {
|
|
46
|
+
tooltipText: string
|
|
47
|
+
delay?: number
|
|
48
|
+
icon?: React.ReactNode
|
|
49
|
+
onCopy?: () => void
|
|
50
|
+
render?: React.ReactElement<{ className?: string }>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const TooltipButton = React.forwardRef<HTMLButtonElement, TooltipButtonProps>(
|
|
54
|
+
({
|
|
55
|
+
className,
|
|
56
|
+
variant,
|
|
57
|
+
size,
|
|
58
|
+
tooltipText,
|
|
59
|
+
delay = 300,
|
|
60
|
+
icon,
|
|
61
|
+
onCopy,
|
|
62
|
+
render,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}, ref) => {
|
|
66
|
+
const triggerElement = render
|
|
67
|
+
? React.cloneElement(render, {
|
|
68
|
+
className: cn(buttonVariants({ variant, size, className }), "cursor-pointer", render.props.className),
|
|
69
|
+
})
|
|
70
|
+
: <button
|
|
71
|
+
className={cn(buttonVariants({ variant, size, className }), "cursor-pointer")}
|
|
72
|
+
onClick={onCopy}
|
|
73
|
+
ref={ref}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
return (
|
|
77
|
+
<TooltipProvider delay={delay}>
|
|
78
|
+
<Tooltip>
|
|
79
|
+
<TooltipTrigger render={triggerElement}>
|
|
80
|
+
{icon || children}
|
|
81
|
+
</TooltipTrigger>
|
|
82
|
+
<TooltipContent>{tooltipText}</TooltipContent>
|
|
83
|
+
</Tooltip>
|
|
84
|
+
</TooltipProvider>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
TooltipButton.displayName = "TooltipButton"
|
|
90
|
+
|
|
91
|
+
export { TooltipButton }
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
|
|
4
|
+
|
|
5
|
+
import { cn } from "cn"
|
|
6
|
+
|
|
7
|
+
function TooltipProvider({
|
|
8
|
+
delay = 0,
|
|
9
|
+
...props
|
|
10
|
+
}: TooltipPrimitive.Provider.Props) {
|
|
11
|
+
return (
|
|
12
|
+
<TooltipPrimitive.Provider
|
|
13
|
+
data-slot="tooltip-provider"
|
|
14
|
+
delay={delay}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
|
|
21
|
+
return (
|
|
22
|
+
<TooltipProvider>
|
|
23
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
24
|
+
</TooltipProvider>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
|
|
29
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function TooltipContent({
|
|
33
|
+
className,
|
|
34
|
+
sideOffset = 0,
|
|
35
|
+
side = "top",
|
|
36
|
+
align = "center",
|
|
37
|
+
alignOffset = 0,
|
|
38
|
+
children,
|
|
39
|
+
...props
|
|
40
|
+
}: TooltipPrimitive.Popup.Props &
|
|
41
|
+
Pick<
|
|
42
|
+
TooltipPrimitive.Positioner.Props,
|
|
43
|
+
"align" | "alignOffset" | "side" | "sideOffset"
|
|
44
|
+
>) {
|
|
45
|
+
return (
|
|
46
|
+
<TooltipPrimitive.Portal>
|
|
47
|
+
<TooltipPrimitive.Positioner
|
|
48
|
+
align={align}
|
|
49
|
+
alignOffset={alignOffset}
|
|
50
|
+
side={side}
|
|
51
|
+
sideOffset={sideOffset}
|
|
52
|
+
positionMethod="fixed"
|
|
53
|
+
className="isolate z-50"
|
|
54
|
+
>
|
|
55
|
+
<TooltipPrimitive.Popup
|
|
56
|
+
data-slot="tooltip-content"
|
|
57
|
+
className={cn(
|
|
58
|
+
"bg-background text-foreground border border-border z-50 w-fit rounded-md px-2 py-1.5 text-xs text-balance origin-(--transform-origin) 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 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",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
<TooltipPrimitive.Arrow className="bg-transparent fill-transparent z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
|
65
|
+
</TooltipPrimitive.Popup>
|
|
66
|
+
</TooltipPrimitive.Positioner>
|
|
67
|
+
</TooltipPrimitive.Portal>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|