@dimaan/ui 0.0.19 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +135 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +191 -166
- package/dist/index.d.ts +191 -166
- package/dist/index.js +136 -182
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1724,12 +1724,26 @@ var formPageBodyClass = "flex-1";
|
|
|
1724
1724
|
var formPageActionsBarClass = "sticky bottom-0 -mx-6 -mb-6 mt-6 flex items-center justify-end gap-2 border-t border-border bg-background/95 px-6 py-3 backdrop-blur supports-[backdrop-filter]:bg-background/80";
|
|
1725
1725
|
var formPageSkeletonRowClass = "h-10 w-full animate-pulse rounded-md bg-muted";
|
|
1726
1726
|
var DEFAULT_SKELETON_ROW_COUNT2 = 6;
|
|
1727
|
+
var DEFAULT_LABELS_LTR = {
|
|
1728
|
+
back: "Back",
|
|
1729
|
+
cancel: "Cancel",
|
|
1730
|
+
save: "Save",
|
|
1731
|
+
saving: "Saving\u2026"
|
|
1732
|
+
};
|
|
1733
|
+
var DEFAULT_LABELS_RTL = {
|
|
1734
|
+
back: "\u0631\u062C\u0648\u0639",
|
|
1735
|
+
cancel: "\u0625\u0644\u063A\u0627\u0621",
|
|
1736
|
+
save: "\u062D\u0641\u0638",
|
|
1737
|
+
saving: "\u062C\u0627\u0631\u064D \u0627\u0644\u062D\u0641\u0638\u2026"
|
|
1738
|
+
};
|
|
1727
1739
|
function FormPage({
|
|
1728
1740
|
title,
|
|
1729
1741
|
description,
|
|
1730
|
-
back,
|
|
1731
1742
|
bordered = true,
|
|
1732
1743
|
onSubmit,
|
|
1744
|
+
onCancel,
|
|
1745
|
+
isSubmitting,
|
|
1746
|
+
labels: labelsProp,
|
|
1733
1747
|
isLoading = false,
|
|
1734
1748
|
loadingRowCount = DEFAULT_SKELETON_ROW_COUNT2,
|
|
1735
1749
|
actions,
|
|
@@ -1739,8 +1753,23 @@ function FormPage({
|
|
|
1739
1753
|
bodyClassName,
|
|
1740
1754
|
actionsClassName
|
|
1741
1755
|
}) {
|
|
1756
|
+
const navigate = reactRouterDom.useNavigate();
|
|
1757
|
+
const dir = useDirection();
|
|
1758
|
+
const formContext = reactHookForm.useFormContext();
|
|
1759
|
+
const submitting = isSubmitting ?? formContext?.formState?.isSubmitting ?? false;
|
|
1760
|
+
const defaults = dir === "rtl" ? DEFAULT_LABELS_RTL : DEFAULT_LABELS_LTR;
|
|
1761
|
+
const labels = { ...defaults, ...labelsProp };
|
|
1762
|
+
const goBack = () => navigate(-1);
|
|
1742
1763
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "form-page", className: cn(formPageBaseClass, className), children: [
|
|
1743
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1765
|
+
PageHeader,
|
|
1766
|
+
{
|
|
1767
|
+
title,
|
|
1768
|
+
description,
|
|
1769
|
+
back: { label: labels.back, onClick: goBack },
|
|
1770
|
+
bordered
|
|
1771
|
+
}
|
|
1772
|
+
),
|
|
1744
1773
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1745
1774
|
"form",
|
|
1746
1775
|
{
|
|
@@ -1751,14 +1780,27 @@ function FormPage({
|
|
|
1751
1780
|
className: cn("flex flex-1 flex-col gap-6", formClassName),
|
|
1752
1781
|
children: [
|
|
1753
1782
|
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "form-page-body", className: cn(formPageBodyClass, bodyClassName), children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(FormPageSkeleton, { rowCount: loadingRowCount }) : children }),
|
|
1754
|
-
|
|
1783
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1755
1784
|
"div",
|
|
1756
1785
|
{
|
|
1757
1786
|
"data-slot": "form-page-actions",
|
|
1758
1787
|
className: cn(formPageActionsBarClass, actionsClassName),
|
|
1759
|
-
children:
|
|
1788
|
+
children: [
|
|
1789
|
+
actions,
|
|
1790
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "outline", onClick: onCancel ?? goBack, children: labels.cancel }),
|
|
1791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1792
|
+
Button,
|
|
1793
|
+
{
|
|
1794
|
+
type: "submit",
|
|
1795
|
+
loading: submitting,
|
|
1796
|
+
loadingText: labels.saving,
|
|
1797
|
+
disabled: isLoading,
|
|
1798
|
+
children: labels.save
|
|
1799
|
+
}
|
|
1800
|
+
)
|
|
1801
|
+
]
|
|
1760
1802
|
}
|
|
1761
|
-
)
|
|
1803
|
+
)
|
|
1762
1804
|
]
|
|
1763
1805
|
}
|
|
1764
1806
|
)
|
|
@@ -2009,15 +2051,35 @@ var SelectItem = react.forwardRef(function SelectItem2({ className, children, ..
|
|
|
2009
2051
|
/* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.ItemText, { children })
|
|
2010
2052
|
] });
|
|
2011
2053
|
});
|
|
2054
|
+
var EN_LABELS = {
|
|
2055
|
+
rowsPerPage: "Rows per page",
|
|
2056
|
+
pageRangeOf: "of",
|
|
2057
|
+
previousPage: "Previous page",
|
|
2058
|
+
nextPage: "Next page"
|
|
2059
|
+
};
|
|
2060
|
+
var AR_LABELS = {
|
|
2061
|
+
rowsPerPage: "\u0635\u0641\u0648\u0641 \u0644\u0643\u0644 \u0635\u0641\u062D\u0629",
|
|
2062
|
+
pageRangeOf: "\u0645\u0646",
|
|
2063
|
+
previousPage: "\u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629",
|
|
2064
|
+
nextPage: "\u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629"
|
|
2065
|
+
};
|
|
2012
2066
|
function Pagination({
|
|
2013
2067
|
pageIndex,
|
|
2014
2068
|
pageSize,
|
|
2015
2069
|
pageCount,
|
|
2016
2070
|
totalRowCount,
|
|
2017
2071
|
pageSizeOptions,
|
|
2018
|
-
onChange
|
|
2072
|
+
onChange,
|
|
2073
|
+
labels: labelsProp
|
|
2019
2074
|
}) {
|
|
2020
2075
|
const dir = useDirection();
|
|
2076
|
+
const localeDefaults = dir === "rtl" ? AR_LABELS : EN_LABELS;
|
|
2077
|
+
const labels = {
|
|
2078
|
+
rowsPerPage: labelsProp?.rowsPerPage ?? localeDefaults.rowsPerPage,
|
|
2079
|
+
pageRangeOf: labelsProp?.pageRangeOf ?? localeDefaults.pageRangeOf,
|
|
2080
|
+
previousPage: labelsProp?.previousPage ?? localeDefaults.previousPage,
|
|
2081
|
+
nextPage: labelsProp?.nextPage ?? localeDefaults.nextPage
|
|
2082
|
+
};
|
|
2021
2083
|
const isRtl = dir === "rtl";
|
|
2022
2084
|
const isFirst = pageIndex <= 0;
|
|
2023
2085
|
const isLast = pageIndex >= pageCount - 1;
|
|
@@ -2031,7 +2093,7 @@ function Pagination({
|
|
|
2031
2093
|
const end = Math.min(totalRowCount, (pageIndex + 1) * pageSize);
|
|
2032
2094
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 text-sm text-muted-foreground", children: [
|
|
2033
2095
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
2034
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.rowsPerPage }),
|
|
2035
2097
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2036
2098
|
"select",
|
|
2037
2099
|
{
|
|
@@ -2050,7 +2112,9 @@ function Pagination({
|
|
|
2050
2112
|
start,
|
|
2051
2113
|
"\u2013",
|
|
2052
2114
|
end,
|
|
2053
|
-
"
|
|
2115
|
+
" ",
|
|
2116
|
+
labels.pageRangeOf,
|
|
2117
|
+
" ",
|
|
2054
2118
|
totalRowCount
|
|
2055
2119
|
] }),
|
|
2056
2120
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
@@ -2062,7 +2126,7 @@ function Pagination({
|
|
|
2062
2126
|
size: "sm",
|
|
2063
2127
|
disabled: isFirst,
|
|
2064
2128
|
onClick: goPrev,
|
|
2065
|
-
"aria-label":
|
|
2129
|
+
"aria-label": labels.previousPage,
|
|
2066
2130
|
children: isRtl ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
2067
2131
|
}
|
|
2068
2132
|
),
|
|
@@ -2079,7 +2143,7 @@ function Pagination({
|
|
|
2079
2143
|
size: "sm",
|
|
2080
2144
|
disabled: isLast,
|
|
2081
2145
|
onClick: goNext,
|
|
2082
|
-
"aria-label":
|
|
2146
|
+
"aria-label": labels.nextPage,
|
|
2083
2147
|
children: isRtl ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
2084
2148
|
}
|
|
2085
2149
|
)
|
|
@@ -2132,66 +2196,28 @@ var alignClass = {
|
|
|
2132
2196
|
end: "text-end"
|
|
2133
2197
|
};
|
|
2134
2198
|
var EMPTY_SELECTION = /* @__PURE__ */ new Set();
|
|
2135
|
-
var NO_SORT = { columnId: null, direction: "asc" };
|
|
2136
2199
|
function useTableState(props) {
|
|
2137
2200
|
const {
|
|
2138
|
-
defaultSort,
|
|
2139
|
-
sort: sortProp,
|
|
2140
|
-
onSortChange,
|
|
2141
|
-
defaultPagination,
|
|
2142
|
-
pagination: paginationProp,
|
|
2143
|
-
onPaginationChange,
|
|
2144
|
-
pageSizeOptions,
|
|
2145
2201
|
defaultSelectedRowIds,
|
|
2146
2202
|
selectedRowIds: selectedRowIdsProp,
|
|
2147
|
-
onSelectedRowIdsChange
|
|
2148
|
-
totalCount
|
|
2203
|
+
onSelectedRowIdsChange
|
|
2149
2204
|
} = props;
|
|
2150
|
-
const [internalSort, setInternalSort] = react.useState(defaultSort ?? NO_SORT);
|
|
2151
|
-
const isSortControlled = sortProp !== void 0;
|
|
2152
|
-
const sort = isSortControlled ? sortProp : internalSort;
|
|
2153
|
-
const setSort = react.useCallback(
|
|
2154
|
-
(next) => {
|
|
2155
|
-
if (!isSortControlled) setInternalSort(next);
|
|
2156
|
-
onSortChange?.(next);
|
|
2157
|
-
},
|
|
2158
|
-
[isSortControlled, onSortChange]
|
|
2159
|
-
);
|
|
2160
|
-
const [internalPagination, setInternalPagination] = react.useState(
|
|
2161
|
-
defaultPagination ?? { pageIndex: 0, pageSize: pageSizeOptions?.[0] ?? 10 }
|
|
2162
|
-
);
|
|
2163
|
-
const isPaginationControlled = paginationProp !== void 0;
|
|
2164
|
-
const pagination = isPaginationControlled ? paginationProp : internalPagination;
|
|
2165
|
-
const setPagination = react.useCallback(
|
|
2166
|
-
(next) => {
|
|
2167
|
-
if (!isPaginationControlled) setInternalPagination(next);
|
|
2168
|
-
onPaginationChange?.(next);
|
|
2169
|
-
},
|
|
2170
|
-
[isPaginationControlled, onPaginationChange]
|
|
2171
|
-
);
|
|
2172
2205
|
const [internalSelected, setInternalSelected] = react.useState(
|
|
2173
2206
|
defaultSelectedRowIds ?? EMPTY_SELECTION
|
|
2174
2207
|
);
|
|
2175
|
-
const
|
|
2176
|
-
const selected =
|
|
2208
|
+
const isControlled = selectedRowIdsProp !== void 0;
|
|
2209
|
+
const selected = isControlled ? selectedRowIdsProp : internalSelected;
|
|
2177
2210
|
const setSelected = react.useCallback(
|
|
2178
2211
|
(next) => {
|
|
2179
|
-
if (!
|
|
2212
|
+
if (!isControlled) setInternalSelected(next);
|
|
2180
2213
|
onSelectedRowIdsChange?.(next);
|
|
2181
2214
|
},
|
|
2182
|
-
[
|
|
2215
|
+
[isControlled, onSelectedRowIdsChange]
|
|
2183
2216
|
);
|
|
2184
|
-
return {
|
|
2185
|
-
sort,
|
|
2186
|
-
setSort,
|
|
2187
|
-
pagination,
|
|
2188
|
-
setPagination,
|
|
2189
|
-
selected,
|
|
2190
|
-
setSelected,
|
|
2191
|
-
isServerSide: totalCount !== void 0
|
|
2192
|
-
};
|
|
2217
|
+
return { selected, setSelected };
|
|
2193
2218
|
}
|
|
2194
2219
|
var DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50];
|
|
2220
|
+
var DEFAULT_PAGE_SIZE = 10;
|
|
2195
2221
|
function defaultGetRowId(row, index) {
|
|
2196
2222
|
const rowId = row.id;
|
|
2197
2223
|
return rowId === void 0 || rowId === null ? String(index) : String(rowId);
|
|
@@ -2218,36 +2244,26 @@ function Table(props) {
|
|
|
2218
2244
|
tableRef,
|
|
2219
2245
|
pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
|
|
2220
2246
|
showPagination,
|
|
2221
|
-
caption
|
|
2247
|
+
caption,
|
|
2248
|
+
sort,
|
|
2249
|
+
onSortChange,
|
|
2250
|
+
pagination,
|
|
2251
|
+
onPaginationChange,
|
|
2252
|
+
totalCount,
|
|
2253
|
+
labels
|
|
2222
2254
|
} = props;
|
|
2223
2255
|
const ariaLabel = props["aria-label"];
|
|
2224
2256
|
const ariaLabelledBy = props["aria-labelledby"];
|
|
2225
|
-
const {
|
|
2226
|
-
const
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
if (!get) return data;
|
|
2232
|
-
const tagged = data.map((row, index) => ({ row, index }));
|
|
2233
|
-
tagged.sort((a, b) => {
|
|
2234
|
-
const cmp = compareValues(get(a.row), get(b.row));
|
|
2235
|
-
if (cmp !== 0) return sort.direction === "asc" ? cmp : -cmp;
|
|
2236
|
-
return a.index - b.index;
|
|
2237
|
-
});
|
|
2238
|
-
return tagged.map((entry) => entry.row);
|
|
2239
|
-
}, [data, columns, sort, isServerSide]);
|
|
2240
|
-
const pagedRows = react.useMemo(() => {
|
|
2241
|
-
if (isServerSide) return sortedRows;
|
|
2242
|
-
const start = pagination.pageIndex * pagination.pageSize;
|
|
2243
|
-
return sortedRows.slice(start, start + pagination.pageSize);
|
|
2244
|
-
}, [sortedRows, pagination, isServerSide]);
|
|
2245
|
-
const totalRowCount = isServerSide ? props.totalCount ?? 0 : data.length;
|
|
2246
|
-
const pageCount = Math.max(1, Math.ceil(totalRowCount / pagination.pageSize));
|
|
2257
|
+
const { selected, setSelected } = useTableState(props);
|
|
2258
|
+
const effectiveSort = sort ?? { columnId: null, direction: "asc" };
|
|
2259
|
+
const pageSize = pagination?.pageSize ?? pageSizeOptions[0] ?? DEFAULT_PAGE_SIZE;
|
|
2260
|
+
const pageIndex = pagination?.pageIndex ?? 0;
|
|
2261
|
+
const totalRowCount = totalCount ?? data.length;
|
|
2262
|
+
const pageCount = Math.max(1, Math.ceil(totalRowCount / pageSize));
|
|
2247
2263
|
const selectableRowIds = react.useMemo(() => {
|
|
2248
2264
|
if (!enableRowSelection) return [];
|
|
2249
|
-
return
|
|
2250
|
-
}, [
|
|
2265
|
+
return data.map((row, index) => ({ row, index })).filter(({ row }) => isRowSelectable ? isRowSelectable(row) : true).map(({ row, index }) => getRowId(row, index));
|
|
2266
|
+
}, [data, enableRowSelection, isRowSelectable, getRowId]);
|
|
2251
2267
|
const selectedOnPageCount = selectableRowIds.reduce(
|
|
2252
2268
|
(acc, id) => selected.has(id) ? acc + 1 : acc,
|
|
2253
2269
|
0
|
|
@@ -2275,13 +2291,16 @@ function Table(props) {
|
|
|
2275
2291
|
};
|
|
2276
2292
|
const clearSelection = () => setSelected(/* @__PURE__ */ new Set());
|
|
2277
2293
|
const handleSortClick = (columnId) => {
|
|
2278
|
-
|
|
2294
|
+
if (!onSortChange) return;
|
|
2295
|
+
onSortChange(nextSort(effectiveSort, columnId));
|
|
2279
2296
|
};
|
|
2297
|
+
const handlePaginationChange = onPaginationChange ?? (() => {
|
|
2298
|
+
});
|
|
2280
2299
|
const totalColumnCount = columns.length + (enableRowSelection ? 1 : 0);
|
|
2281
|
-
const paginationVisible = showPagination ?? totalRowCount >
|
|
2300
|
+
const paginationVisible = Boolean(pagination) && (showPagination ?? totalRowCount > pageSize);
|
|
2282
2301
|
const sizeClasses = tableSizeClass[size];
|
|
2283
2302
|
const showToolbar = enableRowSelection && bulkActions !== void 0 && selected.size > 0;
|
|
2284
|
-
const skeletonCount = loadingRowCount ??
|
|
2303
|
+
const skeletonCount = loadingRowCount ?? pageSize;
|
|
2285
2304
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-3", className), children: [
|
|
2286
2305
|
showToolbar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2287
2306
|
Toolbar,
|
|
@@ -2330,8 +2349,8 @@ function Table(props) {
|
|
|
2330
2349
|
}
|
|
2331
2350
|
) }) : null,
|
|
2332
2351
|
columns.map((column) => {
|
|
2333
|
-
const isSorted =
|
|
2334
|
-
const ariaSort = isSorted ?
|
|
2352
|
+
const isSorted = effectiveSort.columnId === column.id;
|
|
2353
|
+
const ariaSort = isSorted ? effectiveSort.direction === "asc" ? "ascending" : "descending" : "none";
|
|
2335
2354
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2336
2355
|
"th",
|
|
2337
2356
|
{
|
|
@@ -2348,14 +2367,14 @@ function Table(props) {
|
|
|
2348
2367
|
type: "button",
|
|
2349
2368
|
onClick: () => handleSortClick(column.id),
|
|
2350
2369
|
className: "inline-flex items-center gap-1.5 font-inherit uppercase tracking-inherit text-inherit hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
2351
|
-
"aria-label": sortAriaLabel(column,
|
|
2370
|
+
"aria-label": sortAriaLabel(column, effectiveSort),
|
|
2352
2371
|
children: [
|
|
2353
2372
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: renderHeader(column.header) }),
|
|
2354
2373
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2355
2374
|
SortIndicator,
|
|
2356
2375
|
{
|
|
2357
2376
|
active: isSorted,
|
|
2358
|
-
direction: isSorted ?
|
|
2377
|
+
direction: isSorted ? effectiveSort.direction : null
|
|
2359
2378
|
}
|
|
2360
2379
|
)
|
|
2361
2380
|
]
|
|
@@ -2375,14 +2394,14 @@ function Table(props) {
|
|
|
2375
2394
|
columnCount: totalColumnCount,
|
|
2376
2395
|
cellClassName: sizeClasses.cell
|
|
2377
2396
|
}
|
|
2378
|
-
) :
|
|
2397
|
+
) : data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2379
2398
|
"td",
|
|
2380
2399
|
{
|
|
2381
2400
|
colSpan: totalColumnCount,
|
|
2382
2401
|
className: cn(sizeClasses.cell, "py-10 text-center text-muted-foreground"),
|
|
2383
2402
|
children: emptyState ?? "No data"
|
|
2384
2403
|
}
|
|
2385
|
-
) }) :
|
|
2404
|
+
) }) : data.map((row, rowIndex) => {
|
|
2386
2405
|
const id = getRowId(row, rowIndex);
|
|
2387
2406
|
const isSelected = selected.has(id);
|
|
2388
2407
|
const rowSelectable = isRowSelectable ? isRowSelectable(row) : true;
|
|
@@ -2435,12 +2454,13 @@ function Table(props) {
|
|
|
2435
2454
|
paginationVisible ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2436
2455
|
Pagination,
|
|
2437
2456
|
{
|
|
2438
|
-
pageIndex
|
|
2439
|
-
pageSize
|
|
2457
|
+
pageIndex,
|
|
2458
|
+
pageSize,
|
|
2440
2459
|
pageCount,
|
|
2441
2460
|
totalRowCount,
|
|
2442
2461
|
pageSizeOptions,
|
|
2443
|
-
onChange:
|
|
2462
|
+
onChange: handlePaginationChange,
|
|
2463
|
+
labels
|
|
2444
2464
|
}
|
|
2445
2465
|
) : null
|
|
2446
2466
|
] });
|
|
@@ -2456,24 +2476,6 @@ function renderCell(column, row, rowIndex) {
|
|
|
2456
2476
|
}
|
|
2457
2477
|
return null;
|
|
2458
2478
|
}
|
|
2459
|
-
function resolveSortGetter(column) {
|
|
2460
|
-
if (column.sortAccessor) return column.sortAccessor;
|
|
2461
|
-
if (column.accessor !== void 0) {
|
|
2462
|
-
const key = column.accessor;
|
|
2463
|
-
return (row) => row[key];
|
|
2464
|
-
}
|
|
2465
|
-
return null;
|
|
2466
|
-
}
|
|
2467
|
-
function compareValues(a, b) {
|
|
2468
|
-
if (a === b) return 0;
|
|
2469
|
-
if (a === null || a === void 0) return 1;
|
|
2470
|
-
if (b === null || b === void 0) return -1;
|
|
2471
|
-
if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
|
|
2472
|
-
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
2473
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a < b ? -1 : 1;
|
|
2474
|
-
if (typeof a === "boolean" && typeof b === "boolean") return a === b ? 0 : a ? 1 : -1;
|
|
2475
|
-
return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
|
|
2476
|
-
}
|
|
2477
2479
|
function nextSort(current, columnId) {
|
|
2478
2480
|
if (current.columnId !== columnId) return { columnId, direction: "asc" };
|
|
2479
2481
|
if (current.direction === "asc") return { columnId, direction: "desc" };
|
|
@@ -2524,16 +2526,14 @@ function ListPage({
|
|
|
2524
2526
|
getRowId,
|
|
2525
2527
|
isLoading = false,
|
|
2526
2528
|
loadingRowCount,
|
|
2527
|
-
|
|
2528
|
-
searchValue: searchValueProp,
|
|
2529
|
+
searchValue,
|
|
2529
2530
|
onSearchChange,
|
|
2530
2531
|
filters,
|
|
2531
|
-
filterValues
|
|
2532
|
+
filterValues,
|
|
2532
2533
|
onFilterChange,
|
|
2533
2534
|
enableRowSelection,
|
|
2534
2535
|
bulkActions,
|
|
2535
2536
|
pagination,
|
|
2536
|
-
defaultPagination,
|
|
2537
2537
|
onPaginationChange,
|
|
2538
2538
|
totalCount,
|
|
2539
2539
|
pageSizeOptions,
|
|
@@ -2543,82 +2543,36 @@ function ListPage({
|
|
|
2543
2543
|
className
|
|
2544
2544
|
}) {
|
|
2545
2545
|
const labels = { ...DEFAULT_LABELS2, ...labelsProp };
|
|
2546
|
-
const
|
|
2547
|
-
|
|
2546
|
+
const showSearch = onSearchChange !== void 0;
|
|
2547
|
+
const showFilterBar = showSearch || Boolean(filters?.length);
|
|
2548
|
+
const hasActiveQuery = react.useMemo(() => {
|
|
2549
|
+
if ((searchValue ?? "").trim() !== "") return true;
|
|
2548
2550
|
for (const f of filters ?? []) {
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
}, [filters]);
|
|
2553
|
-
const isSearchControlled = searchValueProp !== void 0;
|
|
2554
|
-
const isFiltersControlled = filterValuesProp !== void 0;
|
|
2555
|
-
const [internalSearch, setInternalSearch] = react.useState("");
|
|
2556
|
-
const [internalFilterValues, setInternalFilterValues] = react.useState(initialFilterValues);
|
|
2557
|
-
const search = isSearchControlled ? searchValueProp : internalSearch;
|
|
2558
|
-
const filterValues = isFiltersControlled ? filterValuesProp : internalFilterValues;
|
|
2559
|
-
const setSearch = (next) => {
|
|
2560
|
-
if (!isSearchControlled) setInternalSearch(next);
|
|
2561
|
-
onSearchChange?.(next);
|
|
2562
|
-
};
|
|
2563
|
-
const setFilter = (key, value) => {
|
|
2564
|
-
if (!isFiltersControlled) {
|
|
2565
|
-
setInternalFilterValues((prev) => ({ ...prev, [key]: value }));
|
|
2551
|
+
const current = filterValues?.[f.key];
|
|
2552
|
+
const def = f.options[0]?.value ?? "";
|
|
2553
|
+
if (current !== void 0 && current !== def) return true;
|
|
2566
2554
|
}
|
|
2567
|
-
|
|
2568
|
-
};
|
|
2555
|
+
return false;
|
|
2556
|
+
}, [searchValue, filters, filterValues]);
|
|
2569
2557
|
const reset = () => {
|
|
2570
|
-
if (!isSearchControlled) setInternalSearch("");
|
|
2571
2558
|
onSearchChange?.("");
|
|
2572
|
-
if (!isFiltersControlled) setInternalFilterValues(initialFilterValues);
|
|
2573
2559
|
for (const f of filters ?? []) {
|
|
2574
|
-
const def = f.
|
|
2560
|
+
const def = f.options[0]?.value ?? "";
|
|
2575
2561
|
onFilterChange?.(f.key, def);
|
|
2576
2562
|
}
|
|
2577
2563
|
};
|
|
2578
|
-
const
|
|
2579
|
-
if (search.trim() !== "") return true;
|
|
2580
|
-
for (const f of filters ?? []) {
|
|
2581
|
-
const current = filterValues[f.key];
|
|
2582
|
-
const def = f.defaultValue ?? f.options[0]?.value ?? "";
|
|
2583
|
-
if (current !== def) return true;
|
|
2584
|
-
}
|
|
2585
|
-
return false;
|
|
2586
|
-
}, [search, filters, filterValues]);
|
|
2587
|
-
const filtered = react.useMemo(() => {
|
|
2588
|
-
return data.filter((row) => {
|
|
2589
|
-
if (!isSearchControlled && search.trim() && searchKeys && searchKeys.length > 0) {
|
|
2590
|
-
const q = search.trim().toLowerCase();
|
|
2591
|
-
const matches = searchKeys.some((key) => {
|
|
2592
|
-
const val = row[key];
|
|
2593
|
-
return val != null && String(val).toLowerCase().includes(q);
|
|
2594
|
-
});
|
|
2595
|
-
if (!matches) return false;
|
|
2596
|
-
}
|
|
2597
|
-
if (!isFiltersControlled) {
|
|
2598
|
-
for (const f of filters ?? []) {
|
|
2599
|
-
const value = filterValues[f.key];
|
|
2600
|
-
const def = f.defaultValue ?? f.options[0]?.value ?? "";
|
|
2601
|
-
if (value !== void 0 && value !== def) {
|
|
2602
|
-
if (f.accessor(row) !== value) return false;
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
return true;
|
|
2607
|
-
});
|
|
2608
|
-
}, [data, search, searchKeys, filters, filterValues, isSearchControlled, isFiltersControlled]);
|
|
2609
|
-
const showFilterBar = Boolean(searchKeys?.length) || Boolean(filters?.length);
|
|
2610
|
-
const tableMode = isLoading ? "loading" : data.length === 0 && !hasActiveFilters ? "no-data" : filtered.length === 0 ? "no-results" : "rows";
|
|
2564
|
+
const tableMode = isLoading ? "loading" : data.length === 0 && !hasActiveQuery ? "no-data" : data.length === 0 && hasActiveQuery ? "no-results" : "rows";
|
|
2611
2565
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "list-page", className: cn("space-y-6", className), children: [
|
|
2612
2566
|
/* @__PURE__ */ jsxRuntime.jsx(PageHeader, { title, description, bordered, actions }),
|
|
2613
2567
|
showFilterBar ? /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "list-page-filter-bar", className: "flex flex-wrap items-center gap-3", children: [
|
|
2614
|
-
|
|
2568
|
+
showSearch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2615
2569
|
Input,
|
|
2616
2570
|
{
|
|
2617
2571
|
type: "search",
|
|
2618
2572
|
placeholder: labels.searchPlaceholder,
|
|
2619
2573
|
"aria-label": labels.searchAriaLabel || labels.searchPlaceholder,
|
|
2620
|
-
value:
|
|
2621
|
-
onChange: (e) =>
|
|
2574
|
+
value: searchValue ?? "",
|
|
2575
|
+
onChange: (e) => onSearchChange?.(e.target.value),
|
|
2622
2576
|
leadingIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, {}),
|
|
2623
2577
|
wrapperClassName: "sm:max-w-xs",
|
|
2624
2578
|
disabled: isLoading
|
|
@@ -2627,16 +2581,16 @@ function ListPage({
|
|
|
2627
2581
|
filters?.map((f) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2628
2582
|
Select,
|
|
2629
2583
|
{
|
|
2630
|
-
"aria-label": f.
|
|
2631
|
-
value: filterValues[f.key],
|
|
2632
|
-
onValueChange: (v) =>
|
|
2584
|
+
"aria-label": typeof f.label === "string" ? f.label : f.key,
|
|
2585
|
+
value: filterValues?.[f.key] ?? f.options[0]?.value ?? "",
|
|
2586
|
+
onValueChange: (v) => onFilterChange?.(f.key, v),
|
|
2633
2587
|
options: f.options,
|
|
2634
2588
|
className: FILTER_WIDTH_CLASS[f.width ?? "default"],
|
|
2635
2589
|
disabled: isLoading
|
|
2636
2590
|
},
|
|
2637
2591
|
f.key
|
|
2638
2592
|
)),
|
|
2639
|
-
|
|
2593
|
+
hasActiveQuery && !isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", onClick: reset, children: [
|
|
2640
2594
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, {}),
|
|
2641
2595
|
labels.reset
|
|
2642
2596
|
] }) : null
|
|
@@ -2645,7 +2599,7 @@ function ListPage({
|
|
|
2645
2599
|
Table,
|
|
2646
2600
|
{
|
|
2647
2601
|
"aria-label": typeof title === "string" ? title : void 0,
|
|
2648
|
-
data
|
|
2602
|
+
data,
|
|
2649
2603
|
columns,
|
|
2650
2604
|
getRowId,
|
|
2651
2605
|
enableRowSelection,
|
|
@@ -2653,10 +2607,10 @@ function ListPage({
|
|
|
2653
2607
|
loading: isLoading,
|
|
2654
2608
|
loadingRowCount,
|
|
2655
2609
|
pagination,
|
|
2656
|
-
defaultPagination,
|
|
2657
2610
|
onPaginationChange,
|
|
2658
2611
|
totalCount,
|
|
2659
|
-
pageSizeOptions
|
|
2612
|
+
pageSizeOptions,
|
|
2613
|
+
labels
|
|
2660
2614
|
}
|
|
2661
2615
|
) : tableMode === "no-data" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2662
2616
|
"div",
|