@pallasoft/ps-table-components 1.28.2 → 1.28.4

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.
@@ -41,6 +41,7 @@ const ps_design_system_1 = require("@pallasoft/ps-design-system");
41
41
  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
+ const ps_table_body_classes_1 = require("../constants/ps-table-body-classes");
44
45
  const ps_table_control_classes_1 = require("../constants/ps-table-control-classes");
45
46
  const ps_table_pagination_config_1 = require("../constants/ps-table-pagination-config");
46
47
  const ps_table_pagination_position_1 = require("../constants/ps-table-pagination-position");
@@ -100,6 +101,7 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
100
101
  const stickyRegionRef = (0, react_1.useRef)(null);
101
102
  const stickySentinelRef = (0, react_1.useRef)(null);
102
103
  const stickyCardRef = (0, react_1.useRef)(null);
104
+ const stickyContentRef = (0, react_1.useRef)(null);
103
105
  const stickyHeadRef = (0, react_1.useRef)(null);
104
106
  const currentQuery = query ? query : uncontrolledQuery;
105
107
  if (seenClearKey !== clearSelectionKey) {
@@ -130,6 +132,7 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
130
132
  const overflow = (0, use_ps_table_overflow_1.usePsTableOverflow)(`${visibleColumns.map((column) => column.id).join(',')}:${rows.length}`);
131
133
  const isStuck = (0, use_ps_sticky_head_1.usePsStickyHead)({
132
134
  cardRef: stickyCardRef,
135
+ contentRef: stickyContentRef,
133
136
  headRef: stickyHeadRef,
134
137
  layoutKey: `${visibleColumns.map((column) => column.id).join(',')}:${rows.length}:${isLoading}`,
135
138
  regionRef: stickyRegionRef,
@@ -396,52 +399,54 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
396
399
  updateQuery({ search: next });
397
400
  resetPage();
398
401
  }, rows: rows, search: search, searchPlaceholder: searchPlaceholder })) : null, banner] }));
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: [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', ref: stickyCardRef, children: [showsPagination &&
400
- paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.bottom &&
401
- rowCount > ps_table_pagination_config_1.PsTablePaginationConfig.topMinRows
402
- ? renderPagination('border-b border-t-0')
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
404
- ? groups.map((group, groupIndex) => {
405
- const isExpanded = isGroupExpanded(group.key, groupIndex);
406
- return ((0, jsx_runtime_1.jsxs)("div", { className: 'border-b border-line last:border-b-0', children: [(0, jsx_runtime_1.jsx)(ps_table_group_header_1.PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
407
- ? grouping.renderGroupSummary(group.rows)
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}`));
409
- })
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
411
- ? ''
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) => {
413
- const align = column.align !== null && column.align !== undefined ? column.align : 'left';
414
- const isSorted = sort !== null && sort.columnId === column.id;
415
- return ((0, jsx_runtime_1.jsx)("th", { "aria-sort": isSorted
416
- ? sort.direction
417
- : column.sortValue && isQueryable
418
- ? 'none'
419
- : undefined, className: ps_design_system_1.PallasoftClassNameService.merge(densityClassNames[density].head, alignClassNames[align], placementOf(column, columnIndex), 'whitespace-nowrap'), scope: 'col', style: columnStyle(column, fittedWidths.get(column.id)), children: column.sortValue && isQueryable ? ((0, jsx_runtime_1.jsx)(ps_table_sort_header_1.PsTableSortHeader, { align: align, columnId: column.id, label: column.label, onSort: updateSort, sort: sort })) : (column.label) }, column.id));
420
- })] }) }), (0, jsx_runtime_1.jsxs)("tbody", { className: 'divide-y divide-line', ref: bodyRef, children: [visibleRows.length === 0 && isSearching ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, children: (0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { label: searchingLabel, skeletonRows: table_config_1.PsTableConfig.searchingSkeletonRows }) }) })) : null, visibleRows.length === 0 && isQueried && !isSearching ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsxs)("td", { className: 'px-4 py-12 text-center', colSpan: columnCount, 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)("p", { className: 'mt-1 text-sm text-ink/55', children: table_config_1.PsTableConfig.noMatchesDescription }), (0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'mt-3 text-primary hover:underline'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] }) })) : null, grouping
421
- ? groups.map((group, groupIndex) => {
422
- const isExpanded = isGroupExpanded(group.key, groupIndex);
423
- return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, children: (0, jsx_runtime_1.jsx)(ps_table_group_header_1.PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
424
- ? grouping.renderGroupSummary(group.rows)
425
- : undefined }) }) }), isExpanded
426
- ? renderEntries(api, group.rows.map((row, rowIndex) => ({
427
- motion: groupRowMotion(group.key, rowIndex),
428
- row,
429
- })))
430
- : null] }, `group-${group.key}`));
431
- })
432
- : shouldVirtualize
433
- ? [
434
- (0, jsx_runtime_1.jsx)("tr", { "aria-hidden": 'true', children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualTop } }) }, 'virtual-top'),
435
- ...renderEntries(api, virtualItems.map((item) => ({
436
- row: visibleRows[item.index],
437
- virtualItem: item,
438
- }))),
439
- (0, jsx_runtime_1.jsx)("tr", { "aria-hidden": 'true', children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualBottom } }) }, 'virtual-bottom'),
440
- ]
441
- : renderEntries(api, visibleRows.map((row) => ({ row })))] }), hasFooter ? ((0, jsx_runtime_1.jsx)("tfoot", { className: 'border-t-2 border-line bg-mist/50 text-sm font-semibold text-ink', children: (0, jsx_runtime_1.jsxs)("tr", { children: [reorder ? (0, jsx_runtime_1.jsx)("td", { className: pins.reorder }) : null, isSelectable ? (0, jsx_runtime_1.jsx)("td", { className: pins.select }) : null, visibleColumns.map((column, columnIndex) => ((0, jsx_runtime_1.jsx)("td", { className: ps_design_system_1.PallasoftClassNameService.merge(densityClassNames[density].cell, placementOf(column, columnIndex), alignClassNames[column.align !== null && column.align !== undefined
442
- ? column.align
443
- : 'left'], 'whitespace-nowrap'), children: column.footer }, column.id)))] }) })) : null] }))) }), visibleRows.length > 0 && isSearching ? ((0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { className: 'border-t border-line py-3', label: searchingLabel })) : null, showsPagination && paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.top
444
- ? renderPagination('')
445
- : null] })] }));
402
+ 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: [stickyLeading, topContent] })] })), (0, jsx_runtime_1.jsx)("div", { className: 'min-w-0 overflow-clip rounded-[1.25rem]', children: (0, jsx_runtime_1.jsx)("div", { "aria-busy": isRefreshing, className: 'min-w-0 overflow-hidden rounded-[1.25rem] border border-line bg-surface', ref: stickyCardRef, children: (0, jsx_runtime_1.jsxs)("div", { ref: stickyContentRef, children: [showsPagination &&
403
+ paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.bottom &&
404
+ rowCount > ps_table_pagination_config_1.PsTablePaginationConfig.topMinRows
405
+ ? renderPagination('border-b border-t-0')
406
+ : null, mobileLayout === 'cards' ? ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('sm:hidden', isRefreshing ? ps_table_body_classes_1.PsTableBodyClasses.refreshing : ''), 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
407
+ ? groups.map((group, groupIndex) => {
408
+ const isExpanded = isGroupExpanded(group.key, groupIndex);
409
+ return ((0, jsx_runtime_1.jsxs)("div", { className: 'border-b border-line last:border-b-0', children: [(0, jsx_runtime_1.jsx)(ps_table_group_header_1.PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
410
+ ? grouping.renderGroupSummary(group.rows)
411
+ : 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}`));
412
+ })
413
+ : 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', isRefreshing ? ps_table_body_classes_1.PsTableBodyClasses.refreshing : '', 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
414
+ ? ''
415
+ : '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) => {
416
+ const align = column.align !== null && column.align !== undefined
417
+ ? column.align
418
+ : 'left';
419
+ const isSorted = sort !== null && sort.columnId === column.id;
420
+ return ((0, jsx_runtime_1.jsx)("th", { "aria-sort": isSorted
421
+ ? sort.direction
422
+ : column.sortValue && isQueryable
423
+ ? 'none'
424
+ : undefined, className: ps_design_system_1.PallasoftClassNameService.merge(densityClassNames[density].head, alignClassNames[align], placementOf(column, columnIndex), 'whitespace-nowrap'), scope: 'col', style: columnStyle(column, fittedWidths.get(column.id)), children: column.sortValue && isQueryable ? ((0, jsx_runtime_1.jsx)(ps_table_sort_header_1.PsTableSortHeader, { align: align, columnId: column.id, label: column.label, onSort: updateSort, sort: sort })) : (column.label) }, column.id));
425
+ })] }) }), (0, jsx_runtime_1.jsxs)("tbody", { className: 'divide-y divide-line', ref: bodyRef, children: [visibleRows.length === 0 && isSearching ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, children: (0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { label: searchingLabel, skeletonRows: table_config_1.PsTableConfig.searchingSkeletonRows }) }) })) : null, visibleRows.length === 0 && isQueried && !isSearching ? ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsxs)("td", { className: 'px-4 py-12 text-center', colSpan: columnCount, 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)("p", { className: 'mt-1 text-sm text-ink/55', children: table_config_1.PsTableConfig.noMatchesDescription }), (0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_table_control_classes_1.PsTableControlClasses.textButton, 'mt-3 text-primary hover:underline'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] }) })) : null, grouping
426
+ ? groups.map((group, groupIndex) => {
427
+ const isExpanded = isGroupExpanded(group.key, groupIndex);
428
+ return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, children: (0, jsx_runtime_1.jsx)(ps_table_group_header_1.PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
429
+ ? grouping.renderGroupSummary(group.rows)
430
+ : undefined }) }) }), isExpanded
431
+ ? renderEntries(api, group.rows.map((row, rowIndex) => ({
432
+ motion: groupRowMotion(group.key, rowIndex),
433
+ row,
434
+ })))
435
+ : null] }, `group-${group.key}`));
436
+ })
437
+ : shouldVirtualize
438
+ ? [
439
+ (0, jsx_runtime_1.jsx)("tr", { "aria-hidden": 'true', children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualTop } }) }, 'virtual-top'),
440
+ ...renderEntries(api, virtualItems.map((item) => ({
441
+ row: visibleRows[item.index],
442
+ virtualItem: item,
443
+ }))),
444
+ (0, jsx_runtime_1.jsx)("tr", { "aria-hidden": 'true', children: (0, jsx_runtime_1.jsx)("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualBottom } }) }, 'virtual-bottom'),
445
+ ]
446
+ : renderEntries(api, visibleRows.map((row) => ({ row })))] }), hasFooter ? ((0, jsx_runtime_1.jsx)("tfoot", { className: 'border-t-2 border-line bg-mist/50 text-sm font-semibold text-ink', children: (0, jsx_runtime_1.jsxs)("tr", { children: [reorder ? (0, jsx_runtime_1.jsx)("td", { className: pins.reorder }) : null, isSelectable ? (0, jsx_runtime_1.jsx)("td", { className: pins.select }) : null, visibleColumns.map((column, columnIndex) => ((0, jsx_runtime_1.jsx)("td", { className: ps_design_system_1.PallasoftClassNameService.merge(densityClassNames[density].cell, placementOf(column, columnIndex), alignClassNames[column.align !== null && column.align !== undefined
447
+ ? column.align
448
+ : 'left'], 'whitespace-nowrap'), children: column.footer }, column.id)))] }) })) : null] }))) }), visibleRows.length > 0 && isSearching ? ((0, jsx_runtime_1.jsx)(ps_table_searching_state_1.PsTableSearchingState, { className: 'border-t border-line py-3', label: searchingLabel })) : null, showsPagination && paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.top
449
+ ? renderPagination('')
450
+ : null] }) }) })] }));
446
451
  };
447
452
  exports.PsDataTable = PsDataTable;
@@ -0,0 +1,3 @@
1
+ export declare const PsTableBodyClasses: {
2
+ readonly refreshing: "opacity-60";
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsTableBodyClasses = void 0;
4
+ exports.PsTableBodyClasses = {
5
+ refreshing: 'opacity-60',
6
+ };
@@ -1,4 +1,3 @@
1
1
  export declare const PsTableStickyConfig: {
2
2
  readonly cardGapPx: 12;
3
- readonly cardRadius: "1.25rem";
4
3
  };
@@ -3,5 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsTableStickyConfig = void 0;
4
4
  exports.PsTableStickyConfig = {
5
5
  cardGapPx: 12,
6
- cardRadius: '1.25rem',
7
6
  };
@@ -5,6 +5,7 @@ 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
+ import { PsTableBodyClasses } from '../constants/ps-table-body-classes';
8
9
  import { PsTableControlClasses } from '../constants/ps-table-control-classes';
9
10
  import { PsTablePaginationConfig } from '../constants/ps-table-pagination-config';
10
11
  import { PsTablePaginationPosition } from '../constants/ps-table-pagination-position';
@@ -64,6 +65,7 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
64
65
  const stickyRegionRef = useRef(null);
65
66
  const stickySentinelRef = useRef(null);
66
67
  const stickyCardRef = useRef(null);
68
+ const stickyContentRef = useRef(null);
67
69
  const stickyHeadRef = useRef(null);
68
70
  const currentQuery = query ? query : uncontrolledQuery;
69
71
  if (seenClearKey !== clearSelectionKey) {
@@ -94,6 +96,7 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
94
96
  const overflow = usePsTableOverflow(`${visibleColumns.map((column) => column.id).join(',')}:${rows.length}`);
95
97
  const isStuck = usePsStickyHead({
96
98
  cardRef: stickyCardRef,
99
+ contentRef: stickyContentRef,
97
100
  headRef: stickyHeadRef,
98
101
  layoutKey: `${visibleColumns.map((column) => column.id).join(',')}:${rows.length}:${isLoading}`,
99
102
  regionRef: stickyRegionRef,
@@ -360,51 +363,53 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
360
363
  updateQuery({ search: next });
361
364
  resetPage();
362
365
  }, rows: rows, search: search, searchPlaceholder: searchPlaceholder })) : null, banner] }));
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: [stickyLeading, topContent] })] })), _jsxs("div", { "aria-busy": isRefreshing, className: 'min-w-0 overflow-hidden rounded-[1.25rem] border border-line bg-surface', ref: stickyCardRef, children: [showsPagination &&
364
- paginationPosition !== PsTablePaginationPosition.bottom &&
365
- rowCount > PsTablePaginationConfig.topMinRows
366
- ? renderPagination('border-b border-t-0')
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
368
- ? groups.map((group, groupIndex) => {
369
- const isExpanded = isGroupExpanded(group.key, groupIndex);
370
- return (_jsxs("div", { className: 'border-b border-line last:border-b-0', children: [_jsx(PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
371
- ? grouping.renderGroupSummary(group.rows)
372
- : undefined }), _jsx(PsCollapse, { isOpen: isExpanded && !closingGroupKeys.includes(group.key), children: renderCardList(group.rows, null) })] }, `group-${group.key}`));
373
- })
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
375
- ? ''
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) => {
377
- const align = column.align !== null && column.align !== undefined ? column.align : 'left';
378
- const isSorted = sort !== null && sort.columnId === column.id;
379
- return (_jsx("th", { "aria-sort": isSorted
380
- ? sort.direction
381
- : column.sortValue && isQueryable
382
- ? 'none'
383
- : undefined, className: PallasoftClassNameService.merge(densityClassNames[density].head, alignClassNames[align], placementOf(column, columnIndex), 'whitespace-nowrap'), scope: 'col', style: columnStyle(column, fittedWidths.get(column.id)), children: column.sortValue && isQueryable ? (_jsx(PsTableSortHeader, { align: align, columnId: column.id, label: column.label, onSort: updateSort, sort: sort })) : (column.label) }, column.id));
384
- })] }) }), _jsxs("tbody", { className: 'divide-y divide-line', ref: bodyRef, children: [visibleRows.length === 0 && isSearching ? (_jsx("tr", { children: _jsx("td", { className: 'p-0', colSpan: columnCount, children: _jsx(PsTableSearchingState, { label: searchingLabel, skeletonRows: PsTableConfig.searchingSkeletonRows }) }) })) : null, visibleRows.length === 0 && isQueried && !isSearching ? (_jsx("tr", { children: _jsxs("td", { className: 'px-4 py-12 text-center', colSpan: columnCount, children: [_jsx("p", { className: 'text-sm font-semibold text-ink', children: PsTableConfig.noMatchesTitle }), _jsx("p", { className: 'mt-1 text-sm text-ink/55', children: PsTableConfig.noMatchesDescription }), _jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'mt-3 text-primary hover:underline'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] }) })) : null, grouping
385
- ? groups.map((group, groupIndex) => {
386
- const isExpanded = isGroupExpanded(group.key, groupIndex);
387
- return (_jsxs(Fragment, { children: [_jsx("tr", { children: _jsx("td", { className: 'p-0', colSpan: columnCount, children: _jsx(PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
388
- ? grouping.renderGroupSummary(group.rows)
389
- : undefined }) }) }), isExpanded
390
- ? renderEntries(api, group.rows.map((row, rowIndex) => ({
391
- motion: groupRowMotion(group.key, rowIndex),
392
- row,
393
- })))
394
- : null] }, `group-${group.key}`));
395
- })
396
- : shouldVirtualize
397
- ? [
398
- _jsx("tr", { "aria-hidden": 'true', children: _jsx("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualTop } }) }, 'virtual-top'),
399
- ...renderEntries(api, virtualItems.map((item) => ({
400
- row: visibleRows[item.index],
401
- virtualItem: item,
402
- }))),
403
- _jsx("tr", { "aria-hidden": 'true', children: _jsx("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualBottom } }) }, 'virtual-bottom'),
404
- ]
405
- : renderEntries(api, visibleRows.map((row) => ({ row })))] }), hasFooter ? (_jsx("tfoot", { className: 'border-t-2 border-line bg-mist/50 text-sm font-semibold text-ink', children: _jsxs("tr", { children: [reorder ? _jsx("td", { className: pins.reorder }) : null, isSelectable ? _jsx("td", { className: pins.select }) : null, visibleColumns.map((column, columnIndex) => (_jsx("td", { className: PallasoftClassNameService.merge(densityClassNames[density].cell, placementOf(column, columnIndex), alignClassNames[column.align !== null && column.align !== undefined
406
- ? column.align
407
- : 'left'], 'whitespace-nowrap'), children: column.footer }, column.id)))] }) })) : null] }))) }), visibleRows.length > 0 && isSearching ? (_jsx(PsTableSearchingState, { className: 'border-t border-line py-3', label: searchingLabel })) : null, showsPagination && paginationPosition !== PsTablePaginationPosition.top
408
- ? renderPagination('')
409
- : null] })] }));
366
+ 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: [stickyLeading, topContent] })] })), _jsx("div", { className: 'min-w-0 overflow-clip rounded-[1.25rem]', children: _jsx("div", { "aria-busy": isRefreshing, className: 'min-w-0 overflow-hidden rounded-[1.25rem] border border-line bg-surface', ref: stickyCardRef, children: _jsxs("div", { ref: stickyContentRef, children: [showsPagination &&
367
+ paginationPosition !== PsTablePaginationPosition.bottom &&
368
+ rowCount > PsTablePaginationConfig.topMinRows
369
+ ? renderPagination('border-b border-t-0')
370
+ : null, mobileLayout === 'cards' ? (_jsxs("div", { className: PallasoftClassNameService.merge('sm:hidden', isRefreshing ? PsTableBodyClasses.refreshing : ''), 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
371
+ ? groups.map((group, groupIndex) => {
372
+ const isExpanded = isGroupExpanded(group.key, groupIndex);
373
+ return (_jsxs("div", { className: 'border-b border-line last:border-b-0', children: [_jsx(PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
374
+ ? grouping.renderGroupSummary(group.rows)
375
+ : undefined }), _jsx(PsCollapse, { isOpen: isExpanded && !closingGroupKeys.includes(group.key), children: renderCardList(group.rows, null) })] }, `group-${group.key}`));
376
+ })
377
+ : 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', isRefreshing ? PsTableBodyClasses.refreshing : '', 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
378
+ ? ''
379
+ : '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) => {
380
+ const align = column.align !== null && column.align !== undefined
381
+ ? column.align
382
+ : 'left';
383
+ const isSorted = sort !== null && sort.columnId === column.id;
384
+ return (_jsx("th", { "aria-sort": isSorted
385
+ ? sort.direction
386
+ : column.sortValue && isQueryable
387
+ ? 'none'
388
+ : undefined, className: PallasoftClassNameService.merge(densityClassNames[density].head, alignClassNames[align], placementOf(column, columnIndex), 'whitespace-nowrap'), scope: 'col', style: columnStyle(column, fittedWidths.get(column.id)), children: column.sortValue && isQueryable ? (_jsx(PsTableSortHeader, { align: align, columnId: column.id, label: column.label, onSort: updateSort, sort: sort })) : (column.label) }, column.id));
389
+ })] }) }), _jsxs("tbody", { className: 'divide-y divide-line', ref: bodyRef, children: [visibleRows.length === 0 && isSearching ? (_jsx("tr", { children: _jsx("td", { className: 'p-0', colSpan: columnCount, children: _jsx(PsTableSearchingState, { label: searchingLabel, skeletonRows: PsTableConfig.searchingSkeletonRows }) }) })) : null, visibleRows.length === 0 && isQueried && !isSearching ? (_jsx("tr", { children: _jsxs("td", { className: 'px-4 py-12 text-center', colSpan: columnCount, children: [_jsx("p", { className: 'text-sm font-semibold text-ink', children: PsTableConfig.noMatchesTitle }), _jsx("p", { className: 'mt-1 text-sm text-ink/55', children: PsTableConfig.noMatchesDescription }), _jsx("button", { className: PallasoftClassNameService.merge(PsTableControlClasses.textButton, 'mt-3 text-primary hover:underline'), onClick: clearFilters, type: 'button', children: "Clear search and filters" })] }) })) : null, grouping
390
+ ? groups.map((group, groupIndex) => {
391
+ const isExpanded = isGroupExpanded(group.key, groupIndex);
392
+ return (_jsxs(Fragment, { children: [_jsx("tr", { children: _jsx("td", { className: 'p-0', colSpan: columnCount, children: _jsx(PsTableGroupHeader, { count: group.rows.length, isExpanded: isExpanded, label: grouping.getGroupLabel(group.key, group.rows), onToggle: () => toggleGroup(group.key, isExpanded), summary: grouping.renderGroupSummary
393
+ ? grouping.renderGroupSummary(group.rows)
394
+ : undefined }) }) }), isExpanded
395
+ ? renderEntries(api, group.rows.map((row, rowIndex) => ({
396
+ motion: groupRowMotion(group.key, rowIndex),
397
+ row,
398
+ })))
399
+ : null] }, `group-${group.key}`));
400
+ })
401
+ : shouldVirtualize
402
+ ? [
403
+ _jsx("tr", { "aria-hidden": 'true', children: _jsx("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualTop } }) }, 'virtual-top'),
404
+ ...renderEntries(api, virtualItems.map((item) => ({
405
+ row: visibleRows[item.index],
406
+ virtualItem: item,
407
+ }))),
408
+ _jsx("tr", { "aria-hidden": 'true', children: _jsx("td", { className: 'p-0', colSpan: columnCount, style: { height: virtualBottom } }) }, 'virtual-bottom'),
409
+ ]
410
+ : renderEntries(api, visibleRows.map((row) => ({ row })))] }), hasFooter ? (_jsx("tfoot", { className: 'border-t-2 border-line bg-mist/50 text-sm font-semibold text-ink', children: _jsxs("tr", { children: [reorder ? _jsx("td", { className: pins.reorder }) : null, isSelectable ? _jsx("td", { className: pins.select }) : null, visibleColumns.map((column, columnIndex) => (_jsx("td", { className: PallasoftClassNameService.merge(densityClassNames[density].cell, placementOf(column, columnIndex), alignClassNames[column.align !== null && column.align !== undefined
411
+ ? column.align
412
+ : 'left'], 'whitespace-nowrap'), children: column.footer }, column.id)))] }) })) : null] }))) }), visibleRows.length > 0 && isSearching ? (_jsx(PsTableSearchingState, { className: 'border-t border-line py-3', label: searchingLabel })) : null, showsPagination && paginationPosition !== PsTablePaginationPosition.top
413
+ ? renderPagination('')
414
+ : null] }) }) })] }));
410
415
  };
@@ -0,0 +1,3 @@
1
+ export const PsTableBodyClasses = {
2
+ refreshing: 'opacity-60',
3
+ };
@@ -1,4 +1,3 @@
1
1
  export const PsTableStickyConfig = {
2
2
  cardGapPx: 12,
3
- cardRadius: '1.25rem',
4
3
  };
@@ -2,18 +2,20 @@ import { useLayoutEffect, useState } from 'react';
2
2
  import { PsTableStickyConfig } from '../constants/ps-table-sticky-config';
3
3
  import { PsTableScrollService } from '../services/ps-table-scroll-service';
4
4
  import { PsTableStickyHeadService } from '../services/ps-table-sticky-head-service';
5
- export const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
5
+ export const usePsStickyHead = ({ cardRef, contentRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
6
6
  const [isStuck, setIsStuck] = useState(false);
7
7
  useLayoutEffect(() => {
8
8
  const region = regionRef.current;
9
9
  const sentinel = sentinelRef.current;
10
10
  const card = cardRef.current;
11
+ const content = contentRef.current;
11
12
  const head = headRef.current;
12
13
  const table = head === null ? null : head.parentElement;
13
14
  if (stickyTop === undefined ||
14
15
  region === null ||
15
16
  sentinel === null ||
16
17
  card === null ||
18
+ content === null ||
17
19
  head === null ||
18
20
  table === null)
19
21
  return;
@@ -33,7 +35,7 @@ export const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentin
33
35
  const scrollRange = scroller.scrollHeight - scroller.clientHeight;
34
36
  const timeline = new Timeline({ axis: 'block', source: scroller });
35
37
  const headFrames = PsTableStickyHeadService.keyframes(table.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, headTravel(), scrollRange);
36
- const cardFrames = PsTableStickyHeadService.keyframes(card.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, card.offsetHeight, scrollRange);
38
+ const cardFrames = PsTableStickyHeadService.keyframes(content.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, card.offsetHeight, scrollRange);
37
39
  animations.forEach((animation) => animation.cancel());
38
40
  animations = [
39
41
  head.animate(headFrames.map((keyframe) => ({
@@ -41,15 +43,21 @@ export const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentin
41
43
  transform: `translateY(${keyframe.shift}px)`,
42
44
  })), { fill: 'both', timeline }),
43
45
  card.animate(cardFrames.map((keyframe) => ({
44
- clipPath: PsTableStickyHeadService.clip(keyframe.shift),
45
46
  offset: keyframe.offset,
47
+ transform: `translateY(${keyframe.shift}px)`,
48
+ })), { fill: 'both', timeline }),
49
+ content.animate(cardFrames.map((keyframe) => ({
50
+ offset: keyframe.offset,
51
+ transform: `translateY(${-keyframe.shift}px)`,
46
52
  })), { fill: 'both', timeline }),
47
53
  ];
48
54
  };
49
55
  const follow = () => {
50
56
  const pinnedLine = region.getBoundingClientRect().bottom + PsTableStickyConfig.cardGapPx;
51
57
  head.style.transform = `translateY(${PsTableStickyHeadService.offset(pinnedLine, table.getBoundingClientRect().top, table.offsetHeight, head.offsetHeight)}px)`;
52
- card.style.clipPath = PsTableStickyHeadService.clip(PsTableStickyHeadService.offset(pinnedLine, card.getBoundingClientRect().top, card.offsetHeight, 0));
58
+ const cut = PsTableStickyHeadService.offset(pinnedLine, content.getBoundingClientRect().top, card.offsetHeight, 0);
59
+ card.style.transform = `translateY(${cut}px)`;
60
+ content.style.transform = `translateY(${-cut}px)`;
53
61
  };
54
62
  const check = () => {
55
63
  frame = 0;
@@ -78,12 +86,13 @@ export const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentin
78
86
  observer.disconnect();
79
87
  animations.forEach((animation) => animation.cancel());
80
88
  head.style.transform = '';
81
- card.style.clipPath = '';
89
+ card.style.transform = '';
90
+ content.style.transform = '';
82
91
  window.removeEventListener('scroll', schedule, { capture: true });
83
92
  window.removeEventListener('resize', measure);
84
93
  if (frame !== 0)
85
94
  window.cancelAnimationFrame(frame);
86
95
  };
87
- }, [cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
96
+ }, [cardRef, contentRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
88
97
  return isStuck;
89
98
  };
@@ -1,4 +1,3 @@
1
- import { PsTableStickyConfig } from '../constants/ps-table-sticky-config';
2
1
  export class PsTableStickyHeadService {
3
2
  static offset(pinnedBottom, tableTop, tableHeight, headHeight) {
4
3
  return Math.min(Math.max(pinnedBottom - tableTop, 0), Math.max(tableHeight - headHeight, 0));
@@ -12,10 +11,6 @@ export class PsTableStickyHeadService {
12
11
  shift: shiftAt(scroll),
13
12
  }));
14
13
  }
15
- static clip(shift) {
16
- const radius = PsTableStickyConfig.cardRadius;
17
- return `inset(${shift}px 0 0 0 round ${radius} ${radius} 0 0)`;
18
- }
19
14
  static stops(scrolls, scrollRange) {
20
15
  const inside = scrolls.filter((scroll) => scroll >= 0 && scroll <= scrollRange);
21
16
  return inside.filter((scroll, index) => inside.indexOf(scroll) === index);
@@ -1,2 +1,2 @@
1
1
  import type { PsStickyHeadRefs } from '../interfaces/ps-sticky-head-refs';
2
- export declare const usePsStickyHead: ({ cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }: PsStickyHeadRefs) => boolean;
2
+ export declare const usePsStickyHead: ({ cardRef, contentRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }: PsStickyHeadRefs) => boolean;
@@ -5,18 +5,20 @@ const react_1 = require("react");
5
5
  const ps_table_sticky_config_1 = require("../constants/ps-table-sticky-config");
6
6
  const ps_table_scroll_service_1 = require("../services/ps-table-scroll-service");
7
7
  const ps_table_sticky_head_service_1 = require("../services/ps-table-sticky-head-service");
8
- const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
8
+ const usePsStickyHead = ({ cardRef, contentRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
9
9
  const [isStuck, setIsStuck] = (0, react_1.useState)(false);
10
10
  (0, react_1.useLayoutEffect)(() => {
11
11
  const region = regionRef.current;
12
12
  const sentinel = sentinelRef.current;
13
13
  const card = cardRef.current;
14
+ const content = contentRef.current;
14
15
  const head = headRef.current;
15
16
  const table = head === null ? null : head.parentElement;
16
17
  if (stickyTop === undefined ||
17
18
  region === null ||
18
19
  sentinel === null ||
19
20
  card === null ||
21
+ content === null ||
20
22
  head === null ||
21
23
  table === null)
22
24
  return;
@@ -36,7 +38,7 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
36
38
  const scrollRange = scroller.scrollHeight - scroller.clientHeight;
37
39
  const timeline = new Timeline({ axis: 'block', source: scroller });
38
40
  const headFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(table.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, headTravel(), scrollRange);
39
- const cardFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(card.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, card.offsetHeight, scrollRange);
41
+ const cardFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(content.getBoundingClientRect().top + scroller.scrollTop - pinnedLine, card.offsetHeight, scrollRange);
40
42
  animations.forEach((animation) => animation.cancel());
41
43
  animations = [
42
44
  head.animate(headFrames.map((keyframe) => ({
@@ -44,15 +46,21 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
44
46
  transform: `translateY(${keyframe.shift}px)`,
45
47
  })), { fill: 'both', timeline }),
46
48
  card.animate(cardFrames.map((keyframe) => ({
47
- clipPath: ps_table_sticky_head_service_1.PsTableStickyHeadService.clip(keyframe.shift),
48
49
  offset: keyframe.offset,
50
+ transform: `translateY(${keyframe.shift}px)`,
51
+ })), { fill: 'both', timeline }),
52
+ content.animate(cardFrames.map((keyframe) => ({
53
+ offset: keyframe.offset,
54
+ transform: `translateY(${-keyframe.shift}px)`,
49
55
  })), { fill: 'both', timeline }),
50
56
  ];
51
57
  };
52
58
  const follow = () => {
53
59
  const pinnedLine = region.getBoundingClientRect().bottom + ps_table_sticky_config_1.PsTableStickyConfig.cardGapPx;
54
60
  head.style.transform = `translateY(${ps_table_sticky_head_service_1.PsTableStickyHeadService.offset(pinnedLine, table.getBoundingClientRect().top, table.offsetHeight, head.offsetHeight)}px)`;
55
- card.style.clipPath = ps_table_sticky_head_service_1.PsTableStickyHeadService.clip(ps_table_sticky_head_service_1.PsTableStickyHeadService.offset(pinnedLine, card.getBoundingClientRect().top, card.offsetHeight, 0));
61
+ const cut = ps_table_sticky_head_service_1.PsTableStickyHeadService.offset(pinnedLine, content.getBoundingClientRect().top, card.offsetHeight, 0);
62
+ card.style.transform = `translateY(${cut}px)`;
63
+ content.style.transform = `translateY(${-cut}px)`;
56
64
  };
57
65
  const check = () => {
58
66
  frame = 0;
@@ -81,13 +89,14 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
81
89
  observer.disconnect();
82
90
  animations.forEach((animation) => animation.cancel());
83
91
  head.style.transform = '';
84
- card.style.clipPath = '';
92
+ card.style.transform = '';
93
+ content.style.transform = '';
85
94
  window.removeEventListener('scroll', schedule, { capture: true });
86
95
  window.removeEventListener('resize', measure);
87
96
  if (frame !== 0)
88
97
  window.cancelAnimationFrame(frame);
89
98
  };
90
- }, [cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
99
+ }, [cardRef, contentRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
91
100
  return isStuck;
92
101
  };
93
102
  exports.usePsStickyHead = usePsStickyHead;
@@ -1,6 +1,7 @@
1
1
  import type { RefObject } from 'react';
2
2
  export interface PsStickyHeadRefs {
3
3
  cardRef: RefObject<HTMLDivElement | null>;
4
+ contentRef: RefObject<HTMLDivElement | null>;
4
5
  headRef: RefObject<HTMLTableSectionElement | null>;
5
6
  layoutKey: string;
6
7
  regionRef: RefObject<HTMLDivElement | null>;
@@ -2,6 +2,5 @@ import type { PsTableStickyHeadKeyframe } from '../interfaces/ps-table-sticky-he
2
2
  export declare class PsTableStickyHeadService {
3
3
  static offset(pinnedBottom: number, tableTop: number, tableHeight: number, headHeight: number): number;
4
4
  static keyframes(pinScroll: number, maxShift: number, scrollRange: number): PsTableStickyHeadKeyframe[];
5
- static clip(shift: number): string;
6
5
  private static stops;
7
6
  }
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsTableStickyHeadService = void 0;
4
- const ps_table_sticky_config_1 = require("../constants/ps-table-sticky-config");
5
4
  class PsTableStickyHeadService {
6
5
  static offset(pinnedBottom, tableTop, tableHeight, headHeight) {
7
6
  return Math.min(Math.max(pinnedBottom - tableTop, 0), Math.max(tableHeight - headHeight, 0));
@@ -15,10 +14,6 @@ class PsTableStickyHeadService {
15
14
  shift: shiftAt(scroll),
16
15
  }));
17
16
  }
18
- static clip(shift) {
19
- const radius = ps_table_sticky_config_1.PsTableStickyConfig.cardRadius;
20
- return `inset(${shift}px 0 0 0 round ${radius} ${radius} 0 0)`;
21
- }
22
17
  static stops(scrolls, scrollRange) {
23
18
  const inside = scrolls.filter((scroll) => scroll >= 0 && scroll <= scrollRange);
24
19
  return inside.filter((scroll, index) => inside.indexOf(scroll) === index);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-table-components",
3
- "version": "1.28.2",
3
+ "version": "1.28.4",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",