@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.
- package/dist/icons/index.d.ts +1 -1
- package/dist/index.css +13 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +2119 -74
- package/dist/index.es.js.map +1 -1
- package/dist/src/index.css +13 -13
- package/dist/styles.d.ts +9 -9
- package/dist/views/CardView.d.ts +32 -0
- package/dist/views/CollectionView/CollectionCardView.d.ts +30 -0
- package/dist/views/CollectionView/CollectionKanbanView.d.ts +31 -0
- package/dist/views/CollectionView/CollectionListView.d.ts +30 -0
- package/dist/views/CollectionView/CollectionTableView.d.ts +37 -0
- package/dist/views/CollectionView/CollectionView.d.ts +121 -0
- package/dist/views/CollectionView/CollectionViewToolbar.d.ts +31 -0
- package/dist/views/CollectionView/CollectionViewTypes.d.ts +106 -0
- package/dist/views/CollectionView/DefaultCellRenderer.d.ts +9 -0
- package/dist/views/CollectionView/index.d.ts +24 -0
- package/dist/views/CollectionView/utils.d.ts +5 -0
- package/dist/views/Kanban/Board.d.ts +3 -0
- package/dist/views/Kanban/BoardColumn.d.ts +20 -0
- package/dist/views/Kanban/BoardColumnTitle.d.ts +8 -0
- package/dist/views/Kanban/BoardSortableList.d.ts +14 -0
- package/dist/views/Kanban/board_types.d.ts +61 -0
- package/dist/views/Kanban/index.d.ts +5 -0
- package/dist/views/KanbanView.d.ts +24 -0
- package/dist/views/ListView.d.ts +40 -0
- package/dist/views/TableView.d.ts +6 -0
- package/dist/views/index.d.ts +5 -0
- package/package.json +1 -1
- package/src/components/Alert.tsx +1 -1
- package/src/components/BooleanSwitchWithLabel.tsx +1 -1
- package/src/components/Button.tsx +5 -5
- package/src/components/Chip.tsx +39 -37
- package/src/components/DateTimeField.tsx +2 -2
- package/src/components/Dialog.tsx +1 -1
- package/src/components/ExpandablePanel.tsx +1 -1
- package/src/components/FileUpload.tsx +1 -1
- package/src/components/FilterChip.tsx +2 -2
- package/src/components/IconButton.tsx +1 -1
- package/src/components/MultiSelect.tsx +1 -1
- package/src/components/Select.tsx +2 -2
- package/src/components/Sheet.tsx +8 -4
- package/src/components/Table.tsx +2 -2
- package/src/components/TextField.tsx +3 -3
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/icons/index.ts +3 -0
- package/src/index.css +13 -13
- package/src/index.ts +2 -0
- package/src/styles.ts +9 -9
- package/src/views/CardView.tsx +281 -0
- package/src/views/CollectionView/CollectionCardView.tsx +270 -0
- package/src/views/CollectionView/CollectionKanbanView.tsx +251 -0
- package/src/views/CollectionView/CollectionListView.tsx +245 -0
- package/src/views/CollectionView/CollectionTableView.tsx +229 -0
- package/src/views/CollectionView/CollectionView.tsx +388 -0
- package/src/views/CollectionView/CollectionViewToolbar.tsx +229 -0
- package/src/views/CollectionView/CollectionViewTypes.ts +137 -0
- package/src/views/CollectionView/DefaultCellRenderer.tsx +404 -0
- package/src/views/CollectionView/index.ts +44 -0
- package/src/views/CollectionView/utils.ts +14 -0
- package/src/views/Kanban/Board.tsx +421 -0
- package/src/views/Kanban/BoardColumn.tsx +135 -0
- package/src/views/Kanban/BoardColumnTitle.tsx +47 -0
- package/src/views/Kanban/BoardSortableList.tsx +170 -0
- package/src/views/Kanban/board_types.ts +70 -0
- package/src/views/Kanban/index.tsx +5 -0
- package/src/views/KanbanView.tsx +32 -0
- package/src/views/ListView.tsx +281 -0
- package/src/views/TableView.tsx +7 -0
- package/src/views/index.ts +5 -0
- package/dist/index.umd.js +0 -6958
- 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-
|
|
191
|
-
var fieldBackgroundMixin = "bg-
|
|
192
|
-
var fieldBackgroundInvisibleMixin = "bg-
|
|
193
|
-
var fieldBackgroundDisabledMixin = "
|
|
194
|
-
var fieldBackgroundHoverMixin = "hover:bg-
|
|
195
|
-
var defaultBorderMixin = "border-surface-200
|
|
196
|
-
var paperMixin = "bg-white rounded-
|
|
197
|
-
var cardMixin = "bg-white dark:bg-surface-900 rounded-
|
|
198
|
-
var cardClickableMixin = "hover:bg-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
592
|
-
"border border-secondary bg-secondary focus:ring-secondary
|
|
593
|
-
"border border-red-500 bg-red-500 hover:bg-red-600 focus:ring-red-500
|
|
594
|
-
"border border-surface-accent-200 bg-surface-accent-200 hover:bg-surface-accent-300 focus:ring-surface-accent-400
|
|
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-
|
|
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-
|
|
1011
|
-
small: "px-2 py-0.5 text-
|
|
1012
|
-
medium: "px-
|
|
1013
|
-
large: "px-
|
|
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 = "
|
|
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
|
|
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
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
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-
|
|
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
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
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: [
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
-
}),
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|