@design-edito/tools 0.5.1 → 0.5.3
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/agnostic/arrays/index.d.ts +1 -1
- package/agnostic/arrays/index.js +1 -1
- package/agnostic/colors/index.d.ts +1 -1
- package/agnostic/colors/index.js +1 -1
- package/agnostic/css/index.d.ts +1 -1
- package/agnostic/css/index.js +1 -1
- package/agnostic/html/deep-select/index.js +5 -3
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +9 -9
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +9 -9
- package/agnostic/html/hyper-json/smart-tags/isolated/index.d.ts +1 -1
- package/agnostic/html/hyper-json/smart-tags/isolated/index.js +1 -1
- package/agnostic/html/index.d.ts +3 -3
- package/agnostic/html/index.js +3 -3
- package/agnostic/index.d.ts +3 -3
- package/agnostic/index.js +3 -3
- package/agnostic/misc/index.d.ts +1 -1
- package/agnostic/misc/index.js +1 -1
- package/agnostic/misc/logs/index.d.ts +1 -1
- package/agnostic/misc/logs/index.js +1 -1
- package/agnostic/numbers/index.d.ts +3 -3
- package/agnostic/numbers/index.js +3 -3
- package/agnostic/objects/index.d.ts +3 -3
- package/agnostic/objects/index.js +3 -3
- package/agnostic/random/index.d.ts +1 -1
- package/agnostic/random/index.js +1 -1
- package/agnostic/strings/index.d.ts +3 -3
- package/agnostic/strings/index.js +3 -3
- package/agnostic/time/dates/format-date/index.d.ts +4 -2
- package/agnostic/time/dates/format-date/index.js +43 -94
- package/agnostic/time/dates/format-date/index.test.js +154 -0
- package/agnostic/time/dates/format-date/parts.d.ts +28 -0
- package/agnostic/time/dates/format-date/parts.js +136 -0
- package/agnostic/time/dates/format-date/types.d.ts +84 -0
- package/agnostic/time/dates/format-date/types.js +1 -0
- package/agnostic/time/duration/format-duration/index.d.ts +42 -0
- package/agnostic/time/duration/format-duration/index.js +94 -0
- package/agnostic/time/duration/format-duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/format-duration/index.test.js +148 -0
- package/agnostic/time/duration/format-duration/parts.d.ts +32 -0
- package/agnostic/time/duration/format-duration/parts.js +107 -0
- package/agnostic/time/duration/format-duration/types.d.ts +93 -0
- package/agnostic/time/duration/format-duration/types.js +1 -0
- package/agnostic/time/duration/index.d.ts +6 -1
- package/agnostic/time/duration/index.js +2 -2
- package/agnostic/time/duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/index.test.js +168 -0
- package/components/BeforeAfter/index.controlled.d.ts +25 -25
- package/components/BeforeAfter/index.controlled.js +47 -53
- package/components/BeforeAfter/index.d.ts +20 -23
- package/components/BeforeAfter/index.js +48 -40
- package/components/Button/index.js +1 -1
- package/components/Clippable/index.d.ts +17 -26
- package/components/Clippable/index.js +21 -23
- package/components/Disclaimer/index.d.ts +29 -22
- package/components/Disclaimer/index.js +29 -24
- package/components/Drawer/index.d.ts +45 -25
- package/components/Drawer/index.js +61 -52
- package/components/EventListener/index.d.ts +4 -5
- package/components/Gallery/index.d.ts +14 -16
- package/components/Gallery/index.js +25 -30
- package/components/Iframe/index.js +2 -2
- package/components/Image/index.d.ts +5 -12
- package/components/Image/index.js +11 -32
- package/components/Input/index.d.ts +23 -19
- package/components/Input/index.js +30 -20
- package/components/JsonEditor/index.d.ts +177 -9
- package/components/JsonEditor/index.js +133 -75
- package/components/JsonEditor/types.d.ts +11 -0
- package/components/JsonEditor/types.js +1 -0
- package/components/JsonEditor/utils.d.ts +8 -0
- package/components/JsonEditor/utils.js +23 -0
- package/components/ListLoader/index.controlled.d.ts +78 -0
- package/components/ListLoader/index.controlled.js +99 -0
- package/components/ListLoader/index.d.ts +69 -0
- package/components/ListLoader/index.js +146 -0
- package/components/ListLoader/utils.d.ts +8 -0
- package/components/ListLoader/utils.js +10 -0
- package/components/Overlayer/index.js +4 -4
- package/components/Paginator/index.d.ts +7 -12
- package/components/Paginator/index.js +7 -11
- package/components/ResizeObserver/index.d.ts +14 -3
- package/components/ResizeObserver/index.js +49 -24
- package/components/ResizeObserver/styles.module.css +0 -0
- package/components/Scrllgngn/index.d.ts +17 -13
- package/components/Scrllgngn/index.js +25 -84
- package/components/Scrllgngn/utils.d.ts +52 -0
- package/components/Scrllgngn/utils.js +102 -0
- package/components/ScrollListener/index.d.ts +43 -28
- package/components/ScrollListener/index.js +59 -79
- package/components/ScrollListener/utils.d.ts +37 -16
- package/components/ScrollListener/utils.js +141 -28
- package/components/Select/index.d.ts +24 -20
- package/components/Select/index.js +30 -20
- package/components/Sequencer/index.controlled.d.ts +16 -26
- package/components/Sequencer/index.controlled.js +15 -12
- package/components/Sequencer/index.d.ts +25 -30
- package/components/Sequencer/index.js +20 -34
- package/components/Subtitles/index.d.ts +29 -5
- package/components/Subtitles/index.js +90 -12
- package/components/Textarea/index.d.ts +26 -20
- package/components/Textarea/index.js +40 -21
- package/components/Theatre/index.d.ts +35 -39
- package/components/Theatre/index.js +46 -58
- package/components/UIModule/index.d.ts +25 -29
- package/components/UIModule/index.js +81 -110
- package/components/Video/index.controlled.d.ts +51 -51
- package/components/Video/index.controlled.js +75 -72
- package/components/Video/index.d.ts +12 -14
- package/components/Video/index.js +41 -86
- package/components/Video/utils.d.ts +35 -3
- package/components/Video/utils.js +37 -14
- package/components/index.d.ts +5 -4
- package/components/index.js +5 -4
- package/components/public-classnames.d.ts +1 -0
- package/components/public-classnames.js +1 -0
- package/components/utils/index.d.ts +22 -0
- package/components/utils/index.js +31 -0
- package/node/@google-cloud/storage/directory/index.d.ts +2 -2
- package/node/@google-cloud/storage/directory/index.js +2 -2
- package/node/@google-cloud/storage/file/index.d.ts +2 -2
- package/node/@google-cloud/storage/file/index.js +2 -2
- package/node/@google-cloud/storage/index.d.ts +1 -1
- package/node/@google-cloud/storage/index.js +1 -1
- package/node/cloud-storage/operations/index.d.ts +2 -2
- package/node/cloud-storage/operations/index.js +2 -2
- package/node/ftps/directory/index.d.ts +1 -1
- package/node/ftps/directory/index.js +1 -1
- package/node/ftps/file/index.d.ts +2 -2
- package/node/ftps/file/index.js +2 -2
- package/node/images/index.d.ts +1 -1
- package/node/images/index.js +1 -1
- package/node/images/transform/operations/index.d.ts +3 -3
- package/node/images/transform/operations/index.js +3 -3
- package/node/index.d.ts +2 -2
- package/node/index.js +2 -2
- package/node/process/index.d.ts +1 -1
- package/node/process/index.js +1 -1
- package/node/sftp/directory/index.d.ts +1 -1
- package/node/sftp/directory/index.js +1 -1
- package/node/sftp/file/index.d.ts +1 -1
- package/node/sftp/file/index.js +1 -1
- package/package.json +27 -5
- package/TODO.md +0 -269
- package/components/BeforeAfter/utils.d.ts +0 -4
- package/components/BeforeAfter/utils.js +0 -9
- package/components/Input/index.controlled.d.ts +0 -42
- package/components/Input/index.controlled.js +0 -54
- package/components/Select/index.controlled.d.ts +0 -43
- package/components/Select/index.controlled.js +0 -54
- package/components/Subtitles/types.d.ts +0 -24
- package/components/Subtitles/utils.d.ts +0 -32
- package/components/Subtitles/utils.js +0 -107
- package/components/Textarea/index.controlled.d.ts +0 -50
- package/components/Textarea/index.controlled.js +0 -75
- /package/{components/Subtitles/types.js → agnostic/time/dates/format-date/index.test.d.ts} +0 -0
- /package/components/{ResizeObserver/style.module.css → ListLoader/styles.module.css} +0 -0
|
File without changes
|
|
@@ -71,10 +71,8 @@ export type PropsPage = {
|
|
|
71
71
|
* - `'after'` — forces blocks from pages after the current one.
|
|
72
72
|
* - `'both'` — forces blocks on both sides.
|
|
73
73
|
* - `'none'` — no forcing (default behaviour).
|
|
74
|
-
* @property
|
|
75
|
-
*
|
|
76
|
-
* @property stateHandlers.pageChanged - Called whenever the current page
|
|
77
|
-
* changes. Receives the zero-based index of the current page and the
|
|
74
|
+
* @property onPageChanged - Called once the current page has changed, never on
|
|
75
|
+
* mount. Receives the zero-based index of the new current page and the
|
|
78
76
|
* corresponding page definition, if available.
|
|
79
77
|
* @property className - Optional additional class name(s) applied to the root
|
|
80
78
|
* element.
|
|
@@ -84,9 +82,7 @@ export type Props = WithClassName<{
|
|
|
84
82
|
thresholdOffsetPercent?: number;
|
|
85
83
|
stickyBlocksLazyLoadDistance?: number;
|
|
86
84
|
forceStickBlocks?: 'before' | 'after' | 'both' | 'none';
|
|
87
|
-
|
|
88
|
-
pageChanged?: (currentPagePos: number, pageData?: PropsPage) => void;
|
|
89
|
-
};
|
|
85
|
+
onPageChanged?: (currentPagePos: number, pageData?: PropsPage) => void;
|
|
90
86
|
}>;
|
|
91
87
|
/**
|
|
92
88
|
* Scrollytelling engine component. Orchestrates layered sticky blocks (`back`
|
|
@@ -104,16 +100,24 @@ export type Props = WithClassName<{
|
|
|
104
100
|
* - `--force-stick-blocks-both` — when `forceStickBlocks === 'both'`.
|
|
105
101
|
*
|
|
106
102
|
* ### Data attributes
|
|
107
|
-
*
|
|
108
|
-
*
|
|
103
|
+
* Both are updated on every page change reported by the internal
|
|
104
|
+
* {@link Paginator}.
|
|
105
|
+
* - `data-current-page-pos` — zero-based index of the page currently in view.
|
|
106
|
+
* - `data-current-page-id` — that page's {@link PropsPage.id}. Absent while the
|
|
107
|
+
* current page carries no id, since the id is optional.
|
|
109
108
|
*
|
|
110
109
|
* ### CSS custom properties
|
|
111
110
|
* Exposed on the root element and updated on resize via the internal
|
|
112
111
|
* {@link ResizeObserverComponent}:
|
|
113
|
-
* - `--scrllgngn-screen-left` / `--
|
|
114
|
-
*
|
|
115
|
-
* - `--scrllgngn-screen-
|
|
116
|
-
* - `--scrllgngn-screen-
|
|
112
|
+
* - `--lm-scrllgngn-screen-left` / `--lm-scrllgngn-screen-left-raw` — left edge
|
|
113
|
+
* of the bounding rect.
|
|
114
|
+
* - `--lm-scrllgngn-screen-right` / `--lm-scrllgngn-screen-right-raw` — right edge.
|
|
115
|
+
* - `--lm-scrllgngn-screen-width` / `--lm-scrllgngn-screen-width-raw` — total width.
|
|
116
|
+
* - `--lm-scrllgngn-screen-height` / `--lm-scrllgngn-screen-height-raw` — total height.
|
|
117
|
+
*
|
|
118
|
+
* The same four measurements are also exposed as `--PRIVATE-left`, `-right`,
|
|
119
|
+
* `-width` and `-height` for the component's own stylesheet. They are internal:
|
|
120
|
+
* do not read or override them.
|
|
117
121
|
*
|
|
118
122
|
* ### Sticky block elements
|
|
119
123
|
* Each lazy-loaded sticky block receives:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { clss } from '../../agnostic/css/clss/index.js';
|
|
4
|
-
import { randomHash } from '../../agnostic/random/uuid/index.js';
|
|
5
4
|
import { IntersectionObserverComponent } from '../IntersectionObserver/index.js';
|
|
6
5
|
import { Paginator } from '../Paginator/index.js';
|
|
7
6
|
import { ResizeObserverComponent } from '../ResizeObserver/index.js';
|
|
8
|
-
import { mergeClassNames } from '../utils/index.js';
|
|
7
|
+
import { mergeClassNames, useChangeDispatch } from '../utils/index.js';
|
|
9
8
|
import { scrllgngn as publicClassName } from '../public-classnames.js';
|
|
9
|
+
import { consolidateStickyBlocks, lazyLoadedBlocks, toScreenCssProps } from './utils.js';
|
|
10
10
|
import cssModule from './styles.module.css';
|
|
11
11
|
/**
|
|
12
12
|
* Scrollytelling engine component. Orchestrates layered sticky blocks (`back`
|
|
@@ -24,16 +24,24 @@ import cssModule from './styles.module.css';
|
|
|
24
24
|
* - `--force-stick-blocks-both` — when `forceStickBlocks === 'both'`.
|
|
25
25
|
*
|
|
26
26
|
* ### Data attributes
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* Both are updated on every page change reported by the internal
|
|
28
|
+
* {@link Paginator}.
|
|
29
|
+
* - `data-current-page-pos` — zero-based index of the page currently in view.
|
|
30
|
+
* - `data-current-page-id` — that page's {@link PropsPage.id}. Absent while the
|
|
31
|
+
* current page carries no id, since the id is optional.
|
|
29
32
|
*
|
|
30
33
|
* ### CSS custom properties
|
|
31
34
|
* Exposed on the root element and updated on resize via the internal
|
|
32
35
|
* {@link ResizeObserverComponent}:
|
|
33
|
-
* - `--scrllgngn-screen-left` / `--
|
|
34
|
-
*
|
|
35
|
-
* - `--scrllgngn-screen-
|
|
36
|
-
* - `--scrllgngn-screen-
|
|
36
|
+
* - `--lm-scrllgngn-screen-left` / `--lm-scrllgngn-screen-left-raw` — left edge
|
|
37
|
+
* of the bounding rect.
|
|
38
|
+
* - `--lm-scrllgngn-screen-right` / `--lm-scrllgngn-screen-right-raw` — right edge.
|
|
39
|
+
* - `--lm-scrllgngn-screen-width` / `--lm-scrllgngn-screen-width-raw` — total width.
|
|
40
|
+
* - `--lm-scrllgngn-screen-height` / `--lm-scrllgngn-screen-height-raw` — total height.
|
|
41
|
+
*
|
|
42
|
+
* The same four measurements are also exposed as `--PRIVATE-left`, `-right`,
|
|
43
|
+
* `-width` and `-height` for the component's own stylesheet. They are internal:
|
|
44
|
+
* do not read or override them.
|
|
37
45
|
*
|
|
38
46
|
* ### Sticky block elements
|
|
39
47
|
* Each lazy-loaded sticky block receives:
|
|
@@ -48,7 +56,7 @@ import cssModule from './styles.module.css';
|
|
|
48
56
|
* back-blocks layer, front-blocks layer, paginated scrolling content, and
|
|
49
57
|
* bottom-bound sentinel.
|
|
50
58
|
*/
|
|
51
|
-
export const Scrllgngn = ({ pages, thresholdOffsetPercent, stickyBlocksLazyLoadDistance = 2, forceStickBlocks,
|
|
59
|
+
export const Scrllgngn = ({ pages, thresholdOffsetPercent, stickyBlocksLazyLoadDistance = 2, forceStickBlocks, onPageChanged, className }) => {
|
|
52
60
|
// State
|
|
53
61
|
const [topVisible, setTopVis] = useState(false);
|
|
54
62
|
const [contentVisible, setCntVis] = useState(false);
|
|
@@ -58,69 +66,20 @@ export const Scrllgngn = ({ pages, thresholdOffsetPercent, stickyBlocksLazyLoadD
|
|
|
58
66
|
const [partialBoundingRect, setPartialBoundingRect] = useState();
|
|
59
67
|
// Sticky blocks calculations
|
|
60
68
|
useEffect(() => {
|
|
61
|
-
|
|
62
|
-
for (const page of pages ?? []) {
|
|
63
|
-
const pageIndex = pages?.indexOf(page) ?? -1;
|
|
64
|
-
for (const block of page.blocks ?? []) {
|
|
65
|
-
const blockId = block.id ?? randomHash(12);
|
|
66
|
-
const found = consolidatedBlocks.get(blockId);
|
|
67
|
-
if (found !== undefined)
|
|
68
|
-
consolidatedBlocks.set(blockId, {
|
|
69
|
-
...found,
|
|
70
|
-
...block,
|
|
71
|
-
displayOnPages: [
|
|
72
|
-
...found.displayOnPages,
|
|
73
|
-
pageIndex
|
|
74
|
-
]
|
|
75
|
-
});
|
|
76
|
-
else
|
|
77
|
-
consolidatedBlocks.set(blockId, {
|
|
78
|
-
...block,
|
|
79
|
-
displayOnPages: [pageIndex]
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const consolidatedStickyBlocks = new Map(Array
|
|
84
|
-
.from(consolidatedBlocks)
|
|
85
|
-
.filter((e) => {
|
|
86
|
-
const block = e[1];
|
|
87
|
-
return block.depth === 'back'
|
|
88
|
-
|| block.depth === 'front';
|
|
89
|
-
}));
|
|
90
|
-
setStickyBlocks(consolidatedStickyBlocks);
|
|
69
|
+
setStickyBlocks(consolidateStickyBlocks(pages));
|
|
91
70
|
}, [pages]);
|
|
92
|
-
const lazyLoadedBackBlocks =
|
|
93
|
-
|
|
94
|
-
.filter(([, block]) => block.depth === 'back'
|
|
95
|
-
&& block.displayOnPages.some(dispPage => {
|
|
96
|
-
const absDiff = Math.abs(dispPage - currentPagePos);
|
|
97
|
-
return absDiff <= stickyBlocksLazyLoadDistance;
|
|
98
|
-
})).map(([, block]) => block)
|
|
99
|
-
.sort((a, b) => {
|
|
100
|
-
return (a.zIndex ?? -Infinity) - (b.zIndex ?? -Infinity);
|
|
101
|
-
});
|
|
102
|
-
const lazyLoadedFrontBlocks = Array
|
|
103
|
-
.from(stickyBlocks)
|
|
104
|
-
.filter(([, block]) => block.depth === 'front'
|
|
105
|
-
&& block.displayOnPages.some(dispPage => {
|
|
106
|
-
const absDiff = Math.abs(dispPage - currentPagePos);
|
|
107
|
-
return absDiff <= stickyBlocksLazyLoadDistance;
|
|
108
|
-
})).map(([, block]) => block)
|
|
109
|
-
.sort((a, b) => {
|
|
110
|
-
return (a.zIndex ?? -Infinity) - (b.zIndex ?? -Infinity);
|
|
111
|
-
});
|
|
71
|
+
const lazyLoadedBackBlocks = lazyLoadedBlocks(stickyBlocks, 'back', currentPagePos, stickyBlocksLazyLoadDistance);
|
|
72
|
+
const lazyLoadedFrontBlocks = lazyLoadedBlocks(stickyBlocks, 'front', currentPagePos, stickyBlocksLazyLoadDistance);
|
|
112
73
|
// Handlers
|
|
74
|
+
useChangeDispatch(currentPagePos, pagePos => onPageChanged?.(pagePos, pages?.[pagePos]));
|
|
113
75
|
const handleTopBoundDetect = e => setTopVis(e.ioEntry?.isIntersecting ?? false);
|
|
114
76
|
const handleCntDetect = e => setCntVis(e.ioEntry?.isIntersecting ?? false);
|
|
115
77
|
const handleBtmBoundDetect = e => setBtmVis(e.ioEntry?.isIntersecting ?? false);
|
|
116
|
-
const
|
|
78
|
+
const handlePagesChanged = statePages => {
|
|
117
79
|
const curPagePos = statePages.findIndex(page => page.position === 'curr');
|
|
118
80
|
if (curPagePos === -1)
|
|
119
81
|
return;
|
|
120
|
-
if (curPagePos === currentPagePos)
|
|
121
|
-
return;
|
|
122
82
|
setCurrentPagePos(curPagePos);
|
|
123
|
-
stateHandlers?.pageChanged?.(curPagePos, pages?.[curPagePos]);
|
|
124
83
|
};
|
|
125
84
|
const handleResize = ({ boundingClientRect }) => {
|
|
126
85
|
if (partialBoundingRect === undefined
|
|
@@ -140,24 +99,8 @@ export const Scrllgngn = ({ pages, thresholdOffsetPercent, stickyBlocksLazyLoadD
|
|
|
140
99
|
'force-stick-blocks-after': forceStickBlocks === 'after',
|
|
141
100
|
'force-stick-blocks-both': forceStickBlocks === 'both'
|
|
142
101
|
}), className);
|
|
143
|
-
const customCssProps =
|
|
144
|
-
|
|
145
|
-
customCssProps[`--${publicClassName}-screen-left`] = `${partialBoundingRect.left}px`;
|
|
146
|
-
customCssProps['--PRIVATE-left'] = `${partialBoundingRect.left}px`;
|
|
147
|
-
}
|
|
148
|
-
if (partialBoundingRect?.right !== undefined) {
|
|
149
|
-
customCssProps[`--${publicClassName}-screen-right`] = `${partialBoundingRect.right}px`;
|
|
150
|
-
customCssProps['--PRIVATE-right'] = `${partialBoundingRect.right}px`;
|
|
151
|
-
}
|
|
152
|
-
if (partialBoundingRect?.width !== undefined) {
|
|
153
|
-
customCssProps[`--${publicClassName}-screen-width`] = `${partialBoundingRect.width}px`;
|
|
154
|
-
customCssProps['--PRIVATE-width'] = `${partialBoundingRect.width}px`;
|
|
155
|
-
}
|
|
156
|
-
if (partialBoundingRect?.height !== undefined) {
|
|
157
|
-
customCssProps[`--${publicClassName}-screen-height`] = `${partialBoundingRect.height}px`;
|
|
158
|
-
customCssProps['--PRIVATE-height'] = `${partialBoundingRect.height}px`;
|
|
159
|
-
}
|
|
160
|
-
return _jsx("div", { className: rootClss, "data-current-page-pos": currentPagePos, style: { ...customCssProps }, children: _jsxs(ResizeObserverComponent, { onResized: handleResize, children: [_jsx("div", { className: c('top-bound'), children: _jsx(IntersectionObserverComponent, { onIntersected: handleTopBoundDetect }) }), _jsx("div", { className: c('back-blocks'), children: lazyLoadedBackBlocks.map((block, blockPos) => {
|
|
102
|
+
const customCssProps = toScreenCssProps(partialBoundingRect);
|
|
103
|
+
return _jsx("div", { className: rootClss, "data-current-page-pos": currentPagePos, "data-current-page-id": pages?.[currentPagePos]?.id, style: { ...customCssProps }, children: _jsxs(ResizeObserverComponent, { onResized: handleResize, children: [_jsx("div", { className: c('top-bound'), children: _jsx(IntersectionObserverComponent, { onIntersected: handleTopBoundDetect }) }), _jsx("div", { className: c('back-blocks'), children: lazyLoadedBackBlocks.map((block, blockPos) => {
|
|
161
104
|
const isActive = block.displayOnPages.includes(currentPagePos);
|
|
162
105
|
const blockClss = c('back-block', {
|
|
163
106
|
active: isActive,
|
|
@@ -171,9 +114,7 @@ export const Scrllgngn = ({ pages, thresholdOffsetPercent, stickyBlocksLazyLoadD
|
|
|
171
114
|
'lazy-loaded': !isActive
|
|
172
115
|
});
|
|
173
116
|
return _jsx("div", { className: blockClss, style: { zIndex: blockPos }, children: block.children });
|
|
174
|
-
}) }), _jsx("div", { className: c('scrolling-content'), children: _jsx(IntersectionObserverComponent, { onIntersected: handleCntDetect, children: _jsx(Paginator, { thresholdOffsetPercent: thresholdOffsetPercent,
|
|
175
|
-
pageChanged: handlePageChange
|
|
176
|
-
}, children: pages?.map(page => {
|
|
117
|
+
}) }), _jsx("div", { className: c('scrolling-content'), children: _jsx(IntersectionObserverComponent, { onIntersected: handleCntDetect, children: _jsx(Paginator, { thresholdOffsetPercent: thresholdOffsetPercent, onPagesChanged: handlePagesChanged, children: pages?.map(page => {
|
|
177
118
|
const scrollBlocks = page.blocks
|
|
178
119
|
?.filter(b => b.depth === 'scroll' || b.depth === undefined) ?? [];
|
|
179
120
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PropsPage, PropsStickyBlock } from './index.js';
|
|
2
|
+
/** The subset of a bounding rect a {@link Scrllgngn} tracks and exposes. */
|
|
3
|
+
export type ScreenRect = {
|
|
4
|
+
left: number;
|
|
5
|
+
right: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
/** Zero-based positions of the pages a consolidated block is displayed on. */
|
|
10
|
+
export type BlockConsolidatedData = {
|
|
11
|
+
displayOnPages: number[];
|
|
12
|
+
};
|
|
13
|
+
/** A sticky block, merged across every page it appears on. */
|
|
14
|
+
export type ConsolidatedStickyBlock = PropsStickyBlock & BlockConsolidatedData;
|
|
15
|
+
/**
|
|
16
|
+
* Merges the sticky blocks of every page into a single entry per block id.
|
|
17
|
+
*
|
|
18
|
+
* A block repeated across pages under the same `id` becomes one sticky block
|
|
19
|
+
* listing all the pages it shows on, so it stays mounted across them instead of
|
|
20
|
+
* being torn down and rebuilt at every page change. Blocks without an `id` get a
|
|
21
|
+
* random one and are therefore never merged.
|
|
22
|
+
*
|
|
23
|
+
* @param pages - The pages to walk, in order.
|
|
24
|
+
* @returns The sticky blocks, keyed by id. Scroll blocks are left out.
|
|
25
|
+
*/
|
|
26
|
+
export declare function consolidateStickyBlocks(pages?: PropsPage[]): Map<string, ConsolidatedStickyBlock>;
|
|
27
|
+
/**
|
|
28
|
+
* Picks the sticky blocks of one layer close enough to the current page to be
|
|
29
|
+
* worth mounting.
|
|
30
|
+
*
|
|
31
|
+
* @param blocks - Every consolidated sticky block.
|
|
32
|
+
* @param depth - The layer to pick from.
|
|
33
|
+
* @param currentPagePos - Zero-based position of the page in view.
|
|
34
|
+
* @param lazyLoadDistance - How many pages around the current one still mount
|
|
35
|
+
* their blocks.
|
|
36
|
+
* @returns The blocks to render, stacked by ascending `zIndex`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function lazyLoadedBlocks(blocks: Map<string, ConsolidatedStickyBlock>, depth: 'back' | 'front', currentPagePos: number, lazyLoadDistance: number): ConsolidatedStickyBlock[];
|
|
39
|
+
/**
|
|
40
|
+
* Builds the CSS custom properties exposed on a {@link Scrllgngn} root.
|
|
41
|
+
*
|
|
42
|
+
* The public `screen-*` set follows the usual convention and stays absent until
|
|
43
|
+
* the first measurement lands. The `--PRIVATE-*` set is what the component's own
|
|
44
|
+
* stylesheet positions its fixed layers with, and it is emitted from the very
|
|
45
|
+
* first render — as `initial`, the guaranteed-invalid value — so those layers can
|
|
46
|
+
* never inherit the same names from an ancestor component. `initial` leaves them
|
|
47
|
+
* behaving exactly as an unset variable would, without opening the hole.
|
|
48
|
+
*
|
|
49
|
+
* @param rect - The measured bounding rect, absent until the first resize lands.
|
|
50
|
+
* @returns The custom properties, keyed by their full name.
|
|
51
|
+
*/
|
|
52
|
+
export declare function toScreenCssProps(rect?: ScreenRect): Record<string, string>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { randomHash } from '../../agnostic/random/uuid/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Merges the sticky blocks of every page into a single entry per block id.
|
|
4
|
+
*
|
|
5
|
+
* A block repeated across pages under the same `id` becomes one sticky block
|
|
6
|
+
* listing all the pages it shows on, so it stays mounted across them instead of
|
|
7
|
+
* being torn down and rebuilt at every page change. Blocks without an `id` get a
|
|
8
|
+
* random one and are therefore never merged.
|
|
9
|
+
*
|
|
10
|
+
* @param pages - The pages to walk, in order.
|
|
11
|
+
* @returns The sticky blocks, keyed by id. Scroll blocks are left out.
|
|
12
|
+
*/
|
|
13
|
+
export function consolidateStickyBlocks(pages) {
|
|
14
|
+
const consolidatedBlocks = new Map();
|
|
15
|
+
for (const page of pages ?? []) {
|
|
16
|
+
const pageIndex = pages?.indexOf(page) ?? -1;
|
|
17
|
+
for (const block of page.blocks ?? []) {
|
|
18
|
+
const blockId = block.id ?? randomHash(12);
|
|
19
|
+
const found = consolidatedBlocks.get(blockId);
|
|
20
|
+
if (found !== undefined)
|
|
21
|
+
consolidatedBlocks.set(blockId, {
|
|
22
|
+
...found,
|
|
23
|
+
...block,
|
|
24
|
+
displayOnPages: [
|
|
25
|
+
...found.displayOnPages,
|
|
26
|
+
pageIndex
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
else
|
|
30
|
+
consolidatedBlocks.set(blockId, {
|
|
31
|
+
...block,
|
|
32
|
+
displayOnPages: [pageIndex]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return new Map(Array
|
|
37
|
+
.from(consolidatedBlocks)
|
|
38
|
+
.filter((e) => {
|
|
39
|
+
const block = e[1];
|
|
40
|
+
return block.depth === 'back'
|
|
41
|
+
|| block.depth === 'front';
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Picks the sticky blocks of one layer close enough to the current page to be
|
|
46
|
+
* worth mounting.
|
|
47
|
+
*
|
|
48
|
+
* @param blocks - Every consolidated sticky block.
|
|
49
|
+
* @param depth - The layer to pick from.
|
|
50
|
+
* @param currentPagePos - Zero-based position of the page in view.
|
|
51
|
+
* @param lazyLoadDistance - How many pages around the current one still mount
|
|
52
|
+
* their blocks.
|
|
53
|
+
* @returns The blocks to render, stacked by ascending `zIndex`.
|
|
54
|
+
*/
|
|
55
|
+
export function lazyLoadedBlocks(blocks, depth, currentPagePos, lazyLoadDistance) {
|
|
56
|
+
return Array
|
|
57
|
+
.from(blocks)
|
|
58
|
+
.map(([, block]) => block)
|
|
59
|
+
.filter(block => block.depth === depth
|
|
60
|
+
&& block.displayOnPages.some(dispPage => {
|
|
61
|
+
const absDiff = Math.abs(dispPage - currentPagePos);
|
|
62
|
+
return absDiff <= lazyLoadDistance;
|
|
63
|
+
}))
|
|
64
|
+
.sort((a, b) => (a.zIndex ?? -Infinity) - (b.zIndex ?? -Infinity));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Builds the CSS custom properties exposed on a {@link Scrllgngn} root.
|
|
68
|
+
*
|
|
69
|
+
* The public `screen-*` set follows the usual convention and stays absent until
|
|
70
|
+
* the first measurement lands. The `--PRIVATE-*` set is what the component's own
|
|
71
|
+
* stylesheet positions its fixed layers with, and it is emitted from the very
|
|
72
|
+
* first render — as `initial`, the guaranteed-invalid value — so those layers can
|
|
73
|
+
* never inherit the same names from an ancestor component. `initial` leaves them
|
|
74
|
+
* behaving exactly as an unset variable would, without opening the hole.
|
|
75
|
+
*
|
|
76
|
+
* @param rect - The measured bounding rect, absent until the first resize lands.
|
|
77
|
+
* @returns The custom properties, keyed by their full name.
|
|
78
|
+
*/
|
|
79
|
+
export function toScreenCssProps(rect) {
|
|
80
|
+
const publicProps = rect === undefined
|
|
81
|
+
? {}
|
|
82
|
+
: {
|
|
83
|
+
'--lm-scrllgngn-screen-left': `${rect.left}px`,
|
|
84
|
+
'--lm-scrllgngn-screen-left-raw': `${rect.left}`,
|
|
85
|
+
'--lm-scrllgngn-screen-right': `${rect.right}px`,
|
|
86
|
+
'--lm-scrllgngn-screen-right-raw': `${rect.right}`,
|
|
87
|
+
'--lm-scrllgngn-screen-width': `${rect.width}px`,
|
|
88
|
+
'--lm-scrllgngn-screen-width-raw': `${rect.width}`,
|
|
89
|
+
'--lm-scrllgngn-screen-height': `${rect.height}px`,
|
|
90
|
+
'--lm-scrllgngn-screen-height-raw': `${rect.height}`
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
...publicProps,
|
|
94
|
+
'--PRIVATE-left': toPrivateLength(rect?.left),
|
|
95
|
+
'--PRIVATE-right': toPrivateLength(rect?.right),
|
|
96
|
+
'--PRIVATE-width': toPrivateLength(rect?.width),
|
|
97
|
+
'--PRIVATE-height': toPrivateLength(rect?.height)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function toPrivateLength(value) {
|
|
101
|
+
return value === undefined ? 'initial' : `${value}px`;
|
|
102
|
+
}
|
|
@@ -2,46 +2,61 @@ import { type FunctionComponent, type PropsWithChildren } from 'react';
|
|
|
2
2
|
import type { WithClassName } from '../utils/types.js';
|
|
3
3
|
import { type ScrollState } from './utils.js';
|
|
4
4
|
/**
|
|
5
|
-
* Props for the ScrollListener component.
|
|
5
|
+
* Props for the {@link ScrollListener} component.
|
|
6
6
|
*
|
|
7
|
-
* @property startOnVisible - When `true`, scroll tracking starts
|
|
8
|
-
*
|
|
9
|
-
* @property stopOnHidden - When `true`, scroll tracking stops when the component
|
|
10
|
-
* the viewport.
|
|
11
|
-
* @property
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* component changes. Receives `true` when the component is intersecting the viewport,
|
|
16
|
-
* otherwise `false`.
|
|
7
|
+
* @property startOnVisible - When `true`, scroll tracking only starts once the
|
|
8
|
+
* component enters the viewport, instead of on mount.
|
|
9
|
+
* @property stopOnHidden - When `true`, scroll tracking stops when the component
|
|
10
|
+
* leaves the viewport.
|
|
11
|
+
* @property onScrollStateChanged - Called after the measured {@link ScrollState}
|
|
12
|
+
* changed. Receives `undefined` until the first measurement lands.
|
|
13
|
+
* @property onVisibilityChanged - Called on every intersection change, with
|
|
14
|
+
* `true` when the component intersects the viewport.
|
|
17
15
|
* @property className - Optional additional class name(s) applied to the root element.
|
|
18
16
|
* @property children - React nodes rendered inside the scroll listener container.
|
|
19
17
|
*/
|
|
20
18
|
export type Props = PropsWithChildren<WithClassName<{
|
|
21
|
-
stopOnHidden?: boolean;
|
|
22
19
|
startOnVisible?: boolean;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
20
|
+
stopOnHidden?: boolean;
|
|
21
|
+
onScrollStateChanged?: (scrollState?: ScrollState) => void;
|
|
22
|
+
onVisibilityChanged?: (isVisible: boolean) => void;
|
|
27
23
|
}>>;
|
|
28
24
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* Exposes scroll metrics — both the document's and its own — as CSS custom
|
|
26
|
+
* properties on its root element, so scroll-driven styling needs no JavaScript
|
|
27
|
+
* of its own.
|
|
31
28
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* ### CSS custom properties on the root element
|
|
30
|
+
* Each measurement comes as a `px` length under its bare name, and as a `-raw`
|
|
31
|
+
* twin holding the plain number:
|
|
32
|
+
* - `--lm-scroll-listener-window-width`, `--lm-scroll-listener-window-height`
|
|
33
|
+
* - `--lm-scroll-listener-html-width`, `--lm-scroll-listener-html-height`
|
|
34
|
+
* - `--lm-scroll-listener-scroll-x`, `--lm-scroll-listener-scroll-y`
|
|
35
|
+
* - `--lm-scroll-listener-width`, `--lm-scroll-listener-height`
|
|
36
|
+
* - `--lm-scroll-listener-offset-x`, `--lm-scroll-listener-offset-y`
|
|
35
37
|
*
|
|
36
|
-
*
|
|
37
|
-
* scroll-
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* Ratios are unitless and have no twin:
|
|
39
|
+
* - `--lm-scroll-listener-window-scrolled-x-ratio`,
|
|
40
|
+
* `--lm-scroll-listener-window-scrolled-y-ratio` — how far the document is
|
|
41
|
+
* scrolled.
|
|
42
|
+
* - `--lm-scroll-listener-self-inner-scrolled-x-ratio`,
|
|
43
|
+
* `--lm-scroll-listener-self-inner-scrolled-y-ratio` — `0` when the element's
|
|
44
|
+
* start edge meets the viewport's start edge, `1` when its end edge meets the
|
|
45
|
+
* viewport's end edge. The span where it is fully visible.
|
|
46
|
+
* - `--lm-scroll-listener-self-outer-scrolled-x-ratio`,
|
|
47
|
+
* `--lm-scroll-listener-self-outer-scrolled-y-ratio` — `0` when the element is
|
|
48
|
+
* about to enter the viewport, `1` once it has fully left it. The span where it
|
|
49
|
+
* overlaps the viewport at all.
|
|
41
50
|
*
|
|
42
51
|
* @param props - Component properties.
|
|
43
52
|
* @see {@link Props}
|
|
44
|
-
* @returns A container
|
|
45
|
-
*
|
|
53
|
+
* @returns A container exposing the metrics, wrapping its children inside an
|
|
54
|
+
* {@link IntersectionObserverComponent}.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* All mounted instances share a single pair of `scroll` / `resize` listeners and
|
|
58
|
+
* a single measurement pass per animation frame — the document is measured once
|
|
59
|
+
* for everyone, each element only for itself. The listeners exist only while at
|
|
60
|
+
* least one instance is tracking.
|
|
46
61
|
*/
|
|
47
62
|
export declare const ScrollListener: FunctionComponent<Props>;
|
|
@@ -1,100 +1,80 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { clss } from '../../agnostic/css/clss/index.js';
|
|
4
4
|
import { randomHash } from '../../agnostic/random/uuid/index.js';
|
|
5
|
-
import { mergeClassNames } from '../utils/index.js';
|
|
6
5
|
import { IntersectionObserverComponent } from '../IntersectionObserver/index.js';
|
|
6
|
+
import { mergeClassNames, useChangeDispatch } from '../utils/index.js';
|
|
7
7
|
import { scrollListener as publicClassName } from '../public-classnames.js';
|
|
8
|
-
import {
|
|
8
|
+
import { subscribe, toScrollCssProps, unsubscribe } from './utils.js';
|
|
9
9
|
import cssModule from './styles.module.css';
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Exposes scroll metrics — both the document's and its own — as CSS custom
|
|
12
|
+
* properties on its root element, so scroll-driven styling needs no JavaScript
|
|
13
|
+
* of its own.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* ### CSS custom properties on the root element
|
|
16
|
+
* Each measurement comes as a `px` length under its bare name, and as a `-raw`
|
|
17
|
+
* twin holding the plain number:
|
|
18
|
+
* - `--lm-scroll-listener-window-width`, `--lm-scroll-listener-window-height`
|
|
19
|
+
* - `--lm-scroll-listener-html-width`, `--lm-scroll-listener-html-height`
|
|
20
|
+
* - `--lm-scroll-listener-scroll-x`, `--lm-scroll-listener-scroll-y`
|
|
21
|
+
* - `--lm-scroll-listener-width`, `--lm-scroll-listener-height`
|
|
22
|
+
* - `--lm-scroll-listener-offset-x`, `--lm-scroll-listener-offset-y`
|
|
17
23
|
*
|
|
18
|
-
*
|
|
19
|
-
* scroll-
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
24
|
+
* Ratios are unitless and have no twin:
|
|
25
|
+
* - `--lm-scroll-listener-window-scrolled-x-ratio`,
|
|
26
|
+
* `--lm-scroll-listener-window-scrolled-y-ratio` — how far the document is
|
|
27
|
+
* scrolled.
|
|
28
|
+
* - `--lm-scroll-listener-self-inner-scrolled-x-ratio`,
|
|
29
|
+
* `--lm-scroll-listener-self-inner-scrolled-y-ratio` — `0` when the element's
|
|
30
|
+
* start edge meets the viewport's start edge, `1` when its end edge meets the
|
|
31
|
+
* viewport's end edge. The span where it is fully visible.
|
|
32
|
+
* - `--lm-scroll-listener-self-outer-scrolled-x-ratio`,
|
|
33
|
+
* `--lm-scroll-listener-self-outer-scrolled-y-ratio` — `0` when the element is
|
|
34
|
+
* about to enter the viewport, `1` once it has fully left it. The span where it
|
|
35
|
+
* overlaps the viewport at all.
|
|
23
36
|
*
|
|
24
37
|
* @param props - Component properties.
|
|
25
38
|
* @see {@link Props}
|
|
26
|
-
* @returns A container
|
|
27
|
-
*
|
|
39
|
+
* @returns A container exposing the metrics, wrapping its children inside an
|
|
40
|
+
* {@link IntersectionObserverComponent}.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* All mounted instances share a single pair of `scroll` / `resize` listeners and
|
|
44
|
+
* a single measurement pass per animation frame — the document is measured once
|
|
45
|
+
* for everyone, each element only for itself. The listeners exist only while at
|
|
46
|
+
* least one instance is tracking.
|
|
28
47
|
*/
|
|
29
|
-
export const ScrollListener = ({ startOnVisible, stopOnHidden,
|
|
30
|
-
|
|
31
|
-
const [
|
|
48
|
+
export const ScrollListener = ({ startOnVisible, stopOnHidden, onScrollStateChanged, onVisibilityChanged, className, children }) => {
|
|
49
|
+
// State & refs
|
|
50
|
+
const [subscriberId] = useState(() => randomHash(6));
|
|
51
|
+
const [scrollState, setScrollState] = useState();
|
|
32
52
|
const rootRef = useRef(null);
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// Fx. no dep. - register / unregister to scroll listeners
|
|
53
|
+
// State dispatch
|
|
54
|
+
useChangeDispatch(scrollState, onScrollStateChanged);
|
|
55
|
+
// Fx. no dep. - track from mount, unless waiting for the component to show up.
|
|
56
|
+
// The cleanup runs whichever way the subscription was opened.
|
|
38
57
|
useEffect(() => {
|
|
39
|
-
|
|
40
|
-
|
|
58
|
+
if (startOnVisible !== true) {
|
|
59
|
+
subscribe(subscriberId, { rootRef, onScrollStateChange: setScrollState });
|
|
60
|
+
}
|
|
61
|
+
return () => unsubscribe(subscriberId);
|
|
41
62
|
}, []);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
if (ioEntry?.isIntersecting !== true && stopOnHidden === true)
|
|
49
|
-
unregister(privateId);
|
|
50
|
-
}, [startOnVisible, stopOnHidden]);
|
|
51
|
-
// Rendering
|
|
52
|
-
const customProps = Object
|
|
53
|
-
.entries(scrollData !== undefined
|
|
54
|
-
? {
|
|
55
|
-
// Global
|
|
56
|
-
[`--${publicClassName}-window-width`]: scrollData.global.win.width,
|
|
57
|
-
[`--${publicClassName}-window-height`]: scrollData.global.win.height,
|
|
58
|
-
[`--${publicClassName}-html-width`]: scrollData.global.html.width,
|
|
59
|
-
[`--${publicClassName}-html-height`]: scrollData.global.html.height,
|
|
60
|
-
[`--${publicClassName}-scroll-x`]: scrollData.global.scroll.x,
|
|
61
|
-
[`--${publicClassName}-scroll-y`]: scrollData.global.scroll.y,
|
|
62
|
-
// Local
|
|
63
|
-
[`--${publicClassName}-width`]: scrollData.local.width,
|
|
64
|
-
[`--${publicClassName}-height`]: scrollData.local.height,
|
|
65
|
-
[`--${publicClassName}-offset-x`]: scrollData.local.offsetX,
|
|
66
|
-
[`--${publicClassName}-offset-y`]: scrollData.local.offsetY
|
|
63
|
+
// User action handlers
|
|
64
|
+
const handleIntersection = useCallback(({ ioEntry }) => {
|
|
65
|
+
const isVisible = ioEntry?.isIntersecting ?? false;
|
|
66
|
+
onVisibilityChanged?.(isVisible);
|
|
67
|
+
if (isVisible && startOnVisible === true) {
|
|
68
|
+
subscribe(subscriberId, { rootRef, onScrollStateChange: setScrollState });
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}), {});
|
|
73
|
-
if (scrollData !== undefined) {
|
|
74
|
-
customProps[`--${publicClassName}-window-scrolled-x-ratio`] = (scrollData.global.scroll.x) / Math.max((scrollData.global.html.width - scrollData.global.win.width), 1);
|
|
75
|
-
customProps[`--${publicClassName}-window-scrolled-y-ratio`] = (scrollData.global.scroll.y) / Math.max((scrollData.global.html.height - scrollData.global.win.height), 1);
|
|
76
|
-
const topTouchesTop = scrollData.local.offsetY;
|
|
77
|
-
const topTouchesBottom = scrollData.local.offsetY - scrollData.global.win.height;
|
|
78
|
-
const bottomTouchesTop = scrollData.local.offsetY + scrollData.local.height;
|
|
79
|
-
const bottomTouchesBottom = (scrollData.local.offsetY + scrollData.local.height) - scrollData.global.win.height;
|
|
80
|
-
const leftTouchesLeft = scrollData.local.offsetX;
|
|
81
|
-
const leftTouchesRight = scrollData.local.offsetX - scrollData.global.win.width;
|
|
82
|
-
const rightTouchesLeft = scrollData.local.offsetX + scrollData.local.width;
|
|
83
|
-
const rightTouchesRight = (scrollData.local.offsetX + scrollData.local.width) - scrollData.global.win.width;
|
|
84
|
-
const innerYRange = [bottomTouchesBottom, topTouchesTop];
|
|
85
|
-
const outerYRange = [topTouchesBottom, bottomTouchesTop];
|
|
86
|
-
const innerXRange = [rightTouchesRight, leftTouchesLeft];
|
|
87
|
-
const outerXRange = [leftTouchesRight, rightTouchesLeft];
|
|
88
|
-
const innerScrollYRatio = (scrollData.global.scroll.y - innerYRange[0]) / Math.max((innerYRange[1] - innerYRange[0]), 1);
|
|
89
|
-
const outerScrollYRatio = (scrollData.global.scroll.y - outerYRange[0]) / Math.max((outerYRange[1] - outerYRange[0]), 1);
|
|
90
|
-
const innerScrollXRatio = (scrollData.global.scroll.x - innerXRange[0]) / Math.max((innerXRange[1] - innerXRange[0]), 1);
|
|
91
|
-
const outerScrollXRatio = (scrollData.global.scroll.x - outerXRange[0]) / Math.max((outerXRange[1] - outerXRange[0]), 1);
|
|
92
|
-
customProps[`--${publicClassName}-self-inner-scrolled-y-ratio`] = innerScrollYRatio;
|
|
93
|
-
customProps[`--${publicClassName}-self-outer-scrolled-y-ratio`] = outerScrollYRatio;
|
|
94
|
-
customProps[`--${publicClassName}-self-inner-scrolled-x-ratio`] = innerScrollXRatio;
|
|
95
|
-
customProps[`--${publicClassName}-self-outer-scrolled-x-ratio`] = outerScrollXRatio;
|
|
96
|
-
}
|
|
70
|
+
if (!isVisible && stopOnHidden === true)
|
|
71
|
+
unsubscribe(subscriberId);
|
|
72
|
+
}, [startOnVisible, stopOnHidden, onVisibilityChanged]);
|
|
73
|
+
// Rendering
|
|
97
74
|
const c = clss(publicClassName, { cssModule });
|
|
98
75
|
const rootClss = mergeClassNames(c(), className);
|
|
76
|
+
const customProps = scrollState === undefined
|
|
77
|
+
? {}
|
|
78
|
+
: toScrollCssProps(scrollState);
|
|
99
79
|
return _jsx("div", { className: rootClss, ref: rootRef, style: { ...customProps }, children: _jsx(IntersectionObserverComponent, { onIntersected: handleIntersection, children: children }) });
|
|
100
80
|
};
|