@octanejs/shadcn 0.0.1
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 +21 -0
- package/README.md +43 -0
- package/package.json +63 -0
- package/src/hooks/use-mobile.ts +23 -0
- package/src/index.ts +263 -0
- package/src/lib/types.ts +10 -0
- package/src/lib/utils.ts +8 -0
- package/src/styles/theme.css +104 -0
- package/src/ui/accordion.tsrx +72 -0
- package/src/ui/alert-dialog.tsrx +161 -0
- package/src/ui/alert.tsrx +69 -0
- package/src/ui/aspect-ratio.tsrx +10 -0
- package/src/ui/avatar.tsrx +79 -0
- package/src/ui/badge.tsrx +50 -0
- package/src/ui/breadcrumb.tsrx +89 -0
- package/src/ui/button.tsrx +71 -0
- package/src/ui/card.tsrx +75 -0
- package/src/ui/checkbox.tsrx +31 -0
- package/src/ui/collapsible.tsrx +21 -0
- package/src/ui/context-menu.tsrx +179 -0
- package/src/ui/dialog.tsrx +133 -0
- package/src/ui/dropdown-menu.tsrx +189 -0
- package/src/ui/empty.tsrx +86 -0
- package/src/ui/field.tsrx +188 -0
- package/src/ui/hover-card.tsrx +48 -0
- package/src/ui/input.tsrx +18 -0
- package/src/ui/item.tsrx +171 -0
- package/src/ui/kbd.tsrx +26 -0
- package/src/ui/label.tsrx +21 -0
- package/src/ui/menubar.tsrx +198 -0
- package/src/ui/native-select.tsrx +55 -0
- package/src/ui/navigation-menu.tsrx +116 -0
- package/src/ui/pagination.tsrx +113 -0
- package/src/ui/popover.tsrx +73 -0
- package/src/ui/progress.tsrx +27 -0
- package/src/ui/radio-group.tsrx +37 -0
- package/src/ui/scroll-area.tsrx +43 -0
- package/src/ui/select.tsrx +165 -0
- package/src/ui/separator.tsrx +30 -0
- package/src/ui/sheet.tsrx +114 -0
- package/src/ui/sidebar.tsrx +661 -0
- package/src/ui/skeleton.tsrx +14 -0
- package/src/ui/slider.tsrx +69 -0
- package/src/ui/sonner.tsrx +45 -0
- package/src/ui/spinner.tsrx +23 -0
- package/src/ui/switch.tsrx +30 -0
- package/src/ui/table.tsrx +80 -0
- package/src/ui/tabs.tsrx +69 -0
- package/src/ui/textarea.tsrx +20 -0
- package/src/ui/toggle-group.tsrx +100 -0
- package/src/ui/toggle.tsrx +47 -0
- package/src/ui/tooltip.tsrx +65 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/slider.tsx (the `"use client"` directive is
|
|
3
|
+
// dropped — octane has no RSC axis).
|
|
4
|
+
//
|
|
5
|
+
// The Track/Range/Thumb tree is composed with createElement: upstream renders
|
|
6
|
+
// one Thumb per entry of `_values` via an array map, and mapped/prop-position
|
|
7
|
+
// descriptors are the octane channel for computed children (see
|
|
8
|
+
// breadcrumb.tsrx's comment on opaque compiled children).
|
|
9
|
+
import { createElement, useMemo } from 'octane';
|
|
10
|
+
import { Slider as SliderPrimitive } from '@octanejs/radix';
|
|
11
|
+
|
|
12
|
+
import { cn } from '../lib/utils';
|
|
13
|
+
|
|
14
|
+
export interface SliderProps extends Record<string, unknown> {
|
|
15
|
+
className?: string;
|
|
16
|
+
defaultValue?: number[];
|
|
17
|
+
value?: number[];
|
|
18
|
+
min?: number;
|
|
19
|
+
max?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Slider({
|
|
23
|
+
className,
|
|
24
|
+
defaultValue,
|
|
25
|
+
value,
|
|
26
|
+
min = 0,
|
|
27
|
+
max = 100,
|
|
28
|
+
...props
|
|
29
|
+
}: SliderProps) {
|
|
30
|
+
const _values = useMemo(
|
|
31
|
+
() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
|
|
32
|
+
[value, defaultValue, min, max],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return createElement(
|
|
36
|
+
SliderPrimitive.Root,
|
|
37
|
+
{
|
|
38
|
+
'data-slot': 'slider',
|
|
39
|
+
defaultValue,
|
|
40
|
+
value,
|
|
41
|
+
min,
|
|
42
|
+
max,
|
|
43
|
+
className: cn(
|
|
44
|
+
'relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col',
|
|
45
|
+
className,
|
|
46
|
+
),
|
|
47
|
+
...props,
|
|
48
|
+
},
|
|
49
|
+
createElement(
|
|
50
|
+
SliderPrimitive.Track,
|
|
51
|
+
{
|
|
52
|
+
'data-slot': 'slider-track',
|
|
53
|
+
className: 'relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5',
|
|
54
|
+
},
|
|
55
|
+
createElement(SliderPrimitive.Range, {
|
|
56
|
+
'data-slot': 'slider-range',
|
|
57
|
+
className: 'absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full',
|
|
58
|
+
}),
|
|
59
|
+
),
|
|
60
|
+
...Array.from(
|
|
61
|
+
{ length: _values.length },
|
|
62
|
+
(_, index) => createElement(SliderPrimitive.Thumb, {
|
|
63
|
+
'data-slot': 'slider-thumb',
|
|
64
|
+
key: index,
|
|
65
|
+
className: 'block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50',
|
|
66
|
+
}),
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/sonner.tsx (the `"use client"` directive is
|
|
3
|
+
// dropped — octane has no RSC axis). IconPlaceholder resolves to lucide (see
|
|
4
|
+
// spinner.tsrx).
|
|
5
|
+
//
|
|
6
|
+
// OCTANE DIVERGENCE: upstream reads the theme from next-themes' useTheme()
|
|
7
|
+
// (Next.js-specific); here `theme` is an ordinary prop with upstream's
|
|
8
|
+
// 'system' default — pass your app's theme source explicitly. The icon
|
|
9
|
+
// descriptors are composed with createElement (they travel through a props
|
|
10
|
+
// object, the documented channel for element descriptors).
|
|
11
|
+
import { createElement } from 'octane';
|
|
12
|
+
import { Toaster as Sonner, type ToasterProps } from '@octanejs/sonner';
|
|
13
|
+
import {
|
|
14
|
+
CircleCheckIcon,
|
|
15
|
+
InfoIcon,
|
|
16
|
+
Loader2Icon,
|
|
17
|
+
OctagonXIcon,
|
|
18
|
+
TriangleAlertIcon,
|
|
19
|
+
} from '@octanejs/lucide';
|
|
20
|
+
|
|
21
|
+
export function Toaster({ theme = 'system', ...props }: ToasterProps) {
|
|
22
|
+
return createElement(Sonner, {
|
|
23
|
+
theme: theme as ToasterProps['theme'],
|
|
24
|
+
className: 'toaster group',
|
|
25
|
+
icons: {
|
|
26
|
+
success: createElement(CircleCheckIcon, { className: 'size-4' }),
|
|
27
|
+
info: createElement(InfoIcon, { className: 'size-4' }),
|
|
28
|
+
warning: createElement(TriangleAlertIcon, { className: 'size-4' }),
|
|
29
|
+
error: createElement(OctagonXIcon, { className: 'size-4' }),
|
|
30
|
+
loading: createElement(Loader2Icon, { className: 'size-4 animate-spin' }),
|
|
31
|
+
},
|
|
32
|
+
style: {
|
|
33
|
+
'--normal-bg': 'var(--popover)',
|
|
34
|
+
'--normal-text': 'var(--popover-foreground)',
|
|
35
|
+
'--normal-border': 'var(--border)',
|
|
36
|
+
'--border-radius': 'var(--radius)',
|
|
37
|
+
},
|
|
38
|
+
toastOptions: {
|
|
39
|
+
classNames: {
|
|
40
|
+
toast: 'cn-toast',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
...props,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/spinner.tsx.
|
|
3
|
+
//
|
|
4
|
+
// OCTANE DIVERGENCE: upstream's IconPlaceholder (the CLI-resolved iconLibrary
|
|
5
|
+
// axis) is resolved at port time to the default library, lucide, via
|
|
6
|
+
// @octanejs/lucide. Other icon libraries are a registry-emit concern.
|
|
7
|
+
import { Loader2Icon } from '@octanejs/lucide';
|
|
8
|
+
|
|
9
|
+
import { cn } from '../lib/utils';
|
|
10
|
+
|
|
11
|
+
export interface SpinnerProps extends Record<string, unknown> {
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function Spinner({ className, ...props }: SpinnerProps) @{
|
|
16
|
+
<Loader2Icon
|
|
17
|
+
data-slot="spinner"
|
|
18
|
+
role="status"
|
|
19
|
+
aria-label="Loading"
|
|
20
|
+
className={cn('size-4 animate-spin', className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Default-Tailwind switch flavor (package canonical) — utilities-inlined
|
|
2
|
+
// upstream styling. Octane adaptations: "use client" dropped, radix-ui →
|
|
3
|
+
// @octanejs/radix; pure template JSX.
|
|
4
|
+
import { Switch as SwitchPrimitive } from '@octanejs/radix';
|
|
5
|
+
|
|
6
|
+
import { cn } from '../lib/utils';
|
|
7
|
+
|
|
8
|
+
export interface SwitchProps extends Record<string, unknown> {
|
|
9
|
+
className?: string;
|
|
10
|
+
size?: 'sm' | 'default';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Switch({ className, size = 'default', ...props }: SwitchProps) @{
|
|
14
|
+
<SwitchPrimitive.Root
|
|
15
|
+
data-slot="switch"
|
|
16
|
+
data-size={size}
|
|
17
|
+
className={cn(
|
|
18
|
+
'peer group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80',
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
<SwitchPrimitive.Thumb
|
|
24
|
+
data-slot="switch-thumb"
|
|
25
|
+
className={cn(
|
|
26
|
+
'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 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground',
|
|
27
|
+
)}
|
|
28
|
+
/>
|
|
29
|
+
</SwitchPrimitive.Root>
|
|
30
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/table.tsx (the `"use client"` directive is
|
|
3
|
+
// dropped — octane has no RSC axis). Table renders inside the upstream
|
|
4
|
+
// table-container wrapper div.
|
|
5
|
+
import { cn } from '../lib/utils';
|
|
6
|
+
|
|
7
|
+
// Multi-host family (div/table/thead/tbody/tr/th/td/caption): no single host
|
|
8
|
+
// prop table applies, so the shared alias stays structural.
|
|
9
|
+
type Props = { className?: string } & Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
export function Table({ className, ...props }: Props) @{
|
|
12
|
+
<div data-slot="table-container" className="relative w-full overflow-x-auto">
|
|
13
|
+
<table
|
|
14
|
+
data-slot="table"
|
|
15
|
+
className={cn('w-full caption-bottom text-sm', className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function TableHeader({ className, ...props }: Props) @{
|
|
22
|
+
<thead data-slot="table-header" className={cn('[&_tr]:border-b', className)} {...props} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function TableBody({ className, ...props }: Props) @{
|
|
26
|
+
<tbody
|
|
27
|
+
data-slot="table-body"
|
|
28
|
+
className={cn('[&_tr:last-child]:border-0', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function TableFooter({ className, ...props }: Props) @{
|
|
34
|
+
<tfoot
|
|
35
|
+
data-slot="table-footer"
|
|
36
|
+
className={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function TableRow({ className, ...props }: Props) @{
|
|
42
|
+
<tr
|
|
43
|
+
data-slot="table-row"
|
|
44
|
+
className={cn(
|
|
45
|
+
'border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted',
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function TableHead({ className, ...props }: Props) @{
|
|
53
|
+
<th
|
|
54
|
+
data-slot="table-head"
|
|
55
|
+
className={cn(
|
|
56
|
+
'text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function TableCell({ className, ...props }: Props) @{
|
|
64
|
+
<td
|
|
65
|
+
data-slot="table-cell"
|
|
66
|
+
className={cn(
|
|
67
|
+
'p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
|
68
|
+
className,
|
|
69
|
+
)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function TableCaption({ className, ...props }: Props) @{
|
|
75
|
+
<caption
|
|
76
|
+
data-slot="table-caption"
|
|
77
|
+
className={cn('text-muted-foreground mt-4 text-sm', className)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
}
|
package/src/ui/tabs.tsrx
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Tabs — maintainer-supplied default-Tailwind flavor, class strings verbatim.
|
|
2
|
+
// Octane adaptations: "use client" dropped, radix-ui → @octanejs/radix, cva →
|
|
3
|
+
// class-variance-authority (unchanged).
|
|
4
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
|
+
import { Tabs as TabsPrimitive } from '@octanejs/radix';
|
|
6
|
+
|
|
7
|
+
import { cn } from '../lib/utils';
|
|
8
|
+
|
|
9
|
+
type Props = { className?: string } & Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
export function Tabs({ className, orientation = 'horizontal', ...props }: Props & {
|
|
12
|
+
orientation?: 'horizontal' | 'vertical';
|
|
13
|
+
}) @{
|
|
14
|
+
<TabsPrimitive.Root
|
|
15
|
+
data-slot="tabs"
|
|
16
|
+
data-orientation={orientation}
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
className={cn('group/tabs flex gap-2 data-horizontal:flex-col', className)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const tabsListVariants = cva(
|
|
24
|
+
'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',
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
variant: {
|
|
28
|
+
default: 'bg-muted',
|
|
29
|
+
line: 'gap-1 bg-transparent',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: {
|
|
33
|
+
variant: 'default',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export function TabsList({ className, variant = 'default', ...props }: Props & VariantProps<
|
|
39
|
+
typeof tabsListVariants
|
|
40
|
+
>) @{
|
|
41
|
+
<TabsPrimitive.List
|
|
42
|
+
data-slot="tabs-list"
|
|
43
|
+
data-variant={variant}
|
|
44
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function TabsTrigger({ className, ...props }: Props) @{
|
|
50
|
+
<TabsPrimitive.Trigger
|
|
51
|
+
data-slot="tabs-trigger"
|
|
52
|
+
className={cn(
|
|
53
|
+
'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',
|
|
54
|
+
'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',
|
|
55
|
+
'data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground',
|
|
56
|
+
'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',
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function TabsContent({ className, ...props }: Props) @{
|
|
64
|
+
<TabsPrimitive.Content
|
|
65
|
+
data-slot="tabs-content"
|
|
66
|
+
className={cn('flex-1 text-sm outline-none', className)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/textarea.tsx.
|
|
3
|
+
//
|
|
4
|
+
// OCTANE DIVERGENCE: per-keystroke handling is the native `onInput` event, not
|
|
5
|
+
// a synthetic `onChange`; native `change` keeps its commit-on-blur meaning.
|
|
6
|
+
import { cn } from '../lib/utils';
|
|
7
|
+
import type { HostProps } from '../lib/types';
|
|
8
|
+
|
|
9
|
+
export interface TextareaProps extends HostProps<'textarea'> {}
|
|
10
|
+
|
|
11
|
+
export function Textarea({ className, ...props }: TextareaProps) @{
|
|
12
|
+
<textarea
|
|
13
|
+
data-slot="textarea"
|
|
14
|
+
className={cn(
|
|
15
|
+
'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40',
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/toggle-group.tsx (the `"use client"` directive
|
|
3
|
+
// is dropped — octane has no RSC axis). React.createContext/useContext map onto
|
|
4
|
+
// octane's createContext/useContext.
|
|
5
|
+
//
|
|
6
|
+
// ToggleGroup is composed with createElement: the consumer's children must sit
|
|
7
|
+
// INSIDE the context Provider, and opaque compiled .tsrx children can only flow
|
|
8
|
+
// through the props.children channel (see breadcrumb.tsrx's comment).
|
|
9
|
+
import { createContext, createElement, useContext, type OctaneNode } from 'octane';
|
|
10
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
11
|
+
import { ToggleGroup as ToggleGroupPrimitive } from '@octanejs/radix';
|
|
12
|
+
|
|
13
|
+
import { cn } from '../lib/utils';
|
|
14
|
+
import { toggleVariants } from './toggle.tsrx';
|
|
15
|
+
|
|
16
|
+
const ToggleGroupContext = createContext<
|
|
17
|
+
VariantProps<typeof toggleVariants> & {
|
|
18
|
+
spacing?: number;
|
|
19
|
+
orientation?: 'horizontal' | 'vertical';
|
|
20
|
+
}
|
|
21
|
+
>({
|
|
22
|
+
size: 'default',
|
|
23
|
+
variant: 'default',
|
|
24
|
+
spacing: 2,
|
|
25
|
+
orientation: 'horizontal',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export interface ToggleGroupProps extends Record<string, unknown> {
|
|
29
|
+
className?: string;
|
|
30
|
+
variant?: VariantProps<typeof toggleVariants>['variant'];
|
|
31
|
+
size?: VariantProps<typeof toggleVariants>['size'];
|
|
32
|
+
spacing?: number;
|
|
33
|
+
orientation?: 'horizontal' | 'vertical';
|
|
34
|
+
children?: OctaneNode;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function ToggleGroup({
|
|
38
|
+
className,
|
|
39
|
+
variant,
|
|
40
|
+
size,
|
|
41
|
+
spacing = 2,
|
|
42
|
+
orientation = 'horizontal',
|
|
43
|
+
children,
|
|
44
|
+
...props
|
|
45
|
+
}: ToggleGroupProps) {
|
|
46
|
+
return createElement(
|
|
47
|
+
ToggleGroupPrimitive.Root,
|
|
48
|
+
{
|
|
49
|
+
'data-slot': 'toggle-group',
|
|
50
|
+
'data-variant': variant,
|
|
51
|
+
'data-size': size,
|
|
52
|
+
'data-spacing': spacing,
|
|
53
|
+
'data-orientation': orientation,
|
|
54
|
+
// Forwarded to the primitive: it drives RovingFocusGroup's arrow-key
|
|
55
|
+
// axis (a vertical group must ignore left/right and use up/down).
|
|
56
|
+
orientation,
|
|
57
|
+
style: { '--gap': spacing },
|
|
58
|
+
className: cn(
|
|
59
|
+
'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs',
|
|
60
|
+
className,
|
|
61
|
+
),
|
|
62
|
+
...props,
|
|
63
|
+
},
|
|
64
|
+
createElement(
|
|
65
|
+
ToggleGroupContext.Provider,
|
|
66
|
+
{ value: { variant, size, spacing, orientation } },
|
|
67
|
+
children,
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ToggleGroupItemProps extends Record<string, unknown> {
|
|
73
|
+
className?: string;
|
|
74
|
+
variant?: VariantProps<typeof toggleVariants>['variant'];
|
|
75
|
+
size?: VariantProps<typeof toggleVariants>['size'];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function ToggleGroupItem({
|
|
79
|
+
className,
|
|
80
|
+
variant = 'default',
|
|
81
|
+
size = 'default',
|
|
82
|
+
...props
|
|
83
|
+
}: ToggleGroupItemProps) @{
|
|
84
|
+
const context = useContext(ToggleGroupContext);
|
|
85
|
+
<ToggleGroupPrimitive.Item
|
|
86
|
+
data-slot="toggle-group-item"
|
|
87
|
+
data-variant={context.variant || variant}
|
|
88
|
+
data-size={context.size || size}
|
|
89
|
+
data-spacing={context.spacing}
|
|
90
|
+
className={cn(
|
|
91
|
+
'min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l',
|
|
92
|
+
toggleVariants({
|
|
93
|
+
variant: context.variant || variant,
|
|
94
|
+
size: context.size || size,
|
|
95
|
+
}),
|
|
96
|
+
className,
|
|
97
|
+
)}
|
|
98
|
+
{...props}
|
|
99
|
+
/>
|
|
100
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/toggle.tsx (the `"use client"` directive is
|
|
3
|
+
// dropped — octane has no RSC axis).
|
|
4
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
|
+
import { Toggle as TogglePrimitive } from '@octanejs/radix';
|
|
6
|
+
|
|
7
|
+
import { cn } from '../lib/utils';
|
|
8
|
+
|
|
9
|
+
export const toggleVariants = cva(
|
|
10
|
+
'inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: 'bg-transparent',
|
|
15
|
+
outline: 'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
default: 'h-9 min-w-9 px-2',
|
|
19
|
+
sm: 'h-8 min-w-8 px-1.5',
|
|
20
|
+
lg: 'h-10 min-w-10 px-2.5',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: 'default',
|
|
25
|
+
size: 'default',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export interface ToggleProps extends Record<string, unknown> {
|
|
31
|
+
className?: string;
|
|
32
|
+
variant?: VariantProps<typeof toggleVariants>['variant'];
|
|
33
|
+
size?: VariantProps<typeof toggleVariants>['size'];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Toggle({
|
|
37
|
+
className,
|
|
38
|
+
variant = 'default',
|
|
39
|
+
size = 'default',
|
|
40
|
+
...props
|
|
41
|
+
}: ToggleProps) @{
|
|
42
|
+
<TogglePrimitive.Root
|
|
43
|
+
data-slot="toggle"
|
|
44
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Ported from shadcn-ui/ui@4baadbc6517070ae8f8feb2c97037adc2b305544
|
|
2
|
+
// apps/v4/registry/bases/radix/ui/tooltip.tsx (the `"use client"` directive is
|
|
3
|
+
// dropped — octane has no RSC axis).
|
|
4
|
+
//
|
|
5
|
+
// TooltipContent renders Portal > Content + Arrow: the Portal's child must be
|
|
6
|
+
// a real element DESCRIPTOR (radix portals cannot enumerate opaque compiled
|
|
7
|
+
// .tsrx children), so the pair is composed with createElement. The consumer's
|
|
8
|
+
// children flow into the Content primitive through the ordinary props.children
|
|
9
|
+
// channel.
|
|
10
|
+
import { createElement, type OctaneNode } from 'octane';
|
|
11
|
+
import { Tooltip as TooltipPrimitive } from '@octanejs/radix';
|
|
12
|
+
|
|
13
|
+
import { cn } from '../lib/utils';
|
|
14
|
+
|
|
15
|
+
export interface TooltipProviderProps extends Record<string, unknown> {
|
|
16
|
+
delayDuration?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function TooltipProvider({ delayDuration = 0, ...props }: TooltipProviderProps) @{
|
|
20
|
+
<TooltipPrimitive.Provider
|
|
21
|
+
data-slot="tooltip-provider"
|
|
22
|
+
delayDuration={delayDuration}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function Tooltip(props: Record<string, unknown>) @{
|
|
28
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function TooltipTrigger(props: Record<string, unknown>) @{
|
|
32
|
+
<TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TooltipContentProps extends Record<string, unknown> {
|
|
36
|
+
className?: string;
|
|
37
|
+
sideOffset?: number;
|
|
38
|
+
children?: OctaneNode;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function TooltipContent({
|
|
42
|
+
className,
|
|
43
|
+
sideOffset = 0,
|
|
44
|
+
children,
|
|
45
|
+
...props
|
|
46
|
+
}: TooltipContentProps) {
|
|
47
|
+
return createElement(TooltipPrimitive.Portal, {
|
|
48
|
+
children: createElement(TooltipPrimitive.Content, {
|
|
49
|
+
'data-slot': 'tooltip-content',
|
|
50
|
+
sideOffset,
|
|
51
|
+
className: cn(
|
|
52
|
+
'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',
|
|
53
|
+
className,
|
|
54
|
+
),
|
|
55
|
+
...props,
|
|
56
|
+
children: [
|
|
57
|
+
children,
|
|
58
|
+
createElement(TooltipPrimitive.Arrow, {
|
|
59
|
+
key: 'arrow',
|
|
60
|
+
className: 'z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground',
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
}
|