create-strayl-web-app 1.0.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.
Files changed (78) hide show
  1. package/dist/index.js +59 -0
  2. package/dist/index.js.map +1 -0
  3. package/package.json +39 -0
  4. package/template/README.md +290 -0
  5. package/template/components.json +24 -0
  6. package/template/package.json +56 -0
  7. package/template/public/favicon.ico +0 -0
  8. package/template/public/google-logo.svg +6 -0
  9. package/template/public/logo-dark.ico +0 -0
  10. package/template/public/logo-dark.webp +0 -0
  11. package/template/public/logo-light.ico +0 -0
  12. package/template/public/logo-light.webp +0 -0
  13. package/template/public/manifest.json +16 -0
  14. package/template/public/robots.txt +3 -0
  15. package/template/src/components/Header.tsx +76 -0
  16. package/template/src/components/language-switcher.tsx +38 -0
  17. package/template/src/components/theme-provider.tsx +14 -0
  18. package/template/src/components/themed-logo.tsx +44 -0
  19. package/template/src/components/ui/accordion.tsx +69 -0
  20. package/template/src/components/ui/alert-dialog.tsx +169 -0
  21. package/template/src/components/ui/alert.tsx +80 -0
  22. package/template/src/components/ui/autocomplete.tsx +301 -0
  23. package/template/src/components/ui/avatar.tsx +46 -0
  24. package/template/src/components/ui/badge.tsx +60 -0
  25. package/template/src/components/ui/breadcrumb.tsx +112 -0
  26. package/template/src/components/ui/button.tsx +73 -0
  27. package/template/src/components/ui/card.tsx +244 -0
  28. package/template/src/components/ui/checkbox-group.tsx +16 -0
  29. package/template/src/components/ui/checkbox.tsx +60 -0
  30. package/template/src/components/ui/collapsible.tsx +45 -0
  31. package/template/src/components/ui/combobox.tsx +415 -0
  32. package/template/src/components/ui/command.tsx +264 -0
  33. package/template/src/components/ui/dialog.tsx +196 -0
  34. package/template/src/components/ui/empty.tsx +127 -0
  35. package/template/src/components/ui/field.tsx +74 -0
  36. package/template/src/components/ui/fieldset.tsx +29 -0
  37. package/template/src/components/ui/form.tsx +17 -0
  38. package/template/src/components/ui/frame.tsx +82 -0
  39. package/template/src/components/ui/group.tsx +97 -0
  40. package/template/src/components/ui/input-group.tsx +101 -0
  41. package/template/src/components/ui/input.tsx +66 -0
  42. package/template/src/components/ui/kbd.tsx +28 -0
  43. package/template/src/components/ui/label.tsx +28 -0
  44. package/template/src/components/ui/menu.tsx +310 -0
  45. package/template/src/components/ui/meter.tsx +67 -0
  46. package/template/src/components/ui/number-field.tsx +160 -0
  47. package/template/src/components/ui/pagination.tsx +136 -0
  48. package/template/src/components/ui/popover.tsx +104 -0
  49. package/template/src/components/ui/preview-card.tsx +55 -0
  50. package/template/src/components/ui/progress.tsx +81 -0
  51. package/template/src/components/ui/radio-group.tsx +36 -0
  52. package/template/src/components/ui/scroll-area.tsx +64 -0
  53. package/template/src/components/ui/select.tsx +180 -0
  54. package/template/src/components/ui/separator.tsx +23 -0
  55. package/template/src/components/ui/sheet.tsx +203 -0
  56. package/template/src/components/ui/sidebar.tsx +743 -0
  57. package/template/src/components/ui/skeleton.tsx +16 -0
  58. package/template/src/components/ui/slider.tsx +74 -0
  59. package/template/src/components/ui/spinner.tsx +18 -0
  60. package/template/src/components/ui/switch.tsx +27 -0
  61. package/template/src/components/ui/table.tsx +126 -0
  62. package/template/src/components/ui/tabs.tsx +87 -0
  63. package/template/src/components/ui/textarea.tsx +51 -0
  64. package/template/src/components/ui/toast.tsx +269 -0
  65. package/template/src/components/ui/toggle-group.tsx +102 -0
  66. package/template/src/components/ui/toggle.tsx +45 -0
  67. package/template/src/components/ui/toolbar.tsx +83 -0
  68. package/template/src/components/ui/tooltip.tsx +65 -0
  69. package/template/src/hooks/use-mobile.ts +21 -0
  70. package/template/src/lib/i18n.ts +70 -0
  71. package/template/src/lib/utils.ts +6 -0
  72. package/template/src/routeTree.gen.ts +68 -0
  73. package/template/src/router.tsx +17 -0
  74. package/template/src/routes/__root.tsx +62 -0
  75. package/template/src/routes/index.tsx +71 -0
  76. package/template/src/styles.css +121 -0
  77. package/template/tsconfig.json +28 -0
  78. package/template/vite.config.ts +30 -0
@@ -0,0 +1,415 @@
1
+ "use client";
2
+
3
+ import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox";
4
+ import { ChevronsUpDownIcon, XIcon } from "lucide-react";
5
+ import * as React from "react";
6
+
7
+ import { cn } from "@/lib/utils";
8
+ import { Input } from "@/components/ui/input";
9
+ import { ScrollArea } from "@/components/ui/scroll-area";
10
+
11
+ const ComboboxContext = React.createContext<{
12
+ chipsRef: React.RefObject<Element | null> | null;
13
+ multiple: boolean;
14
+ }>({
15
+ chipsRef: null,
16
+ multiple: false,
17
+ });
18
+
19
+ type ComboboxRootProps<
20
+ ItemValue,
21
+ Multiple extends boolean | undefined,
22
+ > = Parameters<typeof ComboboxPrimitive.Root<ItemValue, Multiple>>[0];
23
+
24
+ function Combobox<ItemValue, Multiple extends boolean | undefined = false>(
25
+ props: ComboboxPrimitive.Root.Props<ItemValue, Multiple>,
26
+ ) {
27
+ const chipsRef = React.useRef<Element | null>(null);
28
+ return (
29
+ <ComboboxContext.Provider value={{ chipsRef, multiple: !!props.multiple }}>
30
+ <ComboboxPrimitive.Root
31
+ {...(props as ComboboxRootProps<ItemValue, Multiple>)}
32
+ />
33
+ </ComboboxContext.Provider>
34
+ );
35
+ }
36
+
37
+ function ComboboxInput({
38
+ className,
39
+ showTrigger = true,
40
+ showClear = false,
41
+ startAddon,
42
+ size,
43
+ ...props
44
+ }: Omit<ComboboxPrimitive.Input.Props, "size"> & {
45
+ showTrigger?: boolean;
46
+ showClear?: boolean;
47
+ startAddon?: React.ReactNode;
48
+ size?: "sm" | "default" | "lg" | number;
49
+ ref?: React.Ref<HTMLInputElement>;
50
+ }) {
51
+ const { multiple } = React.useContext(ComboboxContext);
52
+ const sizeValue = (size ?? "default") as "sm" | "default" | "lg" | number;
53
+
54
+ // multiple mode
55
+ if (multiple) {
56
+ return (
57
+ <ComboboxPrimitive.Input
58
+ className={cn(
59
+ "min-w-12 flex-1 text-base outline-none sm:text-sm [[data-slot=combobox-chip]+&]:ps-0.5",
60
+ sizeValue === "sm" ? "ps-1.5" : "ps-2",
61
+ className,
62
+ )}
63
+ data-size={typeof sizeValue === "string" ? sizeValue : undefined}
64
+ data-slot="combobox-input"
65
+ size={typeof sizeValue === "number" ? sizeValue : undefined}
66
+ {...props}
67
+ />
68
+ );
69
+ }
70
+
71
+ // single mode
72
+ return (
73
+ <div className="relative not-has-[>*.w-full]:w-fit w-full text-foreground has-disabled:opacity-64">
74
+ {startAddon && (
75
+ <div
76
+ aria-hidden="true"
77
+ className="[&_svg]:-mx-0.5 pointer-events-none absolute inset-y-0 start-px z-10 flex items-center ps-[calc(--spacing(3)-1px)] opacity-80 has-[+[data-size=sm]]:ps-[calc(--spacing(2.5)-1px)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4"
78
+ data-slot="combobox-start-addon"
79
+ >
80
+ {startAddon}
81
+ </div>
82
+ )}
83
+ <ComboboxPrimitive.Input
84
+ className={cn(
85
+ startAddon &&
86
+ "data-[size=sm]:*:data-[slot=combobox-input]:ps-[calc(--spacing(7.5)-1px)] *:data-[slot=combobox-input]:ps-[calc(--spacing(8.5)-1px)] sm:data-[size=sm]:*:data-[slot=combobox-input]:ps-[calc(--spacing(7)-1px)] sm:*:data-[slot=combobox-input]:ps-[calc(--spacing(8)-1px)]",
87
+ sizeValue === "sm"
88
+ ? "has-[+[data-slot=combobox-trigger],+[data-slot=combobox-clear]]:*:data-[slot=combobox-input]:pe-6.5"
89
+ : "has-[+[data-slot=combobox-trigger],+[data-slot=combobox-clear]]:*:data-[slot=combobox-input]:pe-7",
90
+ className,
91
+ )}
92
+ data-slot="combobox-input"
93
+ render={
94
+ <Input
95
+ className="has-disabled:opacity-100"
96
+ nativeInput
97
+ size={sizeValue}
98
+ />
99
+ }
100
+ {...props}
101
+ />
102
+ {showTrigger && (
103
+ <ComboboxTrigger
104
+ className={cn(
105
+ "-translate-y-1/2 absolute top-1/2 inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md border border-transparent opacity-80 outline-none transition-opacity pointer-coarse:after:absolute pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:opacity-100 has-[+[data-slot=combobox-clear]]:hidden sm:size-7 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
106
+ sizeValue === "sm" ? "end-0" : "end-0.5",
107
+ )}
108
+ >
109
+ <ChevronsUpDownIcon />
110
+ </ComboboxTrigger>
111
+ )}
112
+ {showClear && (
113
+ <ComboboxClear
114
+ className={cn(
115
+ "-translate-y-1/2 absolute top-1/2 inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md border border-transparent opacity-80 outline-none transition-opacity pointer-coarse:after:absolute pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:opacity-100 has-[+[data-slot=combobox-clear]]:hidden sm:size-7 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
116
+ sizeValue === "sm" ? "end-0" : "end-0.5",
117
+ )}
118
+ >
119
+ <XIcon />
120
+ </ComboboxClear>
121
+ )}
122
+ </div>
123
+ );
124
+ }
125
+
126
+ function ComboboxTrigger({
127
+ className,
128
+ ...props
129
+ }: ComboboxPrimitive.Trigger.Props) {
130
+ return (
131
+ <ComboboxPrimitive.Trigger
132
+ className={className}
133
+ data-slot="combobox-trigger"
134
+ {...props}
135
+ />
136
+ );
137
+ }
138
+
139
+ function ComboboxPopup({
140
+ className,
141
+ children,
142
+ sideOffset = 4,
143
+ ...props
144
+ }: ComboboxPrimitive.Popup.Props & {
145
+ sideOffset?: number;
146
+ }) {
147
+ const { chipsRef } = React.useContext(ComboboxContext);
148
+
149
+ return (
150
+ <ComboboxPrimitive.Portal>
151
+ <ComboboxPrimitive.Positioner
152
+ anchor={chipsRef}
153
+ className="z-50 select-none"
154
+ data-slot="combobox-positioner"
155
+ sideOffset={sideOffset}
156
+ >
157
+ <span
158
+ className={cn(
159
+ "relative flex max-h-full origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
160
+ className,
161
+ )}
162
+ >
163
+ <ComboboxPrimitive.Popup
164
+ className="flex max-h-[min(var(--available-height),23rem)] w-(--anchor-width) max-w-(--available-width) flex-col text-foreground"
165
+ data-slot="combobox-popup"
166
+ {...props}
167
+ >
168
+ {children}
169
+ </ComboboxPrimitive.Popup>
170
+ </span>
171
+ </ComboboxPrimitive.Positioner>
172
+ </ComboboxPrimitive.Portal>
173
+ );
174
+ }
175
+
176
+ function ComboboxItem({
177
+ className,
178
+ children,
179
+ ...props
180
+ }: ComboboxPrimitive.Item.Props) {
181
+ return (
182
+ <ComboboxPrimitive.Item
183
+ className={cn(
184
+ "grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
185
+ className,
186
+ )}
187
+ data-slot="combobox-item"
188
+ {...props}
189
+ >
190
+ <ComboboxPrimitive.ItemIndicator className="col-start-1">
191
+ <svg
192
+ fill="none"
193
+ height="24"
194
+ stroke="currentColor"
195
+ strokeLinecap="round"
196
+ strokeLinejoin="round"
197
+ strokeWidth="2"
198
+ viewBox="0 0 24 24"
199
+ width="24"
200
+ xmlns="http://www.w3.org/1500/svg"
201
+ >
202
+ <path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
203
+ </svg>
204
+ </ComboboxPrimitive.ItemIndicator>
205
+ <div className="col-start-2">{children}</div>
206
+ </ComboboxPrimitive.Item>
207
+ );
208
+ }
209
+
210
+ function ComboboxSeparator({
211
+ className,
212
+ ...props
213
+ }: ComboboxPrimitive.Separator.Props) {
214
+ return (
215
+ <ComboboxPrimitive.Separator
216
+ className={cn("mx-2 my-1 h-px bg-border last:hidden", className)}
217
+ data-slot="combobox-separator"
218
+ {...props}
219
+ />
220
+ );
221
+ }
222
+
223
+ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
224
+ return (
225
+ <ComboboxPrimitive.Group
226
+ className={cn("[[role=group]+&]:mt-1.5", className)}
227
+ data-slot="combobox-group"
228
+ {...props}
229
+ />
230
+ );
231
+ }
232
+
233
+ function ComboboxGroupLabel({
234
+ className,
235
+ ...props
236
+ }: ComboboxPrimitive.GroupLabel.Props) {
237
+ return (
238
+ <ComboboxPrimitive.GroupLabel
239
+ className={cn(
240
+ "px-2 py-1.5 font-medium text-muted-foreground text-xs",
241
+ className,
242
+ )}
243
+ data-slot="combobox-group-label"
244
+ {...props}
245
+ />
246
+ );
247
+ }
248
+
249
+ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
250
+ return (
251
+ <ComboboxPrimitive.Empty
252
+ className={cn(
253
+ "not-empty:p-2 text-center text-base text-muted-foreground sm:text-sm",
254
+ className,
255
+ )}
256
+ data-slot="combobox-empty"
257
+ {...props}
258
+ />
259
+ );
260
+ }
261
+
262
+ function ComboboxRow({ className, ...props }: ComboboxPrimitive.Row.Props) {
263
+ return (
264
+ <ComboboxPrimitive.Row
265
+ className={className}
266
+ data-slot="combobox-row"
267
+ {...props}
268
+ />
269
+ );
270
+ }
271
+
272
+ function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
273
+ return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />;
274
+ }
275
+
276
+ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
277
+ return (
278
+ <ScrollArea scrollbarGutter scrollFade>
279
+ <ComboboxPrimitive.List
280
+ className={cn(
281
+ "not-empty:scroll-py-1 not-empty:px-1 not-empty:py-1 in-data-has-overflow-y:pe-3",
282
+ className,
283
+ )}
284
+ data-slot="combobox-list"
285
+ {...props}
286
+ />
287
+ </ScrollArea>
288
+ );
289
+ }
290
+
291
+ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
292
+ return (
293
+ <ComboboxPrimitive.Clear
294
+ className={className}
295
+ data-slot="combobox-clear"
296
+ {...props}
297
+ />
298
+ );
299
+ }
300
+
301
+ function ComboboxStatus({
302
+ className,
303
+ ...props
304
+ }: ComboboxPrimitive.Status.Props) {
305
+ return (
306
+ <ComboboxPrimitive.Status
307
+ className={cn(
308
+ "px-3 py-2 font-medium text-muted-foreground text-xs empty:m-0 empty:p-0",
309
+ className,
310
+ )}
311
+ data-slot="combobox-status"
312
+ {...props}
313
+ />
314
+ );
315
+ }
316
+
317
+ function ComboboxCollection(props: ComboboxPrimitive.Collection.Props) {
318
+ return (
319
+ <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />
320
+ );
321
+ }
322
+
323
+ function ComboboxChips({
324
+ className,
325
+ children,
326
+ startAddon,
327
+ ...props
328
+ }: ComboboxPrimitive.Chips.Props & {
329
+ startAddon?: React.ReactNode;
330
+ }) {
331
+ const { chipsRef } = React.useContext(ComboboxContext);
332
+
333
+ return (
334
+ <ComboboxPrimitive.Chips
335
+ className={cn(
336
+ "relative inline-flex min-h-9 w-full flex-wrap gap-1 rounded-lg border border-input bg-background not-dark:bg-clip-padding p-[calc(--spacing(1)-1px)] text-base shadow-xs/5 outline-none ring-ring/24 transition-shadow *:min-h-7 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-within:border-ring focus-within:ring-[3px] has-disabled:pointer-events-none has-data-[size=lg]:min-h-10 has-data-[size=sm]:min-h-8 has-aria-invalid:border-destructive/36 has-disabled:opacity-64 has-[:disabled,:focus-within,[aria-invalid]]:shadow-none focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/16 has-data-[size=lg]:*:min-h-8 has-data-[size=sm]:*:min-h-6 sm:min-h-8 sm:text-sm sm:has-data-[size=lg]:min-h-9 sm:has-data-[size=sm]:min-h-7 sm:*:min-h-6 sm:has-data-[size=lg]:*:min-h-7 sm:has-data-[size=sm]:*:min-h-5 dark:not-has-disabled:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
337
+ className,
338
+ )}
339
+ data-slot="combobox-chips"
340
+ onMouseDown={(e) => {
341
+ const target = e.target as HTMLElement;
342
+ const isChip = target.closest('[data-slot="combobox-chip"]');
343
+ if (isChip || !chipsRef?.current) return;
344
+ e.preventDefault();
345
+ const input: HTMLInputElement | null =
346
+ chipsRef.current.querySelector("input");
347
+ if (input && !chipsRef.current.querySelector("input:focus")) {
348
+ input.focus();
349
+ }
350
+ }}
351
+ ref={chipsRef as React.Ref<HTMLDivElement> | null}
352
+ {...props}
353
+ >
354
+ {startAddon && (
355
+ <div
356
+ aria-hidden="true"
357
+ className="[&_svg]:-ms-0.5 [&_svg]:-me-1.5 flex shrink-0 items-center ps-2 opacity-80 has-[~[data-size=sm]]:has-[+[data-slot=combobox-chip]]:pe-1.5 has-[~[data-size=sm]]:ps-1.5 has-[+[data-slot=combobox-chip]]:pe-2 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none"
358
+ data-slot="combobox-start-addon"
359
+ >
360
+ {startAddon}
361
+ </div>
362
+ )}
363
+ {children}
364
+ </ComboboxPrimitive.Chips>
365
+ );
366
+ }
367
+
368
+ function ComboboxChip({ children, ...props }: ComboboxPrimitive.Chip.Props) {
369
+ return (
370
+ <ComboboxPrimitive.Chip
371
+ className="flex items-center rounded-[calc(var(--radius-md)-1px)] bg-accent ps-2 font-medium text-accent-foreground text-sm outline-none sm:text-xs/(--text-xs--line-height) [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
372
+ data-slot="combobox-chip"
373
+ {...props}
374
+ >
375
+ {children}
376
+ <ComboboxChipRemove />
377
+ </ComboboxPrimitive.Chip>
378
+ );
379
+ }
380
+
381
+ function ComboboxChipRemove(props: ComboboxPrimitive.ChipRemove.Props) {
382
+ return (
383
+ <ComboboxPrimitive.ChipRemove
384
+ aria-label="Remove"
385
+ className="h-full shrink-0 cursor-pointer px-1.5 opacity-80 hover:opacity-100 [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
386
+ data-slot="combobox-chip-remove"
387
+ {...props}
388
+ >
389
+ <XIcon />
390
+ </ComboboxPrimitive.ChipRemove>
391
+ );
392
+ }
393
+
394
+ const useComboboxFilter = ComboboxPrimitive.useFilter;
395
+
396
+ export {
397
+ Combobox,
398
+ ComboboxInput,
399
+ ComboboxTrigger,
400
+ ComboboxPopup,
401
+ ComboboxItem,
402
+ ComboboxSeparator,
403
+ ComboboxGroup,
404
+ ComboboxGroupLabel,
405
+ ComboboxEmpty,
406
+ ComboboxValue,
407
+ ComboboxList,
408
+ ComboboxClear,
409
+ ComboboxStatus,
410
+ ComboboxRow,
411
+ ComboboxCollection,
412
+ ComboboxChips,
413
+ ComboboxChip,
414
+ useComboboxFilter,
415
+ };
@@ -0,0 +1,264 @@
1
+ "use client";
2
+
3
+ import { Dialog as CommandDialogPrimitive } from "@base-ui/react/dialog";
4
+ import { SearchIcon } from "lucide-react";
5
+ import type * as React from "react";
6
+ import { cn } from "@/lib/utils";
7
+ import {
8
+ Autocomplete,
9
+ AutocompleteCollection,
10
+ AutocompleteEmpty,
11
+ AutocompleteGroup,
12
+ AutocompleteGroupLabel,
13
+ AutocompleteInput,
14
+ AutocompleteItem,
15
+ AutocompleteList,
16
+ AutocompleteSeparator,
17
+ } from "@/components/ui/autocomplete";
18
+
19
+ const CommandDialog = CommandDialogPrimitive.Root;
20
+
21
+ const CommandDialogPortal = CommandDialogPrimitive.Portal;
22
+
23
+ const CommandCreateHandle = CommandDialogPrimitive.createHandle;
24
+
25
+ function CommandDialogTrigger(props: CommandDialogPrimitive.Trigger.Props) {
26
+ return (
27
+ <CommandDialogPrimitive.Trigger
28
+ data-slot="command-dialog-trigger"
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function 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
+
50
+ function 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
+
66
+ function 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/6%)] 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
+
90
+ function 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
+
106
+ function 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
+
128
+ function 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
+
141
+ function 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
+
154
+ function 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
+
163
+ function 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
+
176
+ function 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
+
189
+ function CommandCollection({
190
+ ...props
191
+ }: React.ComponentProps<typeof AutocompleteCollection>) {
192
+ return <AutocompleteCollection data-slot="command-collection" {...props} />;
193
+ }
194
+
195
+ function 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
+
208
+ function 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
+
221
+ function 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
+
234
+ function 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
+
247
+ export {
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
+ };