uibee 3.1.1 → 3.1.3
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/src/components/index.d.ts +59 -27
- package/dist/src/components/index.js +825 -339
- package/dist/style.css +283 -67
- package/package.json +1 -1
- package/src/components/buttons/button.tsx +6 -3
- package/src/components/index.ts +2 -17
- package/src/components/navbar/navbar.tsx +0 -5
- package/src/components/navbar/navbarDropdown.tsx +0 -2
- package/src/components/navbar/navbarItem.tsx +0 -2
- package/src/components/table/body.tsx +260 -153
- package/src/components/table/constants.ts +53 -0
- package/src/components/table/empty.tsx +31 -0
- package/src/components/table/format.ts +29 -22
- package/src/components/table/header.tsx +115 -70
- package/src/components/table/menu.tsx +43 -27
- package/src/components/table/pagination.tsx +162 -136
- package/src/components/table/skeleton.tsx +56 -0
- package/src/components/table/table.tsx +261 -34
- package/src/components/table/types.ts +94 -0
- package/src/components/table/utils.ts +12 -0
- package/src/components/toggle/theme.tsx +0 -3
- package/src/globals.css +11 -0
- package/src/utils/auth/callback.ts +0 -2
- package/src/utils/index.ts +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as useClickOutside } from "../../useClickOutside-Cmp-RsP3.js";
|
|
2
|
+
import { t as useClickOutside$1 } from "../../useClickOutside-Cmp-RsP3.js";
|
|
3
3
|
import { D as Facebook, Kt as Wikijs, N as Github, W as Linkedin, x as Discord } from "../../icons-lZYQ6Vlr.js";
|
|
4
|
-
import React, { createContext, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { AlertCircle, AlertTriangle, ArrowUpRight, Calendar, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, CircleAlert, CircleHelp, Clock, EllipsisVertical, ExternalLink, Eye, Globe, Info, LogIn, LogOut, Pencil, Search, TriangleAlert, User, X } from "lucide-react";
|
|
4
|
+
import React, { Suspense, createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { AlertCircle, AlertTriangle, ArrowUpRight, Calendar, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, CircleAlert, CircleHelp, Clock, EllipsisVertical, ExternalLink, Eye, Globe, Info, LogIn, LogOut, Pencil, Search, TableIcon, TriangleAlert, User, X } from "lucide-react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import Markdown from "react-markdown";
|
|
8
8
|
import remarkGfm from "remark-gfm";
|
|
@@ -651,7 +651,7 @@ function Input(props) {
|
|
|
651
651
|
const [isOpen, setIsOpen] = useState(false);
|
|
652
652
|
const anchorName = `--input-${useId().replace(/:/g, "")}`;
|
|
653
653
|
const containerRef = useRef(null);
|
|
654
|
-
useClickOutside(containerRef, () => setIsOpen(false));
|
|
654
|
+
useClickOutside$1(containerRef, () => setIsOpen(false));
|
|
655
655
|
const isDateType = [
|
|
656
656
|
"date",
|
|
657
657
|
"datetime-local",
|
|
@@ -988,7 +988,7 @@ function Select({ label, name, value, onChange, options, error, className, disab
|
|
|
988
988
|
setSelectedOption(options.find((opt) => opt.value === value));
|
|
989
989
|
}, [value, options]);
|
|
990
990
|
const containerRef = useRef(null);
|
|
991
|
-
useClickOutside(containerRef, () => setIsOpen(false));
|
|
991
|
+
useClickOutside$1(containerRef, () => setIsOpen(false));
|
|
992
992
|
function handleSelect(option) {
|
|
993
993
|
if (disabled) return;
|
|
994
994
|
setSelectedOption(option);
|
|
@@ -1200,7 +1200,7 @@ function TagInput({ label, name, value = [], onChange, placeholder = "Add...", e
|
|
|
1200
1200
|
function MultiSelect({ label, name, options, value = [], onChange, placeholder = "Select…", error, className, disabled, required, info, description, textSize = "sm" }) {
|
|
1201
1201
|
const [open, setOpen] = useState(false);
|
|
1202
1202
|
const containerRef = useRef(null);
|
|
1203
|
-
useClickOutside(containerRef, () => setOpen(false));
|
|
1203
|
+
useClickOutside$1(containerRef, () => setOpen(false));
|
|
1204
1204
|
function toggleOption(optionValue) {
|
|
1205
1205
|
if (!onChange) return;
|
|
1206
1206
|
if (value.includes(optionValue)) onChange(value.filter((v) => v !== optionValue));
|
|
@@ -2649,7 +2649,9 @@ const variants = {
|
|
|
2649
2649
|
success: "bg-green-600 text-white hover:brightness-110",
|
|
2650
2650
|
info: "bg-blue-600 text-white hover:brightness-110"
|
|
2651
2651
|
};
|
|
2652
|
-
const base = "cursor-pointer
|
|
2652
|
+
const base = "cursor-pointer rounded-md h-9 flex items-center justify-center gap-2 select-none text-sm font-medium transition-all duration-150";
|
|
2653
|
+
const withText = "px-4 w-fit";
|
|
2654
|
+
const iconOnly = "w-9";
|
|
2653
2655
|
const disabledCls = "opacity-40 cursor-not-allowed pointer-events-none";
|
|
2654
2656
|
const iconWrap = (icon) => icon ? /* @__PURE__ */ jsx("span", {
|
|
2655
2657
|
className: "[&>svg]:w-4 [&>svg]:h-4 flex items-center",
|
|
@@ -2657,7 +2659,8 @@ const iconWrap = (icon) => icon ? /* @__PURE__ */ jsx("span", {
|
|
|
2657
2659
|
}) : null;
|
|
2658
2660
|
function Button({ text, className, icon, path, variant = "primary", type, onClick, disabled }) {
|
|
2659
2661
|
const color = variants[variant];
|
|
2660
|
-
const
|
|
2662
|
+
const sizing = icon && !text ? iconOnly : withText;
|
|
2663
|
+
const cls = `${base} ${sizing} ${color} ${disabled ? disabledCls : ""} ${className || ""}`;
|
|
2661
2664
|
if (!path) return /* @__PURE__ */ jsxs("button", {
|
|
2662
2665
|
type: type || "button",
|
|
2663
2666
|
disabled,
|
|
@@ -2672,7 +2675,7 @@ function Button({ text, className, icon, path, variant = "primary", type, onClic
|
|
|
2672
2675
|
});
|
|
2673
2676
|
return /* @__PURE__ */ jsxs(Link, {
|
|
2674
2677
|
href: path,
|
|
2675
|
-
className: `${base} ${color} ${className || ""}`,
|
|
2678
|
+
className: `${base} ${sizing} ${color} ${className || ""}`,
|
|
2676
2679
|
children: [iconWrap(icon), text]
|
|
2677
2680
|
});
|
|
2678
2681
|
}
|
|
@@ -2702,138 +2705,387 @@ function Alert({ children, variant = "warning", className = "" }) {
|
|
|
2702
2705
|
});
|
|
2703
2706
|
}
|
|
2704
2707
|
//#endregion
|
|
2708
|
+
//#region src/components/table/constants.ts
|
|
2709
|
+
const HIGHLIGHT = {
|
|
2710
|
+
green: "bg-green-500/15 text-green-400 ring-1 ring-green-500/25",
|
|
2711
|
+
yellow: "bg-yellow-500/15 text-yellow-400 ring-1 ring-yellow-500/25",
|
|
2712
|
+
red: "bg-red-500/15 text-red-400 ring-1 ring-red-500/25",
|
|
2713
|
+
blue: "bg-blue-500/15 text-blue-400 ring-1 ring-blue-500/25",
|
|
2714
|
+
gray: "bg-gray-500/15 text-gray-400 ring-1 ring-gray-500/25",
|
|
2715
|
+
orange: "bg-orange-500/15 text-orange-400 ring-1 ring-orange-500/25",
|
|
2716
|
+
purple: "bg-purple-500/15 text-purple-400 ring-1 ring-purple-500/25"
|
|
2717
|
+
};
|
|
2718
|
+
const DENSITY_TH = {
|
|
2719
|
+
compact: "px-4 py-2",
|
|
2720
|
+
comfortable: "px-6 py-3",
|
|
2721
|
+
spacious: "px-8 py-4"
|
|
2722
|
+
};
|
|
2723
|
+
const DENSITY_TD = {
|
|
2724
|
+
compact: "px-4 py-1.5",
|
|
2725
|
+
comfortable: "px-6 py-3.5",
|
|
2726
|
+
spacious: "px-8 py-5"
|
|
2727
|
+
};
|
|
2728
|
+
const VARIANT_CONTAINER = {
|
|
2729
|
+
original: "bg-login-500/50 rounded-lg border border-login-600 shadow",
|
|
2730
|
+
modern: "bg-transparent"
|
|
2731
|
+
};
|
|
2732
|
+
const VARIANT_THEAD = {
|
|
2733
|
+
original: "bg-login-700",
|
|
2734
|
+
modern: "bg-transparent border-b border-login-500/40"
|
|
2735
|
+
};
|
|
2736
|
+
const VARIANT_THEAD_TH = {
|
|
2737
|
+
original: "text-login-200",
|
|
2738
|
+
modern: "text-login-300"
|
|
2739
|
+
};
|
|
2740
|
+
const VARIANT_TBODY = {
|
|
2741
|
+
original: "bg-login-500/50 divide-login-600",
|
|
2742
|
+
modern: "divide-login-600/15"
|
|
2743
|
+
};
|
|
2744
|
+
const VARIANT_ROW_HOVER = {
|
|
2745
|
+
original: "hover:bg-login-600/30",
|
|
2746
|
+
modern: "hover:bg-login-700/50"
|
|
2747
|
+
};
|
|
2748
|
+
const VARIANT_ROW_STRIPED = {
|
|
2749
|
+
original: "even:bg-login-600/40",
|
|
2750
|
+
modern: "even:bg-login-800/40"
|
|
2751
|
+
};
|
|
2752
|
+
//#endregion
|
|
2753
|
+
//#region src/components/table/header.tsx
|
|
2754
|
+
function formatLabel(key, label) {
|
|
2755
|
+
if (label) return label;
|
|
2756
|
+
if (key.length <= 2) return key.toUpperCase();
|
|
2757
|
+
return key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ").replaceAll("-", " ").split(/\s+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
2758
|
+
}
|
|
2759
|
+
function Header({ columns, sort, onSort, hasMenu, hasSelect, hasExpand, allSelected, someSelected, onSelectAll, variant, density }) {
|
|
2760
|
+
function handleSort(key) {
|
|
2761
|
+
onSort({
|
|
2762
|
+
column: key,
|
|
2763
|
+
order: sort?.column === key && sort?.order === "asc" ? "desc" : "asc"
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
return /* @__PURE__ */ jsx("thead", {
|
|
2767
|
+
className: `block w-full sticky top-0 z-10 ${VARIANT_THEAD[variant]}`,
|
|
2768
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
2769
|
+
className: "flex w-full",
|
|
2770
|
+
children: [
|
|
2771
|
+
hasSelect && /* @__PURE__ */ jsx("th", {
|
|
2772
|
+
className: "flex items-center justify-center",
|
|
2773
|
+
style: {
|
|
2774
|
+
width: "3rem",
|
|
2775
|
+
minWidth: "3rem",
|
|
2776
|
+
flexShrink: 0
|
|
2777
|
+
},
|
|
2778
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
2779
|
+
type: "button",
|
|
2780
|
+
"aria-label": allSelected ? "Deselect all" : "Select all",
|
|
2781
|
+
onClick: onSelectAll,
|
|
2782
|
+
className: `
|
|
2783
|
+
h-4 w-4 rounded border flex items-center justify-center transition-colors cursor-pointer
|
|
2784
|
+
${allSelected || someSelected ? "bg-login border-login text-white" : "border-login-400 bg-transparent hover:border-login-200"}
|
|
2785
|
+
`,
|
|
2786
|
+
children: [someSelected && !allSelected && /* @__PURE__ */ jsx("span", { className: "block h-0.5 w-2 bg-white rounded-full" }), allSelected && /* @__PURE__ */ jsx("svg", {
|
|
2787
|
+
className: "h-3 w-3",
|
|
2788
|
+
viewBox: "0 0 12 12",
|
|
2789
|
+
fill: "none",
|
|
2790
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
2791
|
+
d: "M2 6l3 3 5-5",
|
|
2792
|
+
stroke: "currentColor",
|
|
2793
|
+
strokeWidth: "1.5",
|
|
2794
|
+
strokeLinecap: "round",
|
|
2795
|
+
strokeLinejoin: "round"
|
|
2796
|
+
})
|
|
2797
|
+
})]
|
|
2798
|
+
})
|
|
2799
|
+
}),
|
|
2800
|
+
columns.map((col) => {
|
|
2801
|
+
const sortable = col.sortable !== false;
|
|
2802
|
+
const isActive = sort?.column === col.key;
|
|
2803
|
+
const ariaSort = isActive ? sort.order === "asc" ? "ascending" : "descending" : "none";
|
|
2804
|
+
const alignClass = col.align === "right" ? "justify-end" : col.align === "center" ? "justify-center" : "";
|
|
2805
|
+
return /* @__PURE__ */ jsx("th", {
|
|
2806
|
+
"aria-sort": sortable ? ariaSort : void 0,
|
|
2807
|
+
style: col.width ? {
|
|
2808
|
+
width: col.width,
|
|
2809
|
+
flexShrink: 0
|
|
2810
|
+
} : void 0,
|
|
2811
|
+
className: `
|
|
2812
|
+
${col.width ? "" : "flex-1"}
|
|
2813
|
+
text-xs font-medium uppercase tracking-wider
|
|
2814
|
+
${DENSITY_TH[density]} ${VARIANT_THEAD_TH[variant]}
|
|
2815
|
+
`,
|
|
2816
|
+
children: sortable ? /* @__PURE__ */ jsxs("button", {
|
|
2817
|
+
type: "button",
|
|
2818
|
+
className: `group inline-flex items-center gap-1.5 w-full cursor-pointer ${alignClass}`,
|
|
2819
|
+
onClick: () => handleSort(col.key),
|
|
2820
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2821
|
+
className: "whitespace-nowrap",
|
|
2822
|
+
children: formatLabel(col.key, col.label)
|
|
2823
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2824
|
+
className: "shrink-0 text-current",
|
|
2825
|
+
children: isActive ? sort.order === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-3.5 w-3.5 opacity-0 group-hover:opacity-35 transition-opacity" })
|
|
2826
|
+
})]
|
|
2827
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
2828
|
+
className: `flex w-full ${alignClass}`,
|
|
2829
|
+
children: formatLabel(col.key, col.label)
|
|
2830
|
+
})
|
|
2831
|
+
}, col.key);
|
|
2832
|
+
}),
|
|
2833
|
+
hasExpand && /* @__PURE__ */ jsx("th", {
|
|
2834
|
+
className: "flex items-center justify-center",
|
|
2835
|
+
style: {
|
|
2836
|
+
width: "2.5rem",
|
|
2837
|
+
minWidth: "2.5rem",
|
|
2838
|
+
flexShrink: 0
|
|
2839
|
+
},
|
|
2840
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
2841
|
+
className: `text-xs font-medium tracking-wider uppercase opacity-50 ${VARIANT_THEAD_TH[variant]}`,
|
|
2842
|
+
children: "+"
|
|
2843
|
+
})
|
|
2844
|
+
}),
|
|
2845
|
+
hasMenu && /* @__PURE__ */ jsx("th", {
|
|
2846
|
+
"aria-hidden": "true",
|
|
2847
|
+
style: {
|
|
2848
|
+
width: "3.5rem",
|
|
2849
|
+
minWidth: "3.5rem",
|
|
2850
|
+
flexShrink: 0
|
|
2851
|
+
}
|
|
2852
|
+
})
|
|
2853
|
+
]
|
|
2854
|
+
})
|
|
2855
|
+
});
|
|
2856
|
+
}
|
|
2857
|
+
//#endregion
|
|
2858
|
+
//#region src/components/table/format.ts
|
|
2859
|
+
const nullableTimeKeys = /* @__PURE__ */ new Set([
|
|
2860
|
+
"date",
|
|
2861
|
+
"last_sent",
|
|
2862
|
+
"sent_at",
|
|
2863
|
+
"time"
|
|
2864
|
+
]);
|
|
2865
|
+
const RX_DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
|
|
2866
|
+
const RX_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
2867
|
+
const RX_TIME = /^\d{2}:\d{2}(:\d{2})?$/;
|
|
2868
|
+
function formatValue(key, value) {
|
|
2869
|
+
if (value === null || value === void 0) return nullableTimeKeys.has(key) ? "Never" : "-";
|
|
2870
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
2871
|
+
if (typeof value === "number") {
|
|
2872
|
+
if (key.includes("capacity") && value === 0) return "Unlimited";
|
|
2873
|
+
return value;
|
|
2874
|
+
}
|
|
2875
|
+
if (typeof value === "string") {
|
|
2876
|
+
if (RX_DATETIME.test(value)) return new Date(value).toLocaleString("nb-NO", {
|
|
2877
|
+
timeZone: "Europe/Oslo",
|
|
2878
|
+
year: "numeric",
|
|
2879
|
+
month: "2-digit",
|
|
2880
|
+
day: "2-digit",
|
|
2881
|
+
hour: "2-digit",
|
|
2882
|
+
minute: "2-digit"
|
|
2883
|
+
});
|
|
2884
|
+
if (RX_DATE.test(value)) return new Date(value).toLocaleDateString("nb-NO", { timeZone: "Europe/Oslo" });
|
|
2885
|
+
if (RX_TIME.test(value)) return (/* @__PURE__ */ new Date(`1970-01-01T${value}`)).toLocaleTimeString("nb-NO", {
|
|
2886
|
+
timeZone: "Europe/Oslo",
|
|
2887
|
+
hour: "2-digit",
|
|
2888
|
+
minute: "2-digit"
|
|
2889
|
+
});
|
|
2890
|
+
return value;
|
|
2891
|
+
}
|
|
2892
|
+
if (Array.isArray(value)) return value.join(", ");
|
|
2893
|
+
return String(value);
|
|
2894
|
+
}
|
|
2895
|
+
//#endregion
|
|
2896
|
+
//#region src/components/table/utils.ts
|
|
2897
|
+
function resolveId(row, idKey, columns) {
|
|
2898
|
+
if (idKey && row[idKey] !== void 0) return String(row[idKey]);
|
|
2899
|
+
if (row["id"] !== void 0) return String(row["id"]);
|
|
2900
|
+
const firstKey = columns[0]?.key ?? Object.keys(row)[0];
|
|
2901
|
+
return String(row[firstKey] ?? "");
|
|
2902
|
+
}
|
|
2903
|
+
//#endregion
|
|
2705
2904
|
//#region src/components/table/menu.tsx
|
|
2706
|
-
const
|
|
2905
|
+
const MenuCtx = createContext({});
|
|
2707
2906
|
function Menu({ ref, children, anchor, onClose }) {
|
|
2907
|
+
useEffect(() => {
|
|
2908
|
+
function handleKey(e) {
|
|
2909
|
+
if (e.key === "Escape") onClose?.();
|
|
2910
|
+
}
|
|
2911
|
+
window.addEventListener("keydown", handleKey);
|
|
2912
|
+
return () => window.removeEventListener("keydown", handleKey);
|
|
2913
|
+
}, [onClose]);
|
|
2708
2914
|
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
2709
2915
|
ref,
|
|
2916
|
+
role: "menu",
|
|
2917
|
+
"aria-orientation": "vertical",
|
|
2710
2918
|
style: {
|
|
2711
2919
|
top: anchor.top,
|
|
2712
2920
|
right: anchor.right
|
|
2713
2921
|
},
|
|
2714
|
-
className: "fixed
|
|
2715
|
-
children: /* @__PURE__ */ jsx(
|
|
2922
|
+
className: "fixed z-[9999] w-44 overflow-hidden rounded-lg border border-login-500/60 bg-login-600 shadow-xl shadow-black/40",
|
|
2923
|
+
children: /* @__PURE__ */ jsx(MenuCtx.Provider, {
|
|
2716
2924
|
value: { onClose },
|
|
2717
2925
|
children
|
|
2718
2926
|
})
|
|
2719
2927
|
}), document.body);
|
|
2720
2928
|
}
|
|
2721
|
-
function MenuButton({ icon, text, hotKey, onClick, className }) {
|
|
2722
|
-
const { onClose } = useContext(
|
|
2929
|
+
function MenuButton({ icon, text, hotKey, onClick, className = "" }) {
|
|
2930
|
+
const { onClose } = useContext(MenuCtx);
|
|
2723
2931
|
useEffect(() => {
|
|
2724
2932
|
if (!hotKey) return;
|
|
2725
|
-
function
|
|
2933
|
+
function handleKey(e) {
|
|
2934
|
+
const tag = e.target.tagName;
|
|
2935
|
+
if (tag === "INPUT" || tag === "TEXTAREA") return;
|
|
2726
2936
|
if (e.key.toLowerCase() === hotKey.toLowerCase()) {
|
|
2727
2937
|
e.preventDefault();
|
|
2728
2938
|
onClick();
|
|
2729
2939
|
onClose?.();
|
|
2730
2940
|
}
|
|
2731
2941
|
}
|
|
2732
|
-
window.addEventListener("keydown",
|
|
2733
|
-
return () => window.removeEventListener("keydown",
|
|
2942
|
+
window.addEventListener("keydown", handleKey);
|
|
2943
|
+
return () => window.removeEventListener("keydown", handleKey);
|
|
2734
2944
|
}, [
|
|
2735
2945
|
hotKey,
|
|
2736
2946
|
onClick,
|
|
2737
2947
|
onClose
|
|
2738
2948
|
]);
|
|
2739
2949
|
return /* @__PURE__ */ jsxs("button", {
|
|
2950
|
+
role: "menuitem",
|
|
2740
2951
|
onClick: () => {
|
|
2741
2952
|
onClick();
|
|
2742
2953
|
onClose?.();
|
|
2743
2954
|
},
|
|
2744
|
-
className: `
|
|
2745
|
-
|
|
2955
|
+
className: `
|
|
2956
|
+
flex w-full items-center justify-between px-3 py-2 text-sm
|
|
2957
|
+
text-login-75 transition-colors duration-100
|
|
2958
|
+
hover:bg-login-500 focus:bg-login-500 focus:outline-none
|
|
2959
|
+
first:rounded-t-lg last:rounded-b-lg
|
|
2960
|
+
${className}
|
|
2746
2961
|
`,
|
|
2747
|
-
children: [/* @__PURE__ */ jsxs("
|
|
2748
|
-
className: "flex items-center",
|
|
2749
|
-
children: [
|
|
2750
|
-
|
|
2751
|
-
|
|
2962
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
2963
|
+
className: "flex items-center gap-2",
|
|
2964
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2965
|
+
className: "h-4 w-4 shrink-0 flex items-center justify-center",
|
|
2966
|
+
children: icon
|
|
2967
|
+
}), text]
|
|
2968
|
+
}), hotKey && /* @__PURE__ */ jsx("kbd", {
|
|
2969
|
+
className: "font-mono text-xs opacity-40",
|
|
2752
2970
|
children: hotKey
|
|
2753
2971
|
})]
|
|
2754
2972
|
});
|
|
2755
2973
|
}
|
|
2756
2974
|
//#endregion
|
|
2757
|
-
//#region src/components/table/
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
}
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
};
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2975
|
+
//#region src/components/table/body.tsx
|
|
2976
|
+
function useClickOutside(ref, cb, enabled) {
|
|
2977
|
+
useEffect(() => {
|
|
2978
|
+
if (!enabled) return;
|
|
2979
|
+
function handler(e) {
|
|
2980
|
+
if (ref.current && !ref.current.contains(e.target)) cb();
|
|
2981
|
+
}
|
|
2982
|
+
document.addEventListener("mousedown", handler);
|
|
2983
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
2984
|
+
}, [
|
|
2985
|
+
ref,
|
|
2986
|
+
cb,
|
|
2987
|
+
enabled
|
|
2988
|
+
]);
|
|
2989
|
+
}
|
|
2990
|
+
function resolveRedirectUrl(redirectPath, row, id) {
|
|
2991
|
+
if (!redirectPath) return null;
|
|
2992
|
+
const cfg = typeof redirectPath === "string" ? {
|
|
2993
|
+
path: redirectPath,
|
|
2994
|
+
key: void 0
|
|
2995
|
+
} : redirectPath;
|
|
2996
|
+
if (!cfg.path) return null;
|
|
2997
|
+
const rid = cfg.key ? String(row[cfg.key] ?? id) : id;
|
|
2998
|
+
return cfg.path.includes("?") ? `${cfg.path}${rid}` : `${cfg.path}/${rid}`;
|
|
2999
|
+
}
|
|
3000
|
+
function Cell({ col, row, density }) {
|
|
3001
|
+
const value = row[col.key];
|
|
3002
|
+
const shouldTruncate = col.truncate === true;
|
|
3003
|
+
const align = col.align ?? "left";
|
|
3004
|
+
const wrapperAlign = align === "right" ? "text-right" : align === "center" ? "text-center" : "";
|
|
3005
|
+
let content;
|
|
3006
|
+
if (col.render) content = col.render(value, row);
|
|
3007
|
+
else if (col.highlight) {
|
|
3008
|
+
const colorName = col.highlight[String(value)] ?? col.highlight["default"];
|
|
3009
|
+
const formatted = String(formatValue(col.key, value));
|
|
3010
|
+
if (colorName) content = /* @__PURE__ */ jsx("span", {
|
|
3011
|
+
className: `inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${HIGHLIGHT[colorName]}`,
|
|
3012
|
+
children: formatted
|
|
3013
|
+
});
|
|
3014
|
+
else content = /* @__PURE__ */ jsx("span", {
|
|
3015
|
+
className: shouldTruncate ? "block truncate" : "whitespace-nowrap",
|
|
3016
|
+
children: formatted
|
|
3017
|
+
});
|
|
3018
|
+
} else {
|
|
3019
|
+
const formatted = formatValue(col.key, value);
|
|
3020
|
+
content = /* @__PURE__ */ jsx("span", {
|
|
3021
|
+
className: shouldTruncate ? "block truncate" : "whitespace-nowrap",
|
|
3022
|
+
children: formatted === null || formatted === void 0 ? "-" : String(formatted)
|
|
3023
|
+
});
|
|
2784
3024
|
}
|
|
2785
|
-
|
|
2786
|
-
|
|
3025
|
+
return /* @__PURE__ */ jsx("td", {
|
|
3026
|
+
style: col.width ? {
|
|
3027
|
+
width: col.width,
|
|
3028
|
+
flexShrink: 0
|
|
3029
|
+
} : void 0,
|
|
3030
|
+
className: `
|
|
3031
|
+
${col.width ? "" : "flex-1"} min-w-0 flex items-center text-sm text-login-75
|
|
3032
|
+
${DENSITY_TD[density]}
|
|
3033
|
+
`,
|
|
3034
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3035
|
+
className: `min-w-0 w-full ${wrapperAlign}`,
|
|
3036
|
+
children: content
|
|
3037
|
+
})
|
|
3038
|
+
});
|
|
2787
3039
|
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
function Body({ list, columns, menuItems, redirectPath, variant = "default", idKey }) {
|
|
3040
|
+
function Body({ data, columns, idKey, variant, density, striped, redirectPath, onRowClick, renderExpandedRow, selectable, selectedIds, onSelectionChange, menuItems }) {
|
|
3041
|
+
const router = useRouter();
|
|
2791
3042
|
const [openMenuId, setOpenMenuId] = useState(null);
|
|
2792
3043
|
const [anchor, setAnchor] = useState(null);
|
|
2793
|
-
const
|
|
3044
|
+
const [expandedId, setExpandedId] = useState(null);
|
|
2794
3045
|
const menuRef = useRef(null);
|
|
2795
3046
|
const tbodyRef = useRef(null);
|
|
2796
3047
|
const menuWasOpenOnMouseDown = useRef(false);
|
|
2797
|
-
|
|
3048
|
+
const closeMenu = useCallback(() => setOpenMenuId(null), []);
|
|
3049
|
+
useClickOutside(menuRef, closeMenu, openMenuId !== null);
|
|
2798
3050
|
useEffect(() => {
|
|
2799
3051
|
const el = tbodyRef.current;
|
|
2800
3052
|
if (!el) return;
|
|
2801
|
-
|
|
2802
|
-
el.
|
|
2803
|
-
|
|
2804
|
-
|
|
3053
|
+
el.addEventListener("scroll", closeMenu);
|
|
3054
|
+
return () => el.removeEventListener("scroll", closeMenu);
|
|
3055
|
+
}, [closeMenu]);
|
|
3056
|
+
function openMenu(id, coords) {
|
|
3057
|
+
setAnchor(coords);
|
|
3058
|
+
setOpenMenuId(id);
|
|
3059
|
+
}
|
|
3060
|
+
const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]);
|
|
3061
|
+
function toggleSelect(id) {
|
|
3062
|
+
onSelectionChange(selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]);
|
|
3063
|
+
}
|
|
3064
|
+
const hasMenu = Boolean(menuItems);
|
|
3065
|
+
const hasExpand = Boolean(renderExpandedRow);
|
|
2805
3066
|
return /* @__PURE__ */ jsx("tbody", {
|
|
2806
3067
|
ref: tbodyRef,
|
|
2807
|
-
className: `
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
const
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
};
|
|
2829
|
-
const buttonClass = openMenuId === id ? menuButtonColors.active : menuButtonColors.inactive;
|
|
2830
|
-
return /* @__PURE__ */ jsxs("tr", {
|
|
2831
|
-
className: `
|
|
2832
|
-
flex w-full group/row transition-colors
|
|
2833
|
-
${redirectConfig.path ? "cursor-pointer" : ""}
|
|
2834
|
-
${variant === "default" && redirectConfig.path ? "hover:bg-login-600/80" : ""}
|
|
2835
|
-
${variant === "minimal" ? "hover:bg-login-600/70 border-b border-login-600/20 last:border-0" : ""}
|
|
2836
|
-
`,
|
|
3068
|
+
className: `block overflow-y-auto flex-1 min-h-0 divide-y ${VARIANT_TBODY[variant]}`,
|
|
3069
|
+
children: data.map((row, rowIdx) => {
|
|
3070
|
+
const id = resolveId(row, idKey, columns);
|
|
3071
|
+
const url = resolveRedirectUrl(redirectPath, row, id);
|
|
3072
|
+
const isClickable = Boolean(url || onRowClick || hasExpand);
|
|
3073
|
+
const isMenuOpen = openMenuId === id;
|
|
3074
|
+
const isExpanded = expandedId === id;
|
|
3075
|
+
const isSelected = selectable && selectedSet.has(id);
|
|
3076
|
+
const expandedContent = renderExpandedRow?.(row);
|
|
3077
|
+
const rowClass = [
|
|
3078
|
+
"flex w-full transition-colors duration-100",
|
|
3079
|
+
isClickable ? "cursor-pointer" : "",
|
|
3080
|
+
VARIANT_ROW_HOVER[variant],
|
|
3081
|
+
striped ? VARIANT_ROW_STRIPED[variant] : "",
|
|
3082
|
+
isSelected ? "bg-login/5" : ""
|
|
3083
|
+
].filter(Boolean).join(" ");
|
|
3084
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsxs("tr", {
|
|
3085
|
+
className: rowClass,
|
|
3086
|
+
onMouseEnter: () => {
|
|
3087
|
+
if (url) router.prefetch(url);
|
|
3088
|
+
},
|
|
2837
3089
|
onMouseDown: () => {
|
|
2838
3090
|
menuWasOpenOnMouseDown.current = openMenuId !== null;
|
|
2839
3091
|
},
|
|
@@ -2842,297 +3094,531 @@ function Body({ list, columns, menuItems, redirectPath, variant = "default", idK
|
|
|
2842
3094
|
menuWasOpenOnMouseDown.current = false;
|
|
2843
3095
|
return;
|
|
2844
3096
|
}
|
|
2845
|
-
if (
|
|
2846
|
-
|
|
3097
|
+
if (hasExpand) {
|
|
3098
|
+
setExpandedId(isExpanded ? null : id);
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3101
|
+
if (onRowClick) {
|
|
3102
|
+
onRowClick(row, id);
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
if (url) router.push(url);
|
|
2847
3106
|
},
|
|
2848
3107
|
onContextMenu: (e) => {
|
|
3108
|
+
if (!hasMenu) return;
|
|
2849
3109
|
e.preventDefault();
|
|
2850
|
-
|
|
3110
|
+
openMenu(id, {
|
|
2851
3111
|
top: e.clientY,
|
|
2852
3112
|
right: window.innerWidth - e.clientX
|
|
2853
3113
|
});
|
|
2854
|
-
setOpenMenuId(id);
|
|
2855
3114
|
},
|
|
2856
|
-
children: [
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
badgeClass = "bg-green-500/20 text-green-400";
|
|
2866
|
-
break;
|
|
2867
|
-
case "yellow":
|
|
2868
|
-
badgeClass = "bg-yellow-500/20 text-yellow-400";
|
|
2869
|
-
break;
|
|
2870
|
-
case "red":
|
|
2871
|
-
badgeClass = "bg-red-500/20 text-red-400";
|
|
2872
|
-
break;
|
|
2873
|
-
case "blue":
|
|
2874
|
-
badgeClass = "bg-blue-500/20 text-blue-400";
|
|
2875
|
-
break;
|
|
2876
|
-
case "gray":
|
|
2877
|
-
badgeClass = "bg-gray-500/20 text-gray-400";
|
|
2878
|
-
break;
|
|
2879
|
-
}
|
|
2880
|
-
badgeClass += " px-2 py-1 rounded";
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
return /* @__PURE__ */ jsx("td", {
|
|
2884
|
-
className: `
|
|
2885
|
-
flex-1 min-w-0 px-6 py-4 whitespace-nowrap text-sm flex items-center text-login-100
|
|
2886
|
-
${variant === "minimal" ? "px-4! py-2!" : ""}
|
|
2887
|
-
`,
|
|
2888
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
2889
|
-
className: "relative w-full min-w-0",
|
|
2890
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
2891
|
-
className: `block max-w-full truncate ${badgeClass}`,
|
|
2892
|
-
children: formatValue(col.key, value)
|
|
2893
|
-
})
|
|
2894
|
-
})
|
|
2895
|
-
}, col.key);
|
|
2896
|
-
}), menuItems && /* @__PURE__ */ jsx("td", {
|
|
2897
|
-
className: "shrink-0 w-16 flex flex-row items-center justify-end p-2 px-4\n whitespace-nowrap text-right text-sm font-medium",
|
|
2898
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
2899
|
-
className: "relative",
|
|
2900
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
3115
|
+
children: [
|
|
3116
|
+
selectable && /* @__PURE__ */ jsx("td", {
|
|
3117
|
+
className: "flex items-center justify-center",
|
|
3118
|
+
style: {
|
|
3119
|
+
width: "3rem",
|
|
3120
|
+
minWidth: "3rem",
|
|
3121
|
+
flexShrink: 0
|
|
3122
|
+
},
|
|
3123
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
2901
3124
|
type: "button",
|
|
2902
|
-
|
|
2903
|
-
|
|
3125
|
+
"aria-label": isSelected ? "Deselect row" : "Select row",
|
|
3126
|
+
"aria-checked": isSelected,
|
|
3127
|
+
role: "checkbox",
|
|
2904
3128
|
onClick: (e) => {
|
|
2905
3129
|
e.stopPropagation();
|
|
2906
|
-
|
|
2907
|
-
const coords = {
|
|
2908
|
-
top: rect.bottom + 4,
|
|
2909
|
-
right: window.innerWidth - rect.right
|
|
2910
|
-
};
|
|
2911
|
-
setAnchor(openMenuId === id ? null : coords);
|
|
2912
|
-
setOpenMenuId(openMenuId === id ? null : id);
|
|
3130
|
+
toggleSelect(id);
|
|
2913
3131
|
},
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
3132
|
+
className: `
|
|
3133
|
+
h-4 w-4 rounded border flex items-center justify-center transition-colors cursor-pointer
|
|
3134
|
+
${isSelected ? "bg-login border-login text-white" : "border-login-400 bg-transparent hover:border-login-100"}
|
|
3135
|
+
`,
|
|
3136
|
+
children: isSelected && /* @__PURE__ */ jsx("svg", {
|
|
3137
|
+
className: "h-3 w-3",
|
|
3138
|
+
viewBox: "0 0 12 12",
|
|
3139
|
+
fill: "none",
|
|
3140
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
3141
|
+
d: "M2 6l3 3 5-5",
|
|
3142
|
+
stroke: "currentColor",
|
|
3143
|
+
strokeWidth: "1.5",
|
|
3144
|
+
strokeLinecap: "round",
|
|
3145
|
+
strokeLinejoin: "round"
|
|
3146
|
+
})
|
|
2917
3147
|
})
|
|
2918
|
-
})
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
3148
|
+
})
|
|
3149
|
+
}),
|
|
3150
|
+
columns.map((col) => /* @__PURE__ */ jsx(Cell, {
|
|
3151
|
+
col,
|
|
3152
|
+
row,
|
|
3153
|
+
density
|
|
3154
|
+
}, col.key)),
|
|
3155
|
+
hasExpand && /* @__PURE__ */ jsx("td", {
|
|
3156
|
+
className: "flex items-center justify-center",
|
|
3157
|
+
style: {
|
|
3158
|
+
width: "2.5rem",
|
|
3159
|
+
minWidth: "2.5rem",
|
|
3160
|
+
flexShrink: 0
|
|
3161
|
+
},
|
|
3162
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: `
|
|
3163
|
+
h-4 w-4 transition-transform duration-200
|
|
3164
|
+
${isExpanded ? "rotate-180 text-login" : "text-login-400"}
|
|
3165
|
+
` })
|
|
3166
|
+
}),
|
|
3167
|
+
hasMenu && /* @__PURE__ */ jsx("td", {
|
|
3168
|
+
className: "flex items-center justify-end pr-3",
|
|
3169
|
+
style: {
|
|
3170
|
+
width: "3.5rem",
|
|
3171
|
+
minWidth: "3.5rem",
|
|
3172
|
+
flexShrink: 0
|
|
3173
|
+
},
|
|
3174
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3175
|
+
className: "relative",
|
|
3176
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
3177
|
+
type: "button",
|
|
3178
|
+
"aria-label": "Row actions",
|
|
3179
|
+
"aria-expanded": isMenuOpen,
|
|
3180
|
+
"aria-haspopup": "menu",
|
|
3181
|
+
onMouseDown: (e) => e.nativeEvent.stopImmediatePropagation(),
|
|
3182
|
+
onClick: (e) => {
|
|
3183
|
+
e.stopPropagation();
|
|
3184
|
+
if (isMenuOpen) setOpenMenuId(null);
|
|
3185
|
+
else {
|
|
3186
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
3187
|
+
openMenu(id, {
|
|
3188
|
+
top: rect.bottom + 4,
|
|
3189
|
+
right: window.innerWidth - rect.right
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
},
|
|
3193
|
+
className: `
|
|
3194
|
+
p-1.5 rounded flex items-center justify-center transition-colors
|
|
3195
|
+
${isMenuOpen ? "bg-login-500 text-login-75" : "text-login-300 hover:bg-login-500/60 hover:text-login-75"}
|
|
3196
|
+
`,
|
|
3197
|
+
children: /* @__PURE__ */ jsx(EllipsisVertical, { className: "h-4 w-4" })
|
|
3198
|
+
}), isMenuOpen && anchor && /* @__PURE__ */ jsx(Menu, {
|
|
3199
|
+
ref: menuRef,
|
|
3200
|
+
anchor,
|
|
3201
|
+
onClose: closeMenu,
|
|
3202
|
+
children: menuItems(row, id)
|
|
3203
|
+
})]
|
|
3204
|
+
})
|
|
2924
3205
|
})
|
|
2925
|
-
|
|
2926
|
-
},
|
|
3206
|
+
]
|
|
3207
|
+
}), hasExpand && isExpanded && /* @__PURE__ */ jsx("tr", {
|
|
3208
|
+
className: "flex w-full bg-login-700/25 border-b border-login-600/20",
|
|
3209
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
3210
|
+
className: "w-full px-6 py-4",
|
|
3211
|
+
onClick: (e) => e.stopPropagation(),
|
|
3212
|
+
children: expandedContent
|
|
3213
|
+
})
|
|
3214
|
+
})] }, id + rowIdx);
|
|
2927
3215
|
})
|
|
2928
3216
|
});
|
|
2929
3217
|
}
|
|
2930
3218
|
//#endregion
|
|
2931
|
-
//#region src/components/table/
|
|
2932
|
-
function
|
|
2933
|
-
return
|
|
2934
|
-
}
|
|
2935
|
-
|
|
2936
|
-
const router = useRouter();
|
|
2937
|
-
const pathname = usePathname();
|
|
2938
|
-
const searchParams = useSearchParams();
|
|
2939
|
-
const [column, setColumn] = useState(searchParams.get("column") ?? "");
|
|
2940
|
-
const [order, setOrder] = useState(parseOrder(searchParams.get("order")));
|
|
2941
|
-
useEffect(() => {
|
|
2942
|
-
if (!column || !order) return;
|
|
2943
|
-
const params = new URLSearchParams(searchParams.toString());
|
|
2944
|
-
if (searchParams.get("order") !== order || searchParams.get("column") !== column) {
|
|
2945
|
-
params.set("order", order);
|
|
2946
|
-
params.set("column", column);
|
|
2947
|
-
params.set("page", "1");
|
|
2948
|
-
router.push(`${pathname}?${params.toString()}`);
|
|
2949
|
-
}
|
|
2950
|
-
}, [
|
|
2951
|
-
order,
|
|
2952
|
-
column,
|
|
2953
|
-
pathname,
|
|
2954
|
-
router,
|
|
2955
|
-
searchParams
|
|
2956
|
-
]);
|
|
2957
|
-
function handleChange(key) {
|
|
2958
|
-
setColumn(key);
|
|
2959
|
-
setOrder((prev) => key === column && prev === "asc" ? "desc" : "asc");
|
|
2960
|
-
}
|
|
2961
|
-
return /* @__PURE__ */ jsx("thead", {
|
|
2962
|
-
className: `
|
|
2963
|
-
block w-full
|
|
2964
|
-
${variant === "default" ? "bg-login-700" : "bg-transparent border-b border-login-600"}
|
|
2965
|
-
`,
|
|
2966
|
-
children: /* @__PURE__ */ jsxs("tr", {
|
|
3219
|
+
//#region src/components/table/skeleton.tsx
|
|
3220
|
+
function Skeleton({ columns, rows, variant, density, hasMenu, hasSelect }) {
|
|
3221
|
+
return /* @__PURE__ */ jsx("tbody", {
|
|
3222
|
+
className: `block divide-y divide-login-600/15 ${VARIANT_TBODY[variant]}`,
|
|
3223
|
+
children: Array.from({ length: rows }).map((_, rowIdx) => /* @__PURE__ */ jsxs("tr", {
|
|
2967
3224
|
className: "flex w-full",
|
|
2968
|
-
children: [
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
3225
|
+
children: [
|
|
3226
|
+
hasSelect && /* @__PURE__ */ jsx("td", {
|
|
3227
|
+
className: "flex items-center justify-center",
|
|
3228
|
+
style: {
|
|
3229
|
+
width: "3rem",
|
|
3230
|
+
minWidth: "3rem",
|
|
3231
|
+
flexShrink: 0
|
|
3232
|
+
},
|
|
3233
|
+
children: /* @__PURE__ */ jsx("span", { className: "block h-4 w-4 rounded animate-shimmer" })
|
|
3234
|
+
}),
|
|
3235
|
+
columns.map((col, colIdx) => /* @__PURE__ */ jsx("td", {
|
|
3236
|
+
style: col.width ? {
|
|
3237
|
+
width: col.width,
|
|
3238
|
+
flexShrink: 0
|
|
3239
|
+
} : void 0,
|
|
2972
3240
|
className: `
|
|
2973
|
-
flex-1 min-w-0
|
|
2974
|
-
${
|
|
2975
|
-
${variant === "minimal" ? "px-4!" : ""}
|
|
3241
|
+
flex-1 min-w-0 flex items-center
|
|
3242
|
+
${DENSITY_TD[density]}
|
|
2976
3243
|
`,
|
|
2977
|
-
children: /* @__PURE__ */
|
|
2978
|
-
className: "
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
2984
|
-
className: "flex flex-col",
|
|
2985
|
-
children: column === key ? order === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 stroke-login-200 opacity-0 group-hover:opacity-100" })
|
|
2986
|
-
})]
|
|
3244
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
3245
|
+
className: "block h-4 rounded animate-shimmer",
|
|
3246
|
+
style: {
|
|
3247
|
+
width: colIdx === 0 ? `${55 + (rowIdx * 17 + colIdx * 31) % 30}%` : `${40 + (rowIdx * 13 + colIdx * 23) % 40}%`,
|
|
3248
|
+
animationDelay: `${(rowIdx * columns.length + colIdx) * 40}ms`
|
|
3249
|
+
}
|
|
2987
3250
|
})
|
|
2988
|
-
}, key)
|
|
2989
|
-
|
|
2990
|
-
|
|
3251
|
+
}, col.key)),
|
|
3252
|
+
hasMenu && /* @__PURE__ */ jsx("td", {
|
|
3253
|
+
className: "flex items-center justify-end pr-3",
|
|
3254
|
+
style: {
|
|
3255
|
+
width: "3.5rem",
|
|
3256
|
+
minWidth: "3.5rem",
|
|
3257
|
+
flexShrink: 0
|
|
3258
|
+
},
|
|
3259
|
+
children: /* @__PURE__ */ jsx("span", { className: "block h-5 w-5 rounded animate-shimmer" })
|
|
3260
|
+
})
|
|
3261
|
+
]
|
|
3262
|
+
}, rowIdx))
|
|
2991
3263
|
});
|
|
2992
3264
|
}
|
|
2993
3265
|
//#endregion
|
|
2994
|
-
//#region src/components/table/
|
|
2995
|
-
function
|
|
2996
|
-
if (
|
|
2997
|
-
className: "
|
|
2998
|
-
children:
|
|
3266
|
+
//#region src/components/table/empty.tsx
|
|
3267
|
+
function Empty({ emptyState }) {
|
|
3268
|
+
if (emptyState) return /* @__PURE__ */ jsx("tbody", {
|
|
3269
|
+
className: "block w-full",
|
|
3270
|
+
children: /* @__PURE__ */ jsx("tr", {
|
|
3271
|
+
className: "flex w-full",
|
|
3272
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
3273
|
+
className: "w-full",
|
|
3274
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3275
|
+
className: "flex items-center justify-center min-h-[160px] py-8 px-6",
|
|
3276
|
+
children: emptyState
|
|
3277
|
+
})
|
|
3278
|
+
})
|
|
3279
|
+
})
|
|
2999
3280
|
});
|
|
3000
|
-
return /* @__PURE__ */ jsx("
|
|
3001
|
-
className:
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
columns,
|
|
3015
|
-
menuItems,
|
|
3016
|
-
redirectPath,
|
|
3017
|
-
variant,
|
|
3018
|
-
idKey
|
|
3019
|
-
})]
|
|
3281
|
+
return /* @__PURE__ */ jsx("tbody", {
|
|
3282
|
+
className: "block w-full",
|
|
3283
|
+
children: /* @__PURE__ */ jsx("tr", {
|
|
3284
|
+
className: "flex w-full",
|
|
3285
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
3286
|
+
className: "w-full",
|
|
3287
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3288
|
+
className: "flex flex-col items-center justify-center gap-3 min-h-[160px] py-8 text-login-300",
|
|
3289
|
+
children: [/* @__PURE__ */ jsx(TableIcon, { className: "h-10 w-10 opacity-30" }), /* @__PURE__ */ jsx("span", {
|
|
3290
|
+
className: "text-sm",
|
|
3291
|
+
children: "No data found"
|
|
3292
|
+
})]
|
|
3293
|
+
})
|
|
3294
|
+
})
|
|
3020
3295
|
})
|
|
3021
3296
|
});
|
|
3022
3297
|
}
|
|
3023
3298
|
//#endregion
|
|
3024
3299
|
//#region src/components/table/pagination.tsx
|
|
3025
|
-
function
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
const
|
|
3030
|
-
const
|
|
3031
|
-
const
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
function updateQuery(p) {
|
|
3037
|
-
const params = new URLSearchParams(searchParams.toString());
|
|
3038
|
-
params.set("page", String(p));
|
|
3039
|
-
router.push(`${pathname}?${params.toString()}`);
|
|
3040
|
-
}
|
|
3041
|
-
function goPrevious() {
|
|
3042
|
-
if (current <= 1) return;
|
|
3043
|
-
const next = current - 1;
|
|
3044
|
-
setCurrent(next);
|
|
3045
|
-
updateQuery(next);
|
|
3300
|
+
function computeTotalPages(totalRows, pageSize) {
|
|
3301
|
+
return Math.max(1, pageSize > 0 ? Math.ceil(totalRows / pageSize) : 1);
|
|
3302
|
+
}
|
|
3303
|
+
function pageRange(current, total) {
|
|
3304
|
+
const delta = 2;
|
|
3305
|
+
const left = Math.max(1, current - delta);
|
|
3306
|
+
const right = Math.min(total, current + delta);
|
|
3307
|
+
const pages = [];
|
|
3308
|
+
if (left > 1) {
|
|
3309
|
+
pages.push(1);
|
|
3310
|
+
if (left > 2) pages.push("…");
|
|
3046
3311
|
}
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
updateQuery(next);
|
|
3312
|
+
for (let i = left; i <= right; i++) pages.push(i);
|
|
3313
|
+
if (right < total) {
|
|
3314
|
+
if (right < total - 1) pages.push("…");
|
|
3315
|
+
pages.push(total);
|
|
3052
3316
|
}
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
}
|
|
3067
|
-
for (let i = left; i <= right; i++) pages.push(i);
|
|
3068
|
-
if (right < total) {
|
|
3069
|
-
if (right < total - 1) pages.push("...");
|
|
3070
|
-
pages.push(total);
|
|
3071
|
-
}
|
|
3072
|
-
return pages;
|
|
3073
|
-
}
|
|
3074
|
-
const pages = getPages(current, totalPages);
|
|
3075
|
-
const start = Math.max(1, (current - 1) * pageSize + 1);
|
|
3076
|
-
const end = Math.min(current * pageSize, totalRows !== void 0 ? totalRows : current * pageSize);
|
|
3317
|
+
return pages;
|
|
3318
|
+
}
|
|
3319
|
+
function PaginationShell({ page, totalPages, totalRows, pageSize, onPageChange, variant }) {
|
|
3320
|
+
const start = totalRows === 0 ? 0 : (page - 1) * pageSize + 1;
|
|
3321
|
+
const end = Math.min(page * pageSize, totalRows);
|
|
3322
|
+
const pages = pageRange(page, totalPages);
|
|
3323
|
+
const btnBase = `
|
|
3324
|
+
flex items-center justify-center rounded-md border text-sm transition-colors duration-100
|
|
3325
|
+
disabled:opacity-35 disabled:cursor-not-allowed
|
|
3326
|
+
`;
|
|
3327
|
+
const btnStyle = variant === "original" ? "border-login-500/50 bg-login-700 hover:bg-login-600 text-login-100" : "border-login-500/40 bg-transparent hover:bg-login-700/60 text-login-100";
|
|
3328
|
+
const pageActive = variant === "original" ? "border-login bg-login/10 text-login" : "border-login text-login bg-transparent";
|
|
3329
|
+
const pageInactive = variant === "original" ? "border-login-500/50 bg-login-700 text-login-100 hover:bg-login-600" : "border-transparent bg-transparent text-login-200 hover:text-login-75 hover:bg-login-700/60";
|
|
3077
3330
|
return /* @__PURE__ */ jsxs("div", {
|
|
3078
|
-
className: "flex items-center justify-between w-full
|
|
3079
|
-
children: [/* @__PURE__ */ jsx("
|
|
3080
|
-
className: "text-
|
|
3081
|
-
children: totalRows
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
end,
|
|
3086
|
-
" of ",
|
|
3087
|
-
totalRows,
|
|
3088
|
-
" results"
|
|
3089
|
-
] }) : null
|
|
3090
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3091
|
-
className: "flex items-center gap-3",
|
|
3331
|
+
className: "flex items-center justify-between w-full gap-4 flex-wrap",
|
|
3332
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3333
|
+
className: "text-xs text-login-300 tabular-nums",
|
|
3334
|
+
children: totalRows === 0 ? "No results" : `${start}-${end} of ${totalRows}`
|
|
3335
|
+
}), /* @__PURE__ */ jsxs("nav", {
|
|
3336
|
+
className: "flex items-center gap-1.5",
|
|
3337
|
+
"aria-label": "Pagination",
|
|
3092
3338
|
children: [
|
|
3093
3339
|
/* @__PURE__ */ jsx("button", {
|
|
3094
3340
|
type: "button",
|
|
3095
|
-
|
|
3096
|
-
disabled:
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
border border-login-500/50 text-sm transition-colors duration-150
|
|
3101
|
-
`,
|
|
3102
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
|
|
3103
|
-
}),
|
|
3104
|
-
/* @__PURE__ */ jsx("nav", {
|
|
3105
|
-
className: "flex items-center gap-1",
|
|
3106
|
-
"aria-label": "Pagination",
|
|
3107
|
-
children: pages.map((p, i) => typeof p === "string" ? /* @__PURE__ */ jsx("span", {
|
|
3108
|
-
className: "px-3 py-1 text-sm",
|
|
3109
|
-
children: p
|
|
3110
|
-
}, `e-${i}`) : /* @__PURE__ */ jsx("button", {
|
|
3111
|
-
type: "button",
|
|
3112
|
-
onClick: () => setPage(p),
|
|
3113
|
-
"aria-current": p === current ? "page" : void 0,
|
|
3114
|
-
className: `
|
|
3115
|
-
px-3 py-1 rounded-lg text-sm border transition-colors duration-150
|
|
3116
|
-
${p === current ? "bg-login text-white border-login" : "bg-login-700 border-login-500/50 hover:bg-login-600"}
|
|
3117
|
-
`,
|
|
3118
|
-
children: p
|
|
3119
|
-
}, p))
|
|
3341
|
+
"aria-label": "Previous page",
|
|
3342
|
+
disabled: page <= 1,
|
|
3343
|
+
onClick: () => onPageChange(page - 1),
|
|
3344
|
+
className: `${btnBase} ${btnStyle} h-8 w-8`,
|
|
3345
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
3120
3346
|
}),
|
|
3347
|
+
pages.map((p, i) => p === "…" ? /* @__PURE__ */ jsx("span", {
|
|
3348
|
+
className: "w-8 text-center text-sm text-login-400 select-none",
|
|
3349
|
+
children: "…"
|
|
3350
|
+
}, `ellipsis-${i}`) : /* @__PURE__ */ jsx("button", {
|
|
3351
|
+
type: "button",
|
|
3352
|
+
"aria-current": p === page ? "page" : void 0,
|
|
3353
|
+
onClick: () => onPageChange(p),
|
|
3354
|
+
className: `${btnBase} h-8 min-w-8 px-2 tabular-nums ${p === page ? pageActive : pageInactive}`,
|
|
3355
|
+
children: p
|
|
3356
|
+
}, p)),
|
|
3121
3357
|
/* @__PURE__ */ jsx("button", {
|
|
3122
3358
|
type: "button",
|
|
3123
|
-
|
|
3124
|
-
disabled:
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
border border-login-500/50 text-sm transition-colors duration-150
|
|
3129
|
-
`,
|
|
3130
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
|
|
3359
|
+
"aria-label": "Next page",
|
|
3360
|
+
disabled: page >= totalPages,
|
|
3361
|
+
onClick: () => onPageChange(page + 1),
|
|
3362
|
+
className: `${btnBase} ${btnStyle} h-8 w-8`,
|
|
3363
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
|
|
3131
3364
|
})
|
|
3132
3365
|
]
|
|
3133
3366
|
})]
|
|
3134
3367
|
});
|
|
3135
3368
|
}
|
|
3369
|
+
function PaginationLocalState({ totalRows, pageSize, variant = "original" }) {
|
|
3370
|
+
const [page, setPage] = useState(1);
|
|
3371
|
+
return /* @__PURE__ */ jsx(PaginationShell, {
|
|
3372
|
+
page,
|
|
3373
|
+
totalPages: computeTotalPages(totalRows, pageSize),
|
|
3374
|
+
totalRows,
|
|
3375
|
+
pageSize,
|
|
3376
|
+
onPageChange: setPage,
|
|
3377
|
+
variant
|
|
3378
|
+
});
|
|
3379
|
+
}
|
|
3380
|
+
function PaginationURLState({ totalRows, pageSize, variant = "original" }) {
|
|
3381
|
+
const router = useRouter();
|
|
3382
|
+
const pathname = usePathname();
|
|
3383
|
+
const searchParams = useSearchParams();
|
|
3384
|
+
const page = Math.max(1, parseInt(searchParams.get("page") ?? "1", 10) || 1);
|
|
3385
|
+
function onPageChange(p) {
|
|
3386
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
3387
|
+
params.set("page", String(p));
|
|
3388
|
+
router.replace(`${pathname}?${params.toString()}`);
|
|
3389
|
+
}
|
|
3390
|
+
return /* @__PURE__ */ jsx(PaginationShell, {
|
|
3391
|
+
page,
|
|
3392
|
+
totalPages: computeTotalPages(totalRows, pageSize),
|
|
3393
|
+
totalRows,
|
|
3394
|
+
pageSize,
|
|
3395
|
+
onPageChange,
|
|
3396
|
+
variant
|
|
3397
|
+
});
|
|
3398
|
+
}
|
|
3399
|
+
function Pagination(props) {
|
|
3400
|
+
const { totalRows, pageSize, variant = "original", urlState, page, onPageChange } = props;
|
|
3401
|
+
if (urlState) return /* @__PURE__ */ jsx(Suspense, {
|
|
3402
|
+
fallback: /* @__PURE__ */ jsx(PaginationShell, {
|
|
3403
|
+
page: 1,
|
|
3404
|
+
totalPages: computeTotalPages(totalRows, pageSize),
|
|
3405
|
+
totalRows,
|
|
3406
|
+
pageSize,
|
|
3407
|
+
onPageChange: () => {},
|
|
3408
|
+
variant
|
|
3409
|
+
}),
|
|
3410
|
+
children: /* @__PURE__ */ jsx(PaginationURLState, { ...props })
|
|
3411
|
+
});
|
|
3412
|
+
if (page !== void 0 && onPageChange !== void 0) return /* @__PURE__ */ jsx(PaginationShell, {
|
|
3413
|
+
page,
|
|
3414
|
+
totalPages: computeTotalPages(totalRows, pageSize),
|
|
3415
|
+
totalRows,
|
|
3416
|
+
pageSize,
|
|
3417
|
+
onPageChange,
|
|
3418
|
+
variant
|
|
3419
|
+
});
|
|
3420
|
+
return /* @__PURE__ */ jsx(PaginationLocalState, { ...props });
|
|
3421
|
+
}
|
|
3422
|
+
//#endregion
|
|
3423
|
+
//#region src/components/table/table.tsx
|
|
3424
|
+
function TableShell({ data, columns, idKey, variant, density, striped, loading, loadingRows, emptyState, redirectPath, onRowClick, renderExpandedRow, selectable, selectedIds, onSelectionChange, sort, onSort, page, onPageChange, totalRows, pageSize, hidePagination, menuItems, className }) {
|
|
3425
|
+
const allIds = data.map((row) => resolveId(row, idKey, columns));
|
|
3426
|
+
const allIdsSet = useMemo(() => new Set(allIds), [allIds]);
|
|
3427
|
+
const allSelected = allIds.length > 0 && allIds.every((id) => selectedIds.includes(id));
|
|
3428
|
+
const someSelected = !allSelected && allIds.some((id) => selectedIds.includes(id));
|
|
3429
|
+
function handleSelectAll() {
|
|
3430
|
+
if (allSelected) onSelectionChange(selectedIds.filter((id) => !allIdsSet.has(id)));
|
|
3431
|
+
else onSelectionChange([.../* @__PURE__ */ new Set([...selectedIds, ...allIds])]);
|
|
3432
|
+
}
|
|
3433
|
+
const isEmpty = !loading && data.length === 0;
|
|
3434
|
+
const showPagination = !hidePagination && pageSize > 0 && totalRows > 0;
|
|
3435
|
+
const hasMenu = Boolean(menuItems);
|
|
3436
|
+
const hasSelect = Boolean(selectable);
|
|
3437
|
+
const hasExpand = Boolean(renderExpandedRow);
|
|
3438
|
+
const paginationPad = variant === "original" ? "px-4 pb-4 pt-3" : "pt-4";
|
|
3439
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3440
|
+
className: [
|
|
3441
|
+
"flex flex-col min-h-0 w-full",
|
|
3442
|
+
VARIANT_CONTAINER[variant],
|
|
3443
|
+
className
|
|
3444
|
+
].filter(Boolean).join(" "),
|
|
3445
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3446
|
+
className: "flex-1 min-h-0 overflow-x-auto",
|
|
3447
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
3448
|
+
className: "min-w-full w-max flex flex-col flex-1 min-h-0 divide-y divide-login-600/20",
|
|
3449
|
+
children: [/* @__PURE__ */ jsx(Header, {
|
|
3450
|
+
columns,
|
|
3451
|
+
sort,
|
|
3452
|
+
onSort,
|
|
3453
|
+
hasMenu,
|
|
3454
|
+
hasSelect,
|
|
3455
|
+
hasExpand,
|
|
3456
|
+
allSelected,
|
|
3457
|
+
someSelected,
|
|
3458
|
+
onSelectAll: handleSelectAll,
|
|
3459
|
+
variant,
|
|
3460
|
+
density
|
|
3461
|
+
}), loading ? /* @__PURE__ */ jsx(Skeleton, {
|
|
3462
|
+
columns,
|
|
3463
|
+
rows: loadingRows,
|
|
3464
|
+
variant,
|
|
3465
|
+
density,
|
|
3466
|
+
hasMenu,
|
|
3467
|
+
hasSelect
|
|
3468
|
+
}) : isEmpty ? /* @__PURE__ */ jsx(Empty, { emptyState }) : /* @__PURE__ */ jsx(Body, {
|
|
3469
|
+
data,
|
|
3470
|
+
columns,
|
|
3471
|
+
idKey,
|
|
3472
|
+
variant,
|
|
3473
|
+
density,
|
|
3474
|
+
striped,
|
|
3475
|
+
redirectPath,
|
|
3476
|
+
onRowClick,
|
|
3477
|
+
renderExpandedRow,
|
|
3478
|
+
selectable,
|
|
3479
|
+
selectedIds,
|
|
3480
|
+
onSelectionChange,
|
|
3481
|
+
menuItems
|
|
3482
|
+
})]
|
|
3483
|
+
})
|
|
3484
|
+
}), showPagination && /* @__PURE__ */ jsx("div", {
|
|
3485
|
+
className: paginationPad,
|
|
3486
|
+
children: /* @__PURE__ */ jsx(Pagination, {
|
|
3487
|
+
page,
|
|
3488
|
+
totalRows,
|
|
3489
|
+
pageSize,
|
|
3490
|
+
onPageChange,
|
|
3491
|
+
variant
|
|
3492
|
+
})
|
|
3493
|
+
})]
|
|
3494
|
+
});
|
|
3495
|
+
}
|
|
3496
|
+
function useInternalSelection(props) {
|
|
3497
|
+
const [internal, setInternal] = useState([]);
|
|
3498
|
+
return {
|
|
3499
|
+
selectedIds: props.selectedIds ?? internal,
|
|
3500
|
+
onSelectionChange: props.onSelectionChange ?? setInternal
|
|
3501
|
+
};
|
|
3502
|
+
}
|
|
3503
|
+
function applyDefaults(props) {
|
|
3504
|
+
return {
|
|
3505
|
+
variant: props.variant ?? "original",
|
|
3506
|
+
density: props.density ?? "comfortable",
|
|
3507
|
+
selectable: props.selectable ?? false,
|
|
3508
|
+
loading: props.loading ?? false,
|
|
3509
|
+
loadingRows: props.loadingRows ?? props.pageSize ?? 5,
|
|
3510
|
+
striped: props.striped ?? false,
|
|
3511
|
+
hidePagination: props.hidePagination ?? false,
|
|
3512
|
+
pageSize: props.pageSize ?? 0
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
function TableLocalState(props) {
|
|
3516
|
+
const defaults = applyDefaults(props);
|
|
3517
|
+
const selection = useInternalSelection(props);
|
|
3518
|
+
const [sort, setSort] = useState(void 0);
|
|
3519
|
+
const [page, setPage] = useState(1);
|
|
3520
|
+
const ps = defaults.pageSize;
|
|
3521
|
+
const allRows = props.data.length;
|
|
3522
|
+
const sorted = useMemo(() => {
|
|
3523
|
+
if (!sort) return props.data;
|
|
3524
|
+
return [...props.data].sort((a, b) => {
|
|
3525
|
+
const av = a[sort.column];
|
|
3526
|
+
const bv = b[sort.column];
|
|
3527
|
+
const cmp = String(av ?? "").localeCompare(String(bv ?? ""), void 0, {
|
|
3528
|
+
numeric: true,
|
|
3529
|
+
sensitivity: "base"
|
|
3530
|
+
});
|
|
3531
|
+
return sort.order === "asc" ? cmp : -cmp;
|
|
3532
|
+
});
|
|
3533
|
+
}, [props.data, sort]);
|
|
3534
|
+
const displayData = ps > 0 ? sorted.slice((page - 1) * ps, page * ps) : sorted;
|
|
3535
|
+
function handleSort(newSort) {
|
|
3536
|
+
setSort(newSort);
|
|
3537
|
+
setPage(1);
|
|
3538
|
+
}
|
|
3539
|
+
return /* @__PURE__ */ jsx(TableShell, {
|
|
3540
|
+
...props,
|
|
3541
|
+
...defaults,
|
|
3542
|
+
...selection,
|
|
3543
|
+
data: displayData,
|
|
3544
|
+
sort,
|
|
3545
|
+
onSort: handleSort,
|
|
3546
|
+
page,
|
|
3547
|
+
onPageChange: setPage,
|
|
3548
|
+
totalRows: ps > 0 ? allRows : props.totalRows ?? allRows
|
|
3549
|
+
});
|
|
3550
|
+
}
|
|
3551
|
+
function TableURLState(props) {
|
|
3552
|
+
const defaults = applyDefaults(props);
|
|
3553
|
+
const selection = useInternalSelection(props);
|
|
3554
|
+
const router = useRouter();
|
|
3555
|
+
const pathname = usePathname();
|
|
3556
|
+
const searchParams = useSearchParams();
|
|
3557
|
+
const urlColumn = searchParams.get("column") ?? "";
|
|
3558
|
+
const urlOrder = searchParams.get("order") ?? "asc";
|
|
3559
|
+
const urlPage = Math.max(1, parseInt(searchParams.get("page") ?? "1", 10) || 1);
|
|
3560
|
+
const sort = urlColumn ? {
|
|
3561
|
+
column: urlColumn,
|
|
3562
|
+
order: urlOrder
|
|
3563
|
+
} : void 0;
|
|
3564
|
+
function handleSort(newSort) {
|
|
3565
|
+
const p = new URLSearchParams(searchParams.toString());
|
|
3566
|
+
p.set("column", newSort.column);
|
|
3567
|
+
p.set("order", newSort.order);
|
|
3568
|
+
p.set("page", "1");
|
|
3569
|
+
router.replace(`${pathname}?${p.toString()}`);
|
|
3570
|
+
}
|
|
3571
|
+
function handlePageChange(newPage) {
|
|
3572
|
+
const p = new URLSearchParams(searchParams.toString());
|
|
3573
|
+
p.set("page", String(newPage));
|
|
3574
|
+
router.replace(`${pathname}?${p.toString()}`);
|
|
3575
|
+
}
|
|
3576
|
+
return /* @__PURE__ */ jsx(TableShell, {
|
|
3577
|
+
...props,
|
|
3578
|
+
...defaults,
|
|
3579
|
+
...selection,
|
|
3580
|
+
sort,
|
|
3581
|
+
onSort: handleSort,
|
|
3582
|
+
page: urlPage,
|
|
3583
|
+
onPageChange: handlePageChange,
|
|
3584
|
+
totalRows: props.totalRows ?? props.data.length
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
function TableControlled(props) {
|
|
3588
|
+
const defaults = applyDefaults(props);
|
|
3589
|
+
const selection = useInternalSelection(props);
|
|
3590
|
+
return /* @__PURE__ */ jsx(TableShell, {
|
|
3591
|
+
...props,
|
|
3592
|
+
...defaults,
|
|
3593
|
+
...selection,
|
|
3594
|
+
sort: props.sort,
|
|
3595
|
+
onSort: props.onSort,
|
|
3596
|
+
page: props.page ?? 1,
|
|
3597
|
+
onPageChange: props.onPageChange ?? (() => {}),
|
|
3598
|
+
totalRows: props.totalRows ?? props.data.length
|
|
3599
|
+
});
|
|
3600
|
+
}
|
|
3601
|
+
function Table(props) {
|
|
3602
|
+
if (props.sort !== void 0 || props.onSort !== void 0) return /* @__PURE__ */ jsx(TableControlled, { ...props });
|
|
3603
|
+
if (props.urlState) {
|
|
3604
|
+
const defaults = applyDefaults(props);
|
|
3605
|
+
return /* @__PURE__ */ jsx(Suspense, {
|
|
3606
|
+
fallback: /* @__PURE__ */ jsx(TableShell, {
|
|
3607
|
+
...props,
|
|
3608
|
+
...defaults,
|
|
3609
|
+
selectedIds: props.selectedIds ?? [],
|
|
3610
|
+
onSelectionChange: props.onSelectionChange ?? (() => {}),
|
|
3611
|
+
sort: void 0,
|
|
3612
|
+
onSort: () => {},
|
|
3613
|
+
page: 1,
|
|
3614
|
+
onPageChange: () => {},
|
|
3615
|
+
totalRows: props.totalRows ?? props.data.length
|
|
3616
|
+
}),
|
|
3617
|
+
children: /* @__PURE__ */ jsx(TableURLState, { ...props })
|
|
3618
|
+
});
|
|
3619
|
+
}
|
|
3620
|
+
return /* @__PURE__ */ jsx(TableLocalState, { ...props });
|
|
3621
|
+
}
|
|
3136
3622
|
//#endregion
|
|
3137
3623
|
//#region src/components/confirm/confirmPopup.tsx
|
|
3138
3624
|
function ConfirmPopup({ isOpen, header, description, confirmText = "Confirm", cancelText = "Cancel", onConfirm, onCancel, variant = "default" }) {
|