@camox/ui 0.6.1 → 0.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camox/ui",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "files": [
5
5
  "src"
6
6
  ],
@@ -10,10 +10,6 @@
10
10
  "types": "./src/lib/utils.ts",
11
11
  "default": "./src/lib/utils.ts"
12
12
  },
13
- "./accordion": {
14
- "types": "./src/components/accordion.tsx",
15
- "default": "./src/components/accordion.tsx"
16
- },
17
13
  "./alert-dialog": {
18
14
  "types": "./src/components/alert-dialog.tsx",
19
15
  "default": "./src/components/alert-dialog.tsx"
@@ -42,18 +38,10 @@
42
38
  "types": "./src/components/button.tsx",
43
39
  "default": "./src/components/button.tsx"
44
40
  },
45
- "./checkbox": {
46
- "types": "./src/components/checkbox.tsx",
47
- "default": "./src/components/checkbox.tsx"
48
- },
49
41
  "./command": {
50
42
  "types": "./src/components/command.tsx",
51
43
  "default": "./src/components/command.tsx"
52
44
  },
53
- "./control-group": {
54
- "types": "./src/components/control-group.tsx",
55
- "default": "./src/components/control-group.tsx"
56
- },
57
45
  "./dialog": {
58
46
  "types": "./src/components/dialog.tsx",
59
47
  "default": "./src/components/dialog.tsx"
@@ -66,13 +54,9 @@
66
54
  "types": "./src/components/floating-toolbar.tsx",
67
55
  "default": "./src/components/floating-toolbar.tsx"
68
56
  },
69
- "./frame": {
70
- "types": "./src/components/frame.tsx",
71
- "default": "./src/components/frame.tsx"
72
- },
73
- "./input-base": {
74
- "types": "./src/components/input-base.tsx",
75
- "default": "./src/components/input-base.tsx"
57
+ "./input-group": {
58
+ "types": "./src/components/input-group.tsx",
59
+ "default": "./src/components/input-group.tsx"
76
60
  },
77
61
  "./input": {
78
62
  "types": "./src/components/input.tsx",
@@ -94,10 +78,6 @@
94
78
  "types": "./src/components/popover.tsx",
95
79
  "default": "./src/components/popover.tsx"
96
80
  },
97
- "./resizable": {
98
- "types": "./src/components/resizable.tsx",
99
- "default": "./src/components/resizable.tsx"
100
- },
101
81
  "./select": {
102
82
  "types": "./src/components/select.tsx",
103
83
  "default": "./src/components/select.tsx"
@@ -141,36 +121,14 @@
141
121
  "./tooltip": {
142
122
  "types": "./src/components/tooltip.tsx",
143
123
  "default": "./src/components/tooltip.tsx"
144
- },
145
- "./use-mobile": {
146
- "types": "./src/hooks/use-mobile.ts",
147
- "default": "./src/hooks/use-mobile.ts"
148
124
  }
149
125
  },
150
126
  "dependencies": {
151
- "@radix-ui/primitive": "1.1.2",
152
- "@radix-ui/react-accordion": "^1.2.12",
153
- "@radix-ui/react-alert-dialog": "^1.1.15",
154
- "@radix-ui/react-checkbox": "^1.3.3",
155
- "@radix-ui/react-compose-refs": "1.1.2",
156
- "@radix-ui/react-dialog": "^1.1.15",
157
- "@radix-ui/react-dropdown-menu": "^2.1.16",
158
- "@radix-ui/react-label": "^2.1.7",
159
- "@radix-ui/react-popover": "^1.1.15",
160
- "@radix-ui/react-primitive": "2.1.2",
161
- "@radix-ui/react-select": "^2.2.6",
162
- "@radix-ui/react-separator": "^1.1.7",
163
- "@radix-ui/react-slot": "^1.2.3",
164
- "@radix-ui/react-switch": "^1.2.6",
165
- "@radix-ui/react-tabs": "^1.1.13",
166
- "@radix-ui/react-toggle": "^1.1.10",
167
- "@radix-ui/react-tooltip": "^1.2.8",
168
- "@window-splitter/react": "^1.1.2",
127
+ "@base-ui/react": "^1.4.0",
169
128
  "class-variance-authority": "^0.7.1",
170
129
  "clsx": "^2.1.1",
171
130
  "cmdk": "^1.1.1",
172
131
  "lucide-react": "^0.476.0",
173
- "radix-ui": "^1.4.3",
174
132
  "sonner": "^2.0.7",
175
133
  "tailwind-merge": "^3.0.2"
176
134
  },
@@ -1,32 +1,27 @@
1
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
1
+ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
2
2
  import * as React from "react";
3
3
 
4
4
  import { cn } from "../lib/utils";
5
- import { buttonVariants } from "./button";
5
+ import { Button } from "./button";
6
6
 
7
- function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
7
+ function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
8
8
  return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
9
9
  }
10
10
 
11
- function AlertDialogTrigger({
12
- ...props
13
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
11
+ function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
14
12
  return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
15
13
  }
16
14
 
17
- function AlertDialogPortal({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
15
+ function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
18
16
  return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
19
17
  }
20
18
 
21
- function AlertDialogOverlay({
22
- className,
23
- ...props
24
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
19
+ function AlertDialogOverlay({ className, ...props }: AlertDialogPrimitive.Backdrop.Props) {
25
20
  return (
26
- <AlertDialogPrimitive.Overlay
21
+ <AlertDialogPrimitive.Backdrop
27
22
  data-slot="alert-dialog-overlay"
28
23
  className={cn(
29
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
24
+ "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
30
25
  className,
31
26
  )}
32
27
  {...props}
@@ -36,15 +31,19 @@ function AlertDialogOverlay({
36
31
 
37
32
  function AlertDialogContent({
38
33
  className,
34
+ size = "default",
39
35
  ...props
40
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
36
+ }: AlertDialogPrimitive.Popup.Props & {
37
+ size?: "default" | "sm";
38
+ }) {
41
39
  return (
42
40
  <AlertDialogPortal>
43
41
  <AlertDialogOverlay />
44
- <AlertDialogPrimitive.Content
42
+ <AlertDialogPrimitive.Popup
45
43
  data-slot="alert-dialog-content"
44
+ data-size={size}
46
45
  className={cn(
47
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
46
+ "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-6 rounded-xl bg-popover p-6 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg 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",
48
47
  className,
49
48
  )}
50
49
  {...props}
@@ -57,7 +56,10 @@ function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">)
57
56
  return (
58
57
  <div
59
58
  data-slot="alert-dialog-header"
60
- className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
59
+ className={cn(
60
+ "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
61
+ className,
62
+ )}
61
63
  {...props}
62
64
  />
63
65
  );
@@ -67,7 +69,23 @@ function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">)
67
69
  return (
68
70
  <div
69
71
  data-slot="alert-dialog-footer"
70
- className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
72
+ className={cn(
73
+ "flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
74
+ className,
75
+ )}
76
+ {...props}
77
+ />
78
+ );
79
+ }
80
+
81
+ function AlertDialogMedia({ className, ...props }: React.ComponentProps<"div">) {
82
+ return (
83
+ <div
84
+ data-slot="alert-dialog-media"
85
+ className={cn(
86
+ "mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8",
87
+ className,
88
+ )}
71
89
  {...props}
72
90
  />
73
91
  );
@@ -80,7 +98,10 @@ function AlertDialogTitle({
80
98
  return (
81
99
  <AlertDialogPrimitive.Title
82
100
  data-slot="alert-dialog-title"
83
- className={cn("text-lg font-semibold", className)}
101
+ className={cn(
102
+ "text-lg font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
103
+ className,
104
+ )}
84
105
  {...props}
85
106
  />
86
107
  );
@@ -93,26 +114,31 @@ function AlertDialogDescription({
93
114
  return (
94
115
  <AlertDialogPrimitive.Description
95
116
  data-slot="alert-dialog-description"
96
- className={cn("text-muted-foreground text-sm", className)}
117
+ className={cn(
118
+ "text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
119
+ className,
120
+ )}
97
121
  {...props}
98
122
  />
99
123
  );
100
124
  }
101
125
 
102
- function AlertDialogAction({
103
- className,
104
- ...props
105
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
106
- return <AlertDialogPrimitive.Action className={cn(buttonVariants(), className)} {...props} />;
126
+ function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof Button>) {
127
+ return <Button data-slot="alert-dialog-action" className={cn(className)} {...props} />;
107
128
  }
108
129
 
109
130
  function AlertDialogCancel({
110
131
  className,
132
+ variant = "outline",
133
+ size = "default",
111
134
  ...props
112
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
135
+ }: AlertDialogPrimitive.Close.Props &
136
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
113
137
  return (
114
- <AlertDialogPrimitive.Cancel
115
- className={cn(buttonVariants({ variant: "outline" }), className)}
138
+ <AlertDialogPrimitive.Close
139
+ data-slot="alert-dialog-cancel"
140
+ className={cn(className)}
141
+ render={<Button variant={variant} size={size} />}
116
142
  {...props}
117
143
  />
118
144
  );
@@ -120,14 +146,15 @@ function AlertDialogCancel({
120
146
 
121
147
  export {
122
148
  AlertDialog,
123
- AlertDialogPortal,
124
- AlertDialogOverlay,
125
- AlertDialogTrigger,
149
+ AlertDialogAction,
150
+ AlertDialogCancel,
126
151
  AlertDialogContent,
127
- AlertDialogHeader,
152
+ AlertDialogDescription,
128
153
  AlertDialogFooter,
154
+ AlertDialogHeader,
155
+ AlertDialogMedia,
156
+ AlertDialogOverlay,
157
+ AlertDialogPortal,
129
158
  AlertDialogTitle,
130
- AlertDialogDescription,
131
- AlertDialogAction,
132
- AlertDialogCancel,
159
+ AlertDialogTrigger,
133
160
  };
@@ -4,13 +4,13 @@ import * as React from "react";
4
4
  import { cn } from "../lib/utils";
5
5
 
6
6
  const alertVariants = cva(
7
- "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
7
+ "group/alert relative grid w-full gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
8
8
  {
9
9
  variants: {
10
10
  variant: {
11
11
  default: "bg-card text-card-foreground",
12
12
  destructive:
13
- "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
13
+ "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
14
14
  },
15
15
  },
16
16
  defaultVariants: {
@@ -38,7 +38,10 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
38
  return (
39
39
  <div
40
40
  data-slot="alert-title"
41
- className={cn("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", className)}
41
+ className={cn(
42
+ "font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
43
+ className,
44
+ )}
42
45
  {...props}
43
46
  />
44
47
  );
@@ -49,7 +52,7 @@ function AlertDescription({ className, ...props }: React.ComponentProps<"div">)
49
52
  <div
50
53
  data-slot="alert-description"
51
54
  className={cn(
52
- "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
55
+ "text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
53
56
  className,
54
57
  )}
55
58
  {...props}
@@ -57,4 +60,14 @@ function AlertDescription({ className, ...props }: React.ComponentProps<"div">)
57
60
  );
58
61
  }
59
62
 
60
- export { Alert, AlertTitle, AlertDescription };
63
+ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
64
+ return (
65
+ <div
66
+ data-slot="alert-action"
67
+ className={cn("absolute top-2.5 right-3", className)}
68
+ {...props}
69
+ />
70
+ );
71
+ }
72
+
73
+ export { Alert, AlertTitle, AlertDescription, AlertAction };
@@ -1,4 +1,4 @@
1
- import { Avatar as AvatarPrimitive } from "radix-ui";
1
+ import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
2
2
  import * as React from "react";
3
3
 
4
4
  import { cn } from "../lib/utils";
@@ -7,7 +7,7 @@ function Avatar({
7
7
  className,
8
8
  size = "default",
9
9
  ...props
10
- }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
10
+ }: AvatarPrimitive.Root.Props & {
11
11
  size?: "default" | "sm" | "lg";
12
12
  }) {
13
13
  return (
@@ -15,7 +15,7 @@ function Avatar({
15
15
  data-slot="avatar"
16
16
  data-size={size}
17
17
  className={cn(
18
- "group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
18
+ "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
19
19
  className,
20
20
  )}
21
21
  {...props}
@@ -23,20 +23,17 @@ function Avatar({
23
23
  );
24
24
  }
25
25
 
26
- function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
26
+ function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
27
27
  return (
28
28
  <AvatarPrimitive.Image
29
29
  data-slot="avatar-image"
30
- className={cn("aspect-square size-full", className)}
30
+ className={cn("aspect-square size-full rounded-full object-cover", className)}
31
31
  {...props}
32
32
  />
33
33
  );
34
34
  }
35
35
 
36
- function AvatarFallback({
37
- className,
38
- ...props
39
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
36
+ function AvatarFallback({ className, ...props }: AvatarPrimitive.Fallback.Props) {
40
37
  return (
41
38
  <AvatarPrimitive.Fallback
42
39
  data-slot="avatar-fallback"
@@ -54,7 +51,7 @@ function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
54
51
  <span
55
52
  data-slot="avatar-badge"
56
53
  className={cn(
57
- "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground ring-2 ring-background select-none",
54
+ "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
58
55
  "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
59
56
  "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
60
57
  "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
@@ -91,4 +88,4 @@ function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">)
91
88
  );
92
89
  }
93
90
 
94
- export { Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup, AvatarGroupCount };
91
+ export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge };
@@ -1,20 +1,21 @@
1
- import { Slot } from "@radix-ui/react-slot";
1
+ import { mergeProps } from "@base-ui/react/merge-props";
2
+ import { useRender } from "@base-ui/react/use-render";
2
3
  import { cva, type VariantProps } from "class-variance-authority";
3
- import * as React from "react";
4
4
 
5
5
  import { cn } from "../lib/utils";
6
6
 
7
7
  const badgeVariants = cva(
8
- "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
8
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
9
  {
10
10
  variants: {
11
11
  variant: {
12
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
13
- secondary:
14
- "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
14
  destructive:
16
- "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
17
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
15
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
16
+ outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
17
+ ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
18
+ link: "text-primary underline-offset-4 hover:underline",
18
19
  },
19
20
  },
20
21
  defaultVariants: {
@@ -25,15 +26,24 @@ const badgeVariants = cva(
25
26
 
26
27
  function Badge({
27
28
  className,
28
- variant,
29
- asChild = false,
29
+ variant = "default",
30
+ render,
30
31
  ...props
31
- }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
32
- const Comp = asChild ? Slot : "span";
33
-
34
- return (
35
- <Comp data-slot="badge" className={cn(badgeVariants({ variant }), className)} {...props} />
36
- );
32
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
33
+ return useRender({
34
+ defaultTagName: "span",
35
+ props: mergeProps<"span">(
36
+ {
37
+ className: cn(badgeVariants({ variant }), className),
38
+ },
39
+ props,
40
+ ),
41
+ render,
42
+ state: {
43
+ slot: "badge",
44
+ variant,
45
+ },
46
+ });
37
47
  }
38
48
 
39
49
  export { Badge, badgeVariants };
@@ -1,11 +1,14 @@
1
- import { ChevronRight, MoreHorizontal } from "lucide-react";
2
- import { Slot } from "radix-ui";
1
+ import { mergeProps } from "@base-ui/react/merge-props";
2
+ import { useRender } from "@base-ui/react/use-render";
3
+ import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
3
4
  import * as React from "react";
4
5
 
5
6
  import { cn } from "../lib/utils";
6
7
 
7
- function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8
- return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
8
+ function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
9
+ return (
10
+ <nav aria-label="breadcrumb" data-slot="breadcrumb" className={cn(className)} {...props} />
11
+ );
9
12
  }
10
13
 
11
14
  function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
@@ -13,7 +16,7 @@ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
13
16
  <ol
14
17
  data-slot="breadcrumb-list"
15
18
  className={cn(
16
- "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
19
+ "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground sm:gap-2.5",
17
20
  className,
18
21
  )}
19
22
  {...props}
@@ -31,22 +34,20 @@ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
31
34
  );
32
35
  }
33
36
 
34
- function BreadcrumbLink({
35
- asChild,
36
- className,
37
- ...props
38
- }: React.ComponentProps<"a"> & {
39
- asChild?: boolean;
40
- }) {
41
- const Comp = asChild ? Slot.Root : "a";
42
-
43
- return (
44
- <Comp
45
- data-slot="breadcrumb-link"
46
- className={cn("hover:text-foreground transition-colors", className)}
47
- {...props}
48
- />
49
- );
37
+ function BreadcrumbLink({ className, render, ...props }: useRender.ComponentProps<"a">) {
38
+ return useRender({
39
+ defaultTagName: "a",
40
+ props: mergeProps<"a">(
41
+ {
42
+ className: cn("transition-colors hover:text-foreground", className),
43
+ },
44
+ props,
45
+ ),
46
+ render,
47
+ state: {
48
+ slot: "breadcrumb-link",
49
+ },
50
+ });
50
51
  }
51
52
 
52
53
  function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
@@ -56,7 +57,7 @@ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
56
57
  role="link"
57
58
  aria-disabled="true"
58
59
  aria-current="page"
59
- className={cn("text-foreground font-normal", className)}
60
+ className={cn("font-normal text-foreground", className)}
60
61
  {...props}
61
62
  />
62
63
  );
@@ -71,7 +72,7 @@ function BreadcrumbSeparator({ children, className, ...props }: React.ComponentP
71
72
  className={cn("[&>svg]:size-3.5", className)}
72
73
  {...props}
73
74
  >
74
- {children ?? <ChevronRight />}
75
+ {children ?? <ChevronRightIcon />}
75
76
  </li>
76
77
  );
77
78
  }
@@ -82,10 +83,10 @@ function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span"
82
83
  data-slot="breadcrumb-ellipsis"
83
84
  role="presentation"
84
85
  aria-hidden="true"
85
- className={cn("flex size-9 items-center justify-center", className)}
86
+ className={cn("flex size-5 items-center justify-center [&>svg]:size-4", className)}
86
87
  {...props}
87
88
  >
88
- <MoreHorizontal className="size-4" />
89
+ <MoreHorizontalIcon />
89
90
  <span className="sr-only">More</span>
90
91
  </span>
91
92
  );
@@ -1,18 +1,19 @@
1
- import { Slot } from "@radix-ui/react-slot";
1
+ import { mergeProps } from "@base-ui/react/merge-props";
2
+ import { useRender } from "@base-ui/react/use-render";
2
3
  import { cva, type VariantProps } from "class-variance-authority";
3
4
 
4
5
  import { cn } from "../lib/utils";
5
6
  import { Separator } from "./separator";
6
7
 
7
8
  const buttonGroupVariants = cva(
8
- "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
9
+ "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
9
10
  {
10
11
  variants: {
11
12
  orientation: {
12
13
  horizontal:
13
- "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
14
+ "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
14
15
  vertical:
15
- "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
16
+ "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0",
16
17
  },
17
18
  },
18
19
  defaultVariants: {
@@ -37,24 +38,23 @@ function ButtonGroup({
37
38
  );
38
39
  }
39
40
 
40
- function ButtonGroupText({
41
- className,
42
- asChild = false,
43
- ...props
44
- }: React.ComponentProps<"div"> & {
45
- asChild?: boolean;
46
- }) {
47
- const Comp = asChild ? Slot : "div";
48
-
49
- return (
50
- <Comp
51
- className={cn(
52
- "bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
53
- className,
54
- )}
55
- {...props}
56
- />
57
- );
41
+ function ButtonGroupText({ className, render, ...props }: useRender.ComponentProps<"div">) {
42
+ return useRender({
43
+ defaultTagName: "div",
44
+ props: mergeProps<"div">(
45
+ {
46
+ className: cn(
47
+ "flex items-center gap-2 rounded-md border bg-muted px-2.5 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
48
+ className,
49
+ ),
50
+ },
51
+ props,
52
+ ),
53
+ render,
54
+ state: {
55
+ slot: "button-group-text",
56
+ },
57
+ });
58
58
  }
59
59
 
60
60
  function ButtonGroupSeparator({
@@ -67,7 +67,7 @@ function ButtonGroupSeparator({
67
67
  data-slot="button-group-separator"
68
68
  orientation={orientation}
69
69
  className={cn(
70
- "bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
70
+ "relative self-stretch bg-input data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
71
71
  className,
72
72
  )}
73
73
  {...props}