@optilogic/core 1.2.1 → 1.3.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/dist/index.cjs +584 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -3
- package/dist/index.d.ts +128 -3
- package/dist/index.js +580 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/combobox.tsx +340 -0
- package/src/components/file-view/components/HtmlRenderer.tsx +2 -0
- package/src/components/multi-select.tsx +375 -0
- package/src/components/select.tsx +18 -2
- package/src/components/tabs.tsx +92 -28
- package/src/index.ts +16 -0
package/dist/index.js
CHANGED
|
@@ -351,17 +351,26 @@ var SelectItem = React20.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
351
351
|
{
|
|
352
352
|
ref,
|
|
353
353
|
className: cn(
|
|
354
|
-
"relative flex w-full cursor-default select-none items-
|
|
354
|
+
"relative flex w-full cursor-default select-none items-start rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
355
355
|
className
|
|
356
356
|
),
|
|
357
357
|
...props,
|
|
358
358
|
children: [
|
|
359
|
-
/* @__PURE__ */ jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }) }),
|
|
359
|
+
/* @__PURE__ */ jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center mt-0.5", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }) }),
|
|
360
360
|
/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
|
|
361
361
|
]
|
|
362
362
|
}
|
|
363
363
|
));
|
|
364
364
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
365
|
+
var SelectItemDescription = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
366
|
+
"span",
|
|
367
|
+
{
|
|
368
|
+
ref,
|
|
369
|
+
className: cn("text-xs text-muted-foreground", className),
|
|
370
|
+
...props
|
|
371
|
+
}
|
|
372
|
+
));
|
|
373
|
+
SelectItemDescription.displayName = "SelectItemDescription";
|
|
365
374
|
var SelectSeparator = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
366
375
|
SelectPrimitive.Separator,
|
|
367
376
|
{
|
|
@@ -372,41 +381,85 @@ var SelectSeparator = React20.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
372
381
|
));
|
|
373
382
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
374
383
|
var Tabs = TabsPrimitive.Root;
|
|
375
|
-
var
|
|
384
|
+
var tabsListVariants = cva(
|
|
385
|
+
"inline-flex h-10 items-center justify-start bg-transparent",
|
|
386
|
+
{
|
|
387
|
+
variants: {
|
|
388
|
+
variant: {
|
|
389
|
+
default: "border-b border-border",
|
|
390
|
+
pill: "gap-1 rounded-lg bg-muted p-1",
|
|
391
|
+
unstyled: ""
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
defaultVariants: {
|
|
395
|
+
variant: "default"
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
var tabsTriggerVariants = cva(
|
|
400
|
+
[
|
|
401
|
+
"inline-flex items-center justify-center whitespace-nowrap",
|
|
402
|
+
"px-4 py-2.5 text-sm font-medium",
|
|
403
|
+
"transition-colors",
|
|
404
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
405
|
+
"disabled:pointer-events-none disabled:opacity-50"
|
|
406
|
+
],
|
|
407
|
+
{
|
|
408
|
+
variants: {
|
|
409
|
+
variant: {
|
|
410
|
+
default: [
|
|
411
|
+
"-mb-px",
|
|
412
|
+
"border-transparent text-muted-foreground",
|
|
413
|
+
"hover:text-foreground hover:border-muted-foreground/50",
|
|
414
|
+
"data-[state=active]:border-foreground data-[state=active]:text-foreground"
|
|
415
|
+
],
|
|
416
|
+
pill: [
|
|
417
|
+
"rounded-md",
|
|
418
|
+
"text-muted-foreground",
|
|
419
|
+
"hover:text-foreground",
|
|
420
|
+
"data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"
|
|
421
|
+
],
|
|
422
|
+
unstyled: [
|
|
423
|
+
"text-muted-foreground",
|
|
424
|
+
"hover:text-foreground",
|
|
425
|
+
"data-[state=active]:text-foreground"
|
|
426
|
+
]
|
|
427
|
+
},
|
|
428
|
+
indicatorSize: {
|
|
429
|
+
sm: "border-b",
|
|
430
|
+
default: "border-b-2",
|
|
431
|
+
lg: "border-b-[3px]"
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
compoundVariants: [
|
|
435
|
+
{ variant: "pill", indicatorSize: "sm", className: "border-b-0" },
|
|
436
|
+
{ variant: "pill", indicatorSize: "default", className: "border-b-0" },
|
|
437
|
+
{ variant: "pill", indicatorSize: "lg", className: "border-b-0" },
|
|
438
|
+
{ variant: "unstyled", indicatorSize: "sm", className: "border-b-0" },
|
|
439
|
+
{ variant: "unstyled", indicatorSize: "default", className: "border-b-0" },
|
|
440
|
+
{ variant: "unstyled", indicatorSize: "lg", className: "border-b-0" }
|
|
441
|
+
],
|
|
442
|
+
defaultVariants: {
|
|
443
|
+
variant: "default",
|
|
444
|
+
indicatorSize: "default"
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
var TabsList = React20.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
376
449
|
TabsPrimitive.List,
|
|
377
450
|
{
|
|
378
451
|
ref,
|
|
379
|
-
className: cn(
|
|
380
|
-
"inline-flex h-10 items-center justify-start",
|
|
381
|
-
"border-b border-border",
|
|
382
|
-
"bg-transparent",
|
|
383
|
-
className
|
|
384
|
-
),
|
|
452
|
+
className: cn(tabsListVariants({ variant }), className),
|
|
385
453
|
...props
|
|
386
454
|
}
|
|
387
455
|
));
|
|
388
456
|
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
389
|
-
var TabsTrigger = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
457
|
+
var TabsTrigger = React20.forwardRef(({ className, variant, indicatorSize, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
390
458
|
TabsPrimitive.Trigger,
|
|
391
459
|
{
|
|
392
460
|
ref,
|
|
393
461
|
className: cn(
|
|
394
|
-
|
|
395
|
-
"inline-flex items-center justify-center whitespace-nowrap",
|
|
396
|
-
"px-4 py-2.5 text-sm font-medium",
|
|
397
|
-
"transition-colors",
|
|
398
|
-
// Border-bottom indicator style
|
|
399
|
-
"border-b-2 -mb-px",
|
|
400
|
-
// Default state
|
|
401
|
-
"border-transparent text-muted-foreground",
|
|
402
|
-
// Hover state
|
|
403
|
-
"hover:text-foreground hover:border-muted-foreground/50",
|
|
404
|
-
// Active/selected state
|
|
405
|
-
"data-[state=active]:border-foreground data-[state=active]:text-foreground",
|
|
406
|
-
// Focus styles
|
|
407
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
408
|
-
// Disabled styles
|
|
409
|
-
"disabled:pointer-events-none disabled:opacity-50",
|
|
462
|
+
tabsTriggerVariants({ variant, indicatorSize }),
|
|
410
463
|
className
|
|
411
464
|
),
|
|
412
465
|
...props
|
|
@@ -419,7 +472,6 @@ var TabsContent = React20.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
419
472
|
ref,
|
|
420
473
|
className: cn(
|
|
421
474
|
"mt-2",
|
|
422
|
-
// Focus styles
|
|
423
475
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
424
476
|
className
|
|
425
477
|
),
|
|
@@ -5613,6 +5665,504 @@ function Autocomplete({
|
|
|
5613
5665
|
)
|
|
5614
5666
|
] });
|
|
5615
5667
|
}
|
|
5668
|
+
function MultiSelect({
|
|
5669
|
+
options,
|
|
5670
|
+
value,
|
|
5671
|
+
onChange,
|
|
5672
|
+
placeholder = "Select items...",
|
|
5673
|
+
searchPlaceholder = "Search...",
|
|
5674
|
+
emptyText = "No options found.",
|
|
5675
|
+
disabled = false,
|
|
5676
|
+
className,
|
|
5677
|
+
clearable = true,
|
|
5678
|
+
maxDisplayItems = 3,
|
|
5679
|
+
showSelectAll = false,
|
|
5680
|
+
selectAllLabel = "Select all"
|
|
5681
|
+
}) {
|
|
5682
|
+
const [open, setOpen] = React20.useState(false);
|
|
5683
|
+
const [search, setSearch] = React20.useState("");
|
|
5684
|
+
const inputRef = React20.useRef(null);
|
|
5685
|
+
const safeOptions = options ?? [];
|
|
5686
|
+
const safeValue = value ?? [];
|
|
5687
|
+
const selectedSet = React20.useMemo(() => new Set(safeValue), [safeValue]);
|
|
5688
|
+
const filteredOptions = React20.useMemo(() => {
|
|
5689
|
+
if (!search.trim()) return safeOptions;
|
|
5690
|
+
const searchLower = search.toLowerCase();
|
|
5691
|
+
return safeOptions.filter(
|
|
5692
|
+
(opt) => opt.label.toLowerCase().includes(searchLower) || opt.description?.toLowerCase().includes(searchLower)
|
|
5693
|
+
);
|
|
5694
|
+
}, [safeOptions, search]);
|
|
5695
|
+
const groupedOptions = React20.useMemo(() => {
|
|
5696
|
+
const groups = {};
|
|
5697
|
+
const ungrouped = [];
|
|
5698
|
+
filteredOptions.forEach((opt) => {
|
|
5699
|
+
if (opt.group) {
|
|
5700
|
+
if (!groups[opt.group]) groups[opt.group] = [];
|
|
5701
|
+
groups[opt.group].push(opt);
|
|
5702
|
+
} else {
|
|
5703
|
+
ungrouped.push(opt);
|
|
5704
|
+
}
|
|
5705
|
+
});
|
|
5706
|
+
return { groups, ungrouped };
|
|
5707
|
+
}, [filteredOptions]);
|
|
5708
|
+
const hasGroups = Object.keys(groupedOptions.groups).length > 0;
|
|
5709
|
+
const selectableFiltered = React20.useMemo(
|
|
5710
|
+
() => filteredOptions.filter((opt) => !opt.disabled),
|
|
5711
|
+
[filteredOptions]
|
|
5712
|
+
);
|
|
5713
|
+
const allFilteredSelected = React20.useMemo(
|
|
5714
|
+
() => selectableFiltered.length > 0 && selectableFiltered.every((opt) => selectedSet.has(opt.value)),
|
|
5715
|
+
[selectableFiltered, selectedSet]
|
|
5716
|
+
);
|
|
5717
|
+
const someFilteredSelected = React20.useMemo(
|
|
5718
|
+
() => !allFilteredSelected && selectableFiltered.some((opt) => selectedSet.has(opt.value)),
|
|
5719
|
+
[selectableFiltered, selectedSet, allFilteredSelected]
|
|
5720
|
+
);
|
|
5721
|
+
const handleToggle = React20.useCallback(
|
|
5722
|
+
(optionValue) => {
|
|
5723
|
+
const next = selectedSet.has(optionValue) ? safeValue.filter((v) => v !== optionValue) : [...safeValue, optionValue];
|
|
5724
|
+
onChange?.(next);
|
|
5725
|
+
},
|
|
5726
|
+
[onChange, safeValue, selectedSet]
|
|
5727
|
+
);
|
|
5728
|
+
const handleRemove = React20.useCallback(
|
|
5729
|
+
(optionValue, e) => {
|
|
5730
|
+
e.stopPropagation();
|
|
5731
|
+
onChange?.(safeValue.filter((v) => v !== optionValue));
|
|
5732
|
+
},
|
|
5733
|
+
[onChange, safeValue]
|
|
5734
|
+
);
|
|
5735
|
+
const handleClearAll = React20.useCallback(
|
|
5736
|
+
(e) => {
|
|
5737
|
+
e.stopPropagation();
|
|
5738
|
+
onChange?.([]);
|
|
5739
|
+
},
|
|
5740
|
+
[onChange]
|
|
5741
|
+
);
|
|
5742
|
+
const handleSelectAll = React20.useCallback(() => {
|
|
5743
|
+
if (allFilteredSelected) {
|
|
5744
|
+
const filteredValues = new Set(selectableFiltered.map((o) => o.value));
|
|
5745
|
+
onChange?.(safeValue.filter((v) => !filteredValues.has(v)));
|
|
5746
|
+
} else {
|
|
5747
|
+
const existing = new Set(safeValue);
|
|
5748
|
+
const next = [...safeValue];
|
|
5749
|
+
for (const opt of selectableFiltered) {
|
|
5750
|
+
if (!existing.has(opt.value)) {
|
|
5751
|
+
next.push(opt.value);
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
onChange?.(next);
|
|
5755
|
+
}
|
|
5756
|
+
}, [allFilteredSelected, selectableFiltered, safeValue, onChange]);
|
|
5757
|
+
React20.useEffect(() => {
|
|
5758
|
+
if (open) {
|
|
5759
|
+
const timeout = setTimeout(() => inputRef.current?.focus(), 0);
|
|
5760
|
+
return () => clearTimeout(timeout);
|
|
5761
|
+
} else {
|
|
5762
|
+
setSearch("");
|
|
5763
|
+
}
|
|
5764
|
+
}, [open]);
|
|
5765
|
+
const handleKeyDown = React20.useCallback((e) => {
|
|
5766
|
+
if (e.key === "Escape") setOpen(false);
|
|
5767
|
+
}, []);
|
|
5768
|
+
const selectedLabels = React20.useMemo(
|
|
5769
|
+
() => safeValue.map((v) => safeOptions.find((o) => o.value === v)?.label ?? v).slice(0, maxDisplayItems),
|
|
5770
|
+
[safeValue, safeOptions, maxDisplayItems]
|
|
5771
|
+
);
|
|
5772
|
+
const overflow = safeValue.length - maxDisplayItems;
|
|
5773
|
+
const isSearching = search.trim().length > 0;
|
|
5774
|
+
const renderOption = (option) => /* @__PURE__ */ jsxs(
|
|
5775
|
+
"button",
|
|
5776
|
+
{
|
|
5777
|
+
type: "button",
|
|
5778
|
+
disabled: option.disabled,
|
|
5779
|
+
onClick: () => handleToggle(option.value),
|
|
5780
|
+
className: cn(
|
|
5781
|
+
"relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
5782
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
5783
|
+
option.disabled && "pointer-events-none opacity-50"
|
|
5784
|
+
),
|
|
5785
|
+
children: [
|
|
5786
|
+
/* @__PURE__ */ jsx(
|
|
5787
|
+
Checkbox,
|
|
5788
|
+
{
|
|
5789
|
+
checked: selectedSet.has(option.value),
|
|
5790
|
+
tabIndex: -1,
|
|
5791
|
+
className: "mt-0.5 pointer-events-none"
|
|
5792
|
+
}
|
|
5793
|
+
),
|
|
5794
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
5795
|
+
/* @__PURE__ */ jsx("div", { className: "truncate", children: option.label }),
|
|
5796
|
+
option.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: option.description })
|
|
5797
|
+
] })
|
|
5798
|
+
]
|
|
5799
|
+
},
|
|
5800
|
+
option.value
|
|
5801
|
+
);
|
|
5802
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
5803
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(
|
|
5804
|
+
"button",
|
|
5805
|
+
{
|
|
5806
|
+
type: "button",
|
|
5807
|
+
role: "combobox",
|
|
5808
|
+
"aria-expanded": open,
|
|
5809
|
+
"aria-haspopup": "listbox",
|
|
5810
|
+
disabled,
|
|
5811
|
+
className: cn(
|
|
5812
|
+
"flex min-h-9 w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-1.5 text-sm shadow-sm ring-offset-background",
|
|
5813
|
+
"hover:border-input-hover",
|
|
5814
|
+
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
5815
|
+
"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-input",
|
|
5816
|
+
className
|
|
5817
|
+
),
|
|
5818
|
+
children: [
|
|
5819
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-wrap gap-1 items-center min-w-0", children: safeValue.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5820
|
+
selectedLabels.map((label, i) => /* @__PURE__ */ jsxs(
|
|
5821
|
+
"span",
|
|
5822
|
+
{
|
|
5823
|
+
className: "inline-flex items-center gap-0.5 rounded-sm bg-accent px-1.5 py-0.5 text-xs font-medium text-accent-foreground",
|
|
5824
|
+
children: [
|
|
5825
|
+
/* @__PURE__ */ jsx("span", { className: "truncate max-w-[100px]", children: label }),
|
|
5826
|
+
/* @__PURE__ */ jsx(
|
|
5827
|
+
"span",
|
|
5828
|
+
{
|
|
5829
|
+
role: "button",
|
|
5830
|
+
tabIndex: -1,
|
|
5831
|
+
onClick: (e) => handleRemove(safeValue[i], e),
|
|
5832
|
+
className: "rounded-sm hover:bg-foreground/10 p-0.5",
|
|
5833
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
5834
|
+
}
|
|
5835
|
+
)
|
|
5836
|
+
]
|
|
5837
|
+
},
|
|
5838
|
+
safeValue[i]
|
|
5839
|
+
)),
|
|
5840
|
+
overflow > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
5841
|
+
"+",
|
|
5842
|
+
overflow
|
|
5843
|
+
] })
|
|
5844
|
+
] }) }),
|
|
5845
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [
|
|
5846
|
+
clearable && safeValue.length > 0 && /* @__PURE__ */ jsx(
|
|
5847
|
+
"span",
|
|
5848
|
+
{
|
|
5849
|
+
role: "button",
|
|
5850
|
+
tabIndex: -1,
|
|
5851
|
+
onClick: handleClearAll,
|
|
5852
|
+
className: "rounded-sm hover:bg-muted p-0.5",
|
|
5853
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
5854
|
+
}
|
|
5855
|
+
),
|
|
5856
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
5857
|
+
] })
|
|
5858
|
+
]
|
|
5859
|
+
}
|
|
5860
|
+
) }),
|
|
5861
|
+
/* @__PURE__ */ jsxs(
|
|
5862
|
+
PopoverContent,
|
|
5863
|
+
{
|
|
5864
|
+
className: "w-[--radix-popover-trigger-width] p-0",
|
|
5865
|
+
align: "start",
|
|
5866
|
+
sideOffset: 4,
|
|
5867
|
+
onKeyDown: handleKeyDown,
|
|
5868
|
+
children: [
|
|
5869
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center border-b border-border px-3", children: [
|
|
5870
|
+
/* @__PURE__ */ jsx(
|
|
5871
|
+
"input",
|
|
5872
|
+
{
|
|
5873
|
+
ref: inputRef,
|
|
5874
|
+
type: "text",
|
|
5875
|
+
value: search,
|
|
5876
|
+
onChange: (e) => setSearch(e.target.value),
|
|
5877
|
+
placeholder: searchPlaceholder,
|
|
5878
|
+
className: "flex h-9 w-full bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground"
|
|
5879
|
+
}
|
|
5880
|
+
),
|
|
5881
|
+
search && /* @__PURE__ */ jsx(
|
|
5882
|
+
"button",
|
|
5883
|
+
{
|
|
5884
|
+
type: "button",
|
|
5885
|
+
onClick: () => setSearch(""),
|
|
5886
|
+
className: "p-1 hover:bg-muted rounded-sm",
|
|
5887
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
5888
|
+
}
|
|
5889
|
+
)
|
|
5890
|
+
] }),
|
|
5891
|
+
/* @__PURE__ */ jsxs("div", { className: "max-h-[300px] overflow-y-auto p-1", children: [
|
|
5892
|
+
showSelectAll && selectableFiltered.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5893
|
+
/* @__PURE__ */ jsxs(
|
|
5894
|
+
"button",
|
|
5895
|
+
{
|
|
5896
|
+
type: "button",
|
|
5897
|
+
onClick: handleSelectAll,
|
|
5898
|
+
className: cn(
|
|
5899
|
+
"relative flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
5900
|
+
"hover:bg-accent hover:text-accent-foreground"
|
|
5901
|
+
),
|
|
5902
|
+
children: [
|
|
5903
|
+
/* @__PURE__ */ jsx(
|
|
5904
|
+
Checkbox,
|
|
5905
|
+
{
|
|
5906
|
+
checked: allFilteredSelected ? true : someFilteredSelected ? "indeterminate" : false,
|
|
5907
|
+
tabIndex: -1,
|
|
5908
|
+
className: "pointer-events-none"
|
|
5909
|
+
}
|
|
5910
|
+
),
|
|
5911
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: isSearching ? `${selectAllLabel} (filtered)` : selectAllLabel })
|
|
5912
|
+
]
|
|
5913
|
+
}
|
|
5914
|
+
),
|
|
5915
|
+
/* @__PURE__ */ jsx("div", { className: "-mx-1 my-1 h-px bg-border" })
|
|
5916
|
+
] }),
|
|
5917
|
+
filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: emptyText }) : hasGroups ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5918
|
+
groupedOptions.ungrouped.map(renderOption),
|
|
5919
|
+
Object.entries(groupedOptions.groups).map(([group, opts]) => /* @__PURE__ */ jsxs("div", { children: [
|
|
5920
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground", children: group }),
|
|
5921
|
+
opts.map(renderOption)
|
|
5922
|
+
] }, group))
|
|
5923
|
+
] }) : filteredOptions.map(renderOption)
|
|
5924
|
+
] })
|
|
5925
|
+
]
|
|
5926
|
+
}
|
|
5927
|
+
)
|
|
5928
|
+
] });
|
|
5929
|
+
}
|
|
5930
|
+
MultiSelect.displayName = "MultiSelect";
|
|
5931
|
+
function Combobox({
|
|
5932
|
+
options,
|
|
5933
|
+
value,
|
|
5934
|
+
onChange,
|
|
5935
|
+
onInputChange,
|
|
5936
|
+
placeholder = "Type or select...",
|
|
5937
|
+
emptyText = "No options found.",
|
|
5938
|
+
disabled = false,
|
|
5939
|
+
className,
|
|
5940
|
+
clearable = false,
|
|
5941
|
+
allowCustomValue = true
|
|
5942
|
+
}) {
|
|
5943
|
+
const [open, setOpen] = React20.useState(false);
|
|
5944
|
+
const [inputValue, setInputValue] = React20.useState("");
|
|
5945
|
+
const inputRef = React20.useRef(null);
|
|
5946
|
+
const wrapperRef = React20.useRef(null);
|
|
5947
|
+
const selectedOption = React20.useMemo(
|
|
5948
|
+
() => options.find((opt) => opt.value === value),
|
|
5949
|
+
[options, value]
|
|
5950
|
+
);
|
|
5951
|
+
React20.useEffect(() => {
|
|
5952
|
+
if (!open) {
|
|
5953
|
+
setInputValue(selectedOption?.label ?? value ?? "");
|
|
5954
|
+
}
|
|
5955
|
+
}, [value, selectedOption, open]);
|
|
5956
|
+
const filteredOptions = React20.useMemo(() => {
|
|
5957
|
+
if (!inputValue.trim()) return options;
|
|
5958
|
+
const searchLower = inputValue.toLowerCase();
|
|
5959
|
+
return options.filter(
|
|
5960
|
+
(opt) => opt.label.toLowerCase().includes(searchLower) || opt.description?.toLowerCase().includes(searchLower)
|
|
5961
|
+
);
|
|
5962
|
+
}, [options, inputValue]);
|
|
5963
|
+
const groupedOptions = React20.useMemo(() => {
|
|
5964
|
+
const groups = {};
|
|
5965
|
+
const ungrouped = [];
|
|
5966
|
+
filteredOptions.forEach((opt) => {
|
|
5967
|
+
if (opt.group) {
|
|
5968
|
+
if (!groups[opt.group]) groups[opt.group] = [];
|
|
5969
|
+
groups[opt.group].push(opt);
|
|
5970
|
+
} else {
|
|
5971
|
+
ungrouped.push(opt);
|
|
5972
|
+
}
|
|
5973
|
+
});
|
|
5974
|
+
return { groups, ungrouped };
|
|
5975
|
+
}, [filteredOptions]);
|
|
5976
|
+
const hasGroups = Object.keys(groupedOptions.groups).length > 0;
|
|
5977
|
+
const handleInputChange = React20.useCallback(
|
|
5978
|
+
(e) => {
|
|
5979
|
+
const newValue = e.target.value;
|
|
5980
|
+
setInputValue(newValue);
|
|
5981
|
+
onInputChange?.(newValue);
|
|
5982
|
+
if (!open) setOpen(true);
|
|
5983
|
+
},
|
|
5984
|
+
[onInputChange, open]
|
|
5985
|
+
);
|
|
5986
|
+
const handleSelect = React20.useCallback(
|
|
5987
|
+
(optionValue) => {
|
|
5988
|
+
const option = options.find((o) => o.value === optionValue);
|
|
5989
|
+
onChange?.(optionValue);
|
|
5990
|
+
setInputValue(option?.label ?? optionValue);
|
|
5991
|
+
setOpen(false);
|
|
5992
|
+
},
|
|
5993
|
+
[onChange, options]
|
|
5994
|
+
);
|
|
5995
|
+
const handleClear = React20.useCallback(
|
|
5996
|
+
(e) => {
|
|
5997
|
+
e.stopPropagation();
|
|
5998
|
+
e.preventDefault();
|
|
5999
|
+
onChange?.(void 0);
|
|
6000
|
+
setInputValue("");
|
|
6001
|
+
inputRef.current?.focus();
|
|
6002
|
+
},
|
|
6003
|
+
[onChange]
|
|
6004
|
+
);
|
|
6005
|
+
const handleFocus = React20.useCallback(() => {
|
|
6006
|
+
setOpen(true);
|
|
6007
|
+
inputRef.current?.select();
|
|
6008
|
+
}, []);
|
|
6009
|
+
const handleBlur = React20.useCallback(() => {
|
|
6010
|
+
setTimeout(() => {
|
|
6011
|
+
if (!wrapperRef.current?.contains(document.activeElement)) {
|
|
6012
|
+
setOpen(false);
|
|
6013
|
+
}
|
|
6014
|
+
if (allowCustomValue && inputValue.trim()) {
|
|
6015
|
+
const matchingOption = options.find(
|
|
6016
|
+
(opt) => opt.label.toLowerCase() === inputValue.toLowerCase()
|
|
6017
|
+
);
|
|
6018
|
+
if (matchingOption) {
|
|
6019
|
+
onChange?.(matchingOption.value);
|
|
6020
|
+
setInputValue(matchingOption.label);
|
|
6021
|
+
} else {
|
|
6022
|
+
onChange?.(inputValue.trim());
|
|
6023
|
+
}
|
|
6024
|
+
} else if (!allowCustomValue) {
|
|
6025
|
+
setInputValue(selectedOption?.label ?? "");
|
|
6026
|
+
}
|
|
6027
|
+
}, 200);
|
|
6028
|
+
}, [allowCustomValue, inputValue, options, onChange, selectedOption]);
|
|
6029
|
+
const handleKeyDown = React20.useCallback(
|
|
6030
|
+
(e) => {
|
|
6031
|
+
if (e.key === "Escape") {
|
|
6032
|
+
setOpen(false);
|
|
6033
|
+
setInputValue(selectedOption?.label ?? value ?? "");
|
|
6034
|
+
inputRef.current?.blur();
|
|
6035
|
+
} else if (e.key === "Enter" && open) {
|
|
6036
|
+
e.preventDefault();
|
|
6037
|
+
if (filteredOptions.length === 1) {
|
|
6038
|
+
handleSelect(filteredOptions[0].value);
|
|
6039
|
+
} else if (allowCustomValue && inputValue.trim()) {
|
|
6040
|
+
const exactMatch = filteredOptions.find(
|
|
6041
|
+
(opt) => opt.label.toLowerCase() === inputValue.toLowerCase()
|
|
6042
|
+
);
|
|
6043
|
+
if (exactMatch) {
|
|
6044
|
+
handleSelect(exactMatch.value);
|
|
6045
|
+
} else {
|
|
6046
|
+
onChange?.(inputValue.trim());
|
|
6047
|
+
setOpen(false);
|
|
6048
|
+
}
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
6051
|
+
},
|
|
6052
|
+
[
|
|
6053
|
+
open,
|
|
6054
|
+
filteredOptions,
|
|
6055
|
+
handleSelect,
|
|
6056
|
+
allowCustomValue,
|
|
6057
|
+
inputValue,
|
|
6058
|
+
onChange,
|
|
6059
|
+
selectedOption,
|
|
6060
|
+
value
|
|
6061
|
+
]
|
|
6062
|
+
);
|
|
6063
|
+
const renderOption = (option) => /* @__PURE__ */ jsxs(
|
|
6064
|
+
"button",
|
|
6065
|
+
{
|
|
6066
|
+
type: "button",
|
|
6067
|
+
disabled: option.disabled,
|
|
6068
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
6069
|
+
onClick: () => handleSelect(option.value),
|
|
6070
|
+
className: cn(
|
|
6071
|
+
"relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
6072
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
6073
|
+
"focus:bg-accent focus:text-accent-foreground",
|
|
6074
|
+
option.disabled && "pointer-events-none opacity-50",
|
|
6075
|
+
value === option.value && "bg-accent/50"
|
|
6076
|
+
),
|
|
6077
|
+
children: [
|
|
6078
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 items-center justify-center flex-shrink-0 mt-0.5", children: value === option.value && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }),
|
|
6079
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
6080
|
+
/* @__PURE__ */ jsx("div", { className: "truncate", children: option.label }),
|
|
6081
|
+
option.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: option.description })
|
|
6082
|
+
] })
|
|
6083
|
+
]
|
|
6084
|
+
},
|
|
6085
|
+
option.value
|
|
6086
|
+
);
|
|
6087
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
6088
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
6089
|
+
"div",
|
|
6090
|
+
{
|
|
6091
|
+
ref: wrapperRef,
|
|
6092
|
+
className: cn(
|
|
6093
|
+
"flex h-9 w-full items-center gap-2 rounded-md border border-input bg-transparent px-3 text-sm shadow-sm ring-offset-background",
|
|
6094
|
+
"hover:border-input-hover",
|
|
6095
|
+
"focus-within:outline-none focus-within:ring-1 focus-within:ring-ring",
|
|
6096
|
+
disabled && "cursor-not-allowed opacity-50 hover:border-input",
|
|
6097
|
+
className
|
|
6098
|
+
),
|
|
6099
|
+
children: [
|
|
6100
|
+
/* @__PURE__ */ jsx(
|
|
6101
|
+
"input",
|
|
6102
|
+
{
|
|
6103
|
+
ref: inputRef,
|
|
6104
|
+
type: "text",
|
|
6105
|
+
value: inputValue,
|
|
6106
|
+
onChange: handleInputChange,
|
|
6107
|
+
onFocus: handleFocus,
|
|
6108
|
+
onBlur: handleBlur,
|
|
6109
|
+
onKeyDown: handleKeyDown,
|
|
6110
|
+
placeholder,
|
|
6111
|
+
disabled,
|
|
6112
|
+
className: "flex-1 min-w-0 bg-transparent py-2 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed",
|
|
6113
|
+
role: "combobox",
|
|
6114
|
+
"aria-expanded": open,
|
|
6115
|
+
"aria-haspopup": "listbox",
|
|
6116
|
+
"aria-autocomplete": "list"
|
|
6117
|
+
}
|
|
6118
|
+
),
|
|
6119
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [
|
|
6120
|
+
clearable && value && /* @__PURE__ */ jsx(
|
|
6121
|
+
"span",
|
|
6122
|
+
{
|
|
6123
|
+
role: "button",
|
|
6124
|
+
tabIndex: -1,
|
|
6125
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
6126
|
+
onClick: handleClear,
|
|
6127
|
+
className: "rounded-sm hover:bg-muted p-0.5",
|
|
6128
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
6129
|
+
}
|
|
6130
|
+
),
|
|
6131
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
6132
|
+
] })
|
|
6133
|
+
]
|
|
6134
|
+
}
|
|
6135
|
+
) }),
|
|
6136
|
+
/* @__PURE__ */ jsx(
|
|
6137
|
+
PopoverContent,
|
|
6138
|
+
{
|
|
6139
|
+
className: "p-0",
|
|
6140
|
+
style: { width: wrapperRef.current?.offsetWidth },
|
|
6141
|
+
align: "start",
|
|
6142
|
+
sideOffset: 4,
|
|
6143
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
6144
|
+
onFocusOutside: (e) => {
|
|
6145
|
+
if (wrapperRef.current?.contains(e.target)) {
|
|
6146
|
+
e.preventDefault();
|
|
6147
|
+
}
|
|
6148
|
+
},
|
|
6149
|
+
onInteractOutside: (e) => {
|
|
6150
|
+
if (wrapperRef.current?.contains(e.target)) {
|
|
6151
|
+
e.preventDefault();
|
|
6152
|
+
}
|
|
6153
|
+
},
|
|
6154
|
+
children: /* @__PURE__ */ jsx("div", { className: "max-h-[300px] overflow-y-auto p-1", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: emptyText }) : hasGroups ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6155
|
+
groupedOptions.ungrouped.map(renderOption),
|
|
6156
|
+
Object.entries(groupedOptions.groups).map(([group, opts]) => /* @__PURE__ */ jsxs("div", { children: [
|
|
6157
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground", children: group }),
|
|
6158
|
+
opts.map(renderOption)
|
|
6159
|
+
] }, group))
|
|
6160
|
+
] }) : filteredOptions.map(renderOption) })
|
|
6161
|
+
}
|
|
6162
|
+
)
|
|
6163
|
+
] });
|
|
6164
|
+
}
|
|
6165
|
+
Combobox.displayName = "Combobox";
|
|
5616
6166
|
var iconButtonVariants = cva(
|
|
5617
6167
|
// Base styles
|
|
5618
6168
|
[
|
|
@@ -7462,6 +8012,8 @@ var PERMISSIONS_POLICY = [
|
|
|
7462
8012
|
"geolocation=()",
|
|
7463
8013
|
"payment=()",
|
|
7464
8014
|
"usb=()",
|
|
8015
|
+
"clipboard-read=()",
|
|
8016
|
+
"clipboard-write=()",
|
|
7465
8017
|
"display-capture=()",
|
|
7466
8018
|
"fullscreen=()",
|
|
7467
8019
|
"autoplay=()",
|
|
@@ -7887,6 +8439,6 @@ var DataStarIcon = forwardRef(
|
|
|
7887
8439
|
);
|
|
7888
8440
|
DataStarIcon.displayName = "DataStarIcon";
|
|
7889
8441
|
|
|
7890
|
-
export { ALL_THEMES, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Autocomplete, Badge, Board, BoardContent, BoardHeader, Button, Calendar, Card, CardActions, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardImage, CardList, CardTitle, CellEditor, Checkbox, Chip, CodeRenderer, ConfirmationModal, ContextMenu, CopyButton, CosmicFrogIcon, CsvRenderer, DARK_ELEGANT_THEME, DEFAULT_RENDERERS, DataGrid, DataStarIcon, DataTable, DatePicker, DatePickerInput, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FileView, FilterPopover, HeaderCell, HtmlRenderer, IconButton, ImageRenderer, Input, Label, LoadingSpinner, MINIMALIST_LIGHT_THEME, MODERN_DARK_THEME, MODERN_LIGHT_THEME, MarkdownRenderer, Modal, ModalButton, OPTILOGIC_DARK_THEME, OPTILOGIC_LEGACY_THEME, OptilogicLogo, OptilogicLogoWithText, PRESET_THEMES, PlainTextRenderer, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, ResizablePanel, ResizeHandle, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SelectableCard, Separator, Skeleton, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemePicker, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger, accordionContentVariants, accordionItemVariants, accordionTriggerVariants, applyFilterOperator, applyFilters, applySorting, applyTheme, areThemesEqual, badgeVariants, boardVariants, buttonVariants, cardActionsVariants, cardGridVariants, cardImageVariants, cardListVariants, cardVariants, cloneTheme, cn, detectContentType, exportTheme, getCellValue, getCurrentTheme, getDefaultTheme, getFileExtension, getPresetTheme, hexToHsl, iconButtonVariants, importTheme, isPresetTheme, isTextContentType, isUrlContentType, labelVariants, loadingSpinnerVariants, mergeRenderers, resolveRenderer, themeToHsl, useColumnResize, useColumnResizeManager, useConfirmation, useContentType, useContextMenu, useDataGridState, useKeyboardNavigation, validateTheme };
|
|
8442
|
+
export { ALL_THEMES, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Autocomplete, Badge, Board, BoardContent, BoardHeader, Button, Calendar, Card, CardActions, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardImage, CardList, CardTitle, CellEditor, Checkbox, Chip, CodeRenderer, Combobox, ConfirmationModal, ContextMenu, CopyButton, CosmicFrogIcon, CsvRenderer, DARK_ELEGANT_THEME, DEFAULT_RENDERERS, DataGrid, DataStarIcon, DataTable, DatePicker, DatePickerInput, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FileView, FilterPopover, HeaderCell, HtmlRenderer, IconButton, ImageRenderer, Input, Label, LoadingSpinner, MINIMALIST_LIGHT_THEME, MODERN_DARK_THEME, MODERN_LIGHT_THEME, MarkdownRenderer, Modal, ModalButton, MultiSelect, OPTILOGIC_DARK_THEME, OPTILOGIC_LEGACY_THEME, OptilogicLogo, OptilogicLogoWithText, PRESET_THEMES, PlainTextRenderer, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, ResizablePanel, ResizeHandle, Select, SelectContent, SelectGroup, SelectItem, SelectItemDescription, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SelectableCard, Separator, Skeleton, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemePicker, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger, accordionContentVariants, accordionItemVariants, accordionTriggerVariants, applyFilterOperator, applyFilters, applySorting, applyTheme, areThemesEqual, badgeVariants, boardVariants, buttonVariants, cardActionsVariants, cardGridVariants, cardImageVariants, cardListVariants, cardVariants, cloneTheme, cn, detectContentType, exportTheme, getCellValue, getCurrentTheme, getDefaultTheme, getFileExtension, getPresetTheme, hexToHsl, iconButtonVariants, importTheme, isPresetTheme, isTextContentType, isUrlContentType, labelVariants, loadingSpinnerVariants, mergeRenderers, resolveRenderer, tabsListVariants, tabsTriggerVariants, themeToHsl, useColumnResize, useColumnResizeManager, useConfirmation, useContentType, useContextMenu, useDataGridState, useKeyboardNavigation, validateTheme };
|
|
7891
8443
|
//# sourceMappingURL=index.js.map
|
|
7892
8444
|
//# sourceMappingURL=index.js.map
|