@octanejs/shadcn 0.0.37 → 0.0.39
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 → LICENSE.upstream} +1 -1
- package/README.md +22 -19
- package/package.json +17 -11
- package/src/bases/base-ui/ui/accordion.tsrx +1 -1
- package/src/bases/base-ui/ui/alert-dialog.tsrx +1 -1
- package/src/bases/base-ui/ui/alert.tsrx +1 -1
- package/src/bases/base-ui/ui/aspect-ratio.tsrx +1 -1
- package/src/bases/base-ui/ui/avatar.tsrx +1 -1
- package/src/bases/base-ui/ui/badge.tsrx +1 -1
- package/src/bases/base-ui/ui/breadcrumb.tsrx +1 -1
- package/src/bases/base-ui/ui/button.tsrx +1 -1
- package/src/bases/base-ui/ui/card.tsrx +1 -1
- package/src/bases/base-ui/ui/checkbox.tsrx +1 -1
- package/src/bases/base-ui/ui/context-menu.tsrx +22 -17
- package/src/bases/base-ui/ui/dialog.tsrx +31 -40
- package/src/bases/base-ui/ui/dropdown-menu.tsrx +22 -17
- package/src/bases/base-ui/ui/empty.tsrx +1 -1
- package/src/bases/base-ui/ui/field.tsrx +1 -1
- package/src/bases/base-ui/ui/hover-card.tsrx +18 -16
- package/src/bases/base-ui/ui/input.tsrx +1 -1
- package/src/bases/base-ui/ui/item.tsrx +1 -1
- package/src/bases/base-ui/ui/kbd.tsrx +1 -1
- package/src/bases/base-ui/ui/label.tsrx +1 -1
- package/src/bases/base-ui/ui/menubar.tsrx +22 -17
- package/src/bases/base-ui/ui/native-select.tsrx +1 -1
- package/src/bases/base-ui/ui/navigation-menu.tsrx +137 -0
- package/src/bases/base-ui/ui/pagination.tsrx +1 -1
- package/src/bases/base-ui/ui/popover.tsrx +18 -16
- package/src/bases/base-ui/ui/progress.tsrx +1 -1
- package/src/bases/base-ui/ui/radio-group.tsrx +1 -1
- package/src/bases/base-ui/ui/scroll-area.tsrx +44 -0
- package/src/bases/base-ui/ui/select.tsrx +157 -0
- package/src/bases/base-ui/ui/separator.tsrx +1 -1
- package/src/bases/base-ui/ui/sheet.tsrx +1 -1
- package/src/bases/base-ui/ui/sidebar.tsrx +1 -1
- package/src/bases/base-ui/ui/skeleton.tsrx +1 -1
- package/src/bases/base-ui/ui/slider.tsrx +41 -52
- package/src/bases/base-ui/ui/spinner.tsrx +1 -1
- package/src/bases/base-ui/ui/switch.tsrx +1 -1
- package/src/bases/base-ui/ui/table.tsrx +1 -1
- package/src/bases/base-ui/ui/tabs.tsrx +8 -17
- package/src/bases/base-ui/ui/textarea.tsrx +1 -1
- package/src/bases/base-ui/ui/toggle-group.tsrx +22 -32
- package/src/bases/base-ui/ui/toggle.tsrx +1 -1
- package/src/bases/base-ui/ui/tooltip.tsrx +18 -16
- package/src/bases/radix/ui/accordion.tsrx +1 -1
- package/src/bases/radix/ui/alert-dialog.tsrx +1 -1
- package/src/bases/radix/ui/alert.tsrx +1 -1
- package/src/bases/radix/ui/avatar.tsrx +1 -1
- package/src/bases/radix/ui/badge.tsrx +1 -1
- package/src/bases/radix/ui/breadcrumb.tsrx +1 -1
- package/src/bases/radix/ui/button.tsrx +1 -1
- package/src/bases/radix/ui/card.tsrx +1 -1
- package/src/bases/radix/ui/checkbox.tsrx +1 -1
- package/src/bases/radix/ui/context-menu.tsrx +1 -1
- package/src/bases/radix/ui/dialog.tsrx +1 -1
- package/src/bases/radix/ui/dropdown-menu.tsrx +1 -1
- package/src/bases/radix/ui/empty.tsrx +1 -1
- package/src/bases/radix/ui/field.tsrx +1 -1
- package/src/bases/radix/ui/hover-card.tsrx +1 -1
- package/src/bases/radix/ui/input.tsrx +1 -1
- package/src/bases/radix/ui/item.tsrx +1 -1
- package/src/bases/radix/ui/kbd.tsrx +1 -1
- package/src/bases/radix/ui/label.tsrx +1 -1
- package/src/bases/radix/ui/menubar.tsrx +1 -1
- package/src/bases/radix/ui/native-select.tsrx +1 -1
- package/src/bases/radix/ui/navigation-menu.tsrx +1 -1
- package/src/bases/radix/ui/pagination.tsrx +1 -1
- package/src/bases/radix/ui/popover.tsrx +1 -1
- package/src/bases/radix/ui/progress.tsrx +1 -1
- package/src/bases/radix/ui/radio-group.tsrx +1 -1
- package/src/bases/radix/ui/scroll-area.tsrx +1 -1
- package/src/bases/radix/ui/select.tsrx +1 -1
- package/src/bases/radix/ui/separator.tsrx +1 -1
- package/src/bases/radix/ui/sheet.tsrx +1 -1
- package/src/bases/radix/ui/sidebar.tsrx +1 -1
- package/src/bases/radix/ui/skeleton.tsrx +1 -1
- package/src/bases/radix/ui/slider.tsrx +1 -1
- package/src/bases/radix/ui/spinner.tsrx +1 -1
- package/src/bases/radix/ui/switch.tsrx +1 -1
- package/src/bases/radix/ui/table.tsrx +1 -1
- package/src/bases/radix/ui/tabs.tsrx +1 -1
- package/src/bases/radix/ui/textarea.tsrx +1 -1
- package/src/bases/radix/ui/toggle-group.tsrx +1 -1
- package/src/bases/radix/ui/toggle.tsrx +1 -1
- package/src/bases/radix/ui/tooltip.tsrx +1 -1
- package/src/bases/react-aria/ui/accordion.tsrx +1 -1
- package/src/bases/react-aria/ui/alert-dialog.tsrx +1 -1
- package/src/bases/react-aria/ui/alert.tsrx +1 -1
- package/src/bases/react-aria/ui/aspect-ratio.tsrx +1 -1
- package/src/bases/react-aria/ui/avatar.tsrx +1 -1
- package/src/bases/react-aria/ui/badge.tsrx +1 -1
- package/src/bases/react-aria/ui/breadcrumb.tsrx +1 -1
- package/src/bases/react-aria/ui/button.tsrx +1 -1
- package/src/bases/react-aria/ui/card.tsrx +1 -1
- package/src/bases/react-aria/ui/checkbox.tsrx +1 -1
- package/src/bases/react-aria/ui/dialog.tsrx +1 -1
- package/src/bases/react-aria/ui/empty.tsrx +1 -1
- package/src/bases/react-aria/ui/field.tsrx +1 -1
- package/src/bases/react-aria/ui/input.tsrx +1 -1
- package/src/bases/react-aria/ui/item.tsrx +1 -1
- package/src/bases/react-aria/ui/kbd.tsrx +1 -1
- package/src/bases/react-aria/ui/label.tsrx +1 -1
- package/src/bases/react-aria/ui/native-select.tsrx +1 -1
- package/src/bases/react-aria/ui/pagination.tsrx +1 -1
- package/src/bases/react-aria/ui/popover.tsrx +1 -1
- package/src/bases/react-aria/ui/radio-group.tsrx +1 -1
- package/src/bases/react-aria/ui/scroll-area.tsrx +1 -1
- package/src/bases/react-aria/ui/separator.tsrx +1 -1
- package/src/bases/react-aria/ui/sheet.tsrx +1 -1
- package/src/bases/react-aria/ui/skeleton.tsrx +1 -1
- package/src/bases/react-aria/ui/slider.tsrx +1 -1
- package/src/bases/react-aria/ui/spinner.tsrx +1 -1
- package/src/bases/react-aria/ui/switch.tsrx +1 -1
- package/src/bases/react-aria/ui/table.tsrx +1 -1
- package/src/bases/react-aria/ui/tabs.tsrx +1 -1
- package/src/bases/react-aria/ui/textarea.tsrx +1 -1
- package/src/bases/react-aria/ui/toggle.tsrx +1 -1
- package/src/lib/utils.ts +1 -8
|
@@ -29,25 +29,27 @@ import { Menubar as MenubarPrimitive } from '@octanejs/base-ui/menubar';
|
|
|
29
29
|
import { Menu as MenuPrimitive } from '@octanejs/base-ui/menu';
|
|
30
30
|
import { CheckIcon, ChevronRightIcon } from '@octanejs/lucide';
|
|
31
31
|
|
|
32
|
-
import { cn } from '
|
|
32
|
+
import { cn } from 'cn';
|
|
33
33
|
|
|
34
34
|
type Props = { className?: string; children?: OctaneNode } & Record<string, unknown>;
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
/** Props routed to the Positioner rather than the popup. */
|
|
37
|
+
export type BaseUiPositioningProps =
|
|
38
|
+
Pick<
|
|
39
|
+
MenuPrimitive.Positioner.Props,
|
|
40
|
+
| 'side'
|
|
41
|
+
| 'sideOffset'
|
|
42
|
+
| 'align'
|
|
43
|
+
| 'alignOffset'
|
|
44
|
+
| 'anchor'
|
|
45
|
+
| 'positionMethod'
|
|
46
|
+
| 'collisionBoundary'
|
|
47
|
+
| 'collisionPadding'
|
|
48
|
+
| 'collisionAvoidance'
|
|
49
|
+
| 'arrowPadding'
|
|
50
|
+
| 'sticky'
|
|
51
|
+
| 'disableAnchorTracking'
|
|
52
|
+
>;
|
|
51
53
|
|
|
52
54
|
export function Menubar({ className, ...props }: Props) @{
|
|
53
55
|
<MenubarPrimitive
|
|
@@ -170,7 +172,10 @@ export function MenubarCheckboxItem(props: Props & {
|
|
|
170
172
|
</MenuPrimitive.CheckboxItem>
|
|
171
173
|
}
|
|
172
174
|
|
|
173
|
-
export function MenubarRadioItem(props: Props & {
|
|
175
|
+
export function MenubarRadioItem(props: Omit<MenuPrimitive.RadioItem.Props, 'className'> & {
|
|
176
|
+
className?: string;
|
|
177
|
+
inset?: boolean;
|
|
178
|
+
}) @{
|
|
174
179
|
const { className, children: _children, inset, ...rest } = props;
|
|
175
180
|
|
|
176
181
|
<MenuPrimitive.RadioItem
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// `onChange` handlers are passed through unrenamed.
|
|
10
10
|
import { ChevronDownIcon } from '@octanejs/lucide';
|
|
11
11
|
|
|
12
|
-
import { cn } from '
|
|
12
|
+
import { cn } from 'cn';
|
|
13
13
|
import type { HostProps } from '../../../lib/types';
|
|
14
14
|
|
|
15
15
|
export type NativeSelectProps =
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Adapted from shadcn/ui 4.21.0 (7c9eaba1), Base UI with the Nova style.
|
|
2
|
+
// MIT: see LICENSE.upstream. Octane uses native events and refs as props.
|
|
3
|
+
import * as React from 'octane';
|
|
4
|
+
import { ChevronDownIcon } from '@octanejs/lucide';
|
|
5
|
+
import { NavigationMenu as NavigationMenuPrimitive } from '@octanejs/base-ui/navigation-menu';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
import { cn } from 'cn';
|
|
8
|
+
|
|
9
|
+
function NavigationMenu({
|
|
10
|
+
align = 'start',
|
|
11
|
+
className,
|
|
12
|
+
children,
|
|
13
|
+
...props
|
|
14
|
+
}: NavigationMenuPrimitive.Root.Props & Pick<NavigationMenuPrimitive.Positioner.Props, 'align'>) {
|
|
15
|
+
return <NavigationMenuPrimitive.Root
|
|
16
|
+
data-slot="navigation-menu"
|
|
17
|
+
className={cn(
|
|
18
|
+
'group/navigation-menu relative flex max-w-max flex-1 items-center justify-center',
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
<NavigationMenuPositioner align={align} />
|
|
25
|
+
</NavigationMenuPrimitive.Root>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function NavigationMenuList({ className, ...props }: React.ComponentPropsWithRef<
|
|
29
|
+
typeof NavigationMenuPrimitive.List
|
|
30
|
+
>) {
|
|
31
|
+
return <NavigationMenuPrimitive.List
|
|
32
|
+
data-slot="navigation-menu-list"
|
|
33
|
+
className={cn('gap-0 group flex flex-1 list-none items-center justify-center', className)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function NavigationMenuItem({ className, ...props }: React.ComponentPropsWithRef<
|
|
39
|
+
typeof NavigationMenuPrimitive.Item
|
|
40
|
+
>) {
|
|
41
|
+
return <NavigationMenuPrimitive.Item
|
|
42
|
+
data-slot="navigation-menu-item"
|
|
43
|
+
className={cn('relative', className)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const navigationMenuTriggerStyle = cva(
|
|
49
|
+
'hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-muted/50 focus-visible:ring-ring/50 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted rounded-lg px-2.5 py-1.5 text-sm font-medium transition-all focus-visible:ring-3 focus-visible:outline-1 disabled:opacity-50 group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center outline-none disabled:pointer-events-none',
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
function NavigationMenuTrigger({
|
|
53
|
+
className,
|
|
54
|
+
children,
|
|
55
|
+
...props
|
|
56
|
+
}: NavigationMenuPrimitive.Trigger.Props) {
|
|
57
|
+
return <NavigationMenuPrimitive.Trigger
|
|
58
|
+
data-slot="navigation-menu-trigger"
|
|
59
|
+
className={cn(navigationMenuTriggerStyle(), 'group', className)}
|
|
60
|
+
{...props}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
{' '}
|
|
64
|
+
<ChevronDownIcon
|
|
65
|
+
className="relative top-px ml-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180"
|
|
66
|
+
aria-hidden="true"
|
|
67
|
+
/>
|
|
68
|
+
</NavigationMenuPrimitive.Trigger>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function NavigationMenuContent({ className, ...props }: NavigationMenuPrimitive.Content.Props) {
|
|
72
|
+
return <NavigationMenuPrimitive.Content
|
|
73
|
+
data-slot="navigation-menu-content"
|
|
74
|
+
className={cn(
|
|
75
|
+
'data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:ring-foreground/10 p-1 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-lg group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300 data-ending-style:data-activation-direction=left:translate-x-[50%] data-ending-style:data-activation-direction=right:translate-x-[-50%] data-starting-style:data-activation-direction=left:translate-x-[-50%] data-starting-style:data-activation-direction=right:translate-x-[50%] h-full w-auto transition-[opacity,transform,translate] duration-[0.35s] data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none',
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function NavigationMenuPositioner({
|
|
83
|
+
className,
|
|
84
|
+
side = 'bottom',
|
|
85
|
+
sideOffset = 8,
|
|
86
|
+
align = 'start',
|
|
87
|
+
alignOffset = 0,
|
|
88
|
+
...props
|
|
89
|
+
}: NavigationMenuPrimitive.Positioner.Props) {
|
|
90
|
+
return <NavigationMenuPrimitive.Portal>
|
|
91
|
+
<NavigationMenuPrimitive.Positioner
|
|
92
|
+
side={side}
|
|
93
|
+
sideOffset={sideOffset}
|
|
94
|
+
align={align}
|
|
95
|
+
alignOffset={alignOffset}
|
|
96
|
+
className={cn(
|
|
97
|
+
'ease-[cubic-bezier(0.22,1,0.36,1)] data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0 isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] data-instant:transition-none',
|
|
98
|
+
className,
|
|
99
|
+
)}
|
|
100
|
+
{...props}
|
|
101
|
+
>
|
|
102
|
+
<NavigationMenuPrimitive.Popup
|
|
103
|
+
className="bg-popover text-popover-foreground ring-foreground/10 rounded-lg shadow ring-1 outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0 data-[ending-style]:easing-[ease] xs:w-(--popup-width) relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) transition-[opacity,transform,width,height,scale,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)]"
|
|
104
|
+
>
|
|
105
|
+
<NavigationMenuPrimitive.Viewport className="relative size-full overflow-hidden" />
|
|
106
|
+
</NavigationMenuPrimitive.Popup>
|
|
107
|
+
</NavigationMenuPrimitive.Positioner>
|
|
108
|
+
</NavigationMenuPrimitive.Portal>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function NavigationMenuLink({ className, ...props }: NavigationMenuPrimitive.Link.Props) {
|
|
112
|
+
return <NavigationMenuPrimitive.Link
|
|
113
|
+
data-slot="navigation-menu-link"
|
|
114
|
+
className={cn(
|
|
115
|
+
'data-active:focus:bg-muted data-active:hover:bg-muted data-active:bg-muted/50 focus-visible:ring-ring/50 hover:bg-muted focus:bg-muted flex items-center gap-2 rounded-lg p-2 text-sm transition-all outline-none focus-visible:ring-3 focus-visible:outline-1 in-data-[slot=navigation-menu-content]:rounded-md [&_svg:not([class*=\'size-\'])]:size-4',
|
|
116
|
+
className,
|
|
117
|
+
)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function NavigationMenuIndicator({ className, ...props }: React.ComponentPropsWithRef<
|
|
123
|
+
typeof NavigationMenuPrimitive.Icon
|
|
124
|
+
>) {
|
|
125
|
+
return <NavigationMenuPrimitive.Icon
|
|
126
|
+
data-slot="navigation-menu-indicator"
|
|
127
|
+
className={cn(
|
|
128
|
+
'data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-1 flex h-1.5 items-end justify-center overflow-hidden',
|
|
129
|
+
className,
|
|
130
|
+
)}
|
|
131
|
+
{...props}
|
|
132
|
+
>
|
|
133
|
+
<div className="bg-border rounded-tl-sm shadow-md relative top-[60%] h-2 w-2 rotate-45" />
|
|
134
|
+
</NavigationMenuPrimitive.Icon>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, NavigationMenuPositioner };
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { createElement, type OctaneNode } from 'octane';
|
|
22
22
|
import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from '@octanejs/lucide';
|
|
23
23
|
|
|
24
|
-
import { cn } from '
|
|
24
|
+
import { cn } from 'cn';
|
|
25
25
|
import { Button, type ButtonProps } from './button.tsrx';
|
|
26
26
|
|
|
27
27
|
type Props = { className?: string } & Record<string, unknown>;
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
import { createElement } from 'octane';
|
|
30
30
|
import { Popover as PopoverPrimitive } from '@octanejs/base-ui/popover';
|
|
31
31
|
|
|
32
|
-
import { cn } from '
|
|
32
|
+
import { cn } from 'cn';
|
|
33
33
|
|
|
34
34
|
type Props = { className?: string } & Record<string, unknown>;
|
|
35
35
|
|
|
@@ -41,21 +41,23 @@ export function PopoverTrigger(props: Record<string, unknown>) @{
|
|
|
41
41
|
<PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
/** Props routed to the Positioner rather than the popup. */
|
|
45
|
+
export type BaseUiPositioningProps =
|
|
46
|
+
Pick<
|
|
47
|
+
PopoverPrimitive.Positioner.Props,
|
|
48
|
+
| 'side'
|
|
49
|
+
| 'sideOffset'
|
|
50
|
+
| 'align'
|
|
51
|
+
| 'alignOffset'
|
|
52
|
+
| 'anchor'
|
|
53
|
+
| 'positionMethod'
|
|
54
|
+
| 'collisionBoundary'
|
|
55
|
+
| 'collisionPadding'
|
|
56
|
+
| 'collisionAvoidance'
|
|
57
|
+
| 'arrowPadding'
|
|
58
|
+
| 'sticky'
|
|
59
|
+
| 'disableAnchorTracking'
|
|
60
|
+
>;
|
|
59
61
|
|
|
60
62
|
export interface PopoverContentProps extends Record<string, unknown>, BaseUiPositioningProps {
|
|
61
63
|
className?: string;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// Indicator to match the extra part.
|
|
22
22
|
import { Progress as ProgressPrimitive } from '@octanejs/base-ui/progress';
|
|
23
23
|
|
|
24
|
-
import { cn } from '
|
|
24
|
+
import { cn } from 'cn';
|
|
25
25
|
|
|
26
26
|
export interface ProgressProps extends Record<string, unknown> {
|
|
27
27
|
className?: string;
|
|
@@ -28,7 +28,7 @@ import { RadioGroup as RadioGroupPrimitive } from '@octanejs/base-ui/radio-group
|
|
|
28
28
|
import { Radio as RadioPrimitive } from '@octanejs/base-ui/radio';
|
|
29
29
|
import { CircleIcon } from '@octanejs/lucide';
|
|
30
30
|
|
|
31
|
-
import { cn } from '
|
|
31
|
+
import { cn } from 'cn';
|
|
32
32
|
|
|
33
33
|
type Props = { className?: string } & Record<string, unknown>;
|
|
34
34
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Adapted from shadcn/ui 4.21.0 (7c9eaba1), Base UI with the Nova style.
|
|
2
|
+
// MIT: see LICENSE.upstream. Octane uses native events and refs as props.
|
|
3
|
+
import * as React from 'octane';
|
|
4
|
+
import { ScrollArea as ScrollAreaPrimitive } from '@octanejs/base-ui/scroll-area';
|
|
5
|
+
import { cn } from 'cn';
|
|
6
|
+
|
|
7
|
+
function ScrollArea({ className, children, ...props }: ScrollAreaPrimitive.Root.Props) {
|
|
8
|
+
return <ScrollAreaPrimitive.Root
|
|
9
|
+
data-slot="scroll-area"
|
|
10
|
+
className={cn('relative', className)}
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
<ScrollAreaPrimitive.Viewport
|
|
14
|
+
data-slot="scroll-area-viewport"
|
|
15
|
+
className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1"
|
|
16
|
+
>{children}</ScrollAreaPrimitive.Viewport>
|
|
17
|
+
<ScrollBar />
|
|
18
|
+
<ScrollAreaPrimitive.Corner />
|
|
19
|
+
</ScrollAreaPrimitive.Root>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function ScrollBar({
|
|
23
|
+
className,
|
|
24
|
+
orientation = 'vertical',
|
|
25
|
+
...props
|
|
26
|
+
}: ScrollAreaPrimitive.Scrollbar.Props) {
|
|
27
|
+
return <ScrollAreaPrimitive.Scrollbar
|
|
28
|
+
data-slot="scroll-area-scrollbar"
|
|
29
|
+
data-orientation={orientation}
|
|
30
|
+
orientation={orientation}
|
|
31
|
+
className={cn(
|
|
32
|
+
'data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent flex touch-none p-px transition-colors select-none',
|
|
33
|
+
className,
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
<ScrollAreaPrimitive.Thumb
|
|
38
|
+
data-slot="scroll-area-thumb"
|
|
39
|
+
className="rounded-full relative flex-1 bg-border"
|
|
40
|
+
/>
|
|
41
|
+
</ScrollAreaPrimitive.Scrollbar>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Adapted from shadcn/ui 4.21.0 (7c9eaba1), Base UI with the Nova style.
|
|
2
|
+
// MIT: see LICENSE.upstream. Octane uses native events and refs as props.
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@octanejs/lucide';
|
|
4
|
+
import * as React from 'octane';
|
|
5
|
+
import { Select as SelectPrimitive } from '@octanejs/base-ui/select';
|
|
6
|
+
import { cn } from 'cn';
|
|
7
|
+
|
|
8
|
+
const Select = SelectPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
|
|
11
|
+
return <SelectPrimitive.Group
|
|
12
|
+
data-slot="select-group"
|
|
13
|
+
className={cn('scroll-my-1 p-1', className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
|
|
19
|
+
return <SelectPrimitive.Value
|
|
20
|
+
data-slot="select-value"
|
|
21
|
+
className={cn('flex flex-1 text-left', className)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function SelectTrigger({
|
|
27
|
+
className,
|
|
28
|
+
size = 'default',
|
|
29
|
+
children,
|
|
30
|
+
...props
|
|
31
|
+
}: SelectPrimitive.Trigger.Props & {
|
|
32
|
+
size?: 'sm' | 'default';
|
|
33
|
+
}) {
|
|
34
|
+
return <SelectPrimitive.Trigger
|
|
35
|
+
data-slot="select-trigger"
|
|
36
|
+
data-size={size}
|
|
37
|
+
className={cn(
|
|
38
|
+
'border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 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:aria-invalid:border-destructive/50 gap-1.5 rounded-lg border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*=\'size-\'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
39
|
+
className,
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
<SelectPrimitive.Icon
|
|
45
|
+
render={<ChevronDownIcon className="text-muted-foreground size-4 pointer-events-none" />}
|
|
46
|
+
/>
|
|
47
|
+
</SelectPrimitive.Trigger>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function SelectContent({
|
|
51
|
+
className,
|
|
52
|
+
children,
|
|
53
|
+
side = 'bottom',
|
|
54
|
+
sideOffset = 4,
|
|
55
|
+
align = 'center',
|
|
56
|
+
alignOffset = 0,
|
|
57
|
+
alignItemWithTrigger = true,
|
|
58
|
+
...props
|
|
59
|
+
}: SelectPrimitive.Popup.Props & Pick<
|
|
60
|
+
SelectPrimitive.Positioner.Props,
|
|
61
|
+
'align' | 'alignOffset' | 'side' | 'sideOffset' | 'alignItemWithTrigger'
|
|
62
|
+
>) {
|
|
63
|
+
return <SelectPrimitive.Portal>
|
|
64
|
+
<SelectPrimitive.Positioner
|
|
65
|
+
side={side}
|
|
66
|
+
sideOffset={sideOffset}
|
|
67
|
+
align={align}
|
|
68
|
+
alignOffset={alignOffset}
|
|
69
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
70
|
+
className="isolate z-50"
|
|
71
|
+
>
|
|
72
|
+
<SelectPrimitive.Popup
|
|
73
|
+
data-slot="select-content"
|
|
74
|
+
data-align-trigger={alignItemWithTrigger}
|
|
75
|
+
className={cn(
|
|
76
|
+
'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-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 ring-foreground/10 min-w-36 rounded-lg shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 cn-menu-target cn-menu-translucent relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none',
|
|
77
|
+
className,
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
>
|
|
81
|
+
<SelectScrollUpButton />
|
|
82
|
+
<SelectPrimitive.List>{children}</SelectPrimitive.List>
|
|
83
|
+
<SelectScrollDownButton />
|
|
84
|
+
</SelectPrimitive.Popup>
|
|
85
|
+
</SelectPrimitive.Positioner>
|
|
86
|
+
</SelectPrimitive.Portal>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel.Props) {
|
|
90
|
+
return <SelectPrimitive.GroupLabel
|
|
91
|
+
data-slot="select-label"
|
|
92
|
+
className={cn('text-muted-foreground px-1.5 py-1 text-xs', className)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Props) {
|
|
98
|
+
return <SelectPrimitive.Item
|
|
99
|
+
data-slot="select-item"
|
|
100
|
+
className={cn(
|
|
101
|
+
'focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm [&_svg:not([class*=\'size-\'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
102
|
+
className,
|
|
103
|
+
)}
|
|
104
|
+
{...props}
|
|
105
|
+
>
|
|
106
|
+
<SelectPrimitive.ItemText
|
|
107
|
+
className="flex flex-1 gap-2 shrink-0 whitespace-nowrap"
|
|
108
|
+
>{children}</SelectPrimitive.ItemText>
|
|
109
|
+
<SelectPrimitive.ItemIndicator
|
|
110
|
+
render={<span
|
|
111
|
+
className="pointer-events-none absolute right-2 flex size-4 items-center justify-center"
|
|
112
|
+
/>}
|
|
113
|
+
>
|
|
114
|
+
<CheckIcon className="pointer-events-none" />
|
|
115
|
+
</SelectPrimitive.ItemIndicator>
|
|
116
|
+
</SelectPrimitive.Item>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) {
|
|
120
|
+
return <SelectPrimitive.Separator
|
|
121
|
+
data-slot="select-separator"
|
|
122
|
+
className={cn('bg-border -mx-1 my-1 h-px pointer-events-none', className)}
|
|
123
|
+
{...props}
|
|
124
|
+
/>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function SelectScrollUpButton({ className, ...props }: React.ComponentProps<
|
|
128
|
+
typeof SelectPrimitive.ScrollUpArrow
|
|
129
|
+
>) {
|
|
130
|
+
return <SelectPrimitive.ScrollUpArrow
|
|
131
|
+
data-slot="select-scroll-up-button"
|
|
132
|
+
className={cn(
|
|
133
|
+
'bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*=\'size-\'])]:size-4 top-0 w-full',
|
|
134
|
+
className,
|
|
135
|
+
)}
|
|
136
|
+
{...props}
|
|
137
|
+
>
|
|
138
|
+
<ChevronUpIcon />
|
|
139
|
+
</SelectPrimitive.ScrollUpArrow>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function SelectScrollDownButton({ className, ...props }: React.ComponentProps<
|
|
143
|
+
typeof SelectPrimitive.ScrollDownArrow
|
|
144
|
+
>) {
|
|
145
|
+
return <SelectPrimitive.ScrollDownArrow
|
|
146
|
+
data-slot="select-scroll-down-button"
|
|
147
|
+
className={cn(
|
|
148
|
+
'bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*=\'size-\'])]:size-4 bottom-0 w-full',
|
|
149
|
+
className,
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
>
|
|
153
|
+
<ChevronDownIcon />
|
|
154
|
+
</SelectPrimitive.ScrollDownArrow>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// exactly this reason. The non-conditional utilities stay in step with the other bases.
|
|
15
15
|
import { Separator as SeparatorPrimitive } from '@octanejs/base-ui/separator';
|
|
16
16
|
|
|
17
|
-
import { cn } from '
|
|
17
|
+
import { cn } from 'cn';
|
|
18
18
|
|
|
19
19
|
export interface SeparatorProps extends Record<string, unknown> {
|
|
20
20
|
className?: string;
|
|
@@ -27,7 +27,7 @@ import { type OctaneNode } from 'octane';
|
|
|
27
27
|
import { Dialog as SheetPrimitive } from '@octanejs/base-ui/dialog';
|
|
28
28
|
import { XIcon } from '@octanejs/lucide';
|
|
29
29
|
|
|
30
|
-
import { cn } from '
|
|
30
|
+
import { cn } from 'cn';
|
|
31
31
|
import { Button } from './button.tsrx';
|
|
32
32
|
|
|
33
33
|
type Props = { className?: string; children?: OctaneNode } & Record<string, unknown>;
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
36
36
|
import { PanelLeftIcon } from '@octanejs/lucide';
|
|
37
37
|
|
|
38
|
-
import { cn } from '
|
|
38
|
+
import { cn } from 'cn';
|
|
39
39
|
import { useIsMobile } from '../../../hooks/use-mobile';
|
|
40
40
|
import { Button } from './button.tsrx';
|
|
41
41
|
import { Input } from './input.tsrx';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Skeleton is the WORST case for this, and the reason the whole batch is labelled: the Radix
|
|
6
6
|
// base renders `bg-accent` where the React Aria base renders `bg-muted`, so the one token that
|
|
7
7
|
// matters here is known to differ ACROSS bases. Verify against the upstream source.
|
|
8
|
-
import { cn } from '
|
|
8
|
+
import { cn } from 'cn';
|
|
9
9
|
import type { DivProps } from '../../../lib/types';
|
|
10
10
|
|
|
11
11
|
export function Skeleton({ className, ...props }: DivProps) @{
|
|
@@ -23,29 +23,26 @@
|
|
|
23
23
|
// `thumbAlignment="edge"` is forwarded as upstream does: it insets the thumb so the two extremes
|
|
24
24
|
// sit flush with the ends of the track instead of overhanging them.
|
|
25
25
|
//
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
import { createElement, useMemo } from 'octane';
|
|
26
|
+
// One keyed thumb is rendered for each value.
|
|
27
|
+
import { useMemo } from 'octane';
|
|
29
28
|
import { Slider as SliderPrimitive } from '@octanejs/base-ui/slider';
|
|
30
29
|
|
|
31
|
-
import { cn } from '
|
|
30
|
+
import { cn } from 'cn';
|
|
32
31
|
|
|
33
|
-
export interface SliderProps
|
|
32
|
+
export interface SliderProps<
|
|
33
|
+
Value extends number | readonly number[] = number | readonly number[],
|
|
34
|
+
> extends Omit<SliderPrimitive.Root.Props<Value>, 'className'> {
|
|
34
35
|
className?: string;
|
|
35
|
-
defaultValue?: number | number[];
|
|
36
|
-
value?: number | number[];
|
|
37
|
-
min?: number;
|
|
38
|
-
max?: number;
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
export function Slider({
|
|
38
|
+
export function Slider<Value extends number | readonly number[]>({
|
|
42
39
|
className,
|
|
43
40
|
defaultValue,
|
|
44
41
|
value,
|
|
45
42
|
min = 0,
|
|
46
43
|
max = 100,
|
|
47
44
|
...props
|
|
48
|
-
}: SliderProps) {
|
|
45
|
+
}: SliderProps<Value>) @{
|
|
49
46
|
// This drives HOW MANY THUMBS get rendered, so a value shape it fails to recognise is a visible
|
|
50
47
|
// bug rather than a type nicety.
|
|
51
48
|
//
|
|
@@ -67,45 +64,37 @@ export function Slider({
|
|
|
67
64
|
return [min, max];
|
|
68
65
|
}, [value, defaultValue, min, max]);
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
className
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
SliderPrimitive.
|
|
87
|
-
|
|
88
|
-
className
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
className
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(_, index) => createElement(SliderPrimitive.Thumb, {
|
|
104
|
-
'data-slot': 'slider-thumb',
|
|
105
|
-
key: index,
|
|
106
|
-
className: 'relative block size-3 shrink-0 rounded-full border border-ring bg-white ring-ring/50 transition-[color,box-shadow] select-none after:absolute after:-inset-2 hover:ring-3 focus-visible:ring-3 focus-visible:outline-hidden active:ring-3 disabled:pointer-events-none disabled:opacity-50',
|
|
107
|
-
}),
|
|
108
|
-
),
|
|
109
|
-
),
|
|
110
|
-
);
|
|
67
|
+
<SliderPrimitive.Root
|
|
68
|
+
className={cn(
|
|
69
|
+
'data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full',
|
|
70
|
+
className,
|
|
71
|
+
)}
|
|
72
|
+
data-slot="slider"
|
|
73
|
+
defaultValue={defaultValue}
|
|
74
|
+
value={value}
|
|
75
|
+
min={min}
|
|
76
|
+
max={max}
|
|
77
|
+
thumbAlignment="edge"
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
<SliderPrimitive.Control
|
|
81
|
+
className="relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col"
|
|
82
|
+
>
|
|
83
|
+
<SliderPrimitive.Track
|
|
84
|
+
data-slot="slider-track"
|
|
85
|
+
className="relative grow overflow-hidden rounded-full bg-muted select-none data-[orientation=horizontal]:h-1 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1"
|
|
86
|
+
>
|
|
87
|
+
<SliderPrimitive.Indicator
|
|
88
|
+
data-slot="slider-range"
|
|
89
|
+
className="bg-primary select-none data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
|
|
90
|
+
/>
|
|
91
|
+
</SliderPrimitive.Track>
|
|
92
|
+
@for (const index of _values.keys(); key index) {
|
|
93
|
+
<SliderPrimitive.Thumb
|
|
94
|
+
data-slot="slider-thumb"
|
|
95
|
+
className="relative block size-3 shrink-0 rounded-full border border-ring bg-white ring-ring/50 transition-[color,box-shadow] select-none after:absolute after:-inset-2 hover:ring-3 focus-visible:ring-3 focus-visible:outline-hidden active:ring-3 disabled:pointer-events-none disabled:opacity-50"
|
|
96
|
+
/>
|
|
97
|
+
}
|
|
98
|
+
</SliderPrimitive.Control>
|
|
99
|
+
</SliderPrimitive.Root>
|
|
111
100
|
}
|