kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1"use client";
2
3import { Dialog as CommandDialogPrimitive } from "@base-ui/react/dialog";
4import { SearchIcon } from "lucide-react";
5import type * as React from "react";
6import {
7 Autocomplete,
8 AutocompleteCollection,
9 AutocompleteEmpty,
10 AutocompleteGroup,
11 AutocompleteGroupLabel,
12 AutocompleteInput,
13 AutocompleteItem,
14 AutocompleteList,
15 AutocompleteSeparator,
16} from "@/components/ui/autocomplete";
17import { cn } from "@/lib/cn";
18
19const CommandDialog = CommandDialogPrimitive.Root;
20
21const CommandDialogPortal = CommandDialogPrimitive.Portal;
22
23const CommandCreateHandle = CommandDialogPrimitive.createHandle;
24
25function CommandDialogTrigger(props: CommandDialogPrimitive.Trigger.Props) {
26 return (
27 <CommandDialogPrimitive.Trigger
28 data-slot="command-dialog-trigger"
29 {...props}
30 />
31 );
32}
33
34function CommandDialogBackdrop({
35 className,
36 ...props
37}: CommandDialogPrimitive.Backdrop.Props) {
38 return (
39 <CommandDialogPrimitive.Backdrop
40 className={cn(
41 "fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0",
42 className,
43 )}
44 data-slot="command-dialog-backdrop"
45 {...props}
46 />
47 );
48}
49
50function CommandDialogViewport({
51 className,
52 ...props
53}: CommandDialogPrimitive.Viewport.Props) {
54 return (
55 <CommandDialogPrimitive.Viewport
56 className={cn(
57 "fixed inset-0 z-50 flex flex-col items-center px-4 py-[max(--spacing(4),4vh)] sm:py-[10vh]",
58 className,
59 )}
60 data-slot="command-dialog-viewport"
61 {...props}
62 />
63 );
64}
65
66function CommandDialogPopup({
67 className,
68 children,
69 ...props
70}: CommandDialogPrimitive.Popup.Props) {
71 return (
72 <CommandDialogPortal>
73 <CommandDialogBackdrop />
74 <CommandDialogViewport>
75 <CommandDialogPrimitive.Popup
76 className={cn(
77 "-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-105 min-h-0 w-full min-w-0 max-w-xl scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 outline-none transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:bg-muted/72 before:shadow-[0_1px_--theme(--color-black/4%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=scroll-area-viewport]:data-has-overflow-y:pe-1 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
78 className,
79 )}
80 data-slot="command-dialog-popup"
81 {...props}
82 >
83 {children}
84 </CommandDialogPrimitive.Popup>
85 </CommandDialogViewport>
86 </CommandDialogPortal>
87 );
88}
89
90function Command({
91 autoHighlight = "always",
92 keepHighlight = true,
93 ...props
94}: React.ComponentProps<typeof Autocomplete>) {
95 return (
96 <Autocomplete
97 autoHighlight={autoHighlight}
98 inline
99 keepHighlight={keepHighlight}
100 open
101 {...props}
102 />
103 );
104}
105
106function CommandInput({
107 className,
108 placeholder = undefined,
109 ...props
110}: React.ComponentProps<typeof AutocompleteInput>) {
111 return (
112 <div className="px-2.5 py-1.5">
113 <AutocompleteInput
114 autoFocus
115 className={cn(
116 "border-transparent! bg-transparent! shadow-none before:hidden has-focus-visible:ring-0",
117 className,
118 )}
119 placeholder={placeholder}
120 size="lg"
121 startAddon={<SearchIcon />}
122 {...props}
123 />
124 </div>
125 );
126}
127
128function CommandList({
129 className,
130 ...props
131}: React.ComponentProps<typeof AutocompleteList>) {
132 return (
133 <AutocompleteList
134 className={cn("not-empty:scroll-py-2 not-empty:p-2", className)}
135 data-slot="command-list"
136 {...props}
137 />
138 );
139}
140
141function CommandEmpty({
142 className,
143 ...props
144}: React.ComponentProps<typeof AutocompleteEmpty>) {
145 return (
146 <AutocompleteEmpty
147 className={cn("not-empty:py-6", className)}
148 data-slot="command-empty"
149 {...props}
150 />
151 );
152}
153
154function CommandPanel({ className, ...props }: React.ComponentProps<"div">) {
155 return (
156 <div
157 className="-mx-px not-has-[+[data-slot=command-footer]]:-mb-px relative min-h-0 rounded-t-xl not-has-[+[data-slot=command-footer]]:rounded-b-2xl border border-b-0 bg-popover bg-clip-padding shadow-xs/5 [clip-path:inset(0_1px)] not-has-[+[data-slot=command-footer]]:[clip-path:inset(0_1px_1px_1px_round_0_0_calc(var(--radius-2xl)-1px)_calc(var(--radius-2xl)-1px))] before:pointer-events-none before:absolute before:inset-0 before:rounded-t-[calc(var(--radius-xl)-1px)] **:data-[slot=scroll-area-scrollbar]:mt-2"
158 {...props}
159 />
160 );
161}
162
163function CommandGroup({
164 className,
165 ...props
166}: React.ComponentProps<typeof AutocompleteGroup>) {
167 return (
168 <AutocompleteGroup
169 className={className}
170 data-slot="command-group"
171 {...props}
172 />
173 );
174}
175
176function CommandGroupLabel({
177 className,
178 ...props
179}: React.ComponentProps<typeof AutocompleteGroupLabel>) {
180 return (
181 <AutocompleteGroupLabel
182 className={className}
183 data-slot="command-group-label"
184 {...props}
185 />
186 );
187}
188
189function CommandCollection({
190 ...props
191}: React.ComponentProps<typeof AutocompleteCollection>) {
192 return <AutocompleteCollection data-slot="command-collection" {...props} />;
193}
194
195function CommandItem({
196 className,
197 ...props
198}: React.ComponentProps<typeof AutocompleteItem>) {
199 return (
200 <AutocompleteItem
201 className={cn("py-1.5", className)}
202 data-slot="command-item"
203 {...props}
204 />
205 );
206}
207
208function CommandSeparator({
209 className,
210 ...props
211}: React.ComponentProps<typeof AutocompleteSeparator>) {
212 return (
213 <AutocompleteSeparator
214 className={cn("my-2", className)}
215 data-slot="command-separator"
216 {...props}
217 />
218 );
219}
220
221function CommandShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
222 return (
223 <kbd
224 className={cn(
225 "ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-widest",
226 className,
227 )}
228 data-slot="command-shortcut"
229 {...props}
230 />
231 );
232}
233
234function CommandFooter({ className, ...props }: React.ComponentProps<"div">) {
235 return (
236 <div
237 className={cn(
238 "flex items-center justify-between gap-2 rounded-b-[calc(var(--radius-2xl)-1px)] border-t px-5 py-3 text-muted-foreground text-xs",
239 className,
240 )}
241 data-slot="command-footer"
242 {...props}
243 />
244 );
245}
246
247export {
248 CommandCreateHandle,
249 Command,
250 CommandCollection,
251 CommandDialog,
252 CommandDialogPopup,
253 CommandDialogTrigger,
254 CommandEmpty,
255 CommandFooter,
256 CommandGroup,
257 CommandGroupLabel,
258 CommandInput,
259 CommandItem,
260 CommandList,
261 CommandPanel,
262 CommandSeparator,
263 CommandShortcut,
264};