@boyernick/standard-ui-react 0.1.0
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/README.md +9 -0
- package/package.json +46 -0
- package/src/accordion.tsx +84 -0
- package/src/alert-dialog.tsx +101 -0
- package/src/attachment.tsx +138 -0
- package/src/autocomplete.tsx +281 -0
- package/src/avatar.tsx +56 -0
- package/src/badge.tsx +28 -0
- package/src/brand.tsx +70 -0
- package/src/breadcrumb.tsx +81 -0
- package/src/button.tsx +129 -0
- package/src/calendar.tsx +84 -0
- package/src/card.tsx +54 -0
- package/src/carousel.tsx +253 -0
- package/src/chart.tsx +185 -0
- package/src/checkbox-group.tsx +14 -0
- package/src/checkbox.tsx +31 -0
- package/src/code-block.tsx +124 -0
- package/src/collapsible.tsx +61 -0
- package/src/combobox.tsx +324 -0
- package/src/command.tsx +377 -0
- package/src/context-menu.tsx +250 -0
- package/src/dialog.tsx +78 -0
- package/src/drawer.tsx +156 -0
- package/src/empty.tsx +52 -0
- package/src/field.tsx +75 -0
- package/src/fieldset.tsx +25 -0
- package/src/form.tsx +14 -0
- package/src/icons.tsx +91 -0
- package/src/illustrations.tsx +167 -0
- package/src/image-modal.tsx +110 -0
- package/src/index.ts +833 -0
- package/src/input.tsx +68 -0
- package/src/lib/cn.ts +3 -0
- package/src/lib/motion.ts +23 -0
- package/src/markdown-editor.tsx +302 -0
- package/src/menu.tsx +205 -0
- package/src/menubar.tsx +22 -0
- package/src/meter.tsx +61 -0
- package/src/navigation-menu.tsx +217 -0
- package/src/number-field.tsx +119 -0
- package/src/orb.tsx +33 -0
- package/src/otp-field.tsx +45 -0
- package/src/pagination.tsx +91 -0
- package/src/popover.tsx +92 -0
- package/src/preview-card.tsx +103 -0
- package/src/progress.tsx +60 -0
- package/src/radio.tsx +43 -0
- package/src/scroll-area.tsx +67 -0
- package/src/select.tsx +161 -0
- package/src/separator.tsx +17 -0
- package/src/sidebar.tsx +82 -0
- package/src/skeleton.tsx +32 -0
- package/src/slider.tsx +56 -0
- package/src/sounds.tsx +270 -0
- package/src/spinner.tsx +45 -0
- package/src/switch.tsx +19 -0
- package/src/table.tsx +81 -0
- package/src/tabs.tsx +62 -0
- package/src/text-animate.tsx +155 -0
- package/src/textarea.tsx +58 -0
- package/src/ticker.tsx +74 -0
- package/src/toast.tsx +142 -0
- package/src/toggle.tsx +32 -0
- package/src/toolbar.tsx +75 -0
- package/src/tooltip.tsx +55 -0
- package/src/video-player.tsx +241 -0
package/src/combobox.tsx
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
|
|
4
|
+
import type { ComponentProps, ReactElement } from "react"
|
|
5
|
+
import { IconChevronDownSmall, IconCrossSmall } from "./icons"
|
|
6
|
+
import { cn } from "./lib/cn"
|
|
7
|
+
import { motion } from "./lib/motion"
|
|
8
|
+
|
|
9
|
+
export type ComboboxProps<
|
|
10
|
+
Value,
|
|
11
|
+
Multiple extends boolean | undefined = false,
|
|
12
|
+
> = ComponentProps<typeof BaseCombobox.Root<Value, Multiple>>
|
|
13
|
+
export type ComboboxLabelProps = ComponentProps<typeof BaseCombobox.Label>
|
|
14
|
+
export type ComboboxInputProps = ComponentProps<typeof BaseCombobox.Input>
|
|
15
|
+
export type ComboboxInputGroupProps = ComponentProps<
|
|
16
|
+
typeof BaseCombobox.InputGroup
|
|
17
|
+
>
|
|
18
|
+
export type ComboboxTriggerProps = ComponentProps<typeof BaseCombobox.Trigger>
|
|
19
|
+
export type ComboboxIconProps = ComponentProps<typeof BaseCombobox.Icon>
|
|
20
|
+
export type ComboboxClearProps = ComponentProps<typeof BaseCombobox.Clear>
|
|
21
|
+
export type ComboboxValueProps = ComponentProps<typeof BaseCombobox.Value>
|
|
22
|
+
export type ComboboxPortalProps = ComponentProps<typeof BaseCombobox.Portal>
|
|
23
|
+
export type ComboboxBackdropProps = ComponentProps<typeof BaseCombobox.Backdrop>
|
|
24
|
+
export type ComboboxPositionerProps = ComponentProps<
|
|
25
|
+
typeof BaseCombobox.Positioner
|
|
26
|
+
>
|
|
27
|
+
export type ComboboxPopupProps = ComponentProps<typeof BaseCombobox.Popup>
|
|
28
|
+
export type ComboboxArrowProps = ComponentProps<typeof BaseCombobox.Arrow>
|
|
29
|
+
export type ComboboxListProps = ComponentProps<typeof BaseCombobox.List>
|
|
30
|
+
export type ComboboxItemProps = ComponentProps<typeof BaseCombobox.Item>
|
|
31
|
+
export type ComboboxItemIndicatorProps = ComponentProps<
|
|
32
|
+
typeof BaseCombobox.ItemIndicator
|
|
33
|
+
>
|
|
34
|
+
export type ComboboxEmptyProps = ComponentProps<typeof BaseCombobox.Empty>
|
|
35
|
+
export type ComboboxStatusProps = ComponentProps<typeof BaseCombobox.Status>
|
|
36
|
+
export type ComboboxGroupProps = ComponentProps<typeof BaseCombobox.Group>
|
|
37
|
+
export type ComboboxGroupLabelProps = ComponentProps<
|
|
38
|
+
typeof BaseCombobox.GroupLabel
|
|
39
|
+
>
|
|
40
|
+
export type ComboboxSeparatorProps = ComponentProps<
|
|
41
|
+
typeof BaseCombobox.Separator
|
|
42
|
+
>
|
|
43
|
+
export type ComboboxCollectionProps = ComponentProps<
|
|
44
|
+
typeof BaseCombobox.Collection
|
|
45
|
+
>
|
|
46
|
+
export type ComboboxChipsProps = ComponentProps<typeof BaseCombobox.Chips>
|
|
47
|
+
export type ComboboxChipProps = ComponentProps<typeof BaseCombobox.Chip>
|
|
48
|
+
export type ComboboxChipRemoveProps = ComponentProps<
|
|
49
|
+
typeof BaseCombobox.ChipRemove
|
|
50
|
+
>
|
|
51
|
+
export type ComboboxRowProps = ComponentProps<typeof BaseCombobox.Row>
|
|
52
|
+
|
|
53
|
+
export const Combobox = <
|
|
54
|
+
Value,
|
|
55
|
+
Multiple extends boolean | undefined = false,
|
|
56
|
+
>(
|
|
57
|
+
props: ComboboxProps<Value, Multiple>,
|
|
58
|
+
): ReactElement => <BaseCombobox.Root {...props} />
|
|
59
|
+
|
|
60
|
+
export const ComboboxLabel = ({ className, ...props }: ComboboxLabelProps) => (
|
|
61
|
+
<BaseCombobox.Label
|
|
62
|
+
className={cn("mb-1.5 block text-sm text-fg-primary", className)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
const inputGroupAccessoryClassName = cn(
|
|
68
|
+
"inline-flex size-9 shrink-0 cursor-pointer items-center justify-center text-fg-tertiary outline-none",
|
|
69
|
+
motion.colors,
|
|
70
|
+
"hover:text-fg-primary focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:outline-none data-disabled:cursor-not-allowed",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
export const ComboboxInputGroup = ({
|
|
74
|
+
className,
|
|
75
|
+
...props
|
|
76
|
+
}: ComboboxInputGroupProps) => (
|
|
77
|
+
<BaseCombobox.InputGroup
|
|
78
|
+
className={cn(
|
|
79
|
+
"relative flex min-h-9 w-full items-center rounded-md border border-border-secondary bg-surface inset-shadow-outline-top outline-none transition-[color,box-shadow]",
|
|
80
|
+
"has-[[data-popup-open]]:bg-background-tertiary/60",
|
|
81
|
+
"focus-within:border-ring focus-within:ring-[3px] focus-within:ring-offset-1 focus-within:ring-offset-background-primary focus-within:ring-ring/20",
|
|
82
|
+
"aria-invalid:border-destructive aria-invalid:focus-within:border-destructive aria-invalid:focus-within:ring-destructive/20",
|
|
83
|
+
"has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:border-destructive has-[[aria-invalid=true]]:focus-within:ring-destructive/20",
|
|
84
|
+
"has-[:disabled]:opacity-50",
|
|
85
|
+
className,
|
|
86
|
+
)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
export const ComboboxInput = ({ className, ...props }: ComboboxInputProps) => (
|
|
92
|
+
<BaseCombobox.Input
|
|
93
|
+
className={cn(
|
|
94
|
+
"h-9 min-w-0 flex-1 cursor-text rounded-md bg-transparent px-3 text-sm text-fg-primary outline-none placeholder:text-fg-quaternary focus-visible:ring-0",
|
|
95
|
+
className,
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
export const ComboboxTrigger = ({
|
|
102
|
+
className,
|
|
103
|
+
children,
|
|
104
|
+
...props
|
|
105
|
+
}: ComboboxTriggerProps) => (
|
|
106
|
+
<BaseCombobox.Trigger
|
|
107
|
+
className={cn(inputGroupAccessoryClassName, className)}
|
|
108
|
+
{...props}
|
|
109
|
+
>
|
|
110
|
+
{children ?? <ComboboxIcon />}
|
|
111
|
+
</BaseCombobox.Trigger>
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
export const ComboboxIcon = ({
|
|
115
|
+
className,
|
|
116
|
+
children,
|
|
117
|
+
...props
|
|
118
|
+
}: ComboboxIconProps) => (
|
|
119
|
+
<BaseCombobox.Icon
|
|
120
|
+
className={cn(
|
|
121
|
+
"flex shrink-0 text-fg-tertiary",
|
|
122
|
+
motion.transform,
|
|
123
|
+
"data-popup-open:rotate-180",
|
|
124
|
+
className,
|
|
125
|
+
)}
|
|
126
|
+
{...props}
|
|
127
|
+
>
|
|
128
|
+
{children ?? <IconChevronDownSmall size={16} className="size-4" aria-hidden />}
|
|
129
|
+
</BaseCombobox.Icon>
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
export const ComboboxClear = ({
|
|
133
|
+
className,
|
|
134
|
+
children,
|
|
135
|
+
...props
|
|
136
|
+
}: ComboboxClearProps) => (
|
|
137
|
+
<BaseCombobox.Clear
|
|
138
|
+
className={cn(inputGroupAccessoryClassName, className)}
|
|
139
|
+
{...props}
|
|
140
|
+
>
|
|
141
|
+
{children ?? (
|
|
142
|
+
<IconCrossSmall size={14} className="size-3.5" aria-hidden />
|
|
143
|
+
)}
|
|
144
|
+
</BaseCombobox.Clear>
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
export const ComboboxValue = (props: ComboboxValueProps) => (
|
|
148
|
+
<BaseCombobox.Value {...props} />
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
export const ComboboxPortal = (props: ComboboxPortalProps) => (
|
|
152
|
+
<BaseCombobox.Portal {...props} />
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
export const ComboboxBackdrop = ({
|
|
156
|
+
className,
|
|
157
|
+
...props
|
|
158
|
+
}: ComboboxBackdropProps) => (
|
|
159
|
+
<BaseCombobox.Backdrop className={cn(className)} {...props} />
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
export const ComboboxPositioner = ({
|
|
163
|
+
sideOffset = 4,
|
|
164
|
+
className,
|
|
165
|
+
...props
|
|
166
|
+
}: ComboboxPositionerProps) => (
|
|
167
|
+
<BaseCombobox.Positioner
|
|
168
|
+
sideOffset={sideOffset}
|
|
169
|
+
className={cn("z-50 outline-none", className)}
|
|
170
|
+
{...props}
|
|
171
|
+
/>
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
export const ComboboxPopup = ({ className, ...props }: ComboboxPopupProps) => (
|
|
175
|
+
<BaseCombobox.Popup
|
|
176
|
+
className={cn(
|
|
177
|
+
"z-50 max-h-[min(24rem,var(--available-height))] w-[var(--anchor-width)] overflow-hidden rounded-md border border-border-primary bg-surface shadow-md outline-none",
|
|
178
|
+
motion.popupAnchor,
|
|
179
|
+
className,
|
|
180
|
+
)}
|
|
181
|
+
{...props}
|
|
182
|
+
/>
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
export const ComboboxArrow = ({ className, ...props }: ComboboxArrowProps) => (
|
|
186
|
+
<BaseCombobox.Arrow
|
|
187
|
+
className={cn(
|
|
188
|
+
"data-[side=bottom]:top-[-6px] data-[side=left]:right-[-6px] data-[side=right]:left-[-6px] data-[side=top]:bottom-[-6px]",
|
|
189
|
+
"size-2.5 rotate-45 border border-border-primary bg-surface",
|
|
190
|
+
"data-[side=bottom]:border-r-0 data-[side=bottom]:border-b-0",
|
|
191
|
+
"data-[side=top]:border-t-0 data-[side=top]:border-l-0",
|
|
192
|
+
"data-[side=left]:border-b-0 data-[side=left]:border-l-0",
|
|
193
|
+
"data-[side=right]:border-t-0 data-[side=right]:border-r-0",
|
|
194
|
+
className,
|
|
195
|
+
)}
|
|
196
|
+
{...props}
|
|
197
|
+
/>
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
export const ComboboxList = ({ className, ...props }: ComboboxListProps) => (
|
|
201
|
+
<BaseCombobox.List
|
|
202
|
+
className={cn("max-h-[inherit] overflow-y-auto p-1 outline-none", className)}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
export const ComboboxItem = ({ className, ...props }: ComboboxItemProps) => (
|
|
208
|
+
<BaseCombobox.Item
|
|
209
|
+
className={cn(
|
|
210
|
+
"flex min-h-8 cursor-default items-center gap-2 rounded-xs px-2.5 py-1.5 text-sm text-fg-primary outline-none select-none",
|
|
211
|
+
motion.colors,
|
|
212
|
+
"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-highlighted:bg-background-tertiary data-highlighted:text-fg-primary",
|
|
213
|
+
className,
|
|
214
|
+
)}
|
|
215
|
+
{...props}
|
|
216
|
+
/>
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
export const ComboboxItemIndicator = ({
|
|
220
|
+
className,
|
|
221
|
+
children,
|
|
222
|
+
...props
|
|
223
|
+
}: ComboboxItemIndicatorProps) => {
|
|
224
|
+
if (children == null) return null
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
<BaseCombobox.ItemIndicator
|
|
228
|
+
className={cn(
|
|
229
|
+
"ml-auto flex size-4 shrink-0 items-center justify-center text-fg-primary data-unchecked:hidden",
|
|
230
|
+
className,
|
|
231
|
+
)}
|
|
232
|
+
{...props}
|
|
233
|
+
>
|
|
234
|
+
{children}
|
|
235
|
+
</BaseCombobox.ItemIndicator>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const ComboboxEmpty = ({ className, ...props }: ComboboxEmptyProps) => (
|
|
240
|
+
<BaseCombobox.Empty
|
|
241
|
+
className={cn("px-2.5 py-2 text-sm text-fg-tertiary empty:hidden", className)}
|
|
242
|
+
{...props}
|
|
243
|
+
/>
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
export const ComboboxStatus = ({ className, ...props }: ComboboxStatusProps) => (
|
|
247
|
+
<BaseCombobox.Status
|
|
248
|
+
className={cn("px-2.5 py-2 text-sm text-fg-tertiary", className)}
|
|
249
|
+
{...props}
|
|
250
|
+
/>
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
export const ComboboxGroup = ({ className, ...props }: ComboboxGroupProps) => (
|
|
254
|
+
<BaseCombobox.Group className={cn(className)} {...props} />
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
export const ComboboxGroupLabel = ({
|
|
258
|
+
className,
|
|
259
|
+
...props
|
|
260
|
+
}: ComboboxGroupLabelProps) => (
|
|
261
|
+
<BaseCombobox.GroupLabel
|
|
262
|
+
className={cn("px-2.5 py-1.5 text-xs text-fg-tertiary", className)}
|
|
263
|
+
{...props}
|
|
264
|
+
/>
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
export const ComboboxSeparator = ({
|
|
268
|
+
className,
|
|
269
|
+
...props
|
|
270
|
+
}: ComboboxSeparatorProps) => (
|
|
271
|
+
<BaseCombobox.Separator
|
|
272
|
+
className={cn("my-1 h-px bg-border-primary", className)}
|
|
273
|
+
{...props}
|
|
274
|
+
/>
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
export const ComboboxCollection = (props: ComboboxCollectionProps) => (
|
|
278
|
+
<BaseCombobox.Collection {...props} />
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
export const ComboboxChips = ({ className, ...props }: ComboboxChipsProps) => (
|
|
282
|
+
<BaseCombobox.Chips
|
|
283
|
+
className={cn(
|
|
284
|
+
"flex min-w-0 flex-1 flex-wrap items-center gap-1 py-1 pl-2",
|
|
285
|
+
className,
|
|
286
|
+
)}
|
|
287
|
+
{...props}
|
|
288
|
+
/>
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
export const ComboboxChip = ({ className, ...props }: ComboboxChipProps) => (
|
|
292
|
+
<BaseCombobox.Chip
|
|
293
|
+
className={cn(
|
|
294
|
+
"inline-flex h-6 items-center gap-1 rounded-xs bg-background-tertiary px-1.5 text-xs text-fg-primary",
|
|
295
|
+
className,
|
|
296
|
+
)}
|
|
297
|
+
{...props}
|
|
298
|
+
/>
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
export const ComboboxChipRemove = ({
|
|
302
|
+
className,
|
|
303
|
+
children,
|
|
304
|
+
...props
|
|
305
|
+
}: ComboboxChipRemoveProps) => (
|
|
306
|
+
<BaseCombobox.ChipRemove
|
|
307
|
+
className={cn(
|
|
308
|
+
"inline-flex size-3.5 cursor-pointer items-center justify-center text-fg-tertiary outline-none hover:text-fg-primary focus-visible:outline-none",
|
|
309
|
+
className,
|
|
310
|
+
)}
|
|
311
|
+
{...props}
|
|
312
|
+
>
|
|
313
|
+
{children ?? (
|
|
314
|
+
<IconCrossSmall size={12} className="size-3" aria-hidden />
|
|
315
|
+
)}
|
|
316
|
+
</BaseCombobox.ChipRemove>
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
export const ComboboxRow = ({ className, ...props }: ComboboxRowProps) => (
|
|
320
|
+
<BaseCombobox.Row className={cn(className)} {...props} />
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
export const useComboboxFilter = BaseCombobox.useFilter
|
|
324
|
+
export const useFilteredItems = BaseCombobox.useFilteredItems
|
package/src/command.tsx
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Dialog as BaseDialog } from "@base-ui/react/dialog"
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
useContext,
|
|
7
|
+
useId,
|
|
8
|
+
useMemo,
|
|
9
|
+
type ButtonHTMLAttributes,
|
|
10
|
+
type ComponentProps,
|
|
11
|
+
type HTMLAttributes,
|
|
12
|
+
type InputHTMLAttributes,
|
|
13
|
+
type ReactNode,
|
|
14
|
+
} from "react"
|
|
15
|
+
import { IconCrossSmall, IconMagnifyingGlass } from "./icons"
|
|
16
|
+
import { cn } from "./lib/cn"
|
|
17
|
+
import { motion } from "./lib/motion"
|
|
18
|
+
|
|
19
|
+
type CommandContextValue = {
|
|
20
|
+
listboxId: string
|
|
21
|
+
activeOptionId?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const CommandContext = createContext<CommandContextValue | null>(null)
|
|
25
|
+
|
|
26
|
+
const useCommandContext = () => {
|
|
27
|
+
const context = useContext(CommandContext)
|
|
28
|
+
if (!context) {
|
|
29
|
+
throw new Error("Command parts must be used within Command.")
|
|
30
|
+
}
|
|
31
|
+
return context
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type CommandProps = ComponentProps<typeof BaseDialog.Root> & {
|
|
35
|
+
activeOptionId?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type CommandTriggerProps = ComponentProps<typeof BaseDialog.Trigger>
|
|
39
|
+
export type CommandPortalProps = ComponentProps<typeof BaseDialog.Portal>
|
|
40
|
+
export type CommandBackdropProps = ComponentProps<typeof BaseDialog.Backdrop>
|
|
41
|
+
export type CommandPopupProps = ComponentProps<typeof BaseDialog.Popup>
|
|
42
|
+
export type CommandToolbarProps = HTMLAttributes<HTMLDivElement>
|
|
43
|
+
export type CommandInputProps = Omit<
|
|
44
|
+
InputHTMLAttributes<HTMLInputElement>,
|
|
45
|
+
"type"
|
|
46
|
+
>
|
|
47
|
+
export type CommandActionsProps = HTMLAttributes<HTMLDivElement>
|
|
48
|
+
export type CommandClearProps = ButtonHTMLAttributes<HTMLButtonElement>
|
|
49
|
+
export type CommandCloseProps = ComponentProps<typeof BaseDialog.Close>
|
|
50
|
+
export type CommandDividerProps = HTMLAttributes<HTMLDivElement>
|
|
51
|
+
export type CommandContentProps = HTMLAttributes<HTMLDivElement>
|
|
52
|
+
export type CommandFiltersProps = HTMLAttributes<HTMLUListElement>
|
|
53
|
+
export type CommandFilterProps = ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
54
|
+
selected?: boolean
|
|
55
|
+
}
|
|
56
|
+
export type CommandListProps = HTMLAttributes<HTMLUListElement>
|
|
57
|
+
export type CommandItemProps = HTMLAttributes<HTMLElement> & {
|
|
58
|
+
selected?: boolean
|
|
59
|
+
disabled?: boolean
|
|
60
|
+
href?: string
|
|
61
|
+
}
|
|
62
|
+
export type CommandEmptyProps = HTMLAttributes<HTMLDivElement>
|
|
63
|
+
export type CommandDialogTitleProps = ComponentProps<typeof BaseDialog.Title>
|
|
64
|
+
|
|
65
|
+
export const Command = ({
|
|
66
|
+
activeOptionId,
|
|
67
|
+
children,
|
|
68
|
+
...props
|
|
69
|
+
}: CommandProps) => {
|
|
70
|
+
const listboxId = useId()
|
|
71
|
+
const value = useMemo(
|
|
72
|
+
() => ({ listboxId, activeOptionId }),
|
|
73
|
+
[activeOptionId, listboxId],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<CommandContext.Provider value={value}>
|
|
78
|
+
<BaseDialog.Root {...props}>{children}</BaseDialog.Root>
|
|
79
|
+
</CommandContext.Provider>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const CommandTrigger = ({
|
|
84
|
+
className,
|
|
85
|
+
...props
|
|
86
|
+
}: CommandTriggerProps) => (
|
|
87
|
+
<BaseDialog.Trigger className={cn("cursor-pointer", className)} {...props} />
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
export const CommandPortal = (props: CommandPortalProps) => (
|
|
91
|
+
<BaseDialog.Portal {...props} />
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
export const CommandBackdrop = ({
|
|
95
|
+
className,
|
|
96
|
+
...props
|
|
97
|
+
}: CommandBackdropProps) => (
|
|
98
|
+
<BaseDialog.Backdrop
|
|
99
|
+
className={cn(
|
|
100
|
+
"fixed inset-0 z-50 bg-black/[0.04] dark:bg-black/40",
|
|
101
|
+
motion.backdrop,
|
|
102
|
+
className,
|
|
103
|
+
)}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
export const CommandPopup = ({ className, ...props }: CommandPopupProps) => (
|
|
109
|
+
<BaseDialog.Popup
|
|
110
|
+
className={cn(
|
|
111
|
+
"fixed top-1/2 left-1/2 z-50 flex h-[min(80vh,32rem)] w-full max-w-xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-2xl border border-border-primary bg-surface-raised shadow-xl outline-none max-sm:max-w-[calc(100vw-2rem)]",
|
|
112
|
+
motion.popupCenter,
|
|
113
|
+
className,
|
|
114
|
+
)}
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
export const CommandToolbar = ({
|
|
120
|
+
className,
|
|
121
|
+
...props
|
|
122
|
+
}: CommandToolbarProps) => (
|
|
123
|
+
<div
|
|
124
|
+
className={cn("flex shrink-0 items-center gap-3 p-4", className)}
|
|
125
|
+
{...props}
|
|
126
|
+
/>
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
export const CommandInput = ({
|
|
130
|
+
className,
|
|
131
|
+
id,
|
|
132
|
+
...props
|
|
133
|
+
}: CommandInputProps) => {
|
|
134
|
+
const { listboxId, activeOptionId } = useCommandContext()
|
|
135
|
+
const fallbackId = useId()
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<input
|
|
139
|
+
id={id ?? fallbackId}
|
|
140
|
+
type="search"
|
|
141
|
+
role="combobox"
|
|
142
|
+
autoComplete="off"
|
|
143
|
+
spellCheck={false}
|
|
144
|
+
aria-autocomplete="list"
|
|
145
|
+
aria-controls={listboxId}
|
|
146
|
+
aria-expanded="true"
|
|
147
|
+
aria-activedescendant={activeOptionId}
|
|
148
|
+
className={cn(
|
|
149
|
+
"h-9 min-w-0 flex-1 cursor-text rounded-md bg-transparent px-2.5 text-base text-fg-primary outline-none placeholder:text-fg-quaternary",
|
|
150
|
+
"focus-visible:bg-background-tertiary/60 focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
151
|
+
"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none",
|
|
152
|
+
className,
|
|
153
|
+
)}
|
|
154
|
+
{...props}
|
|
155
|
+
/>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const CommandActions = ({
|
|
160
|
+
className,
|
|
161
|
+
...props
|
|
162
|
+
}: CommandActionsProps) => (
|
|
163
|
+
<div
|
|
164
|
+
className={cn("flex shrink-0 items-center gap-1.5", className)}
|
|
165
|
+
{...props}
|
|
166
|
+
/>
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
export const CommandClear = ({
|
|
170
|
+
className,
|
|
171
|
+
children = "Clear",
|
|
172
|
+
...props
|
|
173
|
+
}: CommandClearProps) => (
|
|
174
|
+
<button
|
|
175
|
+
type="button"
|
|
176
|
+
className={cn(
|
|
177
|
+
"cursor-pointer rounded-full px-3 py-1.5 text-sm text-fg-quaternary outline-none",
|
|
178
|
+
motion.colors,
|
|
179
|
+
"hover:bg-background-tertiary hover:text-fg-primary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20 data-[active=true]:text-fg-primary",
|
|
180
|
+
className,
|
|
181
|
+
)}
|
|
182
|
+
{...props}
|
|
183
|
+
>
|
|
184
|
+
{children}
|
|
185
|
+
</button>
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
export const CommandDivider = ({
|
|
189
|
+
className,
|
|
190
|
+
...props
|
|
191
|
+
}: CommandDividerProps) => (
|
|
192
|
+
<div
|
|
193
|
+
aria-hidden
|
|
194
|
+
className={cn("h-6 w-px shrink-0 rounded-full bg-border-primary", className)}
|
|
195
|
+
{...props}
|
|
196
|
+
/>
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
export const CommandClose = ({
|
|
200
|
+
className,
|
|
201
|
+
children,
|
|
202
|
+
...props
|
|
203
|
+
}: CommandCloseProps) => (
|
|
204
|
+
<BaseDialog.Close
|
|
205
|
+
className={cn(
|
|
206
|
+
"inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full text-fg-primary outline-none",
|
|
207
|
+
motion.colors,
|
|
208
|
+
"hover:bg-background-tertiary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
209
|
+
className,
|
|
210
|
+
)}
|
|
211
|
+
aria-label={props["aria-label"] ?? "Close"}
|
|
212
|
+
{...props}
|
|
213
|
+
>
|
|
214
|
+
{children ?? (
|
|
215
|
+
<IconCrossSmall size={20} className="size-5" aria-hidden />
|
|
216
|
+
)}
|
|
217
|
+
</BaseDialog.Close>
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
export const CommandContent = ({
|
|
221
|
+
className,
|
|
222
|
+
...props
|
|
223
|
+
}: CommandContentProps) => (
|
|
224
|
+
<div
|
|
225
|
+
className={cn(
|
|
226
|
+
"flex min-h-0 flex-1 flex-col gap-3 overflow-x-visible overflow-y-auto overscroll-contain px-4 pt-1 pb-5",
|
|
227
|
+
className,
|
|
228
|
+
)}
|
|
229
|
+
{...props}
|
|
230
|
+
/>
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
export const CommandFilters = ({
|
|
234
|
+
className,
|
|
235
|
+
...props
|
|
236
|
+
}: CommandFiltersProps) => (
|
|
237
|
+
<ul
|
|
238
|
+
role="list"
|
|
239
|
+
className={cn(
|
|
240
|
+
"flex shrink-0 flex-wrap justify-start gap-1.5 py-1.5",
|
|
241
|
+
className,
|
|
242
|
+
)}
|
|
243
|
+
{...props}
|
|
244
|
+
/>
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
export const CommandFilter = ({
|
|
248
|
+
className,
|
|
249
|
+
selected = false,
|
|
250
|
+
children,
|
|
251
|
+
...props
|
|
252
|
+
}: CommandFilterProps) => (
|
|
253
|
+
<li role="presentation" className="contents">
|
|
254
|
+
<button
|
|
255
|
+
type="button"
|
|
256
|
+
aria-pressed={selected}
|
|
257
|
+
data-selected={selected || undefined}
|
|
258
|
+
className={cn(
|
|
259
|
+
"cursor-pointer rounded-full px-4 py-2 text-sm text-fg-quaternary outline-none",
|
|
260
|
+
motion.colors,
|
|
261
|
+
"hover:text-fg-primary focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
262
|
+
"data-selected:bg-background-tertiary data-selected:text-fg-primary",
|
|
263
|
+
className,
|
|
264
|
+
)}
|
|
265
|
+
{...props}
|
|
266
|
+
>
|
|
267
|
+
{children}
|
|
268
|
+
</button>
|
|
269
|
+
</li>
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
export const CommandList = ({ className, ...props }: CommandListProps) => {
|
|
273
|
+
const { listboxId } = useCommandContext()
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<ul
|
|
277
|
+
id={listboxId}
|
|
278
|
+
role="listbox"
|
|
279
|
+
className={cn(
|
|
280
|
+
"grid min-h-0 flex-1 content-start gap-0 overflow-visible overscroll-contain py-0.5",
|
|
281
|
+
className,
|
|
282
|
+
)}
|
|
283
|
+
{...props}
|
|
284
|
+
/>
|
|
285
|
+
)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export const CommandItem = ({
|
|
289
|
+
className,
|
|
290
|
+
selected = false,
|
|
291
|
+
disabled = false,
|
|
292
|
+
href,
|
|
293
|
+
children,
|
|
294
|
+
id,
|
|
295
|
+
onClick,
|
|
296
|
+
...props
|
|
297
|
+
}: CommandItemProps) => {
|
|
298
|
+
const itemClassName = cn(
|
|
299
|
+
"flex h-15 min-h-15 w-full cursor-pointer items-center justify-between gap-4 rounded-lg px-4 text-left text-sm font-medium text-fg-primary outline-none select-none",
|
|
300
|
+
motion.colors,
|
|
301
|
+
"hover:bg-background-tertiary data-selected:bg-background-tertiary",
|
|
302
|
+
"data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
303
|
+
"focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
304
|
+
className,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<li role="presentation" className="m-0">
|
|
309
|
+
{href ? (
|
|
310
|
+
<a
|
|
311
|
+
id={id}
|
|
312
|
+
href={disabled ? undefined : href}
|
|
313
|
+
role="option"
|
|
314
|
+
aria-selected={selected}
|
|
315
|
+
aria-disabled={disabled || undefined}
|
|
316
|
+
data-selected={selected || undefined}
|
|
317
|
+
data-disabled={disabled || undefined}
|
|
318
|
+
className={itemClassName}
|
|
319
|
+
onClick={onClick as never}
|
|
320
|
+
{...(props as HTMLAttributes<HTMLAnchorElement>)}
|
|
321
|
+
>
|
|
322
|
+
{children}
|
|
323
|
+
</a>
|
|
324
|
+
) : (
|
|
325
|
+
<button
|
|
326
|
+
id={id}
|
|
327
|
+
type="button"
|
|
328
|
+
role="option"
|
|
329
|
+
aria-selected={selected}
|
|
330
|
+
disabled={disabled}
|
|
331
|
+
data-selected={selected || undefined}
|
|
332
|
+
data-disabled={disabled || undefined}
|
|
333
|
+
className={itemClassName}
|
|
334
|
+
onClick={onClick as never}
|
|
335
|
+
{...(props as ButtonHTMLAttributes<HTMLButtonElement>)}
|
|
336
|
+
>
|
|
337
|
+
{children}
|
|
338
|
+
</button>
|
|
339
|
+
)}
|
|
340
|
+
</li>
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export const CommandEmpty = ({
|
|
345
|
+
className,
|
|
346
|
+
children,
|
|
347
|
+
...props
|
|
348
|
+
}: CommandEmptyProps) => (
|
|
349
|
+
<div
|
|
350
|
+
role="presentation"
|
|
351
|
+
className={cn(
|
|
352
|
+
"flex flex-1 items-center justify-center gap-2 px-4 py-6 text-sm font-medium text-fg-quaternary",
|
|
353
|
+
className,
|
|
354
|
+
)}
|
|
355
|
+
aria-live="polite"
|
|
356
|
+
{...props}
|
|
357
|
+
>
|
|
358
|
+
<IconMagnifyingGlass size={20} className="size-5 shrink-0" aria-hidden />
|
|
359
|
+
<span>{children ?? "No results"}</span>
|
|
360
|
+
</div>
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
export type CommandTitleProps = {
|
|
364
|
+
children: ReactNode
|
|
365
|
+
className?: string
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export const CommandTitle = ({ className, children }: CommandTitleProps) => (
|
|
369
|
+
<span className={cn("min-w-0 truncate", className)}>{children}</span>
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
export const CommandDialogTitle = ({
|
|
373
|
+
className,
|
|
374
|
+
...props
|
|
375
|
+
}: CommandDialogTitleProps) => (
|
|
376
|
+
<BaseDialog.Title className={cn("sr-only", className)} {...props} />
|
|
377
|
+
)
|