@postxl/ui-components 1.0.3 → 1.2.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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { clsx } from "clsx";
2
2
  import { twMerge } from "tailwind-merge";
3
3
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
4
- import { ArrowLeftIcon, ArrowRightIcon, CalendarIcon, CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, CopyIcon, Cross1Icon, Cross2Icon, DotFilledIcon, DotsHorizontalIcon, DoubleArrowLeftIcon, DoubleArrowRightIcon, DragHandleDots2Icon, DragHandleHorizontalIcon, EnterFullScreenIcon, EraserIcon, MagnifyingGlassIcon, MixerHorizontalIcon, PlusIcon, TrashIcon } from "@radix-ui/react-icons";
4
+ import { ArrowLeftIcon, ArrowRightIcon, CalendarIcon, CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, Cross1Icon, Cross2Icon, DotFilledIcon, DotsHorizontalIcon, DoubleArrowLeftIcon, DoubleArrowRightIcon, DragHandleDots2Icon, EnterFullScreenIcon, MagnifyingGlassIcon } from "@radix-ui/react-icons";
5
5
  import * as React$46 from "react";
6
6
  import * as React$45 from "react";
7
7
  import * as React$44 from "react";
@@ -57,7 +57,7 @@ import * as AvatarPrimitive from "@radix-ui/react-avatar";
57
57
  import { DayPicker, getDefaultClassNames } from "react-day-picker";
58
58
  import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
59
59
  import useEmblaCarousel from "embla-carousel-react";
60
- import { BaselineIcon, CalendarIcon as CalendarIcon$1, CheckSquareIcon, ChevronDownIcon as ChevronDownIcon$1, ChevronUpIcon as ChevronUpIcon$1, EyeOffIcon, HashIcon, ListChecksIcon, ListIcon, PanelLeftIcon, PinIcon, PinOffIcon, SquareIcon, TextInitialIcon, XIcon } from "lucide-react";
60
+ import { BaselineIcon, CalendarIcon as CalendarIcon$1, CheckIcon as CheckIcon$1, CheckSquareIcon, ChevronDownIcon as ChevronDownIcon$1, ChevronUpIcon as ChevronUpIcon$1, CopyIcon, CrossIcon, EraserIcon, EyeOffIcon, FilterX, GripHorizontalIcon, HashIcon, ListChecksIcon, ListIcon, PanelLeftIcon, PinIcon, PinOffIcon, PlusIcon, Settings2Icon, SquareIcon, TextInitialIcon, TrashIcon, XIcon } from "lucide-react";
61
61
  import * as CollapsePrimitive from "@radix-ui/react-collapsible";
62
62
  import { Command as Command$1 } from "cmdk";
63
63
  import * as DialogPrimitive from "@radix-ui/react-dialog";
@@ -1347,6 +1347,15 @@ const ContextMenuShortcut = ({ className,...props }) => {
1347
1347
  };
1348
1348
  ContextMenuShortcut.displayName = "ContextMenuShortcut";
1349
1349
 
1350
+ //#endregion
1351
+ //#region src/skeleton/skeleton.tsx
1352
+ function Skeleton({ className,...props }) {
1353
+ return /* @__PURE__ */ jsx("div", {
1354
+ className: cn("animate-pulse rounded-md bg-primary/10", className),
1355
+ ...props
1356
+ });
1357
+ }
1358
+
1350
1359
  //#endregion
1351
1360
  //#region src/dropdown-menu/dropdown-menu.tsx
1352
1361
  function DropdownMenu({ ...props }) {
@@ -1774,7 +1783,7 @@ const GanttTimerangePicker = ({ initialDateFrom, initialDateTo, onRangeChange, t
1774
1783
  children: /* @__PURE__ */ jsx(Button, {
1775
1784
  size: "iconSm",
1776
1785
  variant: "extraGhost2",
1777
- children: /* @__PURE__ */ jsx(CalendarIcon, { className: "size-3" })
1786
+ children: /* @__PURE__ */ jsx(CalendarIcon$1, { className: "size-3" })
1778
1787
  })
1779
1788
  }), /* @__PURE__ */ jsxs(PopoverContent, {
1780
1789
  align: "start",
@@ -1792,7 +1801,7 @@ const GanttTimerangePicker = ({ initialDateFrom, initialDateTo, onRangeChange, t
1792
1801
  onClick: () => {
1793
1802
  setIsOpen(false);
1794
1803
  },
1795
- children: /* @__PURE__ */ jsx(Cross2Icon, { className: "size-5" })
1804
+ children: /* @__PURE__ */ jsx(CrossIcon, { className: "size-5" })
1796
1805
  })]
1797
1806
  }),
1798
1807
  /* @__PURE__ */ jsxs("div", {
@@ -2435,13 +2444,19 @@ const DataGridRow = React$30.memo(DataGridRowImpl, (prev, next) => {
2435
2444
  const nextHasFocus = next.focusedCell?.rowIndex === nextRowIndex;
2436
2445
  if (prevHasFocus !== nextHasFocus) return false;
2437
2446
  if (nextHasFocus && prevHasFocus) {
2438
- const prevFocusedCol = prev.focusedCell?.columnId;
2439
- const nextFocusedCol = next.focusedCell?.columnId;
2440
- if (prevFocusedCol !== nextFocusedCol) return false;
2447
+ if (prev.focusedCell?.columnId !== next.focusedCell?.columnId) return false;
2441
2448
  }
2442
- return next.rowVirtualizer.isScrolling;
2449
+ const prevHasEditing = prev.editingCell?.rowIndex === prevRowIndex;
2450
+ const nextHasEditing = next.editingCell?.rowIndex === nextRowIndex;
2451
+ if (prevHasEditing !== nextHasEditing) return false;
2452
+ if (nextHasEditing && prevHasEditing) {
2453
+ if (prev.editingCell?.columnId !== next.editingCell?.columnId) return false;
2454
+ }
2455
+ if (prev.selectionSize !== next.selectionSize) return false;
2456
+ if (prev.visibleColumnIds !== next.visibleColumnIds) return false;
2457
+ return true;
2443
2458
  });
2444
- function DataGridRowImpl({ row, virtualRowIndex, rowVirtualizer, rowMapRef, rowHeight, focusedCell, ref, className,...props }) {
2459
+ function DataGridRowImpl({ row, virtualRowIndex, virtualStart, rowVirtualizer, rowMapRef, rowHeight, focusedCell, editingCell: _editingCell, selectionSize: _selectionSize, visibleColumnIds: _visibleColumnIds, ref, className,...props }) {
2445
2460
  const rowRef = useComposedRefs(ref, (node) => {
2446
2461
  if (node && typeof virtualRowIndex !== "undefined") {
2447
2462
  rowVirtualizer.measureElement(node);
@@ -2458,7 +2473,10 @@ function DataGridRowImpl({ row, virtualRowIndex, rowVirtualizer, rowMapRef, rowH
2458
2473
  ref: rowRef,
2459
2474
  tabIndex: -1,
2460
2475
  className: cn("absolute flex w-full border-b h-[calc(var(--data-grid-line-height)*(var(--line-count))+12px)]", className),
2461
- style: { "--line-count": `${getLineCount(rowHeight)}` },
2476
+ style: {
2477
+ "--line-count": `${getLineCount(rowHeight)}`,
2478
+ transform: `translateY(${virtualStart}px)`
2479
+ },
2462
2480
  ...props,
2463
2481
  children: row.getVisibleCells().map((cell, colIndex) => {
2464
2482
  const isCellFocused = focusedCell?.rowIndex === virtualRowIndex && focusedCell?.columnId === cell.column.id;
@@ -2483,33 +2501,7 @@ function DataGridRowImpl({ row, virtualRowIndex, rowVirtualizer, rowMapRef, rowH
2483
2501
  }
2484
2502
 
2485
2503
  //#endregion
2486
- //#region src/input/input.tsx
2487
- const inputVariants = cva("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
2488
- variants: { variant: {
2489
- default: "h-9 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
2490
- simple: "h-8"
2491
- } },
2492
- defaultVariants: { variant: "default" }
2493
- });
2494
- function Input({ className, type, variant, __e2e_test_id__, onEnter,...props }) {
2495
- return /* @__PURE__ */ jsx("input", {
2496
- type,
2497
- "data-slot": "input",
2498
- className: cn(inputVariants({
2499
- variant,
2500
- className
2501
- })),
2502
- "data-test-id": __e2e_test_id__,
2503
- onKeyDown: (e) => {
2504
- props.onKeyDown?.(e);
2505
- if (e.key === "Enter") onEnter?.();
2506
- },
2507
- ...props
2508
- });
2509
- }
2510
-
2511
- //#endregion
2512
- //#region src/data-grid/hooks/use-callback-ref.ts
2504
+ //#region src/hooks/use-callback-ref.ts
2513
2505
  /**
2514
2506
  * @see https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx
2515
2507
  */
@@ -2526,7 +2518,7 @@ function useCallbackRef(callback) {
2526
2518
  }
2527
2519
 
2528
2520
  //#endregion
2529
- //#region src/data-grid/hooks/use-debounced-callback.ts
2521
+ //#region src/hooks/use-debounced-callback.ts
2530
2522
  function useDebouncedCallback(callback, delay) {
2531
2523
  const handleCallback = useCallbackRef(callback);
2532
2524
  const debounceTimerRef = React$28.useRef(0);
@@ -2538,6 +2530,32 @@ function useDebouncedCallback(callback, delay) {
2538
2530
  return setValue;
2539
2531
  }
2540
2532
 
2533
+ //#endregion
2534
+ //#region src/input/input.tsx
2535
+ const inputVariants = cva("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
2536
+ variants: { variant: {
2537
+ default: "h-9 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
2538
+ simple: "h-8"
2539
+ } },
2540
+ defaultVariants: { variant: "default" }
2541
+ });
2542
+ function Input({ className, type, variant, __e2e_test_id__, onEnter,...props }) {
2543
+ return /* @__PURE__ */ jsx("input", {
2544
+ type,
2545
+ "data-slot": "input",
2546
+ className: cn(inputVariants({
2547
+ variant,
2548
+ className
2549
+ })),
2550
+ "data-test-id": __e2e_test_id__,
2551
+ onKeyDown: (e) => {
2552
+ props.onKeyDown?.(e);
2553
+ if (e.key === "Enter") onEnter?.();
2554
+ },
2555
+ ...props
2556
+ });
2557
+ }
2558
+
2541
2559
  //#endregion
2542
2560
  //#region src/data-grid/data-grid-search.tsx
2543
2561
  const DataGridSearch = React$27.memo(DataGridSearchImpl, (prev, next) => {
@@ -2627,7 +2645,7 @@ function DataGridSearchImpl({ searchMatches, matchIndex, searchOpen, onSearchOpe
2627
2645
  onClick: onNavigateToPrevMatch,
2628
2646
  onPointerDown: onPrevMatchPointerDown,
2629
2647
  disabled: searchMatches.length === 0,
2630
- children: /* @__PURE__ */ jsx(ChevronUpIcon, {})
2648
+ children: /* @__PURE__ */ jsx(ChevronUpIcon$1, {})
2631
2649
  }),
2632
2650
  /* @__PURE__ */ jsx(Button, {
2633
2651
  "aria-label": "Next match",
@@ -2637,7 +2655,7 @@ function DataGridSearchImpl({ searchMatches, matchIndex, searchOpen, onSearchOpe
2637
2655
  onClick: onNavigateToNextMatch,
2638
2656
  onPointerDown: onNextMatchPointerDown,
2639
2657
  disabled: searchMatches.length === 0,
2640
- children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
2658
+ children: /* @__PURE__ */ jsx(ChevronDownIcon$1, {})
2641
2659
  }),
2642
2660
  /* @__PURE__ */ jsx(Button, {
2643
2661
  "aria-label": "Close search",
@@ -2645,7 +2663,7 @@ function DataGridSearchImpl({ searchMatches, matchIndex, searchOpen, onSearchOpe
2645
2663
  size: "icon",
2646
2664
  className: "size-7",
2647
2665
  onClick: onClose,
2648
- children: /* @__PURE__ */ jsx(Cross2Icon, {})
2666
+ children: /* @__PURE__ */ jsx(CrossIcon, {})
2649
2667
  })
2650
2668
  ]
2651
2669
  })]
@@ -2668,6 +2686,14 @@ function DataGrid({ dataGridRef, headerRef, rowMapRef, footerRef, table, rowVirt
2668
2686
  const meta = table.options.meta;
2669
2687
  const rowHeight = meta?.rowHeight ?? "short";
2670
2688
  const focusedCell = meta?.focusedCell ?? null;
2689
+ const editingCell = meta?.editingCell ?? null;
2690
+ const selectionSize = meta?.selectionState?.selectedCells?.size ?? 0;
2691
+ const visibleColumnIds = table.getVisibleLeafColumns().map((c) => c.id).join(",");
2692
+ const prevVisibleColumnIdsRef = React$26.useRef(visibleColumnIds);
2693
+ if (prevVisibleColumnIdsRef.current !== visibleColumnIds) {
2694
+ rowMapRef.current.clear();
2695
+ prevVisibleColumnIdsRef.current = visibleColumnIds;
2696
+ }
2671
2697
  const onGridContextMenu = React$26.useCallback((event) => {
2672
2698
  event.preventDefault();
2673
2699
  }, []);
@@ -2749,16 +2775,31 @@ function DataGrid({ dataGridRef, headerRef, rowMapRef, footerRef, table, rowVirt
2749
2775
  "data-slot": "grid-body",
2750
2776
  className: "relative grid",
2751
2777
  style: { height: `${rowVirtualizer.getTotalSize()}px` },
2752
- children: rowVirtualizer.getVirtualIndexes().map((virtualRowIndex) => {
2753
- const row = rows[virtualRowIndex];
2754
- if (!row) return null;
2778
+ children: rowVirtualizer.getVirtualItems().map((virtualItem) => {
2779
+ const row = rows[virtualItem.index];
2780
+ if (!row) return /* @__PURE__ */ jsx("div", {
2781
+ className: "absolute flex items-center w-full border-b",
2782
+ style: {
2783
+ height: virtualItem.size,
2784
+ transform: `translateY(${virtualItem.start}px)`
2785
+ },
2786
+ children: table.getVisibleLeafColumns().map((col) => /* @__PURE__ */ jsx("div", {
2787
+ className: "px-3",
2788
+ style: { width: `calc(var(--col-${col.id}-size) * 1px)` },
2789
+ children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" })
2790
+ }, col.id))
2791
+ }, `skeleton-${virtualItem.index}`);
2755
2792
  return /* @__PURE__ */ jsx(DataGridRow, {
2756
2793
  row,
2757
2794
  rowMapRef,
2758
- virtualRowIndex,
2795
+ virtualRowIndex: virtualItem.index,
2796
+ virtualStart: virtualItem.start,
2759
2797
  rowVirtualizer,
2760
2798
  rowHeight,
2761
- focusedCell
2799
+ focusedCell,
2800
+ editingCell,
2801
+ selectionSize,
2802
+ visibleColumnIds
2762
2803
  }, row.id);
2763
2804
  })
2764
2805
  }),
@@ -3067,12 +3108,16 @@ function DateCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isSel
3067
3108
  const [value, setValue] = React$23.useState(parseToLocalDate(initialValue));
3068
3109
  const [open, setOpen] = React$23.useState(false);
3069
3110
  const containerRef = React$23.useRef(null);
3111
+ const hasStoppedRef = React$23.useRef(false);
3070
3112
  const meta = table.options.meta;
3071
3113
  const prevInitialValueRef = React$23.useRef(initialValue);
3072
3114
  if (initialValue !== prevInitialValueRef.current) {
3073
3115
  prevInitialValueRef.current = initialValue;
3074
3116
  setValue(parseToLocalDate(initialValue));
3075
3117
  }
3118
+ React$23.useEffect(() => {
3119
+ if (isEditing) hasStoppedRef.current = false;
3120
+ }, [isEditing]);
3076
3121
  const onDateSelect = React$23.useCallback((date) => {
3077
3122
  if (!date) return;
3078
3123
  setValue(date);
@@ -3081,6 +3126,7 @@ function DateCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isSel
3081
3126
  columnId,
3082
3127
  value: formatDateToISOString(date)
3083
3128
  });
3129
+ hasStoppedRef.current = true;
3084
3130
  setOpen(false);
3085
3131
  meta?.onCellEditingStop?.();
3086
3132
  }, [
@@ -3090,16 +3136,22 @@ function DateCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isSel
3090
3136
  ]);
3091
3137
  const onOpenChange = React$23.useCallback((isOpen) => {
3092
3138
  setOpen(isOpen);
3093
- if (!isOpen && isEditing) meta?.onCellEditingStop?.();
3139
+ if (!isOpen && isEditing && !hasStoppedRef.current) {
3140
+ hasStoppedRef.current = true;
3141
+ meta?.onCellEditingStop?.();
3142
+ }
3094
3143
  }, [isEditing, meta]);
3095
3144
  const onWrapperKeyDown = React$23.useCallback((event) => {
3096
3145
  if (isEditing) {
3097
3146
  if (event.key === "Escape") {
3098
3147
  event.preventDefault();
3148
+ hasStoppedRef.current = true;
3099
3149
  setValue(parseToLocalDate(initialValue));
3100
3150
  setOpen(false);
3151
+ meta?.onCellEditingStop?.();
3101
3152
  } else if (event.key === "Tab") {
3102
3153
  event.preventDefault();
3154
+ hasStoppedRef.current = true;
3103
3155
  setOpen(false);
3104
3156
  meta?.onCellEditingStop?.({ direction: event.shiftKey ? "left" : "right" });
3105
3157
  }
@@ -3227,6 +3279,7 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3227
3279
  const [open, setOpen] = React$21.useState(false);
3228
3280
  const textareaRef = React$21.useRef(null);
3229
3281
  const containerRef = React$21.useRef(null);
3282
+ const hasSubmittedRef = React$21.useRef(false);
3230
3283
  const meta = table.options.meta;
3231
3284
  const sideOffset = -(containerRef.current?.clientHeight ?? 0);
3232
3285
  const prevInitialValueRef = React$21.useRef(initialValue);
@@ -3234,6 +3287,9 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3234
3287
  prevInitialValueRef.current = initialValue;
3235
3288
  setValue(initialValue ?? "");
3236
3289
  }
3290
+ React$21.useEffect(() => {
3291
+ if (isEditing) hasSubmittedRef.current = false;
3292
+ }, [isEditing]);
3237
3293
  const debouncedSave = useDebouncedCallback((newValue) => {
3238
3294
  meta?.onDataUpdate?.({
3239
3295
  rowIndex,
@@ -3242,6 +3298,8 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3242
3298
  });
3243
3299
  }, 300);
3244
3300
  const onSave = React$21.useCallback(() => {
3301
+ if (hasSubmittedRef.current) return;
3302
+ hasSubmittedRef.current = true;
3245
3303
  if (value !== initialValue) meta?.onDataUpdate?.({
3246
3304
  rowIndex,
3247
3305
  columnId,
@@ -3257,6 +3315,8 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3257
3315
  columnId
3258
3316
  ]);
3259
3317
  const onCancel = React$21.useCallback(() => {
3318
+ if (hasSubmittedRef.current) return;
3319
+ hasSubmittedRef.current = true;
3260
3320
  setValue(initialValue ?? "");
3261
3321
  meta?.onDataUpdate?.({
3262
3322
  rowIndex,
@@ -3278,7 +3338,8 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3278
3338
  }, [debouncedSave]);
3279
3339
  const onOpenChange = React$21.useCallback((isOpen) => {
3280
3340
  setOpen(isOpen);
3281
- if (!isOpen) {
3341
+ if (!isOpen && !hasSubmittedRef.current) {
3342
+ hasSubmittedRef.current = true;
3282
3343
  if (value !== initialValue) meta?.onDataUpdate?.({
3283
3344
  rowIndex,
3284
3345
  columnId,
@@ -3305,9 +3366,11 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3305
3366
  if (isEditing && !open) {
3306
3367
  if (event.key === "Escape") {
3307
3368
  event.preventDefault();
3369
+ hasSubmittedRef.current = true;
3308
3370
  meta?.onCellEditingStop?.();
3309
3371
  } else if (event.key === "Tab") {
3310
3372
  event.preventDefault();
3373
+ hasSubmittedRef.current = true;
3311
3374
  if (value !== initialValue) meta?.onDataUpdate?.({
3312
3375
  rowIndex,
3313
3376
  columnId,
@@ -3336,6 +3399,8 @@ function LongTextCell({ cell, table, rowIndex, columnId, isFocused, isEditing, i
3336
3399
  event.stopPropagation();
3337
3400
  }, [onCancel, onSave]);
3338
3401
  const onTextareaBlur = React$21.useCallback(() => {
3402
+ if (hasSubmittedRef.current) return;
3403
+ hasSubmittedRef.current = true;
3339
3404
  if (value !== initialValue) meta?.onDataUpdate?.({
3340
3405
  rowIndex,
3341
3406
  columnId,
@@ -3413,8 +3478,28 @@ function MultiSelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing
3413
3478
  const inputRef = React$20.useRef(null);
3414
3479
  const meta = table.options.meta;
3415
3480
  const cellOpts = cell.column.columnDef.meta?.cell;
3416
- const options = cellOpts?.variant === "multi-select" ? cellOpts.options : [];
3417
3481
  const sideOffset = -(containerRef.current?.clientHeight ?? 0);
3482
+ const arrayOptions = cellOpts?.variant === "multi-select" ? cellOpts.options : void 0;
3483
+ const optionsMap = cellOpts?.variant === "multi-select" ? cellOpts.optionsMap : void 0;
3484
+ const arrayOptionsLabelMap = React$20.useMemo(() => arrayOptions ? new Map(arrayOptions.map((opt) => [opt.value, opt.label])) : null, [arrayOptions]);
3485
+ const getLabel = React$20.useCallback((val) => {
3486
+ if (optionsMap) return optionsMap.get(val) ?? val;
3487
+ if (arrayOptionsLabelMap) return arrayOptionsLabelMap.get(val) ?? val;
3488
+ return val;
3489
+ }, [optionsMap, arrayOptionsLabelMap]);
3490
+ const options = React$20.useMemo(() => {
3491
+ if (!isEditing) return [];
3492
+ if (arrayOptions) return arrayOptions;
3493
+ if (optionsMap) return Array.from(optionsMap.entries()).map(([id, label]) => ({
3494
+ value: id,
3495
+ label
3496
+ }));
3497
+ return [];
3498
+ }, [
3499
+ isEditing,
3500
+ arrayOptions,
3501
+ optionsMap
3502
+ ]);
3418
3503
  if (prevCellIdRef.current !== cellId) {
3419
3504
  prevCellIdRef.current = cellId;
3420
3505
  setSelectedValues(cellValue);
@@ -3523,7 +3608,7 @@ function MultiSelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing
3523
3608
  React$20.useEffect(() => {
3524
3609
  if (open && inputRef.current) setTimeout(() => inputRef.current?.focus(), 0);
3525
3610
  }, [open]);
3526
- const displayLabels = selectedValues.map((val) => options.find((opt) => opt.value === val)?.label ?? val).filter(Boolean);
3611
+ const displayLabels = selectedValues.map(getLabel).filter(Boolean);
3527
3612
  const rowHeight = table.options.meta?.rowHeight ?? "short";
3528
3613
  const lineCount = getLineCount(rowHeight);
3529
3614
  const maxVisibleBadgeCount = lineCount * 3;
@@ -3555,23 +3640,19 @@ function MultiSelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing
3555
3640
  className: "[&_[data-slot=command-input-wrapper]]:h-auto [&_[data-slot=command-input-wrapper]]:border-none [&_[data-slot=command-input-wrapper]]:p-0 [&_[data-slot=command-input-wrapper]_svg]:hidden",
3556
3641
  children: [/* @__PURE__ */ jsxs("div", {
3557
3642
  className: "flex min-h-9 flex-wrap items-center gap-1 border-b px-3 py-1.5",
3558
- children: [selectedValues.map((value) => {
3559
- const option = options.find((opt) => opt.value === value);
3560
- const label = option?.label ?? value;
3561
- return /* @__PURE__ */ jsxs(Badge, {
3562
- variant: "secondary",
3563
- className: "h-5 gap-1 px-1.5 text-xs",
3564
- children: [label, /* @__PURE__ */ jsx("button", {
3565
- type: "button",
3566
- onClick: (event) => removeValue(value, event),
3567
- onPointerDown: (event) => {
3568
- event.preventDefault();
3569
- event.stopPropagation();
3570
- },
3571
- children: /* @__PURE__ */ jsx(Cross2Icon, { className: "size-3" })
3572
- })]
3573
- }, value);
3574
- }), /* @__PURE__ */ jsx(CommandInput, {
3643
+ children: [selectedValues.map((value) => /* @__PURE__ */ jsxs(Badge, {
3644
+ variant: "secondary",
3645
+ className: "h-5 gap-1 px-1.5 text-xs",
3646
+ children: [getLabel(value), /* @__PURE__ */ jsx("button", {
3647
+ type: "button",
3648
+ onClick: (event) => removeValue(value, event),
3649
+ onPointerDown: (event) => {
3650
+ event.preventDefault();
3651
+ event.stopPropagation();
3652
+ },
3653
+ children: /* @__PURE__ */ jsx(CrossIcon, { className: "size-3" })
3654
+ })]
3655
+ }, value)), /* @__PURE__ */ jsx(CommandInput, {
3575
3656
  ref: inputRef,
3576
3657
  value: searchValue,
3577
3658
  onValueChange: setSearchValue,
@@ -3592,7 +3673,7 @@ function MultiSelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing
3592
3673
  onSelect: () => onValueChange(option.value),
3593
3674
  children: [/* @__PURE__ */ jsx("div", {
3594
3675
  className: cn("flex size-4 items-center justify-center rounded-sm border border-border", isSelected$1 ? "bg-accent-foreground text-secondary" : "opacity-50 [&_svg]:invisible"),
3595
- children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3" })
3676
+ children: /* @__PURE__ */ jsx(CheckIcon$1, { className: "size-3" })
3596
3677
  }), /* @__PURE__ */ jsx("span", { children: option.label })]
3597
3678
  }, option.value);
3598
3679
  })
@@ -3638,7 +3719,12 @@ function NumberCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3638
3719
  const isEditable = editableResolver(cell.row.original);
3639
3720
  const { min, max, step, prefix = "", suffix = "", fallbackValue = "" } = cellOptions?.variant === "number" ? cellOptions : {};
3640
3721
  const [editValue, setEditValue] = React$19.useState(initialValue !== null && initialValue !== void 0 ? String(initialValue) : "");
3722
+ const hasSubmittedRef = React$19.useRef(false);
3723
+ React$19.useEffect(() => {
3724
+ if (isEditing) hasSubmittedRef.current = false;
3725
+ }, [isEditing]);
3641
3726
  const onBlur = React$19.useCallback(() => {
3727
+ if (hasSubmittedRef.current) return;
3642
3728
  const numValue = editValue === "" ? null : Number(editValue);
3643
3729
  if (numValue !== initialValue) meta?.onDataUpdate?.({
3644
3730
  rowIndex,
@@ -3660,6 +3746,7 @@ function NumberCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3660
3746
  return editValue === "" ? null : Number(editValue);
3661
3747
  }, [editValue]);
3662
3748
  const saveAndStop = React$19.useCallback((options) => {
3749
+ hasSubmittedRef.current = true;
3663
3750
  const numValue = parseNumValue();
3664
3751
  if (numValue !== initialValue) meta?.onDataUpdate?.({
3665
3752
  rowIndex,
@@ -3683,10 +3770,16 @@ function NumberCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3683
3770
  saveAndStop({ direction: event.shiftKey ? "left" : "right" });
3684
3771
  } else if (event.key === "Escape") {
3685
3772
  event.preventDefault();
3773
+ hasSubmittedRef.current = true;
3686
3774
  setEditValue(initialValue !== null && initialValue !== void 0 ? String(initialValue) : "");
3687
3775
  inputRef.current?.blur();
3776
+ meta?.onCellEditingStop?.();
3688
3777
  }
3689
- }, [saveAndStop, initialValue]);
3778
+ }, [
3779
+ saveAndStop,
3780
+ initialValue,
3781
+ meta
3782
+ ]);
3690
3783
  const handleFocusedKeyDown = React$19.useCallback((event) => {
3691
3784
  if (!isEditable) return;
3692
3785
  if (event.key === "Backspace") setEditValue("");
@@ -3777,9 +3870,34 @@ function SelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3777
3870
  const inputRef = React$17.useRef(null);
3778
3871
  const meta = table.options.meta;
3779
3872
  const cellOpts = cell.column.columnDef.meta?.cell;
3780
- const options = cellOpts?.variant === "select" ? cellOpts.options : [];
3781
3873
  const hasSearch = (cellOpts?.variant === "select" && cellOpts?.hasSearch) ?? false;
3782
3874
  const sideOffset = -(inputRef.current?.clientHeight ?? 0);
3875
+ const arrayOptions = cellOpts?.variant === "select" ? cellOpts.options : void 0;
3876
+ const optionsMap = cellOpts?.variant === "select" ? cellOpts.optionsMap : void 0;
3877
+ const arrayOptionsLabelMap = React$17.useMemo(() => arrayOptions ? new Map(arrayOptions.map((opt) => [opt.value, opt.label])) : null, [arrayOptions]);
3878
+ const displayLabel = React$17.useMemo(() => {
3879
+ if (!value) return value;
3880
+ if (optionsMap) return optionsMap.get(value) ?? value;
3881
+ if (arrayOptionsLabelMap) return arrayOptionsLabelMap.get(value) ?? value;
3882
+ return value;
3883
+ }, [
3884
+ value,
3885
+ optionsMap,
3886
+ arrayOptionsLabelMap
3887
+ ]);
3888
+ const options = React$17.useMemo(() => {
3889
+ if (!isEditing) return [];
3890
+ if (arrayOptions) return arrayOptions;
3891
+ if (optionsMap) return Array.from(optionsMap.entries()).map(([id, label]) => ({
3892
+ value: id,
3893
+ label
3894
+ }));
3895
+ return [];
3896
+ }, [
3897
+ isEditing,
3898
+ arrayOptions,
3899
+ optionsMap
3900
+ ]);
3783
3901
  const onValueChange = React$17.useCallback((newValue) => {
3784
3902
  setValue(newValue);
3785
3903
  meta?.onDataUpdate?.({
@@ -3832,7 +3950,6 @@ function SelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3832
3950
  meta?.searchOpen,
3833
3951
  meta?.isScrolling
3834
3952
  ]);
3835
- const displayLabel = options.find((opt) => opt.value === value)?.label ?? value;
3836
3953
  let editingContent;
3837
3954
  if (hasSearch) editingContent = /* @__PURE__ */ jsxs(Popover, {
3838
3955
  open,
@@ -3860,7 +3977,7 @@ function SelectCell({ cell, table, rowIndex, columnId, isFocused, isEditing, isS
3860
3977
  onSelect: () => {
3861
3978
  onValueChange(option.value);
3862
3979
  },
3863
- children: [/* @__PURE__ */ jsx("span", { children: option.label }), value === option.value ? /* @__PURE__ */ jsx(CheckIcon, { className: "ml-auto h-4 w-4" }) : null]
3980
+ children: [/* @__PURE__ */ jsx("span", { children: option.label }), value === option.value ? /* @__PURE__ */ jsx(CheckIcon$1, { className: "ml-auto h-4 w-4" }) : null]
3864
3981
  }, option.value)) })
3865
3982
  ] }) })
3866
3983
  })]
@@ -3910,6 +4027,7 @@ function ShortTextCell({ cell, table, rowIndex, columnId, isEditing, isFocused,
3910
4027
  const [value, setValue] = React$16.useState(initialValue);
3911
4028
  const inputRef = React$16.useRef(null);
3912
4029
  const containerRef = React$16.useRef(null);
4030
+ const hasSubmittedRef = React$16.useRef(false);
3913
4031
  const meta = table.options.meta;
3914
4032
  const colMeta = cell.column.columnDef.meta;
3915
4033
  const editableResolver = React$16.useMemo(() => {
@@ -3918,7 +4036,11 @@ function ShortTextCell({ cell, table, rowIndex, columnId, isEditing, isFocused,
3918
4036
  return typeof v === "function" ? v : () => Boolean(v);
3919
4037
  }, [colMeta?.editable]);
3920
4038
  const isEditable = editableResolver(cell.row.original);
4039
+ React$16.useEffect(() => {
4040
+ if (isEditing) hasSubmittedRef.current = false;
4041
+ }, [isEditing]);
3921
4042
  const onBlur = React$16.useCallback(() => {
4043
+ if (hasSubmittedRef.current) return;
3922
4044
  const currentValue = inputRef.current?.value ?? "";
3923
4045
  if (currentValue !== initialValue) meta?.onDataUpdate?.({
3924
4046
  rowIndex,
@@ -3938,6 +4060,7 @@ function ShortTextCell({ cell, table, rowIndex, columnId, isEditing, isFocused,
3938
4060
  const handleEditingKeyDown = React$16.useCallback((event) => {
3939
4061
  if (event.key === "Enter") {
3940
4062
  event.preventDefault();
4063
+ hasSubmittedRef.current = true;
3941
4064
  const currentValue = inputRef.current?.value ?? "";
3942
4065
  if (currentValue !== initialValue) meta?.onDataUpdate?.({
3943
4066
  rowIndex,
@@ -3947,6 +4070,7 @@ function ShortTextCell({ cell, table, rowIndex, columnId, isEditing, isFocused,
3947
4070
  meta?.onCellEditingStop?.({ moveToNextRow: true });
3948
4071
  } else if (event.key === "Tab") {
3949
4072
  event.preventDefault();
4073
+ hasSubmittedRef.current = true;
3950
4074
  const currentValue = inputRef.current?.value ?? "";
3951
4075
  if (currentValue !== initialValue) meta?.onDataUpdate?.({
3952
4076
  rowIndex,
@@ -3956,8 +4080,10 @@ function ShortTextCell({ cell, table, rowIndex, columnId, isEditing, isFocused,
3956
4080
  meta?.onCellEditingStop?.({ direction: event.shiftKey ? "left" : "right" });
3957
4081
  } else if (event.key === "Escape") {
3958
4082
  event.preventDefault();
4083
+ hasSubmittedRef.current = true;
3959
4084
  setValue(initialValue);
3960
4085
  inputRef.current?.blur();
4086
+ meta?.onCellEditingStop?.();
3961
4087
  }
3962
4088
  }, [
3963
4089
  initialValue,
@@ -4270,7 +4396,7 @@ function DataGridViewMenu({ table,...props }) {
4270
4396
  variant: "outline",
4271
4397
  size: "sm",
4272
4398
  className: "ml-auto hidden h-8 font-normal lg:flex",
4273
- children: [/* @__PURE__ */ jsx(MixerHorizontalIcon, { className: "text-muted-foreground" }), "View"]
4399
+ children: [/* @__PURE__ */ jsx(Settings2Icon, { className: "text-muted-foreground" }), "View"]
4274
4400
  })
4275
4401
  }), /* @__PURE__ */ jsxs(PopoverContent, {
4276
4402
  className: cn("w-56 p-0 m-4 mt-0", isDragging ? "cursor-grabbing" : ""),
@@ -4308,13 +4434,13 @@ function DataGridViewMenu({ table,...props }) {
4308
4434
  startPointerDrag(e, column.id);
4309
4435
  },
4310
4436
  className: cn("size-4 text-muted-foreground", searchQuery.trim() !== "" && "opacity-10", searchQuery.trim() === "" && (isDragging ? "cursor-grabbing" : "cursor-grab")),
4311
- children: /* @__PURE__ */ jsx(DragHandleHorizontalIcon, {})
4437
+ children: /* @__PURE__ */ jsx(GripHorizontalIcon, {})
4312
4438
  }),
4313
4439
  /* @__PURE__ */ jsx("span", {
4314
4440
  className: "truncate",
4315
4441
  children: column.columnDef.meta?.label ?? column.id
4316
4442
  }),
4317
- /* @__PURE__ */ jsx(CheckIcon, { className: cn(
4443
+ /* @__PURE__ */ jsx(CheckIcon$1, { className: cn(
4318
4444
  "ml-auto size-4 shrink-0",
4319
4445
  // Visible columns show the check; non-hideable columns show a muted check
4320
4446
  isHideable ? column.getIsVisible() ? "opacity-100" : "opacity-0" : "opacity-50 text-muted-foreground"
@@ -4363,7 +4489,7 @@ function useStore(store, selector) {
4363
4489
  const getSnapshot = React$14.useCallback(() => selector(store.getState()), [store, selector]);
4364
4490
  return React$14.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);
4365
4491
  }
4366
- function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRowsDelete: onRowsDeleteProp, onCellFocus: onCellFocusProp, rowHeight: rowHeightProp = DEFAULT_ROW_HEIGHT, overscan = OVERSCAN, initialState, autoFocus = false, enableColumnSelection = false, enableSearch = false,...dataGridProps }) {
4492
+ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRowsDelete: onRowsDeleteProp, onCellFocus: onCellFocusProp, rowHeight: rowHeightProp = DEFAULT_ROW_HEIGHT, overscan = OVERSCAN, initialState, autoFocus = false, enableColumnSelection = false, enableSearch = false, manualSorting, sorting: externalSorting, onSortingChange: externalOnSortingChange, onLoadMore, loadMoreThreshold = 25, totalRowCount,...dataGridProps }) {
4367
4493
  const dataGridRef = React$14.useRef(null);
4368
4494
  const tableRef = React$14.useRef(null);
4369
4495
  const rowVirtualizerRef = React$14.useRef(null);
@@ -5225,10 +5351,17 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5225
5351
  enableSearch
5226
5352
  ]);
5227
5353
  const onSortingChange = React$14.useCallback((updater) => {
5228
- const currentState = store.getState();
5229
- const newSorting = typeof updater === "function" ? updater(currentState.sorting) : updater;
5230
- store.setState("sorting", newSorting);
5231
- }, [store]);
5354
+ if (manualSorting && externalOnSortingChange) externalOnSortingChange(updater);
5355
+ else {
5356
+ const currentState = store.getState();
5357
+ const newSorting = typeof updater === "function" ? updater(currentState.sorting) : updater;
5358
+ store.setState("sorting", newSorting);
5359
+ }
5360
+ }, [
5361
+ store,
5362
+ manualSorting,
5363
+ externalOnSortingChange
5364
+ ]);
5232
5365
  const onRowSelectionChange = React$14.useCallback((updater) => {
5233
5366
  const currentState = store.getState();
5234
5367
  const newRowSelection = typeof updater === "function" ? updater(currentState.rowSelection) : updater;
@@ -5292,15 +5425,17 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5292
5425
  minSize: MIN_COLUMN_SIZE,
5293
5426
  maxSize: MAX_COLUMN_SIZE
5294
5427
  }), []);
5428
+ const effectiveSorting = manualSorting && externalSorting ? externalSorting : sorting;
5295
5429
  const tableOptions = React$14.useMemo(() => ({
5296
5430
  ...dataGridPropsRef.current,
5297
5431
  data,
5298
5432
  columns,
5299
5433
  defaultColumn,
5300
5434
  initialState: mergedInitialState,
5435
+ manualSorting,
5301
5436
  state: {
5302
5437
  ...dataGridPropsRef.current.state,
5303
- sorting,
5438
+ sorting: effectiveSorting,
5304
5439
  rowSelection
5305
5440
  },
5306
5441
  onRowSelectionChange,
@@ -5342,7 +5477,8 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5342
5477
  columns,
5343
5478
  defaultColumn,
5344
5479
  mergedInitialState,
5345
- sorting,
5480
+ effectiveSorting,
5481
+ manualSorting,
5346
5482
  rowSelection,
5347
5483
  onRowSelectionChange,
5348
5484
  onSortingChange,
@@ -5375,6 +5511,7 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5375
5511
  const table = useReactTable(tableOptions);
5376
5512
  if (!tableRef.current) tableRef.current = table;
5377
5513
  const columnSizing = table.getState().columnSizing;
5514
+ const columnVisibility = table.getState().columnVisibility;
5378
5515
  const columnSizeVars = React$14.useMemo(() => {
5379
5516
  const headers = table.getFlatHeaders();
5380
5517
  const colSizes = {};
@@ -5385,9 +5522,15 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5385
5522
  colSizes[`--col-${header.column.id}-size`] = colSize;
5386
5523
  }
5387
5524
  return colSizes;
5388
- }, [table, columnSizing]);
5525
+ }, [
5526
+ table,
5527
+ columnSizing,
5528
+ columnVisibility
5529
+ ]);
5530
+ const loadedRowCount = table.getRowModel().rows.length;
5531
+ const virtualizerRowCount = totalRowCount ?? loadedRowCount;
5389
5532
  const rowVirtualizer = useVirtualizer({
5390
- count: table.getRowModel().rows.length,
5533
+ count: virtualizerRowCount,
5391
5534
  getScrollElement: () => dataGridRef.current,
5392
5535
  estimateSize: () => rowHeightValue,
5393
5536
  overscan,
@@ -5398,9 +5541,12 @@ function useDataGrid({ columns, data, onDataChange, onRowAdd: onRowAddProp, onRo
5398
5541
  if (virtualizerIsScrolling !== currentIsScrolling) store.setState("isScrolling", virtualizerIsScrolling);
5399
5542
  const virtualItems = instance.getVirtualItems();
5400
5543
  if (virtualItems.length === 0) return;
5544
+ if (onLoadMore) {
5545
+ const lastVirtualItem = virtualItems.at(-1);
5546
+ if (lastVirtualItem && lastVirtualItem.index >= loadedRowCount - loadMoreThreshold) onLoadMore();
5547
+ }
5401
5548
  requestAnimationFrame(() => {
5402
5549
  for (const virtualRow of virtualItems) {
5403
- if (!virtualRow) continue;
5404
5550
  const rowRef = rowMapRef.current.get(virtualRow.index);
5405
5551
  if (rowRef) rowRef.style.transform = `translateY(${virtualRow.start}px)`;
5406
5552
  }
@@ -6690,13 +6836,132 @@ function SidebarMenuSubButton({ asChild = false, size = "md", isActive = false,
6690
6836
  }
6691
6837
 
6692
6838
  //#endregion
6693
- //#region src/skeleton/skeleton.tsx
6694
- function Skeleton({ className,...props }) {
6695
- return /* @__PURE__ */ jsx("div", {
6696
- className: cn("animate-pulse rounded-md bg-primary/10", className),
6697
- ...props
6839
+ //#region src/slicer/slicer.tsx
6840
+ function Slicer({ filterValues, selectedValues, onChange, title, isLoading = false, optionsHeight = 200, className, defaultCollapsed = false }) {
6841
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
6842
+ const [searchQuery, setSearchQuery] = useState("");
6843
+ const filteredOptions = useMemo(() => {
6844
+ if (!searchQuery) return filterValues;
6845
+ const lowerQuery = searchQuery.toLowerCase();
6846
+ return filterValues.filter((option) => option.label.toLowerCase().includes(lowerQuery));
6847
+ }, [filterValues, searchQuery]);
6848
+ const areAllSelected = filterValues.length > 0 && filterValues.every((option) => selectedValues.has(option.value));
6849
+ const areAllFilteredSelected = filteredOptions.length > 0 && filteredOptions.every((option) => selectedValues.has(option.value));
6850
+ const isAnyFilteredSelected = filteredOptions.some((option) => selectedValues.has(option.value));
6851
+ const handleClear = () => {
6852
+ onChange([]);
6853
+ };
6854
+ const handleSelectAll = () => {
6855
+ let newVals = [];
6856
+ if (searchQuery.length > 0) {
6857
+ const newSelected = new Set(selectedValues);
6858
+ if (areAllFilteredSelected) filteredOptions.forEach((o) => newSelected.delete(o.value));
6859
+ else filteredOptions.forEach((o) => newSelected.add(o.value));
6860
+ newVals = Array.from(newSelected);
6861
+ } else if (areAllSelected) newVals = [];
6862
+ else newVals = filterValues.map((o) => o.value);
6863
+ onChange(newVals);
6864
+ };
6865
+ const handleOptionToggle = (optionValue, checked) => {
6866
+ const newSelected = new Set(selectedValues);
6867
+ if (checked) newSelected.add(optionValue);
6868
+ else newSelected.delete(optionValue);
6869
+ onChange(Array.from(newSelected));
6870
+ };
6871
+ return /* @__PURE__ */ jsxs(Card, {
6872
+ className: cn("flex flex-col overflow-hidden w-56 rounded shadow-sm shrink-0", className),
6873
+ children: [/* @__PURE__ */ jsxs(CardHeader, {
6874
+ className: "px-2 py-0 pt-2 flex space-y-0 border-b border-border bg-muted/50 relative min-h-9",
6875
+ children: [
6876
+ /* @__PURE__ */ jsx(CardTitle, {
6877
+ className: "text-base font-semibold",
6878
+ children: title
6879
+ }),
6880
+ !isCollapsed && /* @__PURE__ */ jsx(Input, {
6881
+ className: "border-none shadow-none rounded-sm text-sm p-0 h-6.5",
6882
+ variant: "simple",
6883
+ placeholder: "Search...",
6884
+ value: searchQuery,
6885
+ onChange: (e) => setSearchQuery(e.target.value)
6886
+ }),
6887
+ /* @__PURE__ */ jsx(Button, {
6888
+ variant: "ghost",
6889
+ size: "iconSm",
6890
+ onClick: () => {
6891
+ if (!isCollapsed) setSearchQuery("");
6892
+ setIsCollapsed(!isCollapsed);
6893
+ },
6894
+ title: isCollapsed ? "Expand slicer" : "Collapse slicer",
6895
+ className: "size-7 absolute top-1 right-9 text-muted-foreground",
6896
+ children: /* @__PURE__ */ jsx(ChevronUpIcon$1, { className: cn(isCollapsed && "rotate-180") })
6897
+ }),
6898
+ /* @__PURE__ */ jsx(Button, {
6899
+ variant: "ghost",
6900
+ size: "iconSm",
6901
+ disabled: selectedValues.size === 0,
6902
+ onClick: handleClear,
6903
+ title: "Clear filter",
6904
+ className: "size-7 absolute top-1 right-1 text-muted-foreground",
6905
+ children: /* @__PURE__ */ jsx(FilterX, {})
6906
+ })
6907
+ ]
6908
+ }), !isCollapsed && /* @__PURE__ */ jsxs(CardContent, {
6909
+ className: "p-1 flex flex-col",
6910
+ children: [/* @__PURE__ */ jsx(Button, {
6911
+ variant: "ghost",
6912
+ size: "xs",
6913
+ className: "w-full justify-start px-2 py-1 rounded-sm text-sm font-normal",
6914
+ onClick: handleSelectAll,
6915
+ children: searchQuery.length > 0 ? /* @__PURE__ */ jsx(Checkbox, {
6916
+ readOnly: true,
6917
+ checked: isAnyFilteredSelected,
6918
+ disabled: filteredOptions.length === 0,
6919
+ label: "Select Search Results",
6920
+ className: "pointer-events-none",
6921
+ checkboxSize: "sm",
6922
+ variant: areAllFilteredSelected ? "simple" : "default",
6923
+ iconStyle: areAllFilteredSelected ? "simple" : "solo",
6924
+ checkIcon: areAllFilteredSelected ? "check" : "square"
6925
+ }) : /* @__PURE__ */ jsx(Checkbox, {
6926
+ readOnly: true,
6927
+ checked: selectedValues.size > 0,
6928
+ disabled: filterValues.length === 0,
6929
+ label: "Select All",
6930
+ className: "pointer-events-none",
6931
+ checkboxSize: "sm",
6932
+ variant: areAllSelected ? "simple" : "default",
6933
+ iconStyle: areAllSelected ? "simple" : "solo",
6934
+ checkIcon: areAllSelected ? "check" : "square"
6935
+ })
6936
+ }), /* @__PURE__ */ jsx("div", {
6937
+ className: `px-2 py-1 h-(--optionsHeight) shrink-0 overflow-auto`,
6938
+ style: { "--optionsHeight": `${optionsHeight}px` },
6939
+ children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", {
6940
+ className: "flex size-full items-center justify-center text-sm",
6941
+ children: filterValues.length === 0 ? "No options available" : "No results found"
6942
+ }) : /* @__PURE__ */ jsx(Fragment, { children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
6943
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-full" }),
6944
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-3/4" }),
6945
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-5/6" })
6946
+ ] }) : /* @__PURE__ */ jsx(Fragment, { children: filteredOptions.map((option) => /* @__PURE__ */ jsx(SlicerItem, {
6947
+ option,
6948
+ isSelected: selectedValues.has(option.value),
6949
+ onToggle: handleOptionToggle
6950
+ }, option.value)) }) })
6951
+ })]
6952
+ })]
6698
6953
  });
6699
6954
  }
6955
+ const SlicerItem = ({ option, isSelected, onToggle }) => {
6956
+ return /* @__PURE__ */ jsx(Checkbox, {
6957
+ checked: isSelected,
6958
+ onChange: (e) => onToggle(option.value, e.target.checked),
6959
+ checkIcon: "check",
6960
+ checkboxSize: "sm",
6961
+ className: cn("whitespace-nowrap py-px text-sm", !option.hasMatches && "opacity-50", (option.value == "" || option.value == null || option.value == void 0) && "italic"),
6962
+ label: option.label
6963
+ }, option.value);
6964
+ };
6700
6965
 
6701
6966
  //#endregion
6702
6967
  //#region src/slider/slider.tsx
@@ -6886,5 +7151,5 @@ const ToggleGroupItem = React$1.forwardRef(({ className, children, variant, size
6886
7151
  ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
6887
7152
 
6888
7153
  //#endregion
6889
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, Checkbox, CheckboxCell, Collapse, CollapseContent, CollapseTrigger, ComboboxDemo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandPalette, CommandPaletteDialog, CommandPaletteEmpty, CommandPaletteGroup, CommandPaletteInput, CommandPaletteItem, CommandPaletteList, CommandPaletteSeparator, CommandPaletteShortcut, CommandSeparator, CommandShortcut, ContentFrame, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataGrid, DataGridCell, DataGridCellWrapper, DataGridColumnHeader, DataGridContextMenu, DataGridRow, DataGridSearch, DataGridViewMenu, DateCell, DatePickerDemo, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, GanttCell, GanttTimeline, GanttTimerangePicker, HeaderComponents, HoverCard, HoverCardContent, HoverCardTrigger, Input, Label, Loader, LongTextCell, MarkValueRenderer, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Modal, MultiSelectCell, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberCell, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ReactNodeCell, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectCell, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, ShortTextCell, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, checkboxVariants, cn, commandInputVariants, getCellKey, getCommonPinningStyles, getLineCount, getRowHeightValue, isoToLocalDate, knobVariants, navigationMenuTriggerStyle, parseCellKey, sliderVariants, toast, toggleVariants, useCallbackRef, useDataGrid, useDebouncedCallback, useIsMobile, useSidebar };
7154
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, Checkbox, CheckboxCell, Collapse, CollapseContent, CollapseTrigger, ComboboxDemo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandPalette, CommandPaletteDialog, CommandPaletteEmpty, CommandPaletteGroup, CommandPaletteInput, CommandPaletteItem, CommandPaletteList, CommandPaletteSeparator, CommandPaletteShortcut, CommandSeparator, CommandShortcut, ContentFrame, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataGrid, DataGridCell, DataGridCellWrapper, DataGridColumnHeader, DataGridContextMenu, DataGridRow, DataGridSearch, DataGridViewMenu, DateCell, DatePickerDemo, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, GanttCell, GanttTimeline, GanttTimerangePicker, HeaderComponents, HoverCard, HoverCardContent, HoverCardTrigger, Input, Label, Loader, LongTextCell, MarkValueRenderer, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Modal, MultiSelectCell, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NumberCell, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ReactNodeCell, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectCell, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, ShortTextCell, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slicer, Slider, Spinner, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, checkboxVariants, cn, commandInputVariants, getCellKey, getCommonPinningStyles, getLineCount, getRowHeightValue, isoToLocalDate, knobVariants, navigationMenuTriggerStyle, parseCellKey, sliderVariants, toast, toggleVariants, useCallbackRef, useDataGrid, useDebouncedCallback, useIsMobile, useSidebar };
6890
7155
  //# sourceMappingURL=index.js.map