@rebasepro/ui 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/icons/index.d.ts +1 -1
  2. package/dist/index.css +13 -13
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.es.js +2119 -74
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/index.css +13 -13
  7. package/dist/styles.d.ts +9 -9
  8. package/dist/views/CardView.d.ts +32 -0
  9. package/dist/views/CollectionView/CollectionCardView.d.ts +30 -0
  10. package/dist/views/CollectionView/CollectionKanbanView.d.ts +31 -0
  11. package/dist/views/CollectionView/CollectionListView.d.ts +30 -0
  12. package/dist/views/CollectionView/CollectionTableView.d.ts +37 -0
  13. package/dist/views/CollectionView/CollectionView.d.ts +121 -0
  14. package/dist/views/CollectionView/CollectionViewToolbar.d.ts +31 -0
  15. package/dist/views/CollectionView/CollectionViewTypes.d.ts +106 -0
  16. package/dist/views/CollectionView/DefaultCellRenderer.d.ts +9 -0
  17. package/dist/views/CollectionView/index.d.ts +24 -0
  18. package/dist/views/CollectionView/utils.d.ts +5 -0
  19. package/dist/views/Kanban/Board.d.ts +3 -0
  20. package/dist/views/Kanban/BoardColumn.d.ts +20 -0
  21. package/dist/views/Kanban/BoardColumnTitle.d.ts +8 -0
  22. package/dist/views/Kanban/BoardSortableList.d.ts +14 -0
  23. package/dist/views/Kanban/board_types.d.ts +61 -0
  24. package/dist/views/Kanban/index.d.ts +5 -0
  25. package/dist/views/KanbanView.d.ts +24 -0
  26. package/dist/views/ListView.d.ts +40 -0
  27. package/dist/views/TableView.d.ts +6 -0
  28. package/dist/views/index.d.ts +5 -0
  29. package/package.json +1 -1
  30. package/src/components/Alert.tsx +1 -1
  31. package/src/components/BooleanSwitchWithLabel.tsx +1 -1
  32. package/src/components/Button.tsx +5 -5
  33. package/src/components/Chip.tsx +39 -37
  34. package/src/components/DateTimeField.tsx +2 -2
  35. package/src/components/Dialog.tsx +1 -1
  36. package/src/components/ExpandablePanel.tsx +1 -1
  37. package/src/components/FileUpload.tsx +1 -1
  38. package/src/components/FilterChip.tsx +2 -2
  39. package/src/components/IconButton.tsx +1 -1
  40. package/src/components/MultiSelect.tsx +1 -1
  41. package/src/components/Select.tsx +2 -2
  42. package/src/components/Sheet.tsx +8 -4
  43. package/src/components/Table.tsx +2 -2
  44. package/src/components/TextField.tsx +3 -3
  45. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  46. package/src/icons/index.ts +3 -0
  47. package/src/index.css +13 -13
  48. package/src/index.ts +2 -0
  49. package/src/styles.ts +9 -9
  50. package/src/views/CardView.tsx +281 -0
  51. package/src/views/CollectionView/CollectionCardView.tsx +270 -0
  52. package/src/views/CollectionView/CollectionKanbanView.tsx +251 -0
  53. package/src/views/CollectionView/CollectionListView.tsx +245 -0
  54. package/src/views/CollectionView/CollectionTableView.tsx +229 -0
  55. package/src/views/CollectionView/CollectionView.tsx +388 -0
  56. package/src/views/CollectionView/CollectionViewToolbar.tsx +229 -0
  57. package/src/views/CollectionView/CollectionViewTypes.ts +137 -0
  58. package/src/views/CollectionView/DefaultCellRenderer.tsx +404 -0
  59. package/src/views/CollectionView/index.ts +44 -0
  60. package/src/views/CollectionView/utils.ts +14 -0
  61. package/src/views/Kanban/Board.tsx +421 -0
  62. package/src/views/Kanban/BoardColumn.tsx +135 -0
  63. package/src/views/Kanban/BoardColumnTitle.tsx +47 -0
  64. package/src/views/Kanban/BoardSortableList.tsx +170 -0
  65. package/src/views/Kanban/board_types.ts +70 -0
  66. package/src/views/Kanban/index.tsx +5 -0
  67. package/src/views/KanbanView.tsx +32 -0
  68. package/src/views/ListView.tsx +281 -0
  69. package/src/views/TableView.tsx +7 -0
  70. package/src/views/index.ts +5 -0
  71. package/dist/index.umd.js +0 -6958
  72. package/dist/index.umd.js.map +0 -1
package/dist/index.es.js CHANGED
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import * as React$1 from "react";
3
- import React, { Children, createContext, createRef, forwardRef, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import React, { Children, createContext, createRef, forwardRef, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { clsx } from "clsx";
5
5
  import { twMerge } from "tailwind-merge";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import * as Collapsible from "@radix-ui/react-collapsible";
8
- import { AlertCircleIcon, AlertCircleIcon as AlertCircleIcon$1, AlertTriangleIcon, AlignLeftIcon, AppWindow, ArrowDownToLineIcon, ArrowLeftIcon, ArrowLeftIcon as ArrowLeftIcon$1, ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, ArrowUpIcon, ArrowUpToLineIcon, BoldIcon, BookOpenIcon, CalendarIcon, CalendarIcon as CalendarIcon$1, CheckCircleIcon, CheckIcon, CheckIcon as CheckIcon$1, CheckSquareIcon, ChevronDownIcon, ChevronDownIcon as ChevronDownIcon$1, ChevronLeftIcon, ChevronLeftIcon as ChevronLeftIcon$1, ChevronRightIcon, ChevronRightIcon as ChevronRightIcon$1, ChevronUpIcon, ChevronUpIcon as ChevronUpIcon$1, ChevronsLeftIcon, ChevronsRightIcon, ChevronsUpDownIcon, CircleIcon, CircleUserIcon, CodeIcon, ColumnsIcon, CopyIcon, DatabaseIcon, DownloadIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileIcon, FileSearchIcon, FileTextIcon, FilterIcon, FilterIcon as FilterIcon$1, FilterXIcon, FlagIcon, FolderIcon, FolderPlusIcon, FolderUpIcon, FunctionSquareIcon, GitBranchIcon, GlobeIcon, HashIcon, Heading1Icon, Heading2Icon, Heading3Icon, HelpCircleIcon, HistoryIcon, HomeIcon, ImageIcon, ImageOffIcon, InfoIcon, ItalicIcon, KanbanIcon, KeyIcon, KeyRoundIcon, LanguagesIcon, LayoutGridIcon, LinkIcon, ListIcon, ListOrderedIcon, LoaderIcon, LogOutIcon, MailIcon, Maximize2Icon, MenuIcon, MinusCircleIcon, MinusIcon, MinusIcon as MinusIcon$1, MoonIcon, MoreVerticalIcon, Music2Icon, PanelLeftIcon, PauseIcon, PencilIcon, PhoneIcon, PlayIcon, PlusIcon, QuoteIcon, RefreshCcwIcon, RefreshCwIcon, RefreshCwIcon as RefreshCwIcon$1, RepeatIcon, Rows3Icon, SaveIcon, SearchIcon, SearchIcon as SearchIcon$1, SendIcon, SettingsIcon, ShieldAlertIcon, ShieldIcon, ShoppingCartIcon, SlidersHorizontalIcon, SquareIcon, StarIcon, StrikethroughIcon, SunIcon, SunMoonIcon, TableIcon, TagIcon, TerminalIcon, TextIcon, Trash2Icon, TypeIcon, UnderlineIcon, UndoIcon, UploadCloudIcon, UploadIcon, UserCheckIcon, UserIcon, VideoIcon, VoteIcon, Wand2Icon, XCircleIcon, XIcon, XIcon as XIcon$1, icons as lucideIcons } from "lucide-react";
8
+ import { AlertCircleIcon, AlertCircleIcon as AlertCircleIcon$1, AlertTriangleIcon, AlignLeftIcon, AppWindow, ArrowDownToLineIcon, ArrowLeftIcon, ArrowLeftIcon as ArrowLeftIcon$1, ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, ArrowUpIcon, ArrowUpToLineIcon, BoldIcon, BookOpenIcon, CalendarIcon, CalendarIcon as CalendarIcon$1, CheckCircleIcon, CheckIcon, CheckIcon as CheckIcon$1, CheckSquareIcon, ChevronDownIcon, ChevronDownIcon as ChevronDownIcon$1, ChevronLeftIcon, ChevronLeftIcon as ChevronLeftIcon$1, ChevronRightIcon, ChevronRightIcon as ChevronRightIcon$1, ChevronUpIcon, ChevronUpIcon as ChevronUpIcon$1, ChevronsLeftIcon, ChevronsRightIcon, ChevronsUpDownIcon, CircleIcon, CircleUserIcon, CodeIcon, ColumnsIcon, CopyIcon, DatabaseIcon, DownloadIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileIcon, FileSearchIcon, FileTextIcon, FilterIcon, FilterIcon as FilterIcon$1, FilterXIcon, FlagIcon, FolderIcon, FolderPlusIcon, FolderUpIcon, FunctionSquareIcon, GitBranchIcon, GlobeIcon, HashIcon, Heading1Icon, Heading2Icon, Heading3Icon, HelpCircleIcon, HistoryIcon, HomeIcon, ImageIcon, ImageIcon as ImageIcon$1, ImageOffIcon, InfoIcon, ItalicIcon, Kanban, KanbanIcon, KeyIcon, KeyRoundIcon, LanguagesIcon, LayoutGrid, LayoutGridIcon, LayoutList, Link2Icon, LinkIcon, ListIcon, ListOrderedIcon, LoaderIcon, LockIcon, LogOutIcon, MailIcon, Maximize2Icon, MenuIcon, MinusCircleIcon, MinusIcon, MinusIcon as MinusIcon$1, MoonIcon, MoreVerticalIcon, Music2Icon, PanelLeftIcon, PauseIcon, PencilIcon, PhoneIcon, PlayIcon, PlusIcon, QuoteIcon, RefreshCcwIcon, RefreshCwIcon, RefreshCwIcon as RefreshCwIcon$1, RepeatIcon, Rows3Icon, SaveIcon, SearchIcon, SearchIcon as SearchIcon$1, SendIcon, Settings2, SettingsIcon, ShieldAlertIcon, ShieldIcon, ShoppingCartIcon, SlidersHorizontalIcon, SquareIcon, StarIcon, StrikethroughIcon, SunIcon, SunMoonIcon, Table2, TableIcon, TagIcon, TerminalIcon, TextIcon, Trash2Icon, TypeIcon, UnderlineIcon, UndoIcon, UploadCloudIcon, UploadIcon, UserCheckIcon, UserIcon, UserPlus, VideoIcon, VoteIcon, Wand2Icon, XCircleIcon, XIcon, XIcon as XIcon$1, icons as lucideIcons } from "lucide-react";
9
9
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
10
10
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
11
11
  import * as DialogPrimitive from "@radix-ui/react-dialog";
@@ -23,13 +23,15 @@ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
23
23
  import * as SelectPrimitive from "@radix-ui/react-select";
24
24
  import * as SliderPrimitive from "@radix-ui/react-slider";
25
25
  import * as ReactDOM from "react-dom";
26
+ import { createPortal } from "react-dom";
26
27
  import * as TabsPrimitive from "@radix-ui/react-tabs";
27
28
  import { FixedSizeList } from "react-window";
28
29
  import useMeasure from "react-use-measure";
29
- import { SortableContext, arrayMove, horizontalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
30
- import { DndContext, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
30
+ import { SortableContext, arrayMove, horizontalListSortingStrategy, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
31
+ import { DndContext, DragOverlay, PointerSensor, closestCenter, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
31
32
  import * as Portal from "@radix-ui/react-portal";
32
33
  import { Slot } from "@radix-ui/react-slot";
34
+ import { CSS } from "@dnd-kit/utilities";
33
35
  //#region src/util/cls.ts
34
36
  function cls(...classes) {
35
37
  return twMerge(clsx(classes));
@@ -187,15 +189,15 @@ function SelectInputLabel({ children, error }) {
187
189
  //#region src/styles.ts
188
190
  var focusedDisabled = "focus-visible:ring-0 focus-visible:ring-offset-0";
189
191
  var focusedInvisibleMixin = "focus:bg-opacity-70 focus:bg-surface-accent-100 focus:dark:bg-surface-900 focus:dark:bg-opacity-60 focus:bg-surface-accent-100/70 dark:focus:bg-surface-900/60";
190
- var focusedClasses = "z-30 outline-hidden outline-none ring-2 ring-primary ring-opacity-75 ring-primary/75 ring-offset-0 ring-offset-transparent ";
191
- var fieldBackgroundMixin = "bg-opacity-50 bg-surface-accent-200 bg-surface-accent-200/50 dark:bg-surface-900 dark:bg-opacity-100 dark:bg-surface-900/100";
192
- var fieldBackgroundInvisibleMixin = "bg-opacity-0 bg-surface-accent-100 dark:bg-surface-900 dark:bg-opacity-0 bg-surface-accent-200/0 dark:bg-surface-900/0";
193
- var fieldBackgroundDisabledMixin = "dark:bg-surface-900 bg-opacity-50 dark:bg-opacity-90 bg-surface-accent-200/50 dark:bg-surface-900/90";
194
- var fieldBackgroundHoverMixin = "hover:bg-opacity-70 dark:hover:bg-surface-700 dark:hover:bg-opacity-40 hover:bg-surface-accent-200/70 hover:dark:bg-surface-700/40";
195
- var defaultBorderMixin = "border-surface-200/60 dark:border-surface-700/60 ";
196
- var paperMixin = "bg-white rounded-md dark:bg-surface-800 border border-surface-200/60 dark:border-surface-700/60";
197
- var cardMixin = "bg-white dark:bg-surface-900 rounded-md border border-surface-200/60 dark:border-surface-700/60 m-1 -p-1";
198
- var cardClickableMixin = "hover:bg-surface-accent-100 dark:hover:bg-surface-800 hover:ring-1 hover:ring-primary/50 hover:shadow-sm cursor-pointer hover:bg-primary/10 dark:hover:bg-primary/10 transition-all duration-150";
192
+ var focusedClasses = "z-30 outline-hidden outline-none ring-2 ring-primary ring-opacity-50 ring-primary/50 ring-offset-0 ring-offset-transparent ";
193
+ var fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-black/30";
194
+ var fieldBackgroundInvisibleMixin = "bg-surface-accent-200/0 dark:bg-black/0";
195
+ var fieldBackgroundDisabledMixin = "bg-surface-accent-200/50 dark:bg-black/20";
196
+ var fieldBackgroundHoverMixin = "hover:bg-surface-accent-200/70 hover:dark:bg-black/50";
197
+ var defaultBorderMixin = "border-surface-200 dark:border-surface-700/60 ";
198
+ var paperMixin = "bg-white rounded-lg dark:bg-surface-900 border border-surface-200 dark:border-surface-700";
199
+ var cardMixin = "bg-white dark:bg-surface-900 rounded-lg border border-surface-200 dark:border-surface-700";
200
+ var cardClickableMixin = "hover:bg-primary/5 dark:hover:bg-primary/5 cursor-pointer transition-colors duration-150";
199
201
  var cardSelectedMixin = "bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75";
200
202
  //#endregion
201
203
  //#region src/hooks/PortalContainerContext.tsx
@@ -452,7 +454,7 @@ var Alert = ({ children, onDismiss, color = "info", size = "medium", action, out
452
454
  const classes = getColorClasses(color);
453
455
  return /* @__PURE__ */ jsxs("div", {
454
456
  style,
455
- className: cls(getSizeClasses(size), "w-full", "font-medium", "rounded-md flex items-center gap-2", classes, outerClassName),
457
+ className: cls(getSizeClasses(size), "w-full", "font-medium", "rounded-lg flex items-center gap-2", classes, outerClassName),
456
458
  children: [
457
459
  /* @__PURE__ */ jsx("div", {
458
460
  className: cls("grow", className),
@@ -553,7 +555,7 @@ var BooleanSwitchWithLabel = function BooleanSwitchWithLabel({ value, position =
553
555
  "aria-disabled": disabled || void 0,
554
556
  "aria-labelledby": label ? switchLabelId : void 0,
555
557
  tabIndex: -1,
556
- className: cls(!invisible && "bg-opacity-50 bg-surface-accent-200 bg-surface-accent-200/50 dark:bg-surface-900 dark:bg-opacity-100 dark:bg-surface-900/100", !invisible && (disabled ? "dark:bg-surface-900 bg-opacity-50 dark:bg-opacity-90 bg-surface-accent-200/50 dark:bg-surface-900/90" : "hover:bg-opacity-70 dark:hover:bg-surface-700 dark:hover:bg-opacity-40 hover:bg-surface-accent-200/70 hover:dark:bg-surface-700/40"), disabled ? "cursor-default" : "cursor-pointer", "rounded-md max-w-full justify-between box-border relative inline-flex items-center", !invisible && focus && !disabled ? focusedClasses : "", error ? "text-red-500 dark:text-red-600" : focus && !disabled ? "text-primary" : !disabled ? "text-text-primary dark:text-text-primary-dark" : "text-text-secondary dark:text-text-secondary-dark", {
558
+ className: cls(!invisible && "bg-surface-accent-200/50 dark:bg-black/30", !invisible && (disabled ? "bg-surface-accent-200/50 dark:bg-black/20" : "hover:bg-surface-accent-200/70 hover:dark:bg-black/50"), disabled ? "cursor-default" : "cursor-pointer", "rounded-lg max-w-full justify-between box-border relative inline-flex items-center", !invisible && focus && !disabled ? focusedClasses : "", error ? "text-red-500 dark:text-red-600" : focus && !disabled ? "text-primary" : !disabled ? "text-text-primary dark:text-text-primary-dark" : "text-text-secondary dark:text-text-secondary-dark", {
557
559
  "min-h-[28px]": size === "smallest",
558
560
  "min-h-[32px]": size === "small",
559
561
  "min-h-[44px]": size === "medium",
@@ -584,14 +586,14 @@ var BooleanSwitchWithLabel = function BooleanSwitchWithLabel({ value, position =
584
586
  //#endregion
585
587
  //#region src/components/Button.tsx
586
588
  var ButtonInner = React.memo(React.forwardRef(({ children, className, variant = "filled", disabled = false, size = "medium", startIcon = null, fullWidth = false, component: Component, color = "neutral", ...props }, ref) => {
587
- const baseClasses = "typography-button h-fit rounded-md whitespace-nowrap inline-flex items-center justify-center p-2 px-4 focus:outline-none transition-all ease-in-out duration-150 gap-2 active:scale-[0.98]";
589
+ const baseClasses = "typography-button h-fit rounded-lg whitespace-nowrap inline-flex items-center justify-center p-2 px-4 focus:outline-none transition-colors ease-in-out duration-150 gap-2";
588
590
  const buttonClasses = cls({
589
591
  "w-full": fullWidth,
590
592
  "w-fit": !fullWidth,
591
- "border border-primary bg-primary focus:ring-primary shadow-sm hover:shadow-md hover:brightness-110 text-white hover:text-white": variant === "filled" && color === "primary" && !disabled,
592
- "border border-secondary bg-secondary focus:ring-secondary shadow-sm hover:shadow-md hover:brightness-110 text-white hover:text-white": variant === "filled" && color === "secondary" && !disabled,
593
- "border border-red-500 bg-red-500 hover:bg-red-600 focus:ring-red-500 shadow-sm hover:shadow-md text-white hover:text-white": variant === "filled" && color === "error" && !disabled,
594
- "border border-surface-accent-200 bg-surface-accent-200 hover:bg-surface-accent-300 focus:ring-surface-accent-400 shadow-sm hover:shadow-md text-text-primary hover:text-text-primary dark:border-surface-accent-700 dark:bg-surface-accent-700 dark:hover:bg-surface-accent-600 dark:text-text-primary-dark hover:dark:text-text-primary-dark": variant === "filled" && color === "text" && !disabled,
593
+ "border border-primary bg-primary focus:ring-primary text-white hover:text-white hover:brightness-105": variant === "filled" && color === "primary" && !disabled,
594
+ "border border-secondary bg-secondary focus:ring-secondary text-white hover:text-white hover:brightness-105": variant === "filled" && color === "secondary" && !disabled,
595
+ "border border-red-500 bg-red-500 hover:bg-red-600 focus:ring-red-500 text-white hover:text-white": variant === "filled" && color === "error" && !disabled,
596
+ "border border-surface-accent-200 bg-surface-accent-200 hover:bg-surface-accent-300 focus:ring-surface-accent-400 text-text-primary hover:text-text-primary dark:border-surface-accent-700 dark:bg-surface-accent-700 dark:hover:bg-surface-accent-600 dark:text-text-primary-dark hover:dark:text-text-primary-dark": variant === "filled" && color === "text" && !disabled,
595
597
  "border border-transparent bg-surface-100 hover:bg-surface-accent-200 text-text-primary dark:bg-surface-700 dark:hover:bg-surface-accent-700 dark:text-text-primary-dark hover:text-text-primary dark:text-text-primary-dark hover:dark:text-text-primary-dark": variant === "filled" && color === "neutral" && !disabled,
596
598
  "border border-transparent text-primary hover:text-primary hover:bg-surface-accent-200 hover:bg-opacity-75 hover:bg-surface-accent-200/75 dark:hover:bg-surface-accent-800": variant === "text" && color === "primary" && !disabled,
597
599
  "border border-transparent text-secondary hover:text-secondary hover:bg-surface-accent-200 hover:bg-opacity-75 hover:bg-surface-accent-200/75 dark:hover:bg-surface-accent-800": variant === "text" && color === "secondary" && !disabled,
@@ -648,7 +650,7 @@ var Card = React.forwardRef(({ children, className, onClick, style, ...props },
648
650
  role: onClick ? "button" : void 0,
649
651
  tabIndex: onClick ? 0 : void 0,
650
652
  onClick,
651
- className: cls(cardMixin, onClick && "hover:bg-surface-accent-100 dark:hover:bg-surface-800 hover:ring-1 hover:ring-primary/50 hover:shadow-sm cursor-pointer hover:bg-primary/10 dark:hover:bg-primary/10 transition-all duration-150", className),
653
+ className: cls(cardMixin, onClick && "hover:bg-primary/5 dark:hover:bg-primary/5 cursor-pointer transition-colors duration-150", className),
652
654
  style,
653
655
  ...props,
654
656
  children
@@ -1007,10 +1009,10 @@ Checkbox.displayName = "Checkbox";
1007
1009
  //#endregion
1008
1010
  //#region src/components/Chip.tsx
1009
1011
  var sizeClassNames = {
1010
- smallest: "px-1.5 text-xs",
1011
- small: "px-2 py-0.5 text-sm",
1012
- medium: "px-3 py-1 text-sm",
1013
- large: "px-4 py-1.5 text-sm"
1012
+ smallest: "px-1.5 py-px text-[10px]",
1013
+ small: "px-2 py-0.5 text-xs",
1014
+ medium: "px-2.5 py-0.5 text-xs",
1015
+ large: "px-3 py-1 text-xs"
1014
1016
  };
1015
1017
  /**
1016
1018
  * Detect if the app is currently in dark mode by checking the
@@ -1020,45 +1022,48 @@ function isDarkMode() {
1020
1022
  return typeof document !== "undefined" && document.documentElement.classList.contains("dark");
1021
1023
  }
1022
1024
  /**
1025
+ * Helper to generate rgba from hex or standard colors.
1026
+ */
1027
+ function getRgba(hex, alpha) {
1028
+ if (!hex || !hex.startsWith("#")) return hex;
1029
+ let color = hex.slice(1);
1030
+ if (color.length === 3) color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2];
1031
+ return `rgba(${parseInt(color.slice(0, 2), 16)}, ${parseInt(color.slice(2, 4), 16)}, ${parseInt(color.slice(4, 6), 16)}, ${alpha})`;
1032
+ }
1033
+ /**
1023
1034
  * @group Preview components
1024
1035
  */
1025
- function Chip({ children, colorScheme, error, outlined, onClick, icon, size = "large", className, style }) {
1036
+ function Chip({ children, colorScheme, error, outlined, onClick, icon, size = "medium", className, style }) {
1026
1037
  const usedColorScheme = typeof colorScheme === "string" ? getColorSchemeForKey(colorScheme) : colorScheme;
1027
1038
  const dark = isDarkMode();
1028
- const getRgba = (hex, alpha) => {
1029
- if (!hex || !hex.startsWith("#")) return hex;
1030
- let color = hex.slice(1);
1031
- if (color.length === 3) color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2];
1032
- return `rgba(${parseInt(color.slice(0, 2), 16)}, ${parseInt(color.slice(2, 4), 16)}, ${parseInt(color.slice(4, 6), 16)}, ${alpha})`;
1033
- };
1039
+ const hasScheme = error || usedColorScheme;
1034
1040
  let textColor = "";
1035
1041
  let bgColor = "";
1036
1042
  let border = "";
1037
1043
  if (error) textColor = dark ? "#f87171" : "#dc2626";
1038
1044
  else if (usedColorScheme) textColor = dark && usedColorScheme.darkText ? usedColorScheme.darkText : usedColorScheme.text;
1039
- else textColor = dark ? "#d4d4d4" : "#404040";
1040
- if (outlined) {
1041
- bgColor = getRgba(textColor, dark ? .12 : .06);
1042
- border = `1px solid ${getRgba(textColor, dark ? .25 : .18)}`;
1043
- } else if (error) {
1044
- bgColor = dark ? "rgba(220, 38, 38, 0.2)" : "rgba(239, 68, 68, 0.15)";
1045
- border = `1px solid ${dark ? "rgba(220, 38, 38, 0.4)" : "rgba(239, 68, 68, 0.3)"}`;
1046
- } else if (usedColorScheme) bgColor = dark && usedColorScheme.darkColor ? usedColorScheme.darkColor : usedColorScheme.color;
1047
- else {
1048
- bgColor = dark ? "#1f1f1f" : "#f4f4f5";
1049
- border = `1px solid ${dark ? "#2e2e30" : "#e4e4e7"}`;
1045
+ if (hasScheme) {
1046
+ if (outlined) {
1047
+ bgColor = getRgba(textColor, dark ? .1 : .06);
1048
+ border = `1px solid ${getRgba(textColor, dark ? .2 : .14)}`;
1049
+ } else if (error) {
1050
+ bgColor = dark ? "rgba(220, 38, 38, 0.15)" : "rgba(239, 68, 68, 0.1)";
1051
+ border = `1px solid ${dark ? "rgba(220, 38, 38, 0.3)" : "rgba(239, 68, 68, 0.2)"}`;
1052
+ } else if (usedColorScheme) bgColor = dark && usedColorScheme.darkColor ? usedColorScheme.darkColor : usedColorScheme.color;
1050
1053
  }
1051
1054
  return /* @__PURE__ */ jsxs("div", {
1052
- className: cls("rounded-lg max-w-full w-max h-fit font-regular inline-flex gap-1", "text-ellipsis", "items-center", onClick ? "cursor-pointer hover:bg-surface-accent-300 dark:hover:bg-surface-accent-700" : "", sizeClassNames[size], className),
1055
+ className: cls("rounded-lg max-w-full w-max h-fit font-medium inline-flex gap-1", "text-ellipsis", "items-center", "transition-colors duration-150", !hasScheme && "bg-surface-100 dark:bg-surface-800 text-text-secondary dark:text-text-secondary-dark border border-surface-200 dark:border-surface-700", !hasScheme && outlined && "bg-transparent dark:bg-transparent", onClick ? "cursor-pointer hover:bg-primary/5 dark:hover:bg-primary/5" : "", sizeClassNames[size], className),
1053
1056
  onClick,
1054
1057
  style: {
1055
- backgroundColor: bgColor,
1056
- color: textColor,
1057
- border: border || void 0,
1058
+ ...hasScheme ? {
1059
+ backgroundColor: bgColor,
1060
+ color: textColor,
1061
+ border: border || void 0
1062
+ } : {},
1058
1063
  overflow: "hidden",
1059
1064
  ...style
1060
1065
  },
1061
- children: [children, icon]
1066
+ children: [icon, children]
1062
1067
  });
1063
1068
  }
1064
1069
  //#endregion
@@ -1247,7 +1252,7 @@ var colorClasses$1 = "text-surface-accent-500 visited:text-surface-accent-500 da
1247
1252
  var sizeClasses$1 = {
1248
1253
  medium: "w-10 !h-10 min-w-10 min-h-10",
1249
1254
  small: "w-8 !h-8 min-w-8 min-h-8",
1250
- smallest: "w-6 !h-6 min-w-6 min-h-6",
1255
+ smallest: "w-7 !h-7 min-w-7 min-h-7",
1251
1256
  large: "w-12 !h-12 min-w-12 min-h-12"
1252
1257
  };
1253
1258
  var shapeClasses = {
@@ -1389,7 +1394,7 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
1389
1394
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1390
1395
  /* @__PURE__ */ jsx("style", { children: inputStyles }),
1391
1396
  /* @__PURE__ */ jsxs("div", {
1392
- className: cls("rounded-md relative max-w-full", !invisible && "bg-opacity-50 bg-surface-accent-200 bg-surface-accent-200/50 dark:bg-surface-900 dark:bg-opacity-100 dark:bg-surface-900/100", disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, {
1397
+ className: cls("rounded-lg relative max-w-full", !invisible && "bg-surface-accent-200/50 dark:bg-black/30", disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, {
1393
1398
  "min-h-[28px]": size === "smallest",
1394
1399
  "min-h-[32px]": size === "small",
1395
1400
  "min-h-[44px]": size === "medium",
@@ -1413,7 +1418,7 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
1413
1418
  onFocus: handleFocus,
1414
1419
  onBlur: handleBlur,
1415
1420
  disabled,
1416
- className: cls("w-full outline-hidden bg-transparent leading-normal text-base px-3", clearable ? "pr-14" : "pr-12", "rounded-md", {
1421
+ className: cls("w-full outline-hidden bg-transparent leading-normal text-base px-3", clearable ? "pr-14" : "pr-12", "rounded-lg", {
1417
1422
  "min-h-[28px]": size === "smallest",
1418
1423
  "min-h-[32px]": size === "small",
1419
1424
  "min-h-[44px]": size === "medium",
@@ -1519,7 +1524,7 @@ var Dialog = ({ open, onOpenChange, children, className, containerClassName, ful
1519
1524
  "aria-describedby": ariaDescribedby,
1520
1525
  className: cls("relative h-full outline-none flex justify-center items-center z-60 opacity-100 transition-all duration-200 ease-in-out"),
1521
1526
  children: /* @__PURE__ */ jsx("div", {
1522
- className: cls(paperMixin, "rounded-2xl", "z-60", "relative", "overflow-hidden", "outline-none focus:outline-none", fullWidth && !fullScreen ? "w-11/12" : void 0, fullHeight && !fullScreen ? "h-full" : void 0, "text-surface-accent-900 dark:text-white", "justify-center items-center", fullScreen ? "h-screen w-screen" : "max-h-[90vh] shadow-xl", "ease-in-out duration-200", scrollable && "overflow-y-auto", displayed && open ? "opacity-100 scale-100" : "opacity-0 scale-[0.97]", maxWidth && !fullScreen ? widthClasses[maxWidth] : void 0, className),
1527
+ className: cls(paperMixin, "rounded-2xl", "z-60", "relative", "overflow-hidden", "outline-none focus:outline-none", fullWidth && !fullScreen ? "w-11/12" : void 0, fullHeight && !fullScreen ? "h-full" : void 0, "text-surface-accent-900 dark:text-white", "justify-center items-center", fullScreen ? "h-screen w-screen" : "max-h-[90vh] shadow-lg", "ease-in-out duration-200", scrollable && "overflow-y-auto", displayed && open ? "opacity-100 scale-100" : "opacity-0 scale-[0.97]", maxWidth && !fullScreen ? widthClasses[maxWidth] : void 0, className),
1523
1528
  children
1524
1529
  })
1525
1530
  })]
@@ -1606,7 +1611,7 @@ function ExpandablePanel({ title, children, invisible = false, expanded, onExpan
1606
1611
  if (expanded !== void 0) setOpen(expanded);
1607
1612
  }, [expanded]);
1608
1613
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Collapsible.Root, {
1609
- className: cls(!invisible && "border-surface-200/60 dark:border-surface-700/60 border", "rounded-md", "w-full", className),
1614
+ className: cls(!invisible && "border-surface-200 dark:border-surface-700/60 border", "rounded-lg", "w-full", className),
1610
1615
  open,
1611
1616
  onOpenChange: (updatedOpen) => {
1612
1617
  onExpandedChange?.(updatedOpen);
@@ -1615,7 +1620,7 @@ function ExpandablePanel({ title, children, invisible = false, expanded, onExpan
1615
1620
  children: [/* @__PURE__ */ jsx(Collapsible.Trigger, {
1616
1621
  asChild: true,
1617
1622
  children: /* @__PURE__ */ jsxs("div", {
1618
- className: cls("rounded-t flex items-center justify-between w-full min-h-[52px]", "hover:bg-surface-accent-200 hover:bg-opacity-40 hover:bg-surface-accent-200/40 dark:hover:bg-surface-800 dark:hover:bg-opacity-40 dark:hover:bg-surface-800/40 active:bg-surface-accent-300/50 dark:active:bg-surface-700/50", invisible ? "border-b px-2" : "p-4", open ? "py-6" : "py-4", "transition-all duration-200", invisible && "border-surface-200/60 dark:border-surface-700/60 ", asField && "bg-opacity-50 bg-surface-accent-200 bg-surface-accent-200/50 dark:bg-surface-900 dark:bg-opacity-100 dark:bg-surface-900/100", titleClassName, "cursor-pointer"),
1623
+ className: cls("rounded-t flex items-center justify-between w-full min-h-[52px]", "hover:bg-surface-accent-200 hover:bg-opacity-40 hover:bg-surface-accent-200/40 dark:hover:bg-surface-800 dark:hover:bg-opacity-40 dark:hover:bg-surface-800/40 active:bg-surface-accent-300/50 dark:active:bg-surface-700/50", invisible ? "border-b px-2" : "p-4", open ? "py-6" : "py-4", "transition-all duration-200", invisible && "border-surface-200 dark:border-surface-700/60 ", asField && "bg-surface-accent-200/50 dark:bg-black/30", titleClassName, "cursor-pointer"),
1619
1624
  role: "button",
1620
1625
  tabIndex: 0,
1621
1626
  "aria-expanded": open,
@@ -1649,7 +1654,7 @@ function FileUpload({ accept, onFilesAdded, onFilesRejected, maxSize, disabled,
1649
1654
  role: "button",
1650
1655
  "aria-label": typeof title === "string" ? title : typeof uploadDescription === "string" ? uploadDescription : "Upload file",
1651
1656
  "aria-disabled": disabled || void 0,
1652
- className: cls(fieldBackgroundMixin, "flex gap-2", "p-4 box-border relative items-center border-2 border-solid border-transparent outline-hidden rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid", {
1657
+ className: cls(fieldBackgroundMixin, "flex gap-2", "p-4 box-border relative items-center border-2 border-solid border-transparent outline-hidden rounded-lg duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid", {
1653
1658
  "h-44": size === "large",
1654
1659
  "h-28": size === "medium",
1655
1660
  "h-16": size === "small",
@@ -1700,7 +1705,7 @@ var FilterChip = React.forwardRef(function FilterChip({ children, active = false
1700
1705
  type: "button",
1701
1706
  onClick,
1702
1707
  disabled,
1703
- className: cls("inline-flex items-center gap-1 rounded-full", "font-medium whitespace-nowrap select-none shrink-0", "transition-all duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50", sizeClasses[size], active ? "bg-primary/12 text-primary dark:bg-primary/20 dark:text-primary shadow-[inset_0_0_0_1.5px_var(--color-primary)]" : cls("bg-surface-accent-100 text-text-secondary dark:bg-surface-accent-800 dark:text-text-secondary-dark", !disabled && "cursor-pointer hover:bg-surface-accent-200 dark:hover:bg-surface-accent-700"), disabled && "opacity-50 cursor-not-allowed", className),
1708
+ className: cls("inline-flex items-center gap-1 rounded-full", "font-medium whitespace-nowrap select-none shrink-0", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50", sizeClasses[size], active ? "bg-primary/12 text-primary dark:bg-primary/20 dark:text-primary shadow-[inset_0_0_0_1.5px_var(--color-primary)]" : cls("bg-surface-accent-100 text-text-secondary dark:bg-surface-accent-800 dark:text-text-secondary-dark", !disabled && "cursor-pointer hover:bg-primary/5 dark:hover:bg-primary/5"), disabled && "opacity-50 cursor-not-allowed", className),
1704
1709
  ...rest,
1705
1710
  children: [icon, children]
1706
1711
  });
@@ -2053,7 +2058,7 @@ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onV
2053
2058
  }, {
2054
2059
  "px-2": size === "small" || size === "smallest",
2055
2060
  "px-4": size === "medium" || size === "large"
2056
- }, "select-none rounded-md text-sm", "focus:ring-0 focus-visible:ring-0 outline-none focus:outline-none focus-visible:outline-none", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, "relative flex items-center", className, inputClassName),
2061
+ }, "select-none rounded-lg text-sm", "focus:ring-0 focus-visible:ring-0 outline-none focus:outline-none focus-visible:outline-none", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, "relative flex items-center", className, inputClassName),
2057
2062
  children: selectedValues.length > 0 ? /* @__PURE__ */ jsxs("div", {
2058
2063
  className: "flex justify-between items-center w-full",
2059
2064
  children: [/* @__PURE__ */ jsxs("div", {
@@ -2289,7 +2294,7 @@ function ResizablePanels({ firstPanel, secondPanel, showFirstPanel = true, showS
2289
2294
  children: firstPanel
2290
2295
  }),
2291
2296
  !stacked && showFirstPanel && showSecondPanel && /* @__PURE__ */ jsx("div", {
2292
- className: cls("relative z-10 flex flex-shrink-0 items-center justify-center", "border-surface-200/60 dark:border-surface-700/60 ", isHorizontal ? "border-l w-px h-full cursor-col-resize" : "border-t h-px w-full cursor-row-resize"),
2297
+ className: cls("relative z-10 flex flex-shrink-0 items-center justify-center", "border-surface-200 dark:border-surface-700/60 ", isHorizontal ? "border-l w-px h-full cursor-col-resize" : "border-t h-px w-full cursor-row-resize"),
2293
2298
  onMouseDown: handleResizeStart,
2294
2299
  children: /* @__PURE__ */ jsx("div", {
2295
2300
  className: cls("absolute flex items-center justify-center group", isHorizontal ? "w-4 h-full cursor-col-resize top-0" : "h-4 w-full cursor-row-resize left-0"),
@@ -2423,7 +2428,7 @@ var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenCh
2423
2428
  children: label
2424
2429
  }) : label,
2425
2430
  /* @__PURE__ */ jsxs("div", {
2426
- className: cls("select-none rounded-md text-sm", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, "relative flex items-center", className, {
2431
+ className: cls("select-none rounded-lg text-sm", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, "relative flex items-center", className, {
2427
2432
  "min-h-[28px]": size === "smallest",
2428
2433
  "min-h-[32px]": size === "small",
2429
2434
  "min-h-[44px]": size === "medium",
@@ -2442,7 +2447,7 @@ var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenCh
2442
2447
  "px-4": size === "large",
2443
2448
  "px-3": size === "medium",
2444
2449
  "px-2": size === "small" || size === "smallest"
2445
- } : "", "outline-hidden focus:outline-hidden", "outline-none focus:outline-none", "select-none rounded-md text-sm", error ? "text-red-500 dark:text-red-600" : "focus:text-text-primary dark:focus:text-text-primary-dark", error ? "border border-red-500 dark:border-red-600" : "", disabled ? "text-surface-accent-600 dark:text-surface-accent-400" : "text-surface-accent-800 dark:text-white", "relative flex flex-row items-center", {
2450
+ } : "", "outline-hidden focus:outline-hidden", "outline-none focus:outline-none", "select-none rounded-lg text-sm", error ? "text-red-500 dark:text-red-600" : "focus:text-text-primary dark:focus:text-text-primary-dark", error ? "border border-red-500 dark:border-red-600" : "", disabled ? "text-surface-accent-600 dark:text-surface-accent-400" : "text-surface-accent-800 dark:text-white", "relative flex flex-row items-center", {
2446
2451
  "min-h-[28px]": size === "smallest",
2447
2452
  "min-h-[32px]": size === "small",
2448
2453
  "min-h-[44px]": size === "medium",
@@ -2571,6 +2576,7 @@ Slider.displayName = "Slider";
2571
2576
  //#region src/components/Sheet.tsx
2572
2577
  var Sheet = ({ children, side = "right", title, modal = true, includeBackgroundOverlay = true, open, onOpenChange, onPointerDownOutside, onInteractOutside, transparent, className, style, overlayClassName, overlayZIndex = "z-50", overlayStyle, portalContainer, ...props }) => {
2573
2578
  const [displayed, setDisplayed] = useState(false);
2579
+ const [contentEl, setContentEl] = useState(null);
2574
2580
  const contextContainer = usePortalContainer();
2575
2581
  const finalContainer = portalContainer ?? contextContainer ?? void 0;
2576
2582
  useEffect(() => {
@@ -2602,17 +2608,19 @@ var Sheet = ({ children, side = "right", title, modal = true, includeBackgroundO
2602
2608
  style: overlayStyle
2603
2609
  }), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
2604
2610
  ...props,
2605
- onFocusCapture: (event) => event.preventDefault(),
2611
+ ref: setContentEl,
2612
+ onOpenAutoFocus: (event) => event.preventDefault(),
2606
2613
  onPointerDownOutside,
2607
2614
  onInteractOutside,
2608
2615
  className: cls("outline-none", borderClass[side], defaultBorderMixin, "transform-gpu", "will-change-transform", "text-surface-accent-900 dark:text-white", "fixed transform z-50 transition-[transform,opacity] ease-in-out", !displayed ? "duration-150" : "duration-100", "outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0", transparent ? "" : "shadow-md bg-white dark:bg-surface-900", side === "top" || side === "bottom" ? "w-full" : "h-full", side === "left" || side === "top" ? "left-0 top-0" : "right-0 bottom-0", displayed && open ? "opacity-100" : "opacity-50", !displayed || !open ? transformValue[side] : "", className),
2609
2616
  style,
2610
2617
  children: [/* @__PURE__ */ jsx(DialogPrimitive.Title, {
2611
- autoFocus: true,
2612
- tabIndex: 0,
2613
2618
  className: "sr-only outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0",
2614
2619
  children: title ?? "Sheet"
2615
- }), children]
2620
+ }), /* @__PURE__ */ jsx(PortalContainerProvider, {
2621
+ container: contentEl,
2622
+ children
2623
+ })]
2616
2624
  })]
2617
2625
  })
2618
2626
  });
@@ -2825,7 +2833,7 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
2825
2833
  onFocus: () => setFocused(true),
2826
2834
  onBlur: () => setFocused(false),
2827
2835
  style: inputStyle,
2828
- className: cls(invisible ? focusedInvisibleMixin : "", "rounded-md resize-none w-full outline-none text-base bg-transparent min-h-[64px] px-3", label ? "pt-8 pb-2" : "py-2", disabled && "outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500", inputClassName)
2836
+ className: cls(invisible ? focusedInvisibleMixin : "", "rounded-lg resize-none w-full outline-none text-base bg-transparent min-h-[64px] px-3", label ? "pt-8 pb-2" : "py-2", disabled && "outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500", inputClassName)
2829
2837
  }) : /* @__PURE__ */ jsx("input", {
2830
2838
  ...inputProps,
2831
2839
  ref: inputRef,
@@ -2835,7 +2843,7 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
2835
2843
  "aria-disabled": disabled || void 0,
2836
2844
  disabled,
2837
2845
  style: inputStyle,
2838
- className: cls("w-full outline-none bg-transparent leading-normal px-3", "rounded-md", "focused:text-text-primary focused:dark:text-text-primary-dark", invisible ? focusedInvisibleMixin : "", disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, {
2846
+ className: cls("w-full outline-none bg-transparent leading-normal px-3", "rounded-lg", "focused:text-text-primary focused:dark:text-text-primary-dark", invisible ? focusedInvisibleMixin : "", disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, {
2839
2847
  "min-h-[28px]": size === "smallest",
2840
2848
  "min-h-[32px]": size === "small",
2841
2849
  "min-h-[44px]": size === "medium",
@@ -2851,7 +2859,7 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
2851
2859
  });
2852
2860
  return /* @__PURE__ */ jsxs("div", {
2853
2861
  ref,
2854
- className: cls("rounded-md relative max-w-full", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, error ? "border border-red-500 dark:border-red-600" : "", {
2862
+ className: cls("rounded-lg relative max-w-full", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin, error ? "border border-red-500 dark:border-red-600" : "", {
2855
2863
  "min-h-[28px]": size === "smallest",
2856
2864
  "min-h-[32px]": size === "small",
2857
2865
  "min-h-[44px]": size === "medium",
@@ -2933,7 +2941,7 @@ function Tabs({ value, onValueChange, className, innerClassName, variant = "stan
2933
2941
  disabled: !showLeftScroll,
2934
2942
  "aria-label": "Scroll tabs left",
2935
2943
  onClick: () => scroll("left"),
2936
- className: cls("absolute left-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showLeftScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-200 dark:hover:bg-surface-800", "bg-surface-50 dark:bg-surface-900 border shadow-sm", "border-surface-200/60 dark:border-surface-700/60 "),
2944
+ className: cls("absolute left-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showLeftScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-200 dark:hover:bg-surface-800", "bg-surface-50 dark:bg-surface-900 border shadow-sm", "border-surface-200 dark:border-surface-700/60 "),
2937
2945
  children: /* @__PURE__ */ jsx(ChevronLeftIcon$1, { size: iconSize.smallest })
2938
2946
  }),
2939
2947
  /* @__PURE__ */ jsx("div", {
@@ -2945,7 +2953,7 @@ function Tabs({ value, onValueChange, className, innerClassName, variant = "stan
2945
2953
  msOverflowStyle: "none"
2946
2954
  },
2947
2955
  children: /* @__PURE__ */ jsx(TabsPrimitive.List, {
2948
- className: cls(variant === "standard" && "inline-flex h-9 items-center justify-start rounded-md bg-surface-50 p-1 text-surface-600 dark:bg-surface-900 dark:text-surface-400 gap-2 border", variant === "standard" && "border-surface-200/60 dark:border-surface-700/60 ", variant === "boxy" && "flex items-center h-full", variant === "pill" && "flex items-center gap-0.5", innerClassName),
2956
+ className: cls(variant === "standard" && "inline-flex h-9 items-center justify-start rounded-md bg-surface-50 p-1 text-surface-600 dark:bg-surface-900 dark:text-surface-400 gap-2 border", variant === "standard" && "border-surface-200 dark:border-surface-700/60 ", variant === "boxy" && "flex items-center h-full", variant === "pill" && "flex items-center gap-0.5", innerClassName),
2949
2957
  children
2950
2958
  })
2951
2959
  }),
@@ -2954,7 +2962,7 @@ function Tabs({ value, onValueChange, className, innerClassName, variant = "stan
2954
2962
  disabled: !showRightScroll,
2955
2963
  "aria-label": "Scroll tabs right",
2956
2964
  onClick: () => scroll("right"),
2957
- className: cls("absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showRightScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-200 dark:hover:bg-surface-800", "bg-surface-50 dark:bg-surface-900 border shadow-sm", "border-surface-200/60 dark:border-surface-700/60 "),
2965
+ className: cls("absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showRightScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-200 dark:hover:bg-surface-800", "bg-surface-50 dark:bg-surface-900 border shadow-sm", "border-surface-200 dark:border-surface-700/60 "),
2958
2966
  children: /* @__PURE__ */ jsx(ChevronRightIcon$1, { size: iconSize.smallest })
2959
2967
  })
2960
2968
  ]
@@ -2973,7 +2981,7 @@ function Tab({ value, className, innerClassName, children, disabled }) {
2973
2981
  //#endregion
2974
2982
  //#region src/components/Table.tsx
2975
2983
  var Table = React.memo(({ children, className, style, ...rest }) => /* @__PURE__ */ jsx("table", {
2976
- className: cls("text-left text-surface-900 dark:text-white rounded-md overflow-x-auto", className),
2984
+ className: cls("text-left text-surface-900 dark:text-white rounded-lg overflow-x-auto", className),
2977
2985
  style,
2978
2986
  ...rest,
2979
2987
  children
@@ -2993,7 +3001,7 @@ var TableHeader = React.memo(({ children, className, ...rest }) => /* @__PURE__
2993
3001
  var TableRow = React.memo(({ children, className, onClick, style, ...rest }) => /* @__PURE__ */ jsx("tr", {
2994
3002
  onClick,
2995
3003
  style,
2996
- className: cls("bg-white dark:bg-surface-900", onClick ? "hover:bg-surface-accent-100 dark:hover:bg-surface-accent-800 cursor-pointer" : "", className),
3004
+ className: cls("bg-white dark:bg-surface-900", onClick ? "hover:bg-primary/5 dark:hover:bg-primary/5 cursor-pointer" : "", className),
2997
3005
  ...rest,
2998
3006
  children
2999
3007
  }));
@@ -3620,7 +3628,7 @@ var VirtualTableRow = React.memo(function VirtualTableRow({ rowData, rowIndex, c
3620
3628
  ]);
3621
3629
  return /* @__PURE__ */ jsx("div", {
3622
3630
  className: cls("flex min-w-full text-sm border-b border-surface-200/60 dark:border-surface-700/60 dark:bg-surface-800", rowClassName ? rowClassName(rowData) : "", {
3623
- "hover:!bg-surface-50/75 dark:hover:!bg-surface-800/75": hoverRow,
3631
+ "hover:!bg-primary/[0.03] dark:hover:!bg-primary/5": hoverRow,
3624
3632
  "cursor-pointer ": onRowClick
3625
3633
  }),
3626
3634
  onClick,
@@ -6086,6 +6094,2043 @@ function HandleIcon() {
6086
6094
  });
6087
6095
  }
6088
6096
  //#endregion
6089
- export { Alert, AlertCircleIcon, AlertTriangleIcon, AlignLeftIcon, AppWindow, ArrowDownToLineIcon, ArrowLeftIcon, ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, ArrowUpToLineIcon, Autocomplete, AutocompleteItem, Avatar, Badge, BoldIcon, BookOpenIcon, BooleanSwitch, BooleanSwitchWithLabel, Button, CHIP_COLORS, CalendarIcon, Card, CenteredView, CheckCircleIcon, CheckIcon, CheckSquareIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ChevronsUpDownIcon, Chip, CircleIcon, CircleUserIcon, CircularProgress, CircularProgressCenter, CodeIcon, Collapse, ColorPicker, ColumnsIcon, Container, CopyIcon, DatabaseIcon, DateTimeField, DebouncedTextField, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, ErrorBoundary, ExpandablePanel, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileIcon, FileSearchIcon, FileTextIcon, FileUpload, FilterChip, FilterIcon, FilterXIcon, FlagIcon, FolderIcon, FolderPlusIcon, FolderUpIcon, FunctionSquareIcon, GitBranchIcon, GitHubIcon, GlobeIcon, HandleIcon, HashIcon, Heading1Icon, Heading2Icon, Heading3Icon, HelpCircleIcon, HistoryIcon, HomeIcon, IconButton, ImageIcon, ImageOffIcon, InfoIcon, InfoLabel, InputLabel, ItalicIcon, KanbanIcon, KeyIcon, KeyRoundIcon, Label, LanguagesIcon, LayoutGridIcon, LinkIcon, ListIcon, ListOrderedIcon, LoaderIcon, LoadingButton, LogOutIcon, MailIcon, Markdown, Maximize2Icon, Menu, MenuIcon, MenuItem, Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarItemIndicator, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarSubTriggerIndicator, MenubarTrigger, MinusCircleIcon, MinusIcon, MoonIcon, MoreVerticalIcon, MultiSelect, MultiSelectContext, MultiSelectItem, Music2Icon, PanelLeftIcon, Paper, PauseIcon, PencilIcon, PhoneIcon, PlayIcon, PlusIcon, Popover, PopoverPrimitive, Portal, PortalContainerProvider, QuoteIcon, RadioGroup, RadioGroupItem, RefreshCcwIcon, RefreshCwIcon, RepeatIcon, ResizablePanels, Rows3Icon, SaveIcon, SearchBar, SearchIcon, Select, SelectGroup, SelectInputLabel, SelectItem, SendIcon, Separator, SettingsIcon, Sheet, ShieldIcon, ShoppingCartIcon, Skeleton, Slider, SlidersHorizontalIcon, Slot, SquareIcon, StarIcon, StrikethroughIcon, SunIcon, SunMoonIcon, Tab, Table, TableBody, TableCell, TableHeader, TableIcon, TableRow, Tabs, TagIcon, TerminalIcon, TextField, TextIcon, TextareaAutosize, ToggleButtonGroup, Tooltip, Trash2Icon, TypeIcon, Typography, UnderlineIcon, UndoIcon, UploadCloudIcon, UploadIcon, UserCheckIcon, UserIcon, VideoIcon, VirtualTable, VoteIcon, Wand2Icon, XCircleIcon, XIcon, cardClickableMixin, cardMixin, cardSelectedMixin, cls, colorClassesMapping, coolIconKeys, debounce, defaultBorderMixin, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundInvisibleMixin, fieldBackgroundMixin, focusedClasses, focusedDisabled, focusedInvisibleMixin, getColorSchemeForKey, getColorSchemeForSeed, iconKeys, iconSize, keyToIconComponent, lucideIcons, paperMixin, useAutoComplete, useDebounceCallback, useDebounceValue, useDebouncedCallback, useInjectStyles, useOutsideAlerter, usePortalContainer };
6097
+ //#region src/views/ListView.tsx
6098
+ function getEstimatedRowHeight(size) {
6099
+ switch (size) {
6100
+ case "xs": return 44;
6101
+ case "s": return 52;
6102
+ case "m": return 64;
6103
+ case "l": return 76;
6104
+ case "xl": return 88;
6105
+ default: return 64;
6106
+ }
6107
+ }
6108
+ var OVERSCAN_COUNT = 8;
6109
+ var LOAD_MORE_THRESHOLD = 400;
6110
+ function getScrollParent$1(element) {
6111
+ let parent = element?.parentElement ?? null;
6112
+ while (parent) {
6113
+ const style = getComputedStyle(parent);
6114
+ if (style.overflowY === "auto" || style.overflowY === "scroll" || style.overflow === "auto" || style.overflow === "scroll") return parent;
6115
+ parent = parent.parentElement;
6116
+ }
6117
+ return document.documentElement;
6118
+ }
6119
+ function ListView({ data, dataLoading = false, noMoreToLoad = false, dataLoadingError, itemCount, setItemCount, pageSize = 50, paginationEnabled = true, onItemClick, selectedIds, highlightedIds, selectionEnabled = true, onSelectionChange, emptyComponent, size = "m", selectedEntityId, renderRow }) {
6120
+ const containerRef = useRef(null);
6121
+ const isLoadingMore = useRef(false);
6122
+ useEffect(() => {
6123
+ if (!dataLoading) isLoadingMore.current = false;
6124
+ }, [dataLoading]);
6125
+ const estimatedRowHeight = getEstimatedRowHeight(size);
6126
+ const [effectiveScrollTop, setEffectiveScrollTop] = useState(0);
6127
+ const [viewportHeight, setViewportHeight] = useState(800);
6128
+ const paginationStateRef = useRef({
6129
+ paginationEnabled,
6130
+ noMoreToLoad,
6131
+ itemCount,
6132
+ pageSize
6133
+ });
6134
+ useEffect(() => {
6135
+ paginationStateRef.current = {
6136
+ paginationEnabled,
6137
+ noMoreToLoad,
6138
+ itemCount,
6139
+ pageSize
6140
+ };
6141
+ }, [
6142
+ paginationEnabled,
6143
+ noMoreToLoad,
6144
+ itemCount,
6145
+ pageSize
6146
+ ]);
6147
+ useEffect(() => {
6148
+ const el = containerRef.current;
6149
+ if (!el) return;
6150
+ const scrollEl = getScrollParent$1(el);
6151
+ if (!scrollEl) return;
6152
+ let rafId = null;
6153
+ const update = () => {
6154
+ rafId = null;
6155
+ const scrollRect = scrollEl.getBoundingClientRect();
6156
+ const listTopRelative = el.getBoundingClientRect().top - scrollRect.top;
6157
+ setEffectiveScrollTop(Math.max(0, -listTopRelative));
6158
+ setViewportHeight(scrollRect.height);
6159
+ const { paginationEnabled: pe, noMoreToLoad: nm, itemCount: ic, pageSize: ps } = paginationStateRef.current;
6160
+ if (pe && !nm && !isLoadingMore.current && scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight < LOAD_MORE_THRESHOLD) {
6161
+ isLoadingMore.current = true;
6162
+ setItemCount?.((ic ?? ps) + ps);
6163
+ }
6164
+ };
6165
+ const onScroll = () => {
6166
+ if (rafId === null) rafId = requestAnimationFrame(update);
6167
+ };
6168
+ scrollEl.addEventListener("scroll", onScroll, { passive: true });
6169
+ const ro = new ResizeObserver(() => update());
6170
+ ro.observe(scrollEl);
6171
+ update();
6172
+ return () => {
6173
+ scrollEl.removeEventListener("scroll", onScroll);
6174
+ ro.disconnect();
6175
+ if (rafId !== null) cancelAnimationFrame(rafId);
6176
+ };
6177
+ }, [setItemCount]);
6178
+ const totalHeight = data.length * estimatedRowHeight;
6179
+ const startIndex = Math.max(0, Math.floor(effectiveScrollTop / estimatedRowHeight) - OVERSCAN_COUNT);
6180
+ const endIndex = Math.min(data.length, Math.ceil((effectiveScrollTop + viewportHeight) / estimatedRowHeight) + OVERSCAN_COUNT);
6181
+ const visibleData = data.slice(startIndex, endIndex);
6182
+ const offsetY = startIndex * estimatedRowHeight;
6183
+ const footerHeight = dataLoading ? 48 : !dataLoading && noMoreToLoad && data.length > 0 ? 32 : 0;
6184
+ const isInitialLoading = dataLoading && data.length === 0;
6185
+ const isEmpty = !dataLoading && data.length === 0 && !dataLoadingError;
6186
+ const getItemId = useCallback((item) => {
6187
+ if (item && typeof item === "object" && "id" in item) {
6188
+ const id = item.id;
6189
+ return typeof id === "number" ? id : String(id);
6190
+ }
6191
+ return String(item);
6192
+ }, []);
6193
+ const borderMixinClass = "border-surface-200 dark:border-surface-800";
6194
+ return /* @__PURE__ */ jsx("div", {
6195
+ ref: containerRef,
6196
+ className: cls("w-full", selectedEntityId === void 0 && `rounded-lg overflow-hidden border ${borderMixinClass}`),
6197
+ children: dataLoadingError && data.length === 0 ? /* @__PURE__ */ jsx("div", {
6198
+ className: "flex items-center justify-center p-8",
6199
+ children: /* @__PURE__ */ jsxs(Typography, {
6200
+ className: "text-red-500",
6201
+ children: ["Error loading data: ", dataLoadingError.message]
6202
+ })
6203
+ }) : isInitialLoading ? /* @__PURE__ */ jsx("div", {
6204
+ className: "flex items-center justify-center py-12 px-8",
6205
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
6206
+ }) : isEmpty ? /* @__PURE__ */ jsx("div", {
6207
+ className: "w-full flex items-center justify-center py-12 px-8",
6208
+ children: emptyComponent ?? /* @__PURE__ */ jsx(Typography, {
6209
+ variant: "label",
6210
+ color: "secondary",
6211
+ children: "No entries found"
6212
+ })
6213
+ }) : /* @__PURE__ */ jsxs("div", {
6214
+ style: {
6215
+ height: totalHeight + footerHeight,
6216
+ position: "relative"
6217
+ },
6218
+ children: [
6219
+ /* @__PURE__ */ jsx("div", {
6220
+ style: {
6221
+ position: "absolute",
6222
+ top: offsetY,
6223
+ left: 0,
6224
+ right: 0
6225
+ },
6226
+ children: visibleData.map((item, i) => {
6227
+ const actualIndex = startIndex + i;
6228
+ const isLast = actualIndex === data.length - 1;
6229
+ const id = getItemId(item);
6230
+ const selected = selectedIds?.has(id) ?? false;
6231
+ const highlighted = highlightedIds?.has(id) ?? false;
6232
+ const handleClick = (e) => {
6233
+ if ((e.metaKey || e.ctrlKey) && selectionEnabled) {
6234
+ e.preventDefault();
6235
+ onSelectionChange?.(item, !selected);
6236
+ return;
6237
+ }
6238
+ onItemClick?.(item);
6239
+ };
6240
+ const handleSelectionChange = (val) => {
6241
+ onSelectionChange?.(item, val);
6242
+ };
6243
+ return /* @__PURE__ */ jsx(React.Fragment, { children: renderRow({
6244
+ item,
6245
+ index: actualIndex,
6246
+ style: { height: estimatedRowHeight },
6247
+ className: cls(!isLast && "border-b", !isLast && borderMixinClass),
6248
+ selected,
6249
+ highlighted,
6250
+ isLast,
6251
+ onClick: handleClick,
6252
+ onSelectionChange: handleSelectionChange
6253
+ }) }, id || actualIndex);
6254
+ })
6255
+ }),
6256
+ dataLoading && /* @__PURE__ */ jsx("div", {
6257
+ className: "flex items-center justify-center py-3",
6258
+ style: {
6259
+ position: "absolute",
6260
+ top: totalHeight,
6261
+ left: 0,
6262
+ right: 0
6263
+ },
6264
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
6265
+ }),
6266
+ !dataLoading && noMoreToLoad && data.length > 0 && /* @__PURE__ */ jsx("div", {
6267
+ className: "flex items-center justify-center py-2 dark:bg-surface-900",
6268
+ style: {
6269
+ position: "absolute",
6270
+ top: totalHeight,
6271
+ left: 0,
6272
+ right: 0
6273
+ },
6274
+ children: /* @__PURE__ */ jsxs(Typography, {
6275
+ variant: "caption",
6276
+ color: "secondary",
6277
+ children: [
6278
+ "All ",
6279
+ data.length,
6280
+ " entries loaded"
6281
+ ]
6282
+ })
6283
+ })
6284
+ ]
6285
+ })
6286
+ });
6287
+ }
6288
+ //#endregion
6289
+ //#region src/views/CardView.tsx
6290
+ function getGridColumnsClass(size) {
6291
+ switch (size) {
6292
+ case "xs": return "grid-cols-4 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10";
6293
+ case "s": return "grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8";
6294
+ case "m": return "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6";
6295
+ case "l": return "grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-4";
6296
+ case "xl": return "grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3";
6297
+ default: return "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6";
6298
+ }
6299
+ }
6300
+ function getScrollParent(element) {
6301
+ if (!element) return null;
6302
+ let parent = element.parentElement;
6303
+ while (parent) {
6304
+ const overflowY = window.getComputedStyle(parent).overflowY;
6305
+ if (overflowY === "auto" || overflowY === "scroll") return parent;
6306
+ parent = parent.parentElement;
6307
+ }
6308
+ return document.documentElement;
6309
+ }
6310
+ function CardView({ data, dataLoading = false, noMoreToLoad = false, dataLoadingError, itemCount, setItemCount, pageSize = 50, paginationEnabled = true, onItemClick, selectedIds, highlightedIds, selectionEnabled = true, onSelectionChange, onScroll, initialScroll, size = "m", renderCard, emptyComponent }) {
6311
+ const containerRef = useRef(null);
6312
+ const hasRestoredScroll = useRef(false);
6313
+ const isLoadingMore = useRef(false);
6314
+ const paginationStateRef = useRef({
6315
+ paginationEnabled,
6316
+ noMoreToLoad,
6317
+ itemCount,
6318
+ pageSize
6319
+ });
6320
+ useEffect(() => {
6321
+ paginationStateRef.current = {
6322
+ paginationEnabled,
6323
+ noMoreToLoad,
6324
+ itemCount,
6325
+ pageSize
6326
+ };
6327
+ }, [
6328
+ paginationEnabled,
6329
+ noMoreToLoad,
6330
+ itemCount,
6331
+ pageSize
6332
+ ]);
6333
+ useEffect(() => {
6334
+ if (!dataLoading) isLoadingMore.current = false;
6335
+ }, [dataLoading]);
6336
+ useEffect(() => {
6337
+ const el = containerRef.current;
6338
+ if (!el) return;
6339
+ const scrollEl = getScrollParent(el);
6340
+ if (!scrollEl) return;
6341
+ let rafId = null;
6342
+ const update = () => {
6343
+ rafId = null;
6344
+ const { paginationEnabled: pe, noMoreToLoad: nm, itemCount: ic, pageSize: ps } = paginationStateRef.current;
6345
+ if (pe && !nm && !isLoadingMore.current && scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight < 400) {
6346
+ isLoadingMore.current = true;
6347
+ setItemCount?.((ic ?? ps) + ps);
6348
+ }
6349
+ };
6350
+ const onScrollEvent = () => {
6351
+ if (rafId === null) rafId = requestAnimationFrame(update);
6352
+ };
6353
+ scrollEl.addEventListener("scroll", onScrollEvent, { passive: true });
6354
+ const ro = new ResizeObserver(() => update());
6355
+ ro.observe(scrollEl);
6356
+ update();
6357
+ return () => {
6358
+ scrollEl.removeEventListener("scroll", onScrollEvent);
6359
+ ro.disconnect();
6360
+ if (rafId !== null) cancelAnimationFrame(rafId);
6361
+ };
6362
+ }, [setItemCount]);
6363
+ useEffect(() => {
6364
+ if (!containerRef.current || !initialScroll || hasRestoredScroll.current || data.length === 0) return;
6365
+ const scrollEl = getScrollParent(containerRef.current);
6366
+ if (!scrollEl) return;
6367
+ let attempts = 0;
6368
+ const maxAttempts = 5;
6369
+ const tryRestore = () => {
6370
+ if (scrollEl.scrollHeight >= initialScroll || attempts >= maxAttempts) {
6371
+ scrollEl.scrollTop = initialScroll;
6372
+ hasRestoredScroll.current = true;
6373
+ } else {
6374
+ attempts++;
6375
+ requestAnimationFrame(tryRestore);
6376
+ }
6377
+ };
6378
+ requestAnimationFrame(tryRestore);
6379
+ }, [initialScroll, data.length]);
6380
+ const lastScrollOffset = useRef(0);
6381
+ useEffect(() => {
6382
+ const el = containerRef.current;
6383
+ if (!el || !onScroll) return;
6384
+ const scrollEl = getScrollParent(el);
6385
+ if (!scrollEl) return;
6386
+ const handleScroll = () => {
6387
+ const currentOffset = scrollEl.scrollTop;
6388
+ const direction = currentOffset > lastScrollOffset.current ? "forward" : "backward";
6389
+ lastScrollOffset.current = currentOffset;
6390
+ onScroll({
6391
+ scrollDirection: direction,
6392
+ scrollOffset: currentOffset,
6393
+ scrollUpdateWasRequested: false
6394
+ });
6395
+ };
6396
+ scrollEl.addEventListener("scroll", handleScroll, { passive: true });
6397
+ return () => scrollEl.removeEventListener("scroll", handleScroll);
6398
+ }, [onScroll]);
6399
+ const getItemId = useCallback((item) => {
6400
+ if (item && typeof item === "object" && "id" in item) {
6401
+ const id = item.id;
6402
+ return typeof id === "number" ? id : String(id);
6403
+ }
6404
+ return String(item);
6405
+ }, []);
6406
+ const gridColumnsClass = getGridColumnsClass(size);
6407
+ const isInitialLoading = dataLoading && data.length === 0 && !dataLoadingError;
6408
+ const isEmpty = !dataLoading && data.length === 0 && !dataLoadingError;
6409
+ return /* @__PURE__ */ jsx("div", {
6410
+ ref: containerRef,
6411
+ className: "w-full p-4",
6412
+ children: dataLoadingError && data.length === 0 ? /* @__PURE__ */ jsx("div", {
6413
+ className: "h-full flex items-center justify-center p-8",
6414
+ children: /* @__PURE__ */ jsxs(Typography, {
6415
+ className: "text-red-500",
6416
+ children: ["Error loading data: ", dataLoadingError.message]
6417
+ })
6418
+ }) : isInitialLoading ? /* @__PURE__ */ jsx("div", {
6419
+ className: "flex items-center justify-center py-12 px-8",
6420
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
6421
+ }) : isEmpty ? /* @__PURE__ */ jsx("div", {
6422
+ className: "w-full flex items-center justify-center py-12 px-8",
6423
+ children: emptyComponent ?? /* @__PURE__ */ jsx(Typography, {
6424
+ variant: "label",
6425
+ color: "secondary",
6426
+ children: "No entries found"
6427
+ })
6428
+ }) : /* @__PURE__ */ jsxs("div", {
6429
+ className: "max-w-7xl mx-auto",
6430
+ children: [/* @__PURE__ */ jsx("div", {
6431
+ className: cls("grid gap-4", gridColumnsClass),
6432
+ children: data.map((item, index) => {
6433
+ const id = getItemId(item);
6434
+ const selected = selectedIds?.has(id) ?? false;
6435
+ const highlighted = highlightedIds?.has(id) ?? false;
6436
+ const handleClick = (e) => {
6437
+ if ((e.metaKey || e.ctrlKey) && selectionEnabled) {
6438
+ e.preventDefault();
6439
+ onSelectionChange?.(item, !selected);
6440
+ return;
6441
+ }
6442
+ onItemClick?.(item);
6443
+ };
6444
+ const handleSelectionChange = (val) => {
6445
+ onSelectionChange?.(item, val);
6446
+ };
6447
+ return /* @__PURE__ */ jsx(React.Fragment, { children: renderCard(item, {
6448
+ selected,
6449
+ highlighted,
6450
+ onSelectionChange: handleSelectionChange,
6451
+ onClick: handleClick
6452
+ }) }, id || index);
6453
+ })
6454
+ }), /* @__PURE__ */ jsxs("div", {
6455
+ className: "flex items-center justify-center py-8",
6456
+ children: [dataLoading && /* @__PURE__ */ jsx(CircularProgress, { size: "small" }), !dataLoading && noMoreToLoad && data.length > 0 && /* @__PURE__ */ jsxs(Typography, {
6457
+ variant: "caption",
6458
+ color: "secondary",
6459
+ children: [
6460
+ "All ",
6461
+ data.length,
6462
+ " entries loaded"
6463
+ ]
6464
+ })]
6465
+ })]
6466
+ })
6467
+ });
6468
+ }
6469
+ //#endregion
6470
+ //#region src/views/Kanban/BoardSortableList.tsx
6471
+ function BoardSortableList({ columnId, items, ItemComponent, isDragging, isDragOverColumn, loading = false, hasMore = false, onLoadMore }) {
6472
+ const { setNodeRef } = useDroppable({
6473
+ id: columnId,
6474
+ data: { type: "ITEM-LIST" }
6475
+ });
6476
+ const sentinelRef = useRef(null);
6477
+ const isLoadingRef = useRef(loading);
6478
+ isLoadingRef.current = loading;
6479
+ const lastLoadTimeRef = useRef(0);
6480
+ useEffect(() => {
6481
+ if (!sentinelRef.current || !hasMore || !onLoadMore) return;
6482
+ const sentinel = sentinelRef.current;
6483
+ const observer = new IntersectionObserver((entries) => {
6484
+ const now = Date.now();
6485
+ if (entries[0].isIntersecting && hasMore && !isLoadingRef.current && now - lastLoadTimeRef.current > 500) {
6486
+ lastLoadTimeRef.current = now;
6487
+ onLoadMore();
6488
+ }
6489
+ }, { threshold: .1 });
6490
+ observer.observe(sentinel);
6491
+ const rect = sentinel.getBoundingClientRect();
6492
+ const containerRect = sentinel.parentElement?.getBoundingClientRect();
6493
+ if (containerRect && rect.top < containerRect.bottom && rect.bottom > containerRect.top) {
6494
+ const now = Date.now();
6495
+ if (hasMore && !isLoadingRef.current && now - lastLoadTimeRef.current > 500) {
6496
+ lastLoadTimeRef.current = now;
6497
+ onLoadMore();
6498
+ }
6499
+ }
6500
+ return () => observer.disconnect();
6501
+ }, [hasMore, onLoadMore]);
6502
+ return /* @__PURE__ */ jsx("div", {
6503
+ ref: setNodeRef,
6504
+ className: useMemo(() => cls("flex flex-col p-2 transition-opacity duration-100 transition-bg ease-linear w-full overflow-y-auto no-scrollbar flex-1 rounded-md", isDragging && isDragOverColumn ? "bg-surface-accent-200 dark:bg-surface-900" : isDragging ? "bg-surface-50 dark:bg-surface-900 hover:bg-surface-accent-100 dark:hover:bg-surface-800" : "bg-surface-50 dark:bg-surface-900"), [isDragging, isDragOverColumn]),
6505
+ style: { minHeight: 80 },
6506
+ children: /* @__PURE__ */ jsx(SortableContext, {
6507
+ items: items.map((i) => i.id),
6508
+ strategy: verticalListSortingStrategy,
6509
+ children: items.length === 0 && !loading ? /* @__PURE__ */ jsx("div", {
6510
+ className: "flex-1 flex items-center justify-center",
6511
+ children: /* @__PURE__ */ jsx("span", {
6512
+ className: "text-xs text-surface-400 dark:text-surface-500",
6513
+ children: "No items"
6514
+ })
6515
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [items.map((item, index) => /* @__PURE__ */ jsx(SortableItem, {
6516
+ item,
6517
+ index,
6518
+ columnId,
6519
+ ItemComponent
6520
+ }, item.id)), (loading || hasMore) && /* @__PURE__ */ jsx("div", {
6521
+ ref: sentinelRef,
6522
+ className: "flex items-center justify-center py-2 min-h-6",
6523
+ children: loading && /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" })
6524
+ })] })
6525
+ })
6526
+ });
6527
+ }
6528
+ var SortableItem = memo(function SortableItem({ item, index, columnId, ItemComponent }) {
6529
+ const { setNodeRef, attributes, listeners, isDragging: isItemBeingDragged, transform, transition } = useSortable({
6530
+ id: item.id,
6531
+ data: {
6532
+ type: "ITEM",
6533
+ columnId
6534
+ }
6535
+ });
6536
+ return /* @__PURE__ */ jsx("div", {
6537
+ ref: setNodeRef,
6538
+ style: useMemo(() => ({
6539
+ transform: CSS.Transform.toString(transform),
6540
+ transition,
6541
+ zIndex: isItemBeingDragged ? 2 : 1,
6542
+ opacity: isItemBeingDragged ? 0 : 1
6543
+ }), [
6544
+ transform,
6545
+ transition,
6546
+ isItemBeingDragged
6547
+ ]),
6548
+ ...attributes,
6549
+ ...listeners,
6550
+ children: /* @__PURE__ */ jsx(ItemComponent, {
6551
+ item,
6552
+ isDragging: isItemBeingDragged,
6553
+ index
6554
+ })
6555
+ });
6556
+ });
6557
+ //#endregion
6558
+ //#region src/views/Kanban/BoardColumnTitle.tsx
6559
+ function BoardColumnTitle({ children, className, color, ...props }) {
6560
+ const colorScheme = useMemo(() => {
6561
+ if (!color) return void 0;
6562
+ if (typeof color === "string") return getColorSchemeForKey(color);
6563
+ return color;
6564
+ }, [color]);
6565
+ return /* @__PURE__ */ jsxs(Typography, {
6566
+ variant: "subtitle2",
6567
+ component: "h4",
6568
+ className: cls("py-3 px-3 transition-colors duration-200 flex-grow select-none relative outline-none focus:outline focus:outline-2 focus:outline-offset-2 flex items-center gap-3", className),
6569
+ ...props,
6570
+ children: [colorScheme && /* @__PURE__ */ jsx("div", {
6571
+ className: "w-3 h-3 rounded-full flex-shrink-0",
6572
+ style: { backgroundColor: colorScheme.darkColor ?? colorScheme.color }
6573
+ }), children]
6574
+ });
6575
+ }
6576
+ //#endregion
6577
+ //#region src/views/Kanban/BoardColumn.tsx
6578
+ var BoardColumn = memo(function BoardColumn({ id, title, items, ItemComponent, isDragging, isDragOverColumn, allowReorder = false, loading = false, hasMore = false, onLoadMore, onAddItem, totalCount, color, style }) {
6579
+ const { setNodeRef, attributes, listeners, isDragging: isColumnBeingDragged, transform, transition } = useSortable({
6580
+ id,
6581
+ data: { type: "COLUMN" },
6582
+ disabled: !allowReorder
6583
+ });
6584
+ const combinedStyle = useMemo(() => ({
6585
+ ...style,
6586
+ transform: CSS.Translate.toString(transform),
6587
+ transition,
6588
+ zIndex: isColumnBeingDragged ? 2 : 1
6589
+ }), [
6590
+ style,
6591
+ transform,
6592
+ transition,
6593
+ isColumnBeingDragged
6594
+ ]);
6595
+ const dragListeners = allowReorder ? listeners : {};
6596
+ const columnClassName = useMemo(() => cls("border h-full w-80 min-w-80 mx-2 flex flex-col rounded-md border-surface-200 dark:border-surface-800", isColumnBeingDragged ? "ring-2 ring-primary" : ""), [isColumnBeingDragged]);
6597
+ const headerClassName = useMemo(() => cls("flex items-center justify-between px-2 rounded-t-md transition-colors duration-200 ease-in-out", isColumnBeingDragged ? "bg-surface-100 dark:bg-surface-700" : "bg-surface-50 hover:bg-surface-100 dark:bg-surface-800 dark:hover:bg-surface-700", allowReorder ? "cursor-grab" : ""), [isColumnBeingDragged, allowReorder]);
6598
+ const itemIds = useMemo(() => items.map((i) => i.id), [items]);
6599
+ return /* @__PURE__ */ jsxs("div", {
6600
+ ref: setNodeRef,
6601
+ style: combinedStyle,
6602
+ ...attributes,
6603
+ className: columnClassName,
6604
+ children: [/* @__PURE__ */ jsxs("div", {
6605
+ ...dragListeners,
6606
+ className: headerClassName,
6607
+ children: [/* @__PURE__ */ jsxs("div", {
6608
+ className: "flex items-center gap-2",
6609
+ children: [/* @__PURE__ */ jsx(BoardColumnTitle, {
6610
+ "aria-label": `${title} item list`,
6611
+ color,
6612
+ children: title
6613
+ }), totalCount !== void 0 && /* @__PURE__ */ jsx("span", {
6614
+ className: "text-xs text-surface-500 dark:text-surface-400",
6615
+ children: totalCount
6616
+ })]
6617
+ }), onAddItem && /* @__PURE__ */ jsx(IconButton, {
6618
+ size: "small",
6619
+ onClick: (e) => {
6620
+ e.stopPropagation();
6621
+ onAddItem();
6622
+ },
6623
+ className: "opacity-60 hover:opacity-100",
6624
+ children: /* @__PURE__ */ jsx(PlusIcon, { size: iconSize.small })
6625
+ })]
6626
+ }), /* @__PURE__ */ jsx(SortableContext, {
6627
+ items: itemIds,
6628
+ strategy: verticalListSortingStrategy,
6629
+ children: /* @__PURE__ */ jsx(BoardSortableList, {
6630
+ columnId: id,
6631
+ items,
6632
+ ItemComponent,
6633
+ isDragging,
6634
+ isDragOverColumn,
6635
+ loading,
6636
+ hasMore,
6637
+ onLoadMore
6638
+ })
6639
+ })]
6640
+ });
6641
+ });
6642
+ //#endregion
6643
+ //#region src/views/Kanban/Board.tsx
6644
+ function Board({ data, columns: columnsProp, columnLabels, columnColors, className, assignColumn, allowColumnReorder = false, onColumnReorder, onItemsReorder, ItemComponent, columnLoadingState, onLoadMoreColumn, onAddItemToColumn, AddColumnComponent }) {
6645
+ const [activeItem, setActiveItem] = useState(null);
6646
+ const [activeColumn, setActiveColumn] = useState(null);
6647
+ const [isDragging, setIsDragging] = useState(false);
6648
+ const [dragOverColumnId, setDragOverColumnId] = useState(null);
6649
+ const grabOffsetRef = useRef({
6650
+ x: 0,
6651
+ y: 0
6652
+ });
6653
+ const [overlayPos, setOverlayPos] = useState(null);
6654
+ const handleMouseMove = useCallback((e) => {
6655
+ setOverlayPos({
6656
+ x: e.clientX - grabOffsetRef.current.x,
6657
+ y: e.clientY - grabOffsetRef.current.y
6658
+ });
6659
+ }, []);
6660
+ useEffect(() => {
6661
+ return () => {
6662
+ window.removeEventListener("mousemove", handleMouseMove);
6663
+ window.removeEventListener("pointermove", handleMouseMove);
6664
+ };
6665
+ }, [handleMouseMove]);
6666
+ const [itemMapState, setItemMapState] = useState(() => {
6667
+ const dataColumnMap = data.reduce((prev, item) => ({
6668
+ ...prev,
6669
+ [item.id]: assignColumn(item)
6670
+ }), {});
6671
+ return columnsProp.reduce((previous, column) => ({
6672
+ ...previous,
6673
+ [column]: data.filter((item) => dataColumnMap[item.id] === column)
6674
+ }), {});
6675
+ });
6676
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
6677
+ useEffect(() => {
6678
+ if (isDragging) return;
6679
+ const dataColumnMap = data.reduce((prev, item) => ({
6680
+ ...prev,
6681
+ [item.id]: assignColumn(item)
6682
+ }), {});
6683
+ const newItemMap = columnsProp.reduce((previous, column) => ({
6684
+ ...previous,
6685
+ [column]: data.filter((item) => dataColumnMap[item.id] === column)
6686
+ }), {});
6687
+ setItemMapState((prevMap) => {
6688
+ let changed = false;
6689
+ for (const col of columnsProp) {
6690
+ const prevItems = prevMap[col] ?? [];
6691
+ const newItems = newItemMap[col] ?? [];
6692
+ if (prevItems.length !== newItems.length) {
6693
+ changed = true;
6694
+ continue;
6695
+ }
6696
+ for (let i = 0; i < prevItems.length; i++) if (prevItems[i].id !== newItems[i].id || prevItems[i].data !== newItems[i].data) {
6697
+ changed = true;
6698
+ break;
6699
+ }
6700
+ }
6701
+ if (!changed) return prevMap;
6702
+ const updated = {};
6703
+ for (const col of columnsProp) {
6704
+ const prevItems = prevMap[col] ?? [];
6705
+ const newItems = newItemMap[col] ?? [];
6706
+ const prevById = /* @__PURE__ */ new Map();
6707
+ for (const item of prevItems) prevById.set(item.id, item);
6708
+ updated[col] = newItems.map((newItem) => {
6709
+ const prev = prevById.get(newItem.id);
6710
+ if (prev && prev.data === newItem.data) return prev;
6711
+ return newItem;
6712
+ });
6713
+ }
6714
+ return updated;
6715
+ });
6716
+ }, [
6717
+ data,
6718
+ columnsProp,
6719
+ assignColumn
6720
+ ]);
6721
+ const findColumnByItemId = (id) => {
6722
+ return Object.keys(itemMapState).find((col) => itemMapState[col]?.some((i) => i.id === id));
6723
+ };
6724
+ const handleDragStart = (event) => {
6725
+ setIsDragging(true);
6726
+ setDragOverColumnId(null);
6727
+ const { active } = event;
6728
+ const activatorEvt = event.activatorEvent;
6729
+ if (activatorEvt) {
6730
+ const target = activatorEvt.target;
6731
+ const rect = (target.closest("[role='button']") ?? target).getBoundingClientRect();
6732
+ grabOffsetRef.current = {
6733
+ x: activatorEvt.clientX - rect.left,
6734
+ y: activatorEvt.clientY - rect.top
6735
+ };
6736
+ setOverlayPos({
6737
+ x: rect.left,
6738
+ y: rect.top
6739
+ });
6740
+ }
6741
+ window.addEventListener("mousemove", handleMouseMove);
6742
+ window.addEventListener("pointermove", handleMouseMove);
6743
+ if (active.data.current?.type === "COLUMN") {
6744
+ const columnId = active.id;
6745
+ const column = columnsProp.find((col) => String(col) === columnId);
6746
+ if (column) setActiveColumn(column);
6747
+ } else if (active.data.current?.type === "ITEM") {
6748
+ const columnId = findColumnByItemId(active.id);
6749
+ if (columnId) {
6750
+ const item = itemMapState[columnId]?.find((i) => i.id === active.id);
6751
+ setActiveItem(item || null);
6752
+ }
6753
+ }
6754
+ };
6755
+ const handleDragOver = (event) => {
6756
+ const { active, over } = event;
6757
+ if (!over) {
6758
+ setDragOverColumnId(null);
6759
+ return;
6760
+ }
6761
+ let currentHoveredColumnId = null;
6762
+ const overId = over.id;
6763
+ const overDataType = over.data.current?.type;
6764
+ if (overDataType === "ITEM-LIST" || overDataType === "COLUMN") currentHoveredColumnId = overId;
6765
+ else if (overDataType === "ITEM") currentHoveredColumnId = findColumnByItemId(overId) || null;
6766
+ else if (columnsProp.includes(overId)) currentHoveredColumnId = overId;
6767
+ setDragOverColumnId(currentHoveredColumnId);
6768
+ if (active.data.current?.type !== "ITEM") return;
6769
+ const activeId = active.id;
6770
+ const activeColumn = findColumnByItemId(activeId);
6771
+ let overColumnForMove = findColumnByItemId(overId);
6772
+ if (!overColumnForMove && overDataType === "ITEM-LIST") overColumnForMove = overId;
6773
+ if (!overColumnForMove && columnsProp.includes(overId)) overColumnForMove = overId;
6774
+ if (!activeColumn || !overColumnForMove) return;
6775
+ if (activeColumn === overColumnForMove) return;
6776
+ if (itemMapState[overColumnForMove]?.some((i) => i.id === activeId)) return;
6777
+ setItemMapState((currentMap) => {
6778
+ const activeItems = [...currentMap[activeColumn] || []];
6779
+ const overItems = [...currentMap[overColumnForMove] || []];
6780
+ const activeIndex = activeItems.findIndex((i) => i.id === activeId);
6781
+ if (activeIndex === -1) return currentMap;
6782
+ let overIndex;
6783
+ if (overDataType === "ITEM-LIST" || columnsProp.includes(overId) && !findColumnByItemId(overId)) overIndex = overItems.length;
6784
+ else {
6785
+ overIndex = overItems.findIndex((i) => i.id === overId);
6786
+ if (overIndex !== -1) {
6787
+ const modifier = (active.rect.current.translated?.top ?? 0) + (active.rect.current.translated?.height ?? 0) / 2 > (over?.rect.top ?? 0) + (over?.rect.height ?? 0) / 2 ? 1 : 0;
6788
+ overIndex = overIndex >= 0 ? overIndex + modifier : overItems.length;
6789
+ } else overIndex = overItems.length;
6790
+ }
6791
+ const newItemMap = { ...currentMap };
6792
+ const [moved] = activeItems.splice(activeIndex, 1);
6793
+ overItems.splice(overIndex, 0, moved);
6794
+ newItemMap[activeColumn] = activeItems;
6795
+ newItemMap[overColumnForMove] = overItems;
6796
+ return newItemMap;
6797
+ });
6798
+ };
6799
+ const handleDragEnd = (event) => {
6800
+ const { active, over } = event;
6801
+ window.removeEventListener("mousemove", handleMouseMove);
6802
+ window.removeEventListener("pointermove", handleMouseMove);
6803
+ setOverlayPos(null);
6804
+ setIsDragging(false);
6805
+ setActiveItem(null);
6806
+ setActiveColumn(null);
6807
+ setDragOverColumnId(null);
6808
+ if (!over) return;
6809
+ const activeId = active.id;
6810
+ const overId = over.id;
6811
+ if (active.data.current?.type === "COLUMN") {
6812
+ if (activeId !== overId) {
6813
+ const oldIndex = columnsProp.indexOf(activeId);
6814
+ const newIndex = columnsProp.indexOf(overId);
6815
+ if (oldIndex !== -1 && newIndex !== -1) {
6816
+ const reordered = arrayMove(columnsProp, oldIndex, newIndex);
6817
+ onColumnReorder?.(reordered);
6818
+ }
6819
+ }
6820
+ return;
6821
+ }
6822
+ const activeCol = findColumnByItemId(activeId);
6823
+ let overCol = findColumnByItemId(overId);
6824
+ if (!overCol) {
6825
+ if (over.data.current?.type === "ITEM-LIST" || columnsProp.includes(overId)) overCol = overId;
6826
+ }
6827
+ if (!activeCol || !overCol) return;
6828
+ const isSameColumn = activeCol === overCol;
6829
+ const activeItems = itemMapState[activeCol] || [];
6830
+ const overItems = itemMapState[overCol] || [];
6831
+ const activeIndex = activeItems.findIndex((i) => i.id === activeId);
6832
+ let overIndex;
6833
+ if (over.id === overCol) overIndex = overItems.length;
6834
+ else overIndex = overItems.findIndex((i) => i.id === overId);
6835
+ if (activeIndex === -1 || overIndex === -1) return;
6836
+ let finalItems = [];
6837
+ if (isSameColumn) finalItems = arrayMove(activeItems, activeIndex, overIndex);
6838
+ else {
6839
+ const newActiveItems = [...activeItems];
6840
+ const newOverItems = [...overItems];
6841
+ const [moved] = newActiveItems.splice(activeIndex, 1);
6842
+ newOverItems.splice(overIndex, 0, moved);
6843
+ finalItems = [...newActiveItems, ...newOverItems];
6844
+ }
6845
+ const fullFlattenedList = [];
6846
+ columnsProp.forEach((col) => {
6847
+ if (col === activeCol) if (isSameColumn) fullFlattenedList.push(...finalItems);
6848
+ else fullFlattenedList.push(...activeItems.filter((i) => i.id !== activeId));
6849
+ else if (col === overCol) {
6850
+ const newOverItems = [...overItems];
6851
+ const [moved] = [...activeItems].splice(activeIndex, 1);
6852
+ newOverItems.splice(overIndex, 0, moved);
6853
+ fullFlattenedList.push(...newOverItems);
6854
+ } else fullFlattenedList.push(...itemMapState[col] || []);
6855
+ });
6856
+ onItemsReorder?.(fullFlattenedList, {
6857
+ itemId: activeId,
6858
+ sourceColumn: activeCol,
6859
+ targetColumn: overCol
6860
+ });
6861
+ };
6862
+ return /* @__PURE__ */ jsxs(DndContext, {
6863
+ sensors,
6864
+ onDragStart: handleDragStart,
6865
+ onDragOver: handleDragOver,
6866
+ onDragEnd: handleDragEnd,
6867
+ children: [/* @__PURE__ */ jsxs("div", {
6868
+ className: cls("flex flex-row h-full w-full overflow-x-auto p-4 select-none items-start", className),
6869
+ children: [/* @__PURE__ */ jsx(SortableContext, {
6870
+ items: columnsProp,
6871
+ children: columnsProp.map((col, index) => {
6872
+ const colItems = itemMapState[col] || [];
6873
+ const loadingState = columnLoadingState?.[col];
6874
+ return /* @__PURE__ */ jsx(BoardColumn, {
6875
+ id: String(col),
6876
+ title: columnLabels?.[col] ?? String(col),
6877
+ items: colItems,
6878
+ index,
6879
+ ItemComponent,
6880
+ isDragging,
6881
+ isDragOverColumn: dragOverColumnId === String(col),
6882
+ allowReorder: allowColumnReorder,
6883
+ loading: loadingState?.loading,
6884
+ hasMore: loadingState?.hasMore,
6885
+ totalCount: loadingState?.totalCount,
6886
+ color: columnColors?.[col],
6887
+ onLoadMore: onLoadMoreColumn ? () => onLoadMoreColumn(col) : void 0,
6888
+ onAddItem: onAddItemToColumn ? () => onAddItemToColumn(col) : void 0
6889
+ }, String(col));
6890
+ })
6891
+ }), AddColumnComponent]
6892
+ }), typeof document !== "undefined" && createPortal(/* @__PURE__ */ jsx(DragOverlay, {
6893
+ dropAnimation: null,
6894
+ children: isDragging && activeItem && /* @__PURE__ */ jsx("div", {
6895
+ style: {
6896
+ position: "fixed",
6897
+ left: overlayPos?.x ?? 0,
6898
+ top: overlayPos?.y ?? 0,
6899
+ pointerEvents: "none",
6900
+ zIndex: 9999
6901
+ },
6902
+ children: /* @__PURE__ */ jsx(ItemComponent, {
6903
+ item: activeItem,
6904
+ isDragging: true,
6905
+ isClone: true
6906
+ })
6907
+ })
6908
+ }), document.body)]
6909
+ });
6910
+ }
6911
+ //#endregion
6912
+ //#region src/views/KanbanView.tsx
6913
+ function KanbanView(props) {
6914
+ return /* @__PURE__ */ jsx(Board, { ...props });
6915
+ }
6916
+ //#endregion
6917
+ //#region src/views/CollectionView/CollectionViewToolbar.tsx
6918
+ var VIEW_MODE_ICONS = {
6919
+ list: /* @__PURE__ */ jsx(LayoutList, { size: iconSize.small }),
6920
+ table: /* @__PURE__ */ jsx(Table2, { size: iconSize.small }),
6921
+ cards: /* @__PURE__ */ jsx(LayoutGrid, { size: iconSize.small }),
6922
+ kanban: /* @__PURE__ */ jsx(Kanban, { size: iconSize.small })
6923
+ };
6924
+ var VIEW_MODE_LABELS = {
6925
+ list: "List",
6926
+ table: "Table",
6927
+ cards: "Cards",
6928
+ kanban: "Board"
6929
+ };
6930
+ var SIZE_LABELS = {
6931
+ xs: "Extra Small",
6932
+ s: "Small",
6933
+ m: "Medium",
6934
+ l: "Large",
6935
+ xl: "Extra Large"
6936
+ };
6937
+ /**
6938
+ * Toolbar for the headless CollectionView.
6939
+ *
6940
+ * Renders a search bar, view mode toggle (popover with toggle button group),
6941
+ * optional size selector, optional kanban property selector, and action slots.
6942
+ *
6943
+ * @group Collection View
6944
+ */
6945
+ function CollectionViewToolbar({ viewMode, onViewModeChange, enabledViews = [
6946
+ "list",
6947
+ "table",
6948
+ "cards",
6949
+ "kanban"
6950
+ ], size = "m", onSizeChange, searchString, onSearchChange, loading, actionsStart, actionsEnd, compact, kanbanPropertyOptions, selectedKanbanProperty, onKanbanPropertyChange }) {
6951
+ const [popoverOpen, setPopoverOpen] = useState(false);
6952
+ const viewOptions = enabledViews.map((mode) => ({
6953
+ value: mode,
6954
+ label: VIEW_MODE_LABELS[mode],
6955
+ icon: VIEW_MODE_ICONS[mode]
6956
+ }));
6957
+ const handleViewModeChange = useCallback((mode) => {
6958
+ onViewModeChange?.(mode);
6959
+ }, [onViewModeChange]);
6960
+ const handleSizeChange = useCallback((value) => {
6961
+ onSizeChange?.(value);
6962
+ }, [onSizeChange]);
6963
+ const handleKanbanPropertyChange = useCallback((value) => {
6964
+ onKanbanPropertyChange?.(value);
6965
+ }, [onKanbanPropertyChange]);
6966
+ const showViewToggle = onViewModeChange && enabledViews.length > 1;
6967
+ const showSizeSelector = onSizeChange && viewMode !== "kanban";
6968
+ const showKanbanSelector = kanbanPropertyOptions && kanbanPropertyOptions.length > 0 && viewMode === "kanban" && onKanbanPropertyChange;
6969
+ const showPopover = showViewToggle || showSizeSelector || showKanbanSelector;
6970
+ return /* @__PURE__ */ jsxs("div", {
6971
+ className: cls("flex items-center gap-2 px-2 flex-shrink-0", "border-b border-surface-200 dark:border-surface-800", compact ? "py-0.5 gap-1" : "py-1"),
6972
+ children: [
6973
+ actionsStart,
6974
+ onSearchChange && /* @__PURE__ */ jsx(SearchBar, {
6975
+ onTextSearch: onSearchChange,
6976
+ size: "small",
6977
+ initialValue: searchString,
6978
+ loading,
6979
+ expandable: true
6980
+ }),
6981
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
6982
+ actionsEnd,
6983
+ showPopover && /* @__PURE__ */ jsx(Popover, {
6984
+ open: popoverOpen,
6985
+ onOpenChange: setPopoverOpen,
6986
+ side: "bottom",
6987
+ align: "end",
6988
+ trigger: /* @__PURE__ */ jsx(IconButton, {
6989
+ size: "small",
6990
+ onClick: () => setPopoverOpen((prev) => !prev),
6991
+ children: /* @__PURE__ */ jsx(Settings2, { size: iconSize.small })
6992
+ }),
6993
+ children: /* @__PURE__ */ jsxs("div", {
6994
+ className: "p-3 min-w-[200px] flex flex-col gap-3",
6995
+ children: [
6996
+ showViewToggle && /* @__PURE__ */ jsxs("div", {
6997
+ className: "flex flex-col gap-1",
6998
+ children: [/* @__PURE__ */ jsx(Typography, {
6999
+ variant: "caption",
7000
+ color: "secondary",
7001
+ className: "font-medium uppercase tracking-wider",
7002
+ children: "View"
7003
+ }), /* @__PURE__ */ jsx(ToggleButtonGroup, {
7004
+ value: viewMode,
7005
+ onValueChange: handleViewModeChange,
7006
+ options: viewOptions
7007
+ })]
7008
+ }),
7009
+ showSizeSelector && /* @__PURE__ */ jsxs("div", {
7010
+ className: "flex flex-col gap-1",
7011
+ children: [/* @__PURE__ */ jsx(Typography, {
7012
+ variant: "caption",
7013
+ color: "secondary",
7014
+ className: "font-medium uppercase tracking-wider",
7015
+ children: "Size"
7016
+ }), /* @__PURE__ */ jsx(Select, {
7017
+ value: size,
7018
+ onValueChange: handleSizeChange,
7019
+ size: "small",
7020
+ children: Object.keys(SIZE_LABELS).map((sizeKey) => /* @__PURE__ */ jsx(SelectItem, {
7021
+ value: sizeKey,
7022
+ children: SIZE_LABELS[sizeKey]
7023
+ }, sizeKey))
7024
+ })]
7025
+ }),
7026
+ showKanbanSelector && /* @__PURE__ */ jsxs("div", {
7027
+ className: "flex flex-col gap-1",
7028
+ children: [/* @__PURE__ */ jsx(Typography, {
7029
+ variant: "caption",
7030
+ color: "secondary",
7031
+ className: "font-medium uppercase tracking-wider",
7032
+ children: "Group by"
7033
+ }), /* @__PURE__ */ jsx(Select, {
7034
+ value: selectedKanbanProperty,
7035
+ onValueChange: handleKanbanPropertyChange,
7036
+ size: "small",
7037
+ children: kanbanPropertyOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, {
7038
+ value: option.key,
7039
+ children: option.label
7040
+ }, option.key))
7041
+ })]
7042
+ })
7043
+ ]
7044
+ })
7045
+ })
7046
+ ]
7047
+ });
7048
+ }
7049
+ //#endregion
7050
+ //#region src/views/CollectionView/DefaultCellRenderer.tsx
7051
+ /**
7052
+ * Resolve an enum key to its display label and optional color.
7053
+ */
7054
+ function resolveEnumLabel(enumValues, value) {
7055
+ if (!enumValues) return void 0;
7056
+ const key = String(value);
7057
+ if (enumValues instanceof Map) {
7058
+ const config = enumValues.get(value);
7059
+ if (!config) return void 0;
7060
+ if (typeof config === "string") return { label: config };
7061
+ return {
7062
+ label: config.label,
7063
+ color: config.color
7064
+ };
7065
+ }
7066
+ const config = enumValues[key];
7067
+ if (!config) return void 0;
7068
+ if (typeof config === "string") return { label: config };
7069
+ return {
7070
+ label: config.label,
7071
+ color: config.color
7072
+ };
7073
+ }
7074
+ /**
7075
+ * Format a date value using Intl.DateTimeFormat.
7076
+ */
7077
+ function formatDate(value, includeTime) {
7078
+ if (value == null) return "—";
7079
+ const date = value instanceof Date ? value : new Date(String(value));
7080
+ if (isNaN(date.getTime())) return String(value);
7081
+ const options = includeTime ? {
7082
+ year: "numeric",
7083
+ month: "short",
7084
+ day: "numeric",
7085
+ hour: "2-digit",
7086
+ minute: "2-digit"
7087
+ } : {
7088
+ year: "numeric",
7089
+ month: "short",
7090
+ day: "numeric"
7091
+ };
7092
+ return new Intl.DateTimeFormat(void 0, options).format(date);
7093
+ }
7094
+ /**
7095
+ * Type guard for geopoint-like objects.
7096
+ */
7097
+ function isGeoPoint(value) {
7098
+ if (typeof value !== "object" || value === null) return false;
7099
+ const obj = value;
7100
+ return typeof obj.lat === "number" && typeof obj.lng === "number";
7101
+ }
7102
+ /**
7103
+ * Default cell renderer for the headless CollectionView.
7104
+ * Handles all built-in property types without depending on any Rebase core types.
7105
+ *
7106
+ * @group Preview components
7107
+ */
7108
+ function DefaultCellRenderer({ row, propertyKey, property, value, size, width, height }) {
7109
+ if (value === null || value === void 0) return /* @__PURE__ */ jsx(Typography, {
7110
+ variant: "body2",
7111
+ color: "secondary",
7112
+ className: "px-1",
7113
+ children: "—"
7114
+ });
7115
+ if (property.Preview) {
7116
+ const PreviewComponent = property.Preview;
7117
+ return /* @__PURE__ */ jsx(PreviewComponent, {
7118
+ row,
7119
+ propertyKey,
7120
+ property,
7121
+ value,
7122
+ size,
7123
+ width,
7124
+ height
7125
+ });
7126
+ }
7127
+ switch (property.type) {
7128
+ case "string": return renderString(property, value);
7129
+ case "number": return renderNumber(property, value);
7130
+ case "boolean": return renderBoolean(value);
7131
+ case "date": return renderDate(property, value);
7132
+ case "array": return renderArray(property, value);
7133
+ case "map": return renderMap(value);
7134
+ case "reference":
7135
+ case "relation": return renderReference(value);
7136
+ case "geopoint": return renderGeopoint(value);
7137
+ default: return /* @__PURE__ */ jsx(Typography, {
7138
+ variant: "body2",
7139
+ color: "secondary",
7140
+ noWrap: true,
7141
+ className: "px-1",
7142
+ children: JSON.stringify(value)
7143
+ });
7144
+ }
7145
+ }
7146
+ function renderString(property, value) {
7147
+ const strValue = String(value);
7148
+ if (property.enum) {
7149
+ const resolved = resolveEnumLabel(property.enum, value);
7150
+ return /* @__PURE__ */ jsx(Chip, {
7151
+ size: "small",
7152
+ colorScheme: resolved?.color ? {
7153
+ color: resolved.color,
7154
+ text: "#fff"
7155
+ } : void 0,
7156
+ children: resolved?.label ?? strValue
7157
+ });
7158
+ }
7159
+ if (property.previewAsTag) return /* @__PURE__ */ jsx(Chip, {
7160
+ size: "small",
7161
+ children: strValue
7162
+ });
7163
+ if (property.url) return /* @__PURE__ */ jsx(Typography, {
7164
+ variant: "body2",
7165
+ noWrap: true,
7166
+ component: "a",
7167
+ href: typeof property.url === "string" ? property.url : strValue,
7168
+ target: "_blank",
7169
+ rel: "noopener noreferrer",
7170
+ className: cls("px-1 text-primary hover:underline cursor-pointer"),
7171
+ children: strValue
7172
+ });
7173
+ if (property.email) return /* @__PURE__ */ jsx(Typography, {
7174
+ variant: "body2",
7175
+ noWrap: true,
7176
+ component: "a",
7177
+ href: `mailto:${strValue}`,
7178
+ className: cls("px-1 text-primary hover:underline cursor-pointer"),
7179
+ children: strValue
7180
+ });
7181
+ if (property.markdown) return /* @__PURE__ */ jsx("div", {
7182
+ className: "px-1 max-h-[100px] overflow-hidden",
7183
+ children: /* @__PURE__ */ jsx(Markdown, {
7184
+ source: strValue,
7185
+ size: "small"
7186
+ })
7187
+ });
7188
+ if (property.storage) return /* @__PURE__ */ jsxs("div", {
7189
+ className: cls("px-1 flex items-center justify-center", "w-[40px] h-[40px] rounded overflow-hidden"),
7190
+ children: [strValue ? /* @__PURE__ */ jsx("img", {
7191
+ src: strValue,
7192
+ alt: "",
7193
+ className: "w-full h-full object-cover",
7194
+ onError: (e) => {
7195
+ const target = e.currentTarget;
7196
+ target.style.display = "none";
7197
+ const fallback = target.nextElementSibling;
7198
+ if (fallback instanceof HTMLElement) fallback.style.display = "flex";
7199
+ }
7200
+ }) : null, /* @__PURE__ */ jsx("div", {
7201
+ className: cls("w-full h-full items-center justify-center rounded", "bg-surface-100 dark:bg-surface-800 text-text-secondary dark:text-text-secondary-dark", strValue ? "hidden" : "flex"),
7202
+ children: /* @__PURE__ */ jsx(ImageIcon$1, { size: iconSize.small })
7203
+ })]
7204
+ });
7205
+ return /* @__PURE__ */ jsx(Tooltip, {
7206
+ title: strValue.length > 50 ? strValue : void 0,
7207
+ side: "bottom",
7208
+ children: /* @__PURE__ */ jsx(Typography, {
7209
+ variant: "body2",
7210
+ noWrap: true,
7211
+ className: "px-1",
7212
+ children: strValue
7213
+ })
7214
+ });
7215
+ }
7216
+ function renderNumber(property, value) {
7217
+ const numStr = String(value);
7218
+ if (property.enum) {
7219
+ const resolved = resolveEnumLabel(property.enum, value);
7220
+ return /* @__PURE__ */ jsx(Chip, {
7221
+ size: "small",
7222
+ colorScheme: resolved?.color ? {
7223
+ color: resolved.color,
7224
+ text: "#fff"
7225
+ } : void 0,
7226
+ children: resolved?.label ?? numStr
7227
+ });
7228
+ }
7229
+ return /* @__PURE__ */ jsx(Typography, {
7230
+ variant: "body2",
7231
+ noWrap: true,
7232
+ align: "right",
7233
+ className: "px-1 tabular-nums",
7234
+ children: numStr
7235
+ });
7236
+ }
7237
+ function renderBoolean(value) {
7238
+ return /* @__PURE__ */ jsx("div", {
7239
+ className: "px-1 flex items-center",
7240
+ children: /* @__PURE__ */ jsx(BooleanSwitch, {
7241
+ value: !!value,
7242
+ size: "small",
7243
+ disabled: true
7244
+ })
7245
+ });
7246
+ }
7247
+ function renderDate(property, value) {
7248
+ return /* @__PURE__ */ jsx(Typography, {
7249
+ variant: "body2",
7250
+ noWrap: true,
7251
+ className: "px-1 tabular-nums",
7252
+ children: formatDate(value, property.mode === "date_time")
7253
+ });
7254
+ }
7255
+ function renderArray(property, value) {
7256
+ if (!Array.isArray(value)) return /* @__PURE__ */ jsx(Typography, {
7257
+ variant: "body2",
7258
+ color: "secondary",
7259
+ className: "px-1",
7260
+ children: "—"
7261
+ });
7262
+ if (property.of?.enum && value.length > 0) return /* @__PURE__ */ jsx("div", {
7263
+ className: "px-1 flex flex-wrap gap-1 overflow-hidden",
7264
+ children: value.map((item, i) => {
7265
+ const resolved = resolveEnumLabel(property.of.enum, item);
7266
+ return /* @__PURE__ */ jsx(Chip, {
7267
+ size: "smallest",
7268
+ colorScheme: resolved?.color ? {
7269
+ color: resolved.color,
7270
+ text: "#fff"
7271
+ } : void 0,
7272
+ children: resolved?.label ?? String(item)
7273
+ }, i);
7274
+ })
7275
+ });
7276
+ if (value.length > 0 && value.every((item) => typeof item === "string")) return /* @__PURE__ */ jsx(Typography, {
7277
+ variant: "body2",
7278
+ noWrap: true,
7279
+ className: "px-1",
7280
+ children: value.join(", ")
7281
+ });
7282
+ return /* @__PURE__ */ jsxs(Typography, {
7283
+ variant: "body2",
7284
+ color: "secondary",
7285
+ className: "px-1",
7286
+ children: [
7287
+ value.length,
7288
+ " ",
7289
+ value.length === 1 ? "item" : "items"
7290
+ ]
7291
+ });
7292
+ }
7293
+ function renderMap(value) {
7294
+ if (typeof value !== "object" || value === null) return /* @__PURE__ */ jsx(Typography, {
7295
+ variant: "body2",
7296
+ color: "secondary",
7297
+ className: "px-1",
7298
+ children: "—"
7299
+ });
7300
+ const fieldCount = Object.keys(value).length;
7301
+ return /* @__PURE__ */ jsxs(Typography, {
7302
+ variant: "body2",
7303
+ color: "secondary",
7304
+ className: "px-1",
7305
+ children: [
7306
+ fieldCount,
7307
+ " ",
7308
+ fieldCount === 1 ? "field" : "fields"
7309
+ ]
7310
+ });
7311
+ }
7312
+ function renderReference(value) {
7313
+ return /* @__PURE__ */ jsx(Typography, {
7314
+ variant: "body2",
7315
+ noWrap: true,
7316
+ className: "px-1",
7317
+ children: String(value)
7318
+ });
7319
+ }
7320
+ function renderGeopoint(value) {
7321
+ if (isGeoPoint(value)) return /* @__PURE__ */ jsxs(Typography, {
7322
+ variant: "body2",
7323
+ noWrap: true,
7324
+ className: "px-1 tabular-nums",
7325
+ children: [
7326
+ value.lat.toFixed(6),
7327
+ ", ",
7328
+ value.lng.toFixed(6)
7329
+ ]
7330
+ });
7331
+ return /* @__PURE__ */ jsx(Typography, {
7332
+ variant: "body2",
7333
+ color: "secondary",
7334
+ className: "px-1",
7335
+ children: String(value)
7336
+ });
7337
+ }
7338
+ //#endregion
7339
+ //#region src/views/CollectionView/utils.ts
7340
+ /**
7341
+ * Traverse an object by dot-separated path.
7342
+ * Returns `undefined` if any segment is missing.
7343
+ */
7344
+ function getValueInPath(obj, path) {
7345
+ if (!obj) return void 0;
7346
+ const parts = path.split(".");
7347
+ let current = obj;
7348
+ for (const part of parts) {
7349
+ if (current === null || current === void 0 || typeof current !== "object") return void 0;
7350
+ current = current[part];
7351
+ }
7352
+ return current;
7353
+ }
7354
+ //#endregion
7355
+ //#region src/views/CollectionView/CollectionTableView.tsx
7356
+ var DEFAULT_COLUMN_WIDTHS = {
7357
+ string: 200,
7358
+ number: 140,
7359
+ date: 160,
7360
+ boolean: 120,
7361
+ array: 200,
7362
+ map: 200,
7363
+ reference: 200,
7364
+ relation: 200,
7365
+ geopoint: 180
7366
+ };
7367
+ var FALLBACK_COLUMN_WIDTH = 200;
7368
+ var SIZE_TO_ROW_HEIGHT = {
7369
+ xs: 36,
7370
+ s: 44,
7371
+ m: 52,
7372
+ l: 64,
7373
+ xl: 80
7374
+ };
7375
+ var SORTABLE_TYPES = new Set([
7376
+ "string",
7377
+ "number",
7378
+ "date"
7379
+ ]);
7380
+ var VIEW_SIZE_TO_RENDERER_SIZE = {
7381
+ xs: "tiny",
7382
+ s: "small",
7383
+ m: "medium",
7384
+ l: "large",
7385
+ xl: "large"
7386
+ };
7387
+ /**
7388
+ * Headless table view that wraps {@link VirtualTable}.
7389
+ *
7390
+ * Converts property configurations into virtual table columns and wires up
7391
+ * sorting, pagination, and cell rendering without coupling to any data layer.
7392
+ *
7393
+ * @group Collection View
7394
+ */
7395
+ function CollectionTableView({ dataController, properties, propertiesOrder, displayedColumnIds, onRowClick, cellRenderer, size = "m", emptyComponent, hoverRow = true, className, onColumnResize, onColumnsOrderChange }) {
7396
+ const columns = useMemo(() => {
7397
+ const order = propertiesOrder ?? Object.keys(properties);
7398
+ return (displayedColumnIds ? order.filter((key) => displayedColumnIds.includes(key)) : order.filter((key) => {
7399
+ const prop = properties[key];
7400
+ return prop && !prop.hideFromCollection;
7401
+ })).map((key) => {
7402
+ const prop = properties[key];
7403
+ if (!prop) return null;
7404
+ return {
7405
+ key,
7406
+ width: prop.columnWidth || DEFAULT_COLUMN_WIDTHS[prop.type] || FALLBACK_COLUMN_WIDTH,
7407
+ title: prop.name,
7408
+ sortable: SORTABLE_TYPES.has(prop.type),
7409
+ resizable: true
7410
+ };
7411
+ }).filter((col) => col !== null);
7412
+ }, [
7413
+ properties,
7414
+ propertiesOrder,
7415
+ displayedColumnIds
7416
+ ]);
7417
+ const rowHeight = SIZE_TO_ROW_HEIGHT[size];
7418
+ const rendererSize = VIEW_SIZE_TO_RENDERER_SIZE[size];
7419
+ const tableCellRenderer = useCallback((params) => {
7420
+ if (!params.rowData) return null;
7421
+ const propertyConfig = properties[params.column.key];
7422
+ if (!propertyConfig) return null;
7423
+ const value = getValueInPath(params.rowData, params.column.key);
7424
+ const cellProps = {
7425
+ row: params.rowData,
7426
+ propertyKey: params.column.key,
7427
+ property: propertyConfig,
7428
+ value,
7429
+ size: rendererSize,
7430
+ width: params.width
7431
+ };
7432
+ if (cellRenderer) {
7433
+ const custom = cellRenderer(cellProps);
7434
+ if (custom !== void 0) return /* @__PURE__ */ jsx("div", {
7435
+ className: "flex items-center h-full px-1 overflow-hidden",
7436
+ children: custom
7437
+ });
7438
+ }
7439
+ return /* @__PURE__ */ jsx("div", {
7440
+ className: "flex items-center h-full px-1 overflow-hidden",
7441
+ children: /* @__PURE__ */ jsx(DefaultCellRenderer, { ...cellProps })
7442
+ });
7443
+ }, [
7444
+ properties,
7445
+ cellRenderer,
7446
+ rendererSize
7447
+ ]);
7448
+ const handleRowClick = useCallback(({ rowData }) => {
7449
+ onRowClick?.(rowData);
7450
+ }, [onRowClick]);
7451
+ const handleEndReached = useCallback(() => {
7452
+ if (dataController.paginationEnabled && !dataController.noMoreToLoad) {
7453
+ const currentCount = dataController.itemCount ?? dataController.pageSize ?? 50;
7454
+ const pageSize = dataController.pageSize ?? 50;
7455
+ dataController.setItemCount?.(currentCount + pageSize);
7456
+ }
7457
+ }, [
7458
+ dataController.paginationEnabled,
7459
+ dataController.noMoreToLoad,
7460
+ dataController.itemCount,
7461
+ dataController.pageSize,
7462
+ dataController.setItemCount
7463
+ ]);
7464
+ const handleColumnResize = useCallback((params) => {
7465
+ onColumnResize?.({
7466
+ key: params.key,
7467
+ width: params.width
7468
+ });
7469
+ }, [onColumnResize]);
7470
+ const handleColumnsOrderChange = useCallback((newColumns) => {
7471
+ onColumnsOrderChange?.(newColumns.map((col) => col.key));
7472
+ }, [onColumnsOrderChange]);
7473
+ return /* @__PURE__ */ jsx(VirtualTable, {
7474
+ data: dataController.data,
7475
+ columns,
7476
+ cellRenderer: tableCellRenderer,
7477
+ rowHeight,
7478
+ sortBy: dataController.sortBy,
7479
+ onSortByUpdate: dataController.setSortBy,
7480
+ onRowClick: handleRowClick,
7481
+ onEndReached: handleEndReached,
7482
+ onColumnResize: handleColumnResize,
7483
+ onColumnsOrderChange: handleColumnsOrderChange,
7484
+ loading: dataController.loading,
7485
+ emptyComponent,
7486
+ error: dataController.error,
7487
+ hoverRow,
7488
+ className: cls("h-full", className),
7489
+ onScroll: dataController.onScroll,
7490
+ initialScroll: dataController.initialScroll
7491
+ });
7492
+ }
7493
+ //#endregion
7494
+ //#region src/views/CollectionView/CollectionCardView.tsx
7495
+ /**
7496
+ * Headless card grid view that wraps {@link CardView}.
7497
+ *
7498
+ * Renders each item as a card with an optional image, title,
7499
+ * preview properties, and selection support.
7500
+ *
7501
+ * @group Collection View
7502
+ */
7503
+ function CollectionCardView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, onRowClick, cellRenderer, size = "m", selectionEnabled, selectionController, highlightedItems, emptyComponent, className }) {
7504
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
7505
+ const titlePropertyKey = useMemo(() => {
7506
+ if (titleProperty) return titleProperty;
7507
+ for (const key of order) {
7508
+ const prop = properties[key];
7509
+ if (prop && prop.type === "string" && !prop.hideFromCollection && !prop.storage) return key;
7510
+ }
7511
+ return idProperty;
7512
+ }, [
7513
+ titleProperty,
7514
+ order,
7515
+ properties,
7516
+ idProperty
7517
+ ]);
7518
+ const imageProperty = useMemo(() => {
7519
+ for (const key of order) {
7520
+ const prop = properties[key];
7521
+ if (prop && prop.type === "string" && prop.storage) return key;
7522
+ }
7523
+ }, [order, properties]);
7524
+ const previewProperties = useMemo(() => {
7525
+ const result = [];
7526
+ for (const key of order) {
7527
+ if (key === titlePropertyKey || key === imageProperty) continue;
7528
+ const prop = properties[key];
7529
+ if (prop && !prop.hideFromCollection) {
7530
+ result.push({
7531
+ key,
7532
+ property: prop
7533
+ });
7534
+ if (result.length >= 3) break;
7535
+ }
7536
+ }
7537
+ return result;
7538
+ }, [
7539
+ order,
7540
+ properties,
7541
+ titlePropertyKey,
7542
+ imageProperty
7543
+ ]);
7544
+ const selectedIds = useMemo(() => {
7545
+ if (!selectionController?.selectedItems) return void 0;
7546
+ const ids = /* @__PURE__ */ new Set();
7547
+ for (const item of selectionController.selectedItems) {
7548
+ const id = getValueInPath(item, idProperty);
7549
+ if (id !== void 0 && id !== null) ids.add(id);
7550
+ }
7551
+ return ids;
7552
+ }, [selectionController?.selectedItems, idProperty]);
7553
+ const highlightedIds = useMemo(() => {
7554
+ if (!highlightedItems) return void 0;
7555
+ const ids = /* @__PURE__ */ new Set();
7556
+ for (const item of highlightedItems) {
7557
+ const id = getValueInPath(item, idProperty);
7558
+ if (id !== void 0 && id !== null) ids.add(id);
7559
+ }
7560
+ return ids;
7561
+ }, [highlightedItems, idProperty]);
7562
+ const handleSelectionChange = useCallback((item, selected) => {
7563
+ if (!selectionController) return;
7564
+ selectionController.setSelectedItems((prev) => {
7565
+ if (selected) return [...prev, item];
7566
+ const itemId = getValueInPath(item, idProperty);
7567
+ return prev.filter((existing) => {
7568
+ return getValueInPath(existing, idProperty) !== itemId;
7569
+ });
7570
+ });
7571
+ }, [selectionController, idProperty]);
7572
+ const renderCard = useCallback((item, extra) => {
7573
+ const titleValue = getValueInPath(item, titlePropertyKey);
7574
+ const imageValue = imageProperty ? getValueInPath(item, imageProperty) : void 0;
7575
+ const hasImage = typeof imageValue === "string" && imageValue.length > 0;
7576
+ return /* @__PURE__ */ jsxs(Card, {
7577
+ onClick: (e) => {
7578
+ if (e) extra.onClick(e);
7579
+ },
7580
+ className: cls("overflow-hidden relative", extra.selected && "bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75", extra.highlighted && !extra.selected && "ring-1 ring-primary/50"),
7581
+ children: [
7582
+ imageProperty && (hasImage ? /* @__PURE__ */ jsx("img", {
7583
+ src: imageValue,
7584
+ alt: "",
7585
+ className: "w-full h-32 object-cover rounded-t-lg"
7586
+ }) : /* @__PURE__ */ jsx("div", { className: cls("h-24 rounded-t-lg", "bg-surface-accent-200/50 dark:bg-black/30") })),
7587
+ selectionEnabled && /* @__PURE__ */ jsx("div", {
7588
+ className: "absolute top-2 right-2",
7589
+ onClick: (e) => e.stopPropagation(),
7590
+ children: /* @__PURE__ */ jsx(Checkbox, {
7591
+ checked: extra.selected,
7592
+ onCheckedChange: extra.onSelectionChange,
7593
+ size: "small"
7594
+ })
7595
+ }),
7596
+ /* @__PURE__ */ jsx(Typography, {
7597
+ variant: "subtitle2",
7598
+ noWrap: true,
7599
+ className: "px-3 pt-2 pb-1",
7600
+ children: String(titleValue ?? "")
7601
+ }),
7602
+ previewProperties.map(({ key, property }) => {
7603
+ const value = getValueInPath(item, key);
7604
+ if (cellRenderer) {
7605
+ const custom = cellRenderer({
7606
+ row: item,
7607
+ propertyKey: key,
7608
+ property,
7609
+ value,
7610
+ size: "small"
7611
+ });
7612
+ if (custom !== void 0) return /* @__PURE__ */ jsx("div", {
7613
+ className: "px-3 py-0.5",
7614
+ children: custom
7615
+ }, key);
7616
+ }
7617
+ return /* @__PURE__ */ jsx("div", {
7618
+ className: "px-3 py-0.5",
7619
+ children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
7620
+ row: item,
7621
+ propertyKey: key,
7622
+ property,
7623
+ value,
7624
+ size: "small"
7625
+ })
7626
+ }, key);
7627
+ }),
7628
+ /* @__PURE__ */ jsx("div", { className: "pb-2" })
7629
+ ]
7630
+ });
7631
+ }, [
7632
+ titlePropertyKey,
7633
+ imageProperty,
7634
+ previewProperties,
7635
+ cellRenderer,
7636
+ selectionEnabled
7637
+ ]);
7638
+ return /* @__PURE__ */ jsx("div", {
7639
+ className: cls("w-full h-full overflow-auto", className),
7640
+ children: /* @__PURE__ */ jsx(CardView, {
7641
+ data: dataController.data,
7642
+ dataLoading: dataController.loading,
7643
+ noMoreToLoad: dataController.noMoreToLoad,
7644
+ dataLoadingError: dataController.error,
7645
+ itemCount: dataController.itemCount,
7646
+ setItemCount: dataController.setItemCount,
7647
+ pageSize: dataController.pageSize,
7648
+ paginationEnabled: dataController.paginationEnabled,
7649
+ onItemClick: onRowClick,
7650
+ selectedIds,
7651
+ highlightedIds,
7652
+ selectionEnabled: !!selectionEnabled,
7653
+ onSelectionChange: handleSelectionChange,
7654
+ size,
7655
+ renderCard,
7656
+ emptyComponent
7657
+ })
7658
+ });
7659
+ }
7660
+ //#endregion
7661
+ //#region src/views/CollectionView/CollectionListView.tsx
7662
+ /**
7663
+ * Headless list view that wraps {@link ListView}.
7664
+ *
7665
+ * Each row displays a title (bold), subtitle with 1–2 secondary property values,
7666
+ * and optional selection support.
7667
+ *
7668
+ * @group Collection View
7669
+ */
7670
+ function CollectionListView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, onRowClick, cellRenderer, size = "m", selectionEnabled, selectionController, highlightedItems, emptyComponent, className }) {
7671
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
7672
+ const titlePropertyKey = useMemo(() => {
7673
+ if (titleProperty) return titleProperty;
7674
+ for (const key of order) {
7675
+ const prop = properties[key];
7676
+ if (prop && prop.type === "string" && !prop.hideFromCollection && !prop.storage) return key;
7677
+ }
7678
+ return idProperty;
7679
+ }, [
7680
+ titleProperty,
7681
+ order,
7682
+ properties,
7683
+ idProperty
7684
+ ]);
7685
+ const subtitleProperties = useMemo(() => {
7686
+ const result = [];
7687
+ for (const key of order) {
7688
+ if (key === titlePropertyKey) continue;
7689
+ const prop = properties[key];
7690
+ if (prop && !prop.hideFromCollection) {
7691
+ result.push({
7692
+ key,
7693
+ property: prop
7694
+ });
7695
+ if (result.length >= 2) break;
7696
+ }
7697
+ }
7698
+ return result;
7699
+ }, [
7700
+ order,
7701
+ properties,
7702
+ titlePropertyKey
7703
+ ]);
7704
+ const selectedIds = useMemo(() => {
7705
+ if (!selectionController?.selectedItems) return void 0;
7706
+ const ids = /* @__PURE__ */ new Set();
7707
+ for (const item of selectionController.selectedItems) {
7708
+ const id = getValueInPath(item, idProperty);
7709
+ if (id !== void 0 && id !== null) ids.add(id);
7710
+ }
7711
+ return ids;
7712
+ }, [selectionController?.selectedItems, idProperty]);
7713
+ const highlightedIds = useMemo(() => {
7714
+ if (!highlightedItems) return void 0;
7715
+ const ids = /* @__PURE__ */ new Set();
7716
+ for (const item of highlightedItems) {
7717
+ const id = getValueInPath(item, idProperty);
7718
+ if (id !== void 0 && id !== null) ids.add(id);
7719
+ }
7720
+ return ids;
7721
+ }, [highlightedItems, idProperty]);
7722
+ const handleSelectionChange = useCallback((item, selected) => {
7723
+ if (!selectionController) return;
7724
+ selectionController.setSelectedItems((prev) => {
7725
+ if (selected) return [...prev, item];
7726
+ const itemId = getValueInPath(item, idProperty);
7727
+ return prev.filter((existing) => {
7728
+ return getValueInPath(existing, idProperty) !== itemId;
7729
+ });
7730
+ });
7731
+ }, [selectionController, idProperty]);
7732
+ const renderRow = useCallback((params) => {
7733
+ const { item, style, className: rowClassName, selected, highlighted, onClick, onSelectionChange } = params;
7734
+ const titleValue = getValueInPath(item, titlePropertyKey);
7735
+ return /* @__PURE__ */ jsxs("div", {
7736
+ style,
7737
+ className: cls("flex items-center gap-3 px-4 cursor-pointer", "hover:bg-surface-50 dark:hover:bg-surface-700", "transition-colors duration-100", selected && "bg-primary-50 dark:bg-primary-900/20", highlighted && "bg-surface-100 dark:bg-surface-800", rowClassName),
7738
+ onClick,
7739
+ children: [selectionEnabled && /* @__PURE__ */ jsx("div", {
7740
+ className: "flex-shrink-0",
7741
+ onClick: (e) => e.stopPropagation(),
7742
+ children: /* @__PURE__ */ jsx(Checkbox, {
7743
+ checked: selected,
7744
+ onCheckedChange: onSelectionChange,
7745
+ size: "small"
7746
+ })
7747
+ }), /* @__PURE__ */ jsxs("div", {
7748
+ className: "flex-1 min-w-0 py-1",
7749
+ children: [/* @__PURE__ */ jsx(Typography, {
7750
+ variant: "subtitle2",
7751
+ noWrap: true,
7752
+ children: String(titleValue ?? "")
7753
+ }), subtitleProperties.length > 0 && /* @__PURE__ */ jsx("div", {
7754
+ className: "flex items-center gap-2",
7755
+ children: subtitleProperties.map(({ key, property }) => {
7756
+ const value = getValueInPath(item, key);
7757
+ if (cellRenderer) {
7758
+ const custom = cellRenderer({
7759
+ row: item,
7760
+ propertyKey: key,
7761
+ property,
7762
+ value,
7763
+ size: "tiny"
7764
+ });
7765
+ if (custom !== void 0) return /* @__PURE__ */ jsx(React.Fragment, { children: custom }, key);
7766
+ }
7767
+ return /* @__PURE__ */ jsx(React.Fragment, { children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
7768
+ row: item,
7769
+ propertyKey: key,
7770
+ property,
7771
+ value,
7772
+ size: "tiny"
7773
+ }) }, key);
7774
+ })
7775
+ })]
7776
+ })]
7777
+ });
7778
+ }, [
7779
+ titlePropertyKey,
7780
+ subtitleProperties,
7781
+ cellRenderer,
7782
+ selectionEnabled
7783
+ ]);
7784
+ return /* @__PURE__ */ jsx("div", {
7785
+ className: cls("w-full h-full overflow-auto", className),
7786
+ children: /* @__PURE__ */ jsx(ListView, {
7787
+ data: dataController.data,
7788
+ dataLoading: dataController.loading,
7789
+ noMoreToLoad: dataController.noMoreToLoad,
7790
+ dataLoadingError: dataController.error,
7791
+ itemCount: dataController.itemCount,
7792
+ setItemCount: dataController.setItemCount,
7793
+ pageSize: dataController.pageSize,
7794
+ paginationEnabled: dataController.paginationEnabled,
7795
+ onItemClick: onRowClick,
7796
+ selectedIds,
7797
+ highlightedIds,
7798
+ selectionEnabled: !!selectionEnabled,
7799
+ onSelectionChange: handleSelectionChange,
7800
+ size,
7801
+ renderRow,
7802
+ emptyComponent
7803
+ })
7804
+ });
7805
+ }
7806
+ //#endregion
7807
+ //#region src/views/CollectionView/CollectionKanbanView.tsx
7808
+ function getEnumLabel(enumConfig, key) {
7809
+ if (!enumConfig) return key;
7810
+ if (enumConfig instanceof Map) {
7811
+ const cfg = enumConfig.get(key);
7812
+ if (!cfg) return key;
7813
+ return typeof cfg === "string" ? cfg : cfg.label;
7814
+ }
7815
+ const cfg = enumConfig[key];
7816
+ if (!cfg) return key;
7817
+ return typeof cfg === "string" ? cfg : cfg.label;
7818
+ }
7819
+ /**
7820
+ * Headless kanban view that wraps {@link KanbanView}.
7821
+ *
7822
+ * Groups data by a kanban property's enum values into columns.
7823
+ * Each card displays a title and 1–2 preview properties.
7824
+ *
7825
+ * @group Collection View
7826
+ */
7827
+ function CollectionKanbanView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, kanbanProperty, onRowClick, cellRenderer, emptyComponent, onRowCreate, className }) {
7828
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
7829
+ const columns = useMemo(() => {
7830
+ const kanbanConfig = properties[kanbanProperty];
7831
+ if (kanbanConfig?.enum) {
7832
+ if (kanbanConfig.enum instanceof Map) return Array.from(kanbanConfig.enum.keys()).map(String);
7833
+ return Object.keys(kanbanConfig.enum);
7834
+ }
7835
+ const seen = /* @__PURE__ */ new Set();
7836
+ for (const row of dataController.data) {
7837
+ const val = getValueInPath(row, kanbanProperty);
7838
+ if (val !== null && val !== void 0) seen.add(String(val));
7839
+ }
7840
+ return Array.from(seen);
7841
+ }, [
7842
+ properties,
7843
+ kanbanProperty,
7844
+ dataController.data
7845
+ ]);
7846
+ const columnLabels = useMemo(() => {
7847
+ const kanbanConfig = properties[kanbanProperty];
7848
+ const labels = {};
7849
+ for (const col of columns) labels[col] = getEnumLabel(kanbanConfig?.enum, col);
7850
+ return labels;
7851
+ }, [
7852
+ properties,
7853
+ kanbanProperty,
7854
+ columns
7855
+ ]);
7856
+ const titlePropertyKey = useMemo(() => {
7857
+ if (titleProperty) return titleProperty;
7858
+ for (const key of order) {
7859
+ const prop = properties[key];
7860
+ if (prop && prop.type === "string" && !prop.hideFromCollection && !prop.storage) return key;
7861
+ }
7862
+ return idProperty;
7863
+ }, [
7864
+ titleProperty,
7865
+ order,
7866
+ properties,
7867
+ idProperty
7868
+ ]);
7869
+ const previewProperties = useMemo(() => {
7870
+ const result = [];
7871
+ for (const key of order) {
7872
+ if (key === titlePropertyKey || key === kanbanProperty) continue;
7873
+ const prop = properties[key];
7874
+ if (prop && !prop.hideFromCollection) {
7875
+ result.push({
7876
+ key,
7877
+ property: prop
7878
+ });
7879
+ if (result.length >= 2) break;
7880
+ }
7881
+ }
7882
+ return result;
7883
+ }, [
7884
+ order,
7885
+ properties,
7886
+ titlePropertyKey,
7887
+ kanbanProperty
7888
+ ]);
7889
+ const boardItems = useMemo(() => {
7890
+ return dataController.data.map((row, index) => {
7891
+ const id = getValueInPath(row, idProperty);
7892
+ return {
7893
+ id: id !== null && id !== void 0 ? String(id) : String(index),
7894
+ data: row
7895
+ };
7896
+ });
7897
+ }, [dataController.data, idProperty]);
7898
+ const assignColumn = useCallback((item) => {
7899
+ const val = getValueInPath(item.data, kanbanProperty);
7900
+ const strVal = val !== null && val !== void 0 ? String(val) : "";
7901
+ if (columns.includes(strVal)) return strVal;
7902
+ return columns[0] ?? "";
7903
+ }, [kanbanProperty, columns]);
7904
+ const ItemComponent = useMemo(() => {
7905
+ function KanbanCard(props) {
7906
+ const { item } = props;
7907
+ const titleValue = getValueInPath(item.data, titlePropertyKey);
7908
+ return /* @__PURE__ */ jsxs(Card, {
7909
+ onClick: () => onRowClick?.(item.data),
7910
+ className: cls("p-3", cardClickableMixin, props.isDragging && "bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75", props.isDragging && "shadow-lg opacity-75"),
7911
+ children: [/* @__PURE__ */ jsx(Typography, {
7912
+ variant: "subtitle2",
7913
+ noWrap: true,
7914
+ children: String(titleValue ?? "")
7915
+ }), previewProperties.map(({ key, property }) => {
7916
+ const value = getValueInPath(item.data, key);
7917
+ if (cellRenderer) {
7918
+ const custom = cellRenderer({
7919
+ row: item.data,
7920
+ propertyKey: key,
7921
+ property,
7922
+ value,
7923
+ size: "tiny"
7924
+ });
7925
+ if (custom !== void 0) return /* @__PURE__ */ jsx("div", {
7926
+ className: "mt-1",
7927
+ children: custom
7928
+ }, key);
7929
+ }
7930
+ return /* @__PURE__ */ jsx("div", {
7931
+ className: "mt-1",
7932
+ children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
7933
+ row: item.data,
7934
+ propertyKey: key,
7935
+ property,
7936
+ value,
7937
+ size: "tiny"
7938
+ })
7939
+ }, key);
7940
+ })]
7941
+ });
7942
+ }
7943
+ return KanbanCard;
7944
+ }, [
7945
+ titlePropertyKey,
7946
+ previewProperties,
7947
+ cellRenderer,
7948
+ onRowClick
7949
+ ]);
7950
+ const handleAddItemToColumn = useCallback((column) => {
7951
+ onRowCreate?.({ [kanbanProperty]: column });
7952
+ }, [onRowCreate, kanbanProperty]);
7953
+ if (columns.length === 0 && !dataController.loading) return /* @__PURE__ */ jsx("div", {
7954
+ className: "flex items-center justify-center p-8",
7955
+ children: emptyComponent ?? /* @__PURE__ */ jsx(Typography, {
7956
+ variant: "body2",
7957
+ color: "secondary",
7958
+ children: "No columns available for kanban view."
7959
+ })
7960
+ });
7961
+ return /* @__PURE__ */ jsx(KanbanView, {
7962
+ columns,
7963
+ columnLabels,
7964
+ data: boardItems,
7965
+ assignColumn,
7966
+ ItemComponent,
7967
+ onAddItemToColumn: onRowCreate ? handleAddItemToColumn : void 0,
7968
+ className
7969
+ });
7970
+ }
7971
+ //#endregion
7972
+ //#region src/views/CollectionView/CollectionView.tsx
7973
+ var DEFAULT_ENABLED_VIEWS = [
7974
+ "list",
7975
+ "table",
7976
+ "cards",
7977
+ "kanban"
7978
+ ];
7979
+ /**
7980
+ * A data-agnostic collection view component that orchestrates table, card,
7981
+ * list, and kanban views — driven entirely by props.
7982
+ *
7983
+ * Zero imports from any entity or data layer. This component lives in
7984
+ * `@rebasepro/ui` and can be used with any data source.
7985
+ *
7986
+ * @example
7987
+ * ```tsx
7988
+ * import { CollectionView } from "@rebasepro/ui";
7989
+ *
7990
+ * <CollectionView
7991
+ * dataController={{ data: myRows, loading: false, noMoreToLoad: true }}
7992
+ * properties={{
7993
+ * name: { type: "string", name: "Name" },
7994
+ * email: { type: "string", name: "Email" },
7995
+ * }}
7996
+ * title="Contacts"
7997
+ * onRowClick={(row) => openDetail(row.id)}
7998
+ * />
7999
+ * ```
8000
+ *
8001
+ * @group Collection View
8002
+ */
8003
+ function CollectionView({ dataController, properties, propertiesOrder, displayedColumnIds, idProperty = "id", titleProperty, title, viewMode: viewModeProp, defaultViewMode = "list", enabledViews = DEFAULT_ENABLED_VIEWS, onViewModeChange: onViewModeChangeProp, size: sizeProp, defaultSize = "m", onSizeChange: onSizeChangeProp, kanbanProperty: kanbanPropertyProp, kanbanPropertyOptions, onKanbanPropertyChange: onKanbanPropertyChangeProp, onRowClick, onRowCreate, canCreate = true, selectionEnabled, selectionController, highlightedItems, onMultipleDelete, cellRenderer, emptyComponent, toolbarActionsStart, toolbarActionsEnd, hideToolbar, hoverRow = true, onColumnResize, onColumnsOrderChange, className }) {
8004
+ const [internalViewMode, setInternalViewMode] = useState(defaultViewMode);
8005
+ const viewMode = viewModeProp ?? internalViewMode;
8006
+ const onViewModeChange = useCallback((mode) => {
8007
+ setInternalViewMode(mode);
8008
+ onViewModeChangeProp?.(mode);
8009
+ }, [onViewModeChangeProp]);
8010
+ const [internalSize, setInternalSize] = useState(defaultSize);
8011
+ const size = sizeProp ?? internalSize;
8012
+ const onSizeChange = useCallback((s) => {
8013
+ setInternalSize(s);
8014
+ onSizeChangeProp?.(s);
8015
+ }, [onSizeChangeProp]);
8016
+ const [internalKanbanProperty, setInternalKanbanProperty] = useState(kanbanPropertyProp);
8017
+ const kanbanProperty = kanbanPropertyProp ?? internalKanbanProperty;
8018
+ const onKanbanPropertyChange = useCallback((property) => {
8019
+ setInternalKanbanProperty(property);
8020
+ onKanbanPropertyChangeProp?.(property);
8021
+ }, [onKanbanPropertyChangeProp]);
8022
+ const resolvedKanbanProperty = useMemo(() => {
8023
+ if (kanbanProperty) return kanbanProperty;
8024
+ const order = propertiesOrder ?? Object.keys(properties);
8025
+ for (const key of order) {
8026
+ const prop = properties[key];
8027
+ if (prop && prop.type === "string" && prop.enum) return key;
8028
+ }
8029
+ }, [
8030
+ kanbanProperty,
8031
+ properties,
8032
+ propertiesOrder
8033
+ ]);
8034
+ const resolvedKanbanPropertyOptions = useMemo(() => {
8035
+ if (kanbanPropertyOptions) return kanbanPropertyOptions;
8036
+ const options = [];
8037
+ const order = propertiesOrder ?? Object.keys(properties);
8038
+ for (const key of order) {
8039
+ const prop = properties[key];
8040
+ if (prop && prop.type === "string" && prop.enum) options.push({
8041
+ key,
8042
+ label: prop.name
8043
+ });
8044
+ }
8045
+ return options;
8046
+ }, [
8047
+ kanbanPropertyOptions,
8048
+ properties,
8049
+ propertiesOrder
8050
+ ]);
8051
+ const sharedProps = {
8052
+ dataController,
8053
+ properties,
8054
+ propertiesOrder,
8055
+ idProperty,
8056
+ titleProperty,
8057
+ onRowClick,
8058
+ cellRenderer,
8059
+ selectionEnabled,
8060
+ selectionController,
8061
+ highlightedItems,
8062
+ emptyComponent
8063
+ };
8064
+ function renderView() {
8065
+ switch (viewMode) {
8066
+ case "table": return /* @__PURE__ */ jsx(CollectionTableView, {
8067
+ ...sharedProps,
8068
+ displayedColumnIds,
8069
+ size,
8070
+ hoverRow,
8071
+ onColumnResize,
8072
+ onColumnsOrderChange
8073
+ });
8074
+ case "cards": return /* @__PURE__ */ jsx(CollectionCardView, {
8075
+ ...sharedProps,
8076
+ size
8077
+ });
8078
+ case "kanban": return resolvedKanbanProperty ? /* @__PURE__ */ jsx(CollectionKanbanView, {
8079
+ ...sharedProps,
8080
+ kanbanProperty: resolvedKanbanProperty,
8081
+ onRowCreate
8082
+ }) : /* @__PURE__ */ jsx("div", {
8083
+ className: "flex items-center justify-center p-8",
8084
+ children: /* @__PURE__ */ jsx(Typography, {
8085
+ variant: "body2",
8086
+ color: "secondary",
8087
+ children: "No enum property available for kanban grouping."
8088
+ })
8089
+ });
8090
+ default: return /* @__PURE__ */ jsx(CollectionListView, {
8091
+ ...sharedProps,
8092
+ size
8093
+ });
8094
+ }
8095
+ }
8096
+ return /* @__PURE__ */ jsxs("div", {
8097
+ className: cls("overflow-hidden h-full w-full rounded-md flex flex-col", "dark:bg-surface-800", className),
8098
+ children: [
8099
+ dataController.error && dataController.data.length > 0 && /* @__PURE__ */ jsx("div", {
8100
+ className: "flex items-center gap-4 px-4 py-2 bg-red-50 dark:bg-red-900/20 border-b border-red-200 dark:border-red-800 flex-shrink-0",
8101
+ children: /* @__PURE__ */ jsxs(Typography, {
8102
+ variant: "body2",
8103
+ className: "text-red-700 dark:text-red-300 flex-1",
8104
+ children: [
8105
+ /* @__PURE__ */ jsx("strong", { children: "Warning:" }),
8106
+ " ",
8107
+ dataController.error.message || "Failed to update data."
8108
+ ]
8109
+ })
8110
+ }),
8111
+ !hideToolbar && /* @__PURE__ */ jsx(CollectionViewToolbar, {
8112
+ viewMode,
8113
+ onViewModeChange: enabledViews.length > 1 ? onViewModeChange : void 0,
8114
+ enabledViews,
8115
+ size,
8116
+ onSizeChange,
8117
+ searchString: dataController.searchString,
8118
+ onSearchChange: dataController.setSearchString,
8119
+ loading: dataController.loading,
8120
+ actionsStart: toolbarActionsStart,
8121
+ actionsEnd: toolbarActionsEnd,
8122
+ kanbanPropertyOptions: viewMode === "kanban" ? resolvedKanbanPropertyOptions : void 0,
8123
+ selectedKanbanProperty: resolvedKanbanProperty,
8124
+ onKanbanPropertyChange
8125
+ }),
8126
+ /* @__PURE__ */ jsx("div", {
8127
+ className: "flex-1 overflow-hidden",
8128
+ children: renderView()
8129
+ })
8130
+ ]
8131
+ });
8132
+ }
8133
+ //#endregion
8134
+ export { Alert, AlertCircleIcon, AlertTriangleIcon, AlignLeftIcon, AppWindow, ArrowDownToLineIcon, ArrowLeftIcon, ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, ArrowUpToLineIcon, Autocomplete, AutocompleteItem, Avatar, Badge, BoldIcon, BookOpenIcon, BooleanSwitch, BooleanSwitchWithLabel, Button, CHIP_COLORS, CalendarIcon, Card, CardView, CenteredView, CheckCircleIcon, CheckIcon, CheckSquareIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ChevronsUpDownIcon, Chip, CircleIcon, CircleUserIcon, CircularProgress, CircularProgressCenter, CodeIcon, Collapse, CollectionCardView, CollectionKanbanView, CollectionListView, CollectionTableView, CollectionView, CollectionViewToolbar, ColorPicker, ColumnsIcon, Container, CopyIcon, DatabaseIcon, DateTimeField, DebouncedTextField, DefaultCellRenderer, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, ErrorBoundary, ExpandablePanel, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileIcon, FileSearchIcon, FileTextIcon, FileUpload, FilterChip, FilterIcon, FilterXIcon, FlagIcon, FolderIcon, FolderPlusIcon, FolderUpIcon, FunctionSquareIcon, GitBranchIcon, GitHubIcon, GlobeIcon, HandleIcon, HashIcon, Heading1Icon, Heading2Icon, Heading3Icon, HelpCircleIcon, HistoryIcon, HomeIcon, IconButton, ImageIcon, ImageOffIcon, InfoIcon, InfoLabel, InputLabel, ItalicIcon, KanbanIcon, KanbanView, KeyIcon, KeyRoundIcon, Label, LanguagesIcon, LayoutGridIcon, Link2Icon, LinkIcon, ListIcon, ListOrderedIcon, ListView, LoaderIcon, LoadingButton, LockIcon, LogOutIcon, MailIcon, Markdown, Maximize2Icon, Menu, MenuIcon, MenuItem, Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarItemIndicator, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarSubTriggerIndicator, MenubarTrigger, MinusCircleIcon, MinusIcon, MoonIcon, MoreVerticalIcon, MultiSelect, MultiSelectContext, MultiSelectItem, Music2Icon, PanelLeftIcon, Paper, PauseIcon, PencilIcon, PhoneIcon, PlayIcon, PlusIcon, Popover, PopoverPrimitive, Portal, PortalContainerProvider, QuoteIcon, RadioGroup, RadioGroupItem, RefreshCcwIcon, RefreshCwIcon, RepeatIcon, ResizablePanels, Rows3Icon, SaveIcon, SearchBar, SearchIcon, Select, SelectGroup, SelectInputLabel, SelectItem, SendIcon, Separator, SettingsIcon, Sheet, ShieldIcon, ShoppingCartIcon, Skeleton, Slider, SlidersHorizontalIcon, Slot, SquareIcon, StarIcon, StrikethroughIcon, SunIcon, SunMoonIcon, Tab, Table, TableBody, TableCell, TableHeader, TableIcon, TableRow, VirtualTable as TableView, VirtualTable, Tabs, TagIcon, TerminalIcon, TextField, TextIcon, TextareaAutosize, ToggleButtonGroup, Tooltip, Trash2Icon, TypeIcon, Typography, UnderlineIcon, UndoIcon, UploadCloudIcon, UploadIcon, UserCheckIcon, UserIcon, UserPlus, VideoIcon, VoteIcon, Wand2Icon, XCircleIcon, XIcon, cardClickableMixin, cardMixin, cardSelectedMixin, cls, colorClassesMapping, coolIconKeys, debounce, defaultBorderMixin, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundInvisibleMixin, fieldBackgroundMixin, focusedClasses, focusedDisabled, focusedInvisibleMixin, getColorSchemeForKey, getColorSchemeForSeed, iconKeys, iconSize, keyToIconComponent, lucideIcons, paperMixin, useAutoComplete, useDebounceCallback, useDebounceValue, useDebouncedCallback, useInjectStyles, useOutsideAlerter, usePortalContainer };
6090
8135
 
6091
8136
  //# sourceMappingURL=index.es.js.map