@multicomma/arkcn 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 +78 -0
- package/bin/arkcn.mjs +78 -0
- package/cli/commands.mjs +251 -0
- package/cli/project.mjs +168 -0
- package/cli/registry.mjs +50 -0
- package/cli/ui.mjs +46 -0
- package/mcp/server.mjs +149 -0
- package/package.json +201 -0
- package/registry/base.css +680 -0
- package/registry/index.json +1833 -0
- package/registry/items/accordion.json +18 -0
- package/registry/items/activity-feed.json +18 -0
- package/registry/items/alert-dialog.json +18 -0
- package/registry/items/alert.json +17 -0
- package/registry/items/angle-slider.json +17 -0
- package/registry/items/app-shell.json +28 -0
- package/registry/items/aspect-ratio.json +13 -0
- package/registry/items/attachment.json +19 -0
- package/registry/items/avatar.json +17 -0
- package/registry/items/badge.json +18 -0
- package/registry/items/breadcrumb.json +18 -0
- package/registry/items/bubble.json +18 -0
- package/registry/items/button-group.json +19 -0
- package/registry/items/button.json +18 -0
- package/registry/items/calendar.json +19 -0
- package/registry/items/canvas.json +24 -0
- package/registry/items/card.json +15 -0
- package/registry/items/carousel.json +19 -0
- package/registry/items/cascader.json +23 -0
- package/registry/items/chart.json +17 -0
- package/registry/items/chat.json +23 -0
- package/registry/items/checkbox.json +18 -0
- package/registry/items/clipboard.json +19 -0
- package/registry/items/collapsible.json +15 -0
- package/registry/items/color-picker.json +19 -0
- package/registry/items/combobox.json +20 -0
- package/registry/items/command.json +21 -0
- package/registry/items/comment-thread.json +25 -0
- package/registry/items/context-menu.json +18 -0
- package/registry/items/controllable.json +14 -0
- package/registry/items/data-grid.json +24 -0
- package/registry/items/data-table-adapter.json +14 -0
- package/registry/items/data-table.json +32 -0
- package/registry/items/date-input.json +17 -0
- package/registry/items/dialog.json +19 -0
- package/registry/items/direction.json +13 -0
- package/registry/items/drag-preview.json +16 -0
- package/registry/items/drawer.json +18 -0
- package/registry/items/dropdown-menu.json +18 -0
- package/registry/items/editable.json +17 -0
- package/registry/items/empty.json +17 -0
- package/registry/items/field.json +19 -0
- package/registry/items/file-upload.json +19 -0
- package/registry/items/floating-panel.json +19 -0
- package/registry/items/floating-toolbar.json +16 -0
- package/registry/items/form.json +14 -0
- package/registry/items/format.json +15 -0
- package/registry/items/gantt.json +22 -0
- package/registry/items/history.json +14 -0
- package/registry/items/hotkeys.json +18 -0
- package/registry/items/hover-card.json +17 -0
- package/registry/items/image-cropper.json +17 -0
- package/registry/items/input-group.json +20 -0
- package/registry/items/input-otp.json +18 -0
- package/registry/items/input.json +15 -0
- package/registry/items/item.json +19 -0
- package/registry/items/json-tree-view.json +17 -0
- package/registry/items/kanban.json +26 -0
- package/registry/items/kbd.json +15 -0
- package/registry/items/label.json +15 -0
- package/registry/items/live-region.json +16 -0
- package/registry/items/marker.json +18 -0
- package/registry/items/marquee.json +17 -0
- package/registry/items/menubar.json +19 -0
- package/registry/items/message.json +15 -0
- package/registry/items/navigation-menu.json +19 -0
- package/registry/items/node-graph.json +22 -0
- package/registry/items/number-input.json +18 -0
- package/registry/items/pagination.json +18 -0
- package/registry/items/password-input.json +18 -0
- package/registry/items/popconfirm.json +20 -0
- package/registry/items/popover.json +18 -0
- package/registry/items/progress.json +17 -0
- package/registry/items/qr-code.json +17 -0
- package/registry/items/query-builder.json +23 -0
- package/registry/items/radio-group.json +17 -0
- package/registry/items/rating-group.json +18 -0
- package/registry/items/resizable.json +17 -0
- package/registry/items/rich-text-editor.json +37 -0
- package/registry/items/row-layout.json +15 -0
- package/registry/items/scheduler.json +23 -0
- package/registry/items/scroll-area.json +17 -0
- package/registry/items/segment-group.json +17 -0
- package/registry/items/select.json +19 -0
- package/registry/items/separator.json +15 -0
- package/registry/items/sheet.json +19 -0
- package/registry/items/sidebar.json +27 -0
- package/registry/items/signature-pad.json +19 -0
- package/registry/items/skeleton.json +15 -0
- package/registry/items/slider.json +17 -0
- package/registry/items/sonner.json +17 -0
- package/registry/items/spinner.json +17 -0
- package/registry/items/steps.json +19 -0
- package/registry/items/swap.json +17 -0
- package/registry/items/switch.json +17 -0
- package/registry/items/table.json +16 -0
- package/registry/items/tabs.json +18 -0
- package/registry/items/tags-input.json +18 -0
- package/registry/items/textarea.json +15 -0
- package/registry/items/time.json +14 -0
- package/registry/items/timer.json +18 -0
- package/registry/items/toc.json +17 -0
- package/registry/items/toggle-group.json +19 -0
- package/registry/items/toggle.json +18 -0
- package/registry/items/tooltip.json +17 -0
- package/registry/items/tour.json +19 -0
- package/registry/items/transfer-list.json +24 -0
- package/registry/items/tree-select.json +24 -0
- package/registry/items/tree-view.json +18 -0
- package/registry/items/use-mobile.json +13 -0
- package/registry/items/utils.json +17 -0
- package/registry/items/virtual-list.json +16 -0
- package/src/components/ui/accordion.tsx +111 -0
- package/src/components/ui/activity-feed.tsx +228 -0
- package/src/components/ui/alert-dialog.tsx +204 -0
- package/src/components/ui/alert.tsx +55 -0
- package/src/components/ui/angle-slider.tsx +117 -0
- package/src/components/ui/app-shell.tsx +985 -0
- package/src/components/ui/aspect-ratio.tsx +35 -0
- package/src/components/ui/attachment.tsx +193 -0
- package/src/components/ui/avatar.tsx +94 -0
- package/src/components/ui/badge.tsx +45 -0
- package/src/components/ui/breadcrumb.tsx +93 -0
- package/src/components/ui/bubble.tsx +119 -0
- package/src/components/ui/button-group.tsx +79 -0
- package/src/components/ui/button.tsx +65 -0
- package/src/components/ui/calendar.tsx +172 -0
- package/src/components/ui/canvas.tsx +723 -0
- package/src/components/ui/card.tsx +69 -0
- package/src/components/ui/carousel.tsx +228 -0
- package/src/components/ui/cascader.tsx +754 -0
- package/src/components/ui/chart.tsx +303 -0
- package/src/components/ui/chat.tsx +544 -0
- package/src/components/ui/checkbox.tsx +94 -0
- package/src/components/ui/clipboard.tsx +94 -0
- package/src/components/ui/collapsible.tsx +32 -0
- package/src/components/ui/color-picker.tsx +441 -0
- package/src/components/ui/combobox.tsx +400 -0
- package/src/components/ui/command.tsx +292 -0
- package/src/components/ui/comment-thread.tsx +923 -0
- package/src/components/ui/context-menu.tsx +331 -0
- package/src/components/ui/data-grid.tsx +1227 -0
- package/src/components/ui/data-table.tsx +993 -0
- package/src/components/ui/date-input.tsx +103 -0
- package/src/components/ui/dialog.tsx +159 -0
- package/src/components/ui/direction.tsx +32 -0
- package/src/components/ui/drawer.tsx +200 -0
- package/src/components/ui/dropdown-menu.tsx +329 -0
- package/src/components/ui/editable.tsx +90 -0
- package/src/components/ui/empty.tsx +86 -0
- package/src/components/ui/field.tsx +218 -0
- package/src/components/ui/file-upload.tsx +204 -0
- package/src/components/ui/floating-panel.tsx +199 -0
- package/src/components/ui/floating-toolbar.tsx +79 -0
- package/src/components/ui/format.tsx +22 -0
- package/src/components/ui/gantt.tsx +950 -0
- package/src/components/ui/hotkeys.tsx +340 -0
- package/src/components/ui/hover-card.tsx +83 -0
- package/src/components/ui/image-cropper.tsx +100 -0
- package/src/components/ui/input-group.tsx +133 -0
- package/src/components/ui/input-otp.tsx +82 -0
- package/src/components/ui/input.tsx +18 -0
- package/src/components/ui/item.tsx +174 -0
- package/src/components/ui/json-tree-view.tsx +37 -0
- package/src/components/ui/kanban.tsx +884 -0
- package/src/components/ui/kbd.tsx +20 -0
- package/src/components/ui/label.tsx +30 -0
- package/src/components/ui/live-region.tsx +54 -0
- package/src/components/ui/marker.tsx +66 -0
- package/src/components/ui/marquee.tsx +61 -0
- package/src/components/ui/menubar.tsx +456 -0
- package/src/components/ui/message.tsx +74 -0
- package/src/components/ui/navigation-menu.tsx +202 -0
- package/src/components/ui/node-graph.tsx +1723 -0
- package/src/components/ui/number-input.tsx +148 -0
- package/src/components/ui/pagination.tsx +88 -0
- package/src/components/ui/password-input.tsx +104 -0
- package/src/components/ui/popconfirm.tsx +149 -0
- package/src/components/ui/popover.tsx +126 -0
- package/src/components/ui/progress.tsx +114 -0
- package/src/components/ui/qr-code.tsx +51 -0
- package/src/components/ui/query-builder.tsx +938 -0
- package/src/components/ui/radio-group.tsx +108 -0
- package/src/components/ui/rating-group.tsx +91 -0
- package/src/components/ui/resizable.tsx +41 -0
- package/src/components/ui/rich-text-editor.tsx +845 -0
- package/src/components/ui/scheduler.tsx +1164 -0
- package/src/components/ui/scroll-area.tsx +82 -0
- package/src/components/ui/segment-group.tsx +95 -0
- package/src/components/ui/select.tsx +354 -0
- package/src/components/ui/separator.tsx +32 -0
- package/src/components/ui/sheet.tsx +130 -0
- package/src/components/ui/sidebar.tsx +665 -0
- package/src/components/ui/signature-pad.tsx +112 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/slider.tsx +183 -0
- package/src/components/ui/sonner.tsx +37 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/steps.tsx +152 -0
- package/src/components/ui/swap.tsx +33 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +72 -0
- package/src/components/ui/tabs.tsx +100 -0
- package/src/components/ui/tags-input.tsx +153 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/timer.tsx +67 -0
- package/src/components/ui/toc.tsx +64 -0
- package/src/components/ui/toggle-group.tsx +89 -0
- package/src/components/ui/toggle.tsx +46 -0
- package/src/components/ui/tooltip.tsx +113 -0
- package/src/components/ui/tour.tsx +168 -0
- package/src/components/ui/transfer-list.tsx +700 -0
- package/src/components/ui/tree-select.tsx +638 -0
- package/src/components/ui/tree-view.tsx +217 -0
- package/src/components/ui/virtual-list.tsx +343 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/controllable.ts +31 -0
- package/src/lib/data-table-adapter.ts +67 -0
- package/src/lib/drag-preview.ts +39 -0
- package/src/lib/form.ts +39 -0
- package/src/lib/history.ts +55 -0
- package/src/lib/row-layout.ts +81 -0
- package/src/lib/table.ts +483 -0
- package/src/lib/time.ts +37 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/arkcn.css +764 -0
- package/src/styles/index.css +3 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import {
|
|
5
|
+
Combobox as ComboboxPrimitive,
|
|
6
|
+
Portal as PortalPrimitive,
|
|
7
|
+
createListCollection,
|
|
8
|
+
useComboboxContext,
|
|
9
|
+
useFilter,
|
|
10
|
+
useListCollection,
|
|
11
|
+
type CollectionItem,
|
|
12
|
+
type ListCollection,
|
|
13
|
+
} from "@ark-ui/react"
|
|
14
|
+
import { cn } from "@/lib/utils"
|
|
15
|
+
|
|
16
|
+
import { Button } from "@/components/ui/button"
|
|
17
|
+
import { InputGroup, InputGroupAddon, InputGroupTrigger, InputGroupInput } from "@/components/ui/input-group"
|
|
18
|
+
import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"
|
|
19
|
+
|
|
20
|
+
function Combobox<T extends CollectionItem>({
|
|
21
|
+
positioning,
|
|
22
|
+
anchor,
|
|
23
|
+
lazyMount = true,
|
|
24
|
+
unmountOnExit = true,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof ComboboxPrimitive.Root<T>> & {
|
|
27
|
+
/** Anchor the popup to another element, e.g. a `ComboboxChips` container. */
|
|
28
|
+
anchor?: React.RefObject<HTMLElement | null>
|
|
29
|
+
}) {
|
|
30
|
+
return (
|
|
31
|
+
<ComboboxPrimitive.Root
|
|
32
|
+
data-slot="combobox"
|
|
33
|
+
positioning={{
|
|
34
|
+
placement: "bottom-start",
|
|
35
|
+
gutter: 6,
|
|
36
|
+
sameWidth: true,
|
|
37
|
+
...(anchor ? { getAnchorElement: () => anchor.current } : {}),
|
|
38
|
+
...positioning,
|
|
39
|
+
}}
|
|
40
|
+
lazyMount={lazyMount}
|
|
41
|
+
unmountOnExit={unmountOnExit}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function ComboboxContext({ ...props }: React.ComponentProps<typeof ComboboxPrimitive.Context>) {
|
|
48
|
+
return <ComboboxPrimitive.Context {...props} />
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function ComboboxRootLabel({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.Label>) {
|
|
52
|
+
return (
|
|
53
|
+
<ComboboxPrimitive.Label
|
|
54
|
+
data-slot="combobox-root-label"
|
|
55
|
+
className={cn("text-sm font-medium", className)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function ComboboxControl({ ...props }: React.ComponentProps<typeof ComboboxPrimitive.Control>) {
|
|
62
|
+
return <ComboboxPrimitive.Control data-slot="combobox-control" {...props} />
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Ark has no value-text part for Combobox. Renders the selected items as
|
|
67
|
+
* text, or `placeholder` when nothing is selected.
|
|
68
|
+
*/
|
|
69
|
+
function ComboboxValue({
|
|
70
|
+
placeholder,
|
|
71
|
+
children,
|
|
72
|
+
...props
|
|
73
|
+
}: React.ComponentProps<"span"> & { placeholder?: React.ReactNode }) {
|
|
74
|
+
const combobox = useComboboxContext()
|
|
75
|
+
return (
|
|
76
|
+
<span data-slot="combobox-value" data-placeholder-shown={combobox.hasSelectedItems ? undefined : ""} {...props}>
|
|
77
|
+
{children ?? (combobox.hasSelectedItems ? combobox.valueAsString : placeholder)}
|
|
78
|
+
</span>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** `id` is omitted: set part ids through the root `ids` prop so Ark's internal lookups keep working. */
|
|
83
|
+
function ComboboxTrigger({
|
|
84
|
+
className,
|
|
85
|
+
children,
|
|
86
|
+
...props
|
|
87
|
+
}: Omit<React.ComponentProps<typeof ComboboxPrimitive.Trigger>, "id">) {
|
|
88
|
+
return (
|
|
89
|
+
<ComboboxPrimitive.Trigger
|
|
90
|
+
data-slot="combobox-trigger"
|
|
91
|
+
className={cn("[&_svg:not([class*='size-'])]:size-4", className)}
|
|
92
|
+
{...props}
|
|
93
|
+
>
|
|
94
|
+
{children}
|
|
95
|
+
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
|
96
|
+
</ComboboxPrimitive.Trigger>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function ComboboxClear({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.ClearTrigger>) {
|
|
101
|
+
const combobox = useComboboxContext()
|
|
102
|
+
// Match Base UI: unmount when there is nothing to clear, so the trigger
|
|
103
|
+
// button (hidden via `has-data-[slot=combobox-clear]`) shows again.
|
|
104
|
+
if (!combobox.hasSelectedItems && !combobox.inputValue) return null
|
|
105
|
+
return (
|
|
106
|
+
<ComboboxPrimitive.ClearTrigger data-slot="combobox-clear" className={cn(className)} asChild {...props}>
|
|
107
|
+
<InputGroupTrigger variant="ghost" size="icon-xs">
|
|
108
|
+
<XIcon className="pointer-events-none" />
|
|
109
|
+
</InputGroupTrigger>
|
|
110
|
+
</ComboboxPrimitive.ClearTrigger>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** `id` is omitted: set part ids through the root `ids` prop so Ark's internal lookups keep working. */
|
|
115
|
+
function ComboboxInput({
|
|
116
|
+
className,
|
|
117
|
+
children,
|
|
118
|
+
disabled = false,
|
|
119
|
+
showTrigger = true,
|
|
120
|
+
showClear = false,
|
|
121
|
+
...props
|
|
122
|
+
}: Omit<React.ComponentProps<typeof ComboboxPrimitive.Input>, "id"> & {
|
|
123
|
+
showTrigger?: boolean
|
|
124
|
+
showClear?: boolean
|
|
125
|
+
}) {
|
|
126
|
+
return (
|
|
127
|
+
<ComboboxPrimitive.Control asChild>
|
|
128
|
+
<InputGroup className={cn("w-auto", className)}>
|
|
129
|
+
<ComboboxPrimitive.Input asChild disabled={disabled} {...props}>
|
|
130
|
+
<InputGroupInput />
|
|
131
|
+
</ComboboxPrimitive.Input>
|
|
132
|
+
<InputGroupAddon align="inline-end">
|
|
133
|
+
{showTrigger && (
|
|
134
|
+
<InputGroupTrigger
|
|
135
|
+
size="icon-xs"
|
|
136
|
+
variant="ghost"
|
|
137
|
+
asChild
|
|
138
|
+
data-slot="input-group-trigger"
|
|
139
|
+
className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
|
|
140
|
+
disabled={disabled}
|
|
141
|
+
>
|
|
142
|
+
<ComboboxTrigger />
|
|
143
|
+
</InputGroupTrigger>
|
|
144
|
+
)}
|
|
145
|
+
{showClear && <ComboboxClear disabled={disabled} />}
|
|
146
|
+
</InputGroupAddon>
|
|
147
|
+
{children}
|
|
148
|
+
</InputGroup>
|
|
149
|
+
</ComboboxPrimitive.Control>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function ComboboxPositioner({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.Positioner>) {
|
|
154
|
+
return (
|
|
155
|
+
<ComboboxPrimitive.Positioner
|
|
156
|
+
data-slot="combobox-positioner"
|
|
157
|
+
className={cn("isolate [--z-index:50]", className)}
|
|
158
|
+
{...props}
|
|
159
|
+
/>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** `id` is omitted: set part ids through the root `ids` prop so Ark's internal lookups keep working. */
|
|
164
|
+
function ComboboxContent({ className, ...props }: Omit<React.ComponentProps<typeof ComboboxPrimitive.Content>, "id">) {
|
|
165
|
+
return (
|
|
166
|
+
<PortalPrimitive>
|
|
167
|
+
<ComboboxPositioner>
|
|
168
|
+
<ComboboxPrimitive.Content
|
|
169
|
+
data-slot="combobox-content"
|
|
170
|
+
className={cn(
|
|
171
|
+
"group/combobox-content relative z-50 max-h-(--available-height) w-(--reference-width) max-w-(--available-width) origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 *: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",
|
|
172
|
+
className
|
|
173
|
+
)}
|
|
174
|
+
{...props}
|
|
175
|
+
/>
|
|
176
|
+
</ComboboxPositioner>
|
|
177
|
+
</PortalPrimitive>
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function ComboboxList({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.List>) {
|
|
182
|
+
return (
|
|
183
|
+
<ComboboxPrimitive.List
|
|
184
|
+
data-slot="combobox-list"
|
|
185
|
+
className={cn(
|
|
186
|
+
"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",
|
|
187
|
+
className
|
|
188
|
+
)}
|
|
189
|
+
{...props}
|
|
190
|
+
/>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function ComboboxItem({
|
|
195
|
+
className,
|
|
196
|
+
children,
|
|
197
|
+
item,
|
|
198
|
+
value,
|
|
199
|
+
...props
|
|
200
|
+
}: Omit<React.ComponentProps<typeof ComboboxPrimitive.Item>, "item"> & {
|
|
201
|
+
/** The collection item. Falls back to `value` for string collections. */
|
|
202
|
+
item?: CollectionItem
|
|
203
|
+
value?: string
|
|
204
|
+
}) {
|
|
205
|
+
return (
|
|
206
|
+
<ComboboxPrimitive.Item
|
|
207
|
+
data-slot="combobox-item"
|
|
208
|
+
item={item ?? value}
|
|
209
|
+
className={cn(
|
|
210
|
+
"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",
|
|
211
|
+
className
|
|
212
|
+
)}
|
|
213
|
+
{...props}
|
|
214
|
+
>
|
|
215
|
+
{children}
|
|
216
|
+
<ComboboxItemIndicator>
|
|
217
|
+
<CheckIcon className="pointer-events-none" />
|
|
218
|
+
</ComboboxItemIndicator>
|
|
219
|
+
</ComboboxPrimitive.Item>
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function ComboboxItemText({ ...props }: React.ComponentProps<typeof ComboboxPrimitive.ItemText>) {
|
|
224
|
+
return <ComboboxPrimitive.ItemText data-slot="combobox-item-text" {...props} />
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function ComboboxItemIndicator({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.ItemIndicator>) {
|
|
228
|
+
return (
|
|
229
|
+
<ComboboxPrimitive.ItemIndicator
|
|
230
|
+
data-slot="combobox-item-indicator"
|
|
231
|
+
className={cn("pointer-events-none absolute right-2 flex size-4 items-center justify-center", className)}
|
|
232
|
+
{...props}
|
|
233
|
+
/>
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function ComboboxGroup({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.ItemGroup>) {
|
|
238
|
+
return <ComboboxPrimitive.ItemGroup data-slot="combobox-group" className={cn(className)} {...props} />
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function ComboboxLabel({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.ItemGroupLabel>) {
|
|
242
|
+
return (
|
|
243
|
+
<ComboboxPrimitive.ItemGroupLabel
|
|
244
|
+
data-slot="combobox-label"
|
|
245
|
+
className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
|
|
246
|
+
{...props}
|
|
247
|
+
/>
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Renders every item in the root's collection through a render function.
|
|
253
|
+
* Ark has no Collection part; this reads the collection from context.
|
|
254
|
+
*/
|
|
255
|
+
function ComboboxCollection<T extends CollectionItem = CollectionItem>({
|
|
256
|
+
children,
|
|
257
|
+
}: {
|
|
258
|
+
children: (item: T, index: number) => React.ReactNode
|
|
259
|
+
}) {
|
|
260
|
+
const combobox = useComboboxContext()
|
|
261
|
+
const items = combobox.collection.items as T[]
|
|
262
|
+
return (
|
|
263
|
+
<React.Fragment>
|
|
264
|
+
{items.map((item, index) => (
|
|
265
|
+
<React.Fragment key={combobox.collection.getItemValue(item) ?? index}>{children(item, index)}</React.Fragment>
|
|
266
|
+
))}
|
|
267
|
+
</React.Fragment>
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function ComboboxEmpty({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.Empty>) {
|
|
272
|
+
return (
|
|
273
|
+
<ComboboxPrimitive.Empty
|
|
274
|
+
data-slot="combobox-empty"
|
|
275
|
+
className={cn("flex w-full justify-center py-2 text-center text-sm text-muted-foreground", className)}
|
|
276
|
+
{...props}
|
|
277
|
+
/>
|
|
278
|
+
)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function ComboboxSeparator({ className, ...props }: React.ComponentProps<"div">) {
|
|
282
|
+
return (
|
|
283
|
+
<div
|
|
284
|
+
role="separator"
|
|
285
|
+
aria-orientation="horizontal"
|
|
286
|
+
data-slot="combobox-separator"
|
|
287
|
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
288
|
+
{...props}
|
|
289
|
+
/>
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Chips for `multiple` comboboxes. Ark has no chip parts; these read the
|
|
295
|
+
* selected values from context and remove them via `clearValue`.
|
|
296
|
+
*/
|
|
297
|
+
function ComboboxChips({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.Control>) {
|
|
298
|
+
return (
|
|
299
|
+
<ComboboxPrimitive.Control
|
|
300
|
+
data-slot="combobox-chips"
|
|
301
|
+
className={cn(
|
|
302
|
+
"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 has-focus-visible:border-ring has-focus-visible:ring-3 has-focus-visible: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",
|
|
303
|
+
className
|
|
304
|
+
)}
|
|
305
|
+
{...props}
|
|
306
|
+
/>
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function ComboboxChip({
|
|
311
|
+
className,
|
|
312
|
+
children,
|
|
313
|
+
value,
|
|
314
|
+
showRemove = true,
|
|
315
|
+
...props
|
|
316
|
+
}: React.ComponentProps<"div"> & {
|
|
317
|
+
/** The selected value this chip represents. */
|
|
318
|
+
value: string
|
|
319
|
+
showRemove?: boolean
|
|
320
|
+
}) {
|
|
321
|
+
const combobox = useComboboxContext()
|
|
322
|
+
return (
|
|
323
|
+
<div
|
|
324
|
+
data-slot="combobox-chip"
|
|
325
|
+
data-value={value}
|
|
326
|
+
className={cn(
|
|
327
|
+
"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",
|
|
328
|
+
className
|
|
329
|
+
)}
|
|
330
|
+
{...props}
|
|
331
|
+
>
|
|
332
|
+
{children}
|
|
333
|
+
{showRemove && (
|
|
334
|
+
<Button
|
|
335
|
+
type="button"
|
|
336
|
+
variant="ghost"
|
|
337
|
+
size="icon-xs"
|
|
338
|
+
data-slot="combobox-chip-remove"
|
|
339
|
+
aria-label={`Remove ${value}`}
|
|
340
|
+
disabled={combobox.disabled}
|
|
341
|
+
className="-ml-1 opacity-50 hover:opacity-100"
|
|
342
|
+
onClick={() => combobox.clearValue(value)}
|
|
343
|
+
>
|
|
344
|
+
<XIcon className="pointer-events-none" />
|
|
345
|
+
</Button>
|
|
346
|
+
)}
|
|
347
|
+
</div>
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function ComboboxChipsInput({ className, ...props }: React.ComponentProps<typeof ComboboxPrimitive.Input>) {
|
|
352
|
+
return (
|
|
353
|
+
<ComboboxPrimitive.Input
|
|
354
|
+
data-slot="combobox-chip-input"
|
|
355
|
+
className={cn("min-w-16 flex-1 outline-none", className)}
|
|
356
|
+
{...props}
|
|
357
|
+
/>
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function useComboboxAnchor() {
|
|
362
|
+
return React.useRef<HTMLDivElement | null>(null)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** Render-prop access to one item's state (`{ selected, highlighted, disabled, ... }`). */
|
|
366
|
+
function ComboboxItemContext({ ...props }: React.ComponentProps<typeof ComboboxPrimitive.ItemContext>) {
|
|
367
|
+
return <ComboboxPrimitive.ItemContext {...props} />
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export {
|
|
371
|
+
Combobox,
|
|
372
|
+
ComboboxChip,
|
|
373
|
+
ComboboxChips,
|
|
374
|
+
ComboboxChipsInput,
|
|
375
|
+
ComboboxClear,
|
|
376
|
+
ComboboxCollection,
|
|
377
|
+
ComboboxContent,
|
|
378
|
+
ComboboxContext,
|
|
379
|
+
ComboboxControl,
|
|
380
|
+
ComboboxEmpty,
|
|
381
|
+
ComboboxGroup,
|
|
382
|
+
ComboboxInput,
|
|
383
|
+
ComboboxItem,
|
|
384
|
+
ComboboxItemIndicator,
|
|
385
|
+
ComboboxItemText,
|
|
386
|
+
ComboboxLabel,
|
|
387
|
+
ComboboxList,
|
|
388
|
+
ComboboxPositioner,
|
|
389
|
+
ComboboxRootLabel,
|
|
390
|
+
ComboboxSeparator,
|
|
391
|
+
ComboboxTrigger,
|
|
392
|
+
ComboboxValue,
|
|
393
|
+
createListCollection,
|
|
394
|
+
useComboboxAnchor,
|
|
395
|
+
useFilter,
|
|
396
|
+
useListCollection,
|
|
397
|
+
type CollectionItem,
|
|
398
|
+
type ListCollection,
|
|
399
|
+
ComboboxItemContext,
|
|
400
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Listbox as CommandPrimitive,
|
|
4
|
+
createListCollection,
|
|
5
|
+
useFilter,
|
|
6
|
+
useListCollection,
|
|
7
|
+
type CollectionItem,
|
|
8
|
+
type ListCollection,
|
|
9
|
+
} from "@ark-ui/react"
|
|
10
|
+
import { cn } from "@/lib/utils"
|
|
11
|
+
|
|
12
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
|
13
|
+
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"
|
|
14
|
+
import { SearchIcon, CheckIcon } from "lucide-react"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Backed by Ark UI's Listbox. Ark has no built-in fuzzy filter: pass a
|
|
18
|
+
* `collection` and filter it yourself (see `useListCollection` and
|
|
19
|
+
* `useFilter`, re-exported below), wiring `CommandInput`'s `onValueChange`
|
|
20
|
+
* to the collection's `filter`.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
type SelectHandler = (value: string) => void
|
|
24
|
+
|
|
25
|
+
const CommandSelectContext = React.createContext<{
|
|
26
|
+
register: (value: string, handler: SelectHandler) => () => void
|
|
27
|
+
} | null>(null)
|
|
28
|
+
|
|
29
|
+
function Command<T extends CollectionItem>({
|
|
30
|
+
className,
|
|
31
|
+
selectionMode = "single",
|
|
32
|
+
onSelect,
|
|
33
|
+
defaultHighlightedValue,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof CommandPrimitive.Root<T>>) {
|
|
36
|
+
// Like cmdk, highlight the first item on mount so Enter works immediately.
|
|
37
|
+
const initialHighlight = defaultHighlightedValue ?? props.collection.firstValue
|
|
38
|
+
const handlers = React.useRef(new Map<string, SelectHandler>())
|
|
39
|
+
const register = React.useCallback((value: string, handler: SelectHandler) => {
|
|
40
|
+
handlers.current.set(value, handler)
|
|
41
|
+
return () => {
|
|
42
|
+
handlers.current.delete(value)
|
|
43
|
+
}
|
|
44
|
+
}, [])
|
|
45
|
+
const ctx = React.useMemo(() => ({ register }), [register])
|
|
46
|
+
return (
|
|
47
|
+
<CommandSelectContext.Provider value={ctx}>
|
|
48
|
+
<CommandPrimitive.Root
|
|
49
|
+
data-slot="command"
|
|
50
|
+
selectionMode={selectionMode}
|
|
51
|
+
defaultHighlightedValue={initialHighlight}
|
|
52
|
+
onSelect={(details) => {
|
|
53
|
+
handlers.current.get(details.value)?.(details.value)
|
|
54
|
+
onSelect?.(details)
|
|
55
|
+
}}
|
|
56
|
+
className={cn(
|
|
57
|
+
"flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
</CommandSelectContext.Provider>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function CommandContext({ ...props }: React.ComponentProps<typeof CommandPrimitive.Context>) {
|
|
67
|
+
return <CommandPrimitive.Context {...props} />
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function CommandDialog({
|
|
71
|
+
title = "Command Palette",
|
|
72
|
+
description = "Search for a command to run...",
|
|
73
|
+
children,
|
|
74
|
+
className,
|
|
75
|
+
showCloseButton = false,
|
|
76
|
+
...props
|
|
77
|
+
}: React.ComponentProps<typeof Dialog> & {
|
|
78
|
+
title?: string
|
|
79
|
+
description?: string
|
|
80
|
+
className?: string
|
|
81
|
+
showCloseButton?: boolean
|
|
82
|
+
}) {
|
|
83
|
+
return (
|
|
84
|
+
<Dialog {...props}>
|
|
85
|
+
<DialogContent className={cn("overflow-hidden rounded-xl! p-0", className)} showCloseButton={showCloseButton}>
|
|
86
|
+
<DialogHeader className="sr-only">
|
|
87
|
+
<DialogTitle>{title}</DialogTitle>
|
|
88
|
+
<DialogDescription>{description}</DialogDescription>
|
|
89
|
+
</DialogHeader>
|
|
90
|
+
{children}
|
|
91
|
+
</DialogContent>
|
|
92
|
+
</Dialog>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function CommandInput({
|
|
97
|
+
className,
|
|
98
|
+
autoHighlight = true,
|
|
99
|
+
onValueChange,
|
|
100
|
+
onChange,
|
|
101
|
+
onFocus,
|
|
102
|
+
...props
|
|
103
|
+
}: React.ComponentProps<typeof CommandPrimitive.Input> & {
|
|
104
|
+
/** Called with the input text on every change. Wire it to your collection's `filter`. */
|
|
105
|
+
onValueChange?: (value: string) => void
|
|
106
|
+
}) {
|
|
107
|
+
const settled = React.useRef(false)
|
|
108
|
+
return (
|
|
109
|
+
<div data-slot="command-input-wrapper" className="p-1 pb-0">
|
|
110
|
+
<InputGroup className="h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!">
|
|
111
|
+
<CommandPrimitive.Input
|
|
112
|
+
data-slot="command-input"
|
|
113
|
+
autoHighlight={autoHighlight}
|
|
114
|
+
onFocus={(event) => {
|
|
115
|
+
onFocus?.(event)
|
|
116
|
+
// When a Dialog focuses this input in the same tick it mounts, the
|
|
117
|
+
// listbox machine has not entered its ready state yet and drops the
|
|
118
|
+
// focus event, leaving the highlighted item invisible. Re-issue the
|
|
119
|
+
// focus once, on the next tick, so the listbox registers it.
|
|
120
|
+
if (settled.current) return
|
|
121
|
+
settled.current = true
|
|
122
|
+
const el = event.currentTarget
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
if (document.activeElement !== el) return
|
|
125
|
+
el.blur()
|
|
126
|
+
el.focus({ preventScroll: true })
|
|
127
|
+
}, 0)
|
|
128
|
+
}}
|
|
129
|
+
className={cn("w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50", className)}
|
|
130
|
+
onChange={(event) => {
|
|
131
|
+
onChange?.(event)
|
|
132
|
+
onValueChange?.(event.currentTarget.value)
|
|
133
|
+
}}
|
|
134
|
+
{...props}
|
|
135
|
+
/>
|
|
136
|
+
<InputGroupAddon>
|
|
137
|
+
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
|
138
|
+
</InputGroupAddon>
|
|
139
|
+
</InputGroup>
|
|
140
|
+
</div>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Content>) {
|
|
145
|
+
return (
|
|
146
|
+
<CommandPrimitive.Content
|
|
147
|
+
data-slot="command-list"
|
|
148
|
+
className={cn("no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none", className)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function CommandEmpty({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
|
155
|
+
return (
|
|
156
|
+
<CommandPrimitive.Empty
|
|
157
|
+
data-slot="command-empty"
|
|
158
|
+
className={cn("py-6 text-center text-sm", className)}
|
|
159
|
+
{...props}
|
|
160
|
+
/>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function CommandGroup({
|
|
165
|
+
className,
|
|
166
|
+
heading,
|
|
167
|
+
children,
|
|
168
|
+
...props
|
|
169
|
+
}: React.ComponentProps<typeof CommandPrimitive.ItemGroup> & {
|
|
170
|
+
heading?: React.ReactNode
|
|
171
|
+
}) {
|
|
172
|
+
return (
|
|
173
|
+
<CommandPrimitive.ItemGroup
|
|
174
|
+
data-slot="command-group"
|
|
175
|
+
className={cn("overflow-hidden p-1 text-foreground", className)}
|
|
176
|
+
{...props}
|
|
177
|
+
>
|
|
178
|
+
{heading != null && <CommandGroupLabel>{heading}</CommandGroupLabel>}
|
|
179
|
+
{children}
|
|
180
|
+
</CommandPrimitive.ItemGroup>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function CommandGroupLabel({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.ItemGroupLabel>) {
|
|
185
|
+
return (
|
|
186
|
+
<CommandPrimitive.ItemGroupLabel
|
|
187
|
+
data-slot="command-group-label"
|
|
188
|
+
className={cn("px-2 py-1.5 text-xs font-medium text-muted-foreground", className)}
|
|
189
|
+
{...props}
|
|
190
|
+
/>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function CommandSeparator({ className, ...props }: React.ComponentProps<"div">) {
|
|
195
|
+
return (
|
|
196
|
+
<div
|
|
197
|
+
role="separator"
|
|
198
|
+
aria-orientation="horizontal"
|
|
199
|
+
data-slot="command-separator"
|
|
200
|
+
className={cn("-mx-1 h-px bg-border", className)}
|
|
201
|
+
{...props}
|
|
202
|
+
/>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function CommandItem({
|
|
207
|
+
className,
|
|
208
|
+
children,
|
|
209
|
+
item,
|
|
210
|
+
value,
|
|
211
|
+
onSelect,
|
|
212
|
+
...props
|
|
213
|
+
}: Omit<React.ComponentProps<typeof CommandPrimitive.Item>, "item" | "onSelect"> & {
|
|
214
|
+
/** The collection item. Falls back to `value` for string collections. */
|
|
215
|
+
item?: CollectionItem
|
|
216
|
+
value?: string
|
|
217
|
+
/** Called with the item's value when it is selected by click or Enter. */
|
|
218
|
+
onSelect?: SelectHandler
|
|
219
|
+
}) {
|
|
220
|
+
const ctx = React.useContext(CommandSelectContext)
|
|
221
|
+
const resolvedItem = item ?? value
|
|
222
|
+
const itemValue =
|
|
223
|
+
typeof resolvedItem === "string" ? resolvedItem : ((resolvedItem as { value?: string } | undefined)?.value ?? value)
|
|
224
|
+
React.useEffect(() => {
|
|
225
|
+
if (!ctx || !onSelect || itemValue == null) return
|
|
226
|
+
return ctx.register(itemValue, onSelect)
|
|
227
|
+
}, [ctx, onSelect, itemValue])
|
|
228
|
+
return (
|
|
229
|
+
<CommandPrimitive.Item
|
|
230
|
+
data-slot="command-item"
|
|
231
|
+
item={resolvedItem}
|
|
232
|
+
className={cn(
|
|
233
|
+
"group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-highlighted:bg-muted data-highlighted:text-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-highlighted:*:[svg]:text-foreground",
|
|
234
|
+
className
|
|
235
|
+
)}
|
|
236
|
+
{...props}
|
|
237
|
+
>
|
|
238
|
+
{children}
|
|
239
|
+
<CommandItemIndicator>
|
|
240
|
+
<CheckIcon />
|
|
241
|
+
</CommandItemIndicator>
|
|
242
|
+
</CommandPrimitive.Item>
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function CommandItemText({ ...props }: React.ComponentProps<typeof CommandPrimitive.ItemText>) {
|
|
247
|
+
return <CommandPrimitive.ItemText data-slot="command-item-text" {...props} />
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function CommandItemIndicator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.ItemIndicator>) {
|
|
251
|
+
return (
|
|
252
|
+
<CommandPrimitive.ItemIndicator
|
|
253
|
+
data-slot="command-item-indicator"
|
|
254
|
+
className={cn("ml-auto group-has-data-[slot=command-shortcut]/command-item:hidden", className)}
|
|
255
|
+
{...props}
|
|
256
|
+
/>
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function CommandShortcut({ className, ...props }: React.ComponentProps<"span">) {
|
|
261
|
+
return (
|
|
262
|
+
<span
|
|
263
|
+
data-slot="command-shortcut"
|
|
264
|
+
className={cn(
|
|
265
|
+
"ml-auto text-xs tracking-widest text-muted-foreground group-data-highlighted/command-item:text-foreground",
|
|
266
|
+
className
|
|
267
|
+
)}
|
|
268
|
+
{...props}
|
|
269
|
+
/>
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export {
|
|
274
|
+
Command,
|
|
275
|
+
CommandContext,
|
|
276
|
+
CommandDialog,
|
|
277
|
+
CommandEmpty,
|
|
278
|
+
CommandGroup,
|
|
279
|
+
CommandGroupLabel,
|
|
280
|
+
CommandInput,
|
|
281
|
+
CommandItem,
|
|
282
|
+
CommandItemIndicator,
|
|
283
|
+
CommandItemText,
|
|
284
|
+
CommandList,
|
|
285
|
+
CommandSeparator,
|
|
286
|
+
CommandShortcut,
|
|
287
|
+
createListCollection,
|
|
288
|
+
useFilter,
|
|
289
|
+
useListCollection,
|
|
290
|
+
type CollectionItem,
|
|
291
|
+
type ListCollection,
|
|
292
|
+
}
|