@pallasoft/ps-core-components 2.42.0 → 2.43.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 (39) hide show
  1. package/dist/components/ps-button.js +3 -1
  2. package/dist/components/ps-reflective-app-shell.d.ts +3 -1
  3. package/dist/components/ps-reflective-app-shell.js +10 -3
  4. package/dist/components/ps-scroll-restoration.d.ts +6 -0
  5. package/dist/components/ps-scroll-restoration.js +9 -0
  6. package/dist/constants/ps-scroll-restoration-config.d.ts +10 -0
  7. package/dist/constants/ps-scroll-restoration-config.js +13 -0
  8. package/dist/esm/components/ps-button.js +3 -1
  9. package/dist/esm/components/ps-reflective-app-shell.js +10 -3
  10. package/dist/esm/components/ps-scroll-restoration.js +5 -0
  11. package/dist/esm/constants/ps-scroll-restoration-config.js +10 -0
  12. package/dist/esm/hooks/use-ps-browser-layout-effect.js +2 -0
  13. package/dist/esm/hooks/use-ps-scroll-restoration.js +103 -0
  14. package/dist/esm/index.js +10 -0
  15. package/dist/esm/models/ps-scroll-offsets-data.js +1 -0
  16. package/dist/esm/models/ps-scroll-pending-save-data.js +1 -0
  17. package/dist/esm/models/ps-scroll-restoration-options.js +1 -0
  18. package/dist/esm/services/ps-scroll-restore-service.js +52 -0
  19. package/dist/esm/services/ps-scroll-storage-service.js +66 -0
  20. package/dist/esm/services/ps-scroll-target-service.js +29 -0
  21. package/dist/hooks/use-ps-browser-layout-effect.d.ts +2 -0
  22. package/dist/hooks/use-ps-browser-layout-effect.js +5 -0
  23. package/dist/hooks/use-ps-scroll-restoration.d.ts +2 -0
  24. package/dist/hooks/use-ps-scroll-restoration.js +107 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.js +10 -0
  27. package/dist/models/ps-scroll-offsets-data.d.ts +1 -0
  28. package/dist/models/ps-scroll-offsets-data.js +2 -0
  29. package/dist/models/ps-scroll-pending-save-data.d.ts +4 -0
  30. package/dist/models/ps-scroll-pending-save-data.js +2 -0
  31. package/dist/models/ps-scroll-restoration-options.d.ts +7 -0
  32. package/dist/models/ps-scroll-restoration-options.js +2 -0
  33. package/dist/services/ps-scroll-restore-service.d.ts +3 -0
  34. package/dist/services/ps-scroll-restore-service.js +56 -0
  35. package/dist/services/ps-scroll-storage-service.d.ts +11 -0
  36. package/dist/services/ps-scroll-storage-service.js +70 -0
  37. package/dist/services/ps-scroll-target-service.d.ts +8 -0
  38. package/dist/services/ps-scroll-target-service.js +33 -0
  39. package/package.json +1 -1
@@ -5,5 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
6
  const ps_button_classes_1 = require("../constants/ps-button-classes");
7
7
  const ps_spinner_1 = require("./ps-spinner");
8
- const PsButton = ({ children, className, disabled, isLabelHiddenOnMobile = false, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_button_classes_1.PsButtonBaseClassName, 'disabled:cursor-not-allowed disabled:opacity-50', ps_button_classes_1.PsButtonSizeClassNames[size], isLabelHiddenOnMobile && leadingIcon ? 'min-w-11 max-sm:px-0' : '', ps_button_classes_1.PsButtonVariantClassNames[variant], className), "aria-busy": isLoading || undefined, disabled: disabled || isLoading, type: type, ...props, children: [isLoading ? ((0, jsx_runtime_1.jsx)(ps_spinner_1.PsSpinner, { className: 'absolute inset-0 m-auto', color: 'current', label: loadingLabel !== null && loadingLabel !== undefined ? loadingLabel : 'Loading', size: 'small' })) : null, (0, jsx_runtime_1.jsxs)("span", { "aria-hidden": isLoading || undefined, className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-w-0 items-center gap-2', isLoading ? 'invisible' : ''), children: [leadingIcon ? (0, jsx_runtime_1.jsx)("span", { className: 'shrink-0', children: leadingIcon }) : null, (0, jsx_runtime_1.jsx)("span", { className: isLabelHiddenOnMobile && leadingIcon ? 'sr-only sm:not-sr-only sm:truncate' : 'truncate', children: children }), trailingIcon ? (0, jsx_runtime_1.jsx)("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
8
+ const PsButton = ({ children, className, disabled, isLabelHiddenOnMobile = false, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_button_classes_1.PsButtonBaseClassName, isLoading && disabled !== true
9
+ ? 'cursor-progress'
10
+ : 'disabled:cursor-not-allowed disabled:opacity-50', ps_button_classes_1.PsButtonSizeClassNames[size], isLabelHiddenOnMobile && leadingIcon ? 'min-w-11 max-sm:px-0' : '', ps_button_classes_1.PsButtonVariantClassNames[variant], className), "aria-busy": isLoading || undefined, disabled: disabled || isLoading, type: type, ...props, children: [isLoading ? ((0, jsx_runtime_1.jsx)(ps_spinner_1.PsSpinner, { className: 'absolute inset-0 m-auto', color: 'current', label: loadingLabel !== null && loadingLabel !== undefined ? loadingLabel : 'Loading', size: 'small' })) : null, (0, jsx_runtime_1.jsxs)("span", { "aria-hidden": isLoading || undefined, className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-w-0 items-center gap-2', isLoading ? 'invisible' : ''), children: [leadingIcon ? (0, jsx_runtime_1.jsx)("span", { className: 'shrink-0', children: leadingIcon }) : null, (0, jsx_runtime_1.jsx)("span", { className: isLabelHiddenOnMobile && leadingIcon ? 'sr-only sm:not-sr-only sm:truncate' : 'truncate', children: children }), trailingIcon ? (0, jsx_runtime_1.jsx)("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
9
11
  exports.PsButton = PsButton;
@@ -4,9 +4,11 @@ export interface PsReflectiveAppShellProps {
4
4
  className?: string;
5
5
  contentClassName?: string;
6
6
  frameClassName?: string;
7
+ scrollPreventReset?: boolean;
7
8
  scrollResetKey?: string;
9
+ scrollRestoreKey?: string;
8
10
  sidebar: ReactNode;
9
11
  sidebarWidth?: string;
10
12
  topbar: ReactNode;
11
13
  }
12
- export declare const PsReflectiveAppShell: ({ children, className, contentClassName, frameClassName, scrollResetKey, sidebar, sidebarWidth, topbar, }: PsReflectiveAppShellProps) => import("react").JSX.Element;
14
+ export declare const PsReflectiveAppShell: ({ children, className, contentClassName, frameClassName, scrollPreventReset, scrollResetKey, scrollRestoreKey, sidebar, sidebarWidth, topbar, }: PsReflectiveAppShellProps) => import("react").JSX.Element;
@@ -4,14 +4,21 @@ exports.PsReflectiveAppShell = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
7
- const PsReflectiveAppShell = ({ children, className, contentClassName, frameClassName, scrollResetKey, sidebar, sidebarWidth = '17rem', topbar, }) => {
7
+ const use_ps_scroll_restoration_1 = require("../hooks/use-ps-scroll-restoration");
8
+ const PsReflectiveAppShell = ({ children, className, contentClassName, frameClassName, scrollPreventReset, scrollResetKey, scrollRestoreKey, sidebar, sidebarWidth = '17rem', topbar, }) => {
8
9
  const contentRef = (0, react_1.useRef)(null);
10
+ (0, use_ps_scroll_restoration_1.usePsScrollRestoration)({
11
+ elementRef: contentRef,
12
+ preventScrollReset: scrollPreventReset,
13
+ resetKey: scrollResetKey,
14
+ restoreKey: scrollRestoreKey,
15
+ });
9
16
  (0, react_1.useLayoutEffect)(() => {
10
- if (scrollResetKey === undefined)
17
+ if (scrollResetKey === undefined || scrollRestoreKey !== undefined)
11
18
  return;
12
19
  contentRef.current?.scrollTo({ top: 0, left: 0 });
13
20
  window.scrollTo({ top: 0, left: 0 });
14
- }, [scrollResetKey]);
21
+ }, [scrollResetKey, scrollRestoreKey]);
15
22
  return ((0, jsx_runtime_1.jsx)("section", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-reflective-frame h-[100dvh] overflow-hidden text-ink', className), children: (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-liquid-strong grid h-full min-h-0 w-full overflow-hidden border-line/70 bg-white/70 backdrop-blur-2xl transition-[grid-template-columns] duration-200 dark:border-white/10 dark:bg-surface/70 md:grid-cols-[var(--ps-sidebar-width)_minmax(0,1fr)]', frameClassName), style: { ['--ps-sidebar-width']: sidebarWidth }, children: [sidebar, (0, jsx_runtime_1.jsxs)("div", { className: 'flex min-h-0 min-w-0 flex-col bg-white/32 dark:bg-white/[0.02]', children: [topbar, (0, jsx_runtime_1.jsx)("main", { ref: contentRef, className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar min-h-0 flex-1 overflow-y-auto px-4 ps-page-enter sm:px-5 lg:px-6 xl:px-7', contentClassName), children: (0, jsx_runtime_1.jsx)("div", { className: 'py-5', children: children }) })] })] }) }));
16
23
  };
17
24
  exports.PsReflectiveAppShell = PsReflectiveAppShell;
@@ -0,0 +1,6 @@
1
+ export interface PsScrollRestorationProps {
2
+ preventScrollReset?: boolean;
3
+ resetKey?: string;
4
+ restoreKey: string;
5
+ }
6
+ export declare const PsScrollRestoration: ({ preventScrollReset, resetKey, restoreKey, }: PsScrollRestorationProps) => null;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScrollRestoration = void 0;
4
+ const use_ps_scroll_restoration_1 = require("../hooks/use-ps-scroll-restoration");
5
+ const PsScrollRestoration = ({ preventScrollReset, resetKey, restoreKey, }) => {
6
+ (0, use_ps_scroll_restoration_1.usePsScrollRestoration)({ preventScrollReset, resetKey, restoreKey });
7
+ return null;
8
+ };
9
+ exports.PsScrollRestoration = PsScrollRestoration;
@@ -0,0 +1,10 @@
1
+ export declare const PsScrollRestorationConfig: {
2
+ readonly elementScope: "element:";
3
+ readonly inputEvents: readonly ["wheel", "touchstart", "keydown", "mousedown"];
4
+ readonly maxEntries: 100;
5
+ readonly persistThrottleMs: 150;
6
+ readonly restoreTimeoutMs: 4000;
7
+ readonly storageKey: "ps-scroll-restoration";
8
+ readonly tolerancePx: 2;
9
+ readonly windowScope: "window:";
10
+ };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScrollRestorationConfig = void 0;
4
+ exports.PsScrollRestorationConfig = {
5
+ elementScope: 'element:',
6
+ inputEvents: ['wheel', 'touchstart', 'keydown', 'mousedown'],
7
+ maxEntries: 100,
8
+ persistThrottleMs: 150,
9
+ restoreTimeoutMs: 4000,
10
+ storageKey: 'ps-scroll-restoration',
11
+ tolerancePx: 2,
12
+ windowScope: 'window:',
13
+ };
@@ -2,4 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
3
  import { PsButtonBaseClassName, PsButtonSizeClassNames, PsButtonVariantClassNames, } from '../constants/ps-button-classes.js';
4
4
  import { PsSpinner } from './ps-spinner.js';
5
- export const PsButton = ({ children, className, disabled, isLabelHiddenOnMobile = false, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => (_jsxs("button", { className: PallasoftClassNameService.merge(PsButtonBaseClassName, 'disabled:cursor-not-allowed disabled:opacity-50', PsButtonSizeClassNames[size], isLabelHiddenOnMobile && leadingIcon ? 'min-w-11 max-sm:px-0' : '', PsButtonVariantClassNames[variant], className), "aria-busy": isLoading || undefined, disabled: disabled || isLoading, type: type, ...props, children: [isLoading ? (_jsx(PsSpinner, { className: 'absolute inset-0 m-auto', color: 'current', label: loadingLabel !== null && loadingLabel !== undefined ? loadingLabel : 'Loading', size: 'small' })) : null, _jsxs("span", { "aria-hidden": isLoading || undefined, className: PallasoftClassNameService.merge('inline-flex min-w-0 items-center gap-2', isLoading ? 'invisible' : ''), children: [leadingIcon ? _jsx("span", { className: 'shrink-0', children: leadingIcon }) : null, _jsx("span", { className: isLabelHiddenOnMobile && leadingIcon ? 'sr-only sm:not-sr-only sm:truncate' : 'truncate', children: children }), trailingIcon ? _jsx("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
5
+ export const PsButton = ({ children, className, disabled, isLabelHiddenOnMobile = false, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => (_jsxs("button", { className: PallasoftClassNameService.merge(PsButtonBaseClassName, isLoading && disabled !== true
6
+ ? 'cursor-progress'
7
+ : 'disabled:cursor-not-allowed disabled:opacity-50', PsButtonSizeClassNames[size], isLabelHiddenOnMobile && leadingIcon ? 'min-w-11 max-sm:px-0' : '', PsButtonVariantClassNames[variant], className), "aria-busy": isLoading || undefined, disabled: disabled || isLoading, type: type, ...props, children: [isLoading ? (_jsx(PsSpinner, { className: 'absolute inset-0 m-auto', color: 'current', label: loadingLabel !== null && loadingLabel !== undefined ? loadingLabel : 'Loading', size: 'small' })) : null, _jsxs("span", { "aria-hidden": isLoading || undefined, className: PallasoftClassNameService.merge('inline-flex min-w-0 items-center gap-2', isLoading ? 'invisible' : ''), children: [leadingIcon ? _jsx("span", { className: 'shrink-0', children: leadingIcon }) : null, _jsx("span", { className: isLabelHiddenOnMobile && leadingIcon ? 'sr-only sm:not-sr-only sm:truncate' : 'truncate', children: children }), trailingIcon ? _jsx("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
@@ -1,13 +1,20 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useLayoutEffect, useRef } from 'react';
3
3
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
4
- export const PsReflectiveAppShell = ({ children, className, contentClassName, frameClassName, scrollResetKey, sidebar, sidebarWidth = '17rem', topbar, }) => {
4
+ import { usePsScrollRestoration } from '../hooks/use-ps-scroll-restoration.js';
5
+ export const PsReflectiveAppShell = ({ children, className, contentClassName, frameClassName, scrollPreventReset, scrollResetKey, scrollRestoreKey, sidebar, sidebarWidth = '17rem', topbar, }) => {
5
6
  const contentRef = useRef(null);
7
+ usePsScrollRestoration({
8
+ elementRef: contentRef,
9
+ preventScrollReset: scrollPreventReset,
10
+ resetKey: scrollResetKey,
11
+ restoreKey: scrollRestoreKey,
12
+ });
6
13
  useLayoutEffect(() => {
7
- if (scrollResetKey === undefined)
14
+ if (scrollResetKey === undefined || scrollRestoreKey !== undefined)
8
15
  return;
9
16
  contentRef.current?.scrollTo({ top: 0, left: 0 });
10
17
  window.scrollTo({ top: 0, left: 0 });
11
- }, [scrollResetKey]);
18
+ }, [scrollResetKey, scrollRestoreKey]);
12
19
  return (_jsx("section", { className: PallasoftClassNameService.merge('ps-reflective-frame h-[100dvh] overflow-hidden text-ink', className), children: _jsxs("div", { className: PallasoftClassNameService.merge('ps-liquid-strong grid h-full min-h-0 w-full overflow-hidden border-line/70 bg-white/70 backdrop-blur-2xl transition-[grid-template-columns] duration-200 dark:border-white/10 dark:bg-surface/70 md:grid-cols-[var(--ps-sidebar-width)_minmax(0,1fr)]', frameClassName), style: { ['--ps-sidebar-width']: sidebarWidth }, children: [sidebar, _jsxs("div", { className: 'flex min-h-0 min-w-0 flex-col bg-white/32 dark:bg-white/[0.02]', children: [topbar, _jsx("main", { ref: contentRef, className: PallasoftClassNameService.merge('ps-scrollbar min-h-0 flex-1 overflow-y-auto px-4 ps-page-enter sm:px-5 lg:px-6 xl:px-7', contentClassName), children: _jsx("div", { className: 'py-5', children: children }) })] })] }) }));
13
20
  };
@@ -0,0 +1,5 @@
1
+ import { usePsScrollRestoration } from '../hooks/use-ps-scroll-restoration.js';
2
+ export const PsScrollRestoration = ({ preventScrollReset, resetKey, restoreKey, }) => {
3
+ usePsScrollRestoration({ preventScrollReset, resetKey, restoreKey });
4
+ return null;
5
+ };
@@ -0,0 +1,10 @@
1
+ export const PsScrollRestorationConfig = {
2
+ elementScope: 'element:',
3
+ inputEvents: ['wheel', 'touchstart', 'keydown', 'mousedown'],
4
+ maxEntries: 100,
5
+ persistThrottleMs: 150,
6
+ restoreTimeoutMs: 4000,
7
+ storageKey: 'ps-scroll-restoration',
8
+ tolerancePx: 2,
9
+ windowScope: 'window:',
10
+ };
@@ -0,0 +1,2 @@
1
+ import { useEffect, useLayoutEffect } from 'react';
2
+ export const usePsBrowserLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
@@ -0,0 +1,103 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { PsScrollRestoreService } from '../services/ps-scroll-restore-service.js';
3
+ import { PsScrollStorageService } from '../services/ps-scroll-storage-service.js';
4
+ import { PsScrollTargetService } from '../services/ps-scroll-target-service.js';
5
+ import { usePsBrowserLayoutEffect } from './use-ps-browser-layout-effect.js';
6
+ export const usePsScrollRestoration = ({ elementRef, preventScrollReset, resetKey, restoreKey, }) => {
7
+ const keyRef = useRef(restoreKey);
8
+ const hasSavedRef = useRef(false);
9
+ const appliedKeyRef = useRef(undefined);
10
+ const appliedResetKeyRef = useRef(undefined);
11
+ const isRestoringRef = useRef(false);
12
+ const pendingRef = useRef(null);
13
+ const isEnabled = restoreKey !== undefined;
14
+ useEffect(() => {
15
+ if (!isEnabled ||
16
+ typeof window === 'undefined' ||
17
+ typeof history === 'undefined' ||
18
+ !('scrollRestoration' in history))
19
+ return;
20
+ const previous = history.scrollRestoration;
21
+ history.scrollRestoration = 'manual';
22
+ return () => {
23
+ history.scrollRestoration = previous;
24
+ };
25
+ }, [isEnabled]);
26
+ usePsBrowserLayoutEffect(() => {
27
+ keyRef.current = restoreKey;
28
+ if (typeof window === 'undefined')
29
+ return;
30
+ PsScrollStorageService.flush();
31
+ if (restoreKey === undefined)
32
+ return;
33
+ const element = elementRef === undefined ? null : elementRef.current;
34
+ const saved = PsScrollStorageService.read(PsScrollTargetService.storageKey(element, restoreKey));
35
+ hasSavedRef.current = saved !== undefined;
36
+ if (saved === undefined)
37
+ return;
38
+ isRestoringRef.current = true;
39
+ const stop = PsScrollRestoreService.start(element, saved, () => {
40
+ isRestoringRef.current = false;
41
+ });
42
+ return () => {
43
+ stop();
44
+ isRestoringRef.current = false;
45
+ };
46
+ }, [restoreKey, elementRef]);
47
+ usePsBrowserLayoutEffect(() => {
48
+ const previousKey = appliedKeyRef.current;
49
+ const previousResetKey = appliedResetKeyRef.current;
50
+ appliedKeyRef.current = restoreKey;
51
+ appliedResetKeyRef.current = resetKey;
52
+ if (restoreKey === undefined || typeof window === 'undefined')
53
+ return;
54
+ const hasChanged = previousResetKey !== undefined && previousResetKey !== resetKey;
55
+ const isRestored = previousKey !== restoreKey && hasSavedRef.current;
56
+ if (!hasChanged || isRestored || preventScrollReset === true)
57
+ return;
58
+ PsScrollTargetService.scrollTo(elementRef === undefined ? null : elementRef.current, 0);
59
+ }, [resetKey, restoreKey, elementRef, preventScrollReset]);
60
+ useEffect(() => {
61
+ if (!isEnabled || typeof window === 'undefined')
62
+ return;
63
+ const element = elementRef === undefined ? null : elementRef.current;
64
+ const target = PsScrollTargetService.eventTarget(element);
65
+ let frame = 0;
66
+ const flushPending = () => {
67
+ const pending = pendingRef.current;
68
+ pendingRef.current = null;
69
+ if (pending !== null)
70
+ PsScrollStorageService.write(pending.key, pending.top);
71
+ };
72
+ const onScroll = () => {
73
+ const key = keyRef.current;
74
+ if (key === undefined || isRestoringRef.current)
75
+ return;
76
+ pendingRef.current = {
77
+ key: PsScrollTargetService.storageKey(element, key),
78
+ top: PsScrollTargetService.top(element),
79
+ };
80
+ if (frame !== 0)
81
+ return;
82
+ frame = window.requestAnimationFrame(() => {
83
+ frame = 0;
84
+ flushPending();
85
+ });
86
+ };
87
+ const onPageHide = () => {
88
+ const key = keyRef.current;
89
+ pendingRef.current = null;
90
+ if (key !== undefined && !isRestoringRef.current)
91
+ PsScrollStorageService.write(PsScrollTargetService.storageKey(element, key), PsScrollTargetService.top(element));
92
+ PsScrollStorageService.flush();
93
+ };
94
+ target.addEventListener('scroll', onScroll, { passive: true });
95
+ window.addEventListener('pagehide', onPageHide);
96
+ return () => {
97
+ target.removeEventListener('scroll', onScroll);
98
+ window.removeEventListener('pagehide', onPageHide);
99
+ window.cancelAnimationFrame(frame);
100
+ flushPending();
101
+ };
102
+ }, [isEnabled, elementRef]);
103
+ };
package/dist/esm/index.js CHANGED
@@ -192,3 +192,13 @@ export * from './components/ps-divider.js';
192
192
  export * from './models/ps-divider-orientation.js';
193
193
  export * from './components/ps-rating-display.js';
194
194
  export * from './constants/ps-rating-display-size.js';
195
+ export * from './constants/ps-scroll-restoration-config.js';
196
+ export * from './models/ps-scroll-offsets-data.js';
197
+ export * from './models/ps-scroll-restoration-options.js';
198
+ export * from './services/ps-scroll-storage-service.js';
199
+ export * from './services/ps-scroll-target-service.js';
200
+ export * from './services/ps-scroll-restore-service.js';
201
+ export * from './hooks/use-ps-scroll-restoration.js';
202
+ export * from './components/ps-scroll-restoration.js';
203
+ export * from './hooks/use-ps-browser-layout-effect.js';
204
+ export * from './models/ps-scroll-pending-save-data.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import { PsScrollRestorationConfig } from '../constants/ps-scroll-restoration-config.js';
2
+ import { PsScrollTargetService } from './ps-scroll-target-service.js';
3
+ export class PsScrollRestoreService {
4
+ static start(element, top, onDone) {
5
+ let isDone = false;
6
+ let observer = null;
7
+ let mutations = null;
8
+ let timer = 0;
9
+ const finish = () => {
10
+ if (isDone)
11
+ return;
12
+ isDone = true;
13
+ window.clearTimeout(timer);
14
+ observer?.disconnect();
15
+ mutations?.disconnect();
16
+ for (const name of PsScrollRestorationConfig.inputEvents)
17
+ window.removeEventListener(name, onInput, true);
18
+ onDone();
19
+ };
20
+ const onInput = () => finish();
21
+ const attempt = () => {
22
+ if (isDone)
23
+ return;
24
+ if (PsScrollTargetService.maxTop(element) >= top - PsScrollRestorationConfig.tolerancePx) {
25
+ PsScrollTargetService.scrollTo(element, top);
26
+ finish();
27
+ }
28
+ };
29
+ for (const name of PsScrollRestorationConfig.inputEvents)
30
+ window.addEventListener(name, onInput, { capture: true, passive: true });
31
+ timer = window.setTimeout(() => {
32
+ if (isDone)
33
+ return;
34
+ PsScrollTargetService.scrollTo(element, top);
35
+ finish();
36
+ }, PsScrollRestorationConfig.restoreTimeoutMs);
37
+ attempt();
38
+ if (!isDone && typeof MutationObserver !== 'undefined') {
39
+ mutations = new MutationObserver(attempt);
40
+ mutations.observe(element === null ? document.body : element, {
41
+ childList: true,
42
+ subtree: true,
43
+ });
44
+ }
45
+ if (!isDone && typeof ResizeObserver !== 'undefined') {
46
+ observer = new ResizeObserver(attempt);
47
+ for (const node of PsScrollTargetService.observed(element))
48
+ observer.observe(node);
49
+ }
50
+ return finish;
51
+ }
52
+ }
@@ -0,0 +1,66 @@
1
+ import { PsScrollRestorationConfig } from '../constants/ps-scroll-restoration-config.js';
2
+ export class PsScrollStorageService {
3
+ static read(key) {
4
+ const offsets = PsScrollStorageService.memory();
5
+ return Object.prototype.hasOwnProperty.call(offsets, key) ? offsets[key] : undefined;
6
+ }
7
+ static write(key, top) {
8
+ const offsets = PsScrollStorageService.memory();
9
+ delete offsets[key];
10
+ offsets[key] = top;
11
+ const keys = Object.keys(offsets);
12
+ const overflow = keys.length - PsScrollRestorationConfig.maxEntries;
13
+ for (const oldest of keys.slice(0, overflow > 0 ? overflow : 0))
14
+ delete offsets[oldest];
15
+ if (PsScrollStorageService.timer !== 0 || typeof window === 'undefined')
16
+ return;
17
+ PsScrollStorageService.timer = window.setTimeout(PsScrollStorageService.flush, PsScrollRestorationConfig.persistThrottleMs);
18
+ }
19
+ static flush() {
20
+ if (typeof window === 'undefined')
21
+ return;
22
+ window.clearTimeout(PsScrollStorageService.timer);
23
+ PsScrollStorageService.timer = 0;
24
+ if (PsScrollStorageService.offsets === null)
25
+ return;
26
+ try {
27
+ window.sessionStorage.setItem(PsScrollRestorationConfig.storageKey, JSON.stringify(PsScrollStorageService.offsets));
28
+ }
29
+ catch {
30
+ return;
31
+ }
32
+ }
33
+ static reset() {
34
+ if (typeof window !== 'undefined')
35
+ window.clearTimeout(PsScrollStorageService.timer);
36
+ PsScrollStorageService.timer = 0;
37
+ PsScrollStorageService.offsets = null;
38
+ }
39
+ static memory() {
40
+ if (PsScrollStorageService.offsets === null)
41
+ PsScrollStorageService.offsets = PsScrollStorageService.load();
42
+ return PsScrollStorageService.offsets;
43
+ }
44
+ static load() {
45
+ if (typeof window === 'undefined')
46
+ return {};
47
+ try {
48
+ const raw = window.sessionStorage.getItem(PsScrollRestorationConfig.storageKey);
49
+ if (raw === null)
50
+ return {};
51
+ const parsed = JSON.parse(raw);
52
+ return PsScrollStorageService.isOffsets(parsed) ? parsed : {};
53
+ }
54
+ catch {
55
+ return {};
56
+ }
57
+ }
58
+ static isOffsets(value) {
59
+ return (typeof value === 'object' &&
60
+ value !== null &&
61
+ !Array.isArray(value) &&
62
+ Object.values(value).every((entry) => typeof entry === 'number' && Number.isFinite(entry)));
63
+ }
64
+ }
65
+ PsScrollStorageService.offsets = null;
66
+ PsScrollStorageService.timer = 0;
@@ -0,0 +1,29 @@
1
+ import { PsScrollRestorationConfig } from '../constants/ps-scroll-restoration-config.js';
2
+ export class PsScrollTargetService {
3
+ static storageKey(element, restoreKey) {
4
+ return `${element === null ? PsScrollRestorationConfig.windowScope : PsScrollRestorationConfig.elementScope}${restoreKey}`;
5
+ }
6
+ static top(element) {
7
+ return element === null ? window.scrollY : element.scrollTop;
8
+ }
9
+ static maxTop(element) {
10
+ if (element !== null)
11
+ return element.scrollHeight - element.clientHeight;
12
+ return document.documentElement.scrollHeight - window.innerHeight;
13
+ }
14
+ static scrollTo(element, top) {
15
+ if (element === null) {
16
+ window.scrollTo({ behavior: 'instant', left: 0, top });
17
+ return;
18
+ }
19
+ element.scrollTo({ behavior: 'instant', left: 0, top });
20
+ }
21
+ static eventTarget(element) {
22
+ return element === null ? window : element;
23
+ }
24
+ static observed(element) {
25
+ if (element === null)
26
+ return [document.documentElement, document.body];
27
+ return [element, ...Array.from(element.children)];
28
+ }
29
+ }
@@ -0,0 +1,2 @@
1
+ import { useEffect } from 'react';
2
+ export declare const usePsBrowserLayoutEffect: typeof useEffect;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsBrowserLayoutEffect = void 0;
4
+ const react_1 = require("react");
5
+ exports.usePsBrowserLayoutEffect = typeof window === 'undefined' ? react_1.useEffect : react_1.useLayoutEffect;
@@ -0,0 +1,2 @@
1
+ import type { PsScrollRestorationOptions } from '../models/ps-scroll-restoration-options';
2
+ export declare const usePsScrollRestoration: ({ elementRef, preventScrollReset, resetKey, restoreKey, }: PsScrollRestorationOptions) => void;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsScrollRestoration = void 0;
4
+ const react_1 = require("react");
5
+ const ps_scroll_restore_service_1 = require("../services/ps-scroll-restore-service");
6
+ const ps_scroll_storage_service_1 = require("../services/ps-scroll-storage-service");
7
+ const ps_scroll_target_service_1 = require("../services/ps-scroll-target-service");
8
+ const use_ps_browser_layout_effect_1 = require("./use-ps-browser-layout-effect");
9
+ const usePsScrollRestoration = ({ elementRef, preventScrollReset, resetKey, restoreKey, }) => {
10
+ const keyRef = (0, react_1.useRef)(restoreKey);
11
+ const hasSavedRef = (0, react_1.useRef)(false);
12
+ const appliedKeyRef = (0, react_1.useRef)(undefined);
13
+ const appliedResetKeyRef = (0, react_1.useRef)(undefined);
14
+ const isRestoringRef = (0, react_1.useRef)(false);
15
+ const pendingRef = (0, react_1.useRef)(null);
16
+ const isEnabled = restoreKey !== undefined;
17
+ (0, react_1.useEffect)(() => {
18
+ if (!isEnabled ||
19
+ typeof window === 'undefined' ||
20
+ typeof history === 'undefined' ||
21
+ !('scrollRestoration' in history))
22
+ return;
23
+ const previous = history.scrollRestoration;
24
+ history.scrollRestoration = 'manual';
25
+ return () => {
26
+ history.scrollRestoration = previous;
27
+ };
28
+ }, [isEnabled]);
29
+ (0, use_ps_browser_layout_effect_1.usePsBrowserLayoutEffect)(() => {
30
+ keyRef.current = restoreKey;
31
+ if (typeof window === 'undefined')
32
+ return;
33
+ ps_scroll_storage_service_1.PsScrollStorageService.flush();
34
+ if (restoreKey === undefined)
35
+ return;
36
+ const element = elementRef === undefined ? null : elementRef.current;
37
+ const saved = ps_scroll_storage_service_1.PsScrollStorageService.read(ps_scroll_target_service_1.PsScrollTargetService.storageKey(element, restoreKey));
38
+ hasSavedRef.current = saved !== undefined;
39
+ if (saved === undefined)
40
+ return;
41
+ isRestoringRef.current = true;
42
+ const stop = ps_scroll_restore_service_1.PsScrollRestoreService.start(element, saved, () => {
43
+ isRestoringRef.current = false;
44
+ });
45
+ return () => {
46
+ stop();
47
+ isRestoringRef.current = false;
48
+ };
49
+ }, [restoreKey, elementRef]);
50
+ (0, use_ps_browser_layout_effect_1.usePsBrowserLayoutEffect)(() => {
51
+ const previousKey = appliedKeyRef.current;
52
+ const previousResetKey = appliedResetKeyRef.current;
53
+ appliedKeyRef.current = restoreKey;
54
+ appliedResetKeyRef.current = resetKey;
55
+ if (restoreKey === undefined || typeof window === 'undefined')
56
+ return;
57
+ const hasChanged = previousResetKey !== undefined && previousResetKey !== resetKey;
58
+ const isRestored = previousKey !== restoreKey && hasSavedRef.current;
59
+ if (!hasChanged || isRestored || preventScrollReset === true)
60
+ return;
61
+ ps_scroll_target_service_1.PsScrollTargetService.scrollTo(elementRef === undefined ? null : elementRef.current, 0);
62
+ }, [resetKey, restoreKey, elementRef, preventScrollReset]);
63
+ (0, react_1.useEffect)(() => {
64
+ if (!isEnabled || typeof window === 'undefined')
65
+ return;
66
+ const element = elementRef === undefined ? null : elementRef.current;
67
+ const target = ps_scroll_target_service_1.PsScrollTargetService.eventTarget(element);
68
+ let frame = 0;
69
+ const flushPending = () => {
70
+ const pending = pendingRef.current;
71
+ pendingRef.current = null;
72
+ if (pending !== null)
73
+ ps_scroll_storage_service_1.PsScrollStorageService.write(pending.key, pending.top);
74
+ };
75
+ const onScroll = () => {
76
+ const key = keyRef.current;
77
+ if (key === undefined || isRestoringRef.current)
78
+ return;
79
+ pendingRef.current = {
80
+ key: ps_scroll_target_service_1.PsScrollTargetService.storageKey(element, key),
81
+ top: ps_scroll_target_service_1.PsScrollTargetService.top(element),
82
+ };
83
+ if (frame !== 0)
84
+ return;
85
+ frame = window.requestAnimationFrame(() => {
86
+ frame = 0;
87
+ flushPending();
88
+ });
89
+ };
90
+ const onPageHide = () => {
91
+ const key = keyRef.current;
92
+ pendingRef.current = null;
93
+ if (key !== undefined && !isRestoringRef.current)
94
+ ps_scroll_storage_service_1.PsScrollStorageService.write(ps_scroll_target_service_1.PsScrollTargetService.storageKey(element, key), ps_scroll_target_service_1.PsScrollTargetService.top(element));
95
+ ps_scroll_storage_service_1.PsScrollStorageService.flush();
96
+ };
97
+ target.addEventListener('scroll', onScroll, { passive: true });
98
+ window.addEventListener('pagehide', onPageHide);
99
+ return () => {
100
+ target.removeEventListener('scroll', onScroll);
101
+ window.removeEventListener('pagehide', onPageHide);
102
+ window.cancelAnimationFrame(frame);
103
+ flushPending();
104
+ };
105
+ }, [isEnabled, elementRef]);
106
+ };
107
+ exports.usePsScrollRestoration = usePsScrollRestoration;
package/dist/index.d.ts CHANGED
@@ -192,3 +192,13 @@ export * from './components/ps-divider';
192
192
  export * from './models/ps-divider-orientation';
193
193
  export * from './components/ps-rating-display';
194
194
  export * from './constants/ps-rating-display-size';
195
+ export * from './constants/ps-scroll-restoration-config';
196
+ export * from './models/ps-scroll-offsets-data';
197
+ export * from './models/ps-scroll-restoration-options';
198
+ export * from './services/ps-scroll-storage-service';
199
+ export * from './services/ps-scroll-target-service';
200
+ export * from './services/ps-scroll-restore-service';
201
+ export * from './hooks/use-ps-scroll-restoration';
202
+ export * from './components/ps-scroll-restoration';
203
+ export * from './hooks/use-ps-browser-layout-effect';
204
+ export * from './models/ps-scroll-pending-save-data';
package/dist/index.js CHANGED
@@ -208,3 +208,13 @@ __exportStar(require("./components/ps-divider"), exports);
208
208
  __exportStar(require("./models/ps-divider-orientation"), exports);
209
209
  __exportStar(require("./components/ps-rating-display"), exports);
210
210
  __exportStar(require("./constants/ps-rating-display-size"), exports);
211
+ __exportStar(require("./constants/ps-scroll-restoration-config"), exports);
212
+ __exportStar(require("./models/ps-scroll-offsets-data"), exports);
213
+ __exportStar(require("./models/ps-scroll-restoration-options"), exports);
214
+ __exportStar(require("./services/ps-scroll-storage-service"), exports);
215
+ __exportStar(require("./services/ps-scroll-target-service"), exports);
216
+ __exportStar(require("./services/ps-scroll-restore-service"), exports);
217
+ __exportStar(require("./hooks/use-ps-scroll-restoration"), exports);
218
+ __exportStar(require("./components/ps-scroll-restoration"), exports);
219
+ __exportStar(require("./hooks/use-ps-browser-layout-effect"), exports);
220
+ __exportStar(require("./models/ps-scroll-pending-save-data"), exports);
@@ -0,0 +1 @@
1
+ export type PsScrollOffsetsData = Record<string, number>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsScrollPendingSaveData {
2
+ key: string;
3
+ top: number;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import type { RefObject } from 'react';
2
+ export interface PsScrollRestorationOptions {
3
+ elementRef?: RefObject<HTMLElement | null>;
4
+ preventScrollReset?: boolean;
5
+ resetKey?: string;
6
+ restoreKey?: string;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export declare class PsScrollRestoreService {
2
+ static start(element: HTMLElement | null, top: number, onDone: () => void): () => void;
3
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScrollRestoreService = void 0;
4
+ const ps_scroll_restoration_config_1 = require("../constants/ps-scroll-restoration-config");
5
+ const ps_scroll_target_service_1 = require("./ps-scroll-target-service");
6
+ class PsScrollRestoreService {
7
+ static start(element, top, onDone) {
8
+ let isDone = false;
9
+ let observer = null;
10
+ let mutations = null;
11
+ let timer = 0;
12
+ const finish = () => {
13
+ if (isDone)
14
+ return;
15
+ isDone = true;
16
+ window.clearTimeout(timer);
17
+ observer?.disconnect();
18
+ mutations?.disconnect();
19
+ for (const name of ps_scroll_restoration_config_1.PsScrollRestorationConfig.inputEvents)
20
+ window.removeEventListener(name, onInput, true);
21
+ onDone();
22
+ };
23
+ const onInput = () => finish();
24
+ const attempt = () => {
25
+ if (isDone)
26
+ return;
27
+ if (ps_scroll_target_service_1.PsScrollTargetService.maxTop(element) >= top - ps_scroll_restoration_config_1.PsScrollRestorationConfig.tolerancePx) {
28
+ ps_scroll_target_service_1.PsScrollTargetService.scrollTo(element, top);
29
+ finish();
30
+ }
31
+ };
32
+ for (const name of ps_scroll_restoration_config_1.PsScrollRestorationConfig.inputEvents)
33
+ window.addEventListener(name, onInput, { capture: true, passive: true });
34
+ timer = window.setTimeout(() => {
35
+ if (isDone)
36
+ return;
37
+ ps_scroll_target_service_1.PsScrollTargetService.scrollTo(element, top);
38
+ finish();
39
+ }, ps_scroll_restoration_config_1.PsScrollRestorationConfig.restoreTimeoutMs);
40
+ attempt();
41
+ if (!isDone && typeof MutationObserver !== 'undefined') {
42
+ mutations = new MutationObserver(attempt);
43
+ mutations.observe(element === null ? document.body : element, {
44
+ childList: true,
45
+ subtree: true,
46
+ });
47
+ }
48
+ if (!isDone && typeof ResizeObserver !== 'undefined') {
49
+ observer = new ResizeObserver(attempt);
50
+ for (const node of ps_scroll_target_service_1.PsScrollTargetService.observed(element))
51
+ observer.observe(node);
52
+ }
53
+ return finish;
54
+ }
55
+ }
56
+ exports.PsScrollRestoreService = PsScrollRestoreService;
@@ -0,0 +1,11 @@
1
+ export declare class PsScrollStorageService {
2
+ private static offsets;
3
+ private static timer;
4
+ static read(key: string): number | undefined;
5
+ static write(key: string, top: number): void;
6
+ static flush(): void;
7
+ static reset(): void;
8
+ private static memory;
9
+ private static load;
10
+ private static isOffsets;
11
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScrollStorageService = void 0;
4
+ const ps_scroll_restoration_config_1 = require("../constants/ps-scroll-restoration-config");
5
+ class PsScrollStorageService {
6
+ static read(key) {
7
+ const offsets = PsScrollStorageService.memory();
8
+ return Object.prototype.hasOwnProperty.call(offsets, key) ? offsets[key] : undefined;
9
+ }
10
+ static write(key, top) {
11
+ const offsets = PsScrollStorageService.memory();
12
+ delete offsets[key];
13
+ offsets[key] = top;
14
+ const keys = Object.keys(offsets);
15
+ const overflow = keys.length - ps_scroll_restoration_config_1.PsScrollRestorationConfig.maxEntries;
16
+ for (const oldest of keys.slice(0, overflow > 0 ? overflow : 0))
17
+ delete offsets[oldest];
18
+ if (PsScrollStorageService.timer !== 0 || typeof window === 'undefined')
19
+ return;
20
+ PsScrollStorageService.timer = window.setTimeout(PsScrollStorageService.flush, ps_scroll_restoration_config_1.PsScrollRestorationConfig.persistThrottleMs);
21
+ }
22
+ static flush() {
23
+ if (typeof window === 'undefined')
24
+ return;
25
+ window.clearTimeout(PsScrollStorageService.timer);
26
+ PsScrollStorageService.timer = 0;
27
+ if (PsScrollStorageService.offsets === null)
28
+ return;
29
+ try {
30
+ window.sessionStorage.setItem(ps_scroll_restoration_config_1.PsScrollRestorationConfig.storageKey, JSON.stringify(PsScrollStorageService.offsets));
31
+ }
32
+ catch {
33
+ return;
34
+ }
35
+ }
36
+ static reset() {
37
+ if (typeof window !== 'undefined')
38
+ window.clearTimeout(PsScrollStorageService.timer);
39
+ PsScrollStorageService.timer = 0;
40
+ PsScrollStorageService.offsets = null;
41
+ }
42
+ static memory() {
43
+ if (PsScrollStorageService.offsets === null)
44
+ PsScrollStorageService.offsets = PsScrollStorageService.load();
45
+ return PsScrollStorageService.offsets;
46
+ }
47
+ static load() {
48
+ if (typeof window === 'undefined')
49
+ return {};
50
+ try {
51
+ const raw = window.sessionStorage.getItem(ps_scroll_restoration_config_1.PsScrollRestorationConfig.storageKey);
52
+ if (raw === null)
53
+ return {};
54
+ const parsed = JSON.parse(raw);
55
+ return PsScrollStorageService.isOffsets(parsed) ? parsed : {};
56
+ }
57
+ catch {
58
+ return {};
59
+ }
60
+ }
61
+ static isOffsets(value) {
62
+ return (typeof value === 'object' &&
63
+ value !== null &&
64
+ !Array.isArray(value) &&
65
+ Object.values(value).every((entry) => typeof entry === 'number' && Number.isFinite(entry)));
66
+ }
67
+ }
68
+ exports.PsScrollStorageService = PsScrollStorageService;
69
+ PsScrollStorageService.offsets = null;
70
+ PsScrollStorageService.timer = 0;
@@ -0,0 +1,8 @@
1
+ export declare class PsScrollTargetService {
2
+ static storageKey(element: HTMLElement | null, restoreKey: string): string;
3
+ static top(element: HTMLElement | null): number;
4
+ static maxTop(element: HTMLElement | null): number;
5
+ static scrollTo(element: HTMLElement | null, top: number): void;
6
+ static eventTarget(element: HTMLElement | null): HTMLElement | Window;
7
+ static observed(element: HTMLElement | null): Element[];
8
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScrollTargetService = void 0;
4
+ const ps_scroll_restoration_config_1 = require("../constants/ps-scroll-restoration-config");
5
+ class PsScrollTargetService {
6
+ static storageKey(element, restoreKey) {
7
+ return `${element === null ? ps_scroll_restoration_config_1.PsScrollRestorationConfig.windowScope : ps_scroll_restoration_config_1.PsScrollRestorationConfig.elementScope}${restoreKey}`;
8
+ }
9
+ static top(element) {
10
+ return element === null ? window.scrollY : element.scrollTop;
11
+ }
12
+ static maxTop(element) {
13
+ if (element !== null)
14
+ return element.scrollHeight - element.clientHeight;
15
+ return document.documentElement.scrollHeight - window.innerHeight;
16
+ }
17
+ static scrollTo(element, top) {
18
+ if (element === null) {
19
+ window.scrollTo({ behavior: 'instant', left: 0, top });
20
+ return;
21
+ }
22
+ element.scrollTo({ behavior: 'instant', left: 0, top });
23
+ }
24
+ static eventTarget(element) {
25
+ return element === null ? window : element;
26
+ }
27
+ static observed(element) {
28
+ if (element === null)
29
+ return [document.documentElement, document.body];
30
+ return [element, ...Array.from(element.children)];
31
+ }
32
+ }
33
+ exports.PsScrollTargetService = PsScrollTargetService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-core-components",
3
- "version": "2.42.0",
3
+ "version": "2.43.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",