tembro 1.0.1 → 1.0.3
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/dist/components/calendar/calendar.cjs +1 -1
- package/dist/components/calendar/calendar.js +3 -3
- package/dist/components/calendar/date-picker.cjs +1 -1
- package/dist/components/calendar/date-picker.js +2 -2
- package/dist/components/calendar/date-range-picker.cjs +1 -1
- package/dist/components/calendar/date-range-picker.js +2 -4
- package/dist/components/data-table/data-table-toolbar.cjs +1 -1
- package/dist/components/data-table/data-table-toolbar.js +2 -2
- package/dist/components/data-table/data-table.cjs +1 -1
- package/dist/components/data-table/data-table.js +3 -3
- package/dist/components/display/carousel.cjs +1 -1
- package/dist/components/display/carousel.d.ts +3 -1
- package/dist/components/display/carousel.js +38 -27
- package/dist/components/inputs/async-select.cjs +1 -1
- package/dist/components/inputs/async-select.js +21 -21
- package/dist/components/inputs/combobox.cjs +1 -1
- package/dist/components/inputs/combobox.d.ts +5 -1
- package/dist/components/inputs/combobox.js +69 -59
- package/dist/components/inputs/simple-select.cjs +1 -1
- package/dist/components/inputs/simple-select.d.ts +1 -1
- package/dist/components/inputs/simple-select.js +5 -5
- package/dist/components/ui/button.cjs +1 -0
- package/dist/components/ui/button.d.ts +1 -0
- package/dist/components/ui/button.js +2 -0
- package/dist/components/ui/input.cjs +1 -0
- package/dist/components/ui/input.d.ts +1 -0
- package/dist/components/ui/input.js +3 -0
- package/dist/components/ui/select/index.cjs +1 -1
- package/dist/components/ui/select/index.d.ts +1 -1
- package/dist/components/ui/select/index.js +3 -3
- package/dist/showcase/tembro-registry.json.cjs +1 -1
- package/dist/showcase/tembro-registry.json.js +1 -1
- package/package.json +2 -1
- package/packages/cli/dist/index.cjs +2 -2
- package/packages/cli/vendor/src/components/calendar/calendar.tsx +3 -3
- package/packages/cli/vendor/src/components/calendar/date-picker.tsx +2 -2
- package/packages/cli/vendor/src/components/calendar/date-range-picker.tsx +4 -5
- package/packages/cli/vendor/src/components/data-table/data-table-toolbar.tsx +2 -2
- package/packages/cli/vendor/src/components/data-table/data-table.tsx +3 -3
- package/packages/cli/vendor/src/components/display/carousel.tsx +30 -12
- package/packages/cli/vendor/src/components/inputs/async-select.tsx +22 -22
- package/packages/cli/vendor/src/components/inputs/combobox.tsx +71 -41
- package/packages/cli/vendor/src/components/inputs/simple-select.tsx +6 -6
- package/packages/cli/vendor/src/components/ui/button.tsx +2 -0
- package/packages/cli/vendor/src/components/ui/input.tsx +2 -0
- package/packages/cli/vendor/src/components/ui/select/index.tsx +4 -4
- package/packages/cli/vendor/src/showcase/tembro-registry.json +1 -1
- package/registry.json +1 -1
|
@@ -314,7 +314,7 @@ function AsyncStateMessage({
|
|
|
314
314
|
<div
|
|
315
315
|
data-slot="async-select-state"
|
|
316
316
|
className={cn(
|
|
317
|
-
"rounded-[
|
|
317
|
+
"rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:color-mix(in_oklch,var(--muted),transparent_55%)] px-3 py-3 text-sm leading-5 text-muted-foreground",
|
|
318
318
|
className
|
|
319
319
|
)}
|
|
320
320
|
>
|
|
@@ -356,18 +356,18 @@ function AsyncOptionButton<
|
|
|
356
356
|
data-selected={selected || undefined}
|
|
357
357
|
data-disabled={option.disabled || undefined}
|
|
358
358
|
className={cn(
|
|
359
|
-
"flex w-full items-start gap-2 rounded-[
|
|
359
|
+
"flex w-full items-start gap-2.5 rounded-[var(--radius-md)] border border-transparent px-3 py-2.5 text-left text-sm outline-none transition-[background-color,border-color,color,box-shadow] hover:border-[color:color-mix(in_oklch,var(--primary),transparent_76%)] hover:bg-[color:color-mix(in_oklch,var(--primary),transparent_93%)] focus-visible:border-[color:var(--aui-focus-ring,var(--ring))] focus-visible:shadow-[0_0_0_3px_var(--aui-focus-ring-soft,transparent)] data-[selected=true]:border-[color:color-mix(in_oklch,var(--primary),transparent_68%)] data-[selected=true]:bg-[color:color-mix(in_oklch,var(--primary),transparent_89%)] data-[selected=true]:text-foreground disabled:pointer-events-none disabled:opacity-50",
|
|
360
360
|
optionClassName
|
|
361
361
|
)}
|
|
362
362
|
onClick={() => onSelect(option)}
|
|
363
363
|
>
|
|
364
|
-
<span className="flex size-4 shrink-0 items-center justify-center">
|
|
365
|
-
{selected && <CheckIcon className="size-
|
|
364
|
+
<span className={cn("mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full border border-border/70", selected && "border-primary bg-primary text-primary-foreground")}>
|
|
365
|
+
{selected && <CheckIcon className="size-3" />}
|
|
366
366
|
</span>
|
|
367
367
|
<span className="min-w-0 flex-1">
|
|
368
368
|
{renderOption?.(option, { selected }) ?? (
|
|
369
369
|
<span className="flex min-w-0 flex-col">
|
|
370
|
-
<span className="truncate">{option.label}</span>
|
|
370
|
+
<span className="truncate font-medium">{option.label}</span>
|
|
371
371
|
{option.description && (
|
|
372
372
|
<span className="truncate text-xs text-muted-foreground">{option.description}</span>
|
|
373
373
|
)}
|
|
@@ -397,7 +397,7 @@ function AsyncCreateButton({
|
|
|
397
397
|
type="button"
|
|
398
398
|
disabled={isCreating}
|
|
399
399
|
data-slot="async-select-create"
|
|
400
|
-
className="flex w-full items-center gap-2 rounded-[
|
|
400
|
+
className="flex w-full items-center gap-2 rounded-[var(--radius-md)] border border-dashed border-[color:color-mix(in_oklch,var(--primary),transparent_55%)] bg-[color:color-mix(in_oklch,var(--primary),transparent_94%)] px-3 py-2.5 text-left text-sm font-medium text-foreground outline-none transition-[background-color,border-color,color,box-shadow] hover:bg-[color:color-mix(in_oklch,var(--primary),transparent_90%)] disabled:pointer-events-none disabled:opacity-50"
|
|
401
401
|
onClick={onCreate}
|
|
402
402
|
>
|
|
403
403
|
<span className="flex size-4 shrink-0 items-center justify-center">
|
|
@@ -625,17 +625,17 @@ function AsyncSelect<
|
|
|
625
625
|
aria-invalid={invalid || undefined}
|
|
626
626
|
data-slot="async-select-trigger"
|
|
627
627
|
className={cn(
|
|
628
|
-
"min-h-11 w-full justify-between",
|
|
628
|
+
"min-h-11 w-full justify-between rounded-[var(--aui-control-radius,var(--radius-md))] px-3.5 text-left",
|
|
629
629
|
triggerClassName
|
|
630
630
|
)}
|
|
631
631
|
onKeyDown={handleTriggerKeyDown}
|
|
632
632
|
/>
|
|
633
633
|
}
|
|
634
634
|
>
|
|
635
|
-
<span className="min-w-0 flex-1 text-left">
|
|
635
|
+
<span className="min-w-0 flex-1 text-left">
|
|
636
636
|
{currentOption ? (
|
|
637
|
-
<span className="flex min-w-0 flex-col">
|
|
638
|
-
<span className="truncate">
|
|
637
|
+
<span className="flex min-w-0 flex-col gap-0.5">
|
|
638
|
+
<span className="truncate font-semibold">
|
|
639
639
|
{renderValue?.(currentOption) ?? currentOption.label}
|
|
640
640
|
</span>
|
|
641
641
|
{currentOption.disabled && currentOption.disabledReason && (
|
|
@@ -643,7 +643,7 @@ function AsyncSelect<
|
|
|
643
643
|
)}
|
|
644
644
|
</span>
|
|
645
645
|
) : (
|
|
646
|
-
<span className="truncate">{labels?.placeholder ?? "Select"}</span>
|
|
646
|
+
<span className="truncate text-muted-foreground">{labels?.placeholder ?? "Select"}</span>
|
|
647
647
|
)}
|
|
648
648
|
</span>
|
|
649
649
|
<span className="ml-2 flex shrink-0 items-center gap-1">
|
|
@@ -671,7 +671,7 @@ function AsyncSelect<
|
|
|
671
671
|
align="start"
|
|
672
672
|
data-slot="async-select-content"
|
|
673
673
|
className={cn(
|
|
674
|
-
"w-(--anchor-width) gap-3 rounded-[var(--radius-
|
|
674
|
+
"w-(--anchor-width) min-w-72 gap-3 rounded-[var(--aui-card-radius,var(--radius-lg))] border-[color:var(--aui-card-border,var(--border))] bg-popover p-3 shadow-[var(--aui-control-panel-shadow,0_18px_40px_rgba(15,23,42,0.14))]",
|
|
675
675
|
contentClassName
|
|
676
676
|
)}
|
|
677
677
|
>
|
|
@@ -686,7 +686,7 @@ function AsyncSelect<
|
|
|
686
686
|
/>
|
|
687
687
|
</div>
|
|
688
688
|
|
|
689
|
-
<div className="max-h-
|
|
689
|
+
<div className="max-h-72 space-y-1 overflow-y-auto pr-1">
|
|
690
690
|
{searchTooShort && flatOptions.length === 0 && (
|
|
691
691
|
renderMinSearch?.(state) ?? (
|
|
692
692
|
<AsyncStateMessage>
|
|
@@ -1043,7 +1043,7 @@ function AsyncMultiSelect<
|
|
|
1043
1043
|
aria-invalid={invalid || undefined}
|
|
1044
1044
|
data-slot="async-select-trigger"
|
|
1045
1045
|
className={cn(
|
|
1046
|
-
"min-h-11 w-full justify-between",
|
|
1046
|
+
"min-h-11 w-full justify-between rounded-[var(--aui-control-radius,var(--radius-md))] px-3.5 text-left",
|
|
1047
1047
|
triggerClassName
|
|
1048
1048
|
)}
|
|
1049
1049
|
onKeyDown={handleTriggerKeyDown}
|
|
@@ -1057,7 +1057,7 @@ function AsyncMultiSelect<
|
|
|
1057
1057
|
key={option.value}
|
|
1058
1058
|
data-slot="async-select-tag"
|
|
1059
1059
|
className={cn(
|
|
1060
|
-
"inline-flex max-w-full items-center gap-1 rounded-
|
|
1060
|
+
"inline-flex max-w-full items-center gap-1.5 rounded-[var(--radius-sm)] border border-[color:color-mix(in_oklch,var(--primary),transparent_70%)] bg-[color:color-mix(in_oklch,var(--primary),transparent_92%)] px-2 py-1 text-xs font-medium text-foreground",
|
|
1061
1061
|
tagClassName
|
|
1062
1062
|
)}
|
|
1063
1063
|
>
|
|
@@ -1076,7 +1076,7 @@ function AsyncMultiSelect<
|
|
|
1076
1076
|
role="button"
|
|
1077
1077
|
tabIndex={0}
|
|
1078
1078
|
data-slot="async-select-tag-remove"
|
|
1079
|
-
className="rounded-full text-muted-foreground transition-colors hover:text-foreground"
|
|
1079
|
+
className="rounded-full p-0.5 text-muted-foreground transition-colors hover:bg-background hover:text-foreground"
|
|
1080
1080
|
aria-label={`Remove ${getOptionLabelText(option)}`}
|
|
1081
1081
|
onClick={(event) => {
|
|
1082
1082
|
stopInteractivePropagation(event)
|
|
@@ -1101,7 +1101,7 @@ function AsyncMultiSelect<
|
|
|
1101
1101
|
role="button"
|
|
1102
1102
|
tabIndex={0}
|
|
1103
1103
|
data-slot="async-select-clear"
|
|
1104
|
-
className="rounded-full border p-1 text-muted-foreground transition-colors hover:text-foreground"
|
|
1104
|
+
className="rounded-full border border-border/65 p-1 text-muted-foreground transition-colors hover:border-border hover:bg-muted/55 hover:text-foreground"
|
|
1105
1105
|
aria-label={labels?.clearAll ?? labels?.clear ?? "Clear all"}
|
|
1106
1106
|
onClick={handleClear}
|
|
1107
1107
|
onKeyDown={(event) => {
|
|
@@ -1121,7 +1121,7 @@ function AsyncMultiSelect<
|
|
|
1121
1121
|
align="start"
|
|
1122
1122
|
data-slot="async-select-content"
|
|
1123
1123
|
className={cn(
|
|
1124
|
-
"w-(--anchor-width) gap-3 rounded-[var(--radius-
|
|
1124
|
+
"w-(--anchor-width) min-w-72 gap-3 rounded-[var(--aui-card-radius,var(--radius-lg))] border-[color:var(--aui-card-border,var(--border))] bg-popover p-3 shadow-[var(--aui-control-panel-shadow,0_18px_40px_rgba(15,23,42,0.14))]",
|
|
1125
1125
|
contentClassName
|
|
1126
1126
|
)}
|
|
1127
1127
|
>
|
|
@@ -1136,7 +1136,7 @@ function AsyncMultiSelect<
|
|
|
1136
1136
|
/>
|
|
1137
1137
|
</div>
|
|
1138
1138
|
|
|
1139
|
-
<div data-slot="async-select-meta" className="flex flex-wrap items-center justify-between gap-2 rounded-[
|
|
1139
|
+
<div data-slot="async-select-meta" className="flex flex-wrap items-center justify-between gap-2 rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:color-mix(in_oklch,var(--muted),transparent_62%)] px-3 py-2 text-xs text-muted-foreground">
|
|
1140
1140
|
{hasValue && labels?.selectedCount && <span>{labels.selectedCount(values.length)}</span>}
|
|
1141
1141
|
{isMaxReached &&
|
|
1142
1142
|
(renderMaxSelected?.(state) ?? (
|
|
@@ -1147,7 +1147,7 @@ function AsyncMultiSelect<
|
|
|
1147
1147
|
<button
|
|
1148
1148
|
type="button"
|
|
1149
1149
|
data-slot="async-select-meta-action"
|
|
1150
|
-
className="rounded-
|
|
1150
|
+
className="rounded-[var(--radius-sm)] border border-border/75 px-2.5 py-1 font-medium text-foreground transition-colors hover:bg-background"
|
|
1151
1151
|
onClick={handleSelectAllVisible}
|
|
1152
1152
|
>
|
|
1153
1153
|
{labels?.selectAll ?? "Select all"}
|
|
@@ -1157,7 +1157,7 @@ function AsyncMultiSelect<
|
|
|
1157
1157
|
<button
|
|
1158
1158
|
type="button"
|
|
1159
1159
|
data-slot="async-select-meta-action"
|
|
1160
|
-
className="rounded-
|
|
1160
|
+
className="rounded-[var(--radius-sm)] border border-border/75 px-2.5 py-1 font-medium text-foreground transition-colors hover:bg-background"
|
|
1161
1161
|
onClick={() => onValueChange?.([], [])}
|
|
1162
1162
|
>
|
|
1163
1163
|
{labels?.clearAll ?? labels?.clear ?? "Clear all"}
|
|
@@ -1166,7 +1166,7 @@ function AsyncMultiSelect<
|
|
|
1166
1166
|
</div>
|
|
1167
1167
|
</div>
|
|
1168
1168
|
|
|
1169
|
-
<div className="max-h-
|
|
1169
|
+
<div className="max-h-72 space-y-1 overflow-y-auto pr-1">
|
|
1170
1170
|
{searchTooShort && flatOptions.length === 0 && (
|
|
1171
1171
|
renderMinSearch?.(state) ?? (
|
|
1172
1172
|
<AsyncStateMessage>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react"
|
|
3
3
|
|
|
4
|
-
import { Button } from "@/components/ui/button"
|
|
5
|
-
import { Input } from "@/components/ui/input"
|
|
6
|
-
import {
|
|
4
|
+
import { Button } from "@/components/ui/button"
|
|
5
|
+
import { Input } from "@/components/ui/input"
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
7
8
|
|
|
8
9
|
export type ComboboxOption<TValue extends string = string> = {
|
|
9
10
|
value: TValue
|
|
@@ -22,8 +23,12 @@ export type ComboboxProps<TValue extends string = string> = React.ComponentProps
|
|
|
22
23
|
searchPlaceholder?: string
|
|
23
24
|
emptyLabel?: React.ReactNode
|
|
24
25
|
disabled?: boolean
|
|
25
|
-
invalid?: boolean
|
|
26
|
-
|
|
26
|
+
invalid?: boolean
|
|
27
|
+
triggerClassName?: string
|
|
28
|
+
contentClassName?: string
|
|
29
|
+
optionClassName?: string
|
|
30
|
+
searchClassName?: string
|
|
31
|
+
}
|
|
27
32
|
|
|
28
33
|
function Combobox<TValue extends string = string>({
|
|
29
34
|
value,
|
|
@@ -32,11 +37,15 @@ function Combobox<TValue extends string = string>({
|
|
|
32
37
|
placeholder = "Select option",
|
|
33
38
|
searchPlaceholder = "Search...",
|
|
34
39
|
emptyLabel = "No option found",
|
|
35
|
-
disabled = false,
|
|
36
|
-
invalid,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
disabled = false,
|
|
41
|
+
invalid,
|
|
42
|
+
triggerClassName,
|
|
43
|
+
contentClassName,
|
|
44
|
+
optionClassName,
|
|
45
|
+
searchClassName,
|
|
46
|
+
className,
|
|
47
|
+
...props
|
|
48
|
+
}: ComboboxProps<TValue>) {
|
|
40
49
|
const [open, setOpen] = React.useState(false)
|
|
41
50
|
const [search, setSearch] = React.useState("")
|
|
42
51
|
const selectedOption = options.find((option) => option.value === value)
|
|
@@ -47,45 +56,66 @@ function Combobox<TValue extends string = string>({
|
|
|
47
56
|
return String(option.searchValue ?? option.label).toLowerCase().includes(normalizedSearch)
|
|
48
57
|
})
|
|
49
58
|
|
|
50
|
-
return (
|
|
51
|
-
<div data-slot="combobox" className={cn("
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
return (
|
|
60
|
+
<div data-slot="combobox" className={cn("grid w-full gap-2", className)} {...props}>
|
|
61
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
62
|
+
<PopoverTrigger
|
|
63
|
+
render={
|
|
64
|
+
<Button
|
|
65
|
+
type="button"
|
|
66
|
+
variant="outline"
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
aria-expanded={open}
|
|
69
|
+
aria-invalid={invalid || undefined}
|
|
70
|
+
className={cn("min-h-11 w-full justify-between rounded-[var(--aui-control-radius,var(--radius-md))] px-3.5 text-left", triggerClassName)}
|
|
71
|
+
/>
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
<span className={cn("min-w-0 flex-1 truncate font-medium", !selectedOption && "font-normal text-muted-foreground")}>
|
|
75
|
+
{selectedOption?.label ?? placeholder}
|
|
76
|
+
</span>
|
|
77
|
+
<ChevronDownIcon className="size-4 opacity-60" />
|
|
78
|
+
</PopoverTrigger>
|
|
79
|
+
<PopoverContent
|
|
80
|
+
align="start"
|
|
81
|
+
data-slot="combobox-content"
|
|
82
|
+
className={cn("w-(--anchor-width) min-w-72 rounded-[var(--aui-card-radius,var(--radius-lg))] border-[color:var(--aui-card-border,var(--border))] bg-popover p-3 shadow-[var(--aui-control-panel-shadow,0_18px_40px_rgba(15,23,42,0.14))]", contentClassName)}
|
|
83
|
+
>
|
|
84
|
+
<div className="relative mb-2">
|
|
85
|
+
<SearchIcon className="pointer-events-none absolute left-2 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
86
|
+
<Input value={search} onChange={(event) => setSearch(event.target.value)} placeholder={searchPlaceholder} className={cn("h-9 pl-8", searchClassName)} />
|
|
87
|
+
</div>
|
|
88
|
+
<div className="max-h-64 overflow-y-auto">
|
|
89
|
+
{filteredOptions.length ? filteredOptions.map((option) => {
|
|
64
90
|
const active = option.value === value
|
|
65
91
|
return (
|
|
66
92
|
<button
|
|
67
|
-
key={option.value}
|
|
68
|
-
type="button"
|
|
69
|
-
disabled={option.disabled}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
key={option.value}
|
|
94
|
+
type="button"
|
|
95
|
+
disabled={option.disabled}
|
|
96
|
+
data-selected={active || undefined}
|
|
97
|
+
className={cn(
|
|
98
|
+
"flex w-full items-start gap-2.5 rounded-[var(--radius-md)] border border-transparent px-3 py-2.5 text-left text-sm transition-colors hover:border-[color:color-mix(in_oklch,var(--primary),transparent_76%)] hover:bg-[color:color-mix(in_oklch,var(--primary),transparent_93%)] disabled:pointer-events-none disabled:opacity-50 data-[selected=true]:border-[color:color-mix(in_oklch,var(--primary),transparent_68%)] data-[selected=true]:bg-[color:color-mix(in_oklch,var(--primary),transparent_89%)]",
|
|
99
|
+
optionClassName
|
|
100
|
+
)}
|
|
101
|
+
onClick={() => {
|
|
102
|
+
onValueChange?.(option.value, option)
|
|
103
|
+
setOpen(false)
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<span className={cn("mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full border border-border/70", active && "border-primary bg-primary text-primary-foreground")}>{active && <CheckIcon className="size-3" />}</span>
|
|
77
107
|
<span className="min-w-0">
|
|
78
108
|
<span className="block truncate font-medium">{option.label}</span>
|
|
79
109
|
{option.description && <span className="block text-xs text-muted-foreground">{option.description}</span>}
|
|
80
110
|
</span>
|
|
81
111
|
</button>
|
|
82
112
|
)
|
|
83
|
-
}) : <div className="px-
|
|
84
|
-
</div>
|
|
85
|
-
</
|
|
86
|
-
|
|
87
|
-
</div>
|
|
88
|
-
)
|
|
89
|
-
}
|
|
113
|
+
}) : <div className="rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:color-mix(in_oklch,var(--muted),transparent_55%)] px-3 py-6 text-center text-sm text-muted-foreground">{emptyLabel}</div>}
|
|
114
|
+
</div>
|
|
115
|
+
</PopoverContent>
|
|
116
|
+
</Popover>
|
|
117
|
+
</div>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
90
120
|
|
|
91
121
|
export { Combobox }
|
|
@@ -29,7 +29,7 @@ export type SimpleSelectProps = Omit<
|
|
|
29
29
|
searchPlaceholder?: string
|
|
30
30
|
emptyLabel?: React.ReactNode
|
|
31
31
|
clearLabel?: string
|
|
32
|
-
size?: "sm" | "default"
|
|
32
|
+
size?: "sm" | "default" | "lg"
|
|
33
33
|
clearable?: boolean
|
|
34
34
|
searchable?: boolean
|
|
35
35
|
loading?: boolean
|
|
@@ -94,7 +94,7 @@ function SimpleSelect({
|
|
|
94
94
|
<button
|
|
95
95
|
type="button"
|
|
96
96
|
aria-label={clearLabel}
|
|
97
|
-
className="ml-1 rounded-sm p-
|
|
97
|
+
className="ml-1 rounded-[var(--radius-sm)] border border-border/65 p-1 text-muted-foreground transition-colors hover:border-border hover:bg-muted/55 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
98
98
|
onClick={(event) => {
|
|
99
99
|
event.preventDefault()
|
|
100
100
|
stopInteractivePropagation(event)
|
|
@@ -114,7 +114,7 @@ function SimpleSelect({
|
|
|
114
114
|
)}
|
|
115
115
|
>
|
|
116
116
|
{searchable ? (
|
|
117
|
-
<div data-slot="select-search" className="sticky top-0 z-10 mb-1 flex items-center gap-2 rounded-[
|
|
117
|
+
<div data-slot="select-search" className="sticky top-0 z-10 mb-1 flex items-center gap-2 rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-popover px-2.5 py-2 text-sm">
|
|
118
118
|
<SearchIcon className="size-4 text-muted-foreground" />
|
|
119
119
|
<input
|
|
120
120
|
value={search}
|
|
@@ -126,12 +126,12 @@ function SimpleSelect({
|
|
|
126
126
|
) : null}
|
|
127
127
|
|
|
128
128
|
{loading ? (
|
|
129
|
-
<div data-slot="select-state" className="flex items-center gap-2 rounded-[
|
|
129
|
+
<div data-slot="select-state" className="flex items-center gap-2 rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:color-mix(in_oklch,var(--muted),transparent_55%)] px-3 py-2.5 text-sm text-muted-foreground">
|
|
130
130
|
<LoaderCircleIcon className="size-4 animate-spin" />
|
|
131
131
|
{loadingLabel}
|
|
132
132
|
</div>
|
|
133
133
|
) : filteredOptions.length === 0 ? (
|
|
134
|
-
<div data-slot="select-state" className="rounded-[
|
|
134
|
+
<div data-slot="select-state" className="rounded-[var(--radius-md)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:color-mix(in_oklch,var(--muted),transparent_55%)] px-3 py-2.5 text-sm text-muted-foreground">{emptyLabel}</div>
|
|
135
135
|
) : (
|
|
136
136
|
filteredOptions.map((option) => {
|
|
137
137
|
const selected = option.value === value
|
|
@@ -140,7 +140,7 @@ function SimpleSelect({
|
|
|
140
140
|
key={option.value}
|
|
141
141
|
value={option.value}
|
|
142
142
|
disabled={option.disabled}
|
|
143
|
-
className={cn("rounded-[
|
|
143
|
+
className={cn("rounded-[var(--radius-md)]", itemClassName)}
|
|
144
144
|
>
|
|
145
145
|
{renderOption ? (
|
|
146
146
|
renderOption(option, { selected })
|
|
@@ -9,7 +9,7 @@ import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
|
|
|
9
9
|
export type SelectRootProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>
|
|
10
10
|
export type SelectGroupProps = SelectPrimitive.Group.Props
|
|
11
11
|
export type SelectValueProps = SelectPrimitive.Value.Props
|
|
12
|
-
export type SelectTriggerProps = SelectPrimitive.Trigger.Props & { size?: "sm" | "default" }
|
|
12
|
+
export type SelectTriggerProps = SelectPrimitive.Trigger.Props & { size?: "sm" | "default" | "lg" }
|
|
13
13
|
export type SelectContentProps = SelectPrimitive.Popup.Props &
|
|
14
14
|
Pick<
|
|
15
15
|
SelectPrimitive.Positioner.Props,
|
|
@@ -54,7 +54,7 @@ function SelectTrigger({
|
|
|
54
54
|
data-slot="select-trigger"
|
|
55
55
|
data-size={size}
|
|
56
56
|
className={cn(
|
|
57
|
-
"flex w-
|
|
57
|
+
"flex w-full min-w-0 items-center justify-between gap-2 rounded-[var(--aui-control-radius,var(--radius-md))] border border-[color:var(--aui-control-border-strong,var(--input))] bg-[color:var(--aui-control-surface,var(--background))] pr-3 pl-3 text-sm whitespace-nowrap text-foreground shadow-[var(--aui-control-shadow,0_1px_2px_rgba(15,23,42,0.04))] transition-[background-color,border-color,box-shadow,color] outline-none select-none hover:border-[color:var(--aui-control-hover-border,var(--ring))] hover:bg-[color:var(--aui-control-surface-hover,var(--background))] hover:shadow-[var(--aui-control-shadow-hover,0_2px_6px_rgba(15,23,42,0.06))] focus-visible:border-[color:var(--ring)] focus-visible:ring-0 focus-visible:shadow-[var(--aui-control-shadow,0_1px_2px_rgba(15,23,42,0.04)),0_0_0_1px_var(--aui-focus-ring,var(--ring)),0_0_0_4px_var(--aui-focus-ring-soft,transparent)] disabled:cursor-not-allowed disabled:border-[color:color-mix(in_oklch,var(--border),transparent_18%)] disabled:bg-[color:var(--aui-control-surface-disabled,var(--muted))] disabled:opacity-100 aria-invalid:border-destructive aria-invalid:shadow-[var(--aui-control-shadow,0_1px_2px_rgba(15,23,42,0.04)),0_0_0_1px_var(--aui-danger-ring,var(--destructive)),0_0_0_4px_var(--aui-danger-ring-soft,transparent)] data-placeholder:text-muted-foreground/74 data-[size=default]:h-10 data-[size=lg]:h-11 data-[size=sm]:h-9 data-[size=sm]:rounded-[var(--radius-sm)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:min-w-0 *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
58
58
|
className
|
|
59
59
|
)}
|
|
60
60
|
{...props}
|
|
@@ -92,7 +92,7 @@ function SelectContent({
|
|
|
92
92
|
<SelectPrimitive.Popup
|
|
93
93
|
data-slot="select-content"
|
|
94
94
|
data-align-trigger={alignItemWithTrigger}
|
|
95
|
-
className={cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-
|
|
95
|
+
className={cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-52 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--aui-card-radius,var(--radius-lg))] border border-[color:var(--aui-card-border,var(--border))] bg-popover p-1.5 text-popover-foreground shadow-[var(--aui-control-panel-shadow,0_18px_40px_rgba(15,23,42,0.14))] backdrop-blur duration-100 data-[align-trigger=true]:animate-none 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-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)}
|
|
96
96
|
{...props}
|
|
97
97
|
>
|
|
98
98
|
<SelectScrollUpButton />
|
|
@@ -126,7 +126,7 @@ function SelectItem({
|
|
|
126
126
|
<SelectPrimitive.Item
|
|
127
127
|
data-slot="select-item"
|
|
128
128
|
className={cn(
|
|
129
|
-
"relative flex w-full cursor-default items-center gap-
|
|
129
|
+
"relative flex w-full cursor-default items-center gap-2 rounded-[var(--radius-md)] border border-transparent py-2.5 pr-9 pl-3 text-sm text-[color:var(--aui-page-muted-strong,var(--foreground))] outline-hidden select-none transition-[background-color,border-color,color,box-shadow,transform] data-[highlighted]:border-[color:color-mix(in_oklch,var(--primary),transparent_72%)] data-[highlighted]:bg-[color:color-mix(in_oklch,var(--primary),transparent_92%)] data-[highlighted]:text-foreground data-[selected]:border-[color:color-mix(in_oklch,var(--primary),transparent_70%)] data-[selected]:bg-[color:color-mix(in_oklch,var(--primary),transparent_90%)] data-[selected]:font-semibold data-[selected]:text-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:min-w-0 *:[span]:last:items-center *:[span]:last:gap-2",
|
|
130
130
|
className
|
|
131
131
|
)}
|
|
132
132
|
{...props}
|