@pallasoft/ps-table-components 1.28.3 → 1.29.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.
Files changed (52) hide show
  1. package/dist/components/ps-data-table.js +52 -50
  2. package/dist/components/ps-report-table-skeleton.d.ts +10 -0
  3. package/dist/components/ps-report-table-skeleton.js +29 -0
  4. package/dist/components/ps-report-table.d.ts +28 -0
  5. package/dist/components/ps-report-table.js +45 -0
  6. package/dist/constants/ps-report-column-align.d.ts +6 -0
  7. package/dist/constants/ps-report-column-align.js +8 -0
  8. package/dist/constants/ps-report-row-kind.d.ts +7 -0
  9. package/dist/constants/ps-report-row-kind.js +9 -0
  10. package/dist/constants/ps-report-row-tone.d.ts +7 -0
  11. package/dist/constants/ps-report-row-tone.js +9 -0
  12. package/dist/constants/ps-report-table-classes.d.ts +52 -0
  13. package/dist/constants/ps-report-table-classes.js +59 -0
  14. package/dist/constants/ps-report-table-config.d.ts +9 -0
  15. package/dist/constants/ps-report-table-config.js +9 -0
  16. package/dist/constants/ps-report-table-density.d.ts +5 -0
  17. package/dist/constants/ps-report-table-density.js +7 -0
  18. package/dist/constants/ps-table-sticky-config.d.ts +1 -1
  19. package/dist/constants/ps-table-sticky-config.js +1 -1
  20. package/dist/esm/components/ps-data-table.js +52 -50
  21. package/dist/esm/components/ps-report-table-skeleton.js +25 -0
  22. package/dist/esm/components/ps-report-table.js +41 -0
  23. package/dist/esm/constants/ps-report-column-align.js +5 -0
  24. package/dist/esm/constants/ps-report-row-kind.js +6 -0
  25. package/dist/esm/constants/ps-report-row-tone.js +6 -0
  26. package/dist/esm/constants/ps-report-table-classes.js +56 -0
  27. package/dist/esm/constants/ps-report-table-config.js +6 -0
  28. package/dist/esm/constants/ps-report-table-density.js +4 -0
  29. package/dist/esm/constants/ps-table-sticky-config.js +1 -1
  30. package/dist/esm/hooks/use-ps-sticky-head.js +34 -22
  31. package/dist/esm/index.js +8 -0
  32. package/dist/esm/interfaces/ps-report-cell-plan.js +1 -0
  33. package/dist/esm/interfaces/ps-report-column.js +1 -0
  34. package/dist/esm/interfaces/ps-table-sticky-head-inputs.js +1 -0
  35. package/dist/esm/services/ps-report-table-service.js +67 -0
  36. package/dist/esm/services/ps-table-sticky-head-service.js +11 -3
  37. package/dist/hooks/use-ps-sticky-head.d.ts +1 -1
  38. package/dist/hooks/use-ps-sticky-head.js +33 -21
  39. package/dist/index.d.ts +8 -0
  40. package/dist/index.js +8 -0
  41. package/dist/interfaces/ps-report-cell-plan.d.ts +6 -0
  42. package/dist/interfaces/ps-report-cell-plan.js +2 -0
  43. package/dist/interfaces/ps-report-column.d.ts +12 -0
  44. package/dist/interfaces/ps-report-column.js +2 -0
  45. package/dist/interfaces/ps-sticky-head-refs.d.ts +1 -1
  46. package/dist/interfaces/ps-table-sticky-head-inputs.d.ts +7 -0
  47. package/dist/interfaces/ps-table-sticky-head-inputs.js +2 -0
  48. package/dist/services/ps-report-table-service.d.ts +17 -0
  49. package/dist/services/ps-report-table-service.js +71 -0
  50. package/dist/services/ps-table-sticky-head-service.d.ts +3 -1
  51. package/dist/services/ps-table-sticky-head-service.js +11 -3
  52. package/package.json +1 -1
@@ -5,18 +5,17 @@ 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, }) => {
9
- const [isStuck, setIsStuck] = (0, react_1.useState)(false);
8
+ const usePsStickyHead = ({ cardRef, contentRef, headRef, layoutKey, regionRef, stickyTop, }) => {
10
9
  (0, react_1.useLayoutEffect)(() => {
11
10
  const region = regionRef.current;
12
- const sentinel = sentinelRef.current;
13
11
  const card = cardRef.current;
12
+ const content = contentRef.current;
14
13
  const head = headRef.current;
15
14
  const table = head === null ? null : head.parentElement;
16
15
  if (stickyTop === undefined ||
17
16
  region === null ||
18
- sentinel === null ||
19
17
  card === null ||
18
+ content === null ||
20
19
  head === null ||
21
20
  table === null)
22
21
  return;
@@ -24,6 +23,7 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
24
23
  const Timeline = window.ScrollTimeline;
25
24
  const isDriven = scroller !== null && Timeline !== undefined;
26
25
  let animations = [];
26
+ let measured = null;
27
27
  let frame = 0;
28
28
  const headTravel = () => Math.max(table.offsetHeight - head.offsetHeight, 0);
29
29
  const drive = () => {
@@ -33,10 +33,19 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
33
33
  Number.parseFloat(getComputedStyle(region).top) +
34
34
  region.offsetHeight +
35
35
  ps_table_sticky_config_1.PsTableStickyConfig.cardGapPx;
36
- const scrollRange = scroller.scrollHeight - scroller.clientHeight;
36
+ const inputs = {
37
+ cardPin: content.getBoundingClientRect().top + scroller.scrollTop - pinnedLine,
38
+ cardTravel: card.offsetHeight,
39
+ headPin: table.getBoundingClientRect().top + scroller.scrollTop - pinnedLine,
40
+ headTravel: headTravel(),
41
+ scrollRange: scroller.scrollHeight - scroller.clientHeight,
42
+ };
43
+ if (ps_table_sticky_head_service_1.PsTableStickyHeadService.sameInputs(measured, inputs))
44
+ return;
45
+ measured = inputs;
37
46
  const timeline = new Timeline({ axis: 'block', source: scroller });
38
- 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);
47
+ const headFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(inputs.headPin, inputs.headTravel, inputs.scrollRange);
48
+ const cardFrames = ps_table_sticky_head_service_1.PsTableStickyHeadService.keyframes(inputs.cardPin, inputs.cardTravel, inputs.scrollRange);
40
49
  animations.forEach((animation) => animation.cancel());
41
50
  animations = [
42
51
  head.animate(headFrames.map((keyframe) => ({
@@ -44,30 +53,32 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
44
53
  transform: `translateY(${keyframe.shift}px)`,
45
54
  })), { fill: 'both', timeline }),
46
55
  card.animate(cardFrames.map((keyframe) => ({
47
- clipPath: ps_table_sticky_head_service_1.PsTableStickyHeadService.clip(keyframe.shift),
48
56
  offset: keyframe.offset,
57
+ transform: `translateY(${keyframe.shift}px)`,
58
+ })), { fill: 'both', timeline }),
59
+ content.animate(cardFrames.map((keyframe) => ({
60
+ offset: keyframe.offset,
61
+ transform: `translateY(${-keyframe.shift}px)`,
49
62
  })), { fill: 'both', timeline }),
50
63
  ];
51
64
  };
52
65
  const follow = () => {
66
+ frame = 0;
53
67
  const pinnedLine = region.getBoundingClientRect().bottom + ps_table_sticky_config_1.PsTableStickyConfig.cardGapPx;
54
68
  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));
56
- };
57
- const check = () => {
58
- frame = 0;
59
- setIsStuck(sentinel.getBoundingClientRect().top < region.getBoundingClientRect().top - 1);
60
- if (!isDriven)
61
- follow();
69
+ const cut = ps_table_sticky_head_service_1.PsTableStickyHeadService.offset(pinnedLine, content.getBoundingClientRect().top, card.offsetHeight, 0);
70
+ card.style.transform = `translateY(${cut}px)`;
71
+ content.style.transform = `translateY(${-cut}px)`;
62
72
  };
63
73
  const schedule = () => {
64
74
  if (frame === 0)
65
- frame = window.requestAnimationFrame(check);
75
+ frame = window.requestAnimationFrame(follow);
66
76
  };
67
77
  const measure = () => {
68
78
  if (isDriven)
69
79
  drive();
70
- schedule();
80
+ else
81
+ schedule();
71
82
  };
72
83
  const observer = new ResizeObserver(measure);
73
84
  measure();
@@ -75,19 +86,20 @@ const usePsStickyHead = ({ cardRef, headRef, layoutKey, regionRef, sentinelRef,
75
86
  observer.observe(card);
76
87
  if (scroller !== null)
77
88
  Array.from(scroller.children).forEach((child) => observer.observe(child));
78
- window.addEventListener('scroll', schedule, { capture: true, passive: true });
79
89
  window.addEventListener('resize', measure);
90
+ if (!isDriven)
91
+ window.addEventListener('scroll', schedule, { capture: true, passive: true });
80
92
  return () => {
81
93
  observer.disconnect();
82
94
  animations.forEach((animation) => animation.cancel());
83
95
  head.style.transform = '';
84
- card.style.clipPath = '';
96
+ card.style.transform = '';
97
+ content.style.transform = '';
85
98
  window.removeEventListener('scroll', schedule, { capture: true });
86
99
  window.removeEventListener('resize', measure);
87
100
  if (frame !== 0)
88
101
  window.cancelAnimationFrame(frame);
89
102
  };
90
- }, [cardRef, headRef, layoutKey, regionRef, sentinelRef, stickyTop]);
91
- return isStuck;
103
+ }, [cardRef, contentRef, headRef, layoutKey, regionRef, stickyTop]);
92
104
  };
93
105
  exports.usePsStickyHead = usePsStickyHead;
package/dist/index.d.ts CHANGED
@@ -64,3 +64,11 @@ export * from './interfaces/ps-server-rows-result';
64
64
  export * from './interfaces/ps-table-cursor-paging';
65
65
  export * from './interfaces/ps-table-select-all-matching';
66
66
  export * from './services/ps-server-rows-service';
67
+ export * from './components/ps-report-table';
68
+ export * from './components/ps-report-table-skeleton';
69
+ export * from './constants/ps-report-column-align';
70
+ export * from './constants/ps-report-row-kind';
71
+ export * from './constants/ps-report-row-tone';
72
+ export * from './constants/ps-report-table-density';
73
+ export * from './interfaces/ps-report-column';
74
+ export * from './services/ps-report-table-service';
package/dist/index.js CHANGED
@@ -80,3 +80,11 @@ __exportStar(require("./interfaces/ps-server-rows-result"), exports);
80
80
  __exportStar(require("./interfaces/ps-table-cursor-paging"), exports);
81
81
  __exportStar(require("./interfaces/ps-table-select-all-matching"), exports);
82
82
  __exportStar(require("./services/ps-server-rows-service"), exports);
83
+ __exportStar(require("./components/ps-report-table"), exports);
84
+ __exportStar(require("./components/ps-report-table-skeleton"), exports);
85
+ __exportStar(require("./constants/ps-report-column-align"), exports);
86
+ __exportStar(require("./constants/ps-report-row-kind"), exports);
87
+ __exportStar(require("./constants/ps-report-row-tone"), exports);
88
+ __exportStar(require("./constants/ps-report-table-density"), exports);
89
+ __exportStar(require("./interfaces/ps-report-column"), exports);
90
+ __exportStar(require("./services/ps-report-table-service"), exports);
@@ -0,0 +1,6 @@
1
+ import type { PsReportColumn } from './ps-report-column';
2
+ export interface PsReportCellPlan<RowData> {
3
+ colSpan: number;
4
+ column: PsReportColumn<RowData>;
5
+ index: number;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { PsReportColumnAlign } from '../constants/ps-report-column-align';
3
+ export interface PsReportColumn<RowData> {
4
+ align?: PsReportColumnAlign;
5
+ id: string;
6
+ label: ReactNode;
7
+ maxWidth?: string;
8
+ minWidth?: string;
9
+ render: (row: RowData) => ReactNode;
10
+ width?: string;
11
+ wrap?: boolean;
12
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,9 +1,9 @@
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>;
7
- sentinelRef: RefObject<HTMLDivElement | null>;
8
8
  stickyTop?: string;
9
9
  }
@@ -0,0 +1,7 @@
1
+ export interface PsTableStickyHeadInputs {
2
+ cardPin: number;
3
+ cardTravel: number;
4
+ headPin: number;
5
+ headTravel: number;
6
+ scrollRange: number;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import type { CSSProperties } from 'react';
2
+ import { PsReportColumnAlign } from '../constants/ps-report-column-align';
3
+ import { PsReportRowTone } from '../constants/ps-report-row-tone';
4
+ import { PsReportTableDensity } from '../constants/ps-report-table-density';
5
+ import type { PsReportCellPlan } from '../interfaces/ps-report-cell-plan';
6
+ import type { PsReportColumn } from '../interfaces/ps-report-column';
7
+ export declare class PsReportTableService {
8
+ static cells<RowData>(columns: PsReportColumn<RowData>[], leadSpan: number): PsReportCellPlan<RowData>[];
9
+ static span(count: number, leadSpan: number): number;
10
+ static indent(level: number, density: PsReportTableDensity): CSSProperties;
11
+ static columnStyle<RowData>(column: PsReportColumn<RowData>): CSSProperties;
12
+ static levelOf(level: number | undefined): number;
13
+ static headClass<RowData>(column: PsReportColumn<RowData>, index: number, density: PsReportTableDensity, isHeaderSticky: boolean, isFirstColumnSticky: boolean): string;
14
+ static headPin(isHeaderSticky: boolean, isPinnedFirst: boolean): string;
15
+ static cellClass<RowData>(column: PsReportColumn<RowData>, index: number, density: PsReportTableDensity, tone: PsReportRowTone, isFirstColumnSticky: boolean): string;
16
+ static alignOf<RowData>(column: PsReportColumn<RowData>): PsReportColumnAlign;
17
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsReportTableService = void 0;
4
+ const ps_report_column_align_1 = require("../constants/ps-report-column-align");
5
+ const ps_report_table_classes_1 = require("../constants/ps-report-table-classes");
6
+ const ps_report_table_config_1 = require("../constants/ps-report-table-config");
7
+ const ps_table_pin_classes_1 = require("../constants/ps-table-pin-classes");
8
+ class PsReportTableService {
9
+ static cells(columns, leadSpan) {
10
+ const span = PsReportTableService.span(columns.length, leadSpan);
11
+ const plan = [{ colSpan: span, column: columns[0], index: 0 }];
12
+ for (let index = span; index < columns.length; index += 1)
13
+ plan.push({ colSpan: 1, column: columns[index], index });
14
+ return plan;
15
+ }
16
+ static span(count, leadSpan) {
17
+ return Math.min(Math.max(leadSpan, 1), count);
18
+ }
19
+ static indent(level, density) {
20
+ const base = ps_report_table_config_1.PsReportTableConfig.baseIndentRem[density];
21
+ return { paddingLeft: `${base + level * ps_report_table_config_1.PsReportTableConfig.indentRem}rem` };
22
+ }
23
+ static columnStyle(column) {
24
+ return {
25
+ maxWidth: column.maxWidth,
26
+ minWidth: column.minWidth,
27
+ width: column.width,
28
+ };
29
+ }
30
+ static levelOf(level) {
31
+ return level !== undefined && level > 0 ? level : 0;
32
+ }
33
+ static headClass(column, index, density, isHeaderSticky, isFirstColumnSticky) {
34
+ const isPinnedFirst = index === 0 && isFirstColumnSticky;
35
+ const pin = PsReportTableService.headPin(isHeaderSticky, isPinnedFirst);
36
+ return [
37
+ ps_report_table_classes_1.PsReportTableClasses.headCell[density],
38
+ ps_report_table_classes_1.PsReportTableClasses.align[PsReportTableService.alignOf(column)],
39
+ pin,
40
+ isPinnedFirst ? ps_table_pin_classes_1.PsTablePinClasses.edge : '',
41
+ ]
42
+ .filter((name) => name !== '')
43
+ .join(' ');
44
+ }
45
+ static headPin(isHeaderSticky, isPinnedFirst) {
46
+ if (isHeaderSticky && isPinnedFirst)
47
+ return ps_report_table_classes_1.PsReportTableClasses.stickyFirstHead;
48
+ if (isHeaderSticky)
49
+ return ps_report_table_classes_1.PsReportTableClasses.stickyHead;
50
+ if (isPinnedFirst)
51
+ return ps_report_table_classes_1.PsReportTableClasses.stickyFirstBody;
52
+ return '';
53
+ }
54
+ static cellClass(column, index, density, tone, isFirstColumnSticky) {
55
+ const isPinnedFirst = index === 0 && isFirstColumnSticky;
56
+ return [
57
+ ps_report_table_classes_1.PsReportTableClasses.cell[density],
58
+ ps_report_table_classes_1.PsReportTableClasses.align[PsReportTableService.alignOf(column)],
59
+ ps_report_table_classes_1.PsReportTableClasses.tone[tone],
60
+ column.wrap === true ? '' : ps_report_table_classes_1.PsReportTableClasses.nowrap,
61
+ column.maxWidth !== undefined ? ps_report_table_classes_1.PsReportTableClasses.truncate : '',
62
+ isPinnedFirst ? `${ps_report_table_classes_1.PsReportTableClasses.stickyFirstBody} ${ps_table_pin_classes_1.PsTablePinClasses.edge}` : '',
63
+ ]
64
+ .filter((name) => name !== '')
65
+ .join(' ');
66
+ }
67
+ static alignOf(column) {
68
+ return column.align !== undefined ? column.align : ps_report_column_align_1.PsReportColumnAlign.left;
69
+ }
70
+ }
71
+ exports.PsReportTableService = PsReportTableService;
@@ -1,7 +1,9 @@
1
+ import type { PsTableStickyHeadInputs } from '../interfaces/ps-table-sticky-head-inputs';
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;
5
+ static sameInputs(previous: PsTableStickyHeadInputs | null, next: PsTableStickyHeadInputs): boolean;
4
6
  static keyframes(pinScroll: number, maxShift: number, scrollRange: number): PsTableStickyHeadKeyframe[];
5
- static clip(shift: number): string;
7
+ private static close;
6
8
  private static stops;
7
9
  }
@@ -6,6 +6,15 @@ class PsTableStickyHeadService {
6
6
  static offset(pinnedBottom, tableTop, tableHeight, headHeight) {
7
7
  return Math.min(Math.max(pinnedBottom - tableTop, 0), Math.max(tableHeight - headHeight, 0));
8
8
  }
9
+ static sameInputs(previous, next) {
10
+ if (previous === null)
11
+ return false;
12
+ return (PsTableStickyHeadService.close(previous.headPin, next.headPin) &&
13
+ PsTableStickyHeadService.close(previous.headTravel, next.headTravel) &&
14
+ PsTableStickyHeadService.close(previous.cardPin, next.cardPin) &&
15
+ PsTableStickyHeadService.close(previous.cardTravel, next.cardTravel) &&
16
+ PsTableStickyHeadService.close(previous.scrollRange, next.scrollRange));
17
+ }
9
18
  static keyframes(pinScroll, maxShift, scrollRange) {
10
19
  if (scrollRange <= 0)
11
20
  return [];
@@ -15,9 +24,8 @@ class PsTableStickyHeadService {
15
24
  shift: shiftAt(scroll),
16
25
  }));
17
26
  }
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)`;
27
+ static close(first, second) {
28
+ return Math.abs(first - second) <= ps_table_sticky_config_1.PsTableStickyConfig.inputTolerancePx;
21
29
  }
22
30
  static stops(scrolls, scrollRange) {
23
31
  const inside = scrolls.filter((scroll) => scroll >= 0 && scroll <= scrollRange);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-table-components",
3
- "version": "1.28.3",
3
+ "version": "1.29.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",