najm-kit 2.2.8 → 2.4.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.mjs +297 -210
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
- `NTablePagination` renders numbered page buttons instead of `Page X of Y`. The window shows the first and last page, the current page, and one page either side, collapsing the rest into at most two gaps. The slot count is constant for any result longer than the window, so the bar does not change width as the reader pages through it, and a gap never stands in for a single page — that slot goes to the page instead.
|
|
6
|
+
- Added `paginationVariant`, defaulting to `"numbered"`. Pass `"compact"` to keep the previous position text with first/previous/next/last controls. **This changes the default appearance of every paginated `NTable`.**
|
|
7
|
+
- The numbered variant drops the first/last double chevrons, because page 1 and page N are now single-click targets of their own. Previous and next remain. The compact variant is unchanged.
|
|
8
|
+
- Numbered pages fall back to compact on their own when the page count is not trustworthy — that is, under `manualPagination` with no `pageCount` supplied, where TanStack infers a count from the rows it happens to hold rather than from a result total. Numbering that would invite clicks on pages that may not exist is not rendered.
|
|
9
|
+
- Below the `sm` breakpoint the numbers give way to the position text; seven page buttons plus the rows-per-page select do not fit a phone.
|
|
10
|
+
- Added `paginationLabels` so the bar can be localized: `rowsPerPage`, `pagination`, `goToPage`, `currentPage`, `firstPage`, `previousPage`, `nextPage`, `lastPage`, `pageOf`, and `rowsSelected`. All optional, all falling back to the previous English strings.
|
|
11
|
+
- Pagination chevrons now mirror under `dir="rtl"`. They previously pointed against the reading direction in right-to-left layouts.
|
|
12
|
+
- The page controls are wrapped in a labelled `nav`, and the current page carries `aria-current="page"`.
|
|
13
|
+
- Exported `buildPageItems` and `NTablePageItem` for consumers that need the same windowing outside the table.
|
|
14
|
+
|
|
3
15
|
## 2.2.1
|
|
4
16
|
|
|
5
17
|
- Fixed a regression in 2.2.0: the dynamic page size reported under `manualPagination` could oscillate. Card row height is measured from rendered cards, so it grows as images decode; feeding that back into the page size refetched, re-rendered, re-measured, and refetched again. A list visibly settled from one page size to another with the loading skeleton flashing twice. The report is now allowed once per container geometry, which does not depend on the rows inside it, so it terminates. A resize still re-arms it, and the debounce still waits for the measurement to settle before reporting.
|
package/dist/index.d.ts
CHANGED
|
@@ -2771,6 +2771,42 @@ type StepSubmitResult = {
|
|
|
2771
2771
|
};
|
|
2772
2772
|
declare function useFormSubmission({ steps, schema, defaultValues, onSubmit, currentStep, isLastStep, handleNext, markStepCompleted, reset, }: UseFormSubmissionOptions): FormSubmissionState;
|
|
2773
2773
|
|
|
2774
|
+
/**
|
|
2775
|
+
* How the page controls present position within the result.
|
|
2776
|
+
*
|
|
2777
|
+
* `numbered` renders a windowed list of page buttons. `compact` renders the
|
|
2778
|
+
* `Page X of Y` text with first/previous/next/last controls.
|
|
2779
|
+
*
|
|
2780
|
+
* `numbered` needs a trustworthy page count. Under `manualPagination` that
|
|
2781
|
+
* means the application must pass a `pageCount` derived from a real result
|
|
2782
|
+
* total; without one, the bar falls back to `compact` on its own rather than
|
|
2783
|
+
* inviting clicks on pages that may not exist.
|
|
2784
|
+
*/
|
|
2785
|
+
type NTablePaginationVariant = "numbered" | "compact";
|
|
2786
|
+
/**
|
|
2787
|
+
* Accessible names and visible copy for the page controls.
|
|
2788
|
+
*
|
|
2789
|
+
* Every field is optional and falls back to English. Supply them to localize —
|
|
2790
|
+
* the numbered variant is mostly digits, but its controls still need names.
|
|
2791
|
+
*/
|
|
2792
|
+
interface NTablePaginationLabels {
|
|
2793
|
+
/** Labels the rows-per-page select. Defaults to `"Rows/page"`. */
|
|
2794
|
+
rowsPerPage?: string;
|
|
2795
|
+
/** Accessible name of the whole page control group. Defaults to `"Pagination"`. */
|
|
2796
|
+
pagination?: string;
|
|
2797
|
+
/** Accessible name for one page button, given a 1-based page. */
|
|
2798
|
+
goToPage?: (page: number) => string;
|
|
2799
|
+
/** Accessible name of the current page button, given a 1-based page. */
|
|
2800
|
+
currentPage?: (page: number) => string;
|
|
2801
|
+
firstPage?: string;
|
|
2802
|
+
previousPage?: string;
|
|
2803
|
+
nextPage?: string;
|
|
2804
|
+
lastPage?: string;
|
|
2805
|
+
/** The `compact` variant's position text, given 1-based values. */
|
|
2806
|
+
pageOf?: (page: number, pageCount: number) => string;
|
|
2807
|
+
/** The selection summary, given selected and total row counts. */
|
|
2808
|
+
rowsSelected?: (selected: number, total: number) => string;
|
|
2809
|
+
}
|
|
2774
2810
|
interface NTableLoadMorePagination {
|
|
2775
2811
|
/** Render the supplied rows as one card list with an explicit continuation control. */
|
|
2776
2812
|
mode: "load-more";
|
|
@@ -2933,6 +2969,8 @@ interface TableState {
|
|
|
2933
2969
|
availableModes: readonly ViewMode[];
|
|
2934
2970
|
setViewMode: (mode: ViewMode) => void;
|
|
2935
2971
|
hasSyncedFromProps: boolean;
|
|
2972
|
+
paginationVariant: NTablePaginationVariant;
|
|
2973
|
+
paginationLabels: NTablePaginationLabels;
|
|
2936
2974
|
manualPagination: boolean;
|
|
2937
2975
|
pageCount: number | undefined;
|
|
2938
2976
|
rowCount: number | undefined;
|
|
@@ -3071,6 +3109,8 @@ declare const createTableStore: (seed?: Partial<TableState>) => {
|
|
|
3071
3109
|
availableModes: () => readonly ViewMode[];
|
|
3072
3110
|
setViewMode: () => (mode: ViewMode) => void;
|
|
3073
3111
|
hasSyncedFromProps: () => boolean;
|
|
3112
|
+
paginationVariant: () => NTablePaginationVariant;
|
|
3113
|
+
paginationLabels: () => NTablePaginationLabels;
|
|
3074
3114
|
manualPagination: () => boolean;
|
|
3075
3115
|
pageCount: () => number;
|
|
3076
3116
|
rowCount: () => number;
|
|
@@ -3262,6 +3302,14 @@ interface NTableProps<T = any, M extends ViewMode = ViewMode> {
|
|
|
3262
3302
|
}) => void;
|
|
3263
3303
|
/** Pagination presentation used whenever NTable is actually rendering cards. */
|
|
3264
3304
|
cardPagination?: NTableCardPagination;
|
|
3305
|
+
/**
|
|
3306
|
+
* How the page controls present position. Defaults to `"numbered"`, which
|
|
3307
|
+
* falls back to `"compact"` on its own when the page count is not
|
|
3308
|
+
* trustworthy. Pass `"compact"` for the `Page X of Y` text everywhere.
|
|
3309
|
+
*/
|
|
3310
|
+
paginationVariant?: NTablePaginationVariant;
|
|
3311
|
+
/** Accessible names and visible copy for the page controls. */
|
|
3312
|
+
paginationLabels?: NTablePaginationLabels;
|
|
3265
3313
|
rowSelection?: RowSelectionState;
|
|
3266
3314
|
defaultRowSelection?: RowSelectionState;
|
|
3267
3315
|
onRowSelectionChange?: (state: RowSelectionState) => void;
|
|
@@ -3519,6 +3567,8 @@ declare const TableStoreContext: React$1.Context<{
|
|
|
3519
3567
|
availableModes: () => readonly ViewMode[];
|
|
3520
3568
|
setViewMode: () => (mode: ViewMode) => void;
|
|
3521
3569
|
hasSyncedFromProps: () => boolean;
|
|
3570
|
+
paginationVariant: () => NTablePaginationVariant;
|
|
3571
|
+
paginationLabels: () => NTablePaginationLabels;
|
|
3522
3572
|
manualPagination: () => boolean;
|
|
3523
3573
|
pageCount: () => number;
|
|
3524
3574
|
rowCount: () => number;
|
|
@@ -3652,6 +3702,8 @@ declare function useStoreSync(props: any): {
|
|
|
3652
3702
|
availableModes: () => readonly ViewMode[];
|
|
3653
3703
|
setViewMode: () => (mode: ViewMode) => void;
|
|
3654
3704
|
hasSyncedFromProps: () => boolean;
|
|
3705
|
+
paginationVariant: () => NTablePaginationVariant;
|
|
3706
|
+
paginationLabels: () => NTablePaginationLabels;
|
|
3655
3707
|
manualPagination: () => boolean;
|
|
3656
3708
|
pageCount: () => number;
|
|
3657
3709
|
rowCount: () => number;
|
package/dist/index.mjs
CHANGED
|
@@ -12222,6 +12222,8 @@ var createTableStore = (seed) => {
|
|
|
12222
12222
|
hasMeasuredLayout: false,
|
|
12223
12223
|
skeletonRowCount: 6,
|
|
12224
12224
|
maxHeight: null,
|
|
12225
|
+
paginationVariant: "numbered",
|
|
12226
|
+
paginationLabels: {},
|
|
12225
12227
|
bodyWidth: 0,
|
|
12226
12228
|
bodyHeight: 0,
|
|
12227
12229
|
tableHeaderHeight: 48,
|
|
@@ -12507,9 +12509,9 @@ function useDynamicPageSize(containerRef, effectiveViewMode) {
|
|
|
12507
12509
|
const calculatePageSize = () => {
|
|
12508
12510
|
const container2 = containerRef.current;
|
|
12509
12511
|
if (!container2) return;
|
|
12512
|
+
if (error || hasNoData && !isFilteredEmpty && !isLoading) return;
|
|
12510
12513
|
const bodyEl = container2.querySelector("[data-ntable-body]");
|
|
12511
12514
|
const tableHeaderEl = container2.querySelector("[data-ntable-table-header]");
|
|
12512
|
-
const loadingHeaderEl = container2.querySelector("[data-ntable-loading-header]");
|
|
12513
12515
|
const cardsGridEl = Array.from(
|
|
12514
12516
|
container2.querySelectorAll(
|
|
12515
12517
|
"[data-ntable-loading-cards-grid], [data-ntable-cards-grid]"
|
|
@@ -12525,11 +12527,6 @@ function useDynamicPageSize(containerRef, effectiveViewMode) {
|
|
|
12525
12527
|
const gap = Number.parseFloat(rootStyles.rowGap || rootStyles.gap || "0") || 0;
|
|
12526
12528
|
bodyHeight = rootHeight - headerHeight - paginationHeight - gap * ROOT_SECTION_GAP_COUNT;
|
|
12527
12529
|
}
|
|
12528
|
-
if (loadingHeaderEl && bodyEl) {
|
|
12529
|
-
const bodyStyles = window.getComputedStyle(bodyEl);
|
|
12530
|
-
const bodyGap = Number.parseFloat(bodyStyles.rowGap || bodyStyles.gap || "0") || 0;
|
|
12531
|
-
bodyHeight = Math.max(0, bodyHeight - loadingHeaderEl.offsetHeight - bodyGap);
|
|
12532
|
-
}
|
|
12533
12530
|
const tableHeaderHeight = tableHeaderEl?.offsetHeight ?? DEFAULT_TABLE_HEADER_HEIGHT;
|
|
12534
12531
|
const newPageSize = calculateDynamicPageSize({ bodyHeight, tableHeaderHeight });
|
|
12535
12532
|
const calculatedMaxHeight = tableHeaderHeight + newPageSize * ROW_HEIGHT;
|
|
@@ -12578,7 +12575,7 @@ function useDynamicPageSize(containerRef, effectiveViewMode) {
|
|
|
12578
12575
|
"[data-ntable-header], [data-ntable-body], [data-ntable-pagination], [data-ntable-table-header]"
|
|
12579
12576
|
).forEach((el) => resizeObserver.observe(el));
|
|
12580
12577
|
container.querySelectorAll(
|
|
12581
|
-
"[data-ntable-loading-
|
|
12578
|
+
"[data-ntable-loading-cards-grid], [data-ntable-loading-card], [data-ntable-cards-grid]"
|
|
12582
12579
|
).forEach((el) => resizeObserver.observe(el));
|
|
12583
12580
|
if (container.parentElement) resizeObserver.observe(container.parentElement);
|
|
12584
12581
|
return () => resizeObserver.disconnect();
|
|
@@ -12612,6 +12609,7 @@ function useTable(effectiveViewModeOverride) {
|
|
|
12612
12609
|
const onStateChange = useTableStore.use.onStateChange();
|
|
12613
12610
|
const getRowId = useTableStore.use.getRowId();
|
|
12614
12611
|
const manualPagination = useTableStore.use.manualPagination();
|
|
12612
|
+
const hasDataRows = useTableStore.use.hasData();
|
|
12615
12613
|
const pageCount = useTableStore.use.pageCount();
|
|
12616
12614
|
const rowCount = useTableStore.use.rowCount();
|
|
12617
12615
|
const storePagination = useTableStore.use.pagination();
|
|
@@ -12725,6 +12723,11 @@ function useTable(effectiveViewModeOverride) {
|
|
|
12725
12723
|
tableConfig.getRowCanExpand = userGetRowCanExpand ? (row) => userGetRowCanExpand(row.original) : () => true;
|
|
12726
12724
|
}
|
|
12727
12725
|
const table = useReactTable(tableConfig);
|
|
12726
|
+
const hasSeededTableRef = useRef(false);
|
|
12727
|
+
if (!hasSeededTableRef.current) {
|
|
12728
|
+
hasSeededTableRef.current = true;
|
|
12729
|
+
syncWithProps({ table });
|
|
12730
|
+
}
|
|
12728
12731
|
useLayoutEffect(() => {
|
|
12729
12732
|
syncWithProps({ table });
|
|
12730
12733
|
}, [table]);
|
|
@@ -12745,12 +12748,17 @@ function useTable(effectiveViewModeOverride) {
|
|
|
12745
12748
|
if (!dynamicPageSizeTarget || dynamicPageSizeTarget < 1) return;
|
|
12746
12749
|
if (dynamicPageSizeTarget === storePagination.pageSize) return;
|
|
12747
12750
|
const reported = reportedGeometryRef.current;
|
|
12751
|
+
if (reported?.key === geometryKey && reported.target === dynamicPageSizeTarget) return;
|
|
12748
12752
|
if (reported?.key === geometryKey && reported.count >= MAX_PAGE_SIZE_REPORTS_PER_GEOMETRY) return;
|
|
12749
12753
|
const commit = () => {
|
|
12750
12754
|
const current = reportedGeometryRef.current;
|
|
12751
|
-
reportedGeometryRef.current = current?.key === geometryKey ? { key: geometryKey, count: current.count + 1 } : { key: geometryKey, count: 1 };
|
|
12755
|
+
reportedGeometryRef.current = current?.key === geometryKey ? { key: geometryKey, count: current.count + 1, target: dynamicPageSizeTarget } : { key: geometryKey, count: 1, target: dynamicPageSizeTarget };
|
|
12752
12756
|
setPagination({ pageIndex: storePagination.pageIndex, pageSize: dynamicPageSizeTarget });
|
|
12753
12757
|
};
|
|
12758
|
+
if (!hasDataRows) {
|
|
12759
|
+
commit();
|
|
12760
|
+
return;
|
|
12761
|
+
}
|
|
12754
12762
|
if (!reported) {
|
|
12755
12763
|
commit();
|
|
12756
12764
|
return;
|
|
@@ -12767,6 +12775,7 @@ function useTable(effectiveViewModeOverride) {
|
|
|
12767
12775
|
dynamicPageSizeTarget,
|
|
12768
12776
|
storePagination.pageIndex,
|
|
12769
12777
|
storePagination.pageSize,
|
|
12778
|
+
hasDataRows,
|
|
12770
12779
|
setPagination
|
|
12771
12780
|
]);
|
|
12772
12781
|
return { table, finalColumns, sorting, setSorting, columnFilters, setColumnFilters, columnVisibility, setColumnVisibility, globalFilter, setGlobalFilter };
|
|
@@ -12960,6 +12969,11 @@ function NTableContent({ effectiveMode }) {
|
|
|
12960
12969
|
const onCellEdit = useTableStore.use.onCellEdit();
|
|
12961
12970
|
useTableStore.use.isLoading();
|
|
12962
12971
|
const error = useTableStore.use.error();
|
|
12972
|
+
const contentDynamicHeight = useTableStore.use.dynamicHeight();
|
|
12973
|
+
const contentManualPagination = useTableStore.use.manualPagination();
|
|
12974
|
+
const contentCardPagination = useTableStore.use.cardPagination();
|
|
12975
|
+
const contentCalculatedPageSize = useTableStore.use.calculatedPageSize();
|
|
12976
|
+
const contentHasMeasuredLayout = useTableStore.use.hasMeasuredLayout();
|
|
12963
12977
|
const hasNoData = useTableStore.use.hasNoData();
|
|
12964
12978
|
const showContent = useTableStore.use.showContent();
|
|
12965
12979
|
const classNames = useTableStore.use.classNames();
|
|
@@ -12981,6 +12995,9 @@ function NTableContent({ effectiveMode }) {
|
|
|
12981
12995
|
if (error || hasNoData || !showContent || !table) return null;
|
|
12982
12996
|
const isTableView = effectiveMode ? effectiveMode === "table" : storeIsTableView;
|
|
12983
12997
|
if (!isTableView) return null;
|
|
12998
|
+
const allRows = table.getRowModel().rows ?? [];
|
|
12999
|
+
const clampRowsToMeasuredPage = contentDynamicHeight && contentManualPagination && contentCardPagination.mode === "paged" && contentHasMeasuredLayout && contentCalculatedPageSize > 0;
|
|
13000
|
+
const visibleRows = clampRowsToMeasuredPage ? allRows.slice(0, contentCalculatedPageSize) : allRows;
|
|
12984
13001
|
const getSortIcon = (column) => {
|
|
12985
13002
|
const dir = column.getIsSorted();
|
|
12986
13003
|
if (dir === "asc") return /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" });
|
|
@@ -12993,13 +13010,22 @@ function NTableContent({ effectiveMode }) {
|
|
|
12993
13010
|
axis: "both",
|
|
12994
13011
|
"data-bordered": bordered === false ? "false" : bordered ? "true" : void 0,
|
|
12995
13012
|
className: cn(
|
|
12996
|
-
"min-h-0
|
|
13013
|
+
"min-h-0 overflow-hidden rounded-md",
|
|
13014
|
+
// Under `dynamicHeight` the page size is the largest row count that
|
|
13015
|
+
// fits, so the rows are always a little shorter than the space they
|
|
13016
|
+
// were measured against — up to one row's worth. Growing into that
|
|
13017
|
+
// remainder leaves the container's bottom edge floating below the last
|
|
13018
|
+
// row. Sizing to content instead ends the border on the last row; the
|
|
13019
|
+
// leftover belongs to the page, not to the table. Without
|
|
13020
|
+
// `dynamicHeight` the row count is the caller's, so the container has
|
|
13021
|
+
// to keep filling its height to stay a scroll viewport.
|
|
13022
|
+
contentDynamicHeight ? "max-h-full shrink" : "flex-1",
|
|
12997
13023
|
surface.className,
|
|
12998
13024
|
classNames?.content
|
|
12999
13025
|
),
|
|
13000
13026
|
style: surface.style,
|
|
13001
13027
|
onContextMenu: handleBackgroundContextMenu,
|
|
13002
|
-
children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
13028
|
+
children: /* @__PURE__ */ jsxs(Table, { className: "table-fixed", children: [
|
|
13003
13029
|
/* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn("bg-card sticky top-0 z-10", headerClassName, bordered === true && "[&_tr]:border-border", classNames?.tableHeader), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsxs(TableRow, { style: rowBorderStyle, className: cn("hover:bg-transparent", bordered === true && "border-border"), children: [
|
|
13004
13030
|
showCheckbox && /* @__PURE__ */ jsx(
|
|
13005
13031
|
TableHead,
|
|
@@ -13030,7 +13056,7 @@ function NTableContent({ effectiveMode }) {
|
|
|
13030
13056
|
return /* @__PURE__ */ jsx(
|
|
13031
13057
|
TableHead,
|
|
13032
13058
|
{
|
|
13033
|
-
className: cn("text-foreground h-12", responsiveClass),
|
|
13059
|
+
className: cn("text-foreground h-12 overflow-hidden text-ellipsis", responsiveClass),
|
|
13034
13060
|
style: headerCellStyle,
|
|
13035
13061
|
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", header.column.getCanSort() && showSorting && "cursor-pointer select-none"), onClick: header.column.getToggleSortingHandler(), children: [
|
|
13036
13062
|
flexRender(header.column.columnDef.header, header.getContext()),
|
|
@@ -13041,7 +13067,7 @@ function NTableContent({ effectiveMode }) {
|
|
|
13041
13067
|
);
|
|
13042
13068
|
})
|
|
13043
13069
|
] }, hg.id)) }),
|
|
13044
|
-
/* @__PURE__ */ jsx(TableBody, { children:
|
|
13070
|
+
/* @__PURE__ */ jsx(TableBody, { children: visibleRows.length ? visibleRows.map((row) => {
|
|
13045
13071
|
const isSelectedByRowId = Boolean(selectedRowId && row.original?.id === selectedRowId);
|
|
13046
13072
|
const canExpand = hasExpansion && row.getCanExpand();
|
|
13047
13073
|
const isExpanded = canExpand && row.getIsExpanded();
|
|
@@ -13094,7 +13120,7 @@ function NTableContent({ effectiveMode }) {
|
|
|
13094
13120
|
const meta = columnDef.meta || {};
|
|
13095
13121
|
const isEditable = Boolean(onCellEdit) && Boolean(meta.editable);
|
|
13096
13122
|
const responsiveClass = resolveHiddenBelowClass(meta.hiddenBelow);
|
|
13097
|
-
return /* @__PURE__ */ jsx(TableCell, { className: cn("h-14", responsiveClass), children: isEditable ? /* @__PURE__ */ jsx(EditableCell, { cell, onCellEdit }) : flexRender(columnDef.cell, cell.getContext()) }, cell.id);
|
|
13123
|
+
return /* @__PURE__ */ jsx(TableCell, { title: typeof cell.getValue?.() === "string" ? cell.getValue() : void 0, className: cn("h-14 overflow-hidden text-ellipsis", responsiveClass), children: isEditable ? /* @__PURE__ */ jsx(EditableCell, { cell, onCellEdit }) : flexRender(columnDef.cell, cell.getContext()) }, cell.id);
|
|
13098
13124
|
})
|
|
13099
13125
|
]
|
|
13100
13126
|
}
|
|
@@ -13234,6 +13260,17 @@ function NDataCardShell({ row, onClick, onContextMenu, actions, children, classN
|
|
|
13234
13260
|
var DEFAULT_ROWS2 = 6;
|
|
13235
13261
|
var UNMEASURED_DYNAMIC_ROWS = 12;
|
|
13236
13262
|
var DEFAULT_CARD_COUNT = 48;
|
|
13263
|
+
var VISUALLY_HIDDEN = {
|
|
13264
|
+
position: "absolute",
|
|
13265
|
+
width: 1,
|
|
13266
|
+
height: 1,
|
|
13267
|
+
margin: -1,
|
|
13268
|
+
padding: 0,
|
|
13269
|
+
overflow: "hidden",
|
|
13270
|
+
clip: "rect(0,0,0,0)",
|
|
13271
|
+
whiteSpace: "nowrap",
|
|
13272
|
+
borderWidth: 0
|
|
13273
|
+
};
|
|
13237
13274
|
function NTableCardSkeleton({ surface }) {
|
|
13238
13275
|
return /* @__PURE__ */ jsx(
|
|
13239
13276
|
"div",
|
|
@@ -13293,75 +13330,6 @@ function NTableCardSkeleton({ surface }) {
|
|
|
13293
13330
|
}
|
|
13294
13331
|
);
|
|
13295
13332
|
}
|
|
13296
|
-
function NTableHeaderSkeleton() {
|
|
13297
|
-
const filters = useTableStore.use.filters();
|
|
13298
|
-
const showViewToggle = useTableStore.use.showViewToggle();
|
|
13299
|
-
const showColumnVisibility = useTableStore.use.showColumnVisibility();
|
|
13300
|
-
const showAddButton = useTableStore.use.showAddButton();
|
|
13301
|
-
const hasHeaderSlot = Boolean(useTableStore.use.headerSlot());
|
|
13302
|
-
const hasToolbar = Boolean(useTableStore.use.renderToolbar());
|
|
13303
|
-
const filterCount = Math.min(Math.max(filters?.length ?? 0, 1), 3);
|
|
13304
|
-
const hasActions = showViewToggle || showColumnVisibility || showAddButton || hasHeaderSlot || hasToolbar;
|
|
13305
|
-
const hasSettings = showViewToggle || showColumnVisibility || hasHeaderSlot || hasToolbar;
|
|
13306
|
-
if (!filters?.length && !hasActions) return null;
|
|
13307
|
-
return /* @__PURE__ */ jsxs(
|
|
13308
|
-
"div",
|
|
13309
|
-
{
|
|
13310
|
-
"data-ntable-loading-header": true,
|
|
13311
|
-
className: "flex shrink-0 flex-wrap items-center justify-between gap-2",
|
|
13312
|
-
children: [
|
|
13313
|
-
filters?.length ? /* @__PURE__ */ jsx(
|
|
13314
|
-
"div",
|
|
13315
|
-
{
|
|
13316
|
-
"data-ntable-loading-desktop-filters": true,
|
|
13317
|
-
className: "hidden min-w-0 flex-1 flex-wrap gap-2 md:flex",
|
|
13318
|
-
children: Array.from({ length: filterCount }).map((_, index) => /* @__PURE__ */ jsx(
|
|
13319
|
-
NSkeleton,
|
|
13320
|
-
{
|
|
13321
|
-
className: cn("h-10 w-full rounded-lg", index < 2 ? "max-w-64" : "max-w-48")
|
|
13322
|
-
},
|
|
13323
|
-
index
|
|
13324
|
-
))
|
|
13325
|
-
}
|
|
13326
|
-
) : /* @__PURE__ */ jsx("span", { className: "hidden min-w-0 flex-1 md:block" }),
|
|
13327
|
-
/* @__PURE__ */ jsxs(
|
|
13328
|
-
"div",
|
|
13329
|
-
{
|
|
13330
|
-
"data-ntable-loading-mobile-toolbar": true,
|
|
13331
|
-
className: "flex w-full min-w-0 items-center gap-2 md:hidden",
|
|
13332
|
-
children: [
|
|
13333
|
-
filters?.length ? /* @__PURE__ */ jsx(
|
|
13334
|
-
NSkeleton,
|
|
13335
|
-
{
|
|
13336
|
-
"data-ntable-loading-mobile-primary": true,
|
|
13337
|
-
className: "h-10 min-w-0 flex-1 rounded-lg"
|
|
13338
|
-
}
|
|
13339
|
-
) : null,
|
|
13340
|
-
filters?.length > 1 ? /* @__PURE__ */ jsx(
|
|
13341
|
-
NSkeleton,
|
|
13342
|
-
{
|
|
13343
|
-
"data-ntable-loading-mobile-filter-button": true,
|
|
13344
|
-
className: "h-10 w-10 shrink-0 rounded-lg"
|
|
13345
|
-
}
|
|
13346
|
-
) : null,
|
|
13347
|
-
showAddButton ? /* @__PURE__ */ jsx(
|
|
13348
|
-
NSkeleton,
|
|
13349
|
-
{
|
|
13350
|
-
"data-ntable-loading-mobile-add-button": true,
|
|
13351
|
-
className: "h-10 w-10 shrink-0 rounded-lg"
|
|
13352
|
-
}
|
|
13353
|
-
) : null
|
|
13354
|
-
]
|
|
13355
|
-
}
|
|
13356
|
-
),
|
|
13357
|
-
hasActions && /* @__PURE__ */ jsxs("div", { className: "hidden shrink-0 gap-2 md:flex", children: [
|
|
13358
|
-
hasSettings && /* @__PURE__ */ jsx(NSkeleton, { className: "h-10 w-10 rounded-lg" }),
|
|
13359
|
-
showAddButton && /* @__PURE__ */ jsx(NSkeleton, { className: "h-10 w-10 rounded-lg" })
|
|
13360
|
-
] })
|
|
13361
|
-
]
|
|
13362
|
-
}
|
|
13363
|
-
);
|
|
13364
|
-
}
|
|
13365
13333
|
function NTableLoadingSkeleton({ rows }) {
|
|
13366
13334
|
const rawColumns = useTableStore.use.columns();
|
|
13367
13335
|
const responsiveColumns = React__default.useMemo(() => filterResponsiveColumns(rawColumns), [rawColumns]);
|
|
@@ -13381,64 +13349,62 @@ function NTableLoadingSkeleton({ rows }) {
|
|
|
13381
13349
|
const loadingText = useTableStore.use.loadingText();
|
|
13382
13350
|
const rowCount = rows ?? (dynamicHeight ? bodyHeight > 0 ? skeletonRowCount : UNMEASURED_DYNAMIC_ROWS : DEFAULT_ROWS2);
|
|
13383
13351
|
const renderHeaderLabel = (header) => typeof header === "string" ? header : null;
|
|
13384
|
-
return /* @__PURE__ */
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
"
|
|
13388
|
-
|
|
13389
|
-
|
|
13390
|
-
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
|
|
13396
|
-
|
|
13397
|
-
|
|
13398
|
-
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13409
|
-
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13414
|
-
|
|
13415
|
-
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13352
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-2", children: /* @__PURE__ */ jsxs(
|
|
13353
|
+
"div",
|
|
13354
|
+
{
|
|
13355
|
+
"data-testid": "ntable-loading-skeleton",
|
|
13356
|
+
"data-ntable-loading-row-count": rowCount,
|
|
13357
|
+
"data-bordered": surface.bordered === false ? "false" : surface.bordered ? "true" : void 0,
|
|
13358
|
+
"aria-busy": "true",
|
|
13359
|
+
"aria-label": loadingText,
|
|
13360
|
+
role: "status",
|
|
13361
|
+
style: surface.style,
|
|
13362
|
+
className: cn(
|
|
13363
|
+
"min-h-0 rounded-md p-0",
|
|
13364
|
+
surface.className,
|
|
13365
|
+
// Sizes to its rows for the same reason `NTableContent` does, and it
|
|
13366
|
+
// has to match: the skeleton draws exactly the row count the real
|
|
13367
|
+
// table will render, so a box that fills its container here and hugs
|
|
13368
|
+
// its rows there would visibly resize the instant the rows arrive —
|
|
13369
|
+
// the one thing this whole layout is meant to avoid.
|
|
13370
|
+
dynamicHeight ? "max-h-full shrink overflow-hidden" : "flex-1 najm-overlay-scroll",
|
|
13371
|
+
classNames?.content
|
|
13372
|
+
),
|
|
13373
|
+
children: [
|
|
13374
|
+
/* @__PURE__ */ jsx("span", { style: VISUALLY_HIDDEN, children: loadingText }),
|
|
13375
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: dynamicHeight ? "najm-overlay-scroll" : void 0, children: /* @__PURE__ */ jsxs(Table, { className: "table-fixed", children: [
|
|
13376
|
+
/* @__PURE__ */ jsx(TableHeader, { "data-ntable-table-header": true, className: cn(headerClassName, "sticky top-0 z-10", classNames?.tableHeader), children: /* @__PURE__ */ jsxs(TableRow, { className: "hover:bg-muted/30", children: [
|
|
13377
|
+
showCheckbox && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Select column", className: "w-10 text-foreground h-12" }),
|
|
13378
|
+
hasExpansion && /* @__PURE__ */ jsx(TableHead, { "aria-label": "Expand column", className: "w-10 text-foreground h-12" }),
|
|
13379
|
+
columns.map((col, i) => /* @__PURE__ */ jsx(
|
|
13380
|
+
TableHead,
|
|
13381
|
+
{
|
|
13382
|
+
className: cn("text-foreground h-12", resolveHiddenBelowClass(col?.meta?.hiddenBelow)),
|
|
13383
|
+
style: col?.size ? { width: col.size } : void 0,
|
|
13384
|
+
children: renderHeaderLabel(col?.header)
|
|
13385
|
+
},
|
|
13386
|
+
col?.id ?? col?.accessorKey ?? i
|
|
13387
|
+
))
|
|
13388
|
+
] }) }),
|
|
13389
|
+
/* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: rowCount }).map((_, r) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
13390
|
+
showCheckbox && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(NSkeleton, { className: "h-4 w-4" }) }),
|
|
13391
|
+
hasExpansion && /* @__PURE__ */ jsx(TableCell, { className: "h-14 w-10", children: /* @__PURE__ */ jsx(NSkeleton, { className: "h-4 w-4" }) }),
|
|
13392
|
+
columns.map((col, c) => /* @__PURE__ */ jsx(
|
|
13393
|
+
TableCell,
|
|
13394
|
+
{
|
|
13395
|
+
className: cn("h-14", resolveHiddenBelowClass(col?.meta?.hiddenBelow)),
|
|
13396
|
+
style: col?.size ? { width: col.size } : void 0,
|
|
13397
|
+
children: /* @__PURE__ */ jsx(NSkeleton, { className: "h-4 w-full" })
|
|
13398
|
+
},
|
|
13399
|
+
`skeleton-${r}-${col?.id ?? col?.accessorKey ?? c}`
|
|
13400
|
+
))
|
|
13401
|
+
] }, `skeleton-${r}`)) })
|
|
13402
|
+
] }) })
|
|
13403
|
+
]
|
|
13404
|
+
}
|
|
13405
|
+
) });
|
|
13431
13406
|
}
|
|
13432
13407
|
function NTableCardsLoadingSkeleton({ rows }) {
|
|
13433
|
-
const filters = useTableStore.use.filters();
|
|
13434
|
-
const showViewToggle = useTableStore.use.showViewToggle();
|
|
13435
|
-
const showColumnVisibility = useTableStore.use.showColumnVisibility();
|
|
13436
|
-
const showAddButton = useTableStore.use.showAddButton();
|
|
13437
|
-
const hasHeaderSlot = Boolean(useTableStore.use.headerSlot());
|
|
13438
|
-
const hasToolbar = Boolean(useTableStore.use.renderToolbar());
|
|
13439
|
-
const hasHeaderSkeleton = Boolean(
|
|
13440
|
-
filters?.length || showViewToggle || showColumnVisibility || showAddButton || hasHeaderSlot || hasToolbar
|
|
13441
|
-
);
|
|
13442
13408
|
const classNames = useTableStore.use.classNames();
|
|
13443
13409
|
const bordered = useTableStore.use.bordered();
|
|
13444
13410
|
const borderColor = useTableStore.use.borderColor();
|
|
@@ -13458,33 +13424,30 @@ function NTableCardsLoadingSkeleton({ rows }) {
|
|
|
13458
13424
|
}) : DEFAULT_CARD_COUNT);
|
|
13459
13425
|
const defaultContainerClass = "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4";
|
|
13460
13426
|
const containerClass = classNames?.cards ?? defaultContainerClass;
|
|
13461
|
-
return /* @__PURE__ */
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
"
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
}
|
|
13486
|
-
)
|
|
13487
|
-
] });
|
|
13427
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-2", children: /* @__PURE__ */ jsxs(
|
|
13428
|
+
NajmScroll,
|
|
13429
|
+
{
|
|
13430
|
+
axis: "y",
|
|
13431
|
+
"aria-busy": "true",
|
|
13432
|
+
"aria-label": loadingText,
|
|
13433
|
+
role: "status",
|
|
13434
|
+
className: "min-h-0 flex-1 overflow-hidden",
|
|
13435
|
+
children: [
|
|
13436
|
+
/* @__PURE__ */ jsx("span", { style: VISUALLY_HIDDEN, children: loadingText }),
|
|
13437
|
+
/* @__PURE__ */ jsx(
|
|
13438
|
+
"div",
|
|
13439
|
+
{
|
|
13440
|
+
"data-testid": "ntable-cards-loading-skeleton",
|
|
13441
|
+
"data-ntable-loading-cards-grid": true,
|
|
13442
|
+
"data-ntable-loading-card-count": cardCount,
|
|
13443
|
+
"aria-hidden": "true",
|
|
13444
|
+
className: cn(containerClass),
|
|
13445
|
+
children: Array.from({ length: cardCount }).map((_, index) => CardSkeletonComponent ? /* @__PURE__ */ jsx("div", { "data-ntable-loading-card": true, children: /* @__PURE__ */ jsx(CardSkeletonComponent, {}) }, index) : /* @__PURE__ */ jsx(NTableCardSkeleton, { surface }, index))
|
|
13446
|
+
}
|
|
13447
|
+
)
|
|
13448
|
+
]
|
|
13449
|
+
}
|
|
13450
|
+
) });
|
|
13488
13451
|
}
|
|
13489
13452
|
var DEFAULT_ROOT_MARGIN = "80px";
|
|
13490
13453
|
function useCardContinuation({
|
|
@@ -13767,6 +13730,51 @@ function NTableCards({ effectiveMode }) {
|
|
|
13767
13730
|
) : null
|
|
13768
13731
|
] });
|
|
13769
13732
|
}
|
|
13733
|
+
|
|
13734
|
+
// src/components/table/paginationPages.ts
|
|
13735
|
+
function buildPageItems(pageIndex, pageCount, siblingCount = 1) {
|
|
13736
|
+
const pages = Math.max(0, Math.floor(pageCount));
|
|
13737
|
+
if (pages <= 0) return [];
|
|
13738
|
+
const current = Math.min(Math.max(0, Math.floor(pageIndex)), pages - 1);
|
|
13739
|
+
const siblings = Math.max(0, Math.floor(siblingCount));
|
|
13740
|
+
const lastIndex = pages - 1;
|
|
13741
|
+
const windowSize = siblings * 2 + 5;
|
|
13742
|
+
if (pages <= windowSize) {
|
|
13743
|
+
return range(0, lastIndex);
|
|
13744
|
+
}
|
|
13745
|
+
const left = Math.max(current - siblings, 0);
|
|
13746
|
+
const right = Math.min(current + siblings, lastIndex);
|
|
13747
|
+
const showStartGap = left - 1 >= 2;
|
|
13748
|
+
const showEndGap = lastIndex - 1 - right >= 2;
|
|
13749
|
+
const runLength = siblings * 2 + 3;
|
|
13750
|
+
if (!showStartGap && showEndGap) {
|
|
13751
|
+
return [
|
|
13752
|
+
...range(0, runLength - 1),
|
|
13753
|
+
{ type: "gap", key: "end" },
|
|
13754
|
+
page(lastIndex)
|
|
13755
|
+
];
|
|
13756
|
+
}
|
|
13757
|
+
if (showStartGap && !showEndGap) {
|
|
13758
|
+
return [
|
|
13759
|
+
page(0),
|
|
13760
|
+
{ type: "gap", key: "start" },
|
|
13761
|
+
...range(lastIndex - runLength + 1, lastIndex)
|
|
13762
|
+
];
|
|
13763
|
+
}
|
|
13764
|
+
return [
|
|
13765
|
+
page(0),
|
|
13766
|
+
{ type: "gap", key: "start" },
|
|
13767
|
+
...range(left, right),
|
|
13768
|
+
{ type: "gap", key: "end" },
|
|
13769
|
+
page(lastIndex)
|
|
13770
|
+
];
|
|
13771
|
+
}
|
|
13772
|
+
function page(pageIndex) {
|
|
13773
|
+
return { type: "page", pageIndex };
|
|
13774
|
+
}
|
|
13775
|
+
function range(from, to) {
|
|
13776
|
+
return Array.from({ length: to - from + 1 }, (_, index) => page(from + index));
|
|
13777
|
+
}
|
|
13770
13778
|
function CardLoadMorePagination({
|
|
13771
13779
|
config,
|
|
13772
13780
|
rowCount,
|
|
@@ -13860,6 +13868,44 @@ function CardLoadMorePagination({
|
|
|
13860
13868
|
}
|
|
13861
13869
|
);
|
|
13862
13870
|
}
|
|
13871
|
+
var navButtonClass = "h-8 w-8 p-0 text-foreground disabled:text-muted-foreground disabled:opacity-70";
|
|
13872
|
+
var chevronClass = "h-4 w-4 rtl:-scale-x-100";
|
|
13873
|
+
function PageNumbers({
|
|
13874
|
+
pageIndex,
|
|
13875
|
+
pageCount,
|
|
13876
|
+
bordered,
|
|
13877
|
+
labels,
|
|
13878
|
+
onSelect
|
|
13879
|
+
}) {
|
|
13880
|
+
return /* @__PURE__ */ jsx(Fragment, { children: buildPageItems(pageIndex, pageCount).map((item) => {
|
|
13881
|
+
if (item.type === "gap") {
|
|
13882
|
+
return /* @__PURE__ */ jsx(
|
|
13883
|
+
"span",
|
|
13884
|
+
{
|
|
13885
|
+
"aria-hidden": "true",
|
|
13886
|
+
className: "flex h-8 w-8 items-center justify-center text-sm text-muted-foreground",
|
|
13887
|
+
children: "\u2026"
|
|
13888
|
+
},
|
|
13889
|
+
`gap-${item.key}`
|
|
13890
|
+
);
|
|
13891
|
+
}
|
|
13892
|
+
const page2 = item.pageIndex + 1;
|
|
13893
|
+
const isCurrent = item.pageIndex === pageIndex;
|
|
13894
|
+
return /* @__PURE__ */ jsx(
|
|
13895
|
+
Button,
|
|
13896
|
+
{
|
|
13897
|
+
bordered,
|
|
13898
|
+
variant: isCurrent ? "default" : "outline",
|
|
13899
|
+
className: cn(navButtonClass, "tabular-nums"),
|
|
13900
|
+
"aria-label": isCurrent ? labels.currentPage?.(page2) ?? `Page ${page2}, current page` : labels.goToPage?.(page2) ?? `Go to page ${page2}`,
|
|
13901
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
13902
|
+
onClick: () => onSelect(item.pageIndex),
|
|
13903
|
+
children: page2
|
|
13904
|
+
},
|
|
13905
|
+
item.pageIndex
|
|
13906
|
+
);
|
|
13907
|
+
}) });
|
|
13908
|
+
}
|
|
13863
13909
|
function NTablePagination() {
|
|
13864
13910
|
const table = useTableStore.use.table();
|
|
13865
13911
|
const showPagination = useTableStore.use.showPagination();
|
|
@@ -13876,7 +13922,9 @@ function NTablePagination() {
|
|
|
13876
13922
|
const setPagination = useTableStore.use.setPagination();
|
|
13877
13923
|
const isPaginationControlled = useTableStore.use.isPaginationControlled();
|
|
13878
13924
|
const bordered = useTableStore.use.bordered();
|
|
13879
|
-
|
|
13925
|
+
const paginationVariant = useTableStore.use.paginationVariant();
|
|
13926
|
+
const labels = useTableStore.use.paginationLabels();
|
|
13927
|
+
if (!showPagination || effectiveViewMode === "json" || effectiveViewMode === "files") return null;
|
|
13880
13928
|
if (cardPagination.mode === "all") return null;
|
|
13881
13929
|
if (effectiveViewMode === "cards" && cardPagination.mode === "infinite") return null;
|
|
13882
13930
|
if (effectiveViewMode === "cards" && cardPagination.mode === "load-more") {
|
|
@@ -13890,10 +13938,10 @@ function NTablePagination() {
|
|
|
13890
13938
|
}
|
|
13891
13939
|
);
|
|
13892
13940
|
}
|
|
13893
|
-
const filteredRows = table.getFilteredRowModel().rows;
|
|
13894
|
-
const selectedRows = table.getFilteredSelectedRowModel().rows;
|
|
13895
|
-
const { pageIndex, pageSize } = table.getState().pagination;
|
|
13896
|
-
const effectivePageCount = manualPagination && pageCount !== void 0 ? pageCount : table.getPageCount();
|
|
13941
|
+
const filteredRows = table ? table.getFilteredRowModel().rows : [];
|
|
13942
|
+
const selectedRows = table ? table.getFilteredSelectedRowModel().rows : [];
|
|
13943
|
+
const { pageIndex, pageSize } = table ? table.getState().pagination : pagination;
|
|
13944
|
+
const effectivePageCount = manualPagination && pageCount !== void 0 ? pageCount : table ? table.getPageCount() : 1;
|
|
13897
13945
|
const currentPagination = pagination ?? { pageIndex, pageSize };
|
|
13898
13946
|
const currentPageSizeOptions = pageSizeOptions.includes(pageSize) ? pageSizeOptions : [...pageSizeOptions, pageSize].sort((a, b) => a - b);
|
|
13899
13947
|
const navigate = (direction) => {
|
|
@@ -13918,10 +13966,15 @@ function NTablePagination() {
|
|
|
13918
13966
|
const newSize = Number(value);
|
|
13919
13967
|
setPagination({ pageIndex: 0, pageSize: newSize });
|
|
13920
13968
|
};
|
|
13969
|
+
const hasTrustworthyPageCount = manualPagination ? pageCount !== void 0 && pageCount > 0 : effectivePageCount > 0;
|
|
13970
|
+
const showNumbers = paginationVariant === "numbered" && hasTrustworthyPageCount;
|
|
13971
|
+
const canPrevious = (table?.getCanPreviousPage?.() ?? pageIndex > 0) && pageIndex > 0;
|
|
13972
|
+
const canNext = (table?.getCanNextPage?.() ?? true) && pageIndex < effectivePageCount - 1;
|
|
13973
|
+
const selectedTotal = manualPagination && rowCount !== void 0 ? rowCount : filteredRows.length;
|
|
13921
13974
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-2 py-1 text-foreground", classNames?.pagination), children: [
|
|
13922
13975
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-4 lg:gap-6", children: [
|
|
13923
13976
|
(!isPaginationControlled || manualPagination) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-foreground", children: [
|
|
13924
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "Rows/page" }),
|
|
13977
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: labels.rowsPerPage ?? "Rows/page" }),
|
|
13925
13978
|
/* @__PURE__ */ jsxs(Select, { value: `${pageSize}`, onValueChange: handlePageSizeChange, children: [
|
|
13926
13979
|
/* @__PURE__ */ jsx(
|
|
13927
13980
|
SelectTrigger,
|
|
@@ -13934,31 +13987,42 @@ function NTablePagination() {
|
|
|
13934
13987
|
/* @__PURE__ */ jsx(SelectContent, { side: "top", children: currentPageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: `${size}`, children: size }, size)) })
|
|
13935
13988
|
] })
|
|
13936
13989
|
] }),
|
|
13937
|
-
/* @__PURE__ */
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13990
|
+
/* @__PURE__ */ jsx("div", { className: cn("text-sm font-medium text-foreground", showNumbers && "sm:hidden"), children: labels.pageOf?.(pageIndex + 1, effectivePageCount) ?? `Page ${pageIndex + 1} of ${effectivePageCount}` }),
|
|
13991
|
+
/* @__PURE__ */ jsxs(
|
|
13992
|
+
"nav",
|
|
13993
|
+
{
|
|
13994
|
+
"aria-label": labels.pagination ?? "Pagination",
|
|
13995
|
+
className: "flex items-center gap-2",
|
|
13996
|
+
children: [
|
|
13997
|
+
!showNumbers && /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: cn(navButtonClass, "hidden lg:flex"), "aria-label": labels.firstPage ?? "First page", onClick: () => navigate("first"), disabled: !canPrevious, children: /* @__PURE__ */ jsx(ChevronsLeft, { className: chevronClass }) }),
|
|
13998
|
+
/* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: navButtonClass, "aria-label": labels.previousPage ?? "Previous", onClick: () => navigate("prev"), disabled: !canPrevious, children: /* @__PURE__ */ jsx(ChevronLeft, { className: chevronClass }) }),
|
|
13999
|
+
showNumbers && /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-2 sm:flex", children: /* @__PURE__ */ jsx(
|
|
14000
|
+
PageNumbers,
|
|
14001
|
+
{
|
|
14002
|
+
pageIndex,
|
|
14003
|
+
pageCount: effectivePageCount,
|
|
14004
|
+
bordered,
|
|
14005
|
+
labels,
|
|
14006
|
+
onSelect: (next) => setPagination({ ...currentPagination, pageIndex: next })
|
|
14007
|
+
}
|
|
14008
|
+
) }),
|
|
14009
|
+
/* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: navButtonClass, "aria-label": labels.nextPage ?? "Next", onClick: () => navigate("next"), disabled: !canNext, children: /* @__PURE__ */ jsx(ChevronRight, { className: chevronClass }) }),
|
|
14010
|
+
!showNumbers && /* @__PURE__ */ jsx(Button, { bordered, variant: "outline", className: cn(navButtonClass, "hidden lg:flex"), "aria-label": labels.lastPage ?? "Last page", onClick: () => navigate("last"), disabled: !canNext, children: /* @__PURE__ */ jsx(ChevronsRight, { className: chevronClass }) })
|
|
14011
|
+
]
|
|
14012
|
+
}
|
|
14013
|
+
)
|
|
13949
14014
|
] }),
|
|
13950
|
-
/* @__PURE__ */
|
|
13951
|
-
selectedRows.length,
|
|
13952
|
-
" of ",
|
|
13953
|
-
manualPagination && rowCount !== void 0 ? rowCount : filteredRows.length,
|
|
13954
|
-
" row(s) selected."
|
|
13955
|
-
] })
|
|
14015
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-none whitespace-nowrap text-sm text-muted-foreground max-sm:hidden", children: labels.rowsSelected?.(selectedRows.length, selectedTotal) ?? `${selectedRows.length} of ${selectedTotal} row(s) selected.` })
|
|
13956
14016
|
] });
|
|
13957
14017
|
}
|
|
14018
|
+
function PendingFilter({ placeholder, icon, bordered }) {
|
|
14019
|
+
return /* @__PURE__ */ jsx(TextInput, { icon, value: "", onChange: () => {
|
|
14020
|
+
}, placeholder, bordered, disabled: true });
|
|
14021
|
+
}
|
|
13958
14022
|
function SearchFilter({ placeholder }) {
|
|
13959
14023
|
const table = useTableStore.use.table();
|
|
13960
14024
|
const bordered = useTableStore.use.bordered();
|
|
13961
|
-
if (!table) return
|
|
14025
|
+
if (!table) return /* @__PURE__ */ jsx(PendingFilter, { icon: Search, placeholder: placeholder ?? "Search\u2026", bordered });
|
|
13962
14026
|
const value = table.getState().globalFilter ?? "";
|
|
13963
14027
|
return /* @__PURE__ */ jsx(TextInput, { icon: Search, value, onChange: (v) => table.setGlobalFilter(v), placeholder: placeholder ?? "Search\u2026", bordered });
|
|
13964
14028
|
}
|
|
@@ -13966,14 +14030,14 @@ function TextFilter({ name, placeholder, icon }) {
|
|
|
13966
14030
|
const table = useTableStore.use.table();
|
|
13967
14031
|
const bordered = useTableStore.use.bordered();
|
|
13968
14032
|
const column = table?.getColumn?.(name);
|
|
13969
|
-
if (!column) return
|
|
14033
|
+
if (!column) return /* @__PURE__ */ jsx(PendingFilter, { icon, placeholder, bordered });
|
|
13970
14034
|
return /* @__PURE__ */ jsx(TextInput, { icon, value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value), placeholder, bordered });
|
|
13971
14035
|
}
|
|
13972
14036
|
function SelectFilter({ name, options, placeholder, inputType }) {
|
|
13973
14037
|
const table = useTableStore.use.table();
|
|
13974
14038
|
const bordered = useTableStore.use.bordered();
|
|
13975
14039
|
const column = table?.getColumn?.(name);
|
|
13976
|
-
if (!column) return
|
|
14040
|
+
if (!column) return /* @__PURE__ */ jsx(PendingFilter, { placeholder: placeholder || "Filter...", bordered });
|
|
13977
14041
|
const allOptions = [{ value: "__clear__", label: "All" }, ...options.map((o) => typeof o === "string" ? { value: o, label: o } : o)];
|
|
13978
14042
|
const InputComponent = inputType === "combobox" ? ComboboxInput : SelectInput;
|
|
13979
14043
|
return /* @__PURE__ */ jsx(InputComponent, { value: column.getFilterValue() ?? "", onChange: (value) => column.setFilterValue(value === "" || value === "__clear__" ? void 0 : value), items: allOptions, placeholder: placeholder || "Filter...", bordered });
|
|
@@ -13982,7 +14046,7 @@ function defaultWrapperClass(filter) {
|
|
|
13982
14046
|
return filter.type === "search" ? "flex-1 min-w-[160px] max-w-sm" : "w-full sm:w-40 xl:w-56 shrink-0";
|
|
13983
14047
|
}
|
|
13984
14048
|
function RenderFilter({ filter, mobilePrimary = false }) {
|
|
13985
|
-
|
|
14049
|
+
useTableStore.use.table();
|
|
13986
14050
|
const bordered = useTableStore.use.bordered();
|
|
13987
14051
|
if (filter.type === "search") {
|
|
13988
14052
|
return /* @__PURE__ */ jsx(SearchFilter, { placeholder: filter.placeholder });
|
|
@@ -14049,20 +14113,24 @@ function RenderFilter({ filter, mobilePrimary = false }) {
|
|
|
14049
14113
|
if (filter.type === "text") {
|
|
14050
14114
|
return /* @__PURE__ */ jsx(TextFilter, { name: filter.name, placeholder: filter.placeholder, icon: mobilePrimary ? Search : void 0 });
|
|
14051
14115
|
}
|
|
14052
|
-
if (!table) return null;
|
|
14053
14116
|
return /* @__PURE__ */ jsx(SelectFilter, { name: filter.name, options: filter.options || [], placeholder: filter.placeholder, inputType: filter.type });
|
|
14054
14117
|
}
|
|
14055
14118
|
function TableFilters() {
|
|
14056
14119
|
const filters = useTableStore.use.filters();
|
|
14057
14120
|
if (!filters?.length) return null;
|
|
14058
|
-
return
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14065
|
-
|
|
14121
|
+
return (
|
|
14122
|
+
// `min-h-10` is the height of one control row. Even if every filter inside
|
|
14123
|
+
// resolves to nothing, the row cannot collapse and change what the body
|
|
14124
|
+
// measures.
|
|
14125
|
+
/* @__PURE__ */ jsx("div", { "data-ntable-desktop-filters": true, className: "hidden min-h-10 flex-1 min-w-0 flex-wrap items-center gap-2 md:flex", children: filters.map((filter) => /* @__PURE__ */ jsx(
|
|
14126
|
+
"div",
|
|
14127
|
+
{
|
|
14128
|
+
className: cn(defaultWrapperClass(filter), filter.className),
|
|
14129
|
+
children: /* @__PURE__ */ jsx(RenderFilter, { filter })
|
|
14130
|
+
},
|
|
14131
|
+
filter.name
|
|
14132
|
+
)) })
|
|
14133
|
+
);
|
|
14066
14134
|
}
|
|
14067
14135
|
function TableAddButton({ mobile = false }) {
|
|
14068
14136
|
const onAddClick = useTableStore.use.onAddClick();
|
|
@@ -14213,12 +14281,14 @@ function NTableHeader() {
|
|
|
14213
14281
|
const isCustomMode = useTableStore.use.isCustomMode();
|
|
14214
14282
|
const showViewToggle = useTableStore.use.showViewToggle();
|
|
14215
14283
|
const showColumnVisibility = useTableStore.use.showColumnVisibility();
|
|
14216
|
-
const hideDataChrome =
|
|
14284
|
+
const hideDataChrome = error || hasNoData && !isFilteredEmpty && !isLoading;
|
|
14285
|
+
const isFirstLoad = Boolean(isLoading) && !isRefreshing;
|
|
14286
|
+
const firstLoadChromeClass = isFirstLoad ? "pointer-events-none opacity-60" : void 0;
|
|
14217
14287
|
if (isCustomMode) {
|
|
14218
14288
|
if (!showViewToggle && !showColumnVisibility && !headerSlot && !hasControls) return null;
|
|
14219
14289
|
if (hideDataChrome) return null;
|
|
14220
14290
|
const justify2 = headerSlot ? "justify-between" : "justify-end";
|
|
14221
|
-
return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, className: cn("flex shrink-0 items-center gap-0 lg:gap-3 flex-wrap lg:flex-nowrap", justify2, classNames?.header), children: [
|
|
14291
|
+
return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, "aria-busy": isFirstLoad ? "true" : void 0, className: cn("flex shrink-0 items-center gap-0 lg:gap-3 flex-wrap lg:flex-nowrap", justify2, firstLoadChromeClass, classNames?.header), children: [
|
|
14222
14292
|
headerSlot && /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: headerSlot }),
|
|
14223
14293
|
hasControls && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 shrink-0", children: [
|
|
14224
14294
|
/* @__PURE__ */ jsx("span", { className: "hidden md:contents", children: /* @__PURE__ */ jsx(TableSettingsMenu, {}) }),
|
|
@@ -14231,7 +14301,7 @@ function NTableHeader() {
|
|
|
14231
14301
|
if (!hasFilters && !hasControls && !headerSlot && !hasToolbar) return null;
|
|
14232
14302
|
if (hideDataChrome) return null;
|
|
14233
14303
|
const justify = hasControls || headerSlot || hasToolbar ? "justify-between" : "justify-start";
|
|
14234
|
-
return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, className: cn("flex shrink-0 items-center gap-0 lg:gap-3 flex-wrap lg:flex-nowrap", justify, classNames?.header), children: [
|
|
14304
|
+
return /* @__PURE__ */ jsxs("div", { "data-ntable-header": true, "aria-busy": isFirstLoad ? "true" : void 0, className: cn("flex shrink-0 items-center gap-0 lg:gap-3 flex-wrap lg:flex-nowrap", justify, firstLoadChromeClass, classNames?.header), children: [
|
|
14235
14305
|
/* @__PURE__ */ jsx(TableFilters, {}),
|
|
14236
14306
|
/* @__PURE__ */ jsx(TableMobileToolbar, {}),
|
|
14237
14307
|
headerSlot && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: headerSlot }),
|
|
@@ -14342,12 +14412,27 @@ function TableLayout(props) {
|
|
|
14342
14412
|
"data-ntable-body": true,
|
|
14343
14413
|
"data-ntable-refreshing": isRefreshing ? "true" : void 0,
|
|
14344
14414
|
"aria-busy": isRefreshing ? "true" : void 0,
|
|
14345
|
-
className: "flex min-h-0 flex-1 flex-col gap-2 overflow-hidden",
|
|
14415
|
+
className: "relative flex min-h-0 flex-1 flex-col gap-2 overflow-hidden",
|
|
14346
14416
|
children: isCustomMode ? customRenderer ? customRenderer() : null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14347
|
-
isLoading && !isRefreshing &&
|
|
14348
|
-
|
|
14349
|
-
|
|
14350
|
-
|
|
14417
|
+
isLoading && !isRefreshing && // Absolutely positioned, the way every grid that measures its own
|
|
14418
|
+
// page size does it: AG Grid paints its loading state as an
|
|
14419
|
+
// overlay, and MUI's DataGrid renders `GridOverlay` on top of the
|
|
14420
|
+
// rows rather than in place of them. A skeleton that occupies a
|
|
14421
|
+
// slot in the layout is a second layout — the one the container
|
|
14422
|
+
// gets measured in — and the page size derived from it is a page
|
|
14423
|
+
// size for a table that no longer exists once rows land. Taking
|
|
14424
|
+
// the skeleton out of flow leaves exactly one layout to measure.
|
|
14425
|
+
/* @__PURE__ */ jsx(
|
|
14426
|
+
"div",
|
|
14427
|
+
{
|
|
14428
|
+
"data-ntable-loading-overlay": true,
|
|
14429
|
+
className: "absolute inset-0 z-10 flex min-h-0 flex-col bg-background",
|
|
14430
|
+
children: props.renderLoading ? /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderLoading() }) : props.responsiveSkeleton ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14431
|
+
/* @__PURE__ */ jsx("div", { "data-ntable-skeleton-variant": "table", className: "hidden min-h-0 flex-1 flex-col lg:flex", children: /* @__PURE__ */ jsx(NTableLoadingSkeleton, {}) }),
|
|
14432
|
+
/* @__PURE__ */ jsx("div", { "data-ntable-skeleton-variant": "cards", className: "flex min-h-0 flex-1 flex-col lg:hidden", children: /* @__PURE__ */ jsx(NTableCardsLoadingSkeleton, {}) })
|
|
14433
|
+
] }) : effectiveMode === "cards" ? /* @__PURE__ */ jsx(NTableCardsLoadingSkeleton, {}) : /* @__PURE__ */ jsx(NTableLoadingSkeleton, {})
|
|
14434
|
+
}
|
|
14435
|
+
),
|
|
14351
14436
|
error && !isLoading && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderError ? props.renderError(error) : /* @__PURE__ */ jsx(NErrorState, { message: typeof error === "string" ? error : "An error occurred" }) }),
|
|
14352
14437
|
showFilteredEmpty && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderFilteredEmpty ? props.renderFilteredEmpty() : renderFilteredEmpty ? renderFilteredEmpty() : props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(DefaultTableFilteredEmptyState, {}) }),
|
|
14353
14438
|
showEmpty && /* @__PURE__ */ jsx(TableStateSlot, { children: props.renderEmpty ? props.renderEmpty() : /* @__PURE__ */ jsx(DefaultTableEmptyState, { title: noDataText }) }),
|
|
@@ -14515,6 +14600,8 @@ function NTable(props) {
|
|
|
14515
14600
|
defaultPagination: props.defaultPagination,
|
|
14516
14601
|
onPaginationChange: props.onPaginationChange ?? null,
|
|
14517
14602
|
cardPagination: props.cardPagination ?? { mode: "paged" },
|
|
14603
|
+
paginationVariant: props.paginationVariant ?? "numbered",
|
|
14604
|
+
paginationLabels: props.paginationLabels ?? {},
|
|
14518
14605
|
// Row selection
|
|
14519
14606
|
rowSelection: props.rowSelection,
|
|
14520
14607
|
defaultRowSelection: props.defaultRowSelection,
|