@pallasoft/ps-table-components 1.27.0 → 1.28.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/dist/components/ps-data-table.d.ts +3 -1
- package/dist/components/ps-data-table.js +18 -44
- package/dist/components/ps-table-pagination.js +2 -2
- package/dist/components/ps-table-toolbar.js +1 -1
- package/dist/constants/ps-table-pagination-config.d.ts +3 -0
- package/dist/constants/ps-table-pagination-config.js +6 -0
- package/dist/esm/components/ps-data-table.js +19 -45
- package/dist/esm/components/ps-table-pagination.js +2 -2
- package/dist/esm/components/ps-table-toolbar.js +1 -1
- package/dist/esm/constants/ps-table-pagination-config.js +3 -0
- package/dist/esm/hooks/use-ps-sticky-head.js +82 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/interfaces/ps-scroll-timeline-options.js +1 -0
- package/dist/esm/interfaces/ps-scroll-timeline-window.js +1 -0
- package/dist/esm/interfaces/ps-sticky-head-refs.js +1 -0
- package/dist/esm/interfaces/ps-table-sticky-head-keyframe.js +1 -0
- package/dist/esm/services/ps-table-sticky-head-service.js +17 -0
- package/dist/hooks/use-ps-sticky-head.d.ts +2 -0
- package/dist/hooks/use-ps-sticky-head.js +86 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/interfaces/ps-scroll-timeline-options.d.ts +4 -0
- package/dist/interfaces/ps-scroll-timeline-options.js +2 -0
- package/dist/interfaces/ps-scroll-timeline-window.d.ts +4 -0
- package/dist/interfaces/ps-scroll-timeline-window.js +2 -0
- package/dist/interfaces/ps-sticky-head-refs.d.ts +9 -0
- package/dist/interfaces/ps-sticky-head-refs.js +2 -0
- package/dist/interfaces/ps-table-sticky-head-keyframe.d.ts +4 -0
- package/dist/interfaces/ps-table-sticky-head-keyframe.js +2 -0
- package/dist/services/ps-table-sticky-head-service.d.ts +5 -0
- package/dist/services/ps-table-sticky-head-service.js +21 -0
- package/package.json +1 -1
|
@@ -42,8 +42,10 @@ export interface PsDataTableProps<RowData> {
|
|
|
42
42
|
searchingLabel?: string;
|
|
43
43
|
searchPlaceholder?: string;
|
|
44
44
|
selectAllMatching?: PsTableSelectAllMatching;
|
|
45
|
+
stickyClassName?: string;
|
|
46
|
+
stickyLeading?: ReactNode;
|
|
45
47
|
stickyTop?: string;
|
|
46
48
|
toolbarActions?: ReactNode;
|
|
47
49
|
totalRows?: number;
|
|
48
50
|
}
|
|
49
|
-
export declare const PsDataTable: <RowData>({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density, expandedRowIds, mobileLayout, getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading, isPending, isRefreshing, layout, onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition, pinFirstColumn, query, renderExpandedRow, reorder, rows, searchingLabel, searchPlaceholder, selectAllMatching, stickyTop, toolbarActions, totalRows, }: PsDataTableProps<RowData>) => import("react").JSX.Element;
|
|
51
|
+
export declare const PsDataTable: <RowData>({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density, expandedRowIds, mobileLayout, getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading, isPending, isRefreshing, layout, onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition, pinFirstColumn, query, renderExpandedRow, reorder, rows, searchingLabel, searchPlaceholder, selectAllMatching, stickyClassName, stickyLeading, stickyTop, toolbarActions, totalRows, }: PsDataTableProps<RowData>) => import("react").JSX.Element;
|
|
@@ -42,11 +42,13 @@ const ps_input_components_1 = require("@pallasoft/ps-input-components");
|
|
|
42
42
|
const ps_motion_components_1 = require("@pallasoft/ps-motion-components");
|
|
43
43
|
const react_virtual_1 = require("@tanstack/react-virtual");
|
|
44
44
|
const ps_table_control_classes_1 = require("../constants/ps-table-control-classes");
|
|
45
|
+
const ps_table_pagination_config_1 = require("../constants/ps-table-pagination-config");
|
|
45
46
|
const ps_table_pagination_position_1 = require("../constants/ps-table-pagination-position");
|
|
46
47
|
const table_breakpoint_1 = require("../constants/table-breakpoint");
|
|
47
48
|
const table_config_1 = require("../constants/table-config");
|
|
48
49
|
const use_ps_incremental_count_1 = require("../hooks/use-ps-incremental-count");
|
|
49
50
|
const use_ps_scroll_anchor_1 = require("../hooks/use-ps-scroll-anchor");
|
|
51
|
+
const use_ps_sticky_head_1 = require("../hooks/use-ps-sticky-head");
|
|
50
52
|
const use_ps_table_overflow_1 = require("../hooks/use-ps-table-overflow");
|
|
51
53
|
const use_ps_table_stream_status_1 = require("../hooks/use-ps-table-stream-status");
|
|
52
54
|
const ps_table_cell_tooltip_service_1 = require("../services/ps-table-cell-tooltip-service");
|
|
@@ -86,7 +88,7 @@ const alignClassNames = {
|
|
|
86
88
|
left: 'text-left',
|
|
87
89
|
right: 'text-right tabular-nums',
|
|
88
90
|
};
|
|
89
|
-
const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density = 'normal', expandedRowIds, mobileLayout = 'cards', getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading = false, isPending = false, isRefreshing = false, layout = 'auto', onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition = ps_table_pagination_position_1.PsTablePaginationPosition.bottom, pinFirstColumn = true, query, renderExpandedRow, reorder, rows, searchingLabel = table_config_1.PsTableConfig.searchingLabel, searchPlaceholder = table_config_1.PsTableConfig.searchPlaceholder, selectAllMatching, stickyTop, toolbarActions, totalRows, }) => {
|
|
91
|
+
const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density = 'normal', expandedRowIds, mobileLayout = 'cards', getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading = false, isPending = false, isRefreshing = false, layout = 'auto', onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition = ps_table_pagination_position_1.PsTablePaginationPosition.bottom, pinFirstColumn = true, query, renderExpandedRow, reorder, rows, searchingLabel = table_config_1.PsTableConfig.searchingLabel, searchPlaceholder = table_config_1.PsTableConfig.searchPlaceholder, selectAllMatching, stickyClassName, stickyLeading, stickyTop, toolbarActions, totalRows, }) => {
|
|
90
92
|
const containerRef = (0, react_1.useRef)(null);
|
|
91
93
|
const [uncontrolledPage, setUncontrolledPage] = (0, react_1.useState)(1);
|
|
92
94
|
const [uncontrolledQuery, setUncontrolledQuery] = (0, react_1.useState)(() => ps_table_query_service_1.PsTableQueryService.empty(defaultSort ? defaultSort : null));
|
|
@@ -97,47 +99,13 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
|
|
|
97
99
|
const [seenClearKey, setSeenClearKey] = (0, react_1.useState)(clearSelectionKey);
|
|
98
100
|
const stickyRegionRef = (0, react_1.useRef)(null);
|
|
99
101
|
const stickySentinelRef = (0, react_1.useRef)(null);
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
+
const stickyBackdropRef = (0, react_1.useRef)(null);
|
|
103
|
+
const stickyHeadRef = (0, react_1.useRef)(null);
|
|
102
104
|
const currentQuery = query ? query : uncontrolledQuery;
|
|
103
105
|
if (seenClearKey !== clearSelectionKey) {
|
|
104
106
|
setSeenClearKey(clearSelectionKey);
|
|
105
107
|
setSelectedIds([]);
|
|
106
108
|
}
|
|
107
|
-
(0, react_1.useLayoutEffect)(() => {
|
|
108
|
-
const region = stickyRegionRef.current;
|
|
109
|
-
if (stickyTop === undefined || region === null)
|
|
110
|
-
return;
|
|
111
|
-
const measure = () => setStickyHeight(region.offsetHeight);
|
|
112
|
-
const observer = new ResizeObserver(measure);
|
|
113
|
-
measure();
|
|
114
|
-
observer.observe(region);
|
|
115
|
-
return () => observer.disconnect();
|
|
116
|
-
}, [stickyTop]);
|
|
117
|
-
(0, react_1.useEffect)(() => {
|
|
118
|
-
const region = stickyRegionRef.current;
|
|
119
|
-
const sentinel = stickySentinelRef.current;
|
|
120
|
-
if (stickyTop === undefined || region === null || sentinel === null)
|
|
121
|
-
return;
|
|
122
|
-
let frame = 0;
|
|
123
|
-
const check = () => {
|
|
124
|
-
frame = 0;
|
|
125
|
-
setIsStuck(sentinel.getBoundingClientRect().top < Number.parseFloat(getComputedStyle(region).top));
|
|
126
|
-
};
|
|
127
|
-
const schedule = () => {
|
|
128
|
-
if (frame === 0)
|
|
129
|
-
frame = window.requestAnimationFrame(check);
|
|
130
|
-
};
|
|
131
|
-
check();
|
|
132
|
-
window.addEventListener('scroll', schedule, { passive: true });
|
|
133
|
-
window.addEventListener('resize', schedule);
|
|
134
|
-
return () => {
|
|
135
|
-
window.removeEventListener('scroll', schedule);
|
|
136
|
-
window.removeEventListener('resize', schedule);
|
|
137
|
-
if (frame !== 0)
|
|
138
|
-
window.cancelAnimationFrame(frame);
|
|
139
|
-
};
|
|
140
|
-
}, [stickyTop]);
|
|
141
109
|
const { filters, hiddenColumnIds, search, sort } = currentQuery;
|
|
142
110
|
const visibleColumns = columns.filter((column) => !hiddenColumnIds.includes(column.id));
|
|
143
111
|
const fittedWidths = (0, react_1.useMemo)(() => new Map(columns
|
|
@@ -160,6 +128,14 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
|
|
|
160
128
|
const pins = ps_table_pin_service_1.PsTablePinService.leading(pinFirstColumn, Boolean(reorder), isSelectable);
|
|
161
129
|
const placementOf = (column, columnIndex) => ps_design_system_1.PallasoftClassNameService.merge(column.hideBelow === undefined ? '' : table_breakpoint_1.PsTableHideBelowClasses[column.hideBelow], columnIndex === 0 ? pins.first : '', ps_table_pin_service_1.PsTablePinService.end(column.pinEnd === true));
|
|
162
130
|
const overflow = (0, use_ps_table_overflow_1.usePsTableOverflow)(`${visibleColumns.map((column) => column.id).join(',')}:${rows.length}`);
|
|
131
|
+
const isStuck = (0, use_ps_sticky_head_1.usePsStickyHead)({
|
|
132
|
+
backdropRef: stickyBackdropRef,
|
|
133
|
+
headRef: stickyHeadRef,
|
|
134
|
+
layoutKey: `${visibleColumns.map((column) => column.id).join(',')}:${rows.length}:${isLoading}`,
|
|
135
|
+
regionRef: stickyRegionRef,
|
|
136
|
+
sentinelRef: stickySentinelRef,
|
|
137
|
+
stickyTop,
|
|
138
|
+
});
|
|
163
139
|
const deferredSearch = (0, react_1.useDeferredValue)(search);
|
|
164
140
|
const queriedRows = (0, react_1.useMemo)(() => isServerPaginated
|
|
165
141
|
? rows
|
|
@@ -420,7 +396,9 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
|
|
|
420
396
|
updateQuery({ search: next });
|
|
421
397
|
resetPage();
|
|
422
398
|
}, rows: rows, search: search, searchPlaceholder: searchPlaceholder })) : null, banner] }));
|
|
423
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3', className), children: [stickyTop === undefined ? (topContent) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: '-mb-3 h-0', ref: stickySentinelRef }), (0, jsx_runtime_1.
|
|
399
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3', className), children: [stickyTop === undefined ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [stickyLeading, topContent] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: '-mb-3 h-0', ref: stickySentinelRef }), (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('sticky z-sticky flex flex-col gap-3', stickyClassName), "data-stuck": isStuck, ref: stickyRegionRef, style: { top: stickyTop }, children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('ps-glass-strong pointer-events-none absolute -inset-x-3 -bottom-3 rounded-b-ps-card border-t-0 transition-opacity duration-150', isStuck ? 'opacity-100' : 'opacity-0'), ref: stickyBackdropRef, style: { top: `calc(-1 * ${stickyTop})` } }), (0, jsx_runtime_1.jsxs)("div", { className: 'relative flex flex-col gap-3', children: [stickyLeading, topContent] })] })] })), (0, jsx_runtime_1.jsxs)("div", { "aria-busy": isRefreshing, className: 'min-w-0 overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [showsPagination &&
|
|
400
|
+
paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.bottom &&
|
|
401
|
+
rowCount > ps_table_pagination_config_1.PsTablePaginationConfig.topMinRows
|
|
424
402
|
? renderPagination('border-b border-t-0')
|
|
425
403
|
: null, mobileLayout === 'cards' ? ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('transition-opacity duration-150 sm:hidden', isRefreshing ? 'opacity-60' : ''), children: [reorder && reorder.cardsReason ? ((0, jsx_runtime_1.jsx)("p", { className: 'border-b border-line px-4 py-2 text-xs text-ink/55', children: reorder.cardsReason })) : null, grouping
|
|
426
404
|
? groups.map((group, groupIndex) => {
|
|
@@ -429,13 +407,9 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
|
|
|
429
407
|
? grouping.renderGroupSummary(group.rows)
|
|
430
408
|
: undefined }), (0, jsx_runtime_1.jsx)(ps_motion_components_1.PsCollapse, { isOpen: isExpanded && !closingGroupKeys.includes(group.key), children: renderCardList(group.rows, null) })] }, `group-${group.key}`));
|
|
431
409
|
})
|
|
432
|
-
: renderCardList(shouldVirtualize ? visibleRows.slice(0, cards.count) : visibleRows, visibleRows.length === 0 && isSearching ? ((0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { label: searchingLabel, skeletonRows: table_config_1.PsTableConfig.searchingSkeletonRows })) : visibleRows.length === 0 && isQueried ? ((0, jsx_runtime_1.jsxs)("div", { className: 'px-4 py-10 text-center', children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-sm font-semibold text-ink', children: table_config_1.PsTableConfig.noMatchesTitle }), (0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'mt-2 text-primary'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] })) : null), !grouping && shouldVirtualize && cards.count < visibleRows.length ? ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: 'h-px', ref: cards.sentinelRef })) : null] })) : null, (0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge(stickyTop === undefined
|
|
433
|
-
? 'ps-scrollbar overflow-x-auto overflow-y-hidden overscroll-x-contain'
|
|
434
|
-
: 'overflow-x-clip', 'transition-opacity duration-150', isRefreshing ? 'opacity-60' : '', mobileLayout === 'cards' ? 'hidden sm:block' : ''), "data-overflow-end": overflow.edges.end, "data-overflow-start": overflow.edges.start, onScroll: overflow.update, ref: overflow.ref, children: renderReorder((api) => ((0, jsx_runtime_1.jsxs)("table", { className: ps_design_system_1.PallasoftClassNameService.merge('w-full border-collapse text-left', layout === 'fixed' ? 'table-fixed' : ''), children: [caption ? (0, jsx_runtime_1.jsx)("caption", { className: 'sr-only', children: caption }) : null, (0, jsx_runtime_1.jsx)("thead", { className: ps_design_system_1.PallasoftClassNameService.merge('bg-mist/70 text-[0.68rem] font-semibold uppercase tracking-[0.18em] text-ink/45', stickyTop === undefined
|
|
410
|
+
: renderCardList(shouldVirtualize ? visibleRows.slice(0, cards.count) : visibleRows, visibleRows.length === 0 && isSearching ? ((0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { label: searchingLabel, skeletonRows: table_config_1.PsTableConfig.searchingSkeletonRows })) : visibleRows.length === 0 && isQueried ? ((0, jsx_runtime_1.jsxs)("div", { className: 'px-4 py-10 text-center', children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-sm font-semibold text-ink', children: table_config_1.PsTableConfig.noMatchesTitle }), (0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'mt-2 text-primary'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] })) : null), !grouping && shouldVirtualize && cards.count < visibleRows.length ? ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: 'h-px', ref: cards.sentinelRef })) : null] })) : null, (0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar overflow-x-auto overflow-y-hidden overscroll-x-contain', 'transition-opacity duration-150', isRefreshing ? 'opacity-60' : '', mobileLayout === 'cards' ? 'hidden sm:block' : ''), "data-overflow-end": overflow.edges.end, "data-overflow-start": overflow.edges.start, onScroll: overflow.update, ref: overflow.ref, children: renderReorder((api) => ((0, jsx_runtime_1.jsxs)("table", { className: ps_design_system_1.PallasoftClassNameService.merge('w-full border-collapse text-left', layout === 'fixed' ? 'table-fixed' : ''), children: [caption ? (0, jsx_runtime_1.jsx)("caption", { className: 'sr-only', children: caption }) : null, (0, jsx_runtime_1.jsx)("thead", { className: ps_design_system_1.PallasoftClassNameService.merge('bg-mist/70 text-[0.68rem] font-semibold uppercase tracking-[0.18em] text-ink/45', stickyTop === undefined
|
|
435
411
|
? ''
|
|
436
|
-
: '
|
|
437
|
-
? undefined
|
|
438
|
-
: { top: `calc(${stickyTop} + ${stickyHeight}px)` }, children: (0, jsx_runtime_1.jsxs)("tr", { children: [reorder ? ((0, jsx_runtime_1.jsx)("th", { className: ps_design_system_1.PallasoftClassNameService.merge('w-9 min-w-9 pl-3 pr-0', pins.reorder), scope: 'col', children: reorder.enabled ? ((0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: reorder.columnLabel })) : reorder.disabledReason ? ((0, jsx_runtime_1.jsx)("span", { "aria-label": reorder.disabledReason, className: 'inline-flex cursor-help opacity-40', role: 'img', title: reorder.disabledReason, children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsDragGrip, {}) })) : null })) : null, isSelectable ? ((0, jsx_runtime_1.jsx)("th", { className: ps_design_system_1.PallasoftClassNameService.merge('w-10 min-w-10 pl-4 pr-0', pins.select), scope: 'col', children: (0, jsx_runtime_1.jsx)(ps_input_components_1.PsCheckbox, { isIndeterminate: !isPageSelected && pageIds.some((rowId) => selectedIdSet.has(rowId)), isSelected: isPageSelected, label: 'Select all rows on this page', onChange: togglePage }) })) : null, visibleColumns.map((column, columnIndex) => {
|
|
412
|
+
: 'relative z-docked bg-surface will-change-transform [&_th]:border-b [&_th]:border-line [&>tr]:bg-mist/70'), ref: stickyHeadRef, children: (0, jsx_runtime_1.jsxs)("tr", { children: [reorder ? ((0, jsx_runtime_1.jsx)("th", { className: ps_design_system_1.PallasoftClassNameService.merge('w-9 min-w-9 pl-3 pr-0', pins.reorder), scope: 'col', children: reorder.enabled ? ((0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: reorder.columnLabel })) : reorder.disabledReason ? ((0, jsx_runtime_1.jsx)("span", { "aria-label": reorder.disabledReason, className: 'inline-flex cursor-help opacity-40', role: 'img', title: reorder.disabledReason, children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsDragGrip, {}) })) : null })) : null, isSelectable ? ((0, jsx_runtime_1.jsx)("th", { className: ps_design_system_1.PallasoftClassNameService.merge('w-10 min-w-10 pl-4 pr-0', pins.select), scope: 'col', children: (0, jsx_runtime_1.jsx)(ps_input_components_1.PsCheckbox, { isIndeterminate: !isPageSelected && pageIds.some((rowId) => selectedIdSet.has(rowId)), isSelected: isPageSelected, label: 'Select all rows on this page', onChange: togglePage }) })) : null, visibleColumns.map((column, columnIndex) => {
|
|
439
413
|
const align = column.align !== null && column.align !== undefined ? column.align : 'left';
|
|
440
414
|
const isSorted = sort !== null && sort.columnId === column.id;
|
|
441
415
|
return ((0, jsx_runtime_1.jsx)("th", { "aria-sort": isSorted
|
|
@@ -11,11 +11,11 @@ const PsTablePagination = ({ className, cursor, isPartial = false, loadedPageCou
|
|
|
11
11
|
const pageNumber = cursor === undefined ? Math.min(page, pageCount) : cursor.pageNumber;
|
|
12
12
|
const cursorFirst = cursor === undefined ? firstRow : (cursor.pageNumber - 1) * pageSize + 1;
|
|
13
13
|
const cursorLast = cursor === undefined ? lastRow : Math.min(cursor.pageNumber * pageSize, totalRows);
|
|
14
|
-
return ((0, jsx_runtime_1.jsxs)("nav", { "aria-label": 'Pagination', className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-wrap items-center justify-between gap-3 border-t border-line px-
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)("nav", { "aria-label": 'Pagination', className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-wrap items-center justify-between gap-x-6 gap-y-3 border-t border-line px-5 py-3', className), children: [(0, jsx_runtime_1.jsx)("p", { className: 'shrink-0 whitespace-nowrap text-sm text-ink/55', children: totalRows === 0
|
|
15
15
|
? 'No rows'
|
|
16
16
|
: cursor === undefined
|
|
17
17
|
? `${firstRow}–${lastRow} of ${totalRows}${isPartial ? '+' : ''}`
|
|
18
|
-
: `${cursorFirst}–${cursorLast} of ${approximately}${totalRows.toLocaleString()}` }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex items-center gap-
|
|
18
|
+
: `${cursorFirst}–${cursorLast} of ${approximately}${totalRows.toLocaleString()}` }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex shrink-0 items-center gap-3', children: [cursor !== undefined && cursor.pageSizeOptions !== undefined && cursor.onPageSizeChange ? ((0, jsx_runtime_1.jsxs)("label", { className: 'flex shrink-0 items-center gap-2 whitespace-nowrap text-sm text-ink/65', children: [(0, jsx_runtime_1.jsx)("span", { className: 'hidden sm:inline', children: "Rows per page" }), (0, jsx_runtime_1.jsx)("select", { "aria-label": 'Rows per page', className: 'ps-input-control ps-focus-ring ps-control ps-control-padding w-auto shrink-0 rounded-ps-control text-sm', onChange: (event) => cursor.onPageSizeChange?.(Number(event.target.value)), value: pageSize, children: cursor.pageSizeOptions.map((option) => ((0, jsx_runtime_1.jsx)("option", { value: option, children: option }, option))) })] })) : null, (0, jsx_runtime_1.jsx)("button", { className: ps_table_control_classes_1.PsTableControlClasses.paginationButton, disabled: cursor === undefined ? page <= 1 : !cursor.hasPrevious, onClick: () => (cursor === undefined ? onPageChange(page - 1) : cursor.onPrevious()), type: 'button', children: "Previous" }), (0, jsx_runtime_1.jsxs)("span", { className: 'hidden whitespace-nowrap text-sm text-ink/65 sm:inline', children: ["Page ", pageNumber, " of ", approximately, pageCount] }), (0, jsx_runtime_1.jsx)("button", { className: ps_table_control_classes_1.PsTableControlClasses.paginationButton, disabled: cursor === undefined
|
|
19
19
|
? page >=
|
|
20
20
|
(loadedPageCount === undefined ? pageCount : Math.min(loadedPageCount, pageCount))
|
|
21
21
|
: !cursor.hasNext, onClick: () => (cursor === undefined ? onPageChange(page + 1) : cursor.onNext()), onFocus: cursor === undefined ? undefined : cursor.onNextIntent, onPointerEnter: cursor === undefined ? undefined : cursor.onNextIntent, type: 'button', children: "Next" })] })] }));
|
|
@@ -13,6 +13,6 @@ const PsTableToolbar = ({ actions, columns, filters, isSearchable, onClearFilter
|
|
|
13
13
|
const filterableColumns = columns.filter((column) => column.filter);
|
|
14
14
|
const zIndex = (0, ps_core_components_1.usePsLayerZIndex)(ps_design_system_1.PallasoftZIndex.Dropdown);
|
|
15
15
|
const activeCount = filterableColumns.filter((column) => ps_table_query_service_1.PsTableQueryService.isActive(filters[column.id])).length;
|
|
16
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-wrap items-center gap-2', children: [isSearchable ? ((0, jsx_runtime_1.jsxs)("label", { className: 'relative basis-full sm:min-w-[12rem] sm:flex-1 sm:basis-auto sm:max-w-xs', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: searchPlaceholder }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/45', iconKey: ps_icons_1.PsIconKey.Search }), (0, jsx_runtime_1.jsx)("input", { className: 'ps-input-control ps-focus-ring ps-control rounded-ps-control pl-10 text-sm', onChange: (event) => onSearchChange(event.target.value), placeholder: searchPlaceholder, type: 'search', value: search })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: '
|
|
16
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-wrap items-center gap-2', children: [isSearchable ? ((0, jsx_runtime_1.jsxs)("label", { className: 'relative basis-full sm:min-w-[12rem] sm:flex-1 sm:basis-auto sm:max-w-xs', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: searchPlaceholder }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/45', iconKey: ps_icons_1.PsIconKey.Search }), (0, jsx_runtime_1.jsx)("input", { className: 'ps-input-control ps-focus-ring ps-control rounded-ps-control pl-10 text-sm', onChange: (event) => onSearchChange(event.target.value), placeholder: searchPlaceholder, type: 'search', value: search })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: 'flex max-w-full shrink-0 grow flex-wrap items-center gap-2', children: [filterableColumns.length > 0 ? ((0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { className: ps_table_control_classes_1.PsTableControlClasses.toolbarButton, children: [(0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: ps_icons_1.PsIconKey.Filter }), (0, jsx_runtime_1.jsx)("span", { className: 'sr-only sm:not-sr-only', children: "Filters" }), activeCount > 0 ? ((0, jsx_runtime_1.jsx)("span", { className: 'inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-xs font-semibold text-[color:var(--ps-color-primary-contrast)]', children: activeCount })) : null] }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-[min(34rem,80vh)] w-[min(22rem,calc(100vw-2rem))] overflow-y-auto outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Dialog, { "aria-label": 'Filters', className: 'flex flex-col gap-4 p-4 outline-none', children: (0, jsx_runtime_1.jsxs)(ps_core_components_1.PsLayer, { zIndex: zIndex, children: [filterableColumns.map((column) => ((0, jsx_runtime_1.jsx)(ps_table_filter_field_1.PsTableFilterField, { kind: column.filter ? column.filter.kind : 'text', label: column.label, onChange: (value) => onFilterChange(column.id, value), options: ps_table_query_service_1.PsTableQueryService.options(rows, column), value: filters[column.id] ? filters[column.id] : {} }, column.id))), (0, jsx_runtime_1.jsx)("div", { className: 'flex justify-end border-t border-line pt-3', children: (0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'text-ink/65 hover:text-ink disabled:opacity-40'), disabled: activeCount === 0, onClick: onClearFilters, type: 'button', children: "Clear all" }) })] }) }) })] })) : null, activeCount > 0 ? ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'text-ink/65 hover:text-ink'), onClick: onClearFilters, type: 'button', children: "Clear filters" })) : null, actions ? (0, jsx_runtime_1.jsx)("div", { className: 'ml-auto flex shrink-0 items-center gap-2', children: actions }) : null] })] }));
|
|
17
17
|
};
|
|
18
18
|
exports.PsTableToolbar = PsTableToolbar;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment, Suspense, lazy, useCallback, useDeferredValue, useEffect,
|
|
2
|
+
import { Fragment, Suspense, lazy, useCallback, useDeferredValue, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { PsDragGrip, PsSkeletonTable } from '@pallasoft/ps-core-components';
|
|
4
4
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
5
5
|
import { PsCheckbox } from '@pallasoft/ps-input-components';
|
|
6
6
|
import { PsCollapse } from '@pallasoft/ps-motion-components';
|
|
7
7
|
import { useVirtualizer, useWindowVirtualizer } from '@tanstack/react-virtual';
|
|
8
8
|
import { PsTableControlClasses } from '../constants/ps-table-control-classes';
|
|
9
|
+
import { PsTablePaginationConfig } from '../constants/ps-table-pagination-config';
|
|
9
10
|
import { PsTablePaginationPosition } from '../constants/ps-table-pagination-position';
|
|
10
11
|
import { PsTableHideBelowClasses } from '../constants/table-breakpoint';
|
|
11
12
|
import { PsTableConfig } from '../constants/table-config';
|
|
12
13
|
import { usePsIncrementalCount } from '../hooks/use-ps-incremental-count';
|
|
13
14
|
import { usePsScrollAnchor } from '../hooks/use-ps-scroll-anchor';
|
|
15
|
+
import { usePsStickyHead } from '../hooks/use-ps-sticky-head';
|
|
14
16
|
import { usePsTableOverflow } from '../hooks/use-ps-table-overflow';
|
|
15
17
|
import { usePsTableStreamStatus } from '../hooks/use-ps-table-stream-status';
|
|
16
18
|
import { PsTableCellTooltipService } from '../services/ps-table-cell-tooltip-service';
|
|
@@ -50,7 +52,7 @@ const alignClassNames = {
|
|
|
50
52
|
left: 'text-left',
|
|
51
53
|
right: 'text-right tabular-nums',
|
|
52
54
|
};
|
|
53
|
-
export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density = 'normal', expandedRowIds, mobileLayout = 'cards', getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading = false, isPending = false, isRefreshing = false, layout = 'auto', onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition = PsTablePaginationPosition.bottom, pinFirstColumn = true, query, renderExpandedRow, reorder, rows, searchingLabel = PsTableConfig.searchingLabel, searchPlaceholder = PsTableConfig.searchPlaceholder, selectAllMatching, stickyTop, toolbarActions, totalRows, }) => {
|
|
55
|
+
export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPaging, defaultSort, density = 'normal', expandedRowIds, mobileLayout = 'cards', getBulkActions, getRowId, getRowLabel, getSearchText, grouping, isLoading = false, isPending = false, isRefreshing = false, layout = 'auto', onPageChange, onQueryChange, onRowClick, onRowHover, page, pageSize, paginationPosition = PsTablePaginationPosition.bottom, pinFirstColumn = true, query, renderExpandedRow, reorder, rows, searchingLabel = PsTableConfig.searchingLabel, searchPlaceholder = PsTableConfig.searchPlaceholder, selectAllMatching, stickyClassName, stickyLeading, stickyTop, toolbarActions, totalRows, }) => {
|
|
54
56
|
const containerRef = useRef(null);
|
|
55
57
|
const [uncontrolledPage, setUncontrolledPage] = useState(1);
|
|
56
58
|
const [uncontrolledQuery, setUncontrolledQuery] = useState(() => PsTableQueryService.empty(defaultSort ? defaultSort : null));
|
|
@@ -61,47 +63,13 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
|
|
|
61
63
|
const [seenClearKey, setSeenClearKey] = useState(clearSelectionKey);
|
|
62
64
|
const stickyRegionRef = useRef(null);
|
|
63
65
|
const stickySentinelRef = useRef(null);
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
+
const stickyBackdropRef = useRef(null);
|
|
67
|
+
const stickyHeadRef = useRef(null);
|
|
66
68
|
const currentQuery = query ? query : uncontrolledQuery;
|
|
67
69
|
if (seenClearKey !== clearSelectionKey) {
|
|
68
70
|
setSeenClearKey(clearSelectionKey);
|
|
69
71
|
setSelectedIds([]);
|
|
70
72
|
}
|
|
71
|
-
useLayoutEffect(() => {
|
|
72
|
-
const region = stickyRegionRef.current;
|
|
73
|
-
if (stickyTop === undefined || region === null)
|
|
74
|
-
return;
|
|
75
|
-
const measure = () => setStickyHeight(region.offsetHeight);
|
|
76
|
-
const observer = new ResizeObserver(measure);
|
|
77
|
-
measure();
|
|
78
|
-
observer.observe(region);
|
|
79
|
-
return () => observer.disconnect();
|
|
80
|
-
}, [stickyTop]);
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
const region = stickyRegionRef.current;
|
|
83
|
-
const sentinel = stickySentinelRef.current;
|
|
84
|
-
if (stickyTop === undefined || region === null || sentinel === null)
|
|
85
|
-
return;
|
|
86
|
-
let frame = 0;
|
|
87
|
-
const check = () => {
|
|
88
|
-
frame = 0;
|
|
89
|
-
setIsStuck(sentinel.getBoundingClientRect().top < Number.parseFloat(getComputedStyle(region).top));
|
|
90
|
-
};
|
|
91
|
-
const schedule = () => {
|
|
92
|
-
if (frame === 0)
|
|
93
|
-
frame = window.requestAnimationFrame(check);
|
|
94
|
-
};
|
|
95
|
-
check();
|
|
96
|
-
window.addEventListener('scroll', schedule, { passive: true });
|
|
97
|
-
window.addEventListener('resize', schedule);
|
|
98
|
-
return () => {
|
|
99
|
-
window.removeEventListener('scroll', schedule);
|
|
100
|
-
window.removeEventListener('resize', schedule);
|
|
101
|
-
if (frame !== 0)
|
|
102
|
-
window.cancelAnimationFrame(frame);
|
|
103
|
-
};
|
|
104
|
-
}, [stickyTop]);
|
|
105
73
|
const { filters, hiddenColumnIds, search, sort } = currentQuery;
|
|
106
74
|
const visibleColumns = columns.filter((column) => !hiddenColumnIds.includes(column.id));
|
|
107
75
|
const fittedWidths = useMemo(() => new Map(columns
|
|
@@ -124,6 +92,14 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
|
|
|
124
92
|
const pins = PsTablePinService.leading(pinFirstColumn, Boolean(reorder), isSelectable);
|
|
125
93
|
const placementOf = (column, columnIndex) => PallasoftClassNameService.merge(column.hideBelow === undefined ? '' : PsTableHideBelowClasses[column.hideBelow], columnIndex === 0 ? pins.first : '', PsTablePinService.end(column.pinEnd === true));
|
|
126
94
|
const overflow = usePsTableOverflow(`${visibleColumns.map((column) => column.id).join(',')}:${rows.length}`);
|
|
95
|
+
const isStuck = usePsStickyHead({
|
|
96
|
+
backdropRef: stickyBackdropRef,
|
|
97
|
+
headRef: stickyHeadRef,
|
|
98
|
+
layoutKey: `${visibleColumns.map((column) => column.id).join(',')}:${rows.length}:${isLoading}`,
|
|
99
|
+
regionRef: stickyRegionRef,
|
|
100
|
+
sentinelRef: stickySentinelRef,
|
|
101
|
+
stickyTop,
|
|
102
|
+
});
|
|
127
103
|
const deferredSearch = useDeferredValue(search);
|
|
128
104
|
const queriedRows = useMemo(() => isServerPaginated
|
|
129
105
|
? rows
|
|
@@ -384,7 +360,9 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
|
|
|
384
360
|
updateQuery({ search: next });
|
|
385
361
|
resetPage();
|
|
386
362
|
}, rows: rows, search: search, searchPlaceholder: searchPlaceholder })) : null, banner] }));
|
|
387
|
-
return (_jsxs("div", { ref: containerRef, className: PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3', className), children: [stickyTop === undefined ? (topContent) : (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: '-mb-3 h-0', ref: stickySentinelRef }),
|
|
363
|
+
return (_jsxs("div", { ref: containerRef, className: PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3', className), children: [stickyTop === undefined ? (_jsxs(_Fragment, { children: [stickyLeading, topContent] })) : (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: '-mb-3 h-0', ref: stickySentinelRef }), _jsxs("div", { className: PallasoftClassNameService.merge('sticky z-sticky flex flex-col gap-3', stickyClassName), "data-stuck": isStuck, ref: stickyRegionRef, style: { top: stickyTop }, children: [_jsx("div", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('ps-glass-strong pointer-events-none absolute -inset-x-3 -bottom-3 rounded-b-ps-card border-t-0 transition-opacity duration-150', isStuck ? 'opacity-100' : 'opacity-0'), ref: stickyBackdropRef, style: { top: `calc(-1 * ${stickyTop})` } }), _jsxs("div", { className: 'relative flex flex-col gap-3', children: [stickyLeading, topContent] })] })] })), _jsxs("div", { "aria-busy": isRefreshing, className: 'min-w-0 overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [showsPagination &&
|
|
364
|
+
paginationPosition !== PsTablePaginationPosition.bottom &&
|
|
365
|
+
rowCount > PsTablePaginationConfig.topMinRows
|
|
388
366
|
? renderPagination('border-b border-t-0')
|
|
389
367
|
: null, mobileLayout === 'cards' ? (_jsxs("div", { className: PallasoftClassNameService.merge('transition-opacity duration-150 sm:hidden', isRefreshing ? 'opacity-60' : ''), children: [reorder && reorder.cardsReason ? (_jsx("p", { className: 'border-b border-line px-4 py-2 text-xs text-ink/55', children: reorder.cardsReason })) : null, grouping
|
|
390
368
|
? groups.map((group, groupIndex) => {
|
|
@@ -393,13 +371,9 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
|
|
|
393
371
|
? grouping.renderGroupSummary(group.rows)
|
|
394
372
|
: undefined }), _jsx(PsCollapse, { isOpen: isExpanded && !closingGroupKeys.includes(group.key), children: renderCardList(group.rows, null) })] }, `group-${group.key}`));
|
|
395
373
|
})
|
|
396
|
-
: renderCardList(shouldVirtualize ? visibleRows.slice(0, cards.count) : visibleRows, visibleRows.length === 0 && isSearching ? (_jsx(PsTableSearchingState, { label: searchingLabel, skeletonRows: PsTableConfig.searchingSkeletonRows })) : visibleRows.length === 0 && isQueried ? (_jsxs("div", { className: 'px-4 py-10 text-center', children: [_jsx("p", { className: 'text-sm font-semibold text-ink', children: PsTableConfig.noMatchesTitle }), _jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'mt-2 text-primary'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] })) : null), !grouping && shouldVirtualize && cards.count < visibleRows.length ? (_jsx("div", { "aria-hidden": 'true', className: 'h-px', ref: cards.sentinelRef })) : null] })) : null, _jsx("div", { className: PallasoftClassNameService.merge(stickyTop === undefined
|
|
397
|
-
? 'ps-scrollbar overflow-x-auto overflow-y-hidden overscroll-x-contain'
|
|
398
|
-
: 'overflow-x-clip', 'transition-opacity duration-150', isRefreshing ? 'opacity-60' : '', mobileLayout === 'cards' ? 'hidden sm:block' : ''), "data-overflow-end": overflow.edges.end, "data-overflow-start": overflow.edges.start, onScroll: overflow.update, ref: overflow.ref, children: renderReorder((api) => (_jsxs("table", { className: PallasoftClassNameService.merge('w-full border-collapse text-left', layout === 'fixed' ? 'table-fixed' : ''), children: [caption ? _jsx("caption", { className: 'sr-only', children: caption }) : null, _jsx("thead", { className: PallasoftClassNameService.merge('bg-mist/70 text-[0.68rem] font-semibold uppercase tracking-[0.18em] text-ink/45', stickyTop === undefined
|
|
374
|
+
: renderCardList(shouldVirtualize ? visibleRows.slice(0, cards.count) : visibleRows, visibleRows.length === 0 && isSearching ? (_jsx(PsTableSearchingState, { label: searchingLabel, skeletonRows: PsTableConfig.searchingSkeletonRows })) : visibleRows.length === 0 && isQueried ? (_jsxs("div", { className: 'px-4 py-10 text-center', children: [_jsx("p", { className: 'text-sm font-semibold text-ink', children: PsTableConfig.noMatchesTitle }), _jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'mt-2 text-primary'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] })) : null), !grouping && shouldVirtualize && cards.count < visibleRows.length ? (_jsx("div", { "aria-hidden": 'true', className: 'h-px', ref: cards.sentinelRef })) : null] })) : null, _jsx("div", { className: PallasoftClassNameService.merge('ps-scrollbar overflow-x-auto overflow-y-hidden overscroll-x-contain', 'transition-opacity duration-150', isRefreshing ? 'opacity-60' : '', mobileLayout === 'cards' ? 'hidden sm:block' : ''), "data-overflow-end": overflow.edges.end, "data-overflow-start": overflow.edges.start, onScroll: overflow.update, ref: overflow.ref, children: renderReorder((api) => (_jsxs("table", { className: PallasoftClassNameService.merge('w-full border-collapse text-left', layout === 'fixed' ? 'table-fixed' : ''), children: [caption ? _jsx("caption", { className: 'sr-only', children: caption }) : null, _jsx("thead", { className: PallasoftClassNameService.merge('bg-mist/70 text-[0.68rem] font-semibold uppercase tracking-[0.18em] text-ink/45', stickyTop === undefined
|
|
399
375
|
? ''
|
|
400
|
-
: '
|
|
401
|
-
? undefined
|
|
402
|
-
: { top: `calc(${stickyTop} + ${stickyHeight}px)` }, children: _jsxs("tr", { children: [reorder ? (_jsx("th", { className: PallasoftClassNameService.merge('w-9 min-w-9 pl-3 pr-0', pins.reorder), scope: 'col', children: reorder.enabled ? (_jsx("span", { className: 'sr-only', children: reorder.columnLabel })) : reorder.disabledReason ? (_jsx("span", { "aria-label": reorder.disabledReason, className: 'inline-flex cursor-help opacity-40', role: 'img', title: reorder.disabledReason, children: _jsx(PsDragGrip, {}) })) : null })) : null, isSelectable ? (_jsx("th", { className: PallasoftClassNameService.merge('w-10 min-w-10 pl-4 pr-0', pins.select), scope: 'col', children: _jsx(PsCheckbox, { isIndeterminate: !isPageSelected && pageIds.some((rowId) => selectedIdSet.has(rowId)), isSelected: isPageSelected, label: 'Select all rows on this page', onChange: togglePage }) })) : null, visibleColumns.map((column, columnIndex) => {
|
|
376
|
+
: 'relative z-docked bg-surface will-change-transform [&_th]:border-b [&_th]:border-line [&>tr]:bg-mist/70'), ref: stickyHeadRef, children: _jsxs("tr", { children: [reorder ? (_jsx("th", { className: PallasoftClassNameService.merge('w-9 min-w-9 pl-3 pr-0', pins.reorder), scope: 'col', children: reorder.enabled ? (_jsx("span", { className: 'sr-only', children: reorder.columnLabel })) : reorder.disabledReason ? (_jsx("span", { "aria-label": reorder.disabledReason, className: 'inline-flex cursor-help opacity-40', role: 'img', title: reorder.disabledReason, children: _jsx(PsDragGrip, {}) })) : null })) : null, isSelectable ? (_jsx("th", { className: PallasoftClassNameService.merge('w-10 min-w-10 pl-4 pr-0', pins.select), scope: 'col', children: _jsx(PsCheckbox, { isIndeterminate: !isPageSelected && pageIds.some((rowId) => selectedIdSet.has(rowId)), isSelected: isPageSelected, label: 'Select all rows on this page', onChange: togglePage }) })) : null, visibleColumns.map((column, columnIndex) => {
|
|
403
377
|
const align = column.align !== null && column.align !== undefined ? column.align : 'left';
|
|
404
378
|
const isSorted = sort !== null && sort.columnId === column.id;
|
|
405
379
|
return (_jsx("th", { "aria-sort": isSorted
|
|
@@ -8,11 +8,11 @@ export const PsTablePagination = ({ className, cursor, isPartial = false, loaded
|
|
|
8
8
|
const pageNumber = cursor === undefined ? Math.min(page, pageCount) : cursor.pageNumber;
|
|
9
9
|
const cursorFirst = cursor === undefined ? firstRow : (cursor.pageNumber - 1) * pageSize + 1;
|
|
10
10
|
const cursorLast = cursor === undefined ? lastRow : Math.min(cursor.pageNumber * pageSize, totalRows);
|
|
11
|
-
return (_jsxs("nav", { "aria-label": 'Pagination', className: PallasoftClassNameService.merge('flex flex-wrap items-center justify-between gap-3 border-t border-line px-
|
|
11
|
+
return (_jsxs("nav", { "aria-label": 'Pagination', className: PallasoftClassNameService.merge('flex flex-wrap items-center justify-between gap-x-6 gap-y-3 border-t border-line px-5 py-3', className), children: [_jsx("p", { className: 'shrink-0 whitespace-nowrap text-sm text-ink/55', children: totalRows === 0
|
|
12
12
|
? 'No rows'
|
|
13
13
|
: cursor === undefined
|
|
14
14
|
? `${firstRow}–${lastRow} of ${totalRows}${isPartial ? '+' : ''}`
|
|
15
|
-
: `${cursorFirst}–${cursorLast} of ${approximately}${totalRows.toLocaleString()}` }), _jsxs("div", { className: 'flex items-center gap-
|
|
15
|
+
: `${cursorFirst}–${cursorLast} of ${approximately}${totalRows.toLocaleString()}` }), _jsxs("div", { className: 'flex shrink-0 items-center gap-3', children: [cursor !== undefined && cursor.pageSizeOptions !== undefined && cursor.onPageSizeChange ? (_jsxs("label", { className: 'flex shrink-0 items-center gap-2 whitespace-nowrap text-sm text-ink/65', children: [_jsx("span", { className: 'hidden sm:inline', children: "Rows per page" }), _jsx("select", { "aria-label": 'Rows per page', className: 'ps-input-control ps-focus-ring ps-control ps-control-padding w-auto shrink-0 rounded-ps-control text-sm', onChange: (event) => cursor.onPageSizeChange?.(Number(event.target.value)), value: pageSize, children: cursor.pageSizeOptions.map((option) => (_jsx("option", { value: option, children: option }, option))) })] })) : null, _jsx("button", { className: PsTableControlClasses.paginationButton, disabled: cursor === undefined ? page <= 1 : !cursor.hasPrevious, onClick: () => (cursor === undefined ? onPageChange(page - 1) : cursor.onPrevious()), type: 'button', children: "Previous" }), _jsxs("span", { className: 'hidden whitespace-nowrap text-sm text-ink/65 sm:inline', children: ["Page ", pageNumber, " of ", approximately, pageCount] }), _jsx("button", { className: PsTableControlClasses.paginationButton, disabled: cursor === undefined
|
|
16
16
|
? page >=
|
|
17
17
|
(loadedPageCount === undefined ? pageCount : Math.min(loadedPageCount, pageCount))
|
|
18
18
|
: !cursor.hasNext, onClick: () => (cursor === undefined ? onPageChange(page + 1) : cursor.onNext()), onFocus: cursor === undefined ? undefined : cursor.onNextIntent, onPointerEnter: cursor === undefined ? undefined : cursor.onNextIntent, type: 'button', children: "Next" })] })] }));
|
|
@@ -10,5 +10,5 @@ export const PsTableToolbar = ({ actions, columns, filters, isSearchable, onClea
|
|
|
10
10
|
const filterableColumns = columns.filter((column) => column.filter);
|
|
11
11
|
const zIndex = usePsLayerZIndex(PallasoftZIndex.Dropdown);
|
|
12
12
|
const activeCount = filterableColumns.filter((column) => PsTableQueryService.isActive(filters[column.id])).length;
|
|
13
|
-
return (_jsxs("div", { className: 'flex flex-wrap items-center gap-2', children: [isSearchable ? (_jsxs("label", { className: 'relative basis-full sm:min-w-[12rem] sm:flex-1 sm:basis-auto sm:max-w-xs', children: [_jsx("span", { className: 'sr-only', children: searchPlaceholder }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/45', iconKey: PsIconKey.Search }), _jsx("input", { className: 'ps-input-control ps-focus-ring ps-control rounded-ps-control pl-10 text-sm', onChange: (event) => onSearchChange(event.target.value), placeholder: searchPlaceholder, type: 'search', value: search })] })) : null, _jsxs("div", { className: '
|
|
13
|
+
return (_jsxs("div", { className: 'flex flex-wrap items-center gap-2', children: [isSearchable ? (_jsxs("label", { className: 'relative basis-full sm:min-w-[12rem] sm:flex-1 sm:basis-auto sm:max-w-xs', children: [_jsx("span", { className: 'sr-only', children: searchPlaceholder }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute left-3.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/45', iconKey: PsIconKey.Search }), _jsx("input", { className: 'ps-input-control ps-focus-ring ps-control rounded-ps-control pl-10 text-sm', onChange: (event) => onSearchChange(event.target.value), placeholder: searchPlaceholder, type: 'search', value: search })] })) : null, _jsxs("div", { className: 'flex max-w-full shrink-0 grow flex-wrap items-center gap-2', children: [filterableColumns.length > 0 ? (_jsxs(DialogTrigger, { children: [_jsxs(Button, { className: PsTableControlClasses.toolbarButton, children: [_jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: PsIconKey.Filter }), _jsx("span", { className: 'sr-only sm:not-sr-only', children: "Filters" }), activeCount > 0 ? (_jsx("span", { className: 'inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-xs font-semibold text-[color:var(--ps-color-primary-contrast)]', children: activeCount })) : null] }), _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-[min(34rem,80vh)] w-[min(22rem,calc(100vw-2rem))] overflow-y-auto outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(Dialog, { "aria-label": 'Filters', className: 'flex flex-col gap-4 p-4 outline-none', children: _jsxs(PsLayer, { zIndex: zIndex, children: [filterableColumns.map((column) => (_jsx(PsTableFilterField, { kind: column.filter ? column.filter.kind : 'text', label: column.label, onChange: (value) => onFilterChange(column.id, value), options: PsTableQueryService.options(rows, column), value: filters[column.id] ? filters[column.id] : {} }, column.id))), _jsx("div", { className: 'flex justify-end border-t border-line pt-3', children: _jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'text-ink/65 hover:text-ink disabled:opacity-40'), disabled: activeCount === 0, onClick: onClearFilters, type: 'button', children: "Clear all" }) })] }) }) })] })) : null, activeCount > 0 ? (_jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'text-ink/65 hover:text-ink'), onClick: onClearFilters, type: 'button', children: "Clear filters" })) : null, actions ? _jsx("div", { className: 'ml-auto flex shrink-0 items-center gap-2', children: actions }) : null] })] }));
|
|
14
14
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useLayoutEffect, useState } from 'react';
|
|
2
|
+
import { PsTableScrollService } from '../services/ps-table-scroll-service';
|
|
3
|
+
import { PsTableStickyHeadService } from '../services/ps-table-sticky-head-service';
|
|
4
|
+
export const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
|
|
5
|
+
const [isStuck, setIsStuck] = useState(false);
|
|
6
|
+
useLayoutEffect(() => {
|
|
7
|
+
const region = regionRef.current;
|
|
8
|
+
const sentinel = sentinelRef.current;
|
|
9
|
+
const backdrop = backdropRef.current;
|
|
10
|
+
const head = headRef.current;
|
|
11
|
+
const table = head === null ? null : head.parentElement;
|
|
12
|
+
if (stickyTop === undefined ||
|
|
13
|
+
region === null ||
|
|
14
|
+
sentinel === null ||
|
|
15
|
+
backdrop === null ||
|
|
16
|
+
head === null ||
|
|
17
|
+
table === null)
|
|
18
|
+
return;
|
|
19
|
+
const scroller = PsTableScrollService.parent(region);
|
|
20
|
+
const Timeline = window.ScrollTimeline;
|
|
21
|
+
const isDriven = scroller !== null && Timeline !== undefined;
|
|
22
|
+
let animation = null;
|
|
23
|
+
let frame = 0;
|
|
24
|
+
const maxShift = () => Math.max(table.offsetHeight - head.offsetHeight, 0);
|
|
25
|
+
const drive = () => {
|
|
26
|
+
if (scroller === null || Timeline === undefined)
|
|
27
|
+
return;
|
|
28
|
+
const scrollerTop = scroller.getBoundingClientRect().top;
|
|
29
|
+
const regionTop = region.getBoundingClientRect().top;
|
|
30
|
+
const pinnedBottom = scrollerTop +
|
|
31
|
+
Number.parseFloat(getComputedStyle(region).top) +
|
|
32
|
+
backdrop.getBoundingClientRect().bottom -
|
|
33
|
+
regionTop;
|
|
34
|
+
const pinScroll = table.getBoundingClientRect().top + scroller.scrollTop - pinnedBottom;
|
|
35
|
+
const keyframes = PsTableStickyHeadService.keyframes(pinScroll, maxShift(), scroller.scrollHeight - scroller.clientHeight);
|
|
36
|
+
if (animation !== null)
|
|
37
|
+
animation.cancel();
|
|
38
|
+
animation =
|
|
39
|
+
keyframes.length === 0
|
|
40
|
+
? null
|
|
41
|
+
: head.animate(keyframes.map((keyframe) => ({
|
|
42
|
+
offset: keyframe.offset,
|
|
43
|
+
transform: `translateY(${keyframe.shift}px)`,
|
|
44
|
+
})), { fill: 'both', timeline: new Timeline({ axis: 'block', source: scroller }) });
|
|
45
|
+
};
|
|
46
|
+
const follow = () => (head.style.transform = `translateY(${PsTableStickyHeadService.offset(backdrop.getBoundingClientRect().bottom, table.getBoundingClientRect().top, table.offsetHeight, head.offsetHeight)}px)`);
|
|
47
|
+
const check = () => {
|
|
48
|
+
frame = 0;
|
|
49
|
+
setIsStuck(sentinel.getBoundingClientRect().top < region.getBoundingClientRect().top - 1);
|
|
50
|
+
if (!isDriven)
|
|
51
|
+
follow();
|
|
52
|
+
};
|
|
53
|
+
const schedule = () => {
|
|
54
|
+
if (frame === 0)
|
|
55
|
+
frame = window.requestAnimationFrame(check);
|
|
56
|
+
};
|
|
57
|
+
const measure = () => {
|
|
58
|
+
if (isDriven)
|
|
59
|
+
drive();
|
|
60
|
+
schedule();
|
|
61
|
+
};
|
|
62
|
+
const observer = new ResizeObserver(measure);
|
|
63
|
+
measure();
|
|
64
|
+
observer.observe(region);
|
|
65
|
+
observer.observe(table);
|
|
66
|
+
if (scroller !== null)
|
|
67
|
+
Array.from(scroller.children).forEach((child) => observer.observe(child));
|
|
68
|
+
window.addEventListener('scroll', schedule, { capture: true, passive: true });
|
|
69
|
+
window.addEventListener('resize', measure);
|
|
70
|
+
return () => {
|
|
71
|
+
observer.disconnect();
|
|
72
|
+
if (animation !== null)
|
|
73
|
+
animation.cancel();
|
|
74
|
+
head.style.transform = '';
|
|
75
|
+
window.removeEventListener('scroll', schedule, { capture: true });
|
|
76
|
+
window.removeEventListener('resize', measure);
|
|
77
|
+
if (frame !== 0)
|
|
78
|
+
window.cancelAnimationFrame(frame);
|
|
79
|
+
};
|
|
80
|
+
}, [backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
|
|
81
|
+
return isStuck;
|
|
82
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -29,9 +29,13 @@ export * from './services/ps-table-group-service';
|
|
|
29
29
|
export * from './services/ps-table-query-service';
|
|
30
30
|
export * from './services/ps-table-search-service';
|
|
31
31
|
export * from './services/ps-table-scroll-service';
|
|
32
|
+
export * from './services/ps-table-sticky-head-service';
|
|
32
33
|
export * from './services/ps-table-pin-service';
|
|
33
34
|
export * from './services/ps-table-overflow-service';
|
|
34
35
|
export * from './hooks/use-ps-table-overflow';
|
|
36
|
+
export * from './hooks/use-ps-sticky-head';
|
|
37
|
+
export * from './interfaces/ps-sticky-head-refs';
|
|
38
|
+
export * from './interfaces/ps-table-sticky-head-keyframe';
|
|
35
39
|
export * from './interfaces/table-pin-classes';
|
|
36
40
|
export * from './interfaces/table-overflow-edges';
|
|
37
41
|
export * from './services/ps-table-stream-service';
|
|
@@ -47,6 +51,7 @@ export * from './interfaces/table-reorder-nesting';
|
|
|
47
51
|
export * from './interfaces/table-nesting-announcements';
|
|
48
52
|
export * from './constants/ps-table-drop-placement';
|
|
49
53
|
export * from './services/ps-table-reorder-service';
|
|
54
|
+
export * from './constants/ps-table-pagination-config';
|
|
50
55
|
export * from './constants/ps-table-pagination-position';
|
|
51
56
|
export * from './interfaces/table-drag-size';
|
|
52
57
|
export * from './components/ps-select-all-matching-banner';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class PsTableStickyHeadService {
|
|
2
|
+
static offset(pinnedBottom, tableTop, tableHeight, headHeight) {
|
|
3
|
+
return Math.min(Math.max(pinnedBottom - tableTop, 0), Math.max(tableHeight - headHeight, 0));
|
|
4
|
+
}
|
|
5
|
+
static keyframes(pinScroll, maxShift, scrollRange) {
|
|
6
|
+
if (scrollRange <= 0)
|
|
7
|
+
return [];
|
|
8
|
+
const shiftAt = (scroll) => Math.min(Math.max(scroll - pinScroll, 0), maxShift);
|
|
9
|
+
const stops = [0, pinScroll, pinScroll + maxShift, scrollRange].filter((scroll) => scroll >= 0 && scroll <= scrollRange);
|
|
10
|
+
return stops
|
|
11
|
+
.filter((scroll, index) => stops.indexOf(scroll) === index)
|
|
12
|
+
.map((scroll) => ({
|
|
13
|
+
offset: scroll / scrollRange,
|
|
14
|
+
shift: shiftAt(scroll),
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsStickyHead = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const ps_table_scroll_service_1 = require("../services/ps-table-scroll-service");
|
|
6
|
+
const ps_table_sticky_head_service_1 = require("../services/ps-table-sticky-head-service");
|
|
7
|
+
const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
|
|
8
|
+
const [isStuck, setIsStuck] = (0, react_1.useState)(false);
|
|
9
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
10
|
+
const region = regionRef.current;
|
|
11
|
+
const sentinel = sentinelRef.current;
|
|
12
|
+
const backdrop = backdropRef.current;
|
|
13
|
+
const head = headRef.current;
|
|
14
|
+
const table = head === null ? null : head.parentElement;
|
|
15
|
+
if (stickyTop === undefined ||
|
|
16
|
+
region === null ||
|
|
17
|
+
sentinel === null ||
|
|
18
|
+
backdrop === null ||
|
|
19
|
+
head === null ||
|
|
20
|
+
table === null)
|
|
21
|
+
return;
|
|
22
|
+
const scroller = ps_table_scroll_service_1.PsTableScrollService.parent(region);
|
|
23
|
+
const Timeline = window.ScrollTimeline;
|
|
24
|
+
const isDriven = scroller !== null && Timeline !== undefined;
|
|
25
|
+
let animation = null;
|
|
26
|
+
let frame = 0;
|
|
27
|
+
const maxShift = () => Math.max(table.offsetHeight - head.offsetHeight, 0);
|
|
28
|
+
const drive = () => {
|
|
29
|
+
if (scroller === null || Timeline === undefined)
|
|
30
|
+
return;
|
|
31
|
+
const scrollerTop = scroller.getBoundingClientRect().top;
|
|
32
|
+
const regionTop = region.getBoundingClientRect().top;
|
|
33
|
+
const pinnedBottom = scrollerTop +
|
|
34
|
+
Number.parseFloat(getComputedStyle(region).top) +
|
|
35
|
+
backdrop.getBoundingClientRect().bottom -
|
|
36
|
+
regionTop;
|
|
37
|
+
const pinScroll = table.getBoundingClientRect().top + scroller.scrollTop - pinnedBottom;
|
|
38
|
+
const keyframes = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(pinScroll, maxShift(), scroller.scrollHeight - scroller.clientHeight);
|
|
39
|
+
if (animation !== null)
|
|
40
|
+
animation.cancel();
|
|
41
|
+
animation =
|
|
42
|
+
keyframes.length === 0
|
|
43
|
+
? null
|
|
44
|
+
: head.animate(keyframes.map((keyframe) => ({
|
|
45
|
+
offset: keyframe.offset,
|
|
46
|
+
transform: `translateY(${keyframe.shift}px)`,
|
|
47
|
+
})), { fill: 'both', timeline: new Timeline({ axis: 'block', source: scroller }) });
|
|
48
|
+
};
|
|
49
|
+
const follow = () => (head.style.transform = `translateY(${ps_table_sticky_head_service_1.PsTableStickyHeadService.offset(backdrop.getBoundingClientRect().bottom, table.getBoundingClientRect().top, table.offsetHeight, head.offsetHeight)}px)`);
|
|
50
|
+
const check = () => {
|
|
51
|
+
frame = 0;
|
|
52
|
+
setIsStuck(sentinel.getBoundingClientRect().top < region.getBoundingClientRect().top - 1);
|
|
53
|
+
if (!isDriven)
|
|
54
|
+
follow();
|
|
55
|
+
};
|
|
56
|
+
const schedule = () => {
|
|
57
|
+
if (frame === 0)
|
|
58
|
+
frame = window.requestAnimationFrame(check);
|
|
59
|
+
};
|
|
60
|
+
const measure = () => {
|
|
61
|
+
if (isDriven)
|
|
62
|
+
drive();
|
|
63
|
+
schedule();
|
|
64
|
+
};
|
|
65
|
+
const observer = new ResizeObserver(measure);
|
|
66
|
+
measure();
|
|
67
|
+
observer.observe(region);
|
|
68
|
+
observer.observe(table);
|
|
69
|
+
if (scroller !== null)
|
|
70
|
+
Array.from(scroller.children).forEach((child) => observer.observe(child));
|
|
71
|
+
window.addEventListener('scroll', schedule, { capture: true, passive: true });
|
|
72
|
+
window.addEventListener('resize', measure);
|
|
73
|
+
return () => {
|
|
74
|
+
observer.disconnect();
|
|
75
|
+
if (animation !== null)
|
|
76
|
+
animation.cancel();
|
|
77
|
+
head.style.transform = '';
|
|
78
|
+
window.removeEventListener('scroll', schedule, { capture: true });
|
|
79
|
+
window.removeEventListener('resize', measure);
|
|
80
|
+
if (frame !== 0)
|
|
81
|
+
window.cancelAnimationFrame(frame);
|
|
82
|
+
};
|
|
83
|
+
}, [backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
|
|
84
|
+
return isStuck;
|
|
85
|
+
};
|
|
86
|
+
exports.usePsStickyHead = usePsStickyHead;
|
package/dist/index.d.ts
CHANGED
|
@@ -29,9 +29,13 @@ export * from './services/ps-table-group-service';
|
|
|
29
29
|
export * from './services/ps-table-query-service';
|
|
30
30
|
export * from './services/ps-table-search-service';
|
|
31
31
|
export * from './services/ps-table-scroll-service';
|
|
32
|
+
export * from './services/ps-table-sticky-head-service';
|
|
32
33
|
export * from './services/ps-table-pin-service';
|
|
33
34
|
export * from './services/ps-table-overflow-service';
|
|
34
35
|
export * from './hooks/use-ps-table-overflow';
|
|
36
|
+
export * from './hooks/use-ps-sticky-head';
|
|
37
|
+
export * from './interfaces/ps-sticky-head-refs';
|
|
38
|
+
export * from './interfaces/ps-table-sticky-head-keyframe';
|
|
35
39
|
export * from './interfaces/table-pin-classes';
|
|
36
40
|
export * from './interfaces/table-overflow-edges';
|
|
37
41
|
export * from './services/ps-table-stream-service';
|
|
@@ -47,6 +51,7 @@ export * from './interfaces/table-reorder-nesting';
|
|
|
47
51
|
export * from './interfaces/table-nesting-announcements';
|
|
48
52
|
export * from './constants/ps-table-drop-placement';
|
|
49
53
|
export * from './services/ps-table-reorder-service';
|
|
54
|
+
export * from './constants/ps-table-pagination-config';
|
|
50
55
|
export * from './constants/ps-table-pagination-position';
|
|
51
56
|
export * from './interfaces/table-drag-size';
|
|
52
57
|
export * from './components/ps-select-all-matching-banner';
|
package/dist/index.js
CHANGED
|
@@ -45,9 +45,13 @@ __exportStar(require("./services/ps-table-group-service"), exports);
|
|
|
45
45
|
__exportStar(require("./services/ps-table-query-service"), exports);
|
|
46
46
|
__exportStar(require("./services/ps-table-search-service"), exports);
|
|
47
47
|
__exportStar(require("./services/ps-table-scroll-service"), exports);
|
|
48
|
+
__exportStar(require("./services/ps-table-sticky-head-service"), exports);
|
|
48
49
|
__exportStar(require("./services/ps-table-pin-service"), exports);
|
|
49
50
|
__exportStar(require("./services/ps-table-overflow-service"), exports);
|
|
50
51
|
__exportStar(require("./hooks/use-ps-table-overflow"), exports);
|
|
52
|
+
__exportStar(require("./hooks/use-ps-sticky-head"), exports);
|
|
53
|
+
__exportStar(require("./interfaces/ps-sticky-head-refs"), exports);
|
|
54
|
+
__exportStar(require("./interfaces/ps-table-sticky-head-keyframe"), exports);
|
|
51
55
|
__exportStar(require("./interfaces/table-pin-classes"), exports);
|
|
52
56
|
__exportStar(require("./interfaces/table-overflow-edges"), exports);
|
|
53
57
|
__exportStar(require("./services/ps-table-stream-service"), exports);
|
|
@@ -63,6 +67,7 @@ __exportStar(require("./interfaces/table-reorder-nesting"), exports);
|
|
|
63
67
|
__exportStar(require("./interfaces/table-nesting-announcements"), exports);
|
|
64
68
|
__exportStar(require("./constants/ps-table-drop-placement"), exports);
|
|
65
69
|
__exportStar(require("./services/ps-table-reorder-service"), exports);
|
|
70
|
+
__exportStar(require("./constants/ps-table-pagination-config"), exports);
|
|
66
71
|
__exportStar(require("./constants/ps-table-pagination-position"), exports);
|
|
67
72
|
__exportStar(require("./interfaces/table-drag-size"), exports);
|
|
68
73
|
__exportStar(require("./components/ps-select-all-matching-banner"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
export interface PsStickyHeadRefs {
|
|
3
|
+
backdropRef: RefObject<HTMLDivElement | null>;
|
|
4
|
+
headRef: RefObject<HTMLTableSectionElement | null>;
|
|
5
|
+
layoutKey: string;
|
|
6
|
+
regionRef: RefObject<HTMLDivElement | null>;
|
|
7
|
+
sentinelRef: RefObject<HTMLDivElement | null>;
|
|
8
|
+
stickyTop?: string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PsTableStickyHeadKeyframe } from '../interfaces/ps-table-sticky-head-keyframe';
|
|
2
|
+
export declare class PsTableStickyHeadService {
|
|
3
|
+
static offset(pinnedBottom: number, tableTop: number, tableHeight: number, headHeight: number): number;
|
|
4
|
+
static keyframes(pinScroll: number, maxShift: number, scrollRange: number): PsTableStickyHeadKeyframe[];
|
|
5
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsTableStickyHeadService = void 0;
|
|
4
|
+
class PsTableStickyHeadService {
|
|
5
|
+
static offset(pinnedBottom, tableTop, tableHeight, headHeight) {
|
|
6
|
+
return Math.min(Math.max(pinnedBottom - tableTop, 0), Math.max(tableHeight - headHeight, 0));
|
|
7
|
+
}
|
|
8
|
+
static keyframes(pinScroll, maxShift, scrollRange) {
|
|
9
|
+
if (scrollRange <= 0)
|
|
10
|
+
return [];
|
|
11
|
+
const shiftAt = (scroll) => Math.min(Math.max(scroll - pinScroll, 0), maxShift);
|
|
12
|
+
const stops = [0, pinScroll, pinScroll + maxShift, scrollRange].filter((scroll) => scroll >= 0 && scroll <= scrollRange);
|
|
13
|
+
return stops
|
|
14
|
+
.filter((scroll, index) => stops.indexOf(scroll) === index)
|
|
15
|
+
.map((scroll) => ({
|
|
16
|
+
offset: scroll / scrollRange,
|
|
17
|
+
shift: shiftAt(scroll),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.PsTableStickyHeadService = PsTableStickyHeadService;
|