@turtleclub/ui 0.7.0-beta.3 → 0.7.0-beta.30
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/.turbo/turbo-build.log +143 -132
- package/CHANGELOG.md +152 -0
- package/dist/index.cjs +76 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36068 -17674
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/components/charts/area-chart.d.ts +108 -0
- package/dist/types/components/charts/area-chart.d.ts.map +1 -0
- package/dist/types/components/charts/bar-chart.d.ts +110 -0
- package/dist/types/components/charts/bar-chart.d.ts.map +1 -0
- package/dist/types/components/charts/index.d.ts +5 -0
- package/dist/types/components/charts/index.d.ts.map +1 -0
- package/dist/types/components/charts/pie-chart.d.ts +94 -0
- package/dist/types/components/charts/pie-chart.d.ts.map +1 -0
- package/dist/types/components/charts/radial-chart.d.ts +151 -0
- package/dist/types/components/charts/radial-chart.d.ts.map +1 -0
- package/dist/types/components/features/data-table/data-table.d.ts +7 -4
- package/dist/types/components/features/data-table/data-table.d.ts.map +1 -1
- package/dist/types/components/features/data-table/sort-dropdown.d.ts.map +1 -1
- package/dist/types/components/features/search-bar.d.ts +1 -0
- package/dist/types/components/features/search-bar.d.ts.map +1 -1
- package/dist/types/components/molecules/swap-input.d.ts +3 -0
- package/dist/types/components/molecules/swap-input.d.ts.map +1 -1
- package/dist/types/components/molecules/token-selector.d.ts +2 -1
- package/dist/types/components/molecules/token-selector.d.ts.map +1 -1
- package/dist/types/components/ui/avatar.d.ts +2 -2
- package/dist/types/components/ui/avatar.d.ts.map +1 -1
- package/dist/types/components/ui/chart.d.ts +18 -4
- package/dist/types/components/ui/chart.d.ts.map +1 -1
- package/dist/types/components/ui/combobox.d.ts +21 -0
- package/dist/types/components/ui/combobox.d.ts.map +1 -1
- package/dist/types/components/ui/dialog.d.ts.map +1 -1
- package/dist/types/components/ui/dropdown.d.ts +2 -1
- package/dist/types/components/ui/dropdown.d.ts.map +1 -1
- package/dist/types/components/ui/index.d.ts +1 -0
- package/dist/types/components/ui/index.d.ts.map +1 -1
- package/dist/types/components/ui/multi-select.d.ts.map +1 -1
- package/dist/types/components/ui/segment-control.d.ts +1 -0
- package/dist/types/components/ui/segment-control.d.ts.map +1 -1
- package/dist/types/components/ui/slider.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/components/charts/QUICK_REFERENCE.md +323 -0
- package/src/components/charts/README.md +658 -0
- package/src/components/charts/RECHARTS_FEATURES.md +458 -0
- package/src/components/charts/area-chart.tsx +248 -0
- package/src/components/charts/bar-chart.tsx +362 -0
- package/src/components/charts/index.ts +4 -0
- package/src/components/charts/pie-chart.tsx +277 -0
- package/src/components/charts/radial-chart.tsx +312 -0
- package/src/components/features/data-table/data-table.tsx +136 -125
- package/src/components/features/data-table/sort-dropdown.tsx +8 -11
- package/src/components/features/search-bar.tsx +6 -1
- package/src/components/molecules/swap-input.tsx +44 -30
- package/src/components/molecules/token-selector.tsx +10 -1
- package/src/components/ui/avatar.tsx +8 -15
- package/src/components/ui/chart.tsx +100 -109
- package/src/components/ui/combobox.tsx +150 -137
- package/src/components/ui/dialog.tsx +9 -23
- package/src/components/ui/dropdown.tsx +3 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/multi-select.tsx +325 -307
- package/src/components/ui/segment-control.tsx +7 -2
- package/src/components/ui/slider.tsx +6 -11
- package/src/index.ts +1 -0
- package/src/styles/globals.css +4 -0
- package/src/styles/themes/semantic.css +26 -56
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { CheckIcon, ChevronDown, WandSparkles, XIcon } from "lucide-react";
|
|
5
|
-
|
|
6
|
-
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { Check as CheckIcon, ChevronDown, WandSparkles, X as XIcon } from "lucide-react";
|
|
5
|
+
import { buttonVariants } from "@/components/ui/button";
|
|
7
6
|
import {
|
|
8
7
|
Command,
|
|
9
8
|
CommandEmpty,
|
|
@@ -12,11 +11,7 @@ import {
|
|
|
12
11
|
CommandItem,
|
|
13
12
|
CommandList,
|
|
14
13
|
} from "@/components/ui/command";
|
|
15
|
-
import {
|
|
16
|
-
Popover,
|
|
17
|
-
PopoverContent,
|
|
18
|
-
PopoverTrigger,
|
|
19
|
-
} from "@/components/ui/popover";
|
|
14
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
20
15
|
import { Separator } from "@/components/ui/separator";
|
|
21
16
|
import { cn } from "@/lib/utils";
|
|
22
17
|
|
|
@@ -89,23 +84,40 @@ interface ComboboxOption<T = string> {
|
|
|
89
84
|
* />
|
|
90
85
|
*/
|
|
91
86
|
interface ComboboxProps<T = string>
|
|
92
|
-
extends Omit<
|
|
93
|
-
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
94
|
-
"animationConfig" | "defaultValue"
|
|
95
|
-
> {
|
|
87
|
+
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "animationConfig" | "defaultValue"> {
|
|
96
88
|
/**
|
|
97
89
|
* An array of option objects or groups to be displayed in the multi-select component.
|
|
98
90
|
*/
|
|
99
91
|
options: ComboboxOption<T>[];
|
|
92
|
+
|
|
100
93
|
/**
|
|
101
94
|
* Callback function triggered when the selected values change.
|
|
102
95
|
* Receives an array of the new selected values.
|
|
103
96
|
*/
|
|
104
97
|
onValueChange: (value: T) => void;
|
|
105
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Custom renderer for the selected value displayed in the input.
|
|
101
|
+
* @param option The currently selected option object.
|
|
102
|
+
*/
|
|
103
|
+
renderValue?: (option: ComboboxOption<T>) => React.ReactNode;
|
|
104
|
+
|
|
106
105
|
/** The default selected values when the component mounts. */
|
|
107
106
|
defaultValue?: T;
|
|
108
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Callback function triggered when the search input value changes.
|
|
110
|
+
* Useful for server-side filtering or handling large datasets externally.
|
|
111
|
+
*/
|
|
112
|
+
onInputValueChange?: (value: string) => void;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* If true, disables the built-in filtering logic.
|
|
116
|
+
* Use this when you filter options externally (e.g. server-side search).
|
|
117
|
+
* Optional, defaults to false.
|
|
118
|
+
*/
|
|
119
|
+
disableLocalFiltering?: boolean;
|
|
120
|
+
|
|
109
121
|
/**
|
|
110
122
|
* Placeholder text to be displayed when no values are selected.
|
|
111
123
|
* Optional, defaults to "Select options".
|
|
@@ -144,6 +156,12 @@ interface ComboboxProps<T = string>
|
|
|
144
156
|
*/
|
|
145
157
|
searchable?: boolean;
|
|
146
158
|
|
|
159
|
+
/**
|
|
160
|
+
* If true, searching will also check the 'value' field in addition to 'label'.
|
|
161
|
+
* Optional, defaults to false.
|
|
162
|
+
*/
|
|
163
|
+
searchByValue?: boolean;
|
|
164
|
+
|
|
147
165
|
/**
|
|
148
166
|
* Custom empty state message when no options match search.
|
|
149
167
|
* Optional, defaults to "No results found."
|
|
@@ -237,10 +255,7 @@ export interface ComboboxRef {
|
|
|
237
255
|
focus: () => void;
|
|
238
256
|
}
|
|
239
257
|
|
|
240
|
-
const ComboboxComponent = <T = string,>(
|
|
241
|
-
props: ComboboxProps<T>,
|
|
242
|
-
ref: React.Ref<ComboboxRef>,
|
|
243
|
-
) => {
|
|
258
|
+
const ComboboxComponent = <T = string,>(props: ComboboxProps<T>, ref: React.Ref<ComboboxRef>) => {
|
|
244
259
|
const {
|
|
245
260
|
options,
|
|
246
261
|
onValueChange,
|
|
@@ -258,6 +273,10 @@ const ComboboxComponent = <T = string,>(
|
|
|
258
273
|
minWidth,
|
|
259
274
|
maxWidth,
|
|
260
275
|
closeOnSelect = false,
|
|
276
|
+
renderValue,
|
|
277
|
+
searchByValue = false,
|
|
278
|
+
onInputValueChange,
|
|
279
|
+
disableLocalFiltering = false,
|
|
261
280
|
...restProps
|
|
262
281
|
} = props;
|
|
263
282
|
|
|
@@ -293,7 +312,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
293
312
|
setTimeout(() => setPoliteMessage(""), 100);
|
|
294
313
|
}
|
|
295
314
|
},
|
|
296
|
-
[]
|
|
315
|
+
[]
|
|
297
316
|
);
|
|
298
317
|
|
|
299
318
|
const multiSelectId = React.useId();
|
|
@@ -334,12 +353,10 @@ const ComboboxComponent = <T = string,>(
|
|
|
334
353
|
}
|
|
335
354
|
},
|
|
336
355
|
}),
|
|
337
|
-
[resetToDefault, onValueChange]
|
|
356
|
+
[resetToDefault, onValueChange]
|
|
338
357
|
);
|
|
339
358
|
|
|
340
|
-
const [screenSize, setScreenSize] = React.useState<
|
|
341
|
-
"mobile" | "tablet" | "desktop"
|
|
342
|
-
>("desktop");
|
|
359
|
+
const [screenSize, setScreenSize] = React.useState<"mobile" | "tablet" | "desktop">("desktop");
|
|
343
360
|
|
|
344
361
|
React.useEffect(() => {
|
|
345
362
|
if (typeof window === "undefined") return;
|
|
@@ -410,25 +427,31 @@ const ComboboxComponent = <T = string,>(
|
|
|
410
427
|
(value: T): ComboboxOption<T> | undefined => {
|
|
411
428
|
const option = getAllOptions().find((option) => option.value === value);
|
|
412
429
|
if (!option && process.env.NODE_ENV === "development") {
|
|
413
|
-
console.warn(
|
|
414
|
-
`Combobox: Option with value "${value}" not found in options list`,
|
|
415
|
-
);
|
|
430
|
+
console.warn(`Combobox: Option with value "${value}" not found in options list`);
|
|
416
431
|
}
|
|
417
432
|
return option;
|
|
418
433
|
},
|
|
419
|
-
[getAllOptions]
|
|
434
|
+
[getAllOptions]
|
|
420
435
|
);
|
|
421
436
|
|
|
422
437
|
const filteredOptions = React.useMemo(() => {
|
|
438
|
+
if (disableLocalFiltering) return options;
|
|
423
439
|
if (!searchable || !searchValue) return options;
|
|
424
440
|
if (options.length === 0) return [];
|
|
425
441
|
|
|
426
|
-
return options.filter(
|
|
427
|
-
(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
442
|
+
return options.filter((option) => {
|
|
443
|
+
const labelMatch = option.label.toLowerCase().includes(searchValue.toLowerCase());
|
|
444
|
+
if (!searchByValue) return labelMatch;
|
|
445
|
+
|
|
446
|
+
const val = option.value;
|
|
447
|
+
const valueMatch =
|
|
448
|
+
typeof val === "string" || typeof val === "number"
|
|
449
|
+
? String(val).toLowerCase().includes(searchValue.toLowerCase())
|
|
450
|
+
: false;
|
|
451
|
+
|
|
452
|
+
return labelMatch || valueMatch;
|
|
453
|
+
});
|
|
454
|
+
}, [disableLocalFiltering, options, searchable, searchValue, searchByValue]);
|
|
432
455
|
|
|
433
456
|
// const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
434
457
|
// if (event.key === "Enter") {
|
|
@@ -477,9 +500,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
477
500
|
|
|
478
501
|
if (isPopoverOpen !== prevIsOpen.current) {
|
|
479
502
|
if (isPopoverOpen) {
|
|
480
|
-
announce(
|
|
481
|
-
`Dropdown opened. ${totalOptions} options available. Use arrow keys to navigate.`,
|
|
482
|
-
);
|
|
503
|
+
announce(`Dropdown opened. ${totalOptions} options available. Use arrow keys to navigate.`);
|
|
483
504
|
} else {
|
|
484
505
|
announce("Dropdown closed.");
|
|
485
506
|
}
|
|
@@ -491,11 +512,11 @@ const ComboboxComponent = <T = string,>(
|
|
|
491
512
|
const filteredCount = allOptions.filter(
|
|
492
513
|
(opt) =>
|
|
493
514
|
opt.label.toLowerCase().includes(searchValue.toLowerCase()) ||
|
|
494
|
-
String(opt.value).toLowerCase().includes(searchValue.toLowerCase())
|
|
515
|
+
String(opt.value).toLowerCase().includes(searchValue.toLowerCase())
|
|
495
516
|
).length;
|
|
496
517
|
|
|
497
518
|
announce(
|
|
498
|
-
`${filteredCount} option${filteredCount === 1 ? "" : "s"} found for "${searchValue}"
|
|
519
|
+
`${filteredCount} option${filteredCount === 1 ? "" : "s"} found for "${searchValue}"`
|
|
499
520
|
);
|
|
500
521
|
}
|
|
501
522
|
prevSearchValue.current = searchValue;
|
|
@@ -513,101 +534,94 @@ const ComboboxComponent = <T = string,>(
|
|
|
513
534
|
</div>
|
|
514
535
|
</div>
|
|
515
536
|
|
|
516
|
-
<Popover
|
|
517
|
-
open={isPopoverOpen}
|
|
518
|
-
onOpenChange={setIsPopoverOpen}
|
|
519
|
-
modal={modalPopover}
|
|
520
|
-
>
|
|
537
|
+
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen} modal={modalPopover}>
|
|
521
538
|
<div id={triggerDescriptionId} className="sr-only">
|
|
522
|
-
Multi-select dropdown. Use arrow keys to navigate, Enter to select,
|
|
523
|
-
and Escape to close.
|
|
539
|
+
Multi-select dropdown. Use arrow keys to navigate, Enter to select, and Escape to close.
|
|
524
540
|
</div>
|
|
525
|
-
<PopoverTrigger
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
{
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
541
|
+
<PopoverTrigger
|
|
542
|
+
ref={buttonRef}
|
|
543
|
+
{...restProps}
|
|
544
|
+
onClick={handleTogglePopover}
|
|
545
|
+
disabled={disabled}
|
|
546
|
+
role="combobox"
|
|
547
|
+
aria-expanded={isPopoverOpen}
|
|
548
|
+
aria-haspopup="listbox"
|
|
549
|
+
aria-controls={isPopoverOpen ? listboxId : undefined}
|
|
550
|
+
aria-describedby={`${triggerDescriptionId} ${selectedCountId}`}
|
|
551
|
+
className={cn(
|
|
552
|
+
buttonVariants({
|
|
553
|
+
variant: "default",
|
|
554
|
+
size: "default",
|
|
555
|
+
border: "plain",
|
|
556
|
+
}),
|
|
557
|
+
"flex h-10 items-center justify-between [&_svg]:pointer-events-auto",
|
|
558
|
+
"!bg-neutral-alpha-2 text-base !font-normal shadow md:text-sm",
|
|
559
|
+
autoSize ? "w-auto" : "w-full",
|
|
560
|
+
responsiveSettings.compactMode && "h-8 text-sm",
|
|
561
|
+
screenSize === "mobile" && "h-12 text-base",
|
|
562
|
+
disabled && "cursor-not-allowed opacity-50",
|
|
563
|
+
className
|
|
564
|
+
)}
|
|
565
|
+
style={{
|
|
566
|
+
...widthConstraints,
|
|
567
|
+
maxWidth: `min(${widthConstraints.maxWidth}, 100%)`,
|
|
568
|
+
}}
|
|
569
|
+
>
|
|
570
|
+
{selectedValue ? (
|
|
571
|
+
<div className="mx-auto flex w-full items-center justify-between">
|
|
572
|
+
<div className="flex items-center gap-2">
|
|
573
|
+
{(() => {
|
|
574
|
+
const selectedOption = options.find((op) => op.value === selectedValue);
|
|
575
|
+
|
|
576
|
+
if (renderValue && selectedOption) {
|
|
577
|
+
return renderValue(selectedOption);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return (
|
|
581
|
+
<>
|
|
582
|
+
{selectedOption?.icon && (
|
|
583
|
+
<selectedOption.icon
|
|
584
|
+
className="text-muted-foreground size-3.5"
|
|
585
|
+
aria-hidden="true"
|
|
586
|
+
/>
|
|
587
|
+
)}
|
|
588
|
+
<span className="text-foreground text-sm">{selectedOption?.label}</span>
|
|
589
|
+
</>
|
|
590
|
+
);
|
|
591
|
+
})()}
|
|
592
|
+
</div>
|
|
593
|
+
<div className="flex items-center justify-between">
|
|
594
|
+
<div
|
|
595
|
+
role="button"
|
|
596
|
+
tabIndex={0}
|
|
597
|
+
onClick={(event) => {
|
|
598
|
+
event.stopPropagation();
|
|
599
|
+
handleClear();
|
|
600
|
+
}}
|
|
601
|
+
onKeyDown={(event) => {
|
|
602
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
603
|
+
event.preventDefault();
|
|
578
604
|
event.stopPropagation();
|
|
579
605
|
handleClear();
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
handleClear();
|
|
586
|
-
}
|
|
587
|
-
}}
|
|
588
|
-
className="text-muted-foreground hover:text-foreground focus:ring-ring mx-2 flex size-3.5 cursor-pointer items-center justify-center rounded-sm focus:ring-2 focus:ring-offset-1 focus:outline-none"
|
|
589
|
-
>
|
|
590
|
-
<XIcon className="size-3.5" />
|
|
591
|
-
</div>
|
|
592
|
-
<Separator
|
|
593
|
-
orientation="vertical"
|
|
594
|
-
className="flex h-full min-h-6"
|
|
595
|
-
/>
|
|
596
|
-
<ChevronDown
|
|
597
|
-
className="text-muted-foreground mx-2 h-4 cursor-pointer"
|
|
598
|
-
aria-hidden="true"
|
|
599
|
-
/>
|
|
606
|
+
}
|
|
607
|
+
}}
|
|
608
|
+
className="text-muted-foreground hover:text-foreground focus:ring-ring mx-2 flex size-3.5 cursor-pointer items-center justify-center rounded-sm focus:ring-2 focus:ring-offset-1 focus:outline-none"
|
|
609
|
+
>
|
|
610
|
+
<XIcon className="size-3.5" />
|
|
600
611
|
</div>
|
|
612
|
+
<Separator orientation="vertical" className="flex h-full min-h-6" />
|
|
613
|
+
<ChevronDown
|
|
614
|
+
className="text-muted-foreground mx-2 h-4 cursor-pointer"
|
|
615
|
+
aria-hidden="true"
|
|
616
|
+
/>
|
|
601
617
|
</div>
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
)}
|
|
610
|
-
</Button>
|
|
618
|
+
</div>
|
|
619
|
+
) : (
|
|
620
|
+
<div className="mx-auto flex w-full items-center justify-between">
|
|
621
|
+
<span className="text-muted-foreground text-sm">{placeholder}</span>
|
|
622
|
+
<ChevronDown className="text-muted-foreground mx-2 h-4 cursor-pointer" />
|
|
623
|
+
</div>
|
|
624
|
+
)}
|
|
611
625
|
</PopoverTrigger>
|
|
612
626
|
<PopoverContent
|
|
613
627
|
id={listboxId}
|
|
@@ -619,7 +633,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
619
633
|
screenSize === "mobile" && "w-[85vw] max-w-[280px]",
|
|
620
634
|
screenSize === "tablet" && "w-[70vw] max-w-md",
|
|
621
635
|
screenSize === "desktop" && "min-w-[300px]",
|
|
622
|
-
popoverClassName
|
|
636
|
+
popoverClassName
|
|
623
637
|
)}
|
|
624
638
|
style={{
|
|
625
639
|
maxWidth: `min(${widthConstraints.maxWidth}, 85vw)`,
|
|
@@ -635,7 +649,10 @@ const ComboboxComponent = <T = string,>(
|
|
|
635
649
|
placeholder="Search options..."
|
|
636
650
|
// onKeyDown={handleInputKeyDown}
|
|
637
651
|
value={searchValue}
|
|
638
|
-
onValueChange={
|
|
652
|
+
onValueChange={(val) => {
|
|
653
|
+
setSearchValue(val);
|
|
654
|
+
onInputValueChange?.(val);
|
|
655
|
+
}}
|
|
639
656
|
aria-label="Search through available options"
|
|
640
657
|
aria-describedby={`${multiSelectId}-search-help`}
|
|
641
658
|
/>
|
|
@@ -649,12 +666,10 @@ const ComboboxComponent = <T = string,>(
|
|
|
649
666
|
className={cn(
|
|
650
667
|
"multiselect-scrollbar max-h-[40vh] overflow-y-auto",
|
|
651
668
|
screenSize === "mobile" && "max-h-[50vh]",
|
|
652
|
-
"overscroll-behavior-y-contain"
|
|
669
|
+
"overscroll-behavior-y-contain"
|
|
653
670
|
)}
|
|
654
671
|
>
|
|
655
|
-
<CommandEmpty>
|
|
656
|
-
{emptyIndicator || "No results found."}
|
|
657
|
-
</CommandEmpty>{" "}
|
|
672
|
+
<CommandEmpty>{emptyIndicator || "No results found."}</CommandEmpty>{" "}
|
|
658
673
|
<CommandGroup>
|
|
659
674
|
{filteredOptions.map((option) => {
|
|
660
675
|
const isSelected = selectedValue === option.value;
|
|
@@ -670,7 +685,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
670
685
|
}${option.disabled ? ", disabled" : ""}`}
|
|
671
686
|
className={cn(
|
|
672
687
|
"cursor-pointer",
|
|
673
|
-
option.disabled && "cursor-not-allowed opacity-50"
|
|
688
|
+
option.disabled && "cursor-not-allowed opacity-50"
|
|
674
689
|
)}
|
|
675
690
|
disabled={option.disabled}
|
|
676
691
|
>
|
|
@@ -681,9 +696,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
681
696
|
/>
|
|
682
697
|
)}
|
|
683
698
|
<span className="grow">{option.label}</span>
|
|
684
|
-
{isSelected ?
|
|
685
|
-
<CheckIcon className="text-muted-foreground size-3.5" />
|
|
686
|
-
) : null}
|
|
699
|
+
{isSelected ? <CheckIcon className="text-muted-foreground size-3.5" /> : null}
|
|
687
700
|
</CommandItem>
|
|
688
701
|
);
|
|
689
702
|
})}
|
|
@@ -695,7 +708,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
695
708
|
<WandSparkles
|
|
696
709
|
className={cn(
|
|
697
710
|
"text-foreground bg-background my-2 h-3 w-3 cursor-pointer",
|
|
698
|
-
isAnimating ? "" : "text-muted-foreground"
|
|
711
|
+
isAnimating ? "" : "text-muted-foreground"
|
|
699
712
|
)}
|
|
700
713
|
onClick={() => setIsAnimating(!isAnimating)}
|
|
701
714
|
/>
|
|
@@ -707,7 +720,7 @@ const ComboboxComponent = <T = string,>(
|
|
|
707
720
|
|
|
708
721
|
// Create the forwardRef wrapper with proper generic typing
|
|
709
722
|
const ComboboxForwardRef = React.forwardRef(ComboboxComponent) as <T = string>(
|
|
710
|
-
props: ComboboxProps<T> & { ref?: React.Ref<ComboboxRef> }
|
|
723
|
+
props: ComboboxProps<T> & { ref?: React.Ref<ComboboxRef> }
|
|
711
724
|
) => React.ReactElement;
|
|
712
725
|
|
|
713
726
|
// Set displayName on a mutable object
|
|
@@ -6,27 +6,19 @@ import { XIcon } from "lucide-react";
|
|
|
6
6
|
|
|
7
7
|
import { cn } from "@/lib/utils";
|
|
8
8
|
|
|
9
|
-
function Dialog({
|
|
10
|
-
...props
|
|
11
|
-
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
9
|
+
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
12
10
|
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
function DialogTrigger({
|
|
16
|
-
...props
|
|
17
|
-
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
13
|
+
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
18
14
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
function DialogPortal({
|
|
22
|
-
...props
|
|
23
|
-
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
17
|
+
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
24
18
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
25
19
|
}
|
|
26
20
|
|
|
27
|
-
function DialogClose({
|
|
28
|
-
...props
|
|
29
|
-
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
21
|
+
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
30
22
|
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
31
23
|
}
|
|
32
24
|
|
|
@@ -38,8 +30,8 @@ function DialogOverlay({
|
|
|
38
30
|
<DialogPrimitive.Overlay
|
|
39
31
|
data-slot="dialog-overlay"
|
|
40
32
|
className={cn(
|
|
41
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
42
|
-
className
|
|
33
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/50",
|
|
34
|
+
className
|
|
43
35
|
)}
|
|
44
36
|
{...props}
|
|
45
37
|
/>
|
|
@@ -61,7 +53,7 @@ function DialogContent({
|
|
|
61
53
|
data-slot="dialog-content"
|
|
62
54
|
className={cn(
|
|
63
55
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 border-gradient-soft fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
64
|
-
className
|
|
56
|
+
className
|
|
65
57
|
)}
|
|
66
58
|
{...props}
|
|
67
59
|
>
|
|
@@ -94,19 +86,13 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
94
86
|
return (
|
|
95
87
|
<div
|
|
96
88
|
data-slot="dialog-footer"
|
|
97
|
-
className={cn(
|
|
98
|
-
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
99
|
-
className,
|
|
100
|
-
)}
|
|
89
|
+
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
|
101
90
|
{...props}
|
|
102
91
|
/>
|
|
103
92
|
);
|
|
104
93
|
}
|
|
105
94
|
|
|
106
|
-
function DialogTitle({
|
|
107
|
-
className,
|
|
108
|
-
...props
|
|
109
|
-
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
95
|
+
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
110
96
|
return (
|
|
111
97
|
<DialogPrimitive.Title
|
|
112
98
|
data-slot="dialog-title"
|
|
@@ -43,10 +43,12 @@ function DropdownMenuTrigger({
|
|
|
43
43
|
children,
|
|
44
44
|
size = "default",
|
|
45
45
|
src,
|
|
46
|
+
compact = false,
|
|
46
47
|
...props
|
|
47
48
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger> & {
|
|
48
49
|
src?: string;
|
|
49
50
|
size?: "default" | "sm" | "lg";
|
|
51
|
+
compact?: boolean;
|
|
50
52
|
}) {
|
|
51
53
|
return (
|
|
52
54
|
<DropdownMenuPrimitive.Trigger
|
|
@@ -76,7 +78,7 @@ function DropdownMenuTrigger({
|
|
|
76
78
|
)}
|
|
77
79
|
/>
|
|
78
80
|
) : undefined}
|
|
79
|
-
<div className={cn("grow py-2 pr-2.5", src ? "pl-2.5" : "pl-4")}>
|
|
81
|
+
<div className={cn("grow py-2 pr-2.5", src ? "pl-2.5" : compact ? "pl-2.5" : "pl-4")}>
|
|
80
82
|
{children}
|
|
81
83
|
</div>
|
|
82
84
|
<ChevronDownIcon className="mr-2.5 size-4" />
|