@marktiderman/genesis-ui 2.0.0 → 2.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/LICENSE +21 -0
- package/dist/{AppShell-BJarYZzz.d.ts → AppShell-sQT0UbXg.d.ts} +4 -4
- package/dist/{chunk-Q4I4SFBD.js → chunk-GDFNAHI4.js} +9 -5
- package/dist/chunk-GDFNAHI4.js.map +1 -0
- package/dist/components/data/index.d.ts +230 -27
- package/dist/components/data/index.js +253 -27
- package/dist/components/data/index.js.map +1 -1
- package/dist/components/layout/index.d.ts +2 -3
- package/dist/components/layout/index.js +4 -4
- package/dist/components/patterns/empty-state.d.ts +4 -5
- package/dist/components/patterns/form-field.d.ts +3 -4
- package/dist/components/patterns/index.d.ts +2 -3
- package/dist/components/patterns/index.js +3 -3
- package/dist/components/patterns/page-loading.d.ts +2 -2
- package/dist/components/patterns/settings-row.d.ts +1 -2
- package/dist/components/patterns/status-badge.d.ts +1 -2
- package/dist/components/patterns/toggle-row.d.ts +1 -2
- package/dist/components/patterns/user-avatar.d.ts +2 -2
- package/dist/components/ui/accessible-icon.d.ts +1 -2
- package/dist/components/ui/alert-dialog.d.ts +2 -3
- package/dist/components/ui/badge.d.ts +1 -2
- package/dist/components/ui/breadcrumb.d.ts +2 -3
- package/dist/components/ui/button-group.d.ts +1 -2
- package/dist/components/ui/calendar.d.ts +2 -3
- package/dist/components/ui/card.d.ts +6 -7
- package/dist/components/ui/carousel.d.ts +2 -3
- package/dist/components/ui/chart.d.ts +4 -5
- package/dist/components/ui/command-palette.d.ts +1 -2
- package/dist/components/ui/command.d.ts +2 -3
- package/dist/components/ui/context-menu.d.ts +1 -2
- package/dist/components/ui/date-picker.d.ts +2 -2
- package/dist/components/ui/dialog.d.ts +2 -3
- package/dist/components/ui/drawer.d.ts +3 -4
- package/dist/components/ui/dropdown-menu.d.ts +1 -2
- package/dist/components/ui/kbd.d.ts +1 -2
- package/dist/components/ui/menubar.d.ts +1 -2
- package/dist/components/ui/pagination.d.ts +5 -6
- package/dist/components/ui/password-toggle-field.d.ts +2 -3
- package/dist/components/ui/progress.d.ts +1 -2
- package/dist/components/ui/resizable.d.ts +2 -3
- package/dist/components/ui/separator.d.ts +1 -2
- package/dist/components/ui/sheet.d.ts +2 -3
- package/dist/components/ui/skeleton.d.ts +1 -2
- package/dist/components/ui/sonner.d.ts +1 -2
- package/dist/components/ui/spinner.d.ts +1 -2
- package/dist/components/ui/tooltip.d.ts +1 -2
- package/dist/components/ui/typography.d.ts +9 -10
- package/dist/hooks/index.d.ts +2 -3
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/use-resource-page.d.ts +2 -3
- package/dist/hooks/use-resource-page.js +1 -1
- package/dist/hooks/use-view-preference.d.ts +2 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +11 -11
- package/dist/{use-resource-page-CPs6wjKt.d.ts → use-resource-page-DTQS011Q.d.ts} +18 -6
- package/dist/{view-settings--KXNT_jE.d.ts → view-settings-kHKCHMjj.d.ts} +2 -2
- package/dist/{view-toggle-DDe_Luj2.d.ts → view-toggle-CahQ87PW.d.ts} +2 -2
- package/package.json +15 -15
- package/dist/chunk-Q4I4SFBD.js.map +0 -1
|
@@ -15,18 +15,18 @@ import '../../chunk-B2GIBUQD.js';
|
|
|
15
15
|
import { Badge } from '../../chunk-NPNADZHM.js';
|
|
16
16
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../../chunk-FK42ZGGV.js';
|
|
17
17
|
import { Popover, PopoverTrigger, PopoverContent } from '../../chunk-22XB3Q6H.js';
|
|
18
|
+
import { PageLoading } from '../../chunk-YRYQXU3G.js';
|
|
19
|
+
import { Spinner } from '../../chunk-OVU3Z2MT.js';
|
|
18
20
|
import { Switch } from '../../chunk-27ELYTGE.js';
|
|
21
|
+
import { DetailPage } from '../../chunk-AFZ76Q26.js';
|
|
22
|
+
import '../../chunk-D2LIXA2Y.js';
|
|
23
|
+
import '../../chunk-AVFZ4P4B.js';
|
|
19
24
|
import { EmptyState } from '../../chunk-65SPT7EA.js';
|
|
20
25
|
export { EmptyState } from '../../chunk-65SPT7EA.js';
|
|
21
26
|
import { Button } from '../../chunk-NWSCYLPT.js';
|
|
22
|
-
import { PageLoading } from '../../chunk-YRYQXU3G.js';
|
|
23
|
-
import { Spinner } from '../../chunk-OVU3Z2MT.js';
|
|
24
27
|
import { FormField, FormLabel, FormError, FormDescription } from '../../chunk-R7QFP6EL.js';
|
|
25
28
|
import '../../chunk-F47U5KNW.js';
|
|
26
|
-
import {
|
|
27
|
-
import '../../chunk-D2LIXA2Y.js';
|
|
28
|
-
import '../../chunk-AVFZ4P4B.js';
|
|
29
|
-
import { titleCase, useResourcePage } from '../../chunk-Q4I4SFBD.js';
|
|
29
|
+
import { titleCase, useResourcePage } from '../../chunk-GDFNAHI4.js';
|
|
30
30
|
export { useSavedViews } from '../../chunk-GCQFVMPI.js';
|
|
31
31
|
import '../../chunk-FTTNGGLA.js';
|
|
32
32
|
import { useViewSettings } from '../../chunk-OZ7ZAYCS.js';
|
|
@@ -40,7 +40,7 @@ import { useKeyboardNavigation } from '../../chunk-YJ6MPS6U.js';
|
|
|
40
40
|
import { useIsMobile } from '../../chunk-M7AU5DDM.js';
|
|
41
41
|
import { AlertTriangle, RefreshCw, ChevronDown, Check, Search, X, ArrowUpDown, Bookmark, Trash2, BookmarkPlus, Loader2, Columns3, ArrowUp, ArrowDown, ChevronLeft, ChevronRight, ExternalLink, Pencil, ChevronsUpDown, ImageIcon, Upload, AlertCircle, FileIcon, Plus } from 'lucide-react';
|
|
42
42
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
43
|
-
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
43
|
+
import { useState, useRef, useEffect, useCallback, useMemo, Fragment as Fragment$1 } from 'react';
|
|
44
44
|
import { formatDistanceToNow, format } from 'date-fns';
|
|
45
45
|
import { useFieldArray, Controller, useWatch } from 'react-hook-form';
|
|
46
46
|
import { useResource, useWizard, useResourceForm, useOne, buildArrayItemDefaults } from '@marktiderman/genesis-core/hooks';
|
|
@@ -1146,6 +1146,7 @@ function DataBulkBar({
|
|
|
1146
1146
|
size: "sm",
|
|
1147
1147
|
variant: action.variant || "outline",
|
|
1148
1148
|
onClick: action.onClick,
|
|
1149
|
+
disabled: action.disabled,
|
|
1149
1150
|
children: [
|
|
1150
1151
|
/* @__PURE__ */ jsx(ActionIcon, { className: "h-3.5 w-3.5 mr-1" }),
|
|
1151
1152
|
action.label
|
|
@@ -2424,6 +2425,29 @@ function ResourcePage(props) {
|
|
|
2424
2425
|
searchPlaceholder,
|
|
2425
2426
|
initialFilters,
|
|
2426
2427
|
onFiltersChange,
|
|
2428
|
+
filters: filtersProp,
|
|
2429
|
+
page: pageProp,
|
|
2430
|
+
perPage: perPageProp,
|
|
2431
|
+
onPageChange,
|
|
2432
|
+
onPerPageChange,
|
|
2433
|
+
onSortChange,
|
|
2434
|
+
onSearchChange,
|
|
2435
|
+
loading: loadingProp,
|
|
2436
|
+
error: errorProp,
|
|
2437
|
+
errorMessage,
|
|
2438
|
+
onRetry: onRetryProp,
|
|
2439
|
+
savedViews,
|
|
2440
|
+
onLoadView,
|
|
2441
|
+
onSaveView,
|
|
2442
|
+
onDeleteView,
|
|
2443
|
+
canSaveViews,
|
|
2444
|
+
columnVisibility,
|
|
2445
|
+
columnVisibilityKey,
|
|
2446
|
+
resizableColumns,
|
|
2447
|
+
resizeKey,
|
|
2448
|
+
stickyHeader,
|
|
2449
|
+
stickyFirstColumn,
|
|
2450
|
+
pageSizeOptions,
|
|
2427
2451
|
onCreate,
|
|
2428
2452
|
onEdit,
|
|
2429
2453
|
onDelete,
|
|
@@ -2437,6 +2461,7 @@ function ResourcePage(props) {
|
|
|
2437
2461
|
formLayout: formLayoutProp,
|
|
2438
2462
|
bulkActions,
|
|
2439
2463
|
renderCard: renderCardProp,
|
|
2464
|
+
renderTable: renderTableProp,
|
|
2440
2465
|
gridCols: gridColsProp,
|
|
2441
2466
|
keyboardNavigation = true,
|
|
2442
2467
|
toolbar,
|
|
@@ -2447,16 +2472,18 @@ function ResourcePage(props) {
|
|
|
2447
2472
|
viewSettingsKey: viewSettingsKeyProp
|
|
2448
2473
|
} = props;
|
|
2449
2474
|
const isClientMode = !!resourceName;
|
|
2475
|
+
const isServerControlled = pageProp !== void 0 || perPageProp !== void 0 || onPageChange !== void 0 || onPerPageChange !== void 0 || onSortChange !== void 0 || onSearchChange !== void 0;
|
|
2450
2476
|
const viewSettingsKey = viewSettingsKeyProp ?? resourceName ?? title.toLowerCase().replace(/\s+/g, "-");
|
|
2451
2477
|
const { settings, updateSetting } = useViewSettings(viewSettingsKey);
|
|
2478
|
+
const effectivePageSize = perPageProp ?? settings.pageSize;
|
|
2452
2479
|
const resourceHook = useResource(
|
|
2453
2480
|
resourceName ?? "__noop__",
|
|
2454
2481
|
isClientMode ? resourceOptions : { enabled: false }
|
|
2455
2482
|
);
|
|
2456
2483
|
const displayData = isClientMode ? resourceHook.list.data?.data ?? [] : dataProp ?? [];
|
|
2457
2484
|
const displayTotal = isClientMode ? resourceHook.list.data?.total ?? 0 : totalProp ?? 0;
|
|
2458
|
-
const isLoading = isClientMode ? resourceHook.list.isLoading : false;
|
|
2459
|
-
const hasError = isClientMode ? resourceHook.list.isError : false;
|
|
2485
|
+
const isLoading = isClientMode ? resourceHook.list.isLoading : loadingProp ?? false;
|
|
2486
|
+
const hasError = isClientMode ? resourceHook.list.isError : errorProp ?? false;
|
|
2460
2487
|
const page = useResourcePage({
|
|
2461
2488
|
resource: resourceName,
|
|
2462
2489
|
data: displayData,
|
|
@@ -2469,7 +2496,8 @@ function ResourcePage(props) {
|
|
|
2469
2496
|
defaultView,
|
|
2470
2497
|
detail,
|
|
2471
2498
|
titleField: titleFieldProp,
|
|
2472
|
-
subtitleField: subtitleFieldProp
|
|
2499
|
+
subtitleField: subtitleFieldProp,
|
|
2500
|
+
controlled: isServerControlled
|
|
2473
2501
|
});
|
|
2474
2502
|
const actions = useMemo(() => {
|
|
2475
2503
|
if (isClientMode) {
|
|
@@ -2481,15 +2509,24 @@ function ResourcePage(props) {
|
|
|
2481
2509
|
}
|
|
2482
2510
|
return {
|
|
2483
2511
|
update: async () => {
|
|
2484
|
-
throw new Error(
|
|
2512
|
+
throw new Error(
|
|
2513
|
+
"ResourceActions.update not available in server-data mode"
|
|
2514
|
+
);
|
|
2485
2515
|
},
|
|
2486
2516
|
remove: async () => {
|
|
2487
|
-
throw new Error(
|
|
2517
|
+
throw new Error(
|
|
2518
|
+
"ResourceActions.remove not available in server-data mode"
|
|
2519
|
+
);
|
|
2488
2520
|
},
|
|
2489
2521
|
refetch: () => {
|
|
2490
2522
|
}
|
|
2491
2523
|
};
|
|
2492
|
-
}, [
|
|
2524
|
+
}, [
|
|
2525
|
+
isClientMode,
|
|
2526
|
+
resourceHook.update,
|
|
2527
|
+
resourceHook.remove,
|
|
2528
|
+
resourceHook.list
|
|
2529
|
+
]);
|
|
2493
2530
|
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
2494
2531
|
const handleToggleSelect = useCallback((id) => {
|
|
2495
2532
|
setSelectedIds((prev) => {
|
|
@@ -2539,15 +2576,101 @@ function ResourcePage(props) {
|
|
|
2539
2576
|
[useBuiltInEdit, onEdit]
|
|
2540
2577
|
);
|
|
2541
2578
|
const tableColumns = useMemo(() => {
|
|
2542
|
-
|
|
2543
|
-
return page.columns.map((col) => ({
|
|
2579
|
+
const base = isClientMode ? page.columns.map((col) => ({
|
|
2544
2580
|
key: col.key,
|
|
2545
2581
|
header: col.header ?? col.key,
|
|
2546
2582
|
sortable: col.sortable ?? true,
|
|
2547
2583
|
hideBelow: col.hideBelow,
|
|
2548
2584
|
render: col.render ? (item, value) => col.render(item, value, actions) : void 0
|
|
2549
|
-
}));
|
|
2550
|
-
|
|
2585
|
+
})) : page.tableColumns;
|
|
2586
|
+
if (!isServerControlled) return base;
|
|
2587
|
+
return base.map((col) => ({ ...col, sortable: false }));
|
|
2588
|
+
}, [
|
|
2589
|
+
isClientMode,
|
|
2590
|
+
isServerControlled,
|
|
2591
|
+
page.columns,
|
|
2592
|
+
page.tableColumns,
|
|
2593
|
+
actions
|
|
2594
|
+
]);
|
|
2595
|
+
const currentPage = pageProp ?? 1;
|
|
2596
|
+
const handleSearchChange = useCallback(
|
|
2597
|
+
(value) => {
|
|
2598
|
+
page.filterConfig.onSearchChange(value);
|
|
2599
|
+
if (!isServerControlled) return;
|
|
2600
|
+
onSearchChange?.(value);
|
|
2601
|
+
if (currentPage !== 1) onPageChange?.(1);
|
|
2602
|
+
},
|
|
2603
|
+
[
|
|
2604
|
+
page.filterConfig,
|
|
2605
|
+
isServerControlled,
|
|
2606
|
+
onSearchChange,
|
|
2607
|
+
onPageChange,
|
|
2608
|
+
currentPage
|
|
2609
|
+
]
|
|
2610
|
+
);
|
|
2611
|
+
const handleSortSelect = useCallback(
|
|
2612
|
+
(value) => {
|
|
2613
|
+
page.filterConfig.onSortChange(value);
|
|
2614
|
+
if (!isServerControlled) return;
|
|
2615
|
+
const [field, order] = value.split(":");
|
|
2616
|
+
onSortChange?.(
|
|
2617
|
+
field && (order === "asc" || order === "desc") ? { field, order } : null
|
|
2618
|
+
);
|
|
2619
|
+
onPageChange?.(1);
|
|
2620
|
+
},
|
|
2621
|
+
[page.filterConfig, isServerControlled, onSortChange, onPageChange]
|
|
2622
|
+
);
|
|
2623
|
+
const handleClearFilters = useCallback(() => {
|
|
2624
|
+
page.clearFilters();
|
|
2625
|
+
if (!isServerControlled) return;
|
|
2626
|
+
onSearchChange?.("");
|
|
2627
|
+
onSortChange?.(null);
|
|
2628
|
+
onPageChange?.(1);
|
|
2629
|
+
}, [page, isServerControlled, onSearchChange, onSortChange, onPageChange]);
|
|
2630
|
+
const handleStatusChange = useCallback(
|
|
2631
|
+
(values) => {
|
|
2632
|
+
page.filterConfig.statusChips?.onChange(values);
|
|
2633
|
+
if (!isServerControlled) return;
|
|
2634
|
+
if (currentPage !== 1) onPageChange?.(1);
|
|
2635
|
+
},
|
|
2636
|
+
[page.filterConfig, isServerControlled, onPageChange, currentPage]
|
|
2637
|
+
);
|
|
2638
|
+
const statusChipsConfig = useMemo(() => {
|
|
2639
|
+
const base = page.filterConfig.statusChips;
|
|
2640
|
+
if (!base) return void 0;
|
|
2641
|
+
return { ...base, onChange: handleStatusChange };
|
|
2642
|
+
}, [page.filterConfig.statusChips, handleStatusChange]);
|
|
2643
|
+
const handlePageSizeChange = useCallback(
|
|
2644
|
+
(size) => {
|
|
2645
|
+
updateSetting("pageSize", size);
|
|
2646
|
+
onPerPageChange?.(size);
|
|
2647
|
+
if (isServerControlled) onPageChange?.(1);
|
|
2648
|
+
},
|
|
2649
|
+
[updateSetting, onPerPageChange, isServerControlled, onPageChange]
|
|
2650
|
+
);
|
|
2651
|
+
const missingPerPage = isServerControlled && !!onPageChange && perPageProp === void 0;
|
|
2652
|
+
const missingTotal = isServerControlled && !!onPageChange && totalProp === void 0;
|
|
2653
|
+
const pagerMisconfigured = missingPerPage || missingTotal;
|
|
2654
|
+
const missingPagerProps = [
|
|
2655
|
+
...missingPerPage ? ["perPage"] : [],
|
|
2656
|
+
...missingTotal ? ["total"] : []
|
|
2657
|
+
];
|
|
2658
|
+
const loggedMissingPerPageRef = useRef(false);
|
|
2659
|
+
useEffect(() => {
|
|
2660
|
+
if (!pagerMisconfigured) return;
|
|
2661
|
+
if (loggedMissingPerPageRef.current) return;
|
|
2662
|
+
loggedMissingPerPageRef.current = true;
|
|
2663
|
+
console.error(
|
|
2664
|
+
`ResourcePage: ${missingPagerProps.map((name) => `\`${name}\``).join(" and ")} ${missingPagerProps.length > 1 ? "are" : "is"} required when \`onPageChange\` is supplied.`
|
|
2665
|
+
);
|
|
2666
|
+
}, [pagerMisconfigured]);
|
|
2667
|
+
const pagerPageSize = perPageProp ?? effectivePageSize;
|
|
2668
|
+
const totalPages = Math.max(
|
|
2669
|
+
1,
|
|
2670
|
+
Math.ceil(displayTotal / Math.max(1, pagerPageSize))
|
|
2671
|
+
);
|
|
2672
|
+
const rangeFrom = page.data.length === 0 ? 0 : (currentPage - 1) * pagerPageSize + 1;
|
|
2673
|
+
const rangeTo = rangeFrom === 0 ? 0 : rangeFrom + page.data.length - 1;
|
|
2551
2674
|
const detailTitle = page.selectedItem ? String(
|
|
2552
2675
|
page.selectedItem[page.titleField] ?? ""
|
|
2553
2676
|
) : "";
|
|
@@ -2691,28 +2814,35 @@ function ResourcePage(props) {
|
|
|
2691
2814
|
isLoading,
|
|
2692
2815
|
hasError,
|
|
2693
2816
|
isEmpty,
|
|
2694
|
-
|
|
2817
|
+
errorMessage,
|
|
2818
|
+
onRetry: isClientMode ? () => resourceHook.list.refetch() : onRetryProp,
|
|
2695
2819
|
viewMode: page.viewMode,
|
|
2696
2820
|
onViewModeChange: page.setViewMode,
|
|
2697
|
-
pageSize:
|
|
2698
|
-
onPageSizeChange:
|
|
2821
|
+
pageSize: effectivePageSize,
|
|
2822
|
+
onPageSizeChange: handlePageSizeChange,
|
|
2699
2823
|
density: settings.density,
|
|
2700
2824
|
onDensityChange: (d) => updateSetting("density", d),
|
|
2701
2825
|
createAction,
|
|
2702
2826
|
hasActiveFilters: page.hasActiveFilters,
|
|
2703
|
-
onClearFilters:
|
|
2827
|
+
onClearFilters: handleClearFilters,
|
|
2704
2828
|
emptyAction: emptyState,
|
|
2705
2829
|
filters: /* @__PURE__ */ jsx(
|
|
2706
2830
|
DataFilters,
|
|
2707
2831
|
{
|
|
2708
2832
|
search: page.filterConfig.search,
|
|
2709
|
-
onSearchChange:
|
|
2833
|
+
onSearchChange: handleSearchChange,
|
|
2710
2834
|
searchPlaceholder,
|
|
2711
2835
|
sort: page.filterConfig.sort,
|
|
2712
|
-
onSortChange:
|
|
2836
|
+
onSortChange: handleSortSelect,
|
|
2713
2837
|
sortOptions: page.filterConfig.sortOptions,
|
|
2714
|
-
|
|
2715
|
-
|
|
2838
|
+
filters: filtersProp,
|
|
2839
|
+
statusChips: statusChipsConfig,
|
|
2840
|
+
savedViews,
|
|
2841
|
+
onLoadView,
|
|
2842
|
+
onSaveView,
|
|
2843
|
+
onDeleteView,
|
|
2844
|
+
canSaveViews,
|
|
2845
|
+
onClearAll: page.hasActiveFilters ? handleClearFilters : void 0
|
|
2716
2846
|
}
|
|
2717
2847
|
),
|
|
2718
2848
|
children: [
|
|
@@ -2727,6 +2857,7 @@ function ResourcePage(props) {
|
|
|
2727
2857
|
label: a.label,
|
|
2728
2858
|
icon: a.icon ?? Trash2,
|
|
2729
2859
|
variant: a.variant,
|
|
2860
|
+
disabled: a.disabled,
|
|
2730
2861
|
onClick: () => {
|
|
2731
2862
|
void a.onAction(Array.from(selectedIds));
|
|
2732
2863
|
}
|
|
@@ -2742,7 +2873,7 @@ function ResourcePage(props) {
|
|
|
2742
2873
|
getKey: (item) => String(item.id ?? ""),
|
|
2743
2874
|
focusedIndex: keyboardNav.focusedIndex,
|
|
2744
2875
|
keyboardContainerRef: keyboardNav.containerRef,
|
|
2745
|
-
renderTable: (items) => /* @__PURE__ */ jsx(
|
|
2876
|
+
renderTable: (items) => renderTableProp ? renderTableProp(items) : /* @__PURE__ */ jsx(
|
|
2746
2877
|
DataTable,
|
|
2747
2878
|
{
|
|
2748
2879
|
items,
|
|
@@ -2754,13 +2885,108 @@ function ResourcePage(props) {
|
|
|
2754
2885
|
onToggleSelect: handleToggleSelect,
|
|
2755
2886
|
onToggleAll: handleToggleAll,
|
|
2756
2887
|
density: settings.density,
|
|
2757
|
-
pageSize:
|
|
2888
|
+
pageSize: effectivePageSize,
|
|
2889
|
+
pageSizeOptions,
|
|
2890
|
+
columnVisibility,
|
|
2891
|
+
columnVisibilityKey,
|
|
2892
|
+
resizableColumns,
|
|
2893
|
+
resizeKey,
|
|
2894
|
+
stickyHeader,
|
|
2895
|
+
stickyFirstColumn,
|
|
2896
|
+
pagination: isServerControlled ? false : void 0
|
|
2758
2897
|
}
|
|
2759
2898
|
),
|
|
2760
2899
|
renderCard: (item, index) => renderCardProp ? renderCardProp(item, index, cardActionsFor(item)) : renderDefaultCard(item),
|
|
2761
2900
|
renderListItem: (item, index) => renderCardProp ? renderCardProp(item, index, cardActionsFor(item)) : renderDefaultListItem(item)
|
|
2762
2901
|
}
|
|
2763
2902
|
),
|
|
2903
|
+
isServerControlled && onPageChange && pagerMisconfigured && /* @__PURE__ */ jsxs(
|
|
2904
|
+
"div",
|
|
2905
|
+
{
|
|
2906
|
+
className: "flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
2907
|
+
"data-testid": "resource-page-pagination-error",
|
|
2908
|
+
role: "alert",
|
|
2909
|
+
children: [
|
|
2910
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
2911
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2912
|
+
"Pagination unavailable:",
|
|
2913
|
+
" ",
|
|
2914
|
+
missingPagerProps.map((name, index) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2915
|
+
index > 0 ? " and " : null,
|
|
2916
|
+
/* @__PURE__ */ jsx("code", { children: name })
|
|
2917
|
+
] }, name)),
|
|
2918
|
+
" ",
|
|
2919
|
+
missingPagerProps.length > 1 ? "are" : "is",
|
|
2920
|
+
" required when",
|
|
2921
|
+
" ",
|
|
2922
|
+
/* @__PURE__ */ jsx("code", { children: "onPageChange" }),
|
|
2923
|
+
" is supplied."
|
|
2924
|
+
] })
|
|
2925
|
+
]
|
|
2926
|
+
}
|
|
2927
|
+
),
|
|
2928
|
+
isServerControlled && onPageChange && !pagerMisconfigured && /* @__PURE__ */ jsxs(
|
|
2929
|
+
"nav",
|
|
2930
|
+
{
|
|
2931
|
+
"aria-label": "Pagination",
|
|
2932
|
+
className: "flex flex-col sm:flex-row items-center justify-between gap-2 px-3 py-2 text-sm",
|
|
2933
|
+
"data-testid": "resource-page-pagination",
|
|
2934
|
+
children: [
|
|
2935
|
+
/* @__PURE__ */ jsx(
|
|
2936
|
+
"span",
|
|
2937
|
+
{
|
|
2938
|
+
className: "text-muted-foreground",
|
|
2939
|
+
"data-testid": "resource-page-range",
|
|
2940
|
+
"aria-live": "polite",
|
|
2941
|
+
children: displayTotal === 0 ? "No records" : `Showing ${rangeFrom}-${rangeTo} of ${displayTotal}`
|
|
2942
|
+
}
|
|
2943
|
+
),
|
|
2944
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2945
|
+
/* @__PURE__ */ jsxs(
|
|
2946
|
+
Button,
|
|
2947
|
+
{
|
|
2948
|
+
variant: "outline",
|
|
2949
|
+
size: "sm",
|
|
2950
|
+
disabled: currentPage <= 1,
|
|
2951
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
2952
|
+
testID: "resource-page-prev",
|
|
2953
|
+
children: [
|
|
2954
|
+
/* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4 mr-1", "aria-hidden": "true" }),
|
|
2955
|
+
"Previous"
|
|
2956
|
+
]
|
|
2957
|
+
}
|
|
2958
|
+
),
|
|
2959
|
+
/* @__PURE__ */ jsxs(
|
|
2960
|
+
"span",
|
|
2961
|
+
{
|
|
2962
|
+
className: "text-muted-foreground",
|
|
2963
|
+
"data-testid": "resource-page-indicator",
|
|
2964
|
+
children: [
|
|
2965
|
+
"Page ",
|
|
2966
|
+
currentPage,
|
|
2967
|
+
" of ",
|
|
2968
|
+
totalPages
|
|
2969
|
+
]
|
|
2970
|
+
}
|
|
2971
|
+
),
|
|
2972
|
+
/* @__PURE__ */ jsxs(
|
|
2973
|
+
Button,
|
|
2974
|
+
{
|
|
2975
|
+
variant: "outline",
|
|
2976
|
+
size: "sm",
|
|
2977
|
+
disabled: currentPage >= totalPages,
|
|
2978
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
2979
|
+
testID: "resource-page-next",
|
|
2980
|
+
children: [
|
|
2981
|
+
"Next",
|
|
2982
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 ml-1", "aria-hidden": "true" })
|
|
2983
|
+
]
|
|
2984
|
+
}
|
|
2985
|
+
)
|
|
2986
|
+
] })
|
|
2987
|
+
]
|
|
2988
|
+
}
|
|
2989
|
+
),
|
|
2764
2990
|
(detail === "panel" || detail === "modal") && /* @__PURE__ */ jsx(
|
|
2765
2991
|
DetailPanel,
|
|
2766
2992
|
{
|