@pallasoft/ps-table-components 1.28.0 → 1.28.1
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.js +1 -1
- package/dist/constants/ps-table-sticky-config.d.ts +3 -0
- package/dist/constants/ps-table-sticky-config.js +6 -0
- package/dist/esm/components/ps-data-table.js +1 -1
- package/dist/esm/constants/ps-table-sticky-config.js +3 -0
- package/dist/esm/hooks/use-ps-sticky-head.js +32 -16
- package/dist/esm/interfaces/ps-table-sticky-backdrop-keyframe.js +1 -0
- package/dist/esm/services/ps-table-sticky-head-service.js +11 -4
- package/dist/hooks/use-ps-sticky-head.js +32 -16
- package/dist/interfaces/ps-table-sticky-backdrop-keyframe.d.ts +4 -0
- package/dist/interfaces/ps-table-sticky-backdrop-keyframe.js +2 -0
- package/dist/services/ps-table-sticky-head-service.d.ts +3 -0
- package/dist/services/ps-table-sticky-head-service.js +11 -4
- package/package.json +1 -1
|
@@ -396,7 +396,7 @@ const PsDataTable = ({ caption, className, clearSelectionKey, columns, cursorPag
|
|
|
396
396
|
updateQuery({ search: next });
|
|
397
397
|
resetPage();
|
|
398
398
|
}, 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: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className:
|
|
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-glass-strong pointer-events-none absolute -inset-x-3 -bottom-3 rounded-b-ps-card border-t-0 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
400
|
paginationPosition !== ps_table_pagination_position_1.PsTablePaginationPosition.bottom &&
|
|
401
401
|
rowCount > ps_table_pagination_config_1.PsTablePaginationConfig.topMinRows
|
|
402
402
|
? renderPagination('border-b border-t-0')
|
|
@@ -360,7 +360,7 @@ export const PsDataTable = ({ caption, className, clearSelectionKey, columns, cu
|
|
|
360
360
|
updateQuery({ search: next });
|
|
361
361
|
resetPage();
|
|
362
362
|
}, 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: [_jsx("div", { "aria-hidden": 'true', className:
|
|
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: 'ps-glass-strong pointer-events-none absolute -inset-x-3 -bottom-3 rounded-b-ps-card border-t-0 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
364
|
paginationPosition !== PsTablePaginationPosition.bottom &&
|
|
365
365
|
rowCount > PsTablePaginationConfig.topMinRows
|
|
366
366
|
? renderPagination('border-b border-t-0')
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useLayoutEffect, useState } from 'react';
|
|
2
|
+
import { PsTableStickyConfig } from '../constants/ps-table-sticky-config';
|
|
2
3
|
import { PsTableScrollService } from '../services/ps-table-scroll-service';
|
|
3
4
|
import { PsTableStickyHeadService } from '../services/ps-table-sticky-head-service';
|
|
4
5
|
export const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
|
|
@@ -19,7 +20,7 @@ export const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, se
|
|
|
19
20
|
const scroller = PsTableScrollService.parent(region);
|
|
20
21
|
const Timeline = window.ScrollTimeline;
|
|
21
22
|
const isDriven = scroller !== null && Timeline !== undefined;
|
|
22
|
-
let
|
|
23
|
+
let animations = [];
|
|
23
24
|
let frame = 0;
|
|
24
25
|
const maxShift = () => Math.max(table.offsetHeight - head.offsetHeight, 0);
|
|
25
26
|
const drive = () => {
|
|
@@ -32,23 +33,38 @@ export const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, se
|
|
|
32
33
|
backdrop.getBoundingClientRect().bottom -
|
|
33
34
|
regionTop;
|
|
34
35
|
const pinScroll = table.getBoundingClientRect().top + scroller.scrollTop - pinnedBottom;
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
const barPinScroll = sentinel.getBoundingClientRect().top -
|
|
37
|
+
scrollerTop +
|
|
38
|
+
scroller.scrollTop -
|
|
39
|
+
Number.parseFloat(getComputedStyle(region).top);
|
|
40
|
+
const scrollRange = scroller.scrollHeight - scroller.clientHeight;
|
|
41
|
+
const timeline = new Timeline({ axis: 'block', source: scroller });
|
|
42
|
+
const headFrames = PsTableStickyHeadService.keyframes(pinScroll, maxShift(), scrollRange);
|
|
43
|
+
const backdropFrames = PsTableStickyHeadService.backdropKeyframes(barPinScroll, PsTableStickyConfig.backdropFadePx, scrollRange);
|
|
44
|
+
animations.forEach((animation) => animation.cancel());
|
|
45
|
+
animations =
|
|
46
|
+
headFrames.length === 0
|
|
47
|
+
? []
|
|
48
|
+
: [
|
|
49
|
+
head.animate(headFrames.map((keyframe) => ({
|
|
50
|
+
offset: keyframe.offset,
|
|
51
|
+
transform: `translateY(${keyframe.shift}px)`,
|
|
52
|
+
})), { fill: 'both', timeline }),
|
|
53
|
+
backdrop.animate(backdropFrames.map((keyframe) => ({
|
|
54
|
+
offset: keyframe.offset,
|
|
55
|
+
opacity: keyframe.opacity,
|
|
56
|
+
})), { fill: 'both', timeline }),
|
|
57
|
+
];
|
|
45
58
|
};
|
|
46
59
|
const follow = () => (head.style.transform = `translateY(${PsTableStickyHeadService.offset(backdrop.getBoundingClientRect().bottom, table.getBoundingClientRect().top, table.offsetHeight, head.offsetHeight)}px)`);
|
|
47
60
|
const check = () => {
|
|
61
|
+
const stuck = sentinel.getBoundingClientRect().top < region.getBoundingClientRect().top - 1;
|
|
48
62
|
frame = 0;
|
|
49
|
-
setIsStuck(
|
|
50
|
-
if (
|
|
51
|
-
|
|
63
|
+
setIsStuck(stuck);
|
|
64
|
+
if (isDriven)
|
|
65
|
+
return;
|
|
66
|
+
backdrop.style.opacity = stuck ? '1' : '0';
|
|
67
|
+
follow();
|
|
52
68
|
};
|
|
53
69
|
const schedule = () => {
|
|
54
70
|
if (frame === 0)
|
|
@@ -69,9 +85,9 @@ export const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, se
|
|
|
69
85
|
window.addEventListener('resize', measure);
|
|
70
86
|
return () => {
|
|
71
87
|
observer.disconnect();
|
|
72
|
-
|
|
73
|
-
animation.cancel();
|
|
88
|
+
animations.forEach((animation) => animation.cancel());
|
|
74
89
|
head.style.transform = '';
|
|
90
|
+
backdrop.style.opacity = '';
|
|
75
91
|
window.removeEventListener('scroll', schedule, { capture: true });
|
|
76
92
|
window.removeEventListener('resize', measure);
|
|
77
93
|
if (frame !== 0)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,12 +6,19 @@ export class PsTableStickyHeadService {
|
|
|
6
6
|
if (scrollRange <= 0)
|
|
7
7
|
return [];
|
|
8
8
|
const shiftAt = (scroll) => Math.min(Math.max(scroll - pinScroll, 0), maxShift);
|
|
9
|
-
|
|
10
|
-
return stops
|
|
11
|
-
.filter((scroll, index) => stops.indexOf(scroll) === index)
|
|
12
|
-
.map((scroll) => ({
|
|
9
|
+
return PsTableStickyHeadService.stops([0, pinScroll, pinScroll + maxShift, scrollRange], scrollRange).map((scroll) => ({
|
|
13
10
|
offset: scroll / scrollRange,
|
|
14
11
|
shift: shiftAt(scroll),
|
|
15
12
|
}));
|
|
16
13
|
}
|
|
14
|
+
static backdropKeyframes(pinScroll, fade, scrollRange) {
|
|
15
|
+
if (scrollRange <= 0)
|
|
16
|
+
return [];
|
|
17
|
+
const opacityAt = (scroll) => Math.min(Math.max((scroll - pinScroll + fade) / fade, 0), 1);
|
|
18
|
+
return PsTableStickyHeadService.stops([0, pinScroll - fade, pinScroll, scrollRange], scrollRange).map((scroll) => ({ offset: scroll / scrollRange, opacity: opacityAt(scroll) }));
|
|
19
|
+
}
|
|
20
|
+
static stops(scrolls, scrollRange) {
|
|
21
|
+
const inside = scrolls.filter((scroll) => scroll >= 0 && scroll <= scrollRange);
|
|
22
|
+
return inside.filter((scroll, index) => inside.indexOf(scroll) === index);
|
|
23
|
+
}
|
|
17
24
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.usePsStickyHead = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
+
const ps_table_sticky_config_1 = require("../constants/ps-table-sticky-config");
|
|
5
6
|
const ps_table_scroll_service_1 = require("../services/ps-table-scroll-service");
|
|
6
7
|
const ps_table_sticky_head_service_1 = require("../services/ps-table-sticky-head-service");
|
|
7
8
|
const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop, }) => {
|
|
@@ -22,7 +23,7 @@ const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelR
|
|
|
22
23
|
const scroller = ps_table_scroll_service_1.PsTableScrollService.parent(region);
|
|
23
24
|
const Timeline = window.ScrollTimeline;
|
|
24
25
|
const isDriven = scroller !== null && Timeline !== undefined;
|
|
25
|
-
let
|
|
26
|
+
let animations = [];
|
|
26
27
|
let frame = 0;
|
|
27
28
|
const maxShift = () => Math.max(table.offsetHeight - head.offsetHeight, 0);
|
|
28
29
|
const drive = () => {
|
|
@@ -35,23 +36,38 @@ const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelR
|
|
|
35
36
|
backdrop.getBoundingClientRect().bottom -
|
|
36
37
|
regionTop;
|
|
37
38
|
const pinScroll = table.getBoundingClientRect().top + scroller.scrollTop - pinnedBottom;
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
const barPinScroll = sentinel.getBoundingClientRect().top -
|
|
40
|
+
scrollerTop +
|
|
41
|
+
scroller.scrollTop -
|
|
42
|
+
Number.parseFloat(getComputedStyle(region).top);
|
|
43
|
+
const scrollRange = scroller.scrollHeight - scroller.clientHeight;
|
|
44
|
+
const timeline = new Timeline({ axis: 'block', source: scroller });
|
|
45
|
+
const headFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(pinScroll, maxShift(), scrollRange);
|
|
46
|
+
const backdropFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.backdropKeyframes(barPinScroll, ps_table_sticky_config_1.PsTableStickyConfig.backdropFadePx, scrollRange);
|
|
47
|
+
animations.forEach((animation) => animation.cancel());
|
|
48
|
+
animations =
|
|
49
|
+
headFrames.length === 0
|
|
50
|
+
? []
|
|
51
|
+
: [
|
|
52
|
+
head.animate(headFrames.map((keyframe) => ({
|
|
53
|
+
offset: keyframe.offset,
|
|
54
|
+
transform: `translateY(${keyframe.shift}px)`,
|
|
55
|
+
})), { fill: 'both', timeline }),
|
|
56
|
+
backdrop.animate(backdropFrames.map((keyframe) => ({
|
|
57
|
+
offset: keyframe.offset,
|
|
58
|
+
opacity: keyframe.opacity,
|
|
59
|
+
})), { fill: 'both', timeline }),
|
|
60
|
+
];
|
|
48
61
|
};
|
|
49
62
|
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
63
|
const check = () => {
|
|
64
|
+
const stuck = sentinel.getBoundingClientRect().top < region.getBoundingClientRect().top - 1;
|
|
51
65
|
frame = 0;
|
|
52
|
-
setIsStuck(
|
|
53
|
-
if (
|
|
54
|
-
|
|
66
|
+
setIsStuck(stuck);
|
|
67
|
+
if (isDriven)
|
|
68
|
+
return;
|
|
69
|
+
backdrop.style.opacity = stuck ? '1' : '0';
|
|
70
|
+
follow();
|
|
55
71
|
};
|
|
56
72
|
const schedule = () => {
|
|
57
73
|
if (frame === 0)
|
|
@@ -72,9 +88,9 @@ const usePsStickyHead = ({ backdropRef, headRef, layoutKey, regionRef, sentinelR
|
|
|
72
88
|
window.addEventListener('resize', measure);
|
|
73
89
|
return () => {
|
|
74
90
|
observer.disconnect();
|
|
75
|
-
|
|
76
|
-
animation.cancel();
|
|
91
|
+
animations.forEach((animation) => animation.cancel());
|
|
77
92
|
head.style.transform = '';
|
|
93
|
+
backdrop.style.opacity = '';
|
|
78
94
|
window.removeEventListener('scroll', schedule, { capture: true });
|
|
79
95
|
window.removeEventListener('resize', measure);
|
|
80
96
|
if (frame !== 0)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { PsTableStickyBackdropKeyframe } from '../interfaces/ps-table-sticky-backdrop-keyframe';
|
|
1
2
|
import type { PsTableStickyHeadKeyframe } from '../interfaces/ps-table-sticky-head-keyframe';
|
|
2
3
|
export declare class PsTableStickyHeadService {
|
|
3
4
|
static offset(pinnedBottom: number, tableTop: number, tableHeight: number, headHeight: number): number;
|
|
4
5
|
static keyframes(pinScroll: number, maxShift: number, scrollRange: number): PsTableStickyHeadKeyframe[];
|
|
6
|
+
static backdropKeyframes(pinScroll: number, fade: number, scrollRange: number): PsTableStickyBackdropKeyframe[];
|
|
7
|
+
private static stops;
|
|
5
8
|
}
|
|
@@ -9,13 +9,20 @@ class PsTableStickyHeadService {
|
|
|
9
9
|
if (scrollRange <= 0)
|
|
10
10
|
return [];
|
|
11
11
|
const shiftAt = (scroll) => Math.min(Math.max(scroll - pinScroll, 0), maxShift);
|
|
12
|
-
|
|
13
|
-
return stops
|
|
14
|
-
.filter((scroll, index) => stops.indexOf(scroll) === index)
|
|
15
|
-
.map((scroll) => ({
|
|
12
|
+
return PsTableStickyHeadService.stops([0, pinScroll, pinScroll + maxShift, scrollRange], scrollRange).map((scroll) => ({
|
|
16
13
|
offset: scroll / scrollRange,
|
|
17
14
|
shift: shiftAt(scroll),
|
|
18
15
|
}));
|
|
19
16
|
}
|
|
17
|
+
static backdropKeyframes(pinScroll, fade, scrollRange) {
|
|
18
|
+
if (scrollRange <= 0)
|
|
19
|
+
return [];
|
|
20
|
+
const opacityAt = (scroll) => Math.min(Math.max((scroll - pinScroll + fade) / fade, 0), 1);
|
|
21
|
+
return PsTableStickyHeadService.stops([0, pinScroll - fade, pinScroll, scrollRange], scrollRange).map((scroll) => ({ offset: scroll / scrollRange, opacity: opacityAt(scroll) }));
|
|
22
|
+
}
|
|
23
|
+
static stops(scrolls, scrollRange) {
|
|
24
|
+
const inside = scrolls.filter((scroll) => scroll >= 0 && scroll <= scrollRange);
|
|
25
|
+
return inside.filter((scroll, index) => inside.indexOf(scroll) === index);
|
|
26
|
+
}
|
|
20
27
|
}
|
|
21
28
|
exports.PsTableStickyHeadService = PsTableStickyHeadService;
|