@nocobase/portal-template-default 1.0.4 → 1.0.6

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.
Files changed (139) hide show
  1. package/README.MD +77 -0
  2. package/package.json +23 -17
  3. package/registry/nocobase-acl/demo/prompt-generator.tsx +6 -39
  4. package/registry/nocobase-acl/demo/role-switcher-prompt-generator.tsx +6 -42
  5. package/registry/nocobase-ai/demo/page-context-prompt-generator.tsx +1 -1
  6. package/registry/nocobase-ai/demo/prompt-card.tsx +7 -28
  7. package/registry/nocobase-ai/demo/prompt-generator.tsx +9 -30
  8. package/registry/nocobase-ai/demo/shortcut.tsx +1 -1
  9. package/registry/nocobase-ai/demo/tool-cards.tsx +10 -30
  10. package/registry/nocobase-auth-cas/README.md +6 -0
  11. package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +41 -0
  12. package/registry/nocobase-auth-cas/demo.tsx +20 -0
  13. package/registry/nocobase-auth-cas/extension.tsx +46 -0
  14. package/registry/nocobase-auth-cas/index.ts +1 -0
  15. package/registry/nocobase-auth-cas/use-cas-sign-in.ts +29 -0
  16. package/registry/nocobase-auth-dingtalk/README.md +7 -0
  17. package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +154 -0
  18. package/registry/nocobase-auth-dingtalk/demo.tsx +23 -0
  19. package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +45 -0
  20. package/registry/nocobase-auth-dingtalk/extension.tsx +55 -0
  21. package/registry/nocobase-auth-dingtalk/index.ts +4 -0
  22. package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +64 -0
  23. package/registry/nocobase-auth-ldap/README.md +6 -0
  24. package/registry/nocobase-auth-ldap/demo.tsx +21 -0
  25. package/registry/nocobase-auth-ldap/extension.tsx +46 -0
  26. package/registry/nocobase-auth-ldap/index.ts +1 -0
  27. package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +69 -0
  28. package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +5 -0
  29. package/registry/nocobase-auth-oidc/README.md +11 -0
  30. package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +13 -0
  31. package/registry/nocobase-auth-oidc/demo.tsx +20 -0
  32. package/registry/nocobase-auth-oidc/extension.tsx +51 -0
  33. package/registry/nocobase-auth-oidc/index.ts +1 -0
  34. package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +44 -0
  35. package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +58 -0
  36. package/registry/nocobase-auth-saml/README.md +6 -0
  37. package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +13 -0
  38. package/registry/nocobase-auth-saml/demo.tsx +20 -0
  39. package/registry/nocobase-auth-saml/extension.tsx +51 -0
  40. package/registry/nocobase-auth-saml/index.ts +1 -0
  41. package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +43 -0
  42. package/registry/nocobase-auth-saml/use-saml-sign-in.ts +51 -0
  43. package/registry/nocobase-auth-sms/README.md +7 -0
  44. package/registry/nocobase-auth-sms/demo.tsx +25 -0
  45. package/registry/nocobase-auth-sms/extension.tsx +46 -0
  46. package/registry/nocobase-auth-sms/index.ts +1 -0
  47. package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +107 -0
  48. package/registry/nocobase-auth-sms/use-sms-sign-in.ts +88 -0
  49. package/registry/nocobase-auth-wecom/README.md +6 -0
  50. package/registry/nocobase-auth-wecom/auto-login-provider.tsx +21 -0
  51. package/registry/nocobase-auth-wecom/demo.tsx +23 -0
  52. package/registry/nocobase-auth-wecom/extension.tsx +49 -0
  53. package/registry/nocobase-auth-wecom/index.ts +1 -0
  54. package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +62 -0
  55. package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +70 -0
  56. package/registry/nocobase-i18n/demo/prompt-generator.tsx +30 -54
  57. package/registry/nocobase-route-surfaces/demo/prompt-generator.tsx +18 -21
  58. package/registry.config.json +112 -0
  59. package/scripts/build-html.mjs +106 -0
  60. package/src/App.tsx +34 -8
  61. package/src/app/extension.ts +4 -0
  62. package/src/app/extensions.tsx +24 -1
  63. package/src/components/auth/authenticator-adapters.ts +20 -0
  64. package/src/components/auth/auto-redirect-provider.tsx +84 -0
  65. package/src/components/auth/basic-sign-in-form.tsx +101 -0
  66. package/src/components/auth/default-sign-in-page.tsx +20 -0
  67. package/src/components/auth/demo/auth-demo-page.tsx +236 -0
  68. package/src/components/auth/demo/auth-demo-prompt-generator.tsx +93 -0
  69. package/src/components/auth/demo/auth-demo-route.tsx +11 -0
  70. package/src/components/auth/demo/auth-method-demo.tsx +48 -0
  71. package/src/components/auth/demo/index.ts +4 -0
  72. package/src/components/auth/dynamic-sign-in.tsx +191 -0
  73. package/src/components/auth/forgot-password-form.tsx +13 -5
  74. package/src/components/auth/index.ts +13 -0
  75. package/src/components/auth/sign-in-form.tsx +1 -111
  76. package/src/components/auth/sign-up-form.tsx +14 -37
  77. package/src/components/auth/types.ts +38 -0
  78. package/src/components/auth/use-authenticator-sign-in.ts +14 -0
  79. package/src/components/auth/use-public-authenticators.ts +26 -0
  80. package/src/components/data-table/data-table-filter.tsx +107 -153
  81. package/src/components/demo/prompt-output.tsx +71 -0
  82. package/src/components/ui/alert-dialog.tsx +2 -0
  83. package/src/components/ui/attachment.tsx +207 -0
  84. package/src/components/ui/bubble.tsx +128 -0
  85. package/src/components/ui/button-group.tsx +87 -0
  86. package/src/components/ui/button.tsx +6 -6
  87. package/src/components/ui/calendar.tsx +0 -2
  88. package/src/components/ui/card.tsx +1 -1
  89. package/src/components/ui/carousel.tsx +2 -0
  90. package/src/components/ui/combobox.tsx +297 -0
  91. package/src/components/ui/command.tsx +43 -41
  92. package/src/components/ui/dialog.tsx +0 -2
  93. package/src/components/ui/direction.tsx +4 -0
  94. package/src/components/ui/drawer.tsx +2 -0
  95. package/src/components/ui/dropdown-menu.tsx +0 -2
  96. package/src/components/ui/empty.tsx +104 -0
  97. package/src/components/ui/field.tsx +238 -0
  98. package/src/components/ui/hover-card.tsx +2 -0
  99. package/src/components/ui/input-group.tsx +0 -2
  100. package/src/components/ui/input-otp.tsx +0 -2
  101. package/src/components/ui/input.tsx +1 -1
  102. package/src/components/ui/item.tsx +201 -0
  103. package/src/components/ui/kbd.tsx +26 -0
  104. package/src/components/ui/label.tsx +2 -0
  105. package/src/components/ui/marker.tsx +71 -0
  106. package/src/components/ui/message-scroller.tsx +131 -0
  107. package/src/components/ui/message.tsx +92 -0
  108. package/src/components/ui/native-select.tsx +61 -0
  109. package/src/components/ui/popover.tsx +0 -2
  110. package/src/components/ui/progress.tsx +2 -0
  111. package/src/components/ui/radio-group.tsx +0 -2
  112. package/src/components/ui/resizable.tsx +2 -0
  113. package/src/components/ui/scroll-area.tsx +0 -2
  114. package/src/components/ui/select.tsx +6 -4
  115. package/src/components/ui/separator.tsx +0 -2
  116. package/src/components/ui/sheet.tsx +21 -22
  117. package/src/components/ui/sidebar.tsx +1 -3
  118. package/src/components/ui/sonner.tsx +2 -0
  119. package/src/components/ui/spinner.tsx +10 -0
  120. package/src/components/ui/switch.tsx +0 -2
  121. package/src/components/ui/table.tsx +4 -2
  122. package/src/components/ui/tabs.tsx +0 -2
  123. package/src/components/ui/textarea.tsx +1 -1
  124. package/src/components/ui/toggle-group.tsx +2 -0
  125. package/src/components/ui/toggle.tsx +2 -0
  126. package/src/components/ui/tooltip.tsx +0 -2
  127. package/src/index.tsx +3 -0
  128. package/src/lib/nocobase/client.ts +32 -2
  129. package/src/lib/utils.ts +2 -1
  130. package/src/locales/en-US.ts +4 -2
  131. package/src/locales/zh-CN.ts +4 -2
  132. package/src/pages/login/index.tsx +2 -2
  133. package/src/pages/users/list.tsx +144 -16
  134. package/src/providers/auth-callback.ts +21 -0
  135. package/src/providers/auth.ts +108 -22
  136. package/src/providers/constants.ts +4 -1
  137. package/src/providers/runtime-config.ts +19 -0
  138. package/src/vite-env.d.ts +5 -0
  139. package/vite.config.ts +55 -2
@@ -0,0 +1,128 @@
1
+ import * as React from "react"
2
+ import { mergeProps } from "@base-ui/react/merge-props"
3
+ import { useRender } from "@base-ui/react/use-render"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
9
+ return (
10
+ <div
11
+ data-slot="bubble-group"
12
+ className={cn("flex min-w-0 flex-col gap-2", className)}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ const bubbleVariants = cva(
19
+ "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
20
+ {
21
+ variants: {
22
+ variant: {
23
+ default:
24
+ "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
25
+ secondary:
26
+ "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
27
+ muted:
28
+ "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
29
+ tinted:
30
+ "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
31
+ outline:
32
+ "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
33
+ ghost:
34
+ "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
35
+ destructive:
36
+ "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30",
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ variant: "default",
41
+ },
42
+ }
43
+ )
44
+
45
+ function Bubble({
46
+ variant = "default",
47
+ align = "start",
48
+ className,
49
+ ...props
50
+ }: React.ComponentProps<"div"> &
51
+ VariantProps<typeof bubbleVariants> & {
52
+ align?: "start" | "end"
53
+ }) {
54
+ return (
55
+ <div
56
+ data-slot="bubble"
57
+ data-variant={variant}
58
+ data-align={align}
59
+ className={cn(bubbleVariants({ variant }), className)}
60
+ {...props}
61
+ />
62
+ )
63
+ }
64
+
65
+ function BubbleContent({
66
+ className,
67
+ render,
68
+ ...props
69
+ }: useRender.ComponentProps<"div">) {
70
+ return useRender({
71
+ defaultTagName: "div",
72
+ props: mergeProps<"div">(
73
+ {
74
+ className: cn(
75
+ "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
76
+ className
77
+ ),
78
+ },
79
+ props
80
+ ),
81
+ render,
82
+ state: {
83
+ slot: "bubble-content",
84
+ },
85
+ })
86
+ }
87
+
88
+ const bubbleReactionsVariants = cva(
89
+ "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
90
+ {
91
+ variants: {
92
+ side: {
93
+ top: "top-0 -translate-y-3/4",
94
+ bottom: "bottom-0 translate-y-3/4",
95
+ },
96
+ align: {
97
+ start: "left-3",
98
+ end: "right-3",
99
+ },
100
+ },
101
+ defaultVariants: {
102
+ side: "bottom",
103
+ align: "end",
104
+ },
105
+ }
106
+ )
107
+
108
+ function BubbleReactions({
109
+ side = "bottom",
110
+ align = "end",
111
+ className,
112
+ ...props
113
+ }: React.ComponentProps<"div"> & {
114
+ align?: "start" | "end"
115
+ side?: "top" | "bottom"
116
+ }) {
117
+ return (
118
+ <div
119
+ data-slot="bubble-reactions"
120
+ data-align={align}
121
+ data-side={side}
122
+ className={cn(bubbleReactionsVariants({ side, align }), className)}
123
+ {...props}
124
+ />
125
+ )
126
+ }
127
+
128
+ export { BubbleGroup, Bubble, BubbleContent, BubbleReactions }
@@ -0,0 +1,87 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import { Separator } from "@/components/ui/separator"
7
+
8
+ const buttonGroupVariants = cva(
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-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
10
+ {
11
+ variants: {
12
+ orientation: {
13
+ horizontal:
14
+ "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-lg! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
15
+ vertical:
16
+ "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-lg! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ orientation: "horizontal",
21
+ },
22
+ }
23
+ )
24
+
25
+ function ButtonGroup({
26
+ className,
27
+ orientation,
28
+ ...props
29
+ }: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
30
+ return (
31
+ <div
32
+ role="group"
33
+ data-slot="button-group"
34
+ data-orientation={orientation}
35
+ className={cn(buttonGroupVariants({ orientation }), className)}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function ButtonGroupText({
42
+ className,
43
+ render,
44
+ ...props
45
+ }: useRender.ComponentProps<"div">) {
46
+ return useRender({
47
+ defaultTagName: "div",
48
+ props: mergeProps<"div">(
49
+ {
50
+ className: cn(
51
+ "flex items-center gap-2 rounded-lg border bg-muted px-2.5 text-sm font-medium [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
52
+ className
53
+ ),
54
+ },
55
+ props
56
+ ),
57
+ render,
58
+ state: {
59
+ slot: "button-group-text",
60
+ },
61
+ })
62
+ }
63
+
64
+ function ButtonGroupSeparator({
65
+ className,
66
+ orientation = "vertical",
67
+ ...props
68
+ }: React.ComponentProps<typeof Separator>) {
69
+ return (
70
+ <Separator
71
+ data-slot="button-group-separator"
72
+ orientation={orientation}
73
+ className={cn(
74
+ "relative self-stretch bg-input data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
75
+ className
76
+ )}
77
+ {...props}
78
+ />
79
+ )
80
+ }
81
+
82
+ export {
83
+ ButtonGroup,
84
+ ButtonGroupSeparator,
85
+ ButtonGroupText,
86
+ buttonGroupVariants,
87
+ }
@@ -21,16 +21,16 @@ const buttonVariants = cva(
21
21
  },
22
22
  size: {
23
23
  default:
24
- "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
24
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
25
25
  xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
26
- sm: "h-8 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
27
- lg: "h-11 gap-2 px-5 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4",
28
- icon: "size-9",
26
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
27
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
28
+ icon: "size-8",
29
29
  "icon-xs":
30
30
  "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
31
31
  "icon-sm":
32
- "size-8 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
33
- "icon-lg": "size-10",
32
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
33
+ "icon-lg": "size-9",
34
34
  },
35
35
  },
36
36
  defaultVariants: {
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import * as React from "react"
4
2
  import {
5
3
  DayPicker,
@@ -12,7 +12,7 @@ function Card({
12
12
  data-slot="card"
13
13
  data-size={size}
14
14
  className={cn(
15
- "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl border bg-card py-(--card-spacing) text-sm text-card-foreground shadow-[0_1px_2px_rgba(0,0,0,0.04)] [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
15
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
16
16
  className
17
17
  )}
18
18
  {...props}
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import useEmblaCarousel, {
3
5
  type UseEmblaCarouselType,
@@ -0,0 +1,297 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Combobox as ComboboxPrimitive } from "@base-ui/react"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { Button } from "@/components/ui/button"
8
+ import {
9
+ InputGroup,
10
+ InputGroupAddon,
11
+ InputGroupButton,
12
+ InputGroupInput,
13
+ } from "@/components/ui/input-group"
14
+ import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"
15
+
16
+ const Combobox = ComboboxPrimitive.Root
17
+
18
+ function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
19
+ return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />
20
+ }
21
+
22
+ function ComboboxTrigger({
23
+ className,
24
+ children,
25
+ ...props
26
+ }: ComboboxPrimitive.Trigger.Props) {
27
+ return (
28
+ <ComboboxPrimitive.Trigger
29
+ data-slot="combobox-trigger"
30
+ className={cn("[&_svg:not([class*='size-'])]:size-4", className)}
31
+ {...props}
32
+ >
33
+ {children}
34
+ <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
35
+ </ComboboxPrimitive.Trigger>
36
+ )
37
+ }
38
+
39
+ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
40
+ return (
41
+ <ComboboxPrimitive.Clear
42
+ data-slot="combobox-clear"
43
+ render={<InputGroupButton variant="ghost" size="icon-xs" />}
44
+ className={cn(className)}
45
+ {...props}
46
+ >
47
+ <XIcon className="pointer-events-none" />
48
+ </ComboboxPrimitive.Clear>
49
+ )
50
+ }
51
+
52
+ function ComboboxInput({
53
+ className,
54
+ children,
55
+ disabled = false,
56
+ showTrigger = true,
57
+ showClear = false,
58
+ ...props
59
+ }: ComboboxPrimitive.Input.Props & {
60
+ showTrigger?: boolean
61
+ showClear?: boolean
62
+ }) {
63
+ return (
64
+ <InputGroup className={cn("w-auto", className)}>
65
+ <ComboboxPrimitive.Input
66
+ render={<InputGroupInput disabled={disabled} />}
67
+ {...props}
68
+ />
69
+ <InputGroupAddon align="inline-end">
70
+ {showTrigger && (
71
+ <InputGroupButton
72
+ size="icon-xs"
73
+ variant="ghost"
74
+ render={<ComboboxTrigger />}
75
+ data-slot="input-group-button"
76
+ className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
77
+ disabled={disabled}
78
+ />
79
+ )}
80
+ {showClear && <ComboboxClear disabled={disabled} />}
81
+ </InputGroupAddon>
82
+ {children}
83
+ </InputGroup>
84
+ )
85
+ }
86
+
87
+ function ComboboxContent({
88
+ className,
89
+ side = "bottom",
90
+ sideOffset = 6,
91
+ align = "start",
92
+ alignOffset = 0,
93
+ anchor,
94
+ ...props
95
+ }: ComboboxPrimitive.Popup.Props &
96
+ Pick<
97
+ ComboboxPrimitive.Positioner.Props,
98
+ "side" | "align" | "sideOffset" | "alignOffset" | "anchor"
99
+ >) {
100
+ return (
101
+ <ComboboxPrimitive.Portal>
102
+ <ComboboxPrimitive.Positioner
103
+ side={side}
104
+ sideOffset={sideOffset}
105
+ align={align}
106
+ alignOffset={alignOffset}
107
+ anchor={anchor}
108
+ className="isolate z-50"
109
+ >
110
+ <ComboboxPrimitive.Popup
111
+ data-slot="combobox-content"
112
+ data-chips={!!anchor}
113
+ className={cn("group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none 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", className )}
114
+ {...props}
115
+ />
116
+ </ComboboxPrimitive.Positioner>
117
+ </ComboboxPrimitive.Portal>
118
+ )
119
+ }
120
+
121
+ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
122
+ return (
123
+ <ComboboxPrimitive.List
124
+ data-slot="combobox-list"
125
+ className={cn(
126
+ "no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0",
127
+ className
128
+ )}
129
+ {...props}
130
+ />
131
+ )
132
+ }
133
+
134
+ function ComboboxItem({
135
+ className,
136
+ children,
137
+ ...props
138
+ }: ComboboxPrimitive.Item.Props) {
139
+ return (
140
+ <ComboboxPrimitive.Item
141
+ data-slot="combobox-item"
142
+ className={cn(
143
+ "relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
144
+ className
145
+ )}
146
+ {...props}
147
+ >
148
+ {children}
149
+ <ComboboxPrimitive.ItemIndicator
150
+ render={
151
+ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
152
+ }
153
+ >
154
+ <CheckIcon className="pointer-events-none" />
155
+ </ComboboxPrimitive.ItemIndicator>
156
+ </ComboboxPrimitive.Item>
157
+ )
158
+ }
159
+
160
+ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
161
+ return (
162
+ <ComboboxPrimitive.Group
163
+ data-slot="combobox-group"
164
+ className={cn(className)}
165
+ {...props}
166
+ />
167
+ )
168
+ }
169
+
170
+ function ComboboxLabel({
171
+ className,
172
+ ...props
173
+ }: ComboboxPrimitive.GroupLabel.Props) {
174
+ return (
175
+ <ComboboxPrimitive.GroupLabel
176
+ data-slot="combobox-label"
177
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
178
+ {...props}
179
+ />
180
+ )
181
+ }
182
+
183
+ function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {
184
+ return (
185
+ <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />
186
+ )
187
+ }
188
+
189
+ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
190
+ return (
191
+ <ComboboxPrimitive.Empty
192
+ data-slot="combobox-empty"
193
+ className={cn(
194
+ "hidden w-full justify-center py-2 text-center text-sm text-muted-foreground group-data-empty/combobox-content:flex",
195
+ className
196
+ )}
197
+ {...props}
198
+ />
199
+ )
200
+ }
201
+
202
+ function ComboboxSeparator({
203
+ className,
204
+ ...props
205
+ }: ComboboxPrimitive.Separator.Props) {
206
+ return (
207
+ <ComboboxPrimitive.Separator
208
+ data-slot="combobox-separator"
209
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
210
+ {...props}
211
+ />
212
+ )
213
+ }
214
+
215
+ function ComboboxChips({
216
+ className,
217
+ ...props
218
+ }: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &
219
+ ComboboxPrimitive.Chips.Props) {
220
+ return (
221
+ <ComboboxPrimitive.Chips
222
+ data-slot="combobox-chips"
223
+ className={cn(
224
+ "flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40",
225
+ className
226
+ )}
227
+ {...props}
228
+ />
229
+ )
230
+ }
231
+
232
+ function ComboboxChip({
233
+ className,
234
+ children,
235
+ showRemove = true,
236
+ ...props
237
+ }: ComboboxPrimitive.Chip.Props & {
238
+ showRemove?: boolean
239
+ }) {
240
+ return (
241
+ <ComboboxPrimitive.Chip
242
+ data-slot="combobox-chip"
243
+ className={cn(
244
+ "flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0",
245
+ className
246
+ )}
247
+ {...props}
248
+ >
249
+ {children}
250
+ {showRemove && (
251
+ <ComboboxPrimitive.ChipRemove
252
+ render={<Button variant="ghost" size="icon-xs" />}
253
+ className="-ml-1 opacity-50 hover:opacity-100"
254
+ data-slot="combobox-chip-remove"
255
+ >
256
+ <XIcon className="pointer-events-none" />
257
+ </ComboboxPrimitive.ChipRemove>
258
+ )}
259
+ </ComboboxPrimitive.Chip>
260
+ )
261
+ }
262
+
263
+ function ComboboxChipsInput({
264
+ className,
265
+ ...props
266
+ }: ComboboxPrimitive.Input.Props) {
267
+ return (
268
+ <ComboboxPrimitive.Input
269
+ data-slot="combobox-chip-input"
270
+ className={cn("min-w-16 flex-1 outline-none", className)}
271
+ {...props}
272
+ />
273
+ )
274
+ }
275
+
276
+ function useComboboxAnchor() {
277
+ return React.useRef<HTMLDivElement | null>(null)
278
+ }
279
+
280
+ export {
281
+ Combobox,
282
+ ComboboxInput,
283
+ ComboboxContent,
284
+ ComboboxList,
285
+ ComboboxItem,
286
+ ComboboxGroup,
287
+ ComboboxLabel,
288
+ ComboboxCollection,
289
+ ComboboxEmpty,
290
+ ComboboxSeparator,
291
+ ComboboxChips,
292
+ ComboboxChip,
293
+ ComboboxChipsInput,
294
+ ComboboxTrigger,
295
+ ComboboxValue,
296
+ useComboboxAnchor,
297
+ }