@dynostack/react-grid 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +305 -18
- package/dist/index.cjs +375 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -43
- package/dist/index.d.ts +142 -43
- package/dist/index.js +371 -99
- package/dist/index.js.map +1 -1
- package/dist/page.css +24 -0
- package/dist/styles.css +145 -46
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ var tailwindMerge = require('tailwind-merge');
|
|
|
8
8
|
var radixUi = require('radix-ui');
|
|
9
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
10
|
var classVarianceAuthority = require('class-variance-authority');
|
|
11
|
+
var reactDom = require('react-dom');
|
|
11
12
|
|
|
12
13
|
function cn(...inputs) {
|
|
13
14
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
@@ -1717,14 +1718,34 @@ function DataTableRowActions({
|
|
|
1717
1718
|
onCancelEdit
|
|
1718
1719
|
}) {
|
|
1719
1720
|
const [open, setOpen] = react.useState(false);
|
|
1721
|
+
const [menuPosition, setMenuPosition] = react.useState({ top: 0, left: 0 });
|
|
1722
|
+
const triggerRef = react.useRef(null);
|
|
1720
1723
|
const menuRef = react.useRef(null);
|
|
1724
|
+
react.useLayoutEffect(() => {
|
|
1725
|
+
if (!open || !triggerRef.current) return;
|
|
1726
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
1727
|
+
setMenuPosition({
|
|
1728
|
+
top: rect.bottom + 4,
|
|
1729
|
+
left: Math.max(8, rect.right - 160)
|
|
1730
|
+
});
|
|
1731
|
+
}, [open]);
|
|
1721
1732
|
react.useEffect(() => {
|
|
1722
1733
|
if (!open) return;
|
|
1723
1734
|
const onPointerDown = (event) => {
|
|
1724
|
-
|
|
1735
|
+
const target = event.target;
|
|
1736
|
+
if (!menuRef.current?.contains(target) && !triggerRef.current?.contains(target)) {
|
|
1737
|
+
setOpen(false);
|
|
1738
|
+
}
|
|
1725
1739
|
};
|
|
1740
|
+
const onDismiss = () => setOpen(false);
|
|
1726
1741
|
document.addEventListener("pointerdown", onPointerDown);
|
|
1727
|
-
|
|
1742
|
+
window.addEventListener("scroll", onDismiss, true);
|
|
1743
|
+
window.addEventListener("resize", onDismiss);
|
|
1744
|
+
return () => {
|
|
1745
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
1746
|
+
window.removeEventListener("scroll", onDismiss, true);
|
|
1747
|
+
window.removeEventListener("resize", onDismiss);
|
|
1748
|
+
};
|
|
1728
1749
|
}, [open]);
|
|
1729
1750
|
if (isEditing) {
|
|
1730
1751
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1", children: [
|
|
@@ -1755,6 +1776,7 @@ function DataTableRowActions({
|
|
|
1755
1776
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1756
1777
|
Button,
|
|
1757
1778
|
{
|
|
1779
|
+
ref: triggerRef,
|
|
1758
1780
|
variant: "ghost",
|
|
1759
1781
|
size: "icon-xs",
|
|
1760
1782
|
"aria-label": "Open row actions",
|
|
@@ -1763,41 +1785,52 @@ function DataTableRowActions({
|
|
|
1763
1785
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontalIcon, {})
|
|
1764
1786
|
}
|
|
1765
1787
|
),
|
|
1766
|
-
open &&
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
{
|
|
1770
|
-
danger: a === "delete",
|
|
1771
|
-
onClick: () => {
|
|
1772
|
-
setOpen(false);
|
|
1773
|
-
onAction?.(a, row);
|
|
1774
|
-
},
|
|
1775
|
-
children: [
|
|
1776
|
-
builtinIcons[a],
|
|
1777
|
-
" ",
|
|
1778
|
-
builtinLabels[a]
|
|
1779
|
-
]
|
|
1780
|
-
},
|
|
1781
|
-
a
|
|
1782
|
-
)),
|
|
1783
|
-
customActions.length > 0 && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-1 my-1 h-px bg-border" }),
|
|
1784
|
-
customActions.filter((c) => c.show ? c.show(row) : true).map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1785
|
-
RowActionButton,
|
|
1788
|
+
open && reactDom.createPortal(
|
|
1789
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1790
|
+
"div",
|
|
1786
1791
|
{
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
onAction?.(c.id, row);
|
|
1791
|
-
},
|
|
1792
|
+
ref: menuRef,
|
|
1793
|
+
className: "fixed z-[1000] w-40 rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",
|
|
1794
|
+
style: { top: menuPosition.top, left: menuPosition.left },
|
|
1792
1795
|
children: [
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
+
actions.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1797
|
+
RowActionButton,
|
|
1798
|
+
{
|
|
1799
|
+
danger: a === "delete",
|
|
1800
|
+
onClick: () => {
|
|
1801
|
+
setOpen(false);
|
|
1802
|
+
onAction?.(a, row);
|
|
1803
|
+
},
|
|
1804
|
+
children: [
|
|
1805
|
+
builtinIcons[a],
|
|
1806
|
+
" ",
|
|
1807
|
+
builtinLabels[a]
|
|
1808
|
+
]
|
|
1809
|
+
},
|
|
1810
|
+
a
|
|
1811
|
+
)),
|
|
1812
|
+
customActions.length > 0 && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-1 my-1 h-px bg-border" }),
|
|
1813
|
+
customActions.filter((c) => c.show ? c.show(row) : true).map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1814
|
+
RowActionButton,
|
|
1815
|
+
{
|
|
1816
|
+
danger: c.danger,
|
|
1817
|
+
onClick: () => {
|
|
1818
|
+
setOpen(false);
|
|
1819
|
+
onAction?.(c.id, row);
|
|
1820
|
+
},
|
|
1821
|
+
children: [
|
|
1822
|
+
c.icon,
|
|
1823
|
+
" ",
|
|
1824
|
+
c.label
|
|
1825
|
+
]
|
|
1826
|
+
},
|
|
1827
|
+
c.id
|
|
1828
|
+
))
|
|
1796
1829
|
]
|
|
1797
|
-
}
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1830
|
+
}
|
|
1831
|
+
),
|
|
1832
|
+
document.body
|
|
1833
|
+
)
|
|
1801
1834
|
] });
|
|
1802
1835
|
}
|
|
1803
1836
|
function RowActionButton({
|
|
@@ -1993,57 +2026,148 @@ var TOKEN_TO_VAR = {
|
|
|
1993
2026
|
radius: "--radius",
|
|
1994
2027
|
fontFamily: "--font-family"
|
|
1995
2028
|
};
|
|
1996
|
-
function
|
|
1997
|
-
if (!theme) return
|
|
2029
|
+
function isModed(theme) {
|
|
2030
|
+
if (!theme) return false;
|
|
2031
|
+
return "light" in theme || "dark" in theme;
|
|
2032
|
+
}
|
|
2033
|
+
function tokensToStyle(tokens) {
|
|
2034
|
+
if (!tokens) return {};
|
|
1998
2035
|
const out = {};
|
|
1999
|
-
for (const [k, v] of Object.entries(
|
|
2036
|
+
for (const [k, v] of Object.entries(tokens)) {
|
|
2000
2037
|
if (v == null) continue;
|
|
2001
2038
|
const cssVar = TOKEN_TO_VAR[k];
|
|
2002
2039
|
if (cssVar) out[cssVar] = v;
|
|
2003
2040
|
}
|
|
2004
2041
|
return out;
|
|
2005
2042
|
}
|
|
2006
|
-
|
|
2043
|
+
function themeToStyle(theme) {
|
|
2044
|
+
if (!theme) return {};
|
|
2045
|
+
if (isModed(theme)) return tokensToStyle(theme.light);
|
|
2046
|
+
return tokensToStyle(theme);
|
|
2047
|
+
}
|
|
2048
|
+
function splitTheme(theme) {
|
|
2049
|
+
if (!theme) return { light: void 0, dark: void 0 };
|
|
2050
|
+
if (isModed(theme)) return { light: theme.light, dark: theme.dark };
|
|
2051
|
+
return { light: theme, dark: void 0 };
|
|
2052
|
+
}
|
|
2053
|
+
function buildPreset(hue, chroma = 0.03) {
|
|
2054
|
+
const c = chroma;
|
|
2055
|
+
return {
|
|
2056
|
+
light: {
|
|
2057
|
+
background: `oklch(0.99 ${c * 0.2} ${hue})`,
|
|
2058
|
+
foreground: `oklch(0.18 ${c * 1.2} ${hue})`,
|
|
2059
|
+
card: `oklch(1 0 0)`,
|
|
2060
|
+
cardForeground: `oklch(0.18 ${c * 1.2} ${hue})`,
|
|
2061
|
+
popover: `oklch(1 0 0)`,
|
|
2062
|
+
popoverForeground: `oklch(0.18 ${c * 1.2} ${hue})`,
|
|
2063
|
+
primary: `oklch(0.55 0.2 ${hue})`,
|
|
2064
|
+
primaryForeground: `oklch(0.99 0 0)`,
|
|
2065
|
+
secondary: `oklch(0.96 ${c} ${hue})`,
|
|
2066
|
+
secondaryForeground: `oklch(0.25 ${c * 2} ${hue})`,
|
|
2067
|
+
muted: `oklch(0.96 ${c} ${hue})`,
|
|
2068
|
+
mutedForeground: `oklch(0.5 ${c * 1.5} ${hue})`,
|
|
2069
|
+
accent: `oklch(0.94 ${c * 1.2} ${hue})`,
|
|
2070
|
+
accentForeground: `oklch(0.3 ${c * 3} ${hue})`,
|
|
2071
|
+
destructive: `oklch(0.577 0.245 27.325)`,
|
|
2072
|
+
destructiveForeground: `oklch(0.985 0 0)`,
|
|
2073
|
+
border: `oklch(0.9 ${c * 0.8} ${hue})`,
|
|
2074
|
+
input: `oklch(0.9 ${c * 0.8} ${hue})`,
|
|
2075
|
+
ring: `oklch(0.55 0.2 ${hue} / 0.5)`,
|
|
2076
|
+
radius: "0.625rem"
|
|
2077
|
+
},
|
|
2078
|
+
dark: {
|
|
2079
|
+
background: `oklch(0.16 ${c * 0.6} ${hue})`,
|
|
2080
|
+
foreground: `oklch(0.97 ${c * 0.2} ${hue})`,
|
|
2081
|
+
card: `oklch(0.21 ${c * 0.8} ${hue})`,
|
|
2082
|
+
cardForeground: `oklch(0.97 ${c * 0.2} ${hue})`,
|
|
2083
|
+
popover: `oklch(0.21 ${c * 0.8} ${hue})`,
|
|
2084
|
+
popoverForeground: `oklch(0.97 ${c * 0.2} ${hue})`,
|
|
2085
|
+
primary: `oklch(0.7 0.18 ${hue})`,
|
|
2086
|
+
primaryForeground: `oklch(0.16 ${c * 0.6} ${hue})`,
|
|
2087
|
+
secondary: `oklch(0.27 ${c * 0.8} ${hue})`,
|
|
2088
|
+
secondaryForeground: `oklch(0.97 ${c * 0.2} ${hue})`,
|
|
2089
|
+
muted: `oklch(0.27 ${c * 0.8} ${hue})`,
|
|
2090
|
+
mutedForeground: `oklch(0.7 ${c * 0.5} ${hue})`,
|
|
2091
|
+
accent: `oklch(0.3 ${c * 1.5} ${hue})`,
|
|
2092
|
+
accentForeground: `oklch(0.97 ${c * 0.2} ${hue})`,
|
|
2093
|
+
destructive: `oklch(0.577 0.245 27.325 / 0.6)`,
|
|
2094
|
+
destructiveForeground: `oklch(0.985 0 0)`,
|
|
2095
|
+
border: `oklch(0.27 ${c * 0.8} ${hue})`,
|
|
2096
|
+
input: `oklch(0.27 ${c * 0.8} ${hue})`,
|
|
2097
|
+
ring: `oklch(0.7 0.18 ${hue} / 0.5)`,
|
|
2098
|
+
radius: "0.625rem"
|
|
2099
|
+
}
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
function tokensToCssBlock(tokens) {
|
|
2103
|
+
if (!tokens) return "";
|
|
2104
|
+
const parts = [];
|
|
2105
|
+
for (const [k, v] of Object.entries(tokens)) {
|
|
2106
|
+
if (v == null) continue;
|
|
2107
|
+
const cssVar = TOKEN_TO_VAR[k];
|
|
2108
|
+
if (cssVar) parts.push(`${cssVar}:${v}`);
|
|
2109
|
+
}
|
|
2110
|
+
return parts.join(";");
|
|
2111
|
+
}
|
|
2112
|
+
var neutral = {
|
|
2007
2113
|
light: {
|
|
2008
2114
|
background: "oklch(1 0 0)",
|
|
2009
2115
|
foreground: "oklch(0.145 0 0)",
|
|
2010
2116
|
card: "oklch(1 0 0)",
|
|
2011
2117
|
cardForeground: "oklch(0.145 0 0)",
|
|
2118
|
+
popover: "oklch(1 0 0)",
|
|
2119
|
+
popoverForeground: "oklch(0.145 0 0)",
|
|
2012
2120
|
primary: "oklch(0.205 0 0)",
|
|
2013
2121
|
primaryForeground: "oklch(0.985 0 0)",
|
|
2014
|
-
|
|
2122
|
+
secondary: "oklch(0.97 0 0)",
|
|
2123
|
+
secondaryForeground: "oklch(0.205 0 0)",
|
|
2124
|
+
muted: "oklch(0.97 0 0)",
|
|
2125
|
+
mutedForeground: "oklch(0.556 0 0)",
|
|
2126
|
+
accent: "oklch(0.97 0 0)",
|
|
2127
|
+
accentForeground: "oklch(0.205 0 0)",
|
|
2128
|
+
destructive: "oklch(0.577 0.245 27.325)",
|
|
2129
|
+
destructiveForeground: "oklch(0.985 0 0)",
|
|
2130
|
+
border: "oklch(0.922 0 0)",
|
|
2131
|
+
input: "oklch(0.922 0 0)",
|
|
2132
|
+
ring: "oklch(0.708 0 0)",
|
|
2133
|
+
radius: "0.625rem"
|
|
2015
2134
|
},
|
|
2016
2135
|
dark: {
|
|
2017
2136
|
background: "oklch(0.145 0 0)",
|
|
2018
2137
|
foreground: "oklch(0.985 0 0)",
|
|
2019
2138
|
card: "oklch(0.205 0 0)",
|
|
2020
2139
|
cardForeground: "oklch(0.985 0 0)",
|
|
2140
|
+
popover: "oklch(0.205 0 0)",
|
|
2141
|
+
popoverForeground: "oklch(0.985 0 0)",
|
|
2021
2142
|
primary: "oklch(0.985 0 0)",
|
|
2022
2143
|
primaryForeground: "oklch(0.205 0 0)",
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
accent: "oklch(0.94 0.04 285)",
|
|
2036
|
-
accentForeground: "oklch(0.3 0.12 285)",
|
|
2037
|
-
ring: "oklch(0.55 0.22 285 / 0.5)"
|
|
2038
|
-
},
|
|
2039
|
-
amber: {
|
|
2040
|
-
primary: "oklch(0.7 0.18 65)",
|
|
2041
|
-
primaryForeground: "oklch(0.2 0 0)",
|
|
2042
|
-
accent: "oklch(0.94 0.05 65)",
|
|
2043
|
-
accentForeground: "oklch(0.3 0.12 65)",
|
|
2044
|
-
ring: "oklch(0.7 0.18 65 / 0.5)"
|
|
2144
|
+
secondary: "oklch(0.269 0 0)",
|
|
2145
|
+
secondaryForeground: "oklch(0.985 0 0)",
|
|
2146
|
+
muted: "oklch(0.269 0 0)",
|
|
2147
|
+
mutedForeground: "oklch(0.708 0 0)",
|
|
2148
|
+
accent: "oklch(0.269 0 0)",
|
|
2149
|
+
accentForeground: "oklch(0.985 0 0)",
|
|
2150
|
+
destructive: "oklch(0.577 0.245 27.325 / 0.6)",
|
|
2151
|
+
destructiveForeground: "oklch(0.985 0 0)",
|
|
2152
|
+
border: "oklch(0.269 0 0)",
|
|
2153
|
+
input: "oklch(0.269 0 0)",
|
|
2154
|
+
ring: "oklch(0.439 0 0)",
|
|
2155
|
+
radius: "0.625rem"
|
|
2045
2156
|
}
|
|
2046
2157
|
};
|
|
2158
|
+
var themePresets = {
|
|
2159
|
+
neutral,
|
|
2160
|
+
light: { light: neutral.light },
|
|
2161
|
+
dark: { light: neutral.dark },
|
|
2162
|
+
violet: buildPreset(285),
|
|
2163
|
+
emerald: buildPreset(162),
|
|
2164
|
+
amber: buildPreset(65),
|
|
2165
|
+
rose: buildPreset(15),
|
|
2166
|
+
sky: buildPreset(235),
|
|
2167
|
+
slate: buildPreset(240, 0.015)
|
|
2168
|
+
};
|
|
2169
|
+
var ISOLATE_LIGHT_TOKENS = neutral.light;
|
|
2170
|
+
var ISOLATE_DARK_TOKENS = neutral.dark;
|
|
2047
2171
|
function getPinningStyles(column) {
|
|
2048
2172
|
const isPinned = column.getIsPinned();
|
|
2049
2173
|
if (!isPinned) return {};
|
|
@@ -2166,6 +2290,8 @@ var DEFAULT_LABELS = {
|
|
|
2166
2290
|
total: "Total",
|
|
2167
2291
|
noData: "No data.",
|
|
2168
2292
|
noResults: "No rows match the current filters.",
|
|
2293
|
+
loadError: "Could not load rows.",
|
|
2294
|
+
retry: "Retry",
|
|
2169
2295
|
refreshing: "Refreshing",
|
|
2170
2296
|
rowsPerPage: "Rows per page",
|
|
2171
2297
|
page: "Page",
|
|
@@ -2179,6 +2305,7 @@ var DENSITY_CLASS = {
|
|
|
2179
2305
|
function DataTable({
|
|
2180
2306
|
data,
|
|
2181
2307
|
columns,
|
|
2308
|
+
dataSource,
|
|
2182
2309
|
isLoading,
|
|
2183
2310
|
isFetching,
|
|
2184
2311
|
onRefresh,
|
|
@@ -2205,12 +2332,13 @@ function DataTable({
|
|
|
2205
2332
|
features,
|
|
2206
2333
|
labels: labelsProp,
|
|
2207
2334
|
density = "default",
|
|
2208
|
-
theme
|
|
2335
|
+
theme,
|
|
2336
|
+
isolate = false
|
|
2209
2337
|
}) {
|
|
2210
2338
|
const labels = { ...DEFAULT_LABELS, ...labelsProp };
|
|
2211
2339
|
const f = {
|
|
2212
2340
|
search: features?.search ?? true,
|
|
2213
|
-
refresh: features?.refresh ?? !!onRefresh,
|
|
2341
|
+
refresh: features?.refresh ?? !!(onRefresh || dataSource),
|
|
2214
2342
|
columnVisibility: features?.columnVisibility ?? true,
|
|
2215
2343
|
export: features?.export ?? true,
|
|
2216
2344
|
addRow: features?.addRow ?? !!onAddRow,
|
|
@@ -2221,7 +2349,20 @@ function DataTable({
|
|
|
2221
2349
|
reordering: features?.reordering ?? true,
|
|
2222
2350
|
pinning: features?.pinning ?? true
|
|
2223
2351
|
};
|
|
2224
|
-
const
|
|
2352
|
+
const rawInstanceId = react.useId();
|
|
2353
|
+
const instanceId = react.useMemo(
|
|
2354
|
+
() => `dyno-grid-${rawInstanceId.replace(/[^a-zA-Z0-9]/g, "")}`,
|
|
2355
|
+
[rawInstanceId]
|
|
2356
|
+
);
|
|
2357
|
+
const { lightStyle, darkCss } = react.useMemo(() => {
|
|
2358
|
+
const { light, dark } = splitTheme(theme);
|
|
2359
|
+
const lightTokens = isolate ? { ...ISOLATE_LIGHT_TOKENS, ...light ?? {} } : light;
|
|
2360
|
+
const darkTokens = isolate ? { ...ISOLATE_DARK_TOKENS, ...dark ?? light ?? {} } : dark;
|
|
2361
|
+
return {
|
|
2362
|
+
lightStyle: tokensToStyle(lightTokens),
|
|
2363
|
+
darkCss: darkTokens ? tokensToCssBlock(darkTokens) : null
|
|
2364
|
+
};
|
|
2365
|
+
}, [theme, isolate]);
|
|
2225
2366
|
const [sorting, setSorting] = react.useState([]);
|
|
2226
2367
|
const [columnFilters, setColumnFilters] = react.useState([]);
|
|
2227
2368
|
const [internalGlobalFilter, setInternalGlobalFilter] = react.useState("");
|
|
@@ -2254,14 +2395,80 @@ function DataTable({
|
|
|
2254
2395
|
pageIndex: 0,
|
|
2255
2396
|
pageSize: initialPageSize
|
|
2256
2397
|
});
|
|
2398
|
+
const [sourceRows, setSourceRows] = react.useState(
|
|
2399
|
+
() => dataSource?.initialData ?? []
|
|
2400
|
+
);
|
|
2401
|
+
const [sourceTotalRecords, setSourceTotalRecords] = react.useState(void 0);
|
|
2402
|
+
const [sourceError, setSourceError] = react.useState(null);
|
|
2403
|
+
const [sourceLoading, setSourceLoading] = react.useState(false);
|
|
2404
|
+
const [sourceFetching, setSourceFetching] = react.useState(false);
|
|
2405
|
+
const [sourceRefreshKey, setSourceRefreshKey] = react.useState(0);
|
|
2257
2406
|
const [editingCell, setEditingCell] = react.useState(null);
|
|
2258
2407
|
const [editingRowId, setEditingRowId] = react.useState(null);
|
|
2259
2408
|
const [rowDraft, setRowDraft] = react.useState({});
|
|
2409
|
+
const dataSourceEnabled = !!dataSource && dataSource.enabled !== false;
|
|
2410
|
+
const dataSourceMode = dataSource?.mode ?? "client";
|
|
2411
|
+
const isServerSideDataSource = dataSourceEnabled && dataSourceMode === "server";
|
|
2412
|
+
const dataSourceDeps = dataSource?.deps ?? [];
|
|
2413
|
+
react.useEffect(() => {
|
|
2414
|
+
if (!dataSourceEnabled || !dataSource) return;
|
|
2415
|
+
let cancelled = false;
|
|
2416
|
+
const isInitialLoad = sourceRows.length === 0;
|
|
2417
|
+
setSourceError(null);
|
|
2418
|
+
setSourceLoading(isInitialLoad);
|
|
2419
|
+
setSourceFetching(!isInitialLoad);
|
|
2420
|
+
dataSource.fetchRows({
|
|
2421
|
+
pageIndex: pagination.pageIndex,
|
|
2422
|
+
pageSize: pagination.pageSize,
|
|
2423
|
+
sorting,
|
|
2424
|
+
columnFilters,
|
|
2425
|
+
globalFilter
|
|
2426
|
+
}).then((result) => {
|
|
2427
|
+
if (cancelled) return;
|
|
2428
|
+
const rows2 = Array.isArray(result) ? result : result.rows;
|
|
2429
|
+
setSourceRows(rows2);
|
|
2430
|
+
setSourceTotalRecords(
|
|
2431
|
+
Array.isArray(result) ? rows2.length : result.totalRecords ?? rows2.length
|
|
2432
|
+
);
|
|
2433
|
+
}).catch((error) => {
|
|
2434
|
+
if (cancelled) return;
|
|
2435
|
+
setSourceError(error);
|
|
2436
|
+
dataSource.onError?.(error, {
|
|
2437
|
+
type: isInitialLoad ? "load" : "refresh",
|
|
2438
|
+
message: isInitialLoad ? labels.loadError : labels.refreshing
|
|
2439
|
+
});
|
|
2440
|
+
}).finally(() => {
|
|
2441
|
+
if (cancelled) return;
|
|
2442
|
+
setSourceLoading(false);
|
|
2443
|
+
setSourceFetching(false);
|
|
2444
|
+
});
|
|
2445
|
+
return () => {
|
|
2446
|
+
cancelled = true;
|
|
2447
|
+
};
|
|
2448
|
+
}, [
|
|
2449
|
+
dataSourceEnabled,
|
|
2450
|
+
dataSource,
|
|
2451
|
+
sourceRefreshKey,
|
|
2452
|
+
pagination.pageIndex,
|
|
2453
|
+
pagination.pageSize,
|
|
2454
|
+
sorting,
|
|
2455
|
+
columnFilters,
|
|
2456
|
+
globalFilter,
|
|
2457
|
+
labels.loadError,
|
|
2458
|
+
labels.refreshing,
|
|
2459
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2460
|
+
...dataSourceDeps
|
|
2461
|
+
]);
|
|
2462
|
+
const baseData = dataSourceEnabled ? sourceRows : data ?? [];
|
|
2463
|
+
const effectiveIsLoading = dataSourceEnabled ? sourceLoading : isLoading;
|
|
2464
|
+
const effectiveIsFetching = dataSourceEnabled ? sourceFetching : isFetching;
|
|
2465
|
+
const effectiveOnRefresh = dataSourceEnabled ? () => setSourceRefreshKey((key) => key + 1) : onRefresh;
|
|
2260
2466
|
const [extraRows, setExtraRows] = react.useState([]);
|
|
2261
2467
|
const mergedData = react.useMemo(
|
|
2262
|
-
() => extraRows.length ? [...extraRows, ...
|
|
2263
|
-
[extraRows,
|
|
2468
|
+
() => extraRows.length ? [...extraRows, ...baseData] : baseData,
|
|
2469
|
+
[extraRows, baseData]
|
|
2264
2470
|
);
|
|
2471
|
+
const effectiveTotalRecords = totalRecords ?? (dataSourceEnabled ? sourceTotalRecords ?? mergedData.length : mergedData.length);
|
|
2265
2472
|
const augmentedColumns = react.useMemo(() => {
|
|
2266
2473
|
const wrap = (col) => {
|
|
2267
2474
|
const meta = col.meta;
|
|
@@ -2411,6 +2618,10 @@ function DataTable({
|
|
|
2411
2618
|
enableRowSelection: true,
|
|
2412
2619
|
enableExpanding: !!(renderSubRow || getSubRows),
|
|
2413
2620
|
enablePinning: f.pinning,
|
|
2621
|
+
manualPagination: isServerSideDataSource,
|
|
2622
|
+
manualSorting: isServerSideDataSource,
|
|
2623
|
+
manualFiltering: isServerSideDataSource,
|
|
2624
|
+
pageCount: isServerSideDataSource ? Math.max(1, Math.ceil(effectiveTotalRecords / pagination.pageSize)) : void 0,
|
|
2414
2625
|
getRowId: (row) => String(row.id),
|
|
2415
2626
|
getSubRows,
|
|
2416
2627
|
getRowCanExpand: (row) => {
|
|
@@ -2435,27 +2646,56 @@ function DataTable({
|
|
|
2435
2646
|
getExpandedRowModel: reactTable.getExpandedRowModel(),
|
|
2436
2647
|
getPaginationRowModel: reactTable.getPaginationRowModel()
|
|
2437
2648
|
});
|
|
2438
|
-
const
|
|
2439
|
-
const
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2649
|
+
const reorderState = react.useRef(null);
|
|
2650
|
+
const [activeReorderId, setActiveReorderId] = react.useState(null);
|
|
2651
|
+
const [dragOverColId, setDragOverColId] = react.useState(null);
|
|
2652
|
+
const isInteractiveTarget = (target) => {
|
|
2653
|
+
const el = target;
|
|
2654
|
+
if (!el || !el.closest) return false;
|
|
2655
|
+
return !!el.closest(
|
|
2656
|
+
'button, a, input, select, textarea, [role="menuitem"], [data-no-drag]'
|
|
2657
|
+
);
|
|
2443
2658
|
};
|
|
2444
|
-
const
|
|
2445
|
-
e.
|
|
2446
|
-
e.
|
|
2659
|
+
const onHeaderPointerDown = (id) => (e) => {
|
|
2660
|
+
if (e.button !== 0) return;
|
|
2661
|
+
if (isInteractiveTarget(e.target)) return;
|
|
2662
|
+
reorderState.current = { x: e.clientX, y: e.clientY, id };
|
|
2447
2663
|
};
|
|
2448
|
-
const
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2451
|
-
if (!
|
|
2664
|
+
const onHeaderPointerMove = (e) => {
|
|
2665
|
+
const start = reorderState.current;
|
|
2666
|
+
if (!start) return;
|
|
2667
|
+
if (!activeReorderId) {
|
|
2668
|
+
const dx = e.clientX - start.x;
|
|
2669
|
+
const dy = e.clientY - start.y;
|
|
2670
|
+
if (Math.hypot(dx, dy) < 6) return;
|
|
2671
|
+
setActiveReorderId(start.id);
|
|
2672
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2673
|
+
}
|
|
2674
|
+
const el = document.elementFromPoint(e.clientX, e.clientY);
|
|
2675
|
+
const th = el ? el.closest("th[data-col-id]") : null;
|
|
2676
|
+
const overId = th?.dataset.colId ?? null;
|
|
2677
|
+
const next = overId && overId !== start.id ? overId : null;
|
|
2678
|
+
if (next !== dragOverColId) setDragOverColId(next);
|
|
2679
|
+
};
|
|
2680
|
+
const onHeaderPointerUp = (e) => {
|
|
2681
|
+
const start = reorderState.current;
|
|
2682
|
+
reorderState.current = null;
|
|
2683
|
+
if (!activeReorderId) return;
|
|
2684
|
+
try {
|
|
2685
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
2686
|
+
} catch {
|
|
2687
|
+
}
|
|
2688
|
+
const target = dragOverColId;
|
|
2689
|
+
setActiveReorderId(null);
|
|
2690
|
+
setDragOverColId(null);
|
|
2691
|
+
if (!start || !target || target === start.id) return;
|
|
2452
2692
|
setColumnOrder((order) => {
|
|
2453
2693
|
const next = [...order];
|
|
2454
|
-
const from = next.indexOf(
|
|
2455
|
-
const to = next.indexOf(
|
|
2694
|
+
const from = next.indexOf(start.id);
|
|
2695
|
+
const to = next.indexOf(target);
|
|
2456
2696
|
if (from === -1 || to === -1) return order;
|
|
2457
2697
|
next.splice(from, 1);
|
|
2458
|
-
next.splice(to, 0,
|
|
2698
|
+
next.splice(to, 0, start.id);
|
|
2459
2699
|
return next;
|
|
2460
2700
|
});
|
|
2461
2701
|
};
|
|
@@ -2501,20 +2741,26 @@ function DataTable({
|
|
|
2501
2741
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2502
2742
|
"div",
|
|
2503
2743
|
{
|
|
2744
|
+
"data-dyno-grid": instanceId,
|
|
2504
2745
|
className: cn(
|
|
2505
2746
|
"flex flex-col rounded-lg border bg-card text-card-foreground shadow-sm",
|
|
2506
2747
|
DENSITY_CLASS[density],
|
|
2507
2748
|
className
|
|
2508
2749
|
),
|
|
2509
|
-
style:
|
|
2750
|
+
style: lightStyle,
|
|
2510
2751
|
children: [
|
|
2752
|
+
darkCss && /* @__PURE__ */ jsxRuntime.jsxs("style", { children: [
|
|
2753
|
+
`@media (prefers-color-scheme: dark){[data-dyno-grid="${instanceId}"]{${darkCss}}}`,
|
|
2754
|
+
`.dark [data-dyno-grid="${instanceId}"]{${darkCss}}`,
|
|
2755
|
+
`[data-dyno-grid="${instanceId}"].dark{${darkCss}}`
|
|
2756
|
+
] }),
|
|
2511
2757
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2512
2758
|
DataTableToolbar,
|
|
2513
2759
|
{
|
|
2514
2760
|
table,
|
|
2515
|
-
totalRecords:
|
|
2516
|
-
isFetching,
|
|
2517
|
-
onRefresh: f.refresh ?
|
|
2761
|
+
totalRecords: effectiveTotalRecords,
|
|
2762
|
+
isFetching: effectiveIsFetching,
|
|
2763
|
+
onRefresh: f.refresh ? effectiveOnRefresh : void 0,
|
|
2518
2764
|
onAddRow: f.addRow ? handleAddRow : void 0,
|
|
2519
2765
|
onBulkDelete,
|
|
2520
2766
|
exportFileName,
|
|
@@ -2542,32 +2788,38 @@ function DataTable({
|
|
|
2542
2788
|
const meta = header.column.columnDef.meta;
|
|
2543
2789
|
const isUtility = header.column.id === "__select" || header.column.id === "__expand" || header.column.id === "__actions";
|
|
2544
2790
|
const isPinned = !!header.column.getIsPinned();
|
|
2791
|
+
const canReorder = !isUtility && f.reordering;
|
|
2792
|
+
const isDropTarget = canReorder && dragOverColId === header.column.id;
|
|
2793
|
+
const isBeingDragged = canReorder && activeReorderId === header.column.id;
|
|
2545
2794
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2546
2795
|
"th",
|
|
2547
2796
|
{
|
|
2548
2797
|
colSpan: header.colSpan,
|
|
2798
|
+
"data-col-id": header.column.id,
|
|
2799
|
+
onPointerDown: canReorder ? onHeaderPointerDown(header.column.id) : void 0,
|
|
2800
|
+
onPointerMove: canReorder ? onHeaderPointerMove : void 0,
|
|
2801
|
+
onPointerUp: canReorder ? onHeaderPointerUp : void 0,
|
|
2802
|
+
onPointerCancel: canReorder ? onHeaderPointerUp : void 0,
|
|
2549
2803
|
style: {
|
|
2550
2804
|
width: header.getSize(),
|
|
2551
2805
|
...getPinningStyles(header.column),
|
|
2552
2806
|
...isPinned ? { zIndex: 2 } : {}
|
|
2553
2807
|
},
|
|
2554
2808
|
className: cn(
|
|
2555
|
-
"group/th relative h-9 px-2 text-left align-middle text-xs font-medium text-muted-foreground",
|
|
2809
|
+
"group/th relative h-9 px-2 text-left align-middle text-xs font-medium text-muted-foreground select-none",
|
|
2810
|
+
canReorder && "cursor-grab active:cursor-grabbing",
|
|
2556
2811
|
isPinned && "bg-card",
|
|
2812
|
+
isBeingDragged && "opacity-50",
|
|
2813
|
+
isDropTarget && "bg-primary/10 ring-2 ring-inset ring-primary/40",
|
|
2557
2814
|
meta?.headerClassName
|
|
2558
2815
|
),
|
|
2559
2816
|
children: [
|
|
2560
2817
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2561
|
-
|
|
2562
|
-
|
|
2818
|
+
canReorder && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2819
|
+
lucideReact.GripVerticalIcon,
|
|
2563
2820
|
{
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
onDragOver: onHeaderDragOver,
|
|
2567
|
-
onDrop: () => onHeaderDrop(header.column.id),
|
|
2568
|
-
className: "-ml-1 cursor-grab rounded p-0.5 text-muted-foreground/40 opacity-0 transition group-hover/th:opacity-100 hover:bg-muted hover:text-foreground active:cursor-grabbing",
|
|
2569
|
-
title: "Drag to reorder",
|
|
2570
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVerticalIcon, { className: "size-3" })
|
|
2821
|
+
className: "-ml-1 size-3 shrink-0 text-muted-foreground/40 opacity-0 transition group-hover/th:opacity-100",
|
|
2822
|
+
"aria-hidden": "true"
|
|
2571
2823
|
}
|
|
2572
2824
|
),
|
|
2573
2825
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()) })
|
|
@@ -2575,6 +2827,8 @@ function DataTable({
|
|
|
2575
2827
|
header.column.getCanResize() && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2576
2828
|
"span",
|
|
2577
2829
|
{
|
|
2830
|
+
"data-no-drag": true,
|
|
2831
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
2578
2832
|
onMouseDown: header.getResizeHandler(),
|
|
2579
2833
|
onTouchStart: header.getResizeHandler(),
|
|
2580
2834
|
onDoubleClick: () => header.column.resetSize(),
|
|
@@ -2589,7 +2843,25 @@ function DataTable({
|
|
|
2589
2843
|
header.id
|
|
2590
2844
|
);
|
|
2591
2845
|
}) }, hg.id)) }),
|
|
2592
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children:
|
|
2846
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: effectiveIsLoading ? renderSkeleton(visibleLeafCount, pagination.pageSize) : sourceError && rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2847
|
+
"td",
|
|
2848
|
+
{
|
|
2849
|
+
colSpan: visibleLeafCount,
|
|
2850
|
+
className: "h-32 text-center text-sm text-muted-foreground",
|
|
2851
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
2852
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.loadError }),
|
|
2853
|
+
effectiveOnRefresh && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2854
|
+
"button",
|
|
2855
|
+
{
|
|
2856
|
+
type: "button",
|
|
2857
|
+
onClick: effectiveOnRefresh,
|
|
2858
|
+
className: "rounded-md border px-2 py-1 text-xs text-foreground hover:bg-muted",
|
|
2859
|
+
children: labels.retry
|
|
2860
|
+
}
|
|
2861
|
+
)
|
|
2862
|
+
] })
|
|
2863
|
+
}
|
|
2864
|
+
) }) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2593
2865
|
"td",
|
|
2594
2866
|
{
|
|
2595
2867
|
colSpan: visibleLeafCount,
|
|
@@ -2608,7 +2880,7 @@ function DataTable({
|
|
|
2608
2880
|
]
|
|
2609
2881
|
}
|
|
2610
2882
|
),
|
|
2611
|
-
|
|
2883
|
+
effectiveIsFetching && !effectiveIsLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none absolute top-1.5 right-2 flex items-center gap-1.5 rounded-md bg-background/80 px-2 py-1 text-xs text-muted-foreground shadow-sm backdrop-blur", children: [
|
|
2612
2884
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "size-3 animate-spin" }),
|
|
2613
2885
|
" ",
|
|
2614
2886
|
labels.refreshing
|
|
@@ -2675,15 +2947,21 @@ exports.DataTablePagination = DataTablePagination;
|
|
|
2675
2947
|
exports.DataTableRowActions = DataTableRowActions;
|
|
2676
2948
|
exports.DataTableToolbar = DataTableToolbar;
|
|
2677
2949
|
exports.EditableCell = EditableCell;
|
|
2950
|
+
exports.ISOLATE_DARK_TOKENS = ISOLATE_DARK_TOKENS;
|
|
2951
|
+
exports.ISOLATE_LIGHT_TOKENS = ISOLATE_LIGHT_TOKENS;
|
|
2678
2952
|
exports.booleanFilterFn = booleanFilterFn;
|
|
2953
|
+
exports.buildPreset = buildPreset;
|
|
2679
2954
|
exports.dateFilterFn = dateFilterFn;
|
|
2680
2955
|
exports.exportToCsv = exportToCsv;
|
|
2681
2956
|
exports.exportToExcel = exportToExcel;
|
|
2682
2957
|
exports.isFilterActive = isFilterActive;
|
|
2683
2958
|
exports.numberFilterFn = numberFilterFn;
|
|
2684
2959
|
exports.setFilterFn = setFilterFn;
|
|
2960
|
+
exports.splitTheme = splitTheme;
|
|
2685
2961
|
exports.textFilterFn = textFilterFn;
|
|
2686
2962
|
exports.themePresets = themePresets;
|
|
2687
2963
|
exports.themeToStyle = themeToStyle;
|
|
2964
|
+
exports.tokensToCssBlock = tokensToCssBlock;
|
|
2965
|
+
exports.tokensToStyle = tokensToStyle;
|
|
2688
2966
|
//# sourceMappingURL=index.cjs.map
|
|
2689
2967
|
//# sourceMappingURL=index.cjs.map
|