@dimaan/ui 0.0.18 → 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.js CHANGED
@@ -5,7 +5,7 @@ import { twMerge } from 'tailwind-merge';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { Loader2, Check, Minus, Calendar, X, ChevronLeft, ChevronRight, ChevronDown, ChevronUp, ArrowLeft, Menu, FileQuestion, ChevronsUpDown, Search, RefreshCw, Inbox, SearchX } from 'lucide-react';
7
7
  import { DirectionProvider } from '@radix-ui/react-direction';
8
- import { Link, useLocation, useResolvedPath } from 'react-router-dom';
8
+ import { Link, useLocation, useResolvedPath, useNavigate } from 'react-router-dom';
9
9
  import * as RadixPopover from '@radix-ui/react-popover';
10
10
  import { DayPicker } from 'react-day-picker';
11
11
  import * as RadixDialog from '@radix-ui/react-dialog';
@@ -1696,12 +1696,26 @@ var formPageBodyClass = "flex-1";
1696
1696
  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";
1697
1697
  var formPageSkeletonRowClass = "h-10 w-full animate-pulse rounded-md bg-muted";
1698
1698
  var DEFAULT_SKELETON_ROW_COUNT2 = 6;
1699
+ var DEFAULT_LABELS_LTR = {
1700
+ back: "Back",
1701
+ cancel: "Cancel",
1702
+ save: "Save",
1703
+ saving: "Saving\u2026"
1704
+ };
1705
+ var DEFAULT_LABELS_RTL = {
1706
+ back: "\u0631\u062C\u0648\u0639",
1707
+ cancel: "\u0625\u0644\u063A\u0627\u0621",
1708
+ save: "\u062D\u0641\u0638",
1709
+ saving: "\u062C\u0627\u0631\u064D \u0627\u0644\u062D\u0641\u0638\u2026"
1710
+ };
1699
1711
  function FormPage({
1700
1712
  title,
1701
1713
  description,
1702
- back,
1703
1714
  bordered = true,
1704
1715
  onSubmit,
1716
+ onCancel,
1717
+ isSubmitting,
1718
+ labels: labelsProp,
1705
1719
  isLoading = false,
1706
1720
  loadingRowCount = DEFAULT_SKELETON_ROW_COUNT2,
1707
1721
  actions,
@@ -1711,8 +1725,23 @@ function FormPage({
1711
1725
  bodyClassName,
1712
1726
  actionsClassName
1713
1727
  }) {
1728
+ const navigate = useNavigate();
1729
+ const dir = useDirection();
1730
+ const formContext = useFormContext();
1731
+ const submitting = isSubmitting ?? formContext?.formState?.isSubmitting ?? false;
1732
+ const defaults = dir === "rtl" ? DEFAULT_LABELS_RTL : DEFAULT_LABELS_LTR;
1733
+ const labels = { ...defaults, ...labelsProp };
1734
+ const goBack = () => navigate(-1);
1714
1735
  return /* @__PURE__ */ jsxs("div", { "data-slot": "form-page", className: cn(formPageBaseClass, className), children: [
1715
- /* @__PURE__ */ jsx(PageHeader, { title, description, back, bordered }),
1736
+ /* @__PURE__ */ jsx(
1737
+ PageHeader,
1738
+ {
1739
+ title,
1740
+ description,
1741
+ back: { label: labels.back, onClick: goBack },
1742
+ bordered
1743
+ }
1744
+ ),
1716
1745
  /* @__PURE__ */ jsxs(
1717
1746
  "form",
1718
1747
  {
@@ -1723,14 +1752,27 @@ function FormPage({
1723
1752
  className: cn("flex flex-1 flex-col gap-6", formClassName),
1724
1753
  children: [
1725
1754
  /* @__PURE__ */ jsx("div", { "data-slot": "form-page-body", className: cn(formPageBodyClass, bodyClassName), children: isLoading ? /* @__PURE__ */ jsx(FormPageSkeleton, { rowCount: loadingRowCount }) : children }),
1726
- actions !== null && actions !== void 0 ? /* @__PURE__ */ jsx(
1755
+ /* @__PURE__ */ jsxs(
1727
1756
  "div",
1728
1757
  {
1729
1758
  "data-slot": "form-page-actions",
1730
1759
  className: cn(formPageActionsBarClass, actionsClassName),
1731
- children: actions
1760
+ children: [
1761
+ actions,
1762
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onCancel ?? goBack, children: labels.cancel }),
1763
+ /* @__PURE__ */ jsx(
1764
+ Button,
1765
+ {
1766
+ type: "submit",
1767
+ loading: submitting,
1768
+ loadingText: labels.saving,
1769
+ disabled: isLoading,
1770
+ children: labels.save
1771
+ }
1772
+ )
1773
+ ]
1732
1774
  }
1733
- ) : null
1775
+ )
1734
1776
  ]
1735
1777
  }
1736
1778
  )
@@ -1981,15 +2023,35 @@ var SelectItem = forwardRef(function SelectItem2({ className, children, ...props
1981
2023
  /* @__PURE__ */ jsx(RadixSelect.ItemText, { children })
1982
2024
  ] });
1983
2025
  });
2026
+ var EN_LABELS = {
2027
+ rowsPerPage: "Rows per page",
2028
+ pageRangeOf: "of",
2029
+ previousPage: "Previous page",
2030
+ nextPage: "Next page"
2031
+ };
2032
+ var AR_LABELS = {
2033
+ rowsPerPage: "\u0635\u0641\u0648\u0641 \u0644\u0643\u0644 \u0635\u0641\u062D\u0629",
2034
+ pageRangeOf: "\u0645\u0646",
2035
+ previousPage: "\u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629",
2036
+ nextPage: "\u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629"
2037
+ };
1984
2038
  function Pagination({
1985
2039
  pageIndex,
1986
2040
  pageSize,
1987
2041
  pageCount,
1988
2042
  totalRowCount,
1989
2043
  pageSizeOptions,
1990
- onChange
2044
+ onChange,
2045
+ labels: labelsProp
1991
2046
  }) {
1992
2047
  const dir = useDirection();
2048
+ const localeDefaults = dir === "rtl" ? AR_LABELS : EN_LABELS;
2049
+ const labels = {
2050
+ rowsPerPage: labelsProp?.rowsPerPage ?? localeDefaults.rowsPerPage,
2051
+ pageRangeOf: labelsProp?.pageRangeOf ?? localeDefaults.pageRangeOf,
2052
+ previousPage: labelsProp?.previousPage ?? localeDefaults.previousPage,
2053
+ nextPage: labelsProp?.nextPage ?? localeDefaults.nextPage
2054
+ };
1993
2055
  const isRtl = dir === "rtl";
1994
2056
  const isFirst = pageIndex <= 0;
1995
2057
  const isLast = pageIndex >= pageCount - 1;
@@ -2003,7 +2065,7 @@ function Pagination({
2003
2065
  const end = Math.min(totalRowCount, (pageIndex + 1) * pageSize);
2004
2066
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 text-sm text-muted-foreground", children: [
2005
2067
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
2006
- /* @__PURE__ */ jsx("span", { children: "Rows per page" }),
2068
+ /* @__PURE__ */ jsx("span", { children: labels.rowsPerPage }),
2007
2069
  /* @__PURE__ */ jsx(
2008
2070
  "select",
2009
2071
  {
@@ -2022,7 +2084,9 @@ function Pagination({
2022
2084
  start,
2023
2085
  "\u2013",
2024
2086
  end,
2025
- " of ",
2087
+ " ",
2088
+ labels.pageRangeOf,
2089
+ " ",
2026
2090
  totalRowCount
2027
2091
  ] }),
2028
2092
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
@@ -2034,7 +2098,7 @@ function Pagination({
2034
2098
  size: "sm",
2035
2099
  disabled: isFirst,
2036
2100
  onClick: goPrev,
2037
- "aria-label": "Previous page",
2101
+ "aria-label": labels.previousPage,
2038
2102
  children: isRtl ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
2039
2103
  }
2040
2104
  ),
@@ -2051,7 +2115,7 @@ function Pagination({
2051
2115
  size: "sm",
2052
2116
  disabled: isLast,
2053
2117
  onClick: goNext,
2054
- "aria-label": "Next page",
2118
+ "aria-label": labels.nextPage,
2055
2119
  children: isRtl ? /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
2056
2120
  }
2057
2121
  )
@@ -2104,71 +2168,37 @@ var alignClass = {
2104
2168
  end: "text-end"
2105
2169
  };
2106
2170
  var EMPTY_SELECTION = /* @__PURE__ */ new Set();
2107
- var NO_SORT = { columnId: null, direction: "asc" };
2108
2171
  function useTableState(props) {
2109
2172
  const {
2110
- defaultSort,
2111
- sort: sortProp,
2112
- onSortChange,
2113
- defaultPagination,
2114
- pagination: paginationProp,
2115
- onPaginationChange,
2116
- pageSizeOptions,
2117
2173
  defaultSelectedRowIds,
2118
2174
  selectedRowIds: selectedRowIdsProp,
2119
- onSelectedRowIdsChange,
2120
- totalCount
2175
+ onSelectedRowIdsChange
2121
2176
  } = props;
2122
- const [internalSort, setInternalSort] = useState(defaultSort ?? NO_SORT);
2123
- const isSortControlled = sortProp !== void 0;
2124
- const sort = isSortControlled ? sortProp : internalSort;
2125
- const setSort = useCallback(
2126
- (next) => {
2127
- if (!isSortControlled) setInternalSort(next);
2128
- onSortChange?.(next);
2129
- },
2130
- [isSortControlled, onSortChange]
2131
- );
2132
- const [internalPagination, setInternalPagination] = useState(
2133
- defaultPagination ?? { pageIndex: 0, pageSize: pageSizeOptions?.[0] ?? 10 }
2134
- );
2135
- const isPaginationControlled = paginationProp !== void 0;
2136
- const pagination = isPaginationControlled ? paginationProp : internalPagination;
2137
- const setPagination = useCallback(
2138
- (next) => {
2139
- if (!isPaginationControlled) setInternalPagination(next);
2140
- onPaginationChange?.(next);
2141
- },
2142
- [isPaginationControlled, onPaginationChange]
2143
- );
2144
2177
  const [internalSelected, setInternalSelected] = useState(
2145
2178
  defaultSelectedRowIds ?? EMPTY_SELECTION
2146
2179
  );
2147
- const isSelectionControlled = selectedRowIdsProp !== void 0;
2148
- const selected = isSelectionControlled ? selectedRowIdsProp : internalSelected;
2180
+ const isControlled = selectedRowIdsProp !== void 0;
2181
+ const selected = isControlled ? selectedRowIdsProp : internalSelected;
2149
2182
  const setSelected = useCallback(
2150
2183
  (next) => {
2151
- if (!isSelectionControlled) setInternalSelected(next);
2184
+ if (!isControlled) setInternalSelected(next);
2152
2185
  onSelectedRowIdsChange?.(next);
2153
2186
  },
2154
- [isSelectionControlled, onSelectedRowIdsChange]
2187
+ [isControlled, onSelectedRowIdsChange]
2155
2188
  );
2156
- return {
2157
- sort,
2158
- setSort,
2159
- pagination,
2160
- setPagination,
2161
- selected,
2162
- setSelected,
2163
- isServerSide: totalCount !== void 0
2164
- };
2189
+ return { selected, setSelected };
2165
2190
  }
2166
2191
  var DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50];
2192
+ var DEFAULT_PAGE_SIZE = 10;
2193
+ function defaultGetRowId(row, index) {
2194
+ const rowId = row.id;
2195
+ return rowId === void 0 || rowId === null ? String(index) : String(rowId);
2196
+ }
2167
2197
  function Table(props) {
2168
2198
  const {
2169
2199
  data,
2170
2200
  columns,
2171
- getRowId,
2201
+ getRowId = defaultGetRowId,
2172
2202
  enableRowSelection = false,
2173
2203
  isRowSelectable,
2174
2204
  bulkActions,
@@ -2186,36 +2216,26 @@ function Table(props) {
2186
2216
  tableRef,
2187
2217
  pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
2188
2218
  showPagination,
2189
- caption
2219
+ caption,
2220
+ sort,
2221
+ onSortChange,
2222
+ pagination,
2223
+ onPaginationChange,
2224
+ totalCount,
2225
+ labels
2190
2226
  } = props;
2191
2227
  const ariaLabel = props["aria-label"];
2192
2228
  const ariaLabelledBy = props["aria-labelledby"];
2193
- const { sort, setSort, pagination, setPagination, selected, setSelected, isServerSide } = useTableState(props);
2194
- const sortedRows = useMemo(() => {
2195
- if (isServerSide || sort.columnId === null) return data;
2196
- const col = columns.find((c) => c.id === sort.columnId);
2197
- if (!col) return data;
2198
- const get = resolveSortGetter(col);
2199
- if (!get) return data;
2200
- const tagged = data.map((row, index) => ({ row, index }));
2201
- tagged.sort((a, b) => {
2202
- const cmp = compareValues(get(a.row), get(b.row));
2203
- if (cmp !== 0) return sort.direction === "asc" ? cmp : -cmp;
2204
- return a.index - b.index;
2205
- });
2206
- return tagged.map((entry) => entry.row);
2207
- }, [data, columns, sort, isServerSide]);
2208
- const pagedRows = useMemo(() => {
2209
- if (isServerSide) return sortedRows;
2210
- const start = pagination.pageIndex * pagination.pageSize;
2211
- return sortedRows.slice(start, start + pagination.pageSize);
2212
- }, [sortedRows, pagination, isServerSide]);
2213
- const totalRowCount = isServerSide ? props.totalCount ?? 0 : data.length;
2214
- const pageCount = Math.max(1, Math.ceil(totalRowCount / pagination.pageSize));
2229
+ const { selected, setSelected } = useTableState(props);
2230
+ const effectiveSort = sort ?? { columnId: null, direction: "asc" };
2231
+ const pageSize = pagination?.pageSize ?? pageSizeOptions[0] ?? DEFAULT_PAGE_SIZE;
2232
+ const pageIndex = pagination?.pageIndex ?? 0;
2233
+ const totalRowCount = totalCount ?? data.length;
2234
+ const pageCount = Math.max(1, Math.ceil(totalRowCount / pageSize));
2215
2235
  const selectableRowIds = useMemo(() => {
2216
2236
  if (!enableRowSelection) return [];
2217
- return pagedRows.map((row, index) => ({ row, index })).filter(({ row }) => isRowSelectable ? isRowSelectable(row) : true).map(({ row, index }) => getRowId(row, index));
2218
- }, [pagedRows, enableRowSelection, isRowSelectable, getRowId]);
2237
+ return data.map((row, index) => ({ row, index })).filter(({ row }) => isRowSelectable ? isRowSelectable(row) : true).map(({ row, index }) => getRowId(row, index));
2238
+ }, [data, enableRowSelection, isRowSelectable, getRowId]);
2219
2239
  const selectedOnPageCount = selectableRowIds.reduce(
2220
2240
  (acc, id) => selected.has(id) ? acc + 1 : acc,
2221
2241
  0
@@ -2243,13 +2263,16 @@ function Table(props) {
2243
2263
  };
2244
2264
  const clearSelection = () => setSelected(/* @__PURE__ */ new Set());
2245
2265
  const handleSortClick = (columnId) => {
2246
- setSort(nextSort(sort, columnId));
2266
+ if (!onSortChange) return;
2267
+ onSortChange(nextSort(effectiveSort, columnId));
2247
2268
  };
2269
+ const handlePaginationChange = onPaginationChange ?? (() => {
2270
+ });
2248
2271
  const totalColumnCount = columns.length + (enableRowSelection ? 1 : 0);
2249
- const paginationVisible = showPagination ?? totalRowCount > pagination.pageSize;
2272
+ const paginationVisible = Boolean(pagination) && (showPagination ?? totalRowCount > pageSize);
2250
2273
  const sizeClasses = tableSizeClass[size];
2251
2274
  const showToolbar = enableRowSelection && bulkActions !== void 0 && selected.size > 0;
2252
- const skeletonCount = loadingRowCount ?? pagination.pageSize;
2275
+ const skeletonCount = loadingRowCount ?? pageSize;
2253
2276
  return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full flex-col gap-3", className), children: [
2254
2277
  showToolbar && /* @__PURE__ */ jsx(
2255
2278
  Toolbar,
@@ -2298,8 +2321,8 @@ function Table(props) {
2298
2321
  }
2299
2322
  ) }) : null,
2300
2323
  columns.map((column) => {
2301
- const isSorted = sort.columnId === column.id;
2302
- const ariaSort = isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none";
2324
+ const isSorted = effectiveSort.columnId === column.id;
2325
+ const ariaSort = isSorted ? effectiveSort.direction === "asc" ? "ascending" : "descending" : "none";
2303
2326
  return /* @__PURE__ */ jsx(
2304
2327
  "th",
2305
2328
  {
@@ -2316,14 +2339,14 @@ function Table(props) {
2316
2339
  type: "button",
2317
2340
  onClick: () => handleSortClick(column.id),
2318
2341
  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",
2319
- "aria-label": sortAriaLabel(column, sort),
2342
+ "aria-label": sortAriaLabel(column, effectiveSort),
2320
2343
  children: [
2321
2344
  /* @__PURE__ */ jsx("span", { children: renderHeader(column.header) }),
2322
2345
  /* @__PURE__ */ jsx(
2323
2346
  SortIndicator,
2324
2347
  {
2325
2348
  active: isSorted,
2326
- direction: isSorted ? sort.direction : null
2349
+ direction: isSorted ? effectiveSort.direction : null
2327
2350
  }
2328
2351
  )
2329
2352
  ]
@@ -2343,14 +2366,14 @@ function Table(props) {
2343
2366
  columnCount: totalColumnCount,
2344
2367
  cellClassName: sizeClasses.cell
2345
2368
  }
2346
- ) : pagedRows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
2369
+ ) : data.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
2347
2370
  "td",
2348
2371
  {
2349
2372
  colSpan: totalColumnCount,
2350
2373
  className: cn(sizeClasses.cell, "py-10 text-center text-muted-foreground"),
2351
2374
  children: emptyState ?? "No data"
2352
2375
  }
2353
- ) }) : pagedRows.map((row, rowIndex) => {
2376
+ ) }) : data.map((row, rowIndex) => {
2354
2377
  const id = getRowId(row, rowIndex);
2355
2378
  const isSelected = selected.has(id);
2356
2379
  const rowSelectable = isRowSelectable ? isRowSelectable(row) : true;
@@ -2403,12 +2426,13 @@ function Table(props) {
2403
2426
  paginationVisible ? /* @__PURE__ */ jsx(
2404
2427
  Pagination,
2405
2428
  {
2406
- pageIndex: pagination.pageIndex,
2407
- pageSize: pagination.pageSize,
2429
+ pageIndex,
2430
+ pageSize,
2408
2431
  pageCount,
2409
2432
  totalRowCount,
2410
2433
  pageSizeOptions,
2411
- onChange: setPagination
2434
+ onChange: handlePaginationChange,
2435
+ labels
2412
2436
  }
2413
2437
  ) : null
2414
2438
  ] });
@@ -2424,24 +2448,6 @@ function renderCell(column, row, rowIndex) {
2424
2448
  }
2425
2449
  return null;
2426
2450
  }
2427
- function resolveSortGetter(column) {
2428
- if (column.sortAccessor) return column.sortAccessor;
2429
- if (column.accessor !== void 0) {
2430
- const key = column.accessor;
2431
- return (row) => row[key];
2432
- }
2433
- return null;
2434
- }
2435
- function compareValues(a, b) {
2436
- if (a === b) return 0;
2437
- if (a === null || a === void 0) return 1;
2438
- if (b === null || b === void 0) return -1;
2439
- if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
2440
- if (typeof a === "number" && typeof b === "number") return a - b;
2441
- if (typeof a === "bigint" && typeof b === "bigint") return a < b ? -1 : 1;
2442
- if (typeof a === "boolean" && typeof b === "boolean") return a === b ? 0 : a ? 1 : -1;
2443
- return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
2444
- }
2445
2451
  function nextSort(current, columnId) {
2446
2452
  if (current.columnId !== columnId) return { columnId, direction: "asc" };
2447
2453
  if (current.direction === "asc") return { columnId, direction: "desc" };
@@ -2492,12 +2498,14 @@ function ListPage({
2492
2498
  getRowId,
2493
2499
  isLoading = false,
2494
2500
  loadingRowCount,
2495
- searchKeys,
2501
+ searchValue,
2502
+ onSearchChange,
2496
2503
  filters,
2504
+ filterValues,
2505
+ onFilterChange,
2497
2506
  enableRowSelection,
2498
2507
  bulkActions,
2499
2508
  pagination,
2500
- defaultPagination,
2501
2509
  onPaginationChange,
2502
2510
  totalCount,
2503
2511
  pageSizeOptions,
@@ -2507,64 +2515,36 @@ function ListPage({
2507
2515
  className
2508
2516
  }) {
2509
2517
  const labels = { ...DEFAULT_LABELS2, ...labelsProp };
2510
- const initialFilterValues = useMemo(() => {
2511
- const init = {};
2518
+ const showSearch = onSearchChange !== void 0;
2519
+ const showFilterBar = showSearch || Boolean(filters?.length);
2520
+ const hasActiveQuery = useMemo(() => {
2521
+ if ((searchValue ?? "").trim() !== "") return true;
2512
2522
  for (const f of filters ?? []) {
2513
- init[f.key] = f.defaultValue ?? f.options[0]?.value ?? "";
2523
+ const current = filterValues?.[f.key];
2524
+ const def = f.options[0]?.value ?? "";
2525
+ if (current !== void 0 && current !== def) return true;
2514
2526
  }
2515
- return init;
2516
- }, [filters]);
2517
- const [search, setSearch] = useState("");
2518
- const [filterValues, setFilterValues] = useState(initialFilterValues);
2519
- const setFilter = (key, value) => {
2520
- setFilterValues((prev) => ({ ...prev, [key]: value }));
2521
- };
2527
+ return false;
2528
+ }, [searchValue, filters, filterValues]);
2522
2529
  const reset = () => {
2523
- setSearch("");
2524
- setFilterValues(initialFilterValues);
2525
- };
2526
- const hasActiveFilters = useMemo(() => {
2527
- if (search.trim() !== "") return true;
2530
+ onSearchChange?.("");
2528
2531
  for (const f of filters ?? []) {
2529
- const current = filterValues[f.key];
2530
- const def = f.defaultValue ?? f.options[0]?.value ?? "";
2531
- if (current !== def) return true;
2532
+ const def = f.options[0]?.value ?? "";
2533
+ onFilterChange?.(f.key, def);
2532
2534
  }
2533
- return false;
2534
- }, [search, filters, filterValues]);
2535
- const filtered = useMemo(() => {
2536
- return data.filter((row) => {
2537
- if (search.trim() && searchKeys && searchKeys.length > 0) {
2538
- const q = search.trim().toLowerCase();
2539
- const matches = searchKeys.some((key) => {
2540
- const val = row[key];
2541
- return val != null && String(val).toLowerCase().includes(q);
2542
- });
2543
- if (!matches) return false;
2544
- }
2545
- for (const f of filters ?? []) {
2546
- const value = filterValues[f.key];
2547
- const def = f.defaultValue ?? f.options[0]?.value ?? "";
2548
- if (value !== void 0 && value !== def) {
2549
- if (f.accessor(row) !== value) return false;
2550
- }
2551
- }
2552
- return true;
2553
- });
2554
- }, [data, search, searchKeys, filters, filterValues]);
2555
- const showFilterBar = Boolean(searchKeys?.length) || Boolean(filters?.length);
2556
- const tableMode = isLoading ? "loading" : data.length === 0 && !hasActiveFilters ? "no-data" : filtered.length === 0 ? "no-results" : "rows";
2535
+ };
2536
+ const tableMode = isLoading ? "loading" : data.length === 0 && !hasActiveQuery ? "no-data" : data.length === 0 && hasActiveQuery ? "no-results" : "rows";
2557
2537
  return /* @__PURE__ */ jsxs("div", { "data-slot": "list-page", className: cn("space-y-6", className), children: [
2558
2538
  /* @__PURE__ */ jsx(PageHeader, { title, description, bordered, actions }),
2559
2539
  showFilterBar ? /* @__PURE__ */ jsxs("div", { "data-slot": "list-page-filter-bar", className: "flex flex-wrap items-center gap-3", children: [
2560
- searchKeys?.length ? /* @__PURE__ */ jsx(
2540
+ showSearch ? /* @__PURE__ */ jsx(
2561
2541
  Input,
2562
2542
  {
2563
2543
  type: "search",
2564
2544
  placeholder: labels.searchPlaceholder,
2565
2545
  "aria-label": labels.searchAriaLabel || labels.searchPlaceholder,
2566
- value: search,
2567
- onChange: (e) => setSearch(e.target.value),
2546
+ value: searchValue ?? "",
2547
+ onChange: (e) => onSearchChange?.(e.target.value),
2568
2548
  leadingIcon: /* @__PURE__ */ jsx(Search, {}),
2569
2549
  wrapperClassName: "sm:max-w-xs",
2570
2550
  disabled: isLoading
@@ -2573,16 +2553,16 @@ function ListPage({
2573
2553
  filters?.map((f) => /* @__PURE__ */ jsx(
2574
2554
  Select,
2575
2555
  {
2576
- "aria-label": f.ariaLabel,
2577
- value: filterValues[f.key],
2578
- onValueChange: (v) => setFilter(f.key, v),
2556
+ "aria-label": typeof f.label === "string" ? f.label : f.key,
2557
+ value: filterValues?.[f.key] ?? f.options[0]?.value ?? "",
2558
+ onValueChange: (v) => onFilterChange?.(f.key, v),
2579
2559
  options: f.options,
2580
2560
  className: FILTER_WIDTH_CLASS[f.width ?? "default"],
2581
2561
  disabled: isLoading
2582
2562
  },
2583
2563
  f.key
2584
2564
  )),
2585
- hasActiveFilters && !isLoading ? /* @__PURE__ */ jsxs(Button, { variant: "ghost", onClick: reset, children: [
2565
+ hasActiveQuery && !isLoading ? /* @__PURE__ */ jsxs(Button, { variant: "ghost", onClick: reset, children: [
2586
2566
  /* @__PURE__ */ jsx(RefreshCw, {}),
2587
2567
  labels.reset
2588
2568
  ] }) : null
@@ -2591,7 +2571,7 @@ function ListPage({
2591
2571
  Table,
2592
2572
  {
2593
2573
  "aria-label": typeof title === "string" ? title : void 0,
2594
- data: filtered,
2574
+ data,
2595
2575
  columns,
2596
2576
  getRowId,
2597
2577
  enableRowSelection,
@@ -2599,10 +2579,10 @@ function ListPage({
2599
2579
  loading: isLoading,
2600
2580
  loadingRowCount,
2601
2581
  pagination,
2602
- defaultPagination,
2603
2582
  onPaginationChange,
2604
2583
  totalCount,
2605
- pageSizeOptions
2584
+ pageSizeOptions,
2585
+ labels
2606
2586
  }
2607
2587
  ) : tableMode === "no-data" ? /* @__PURE__ */ jsx(
2608
2588
  "div",