react-sticky-kit 0.3.0 โ 0.4.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.
- package/README.md +90 -31
- package/dist/context.d.cts +2 -0
- package/dist/context.d.ts +2 -0
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/react-sticky.cjs +1 -1
- package/dist/react-sticky.es.js +188 -112
- package/dist/react-sticky.umd.js +1 -1
- package/dist/scheduler.d.cts +1 -0
- package/dist/scheduler.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +12 -7
package/README.md
CHANGED
|
@@ -24,62 +24,117 @@
|
|
|
24
24
|
</a>
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Coordinate multiple sticky section headers in React. Stack headers using their actual
|
|
28
|
+
heights, replace a section header as the next one arrives, or mix both behaviors
|
|
29
|
+
under a shared viewport offset.
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
**Use native CSS `position: sticky` for a single header or a straightforward grouped
|
|
32
|
+
list.** Choose React Sticky Kit when you need dynamic-height stacking, mixed
|
|
33
|
+
stack/replace behavior, or the total sticky height without maintaining your own
|
|
34
|
+
measurement and scroll logic.
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
36
|
+
## See the behavior
|
|
37
|
+
|
|
38
|
+
| Replace section headings | Stack reached headings |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
|  |  |
|
|
41
|
+
|
|
42
|
+
- **Replace:** an alphabetical contact list updates its section heading as you scroll.
|
|
43
|
+
- **Stack:** previously reached headings accumulate below the shared offset; their
|
|
44
|
+
heights are measured automatically, including when content changes.
|
|
45
|
+
- **Mixed:** keep a page title stacked while section headings replace below it.
|
|
46
|
+
|
|
47
|
+
[Open the live demo](https://app.evecalm.com/react-sticky-kit/) โ no installation required.
|
|
48
|
+
Try [replace](https://app.evecalm.com/react-sticky-kit/#replace),
|
|
49
|
+
[stack](https://app.evecalm.com/react-sticky-kit/#stack), or
|
|
50
|
+
[mixed modes](https://app.evecalm.com/react-sticky-kit/#mixed-mode).
|
|
51
|
+
The demo also includes dynamic heights, nested groups and container boundaries.
|
|
52
|
+
To edit an example, use the [contact-list sandbox](https://codesandbox.io/p/sandbox/dreamy-hofstadter-v9dzfz);
|
|
53
|
+
see [running the demo](#run-the-demo) for local development.
|
|
54
|
+
|
|
55
|
+
## Content taller than the viewport
|
|
56
|
+
|
|
57
|
+
Keep the existing Container / Item structure and opt into coordinated scrolling:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<StickyContainer defaultMode="stack" overflowBehavior="scroll"
|
|
61
|
+
offsetTop={16} offsetBottom={16} positionStrategy="auto">
|
|
62
|
+
<StickyItem><Sidebar /></StickyItem>
|
|
63
|
+
<main>{content}</main>
|
|
64
|
+
</StickyContainer>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Oversized active items scroll as one group before pinning their top or bottom
|
|
68
|
+
edge. The default behavior remains unchanged. `auto` uses native sticky for
|
|
69
|
+
eligible single short items and falls back to fixed positioning for other cases.
|
|
70
|
+
This is still a viewport-scrolling API, not support for internal scroll frames.
|
|
71
|
+
See [behavior, compatibility checks and measurements](docs/oversized-content.md).
|
|
39
72
|
|
|
40
73
|
## Installation
|
|
41
74
|
|
|
42
75
|
```bash
|
|
43
76
|
npm install react-sticky-kit
|
|
44
|
-
# or
|
|
45
|
-
yarn add react-sticky-kit
|
|
46
|
-
# or
|
|
47
|
-
pnpm add react-sticky-kit
|
|
77
|
+
# or: pnpm add react-sticky-kit
|
|
48
78
|
```
|
|
49
79
|
|
|
50
|
-
##
|
|
51
|
-
- [Apple iOS Contact App](https://codesandbox.io/p/sandbox/dreamy-hofstadter-v9dzfz)
|
|
80
|
+
## Quick start: replacing section headers
|
|
52
81
|
|
|
53
|
-
|
|
82
|
+
Import the stylesheet once. Give sections enough content to scroll; headers replace
|
|
83
|
+
one another within the container's boundary.
|
|
54
84
|
|
|
55
85
|
```tsx
|
|
56
86
|
import { StickyContainer, StickyItem } from 'react-sticky-kit';
|
|
57
|
-
|
|
58
|
-
import 'react-sticky-kit/dist/style.css';
|
|
59
|
-
// or `import 'react-sticky-kit/style';` for more clean style path(require modern bundler tools)
|
|
87
|
+
import 'react-sticky-kit/style';
|
|
60
88
|
|
|
61
|
-
export default function
|
|
89
|
+
export default function Sections() {
|
|
62
90
|
return (
|
|
63
|
-
<StickyContainer
|
|
64
|
-
<StickyItem>
|
|
65
|
-
|
|
66
|
-
</StickyItem>
|
|
67
|
-
<
|
|
68
|
-
<StickyItem mode="replace">
|
|
69
|
-
<div>Another Sticky Header (replace mode)</div>
|
|
70
|
-
</StickyItem>
|
|
71
|
-
<div>More Content...</div>
|
|
91
|
+
<StickyContainer defaultMode="replace" offsetTop={48}>
|
|
92
|
+
<StickyItem><h2 style={{ margin: 0, padding: 12, background: '#fff' }}>Overview</h2></StickyItem>
|
|
93
|
+
<section style={{ minHeight: 600 }}>Overview content</section>
|
|
94
|
+
<StickyItem><h2 style={{ margin: 0, padding: 12, background: '#fff' }}>Details</h2></StickyItem>
|
|
95
|
+
<section style={{ minHeight: 600 }}>Details content</section>
|
|
72
96
|
</StickyContainer>
|
|
73
97
|
);
|
|
74
98
|
}
|
|
75
99
|
```
|
|
76
100
|
|
|
101
|
+
Change `defaultMode` to `"stack"` to retain previously reached headings. To keep a
|
|
102
|
+
page title above replacing section headings, add a first `<StickyItem mode="stack">`.
|
|
103
|
+
Offsets are relative to the **viewport**, including when scrolling an inner element.
|
|
104
|
+
For offsets relative to a scrollable panel, prefer native CSS sticky positioning.
|
|
105
|
+
|
|
106
|
+
## Which approach should I choose?
|
|
107
|
+
|
|
108
|
+
| Need | Start with |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| A single sticky navigation bar or simple grouped list | Native CSS `position: sticky` |
|
|
111
|
+
| A sidebar taller than the viewport | A sidebar-focused solution such as `react-sticky-box` |
|
|
112
|
+
| Dynamic-height headers that stack automatically | React Sticky Kit, `stack` mode |
|
|
113
|
+
| A persistent title above replacing section headings | React Sticky Kit, mixed modes |
|
|
114
|
+
| The current total sticky height | `onStickyItemsHeightChange` |
|
|
115
|
+
| Table columns, built-in virtualization, or hide-on-scroll navigation | A solution designed for that specific interaction |
|
|
116
|
+
|
|
117
|
+
React Sticky Kit uses fixed positioning while active. It is not a drop-in
|
|
118
|
+
replacement for scroll-container-relative sticky behavior. Ancestor transforms
|
|
119
|
+
and overflow clipping can affect fixed positioning.
|
|
120
|
+
|
|
121
|
+
React 17/18/19, SSR and TypeScript 5 NodeNext consumers are covered by package
|
|
122
|
+
checks. The ESM artifact is approximately **4.43 kB gzip**, excluding React and CSS;
|
|
123
|
+
there are no additional runtime dependencies. See the
|
|
124
|
+
[performance audit](docs/performance.md) for methods and tradeoffs.
|
|
125
|
+
|
|
126
|
+
For practical examples and existing-library migration, see the
|
|
127
|
+
[patterns and migration guide](docs/patterns-and-migration.md).
|
|
128
|
+
|
|
77
129
|
## Props
|
|
78
130
|
|
|
79
131
|
### `<StickyContainer />`
|
|
80
132
|
| Prop | Type | Default | Description |
|
|
81
133
|
|-----------------------------|------------------------------------------------------|-------------|---------------------------------------------------------------------------------------------|
|
|
82
134
|
| `offsetTop` | `number` | `0` | Offset from the top of the viewport |
|
|
135
|
+
| `offsetBottom` | `number` | `0` | Bottom space reserved for oversized scrolling groups |
|
|
136
|
+
| `overflowBehavior` | `'pin' \| 'scroll'` | `'pin'` | Opt into coordinated scrolling of oversized active items |
|
|
137
|
+
| `positionStrategy` | `'fixed' \| 'auto'` | `'fixed'` | Opt into native sticky for eligible single short items |
|
|
83
138
|
| `defaultMode` | `'replace' \| 'stack' \| 'none'` | `'replace'` | Default sticky mode for all items |
|
|
84
139
|
| `baseZIndex` | `number` | `200` | Base z-index for sticky items. Should be greater than the number of sticky items. |
|
|
85
140
|
| | | | In `replace` mode, z-index = baseZIndex - index; in `stack` mode, z-index = baseZIndex + index. |
|
|
@@ -129,7 +184,11 @@ When you set `constraint="none"`, the sticky items will always stick when they r
|
|
|
129
184
|
|
|
130
185
|
In contrast, the default behavior (without specifying a constraint) only makes items sticky when their parent container is visible in the viewport.
|
|
131
186
|
|
|
132
|
-
##
|
|
187
|
+
## Run the demo
|
|
188
|
+
|
|
189
|
+
The demo builds as a standalone static site with `pnpm build:demo`. Its relative
|
|
190
|
+
asset paths work when hosted under a repository subdirectory.
|
|
191
|
+
See [deployment instructions](docs/demo-deployment.md) for GitHub Pages setup.
|
|
133
192
|
|
|
134
193
|
Run the demo locally:
|
|
135
194
|
|
package/dist/context.d.cts
CHANGED
|
@@ -11,6 +11,8 @@ export interface IStickyItemMeasurement {
|
|
|
11
11
|
export interface IStickyItemHandle {
|
|
12
12
|
el: HTMLElement;
|
|
13
13
|
content: HTMLElement;
|
|
14
|
+
canNative: boolean;
|
|
15
|
+
applyNative: (top: number, zIndex: number) => void;
|
|
14
16
|
mode: Exclude<IStickyMode, 'none'>;
|
|
15
17
|
measure: (rect: DOMRect) => IStickyItemMeasurement;
|
|
16
18
|
invalidate: () => void;
|
package/dist/context.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface IStickyItemMeasurement {
|
|
|
11
11
|
export interface IStickyItemHandle {
|
|
12
12
|
el: HTMLElement;
|
|
13
13
|
content: HTMLElement;
|
|
14
|
+
canNative: boolean;
|
|
15
|
+
applyNative: (top: number, zIndex: number) => void;
|
|
14
16
|
mode: Exclude<IStickyMode, 'none'>;
|
|
15
17
|
measure: (rect: DOMRect) => IStickyItemMeasurement;
|
|
16
18
|
invalidate: () => void;
|
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,12 @@ export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
7
7
|
* The offset from the top of the viewport for sticky elements. Default is 0.
|
|
8
8
|
*/
|
|
9
9
|
offsetTop?: number;
|
|
10
|
+
/** Space below oversized groups when overflowBehavior="scroll". */
|
|
11
|
+
offsetBottom?: number;
|
|
12
|
+
/** Preserve pinning (default), or scroll oversized active groups as one unit. */
|
|
13
|
+
overflowBehavior?: 'pin' | 'scroll';
|
|
14
|
+
/** Opt into native sticky for eligible single, direct-child items. Defaults to fixed. */
|
|
15
|
+
positionStrategy?: 'fixed' | 'auto';
|
|
10
16
|
/**
|
|
11
17
|
* base z-index for sticky items. Default is 200. minimum z-index is 20.
|
|
12
18
|
* * - When using the `replace` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` minus its index within the container.
|
|
@@ -31,4 +37,4 @@ export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
31
37
|
*/
|
|
32
38
|
constraint?: 'none';
|
|
33
39
|
}
|
|
34
|
-
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
|
40
|
+
export declare function StickyContainer({ children, offsetTop, offsetBottom, overflowBehavior, positionStrategy, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
7
7
|
* The offset from the top of the viewport for sticky elements. Default is 0.
|
|
8
8
|
*/
|
|
9
9
|
offsetTop?: number;
|
|
10
|
+
/** Space below oversized groups when overflowBehavior="scroll". */
|
|
11
|
+
offsetBottom?: number;
|
|
12
|
+
/** Preserve pinning (default), or scroll oversized active groups as one unit. */
|
|
13
|
+
overflowBehavior?: 'pin' | 'scroll';
|
|
14
|
+
/** Opt into native sticky for eligible single, direct-child items. Defaults to fixed. */
|
|
15
|
+
positionStrategy?: 'fixed' | 'auto';
|
|
10
16
|
/**
|
|
11
17
|
* base z-index for sticky items. Default is 200. minimum z-index is 20.
|
|
12
18
|
* * - When using the `replace` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` minus its index within the container.
|
|
@@ -31,4 +37,4 @@ export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
31
37
|
*/
|
|
32
38
|
constraint?: 'none';
|
|
33
39
|
}
|
|
34
|
-
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
|
40
|
+
export declare function StickyContainer({ children, offsetTop, offsetBottom, overflowBehavior, positionStrategy, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
package/dist/react-sticky.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("react");c=s(c,1);var l=(0,c.createContext)(null);function u(){return(0,c.useContext)(l)}var d=new Map,f=null;function p(e,t){if(typeof ResizeObserver>`u`)return()=>{};f!=null||(f=new ResizeObserver(e=>{let t=new Map;for(let r of e){var n;for(let e of(n=d.get(r.target))==null?[]:n){let n=t.get(e);n?n.push(r):t.set(e,[r])}}for(let[e,n]of t)e(n)}));let n=d.get(e);return n||(n=new Set,d.set(e,n),f.observe(e)),n.add(t),()=>{n.delete(t),n.size||(d.delete(e),f==null||f.unobserve(e)),d.size||(f==null||f.disconnect(),f=null)}}var m=new Map,h=new Map,g=null,_=!1;function v(){for(let e of m.values())e()}function y(){_||(_=!0,Promise.resolve().then(()=>{_=!1,m.size&&b()}))}function b(){let e=new Set,t=new Set;for(let n of m.keys())for(let r=n;r!=null&&r.parentElement;r=r.parentElement){let n=r.parentElement;e.add(n);for(let t=r.previousElementSibling;t&&!e.has(t);t=t.previousElementSibling)e.add(t);if(t.has(n))break;t.add(n)}let n=[...h.keys()].filter(t=>!e.has(t));n.length&&(g==null||g.disconnect());for(let e of n)h.get(e)(),h.delete(e);for(let t of e){let e=!h.has(t);e&&h.set(t,p(t,v)),(e||n.length)&&(g==null||g.observe(t,{childList:!0,attributes:!0,attributeFilter:[`class`,`style`]}))}}function x(e,t){return m.set(e,t),!g&&typeof MutationObserver<`u`&&(g=new MutationObserver(e=>{e.some(e=>e.type===`childList`)&&y(),v()})),y(),()=>{if(m.delete(e),m.size)y();else{g==null||g.disconnect(),g=null;for(let e of h.values())e();h.clear()}}}var S=new Set,C=new Set,w=null;function T(e){S.has(e)&&(C.add(e),w!=null||(w=requestAnimationFrame(O)))}function E(){for(let e of S)T(e)}function D(){for(let e of S)e.resize(),T(e)}function O(){w=null;let e=[...C];C.clear();let t=[],n=[],r=[];for(let n of e)if(S.has(n))try{let e=n.read();e&&t.push({client:n,write:e})}catch(e){r.push(e)}for(let{client:e,write:i}of t)if(S.has(e))try{let t=i();t&&n.push({client:e,notify:t})}catch(e){r.push(e)}for(let{client:e,notify:t}of n)if(S.has(e))try{t()}catch(e){r.push(e)}if(r.length)throw r[0]}function k(e,t){let n={read:e,resize:t};return S.size||(window.addEventListener(`scroll`,E,{passive:!0,capture:!0}),window.addEventListener(`resize`,D,{passive:!0})),S.add(n),T(n),{schedule:()=>T(n),stop:()=>{S.delete(n),C.delete(n),!C.size&&w!==null&&(cancelAnimationFrame(w),w=null),S.size||(window.removeEventListener(`scroll`,E,!0),window.removeEventListener(`resize`,D))}}}function A({mode:e,children:t,className:n,...r}){var i;let a=u(),o=(0,c.useRef)(null),s=(0,c.useRef)(null),l=a==null?void 0:a.register,d=e==null?a==null?void 0:a.mode:e,f=a==null?void 0:a.baseZIndex,p=(i=r.style)==null?void 0:i.height,m=(0,c.useRef)(null),h=a==null?void 0:a.scheduleUpdate;return(0,c.useEffect)(()=>{let e=o.current,t=s.current;if(!e||!t)return;let n=typeof p==`number`?`${p}px`:p==null?``:p;if(j(e,`height`,n),!l||!d||d===`none`)return;let r=p===void 0||[`auto`,`initial`,`unset`,`revert`,`revert-layer`,`fit-content`,`min-content`,`max-content`].includes(String(p)),i=!1,a=null,c=()=>{if(i){i=!1,a=null,t.classList.remove(`is-sticky`),e.style.height=n;for(let e of[`top`,`left`,`width`,`z-index`])t.style.removeProperty(e)}},u=null,h={el:e,content:t,mode:d,apply:n=>{if(n===null){c();return}let{top:o,wrapperHeight:s,width:l,left:u,index:p}=n;a&&a.top===o&&a.wrapperHeight===s&&a.width===l&&a.left===u&&a.index===p||(a=n,r&&j(e,`height`,`${s}px`),j(t,`top`,`${o}px`),j(t,`left`,`${u}px`),j(t,`width`,`${l}px`),j(t,`zIndex`,`${(f==null?200:f)+(d===`replace`?-p:p)}`),i||(i=!0,t.classList.add(`is-sticky`)))},measure:n=>{u!=null||(u=M(e,t));let r=t.getBoundingClientRect().height;return{height:r,wrapperHeight:r+u.heightInset,width:Math.max(0,n.width-u.widthInset),left:n.left+u.leftInset}},invalidate:()=>{u=null,a=null}};m.current=h;let g=l(h);return()=>{m.current=null,g(),c()}},[l,d,f,p]),(0,c.useEffect)(()=>{var e;(e=m.current)==null||e.invalidate(),h==null||h()}),c.default.createElement(`div`,{...r,className:[`oe-sticky-item`,n].filter(Boolean).join(` `),ref:o},c.default.createElement(`div`,{className:`oe-sticky-content`,ref:s},t))}function j(e,t,n){e.style[t]!==n&&(e.style[t]=n)}function M(e,t){let n=getComputedStyle(e),r=getComputedStyle(t),i=e=>Number.parseFloat(e)||0,a=e=>i(e.paddingLeft)+i(e.paddingRight)+i(e.borderLeftWidth)+i(e.borderRightWidth);return{heightInset:n.boxSizing===`border-box`?i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth):0,widthInset:a(n)+(r.boxSizing===`border-box`?0:a(r)),leftInset:i(n.paddingLeft)+i(n.borderLeftWidth)}}function N({children:e,offsetTop:t=0,baseZIndex:n,onStickyItemsHeightChange:r,defaultMode:i=`replace`,constraint:a,className:o,...s}){let u=(0,c.useRef)(null),d=(0,c.useRef)(new Set),f=(0,c.useRef)(null),m=(0,c.useRef)(new Map),h=(0,c.useRef)(!1),g=(0,c.useRef)(null),_=(0,c.useRef)(new Map),v=(0,c.useRef)(0),y=(0,c.useRef)({offsetTop:t,constraint:a,onStickyItemsHeightChange:r}),b=(0,c.useCallback)(()=>{var e;return(e=g.current)==null?void 0:e.schedule()},[]),S=(0,c.useCallback)(()=>{var e;let t=u.current;if(!t)return;let n=y.current,r=t.getBoundingClientRect();if(!(n.constraint===`none`||r.top<=n.offsetTop&&r.bottom>=n.offsetTop))return()=>{if(h.current){t.classList.remove(`can-sticky`);for(let e of d.current)e.apply(null);h.current=!1}if(v.current!==0)return v.current=0,()=>{var e;return(e=n.onStickyItemsHeightChange)==null?void 0:e.call(n,0)}};let i=((e=f.current)==null?f.current=[...d.current]:e).map(e=>({item:e,rect:e.el.getBoundingClientRect()})).sort((e,t)=>{let n=e.rect.top-t.rect.top;return n===0?e.item.el.compareDocumentPosition(t.item.el)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1:n}),a=n.offsetTop,o=0,s=i.map(({item:e,rect:t},n)=>{var r;if(t.top>a)return null;let s=(r=i[n+1])==null?void 0:r.rect.top;if(e.mode===`replace`&&s!==void 0&&s<a)return null;let c=e.measure(t),l=e.mode===`replace`&&s!==void 0?Math.min(a,s-c.height):a;return o+=c.height,e.mode===`stack`&&(a+=c.height),{...c,top:l,index:n}}),c=n.constraint===`none`?0:Math.min(0,r.bottom-n.offsetTop-o);return()=>{if(h.current=s.some(e=>e!==null),t.classList.toggle(`can-sticky`,h.current),i.forEach(({item:e},t)=>{let n=s[t];n&&(n.top+=c),e.apply(n)}),v.current!==o)return v.current=o,()=>{var e;return(e=n.onStickyItemsHeightChange)==null?void 0:e.call(n,o)}}},[]),C=(0,c.useCallback)(e=>{var t;for(let n of e)(t=m.current.get(n.target))==null||t.invalidate();b()},[b]),w=(0,c.useCallback)(()=>{for(let e of d.current)e.invalidate()},[]),T=(0,c.useCallback)(e=>(d.current.add(e),f.current=null,m.current.set(e.el,e),m.current.set(e.content,e),g.current&&(_.current.set(e.el,p(e.el,C)),_.current.set(e.content,p(e.content,C))),b(),()=>{var t,n;(t=_.current.get(e.el))==null||t(),(n=_.current.get(e.content))==null||n(),_.current.delete(e.el),_.current.delete(e.content),m.current.delete(e.el),m.current.delete(e.content),d.current.delete(e),f.current=null,b()}),[b,C]);(0,c.useEffect)(()=>{g.current=k(S,w);let e;if(typeof ResizeObserver<`u`){u.current&&(_.current.set(u.current,p(u.current,C)),e=x(u.current,()=>{w(),b()}));for(let e of d.current)_.current.set(e.el,p(e.el,C)),_.current.set(e.content,p(e.content,C))}let t=_.current;return()=>{var n;(n=g.current)==null||n.stop(),g.current=null,e==null||e();for(let e of t.values())e();t.clear()}},[S,w,b,C]),(0,c.useEffect)(()=>{y.current={offsetTop:t,constraint:a,onStickyItemsHeightChange:r};for(let e of d.current)e.invalidate();b()});let E=n===void 0?200:Math.max(Number(n)||0,20),D=(0,c.useMemo)(()=>({register:T,scheduleUpdate:b,baseZIndex:E,mode:i}),[T,b,E,i]);return c.default.createElement(l.Provider,{value:D},c.default.createElement(`div`,{...s,ref:u,className:[`oe-sticky-container`,o].filter(Boolean).join(` `)},e))}exports.StickyContainer=N,exports.StickyItem=A;
|
|
1
|
+
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("react");c=s(c,1);var l=(0,c.createContext)(null);function u(){return(0,c.useContext)(l)}var d=new Map,f=null;function p(e,t){if(typeof ResizeObserver>`u`)return()=>{};f!=null||(f=new ResizeObserver(e=>{let t=new Map;for(let r of e){var n;for(let e of(n=d.get(r.target))==null?[]:n){let n=t.get(e);n?n.push(r):t.set(e,[r])}}for(let[e,n]of t)e(n)}));let n=d.get(e);return n||(n=new Set,d.set(e,n),f.observe(e)),n.add(t),()=>{n.delete(t),n.size||(d.delete(e),f==null||f.unobserve(e)),d.size||(f==null||f.disconnect(),f=null)}}var m=new Map,h=new Map,g=null,_=!1;function v(){for(let e of m.values())e()}function y(){_||(_=!0,Promise.resolve().then(()=>{_=!1,m.size&&b()}))}function b(){let e=new Set,t=new Set;for(let n of m.keys())for(let r=n;r!=null&&r.parentElement;r=r.parentElement){let n=r.parentElement;e.add(n);for(let t=r.previousElementSibling;t&&!e.has(t);t=t.previousElementSibling)e.add(t);if(t.has(n))break;t.add(n)}let n=[...h.keys()].filter(t=>!e.has(t));n.length&&(g==null||g.disconnect());for(let e of n)h.get(e)(),h.delete(e);for(let t of e){let e=!h.has(t);e&&h.set(t,p(t,v)),(e||n.length)&&(g==null||g.observe(t,{childList:!0,attributes:!0,attributeFilter:[`class`,`style`]}))}}function x(e,t){return m.set(e,t),!g&&typeof MutationObserver<`u`&&(g=new MutationObserver(e=>{e.some(e=>e.type===`childList`)&&y(),v()})),y(),()=>{if(m.delete(e),m.size)y();else{g==null||g.disconnect(),g=null;for(let e of h.values())e();h.clear()}}}var S=new Set,C=new Set,w=new Set,T=null;function E(e){S.has(e)&&(w.add(e),T!=null||(T=requestAnimationFrame(k)))}function D(){for(let e of C)E(e)}function O(){for(let e of S)e.resize(),E(e)}function k(){T=null;let e=[...w];w.clear();let t=[],n=[],r;for(let n of e)if(S.has(n))try{let e=n.read();e&&t.push({client:n,write:e})}catch(e){var i;((i=r)==null?r=[]:i).push(e)}for(let{client:e,write:i}of t)if(S.has(e))try{let t=i();t&&n.push({client:e,notify:t})}catch(e){var a;((a=r)==null?r=[]:a).push(e)}for(let{client:e,notify:t}of n)if(S.has(e))try{t()}catch(e){var o;((o=r)==null?r=[]:o).push(e)}if(r)throw r[0]}function A(e,t){let n={read:e,resize:t};return S.size||(window.addEventListener(`scroll`,D,{passive:!0,capture:!0}),window.addEventListener(`resize`,O,{passive:!0})),S.add(n),C.add(n),E(n),{schedule:()=>E(n),setScrollEnabled:e=>{e?C.add(n):C.delete(n)},stop:()=>{S.delete(n),C.delete(n),w.delete(n),!w.size&&T!==null&&(cancelAnimationFrame(T),T=null),S.size||(window.removeEventListener(`scroll`,D,!0),window.removeEventListener(`resize`,O))}}}function j({mode:e,children:t,className:n,...r}){var i;let a=u(),o=(0,c.useRef)(null),s=(0,c.useRef)(null),l=a==null?void 0:a.register,d=e==null?a==null?void 0:a.mode:e,f=a==null?void 0:a.baseZIndex,p=(i=r.style)==null?void 0:i.height,m=(0,c.useRef)(null),h=a==null?void 0:a.scheduleUpdate;return(0,c.useEffect)(()=>{let e=o.current,t=s.current;if(!e||!t)return;let n=typeof p==`number`?`${p}px`:p==null?``:p;if(M(e,`height`,n),!l||!d||d===`none`)return;let r=p===void 0||[`auto`,`initial`,`unset`,`revert`,`revert-layer`,`fit-content`,`min-content`,`max-content`].includes(String(p)),i=!1,a=null,c,u=null,h=()=>{if(a!==null&&(a=null,e.classList.remove(`is-native-sticky`),e.style.removeProperty(`--oe-sticky-top`),e.style.removeProperty(`--oe-sticky-z`)),i){i=!1,u=null,t.classList.remove(`is-sticky`),e.style.height=n;for(let e of[`top`,`left`,`width`,`z-index`])t.style.removeProperty(e)}},g=null,_={canNative:!1,applyNative:(t,n)=>{(a!==t||c!==n)&&(h(),a=t,c=n,e.style.setProperty(`--oe-sticky-top`,`${t}px`),e.style.setProperty(`--oe-sticky-z`,String(n)),e.classList.add(`is-native-sticky`))},el:e,content:t,mode:d,apply:n=>{if(n===null){h();return}a!==null&&h();let{top:o,wrapperHeight:s,width:c,left:l,index:p}=n;u&&u.top===o&&u.wrapperHeight===s&&u.width===c&&u.left===l&&u.index===p||(u=n,r&&M(e,`height`,`${s}px`),M(t,`top`,`${o}px`),M(t,`left`,`${l}px`),M(t,`width`,`${c}px`),M(t,`zIndex`,`${(f==null?200:f)+(d===`replace`?-p:p)}`),i||(i=!0,t.classList.add(`is-sticky`)))},measure:n=>{g!=null||(g=N(e,t));let r=t.getBoundingClientRect().height;return{height:r,wrapperHeight:r+g.heightInset,width:Math.max(0,n.width-g.widthInset),left:n.left+g.leftInset}},invalidate:()=>{g=null,u=null}};m.current=_;let v=l(_);return()=>{m.current=null,v(),h()}},[l,d,f,p]),(0,c.useEffect)(()=>{if(m.current){var e;let t=r.style;m.current.canNative=p===void 0&&(t==null?void 0:t.position)===void 0&&(t==null?void 0:t.top)===void 0&&(t==null?void 0:t.bottom)===void 0&&(t==null?void 0:t.zIndex)===void 0,!m.current.canNative&&(e=o.current)!=null&&e.classList.contains(`is-native-sticky`)&&m.current.apply(null),m.current.invalidate()}h==null||h()}),c.default.createElement(`div`,{...r,className:[`oe-sticky-item`,n].filter(Boolean).join(` `),ref:o},c.default.createElement(`div`,{className:`oe-sticky-content`,ref:s},t))}function M(e,t,n){e.style[t]!==n&&(e.style[t]=n)}function N(e,t){let n=getComputedStyle(e),r=getComputedStyle(t),i=e=>Number.parseFloat(e)||0,a=e=>i(e.paddingLeft)+i(e.paddingRight)+i(e.borderLeftWidth)+i(e.borderRightWidth);return{heightInset:n.boxSizing===`border-box`?i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth):0,widthInset:a(n)+(r.boxSizing===`border-box`?0:a(r)),leftInset:i(n.paddingLeft)+i(n.borderLeftWidth)}}function P({children:e,offsetTop:t=0,offsetBottom:n=0,overflowBehavior:r=`pin`,positionStrategy:i=`fixed`,baseZIndex:a,onStickyItemsHeightChange:o,defaultMode:s=`replace`,constraint:u,className:d,...f}){let m=a===void 0?200:Math.max(Number(a)||0,20),h=(0,c.useRef)(null),g=(0,c.useRef)(new Set),_=(0,c.useRef)(null),v=(0,c.useRef)(new Map),y=(0,c.useRef)(!1),b=(0,c.useRef)(null),S=(0,c.useRef)(null),C=(0,c.useRef)(new Map),w=(0,c.useRef)(0),T=(0,c.useRef)(null),E=(0,c.useRef)({offsetTop:t,offsetBottom:n,overflowBehavior:r,positionStrategy:i,baseZIndex:m,constraint:u,onStickyItemsHeightChange:o}),D=(0,c.useCallback)(()=>{var e;return(e=S.current)==null?void 0:e.schedule()},[]),O=(0,c.useCallback)(()=>{var e,t;let n=h.current;if(!n)return;let r=E.current,i=n.getBoundingClientRect(),a=r.constraint===`none`||i.top<=r.offsetTop&&i.bottom>=r.offsetTop,o=r.positionStrategy===`auto`&&b.current!==!1&&g.current.size===1?g.current.values().next().value:void 0;if(r.positionStrategy===`auto`&&r.constraint!==`none`&&o!=null&&o.canNative&&o.el.parentElement===n&&((e=b.current)==null?b.current=F(n,o.el):e)){let e=o.content.getBoundingClientRect().height,t=o.el.getBoundingClientRect();if(t.height<=e+1&&e+r.offsetTop+Math.max(0,r.offsetBottom)<=window.innerHeight){let i=a&&t.top<=r.offsetTop?e:0;return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!!r.onStickyItemsHeightChange),T.current=null,y.current=!0,n.classList.remove(`can-sticky`),o.applyNative(r.offsetTop,r.baseZIndex),w.current!==i)return w.current=i,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,i)}}}b.current=!1}if(!a)return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!0),T.current=null,y.current){n.classList.remove(`can-sticky`);for(let e of g.current)e.apply(null);y.current=!1}if(w.current!==0)return w.current=0,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,0)}};let s=_.current;if(s)for(let e of s)e.rect=e.item.el.getBoundingClientRect();else s=_.current=[...g.current].map(e=>({item:e,rect:e.el.getBoundingClientRect()}));s.sort((e,t)=>{let n=e.rect.top-t.rect.top;return n===0?e.item.el.compareDocumentPosition(t.item.el)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1:n});let c=r.overflowBehavior===`scroll`,l=c?window.scrollY:0,u=c?T.current:null,d=0,f;if(c){if(u)d=Math.max(-u.maximum,Math.min(0,u.shift-(l-u.scrollY)));else{let e=s[0];if(e&&e.rect.top<=r.offsetTop){f=e.item.measure(e.rect);let t=f.height,n=Math.max(0,t+r.offsetTop+Math.max(0,r.offsetBottom)-window.innerHeight);d=Math.max(-n,Math.min(0,e.rect.top-r.offsetTop))}}}let p=c&&s.every(({item:e})=>e.mode===`replace`),m=r.offsetTop+d,v=0,x=s.map(({item:e,rect:t},n)=>{var r;let i=m-(p?d:0);if(t.top>i)return null;let a=(r=s[n+1])==null?void 0:r.rect.top;if(e.mode===`replace`&&a!==void 0&&a<i)return null;let o=n===0&&f?f:e.measure(t),c=e.mode===`replace`&&a!==void 0?Math.min(m,a-o.height):m;return v+=o.height,e.mode===`stack`&&(m+=o.height),{...o,top:c,index:n}}),C=null;if(c&&v>0){let e=Math.max(0,v+r.offsetTop+Math.max(0,r.offsetBottom)-window.innerHeight),t=Math.max(-e,d);for(let e of x)e&&(e.top+=t-d);C={scrollY:l,shift:t,maximum:e}}let D=r.constraint===`none`?0:Math.min(0,i.bottom-r.offsetTop-v-((t=C==null?void 0:C.shift)==null?0:t));return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!0),T.current=C,y.current=x.some(e=>e!==null),n.classList.toggle(`can-sticky`,y.current),s.forEach(({item:e},t)=>{let n=x[t];n&&(n.top+=D),e.apply(n)}),w.current!==v)return w.current=v,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,v)}}},[]),k=(0,c.useCallback)(e=>{var t;b.current=null;for(let n of e)(t=v.current.get(n.target))==null||t.invalidate();D()},[D]),j=(0,c.useCallback)(()=>{b.current=null;for(let e of g.current)e.invalidate()},[]),M=(0,c.useCallback)(e=>(g.current.add(e),b.current=null,_.current=null,v.current.set(e.el,e),v.current.set(e.content,e),S.current&&(C.current.set(e.el,p(e.el,k)),C.current.set(e.content,p(e.content,k))),D(),()=>{var t,n;(t=C.current.get(e.el))==null||t(),(n=C.current.get(e.content))==null||n(),C.current.delete(e.el),C.current.delete(e.content),v.current.delete(e.el),v.current.delete(e.content),g.current.delete(e),b.current=null,_.current=null,D()}),[D,k]);(0,c.useEffect)(()=>{S.current=A(O,j);let e;if(typeof ResizeObserver<`u`){h.current&&(C.current.set(h.current,p(h.current,k)),e=x(h.current,()=>{j(),D()}));for(let e of g.current)C.current.set(e.el,p(e.el,k)),C.current.set(e.content,p(e.content,k))}let t=C.current;return()=>{var n;(n=S.current)==null||n.stop(),S.current=null,e==null||e();for(let e of t.values())e();t.clear()}},[O,j,D,k]),(0,c.useEffect)(()=>{b.current=null,E.current={offsetTop:t,offsetBottom:n,overflowBehavior:r,positionStrategy:i,baseZIndex:m,constraint:u,onStickyItemsHeightChange:o};for(let e of g.current)e.invalidate();D()});let N=(0,c.useMemo)(()=>({register:M,scheduleUpdate:D,baseZIndex:m,mode:s}),[M,D,m,s]);return c.default.createElement(l.Provider,{value:N},c.default.createElement(`div`,{...f,ref:h,className:[`oe-sticky-container`,d].filter(Boolean).join(` `)},e))}function F(e,t){if(typeof ResizeObserver>`u`||typeof CSS>`u`||typeof CSS.supports!=`function`||!CSS.supports(`position`,`sticky`))return!1;for(let n=e;n;n=n.parentElement){let r=getComputedStyle(n);if(n===e&&(r.display.includes(`grid`)||r.display.includes(`flex`)&&!r.flexDirection.startsWith(`column`))&&/^(normal|stretch)$/.test(r.alignItems)&&/^(auto|normal|stretch)$/.test(getComputedStyle(t).alignSelf)||/(auto|scroll|hidden|overlay)/.test(`${r.overflowX} ${r.overflowY}`))return!1}return!0}exports.StickyContainer=P,exports.StickyItem=j;
|
package/dist/react-sticky.es.js
CHANGED
|
@@ -72,21 +72,21 @@ function y(e, t) {
|
|
|
72
72
|
}
|
|
73
73
|
//#endregion
|
|
74
74
|
//#region src/scheduler.ts
|
|
75
|
-
var b = /* @__PURE__ */ new Set(), x = /* @__PURE__ */ new Set(), S = null;
|
|
76
|
-
function
|
|
77
|
-
b.has(e) && (
|
|
78
|
-
}
|
|
79
|
-
function w() {
|
|
80
|
-
for (let e of b) C(e);
|
|
75
|
+
var b = /* @__PURE__ */ new Set(), x = /* @__PURE__ */ new Set(), S = /* @__PURE__ */ new Set(), C = null;
|
|
76
|
+
function w(e) {
|
|
77
|
+
b.has(e) && (S.add(e), C != null || (C = requestAnimationFrame(D)));
|
|
81
78
|
}
|
|
82
79
|
function T() {
|
|
83
|
-
for (let e of
|
|
80
|
+
for (let e of x) w(e);
|
|
84
81
|
}
|
|
85
82
|
function E() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
for (let e of b) e.resize(), w(e);
|
|
84
|
+
}
|
|
85
|
+
function D() {
|
|
86
|
+
C = null;
|
|
87
|
+
let e = [...S];
|
|
88
|
+
S.clear();
|
|
89
|
+
let t = [], n = [], r;
|
|
90
90
|
for (let n of e) if (b.has(n)) try {
|
|
91
91
|
let e = n.read();
|
|
92
92
|
e && t.push({
|
|
@@ -94,7 +94,8 @@ function E() {
|
|
|
94
94
|
write: e
|
|
95
95
|
});
|
|
96
96
|
} catch (e) {
|
|
97
|
-
|
|
97
|
+
var i;
|
|
98
|
+
((i = r) == null ? r = [] : i).push(e);
|
|
98
99
|
}
|
|
99
100
|
for (let { client: e, write: i } of t) if (b.has(e)) try {
|
|
100
101
|
let t = i();
|
|
@@ -103,40 +104,45 @@ function E() {
|
|
|
103
104
|
notify: t
|
|
104
105
|
});
|
|
105
106
|
} catch (e) {
|
|
106
|
-
|
|
107
|
+
var a;
|
|
108
|
+
((a = r) == null ? r = [] : a).push(e);
|
|
107
109
|
}
|
|
108
110
|
for (let { client: e, notify: t } of n) if (b.has(e)) try {
|
|
109
111
|
t();
|
|
110
112
|
} catch (e) {
|
|
111
|
-
|
|
113
|
+
var o;
|
|
114
|
+
((o = r) == null ? r = [] : o).push(e);
|
|
112
115
|
}
|
|
113
|
-
if (r
|
|
116
|
+
if (r) throw r[0];
|
|
114
117
|
}
|
|
115
|
-
function
|
|
118
|
+
function O(e, t) {
|
|
116
119
|
let n = {
|
|
117
120
|
read: e,
|
|
118
121
|
resize: t
|
|
119
122
|
};
|
|
120
|
-
return b.size || (window.addEventListener("scroll",
|
|
123
|
+
return b.size || (window.addEventListener("scroll", T, {
|
|
121
124
|
passive: !0,
|
|
122
125
|
capture: !0
|
|
123
|
-
}), window.addEventListener("resize",
|
|
124
|
-
schedule: () =>
|
|
126
|
+
}), window.addEventListener("resize", E, { passive: !0 })), b.add(n), x.add(n), w(n), {
|
|
127
|
+
schedule: () => w(n),
|
|
128
|
+
setScrollEnabled: (e) => {
|
|
129
|
+
e ? x.add(n) : x.delete(n);
|
|
130
|
+
},
|
|
125
131
|
stop: () => {
|
|
126
|
-
b.delete(n), x.delete(n), !
|
|
132
|
+
b.delete(n), x.delete(n), S.delete(n), !S.size && C !== null && (cancelAnimationFrame(C), C = null), b.size || (window.removeEventListener("scroll", T, !0), window.removeEventListener("resize", E));
|
|
127
133
|
}
|
|
128
134
|
};
|
|
129
135
|
}
|
|
130
136
|
//#endregion
|
|
131
137
|
//#region src/sticky-item.tsx
|
|
132
|
-
function
|
|
138
|
+
function k({ mode: t, children: n, className: r, ...a }) {
|
|
133
139
|
var s;
|
|
134
140
|
let l = c(), u = o(null), d = o(null), f = l == null ? void 0 : l.register, p = t == null ? l == null ? void 0 : l.mode : t, m = l == null ? void 0 : l.baseZIndex, h = (s = a.style) == null ? void 0 : s.height, g = o(null), _ = l == null ? void 0 : l.scheduleUpdate;
|
|
135
141
|
return i(() => {
|
|
136
142
|
let e = u.current, t = d.current;
|
|
137
143
|
if (!e || !t) return;
|
|
138
144
|
let n = typeof h == "number" ? `${h}px` : h == null ? "" : h;
|
|
139
|
-
if (
|
|
145
|
+
if (A(e, "height", n), !f || !p || p === "none") return;
|
|
140
146
|
let r = h === void 0 || [
|
|
141
147
|
"auto",
|
|
142
148
|
"initial",
|
|
@@ -146,9 +152,9 @@ function O({ mode: t, children: n, className: r, ...a }) {
|
|
|
146
152
|
"fit-content",
|
|
147
153
|
"min-content",
|
|
148
154
|
"max-content"
|
|
149
|
-
].includes(String(h)), i = !1, a = null, o = () => {
|
|
150
|
-
if (i) {
|
|
151
|
-
i = !1,
|
|
155
|
+
].includes(String(h)), i = !1, a = null, o, s = null, c = () => {
|
|
156
|
+
if (a !== null && (a = null, e.classList.remove("is-native-sticky"), e.style.removeProperty("--oe-sticky-top"), e.style.removeProperty("--oe-sticky-z")), i) {
|
|
157
|
+
i = !1, s = null, t.classList.remove("is-sticky"), e.style.height = n;
|
|
152
158
|
for (let e of [
|
|
153
159
|
"top",
|
|
154
160
|
"left",
|
|
@@ -156,36 +162,41 @@ function O({ mode: t, children: n, className: r, ...a }) {
|
|
|
156
162
|
"z-index"
|
|
157
163
|
]) t.style.removeProperty(e);
|
|
158
164
|
}
|
|
159
|
-
},
|
|
165
|
+
}, l = null, _ = {
|
|
166
|
+
canNative: !1,
|
|
167
|
+
applyNative: (t, n) => {
|
|
168
|
+
(a !== t || o !== n) && (c(), a = t, o = n, e.style.setProperty("--oe-sticky-top", `${t}px`), e.style.setProperty("--oe-sticky-z", String(n)), e.classList.add("is-native-sticky"));
|
|
169
|
+
},
|
|
160
170
|
el: e,
|
|
161
171
|
content: t,
|
|
162
172
|
mode: p,
|
|
163
173
|
apply: (n) => {
|
|
164
174
|
if (n === null) {
|
|
165
|
-
|
|
175
|
+
c();
|
|
166
176
|
return;
|
|
167
177
|
}
|
|
168
|
-
|
|
169
|
-
|
|
178
|
+
a !== null && c();
|
|
179
|
+
let { top: o, wrapperHeight: l, width: u, left: d, index: f } = n;
|
|
180
|
+
s && s.top === o && s.wrapperHeight === l && s.width === u && s.left === d && s.index === f || (s = n, r && A(e, "height", `${l}px`), A(t, "top", `${o}px`), A(t, "left", `${d}px`), A(t, "width", `${u}px`), A(t, "zIndex", `${(m == null ? 200 : m) + (p === "replace" ? -f : f)}`), i || (i = !0, t.classList.add("is-sticky")));
|
|
170
181
|
},
|
|
171
182
|
measure: (n) => {
|
|
172
|
-
|
|
183
|
+
l != null || (l = j(e, t));
|
|
173
184
|
let r = t.getBoundingClientRect().height;
|
|
174
185
|
return {
|
|
175
186
|
height: r,
|
|
176
|
-
wrapperHeight: r +
|
|
177
|
-
width: Math.max(0, n.width -
|
|
178
|
-
left: n.left +
|
|
187
|
+
wrapperHeight: r + l.heightInset,
|
|
188
|
+
width: Math.max(0, n.width - l.widthInset),
|
|
189
|
+
left: n.left + l.leftInset
|
|
179
190
|
};
|
|
180
191
|
},
|
|
181
192
|
invalidate: () => {
|
|
182
|
-
|
|
193
|
+
l = null, s = null;
|
|
183
194
|
}
|
|
184
195
|
};
|
|
185
|
-
g.current =
|
|
186
|
-
let
|
|
196
|
+
g.current = _;
|
|
197
|
+
let v = f(_);
|
|
187
198
|
return () => {
|
|
188
|
-
g.current = null,
|
|
199
|
+
g.current = null, v(), c();
|
|
189
200
|
};
|
|
190
201
|
}, [
|
|
191
202
|
f,
|
|
@@ -193,8 +204,12 @@ function O({ mode: t, children: n, className: r, ...a }) {
|
|
|
193
204
|
m,
|
|
194
205
|
h
|
|
195
206
|
]), i(() => {
|
|
196
|
-
|
|
197
|
-
|
|
207
|
+
if (g.current) {
|
|
208
|
+
var e;
|
|
209
|
+
let t = a.style;
|
|
210
|
+
g.current.canNative = h === void 0 && (t == null ? void 0 : t.position) === void 0 && (t == null ? void 0 : t.top) === void 0 && (t == null ? void 0 : t.bottom) === void 0 && (t == null ? void 0 : t.zIndex) === void 0, !g.current.canNative && (e = u.current) != null && e.classList.contains("is-native-sticky") && g.current.apply(null), g.current.invalidate();
|
|
211
|
+
}
|
|
212
|
+
_ == null || _();
|
|
198
213
|
}), /* @__PURE__ */ e.createElement("div", {
|
|
199
214
|
...a,
|
|
200
215
|
className: ["oe-sticky-item", r].filter(Boolean).join(" "),
|
|
@@ -204,10 +219,10 @@ function O({ mode: t, children: n, className: r, ...a }) {
|
|
|
204
219
|
ref: d
|
|
205
220
|
}, n));
|
|
206
221
|
}
|
|
207
|
-
function
|
|
222
|
+
function A(e, t, n) {
|
|
208
223
|
e.style[t] !== n && (e.style[t] = n);
|
|
209
224
|
}
|
|
210
|
-
function
|
|
225
|
+
function j(e, t) {
|
|
211
226
|
let n = getComputedStyle(e), r = getComputedStyle(t), i = (e) => Number.parseFloat(e) || 0, a = (e) => i(e.paddingLeft) + i(e.paddingRight) + i(e.borderLeftWidth) + i(e.borderRightWidth);
|
|
212
227
|
return {
|
|
213
228
|
heightInset: n.boxSizing === "border-box" ? i(n.paddingTop) + i(n.paddingBottom) + i(n.borderTopWidth) + i(n.borderBottomWidth) : 0,
|
|
@@ -217,113 +232,174 @@ function A(e, t) {
|
|
|
217
232
|
}
|
|
218
233
|
//#endregion
|
|
219
234
|
//#region src/index.tsx
|
|
220
|
-
function
|
|
221
|
-
let
|
|
235
|
+
function M({ children: t, offsetTop: r = 0, offsetBottom: c = 0, overflowBehavior: l = "pin", positionStrategy: u = "fixed", baseZIndex: f, onStickyItemsHeightChange: p, defaultMode: m = "replace", constraint: h, className: g, ..._ }) {
|
|
236
|
+
let v = f === void 0 ? 200 : Math.max(Number(f) || 0, 20), b = o(null), x = o(/* @__PURE__ */ new Set()), S = o(null), C = o(/* @__PURE__ */ new Map()), w = o(!1), T = o(null), E = o(null), D = o(/* @__PURE__ */ new Map()), k = o(0), A = o(null), j = o({
|
|
222
237
|
offsetTop: r,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
238
|
+
offsetBottom: c,
|
|
239
|
+
overflowBehavior: l,
|
|
240
|
+
positionStrategy: u,
|
|
241
|
+
baseZIndex: v,
|
|
242
|
+
constraint: h,
|
|
243
|
+
onStickyItemsHeightChange: p
|
|
244
|
+
}), M = n(() => {
|
|
226
245
|
var e;
|
|
227
|
-
return (e =
|
|
228
|
-
}, []),
|
|
229
|
-
var e;
|
|
230
|
-
let
|
|
231
|
-
if (!
|
|
232
|
-
let
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
246
|
+
return (e = E.current) == null ? void 0 : e.schedule();
|
|
247
|
+
}, []), P = n(() => {
|
|
248
|
+
var e, t;
|
|
249
|
+
let n = b.current;
|
|
250
|
+
if (!n) return;
|
|
251
|
+
let r = j.current, i = n.getBoundingClientRect(), a = r.constraint === "none" || i.top <= r.offsetTop && i.bottom >= r.offsetTop, o = r.positionStrategy === "auto" && T.current !== !1 && x.current.size === 1 ? x.current.values().next().value : void 0;
|
|
252
|
+
if (r.positionStrategy === "auto" && r.constraint !== "none" && o != null && o.canNative && o.el.parentElement === n && ((e = T.current) == null ? T.current = N(n, o.el) : e)) {
|
|
253
|
+
let e = o.content.getBoundingClientRect().height, t = o.el.getBoundingClientRect();
|
|
254
|
+
if (t.height <= e + 1 && e + r.offsetTop + Math.max(0, r.offsetBottom) <= window.innerHeight) {
|
|
255
|
+
let i = a && t.top <= r.offsetTop ? e : 0;
|
|
256
|
+
return () => {
|
|
257
|
+
var e;
|
|
258
|
+
if ((e = E.current) == null || e.setScrollEnabled(!!r.onStickyItemsHeightChange), A.current = null, w.current = !0, n.classList.remove("can-sticky"), o.applyNative(r.offsetTop, r.baseZIndex), k.current !== i) return k.current = i, () => {
|
|
259
|
+
var e;
|
|
260
|
+
return (e = r.onStickyItemsHeightChange) == null ? void 0 : e.call(r, i);
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
T.current = !1;
|
|
265
|
+
}
|
|
266
|
+
if (!a) return () => {
|
|
267
|
+
var e;
|
|
268
|
+
if ((e = E.current) == null || e.setScrollEnabled(!0), A.current = null, w.current) {
|
|
269
|
+
n.classList.remove("can-sticky");
|
|
270
|
+
for (let e of x.current) e.apply(null);
|
|
271
|
+
w.current = !1;
|
|
238
272
|
}
|
|
239
|
-
if (
|
|
273
|
+
if (k.current !== 0) return k.current = 0, () => {
|
|
240
274
|
var e;
|
|
241
|
-
return (e =
|
|
275
|
+
return (e = r.onStickyItemsHeightChange) == null ? void 0 : e.call(r, 0);
|
|
242
276
|
};
|
|
243
277
|
};
|
|
244
|
-
let
|
|
278
|
+
let s = S.current;
|
|
279
|
+
if (s) for (let e of s) e.rect = e.item.el.getBoundingClientRect();
|
|
280
|
+
else s = S.current = [...x.current].map((e) => ({
|
|
245
281
|
item: e,
|
|
246
282
|
rect: e.el.getBoundingClientRect()
|
|
247
|
-
}))
|
|
283
|
+
}));
|
|
284
|
+
s.sort((e, t) => {
|
|
248
285
|
let n = e.rect.top - t.rect.top;
|
|
249
286
|
return n === 0 ? e.item.el.compareDocumentPosition(t.item.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1 : n;
|
|
250
|
-
})
|
|
287
|
+
});
|
|
288
|
+
let c = r.overflowBehavior === "scroll", l = c ? window.scrollY : 0, u = c ? A.current : null, d = 0, f;
|
|
289
|
+
if (c) {
|
|
290
|
+
if (u) d = Math.max(-u.maximum, Math.min(0, u.shift - (l - u.scrollY)));
|
|
291
|
+
else {
|
|
292
|
+
let e = s[0];
|
|
293
|
+
if (e && e.rect.top <= r.offsetTop) {
|
|
294
|
+
f = e.item.measure(e.rect);
|
|
295
|
+
let t = f.height, n = Math.max(0, t + r.offsetTop + Math.max(0, r.offsetBottom) - window.innerHeight);
|
|
296
|
+
d = Math.max(-n, Math.min(0, e.rect.top - r.offsetTop));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
let p = c && s.every(({ item: e }) => e.mode === "replace"), m = r.offsetTop + d, h = 0, g = s.map(({ item: e, rect: t }, n) => {
|
|
251
301
|
var r;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
302
|
+
let i = m - (p ? d : 0);
|
|
303
|
+
if (t.top > i) return null;
|
|
304
|
+
let a = (r = s[n + 1]) == null ? void 0 : r.rect.top;
|
|
305
|
+
if (e.mode === "replace" && a !== void 0 && a < i) return null;
|
|
306
|
+
let o = n === 0 && f ? f : e.measure(t), c = e.mode === "replace" && a !== void 0 ? Math.min(m, a - o.height) : m;
|
|
307
|
+
return h += o.height, e.mode === "stack" && (m += o.height), {
|
|
308
|
+
...o,
|
|
309
|
+
top: c,
|
|
259
310
|
index: n
|
|
260
311
|
};
|
|
261
|
-
}),
|
|
312
|
+
}), _ = null;
|
|
313
|
+
if (c && h > 0) {
|
|
314
|
+
let e = Math.max(0, h + r.offsetTop + Math.max(0, r.offsetBottom) - window.innerHeight), t = Math.max(-e, d);
|
|
315
|
+
for (let e of g) e && (e.top += t - d);
|
|
316
|
+
_ = {
|
|
317
|
+
scrollY: l,
|
|
318
|
+
shift: t,
|
|
319
|
+
maximum: e
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
let v = r.constraint === "none" ? 0 : Math.min(0, i.bottom - r.offsetTop - h - ((t = _ == null ? void 0 : _.shift) == null ? 0 : t));
|
|
262
323
|
return () => {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
324
|
+
var e;
|
|
325
|
+
if ((e = E.current) == null || e.setScrollEnabled(!0), A.current = _, w.current = g.some((e) => e !== null), n.classList.toggle("can-sticky", w.current), s.forEach(({ item: e }, t) => {
|
|
326
|
+
let n = g[t];
|
|
327
|
+
n && (n.top += v), e.apply(n);
|
|
328
|
+
}), k.current !== h) return k.current = h, () => {
|
|
267
329
|
var e;
|
|
268
|
-
return (e =
|
|
330
|
+
return (e = r.onStickyItemsHeightChange) == null ? void 0 : e.call(r, h);
|
|
269
331
|
};
|
|
270
332
|
};
|
|
271
|
-
}, []),
|
|
333
|
+
}, []), F = n((e) => {
|
|
272
334
|
var t;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
335
|
+
T.current = null;
|
|
336
|
+
for (let n of e) (t = C.current.get(n.target)) == null || t.invalidate();
|
|
337
|
+
M();
|
|
338
|
+
}, [M]), I = n(() => {
|
|
339
|
+
T.current = null;
|
|
340
|
+
for (let e of x.current) e.invalidate();
|
|
341
|
+
}, []), L = n((e) => (x.current.add(e), T.current = null, S.current = null, C.current.set(e.el, e), C.current.set(e.content, e), E.current && (D.current.set(e.el, d(e.el, F)), D.current.set(e.content, d(e.content, F))), M(), () => {
|
|
278
342
|
var t, n;
|
|
279
|
-
(t =
|
|
280
|
-
}), [
|
|
343
|
+
(t = D.current.get(e.el)) == null || t(), (n = D.current.get(e.content)) == null || n(), D.current.delete(e.el), D.current.delete(e.content), C.current.delete(e.el), C.current.delete(e.content), x.current.delete(e), T.current = null, S.current = null, M();
|
|
344
|
+
}), [M, F]);
|
|
281
345
|
i(() => {
|
|
282
|
-
|
|
346
|
+
E.current = O(P, I);
|
|
283
347
|
let e;
|
|
284
348
|
if (typeof ResizeObserver < "u") {
|
|
285
|
-
|
|
286
|
-
|
|
349
|
+
b.current && (D.current.set(b.current, d(b.current, F)), e = y(b.current, () => {
|
|
350
|
+
I(), M();
|
|
287
351
|
}));
|
|
288
|
-
for (let e of
|
|
352
|
+
for (let e of x.current) D.current.set(e.el, d(e.el, F)), D.current.set(e.content, d(e.content, F));
|
|
289
353
|
}
|
|
290
|
-
let t =
|
|
354
|
+
let t = D.current;
|
|
291
355
|
return () => {
|
|
292
356
|
var n;
|
|
293
|
-
(n =
|
|
357
|
+
(n = E.current) == null || n.stop(), E.current = null, e == null || e();
|
|
294
358
|
for (let e of t.values()) e();
|
|
295
359
|
t.clear();
|
|
296
360
|
};
|
|
297
361
|
}, [
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
362
|
+
P,
|
|
363
|
+
I,
|
|
364
|
+
M,
|
|
365
|
+
F
|
|
302
366
|
]), i(() => {
|
|
303
|
-
|
|
367
|
+
T.current = null, j.current = {
|
|
304
368
|
offsetTop: r,
|
|
305
|
-
|
|
306
|
-
|
|
369
|
+
offsetBottom: c,
|
|
370
|
+
overflowBehavior: l,
|
|
371
|
+
positionStrategy: u,
|
|
372
|
+
baseZIndex: v,
|
|
373
|
+
constraint: h,
|
|
374
|
+
onStickyItemsHeightChange: p
|
|
307
375
|
};
|
|
308
|
-
for (let e of
|
|
309
|
-
|
|
376
|
+
for (let e of x.current) e.invalidate();
|
|
377
|
+
M();
|
|
310
378
|
});
|
|
311
|
-
let
|
|
312
|
-
register:
|
|
313
|
-
scheduleUpdate:
|
|
314
|
-
baseZIndex:
|
|
315
|
-
mode:
|
|
379
|
+
let R = a(() => ({
|
|
380
|
+
register: L,
|
|
381
|
+
scheduleUpdate: M,
|
|
382
|
+
baseZIndex: v,
|
|
383
|
+
mode: m
|
|
316
384
|
}), [
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
385
|
+
L,
|
|
386
|
+
M,
|
|
387
|
+
v,
|
|
388
|
+
m
|
|
321
389
|
]);
|
|
322
|
-
return /* @__PURE__ */ e.createElement(s.Provider, { value:
|
|
323
|
-
...
|
|
324
|
-
ref:
|
|
325
|
-
className: ["oe-sticky-container",
|
|
390
|
+
return /* @__PURE__ */ e.createElement(s.Provider, { value: R }, /* @__PURE__ */ e.createElement("div", {
|
|
391
|
+
..._,
|
|
392
|
+
ref: b,
|
|
393
|
+
className: ["oe-sticky-container", g].filter(Boolean).join(" ")
|
|
326
394
|
}, t));
|
|
327
395
|
}
|
|
396
|
+
function N(e, t) {
|
|
397
|
+
if (typeof ResizeObserver > "u" || typeof CSS > "u" || typeof CSS.supports != "function" || !CSS.supports("position", "sticky")) return !1;
|
|
398
|
+
for (let n = e; n; n = n.parentElement) {
|
|
399
|
+
let r = getComputedStyle(n);
|
|
400
|
+
if (n === e && (r.display.includes("grid") || r.display.includes("flex") && !r.flexDirection.startsWith("column")) && /^(normal|stretch)$/.test(r.alignItems) && /^(auto|normal|stretch)$/.test(getComputedStyle(t).alignSelf) || /(auto|scroll|hidden|overlay)/.test(`${r.overflowX} ${r.overflowY}`)) return !1;
|
|
401
|
+
}
|
|
402
|
+
return !0;
|
|
403
|
+
}
|
|
328
404
|
//#endregion
|
|
329
|
-
export {
|
|
405
|
+
export { M as StickyContainer, k as StickyItem };
|
package/dist/react-sticky.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactSticky={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule||!s.call(e,`default`)?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);var l=(0,t.createContext)(null);function u(){return(0,t.useContext)(l)}var d=new Map,f=null;function p(e,t){if(typeof ResizeObserver>`u`)return()=>{};f!=null||(f=new ResizeObserver(e=>{let t=new Map;for(let r of e){var n;for(let e of(n=d.get(r.target))==null?[]:n){let n=t.get(e);n?n.push(r):t.set(e,[r])}}for(let[e,n]of t)e(n)}));let n=d.get(e);return n||(n=new Set,d.set(e,n),f.observe(e)),n.add(t),()=>{n.delete(t),n.size||(d.delete(e),f==null||f.unobserve(e)),d.size||(f==null||f.disconnect(),f=null)}}var m=new Map,h=new Map,g=null,_=!1;function v(){for(let e of m.values())e()}function y(){_||(_=!0,Promise.resolve().then(()=>{_=!1,m.size&&b()}))}function b(){let e=new Set,t=new Set;for(let n of m.keys())for(let r=n;r!=null&&r.parentElement;r=r.parentElement){let n=r.parentElement;e.add(n);for(let t=r.previousElementSibling;t&&!e.has(t);t=t.previousElementSibling)e.add(t);if(t.has(n))break;t.add(n)}let n=[...h.keys()].filter(t=>!e.has(t));n.length&&(g==null||g.disconnect());for(let e of n)h.get(e)(),h.delete(e);for(let t of e){let e=!h.has(t);e&&h.set(t,p(t,v)),(e||n.length)&&(g==null||g.observe(t,{childList:!0,attributes:!0,attributeFilter:[`class`,`style`]}))}}function x(e,t){return m.set(e,t),!g&&typeof MutationObserver<`u`&&(g=new MutationObserver(e=>{e.some(e=>e.type===`childList`)&&y(),v()})),y(),()=>{if(m.delete(e),m.size)y();else{g==null||g.disconnect(),g=null;for(let e of h.values())e();h.clear()}}}var S=new Set,C=new Set,w=null;function T(e){S.has(e)&&(C.add(e),w!=null||(w=requestAnimationFrame(O)))}function E(){for(let e of S)T(e)}function D(){for(let e of S)e.resize(),T(e)}function O(){w=null;let e=[...C];C.clear();let t=[],n=[],r=[];for(let n of e)if(S.has(n))try{let e=n.read();e&&t.push({client:n,write:e})}catch(e){r.push(e)}for(let{client:e,write:i}of t)if(S.has(e))try{let t=i();t&&n.push({client:e,notify:t})}catch(e){r.push(e)}for(let{client:e,notify:t}of n)if(S.has(e))try{t()}catch(e){r.push(e)}if(r.length)throw r[0]}function k(e,t){let n={read:e,resize:t};return S.size||(window.addEventListener(`scroll`,E,{passive:!0,capture:!0}),window.addEventListener(`resize`,D,{passive:!0})),S.add(n),T(n),{schedule:()=>T(n),stop:()=>{S.delete(n),C.delete(n),!C.size&&w!==null&&(cancelAnimationFrame(w),w=null),S.size||(window.removeEventListener(`scroll`,E,!0),window.removeEventListener(`resize`,D))}}}function A({mode:e,children:n,className:r,...i}){var a;let o=u(),s=(0,t.useRef)(null),c=(0,t.useRef)(null),l=o==null?void 0:o.register,d=e==null?o==null?void 0:o.mode:e,f=o==null?void 0:o.baseZIndex,p=(a=i.style)==null?void 0:a.height,m=(0,t.useRef)(null),h=o==null?void 0:o.scheduleUpdate;return(0,t.useEffect)(()=>{let e=s.current,t=c.current;if(!e||!t)return;let n=typeof p==`number`?`${p}px`:p==null?``:p;if(j(e,`height`,n),!l||!d||d===`none`)return;let r=p===void 0||[`auto`,`initial`,`unset`,`revert`,`revert-layer`,`fit-content`,`min-content`,`max-content`].includes(String(p)),i=!1,a=null,o=()=>{if(i){i=!1,a=null,t.classList.remove(`is-sticky`),e.style.height=n;for(let e of[`top`,`left`,`width`,`z-index`])t.style.removeProperty(e)}},u=null,h={el:e,content:t,mode:d,apply:n=>{if(n===null){o();return}let{top:s,wrapperHeight:c,width:l,left:u,index:p}=n;a&&a.top===s&&a.wrapperHeight===c&&a.width===l&&a.left===u&&a.index===p||(a=n,r&&j(e,`height`,`${c}px`),j(t,`top`,`${s}px`),j(t,`left`,`${u}px`),j(t,`width`,`${l}px`),j(t,`zIndex`,`${(f==null?200:f)+(d===`replace`?-p:p)}`),i||(i=!0,t.classList.add(`is-sticky`)))},measure:n=>{u!=null||(u=M(e,t));let r=t.getBoundingClientRect().height;return{height:r,wrapperHeight:r+u.heightInset,width:Math.max(0,n.width-u.widthInset),left:n.left+u.leftInset}},invalidate:()=>{u=null,a=null}};m.current=h;let g=l(h);return()=>{m.current=null,g(),o()}},[l,d,f,p]),(0,t.useEffect)(()=>{var e;(e=m.current)==null||e.invalidate(),h==null||h()}),t.default.createElement(`div`,{...i,className:[`oe-sticky-item`,r].filter(Boolean).join(` `),ref:s},t.default.createElement(`div`,{className:`oe-sticky-content`,ref:c},n))}function j(e,t,n){e.style[t]!==n&&(e.style[t]=n)}function M(e,t){let n=getComputedStyle(e),r=getComputedStyle(t),i=e=>Number.parseFloat(e)||0,a=e=>i(e.paddingLeft)+i(e.paddingRight)+i(e.borderLeftWidth)+i(e.borderRightWidth);return{heightInset:n.boxSizing===`border-box`?i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth):0,widthInset:a(n)+(r.boxSizing===`border-box`?0:a(r)),leftInset:i(n.paddingLeft)+i(n.borderLeftWidth)}}function N({children:e,offsetTop:n=0,baseZIndex:r,onStickyItemsHeightChange:i,defaultMode:a=`replace`,constraint:o,className:s,...c}){let u=(0,t.useRef)(null),d=(0,t.useRef)(new Set),f=(0,t.useRef)(null),m=(0,t.useRef)(new Map),h=(0,t.useRef)(!1),g=(0,t.useRef)(null),_=(0,t.useRef)(new Map),v=(0,t.useRef)(0),y=(0,t.useRef)({offsetTop:n,constraint:o,onStickyItemsHeightChange:i}),b=(0,t.useCallback)(()=>{var e;return(e=g.current)==null?void 0:e.schedule()},[]),S=(0,t.useCallback)(()=>{var e;let t=u.current;if(!t)return;let n=y.current,r=t.getBoundingClientRect();if(!(n.constraint===`none`||r.top<=n.offsetTop&&r.bottom>=n.offsetTop))return()=>{if(h.current){t.classList.remove(`can-sticky`);for(let e of d.current)e.apply(null);h.current=!1}if(v.current!==0)return v.current=0,()=>{var e;return(e=n.onStickyItemsHeightChange)==null?void 0:e.call(n,0)}};let i=((e=f.current)==null?f.current=[...d.current]:e).map(e=>({item:e,rect:e.el.getBoundingClientRect()})).sort((e,t)=>{let n=e.rect.top-t.rect.top;return n===0?e.item.el.compareDocumentPosition(t.item.el)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1:n}),a=n.offsetTop,o=0,s=i.map(({item:e,rect:t},n)=>{var r;if(t.top>a)return null;let s=(r=i[n+1])==null?void 0:r.rect.top;if(e.mode===`replace`&&s!==void 0&&s<a)return null;let c=e.measure(t),l=e.mode===`replace`&&s!==void 0?Math.min(a,s-c.height):a;return o+=c.height,e.mode===`stack`&&(a+=c.height),{...c,top:l,index:n}}),c=n.constraint===`none`?0:Math.min(0,r.bottom-n.offsetTop-o);return()=>{if(h.current=s.some(e=>e!==null),t.classList.toggle(`can-sticky`,h.current),i.forEach(({item:e},t)=>{let n=s[t];n&&(n.top+=c),e.apply(n)}),v.current!==o)return v.current=o,()=>{var e;return(e=n.onStickyItemsHeightChange)==null?void 0:e.call(n,o)}}},[]),C=(0,t.useCallback)(e=>{var t;for(let n of e)(t=m.current.get(n.target))==null||t.invalidate();b()},[b]),w=(0,t.useCallback)(()=>{for(let e of d.current)e.invalidate()},[]),T=(0,t.useCallback)(e=>(d.current.add(e),f.current=null,m.current.set(e.el,e),m.current.set(e.content,e),g.current&&(_.current.set(e.el,p(e.el,C)),_.current.set(e.content,p(e.content,C))),b(),()=>{var t,n;(t=_.current.get(e.el))==null||t(),(n=_.current.get(e.content))==null||n(),_.current.delete(e.el),_.current.delete(e.content),m.current.delete(e.el),m.current.delete(e.content),d.current.delete(e),f.current=null,b()}),[b,C]);(0,t.useEffect)(()=>{g.current=k(S,w);let e;if(typeof ResizeObserver<`u`){u.current&&(_.current.set(u.current,p(u.current,C)),e=x(u.current,()=>{w(),b()}));for(let e of d.current)_.current.set(e.el,p(e.el,C)),_.current.set(e.content,p(e.content,C))}let t=_.current;return()=>{var n;(n=g.current)==null||n.stop(),g.current=null,e==null||e();for(let e of t.values())e();t.clear()}},[S,w,b,C]),(0,t.useEffect)(()=>{y.current={offsetTop:n,constraint:o,onStickyItemsHeightChange:i};for(let e of d.current)e.invalidate();b()});let E=r===void 0?200:Math.max(Number(r)||0,20),D=(0,t.useMemo)(()=>({register:T,scheduleUpdate:b,baseZIndex:E,mode:a}),[T,b,E,a]);return t.default.createElement(l.Provider,{value:D},t.default.createElement(`div`,{...c,ref:u,className:[`oe-sticky-container`,s].filter(Boolean).join(` `)},e))}e.StickyContainer=N,e.StickyItem=A});
|
|
1
|
+
"use client";(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactSticky={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule||!s.call(e,`default`)?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);var l=(0,t.createContext)(null);function u(){return(0,t.useContext)(l)}var d=new Map,f=null;function p(e,t){if(typeof ResizeObserver>`u`)return()=>{};f!=null||(f=new ResizeObserver(e=>{let t=new Map;for(let r of e){var n;for(let e of(n=d.get(r.target))==null?[]:n){let n=t.get(e);n?n.push(r):t.set(e,[r])}}for(let[e,n]of t)e(n)}));let n=d.get(e);return n||(n=new Set,d.set(e,n),f.observe(e)),n.add(t),()=>{n.delete(t),n.size||(d.delete(e),f==null||f.unobserve(e)),d.size||(f==null||f.disconnect(),f=null)}}var m=new Map,h=new Map,g=null,_=!1;function v(){for(let e of m.values())e()}function y(){_||(_=!0,Promise.resolve().then(()=>{_=!1,m.size&&b()}))}function b(){let e=new Set,t=new Set;for(let n of m.keys())for(let r=n;r!=null&&r.parentElement;r=r.parentElement){let n=r.parentElement;e.add(n);for(let t=r.previousElementSibling;t&&!e.has(t);t=t.previousElementSibling)e.add(t);if(t.has(n))break;t.add(n)}let n=[...h.keys()].filter(t=>!e.has(t));n.length&&(g==null||g.disconnect());for(let e of n)h.get(e)(),h.delete(e);for(let t of e){let e=!h.has(t);e&&h.set(t,p(t,v)),(e||n.length)&&(g==null||g.observe(t,{childList:!0,attributes:!0,attributeFilter:[`class`,`style`]}))}}function x(e,t){return m.set(e,t),!g&&typeof MutationObserver<`u`&&(g=new MutationObserver(e=>{e.some(e=>e.type===`childList`)&&y(),v()})),y(),()=>{if(m.delete(e),m.size)y();else{g==null||g.disconnect(),g=null;for(let e of h.values())e();h.clear()}}}var S=new Set,C=new Set,w=new Set,T=null;function E(e){S.has(e)&&(w.add(e),T!=null||(T=requestAnimationFrame(k)))}function D(){for(let e of C)E(e)}function O(){for(let e of S)e.resize(),E(e)}function k(){T=null;let e=[...w];w.clear();let t=[],n=[],r;for(let n of e)if(S.has(n))try{let e=n.read();e&&t.push({client:n,write:e})}catch(e){var i;((i=r)==null?r=[]:i).push(e)}for(let{client:e,write:i}of t)if(S.has(e))try{let t=i();t&&n.push({client:e,notify:t})}catch(e){var a;((a=r)==null?r=[]:a).push(e)}for(let{client:e,notify:t}of n)if(S.has(e))try{t()}catch(e){var o;((o=r)==null?r=[]:o).push(e)}if(r)throw r[0]}function A(e,t){let n={read:e,resize:t};return S.size||(window.addEventListener(`scroll`,D,{passive:!0,capture:!0}),window.addEventListener(`resize`,O,{passive:!0})),S.add(n),C.add(n),E(n),{schedule:()=>E(n),setScrollEnabled:e=>{e?C.add(n):C.delete(n)},stop:()=>{S.delete(n),C.delete(n),w.delete(n),!w.size&&T!==null&&(cancelAnimationFrame(T),T=null),S.size||(window.removeEventListener(`scroll`,D,!0),window.removeEventListener(`resize`,O))}}}function j({mode:e,children:n,className:r,...i}){var a;let o=u(),s=(0,t.useRef)(null),c=(0,t.useRef)(null),l=o==null?void 0:o.register,d=e==null?o==null?void 0:o.mode:e,f=o==null?void 0:o.baseZIndex,p=(a=i.style)==null?void 0:a.height,m=(0,t.useRef)(null),h=o==null?void 0:o.scheduleUpdate;return(0,t.useEffect)(()=>{let e=s.current,t=c.current;if(!e||!t)return;let n=typeof p==`number`?`${p}px`:p==null?``:p;if(M(e,`height`,n),!l||!d||d===`none`)return;let r=p===void 0||[`auto`,`initial`,`unset`,`revert`,`revert-layer`,`fit-content`,`min-content`,`max-content`].includes(String(p)),i=!1,a=null,o,u=null,h=()=>{if(a!==null&&(a=null,e.classList.remove(`is-native-sticky`),e.style.removeProperty(`--oe-sticky-top`),e.style.removeProperty(`--oe-sticky-z`)),i){i=!1,u=null,t.classList.remove(`is-sticky`),e.style.height=n;for(let e of[`top`,`left`,`width`,`z-index`])t.style.removeProperty(e)}},g=null,_={canNative:!1,applyNative:(t,n)=>{(a!==t||o!==n)&&(h(),a=t,o=n,e.style.setProperty(`--oe-sticky-top`,`${t}px`),e.style.setProperty(`--oe-sticky-z`,String(n)),e.classList.add(`is-native-sticky`))},el:e,content:t,mode:d,apply:n=>{if(n===null){h();return}a!==null&&h();let{top:o,wrapperHeight:s,width:c,left:l,index:p}=n;u&&u.top===o&&u.wrapperHeight===s&&u.width===c&&u.left===l&&u.index===p||(u=n,r&&M(e,`height`,`${s}px`),M(t,`top`,`${o}px`),M(t,`left`,`${l}px`),M(t,`width`,`${c}px`),M(t,`zIndex`,`${(f==null?200:f)+(d===`replace`?-p:p)}`),i||(i=!0,t.classList.add(`is-sticky`)))},measure:n=>{g!=null||(g=N(e,t));let r=t.getBoundingClientRect().height;return{height:r,wrapperHeight:r+g.heightInset,width:Math.max(0,n.width-g.widthInset),left:n.left+g.leftInset}},invalidate:()=>{g=null,u=null}};m.current=_;let v=l(_);return()=>{m.current=null,v(),h()}},[l,d,f,p]),(0,t.useEffect)(()=>{if(m.current){var e;let t=i.style;m.current.canNative=p===void 0&&(t==null?void 0:t.position)===void 0&&(t==null?void 0:t.top)===void 0&&(t==null?void 0:t.bottom)===void 0&&(t==null?void 0:t.zIndex)===void 0,!m.current.canNative&&(e=s.current)!=null&&e.classList.contains(`is-native-sticky`)&&m.current.apply(null),m.current.invalidate()}h==null||h()}),t.default.createElement(`div`,{...i,className:[`oe-sticky-item`,r].filter(Boolean).join(` `),ref:s},t.default.createElement(`div`,{className:`oe-sticky-content`,ref:c},n))}function M(e,t,n){e.style[t]!==n&&(e.style[t]=n)}function N(e,t){let n=getComputedStyle(e),r=getComputedStyle(t),i=e=>Number.parseFloat(e)||0,a=e=>i(e.paddingLeft)+i(e.paddingRight)+i(e.borderLeftWidth)+i(e.borderRightWidth);return{heightInset:n.boxSizing===`border-box`?i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth):0,widthInset:a(n)+(r.boxSizing===`border-box`?0:a(r)),leftInset:i(n.paddingLeft)+i(n.borderLeftWidth)}}function P({children:e,offsetTop:n=0,offsetBottom:r=0,overflowBehavior:i=`pin`,positionStrategy:a=`fixed`,baseZIndex:o,onStickyItemsHeightChange:s,defaultMode:c=`replace`,constraint:u,className:d,...f}){let m=o===void 0?200:Math.max(Number(o)||0,20),h=(0,t.useRef)(null),g=(0,t.useRef)(new Set),_=(0,t.useRef)(null),v=(0,t.useRef)(new Map),y=(0,t.useRef)(!1),b=(0,t.useRef)(null),S=(0,t.useRef)(null),C=(0,t.useRef)(new Map),w=(0,t.useRef)(0),T=(0,t.useRef)(null),E=(0,t.useRef)({offsetTop:n,offsetBottom:r,overflowBehavior:i,positionStrategy:a,baseZIndex:m,constraint:u,onStickyItemsHeightChange:s}),D=(0,t.useCallback)(()=>{var e;return(e=S.current)==null?void 0:e.schedule()},[]),O=(0,t.useCallback)(()=>{var e,t;let n=h.current;if(!n)return;let r=E.current,i=n.getBoundingClientRect(),a=r.constraint===`none`||i.top<=r.offsetTop&&i.bottom>=r.offsetTop,o=r.positionStrategy===`auto`&&b.current!==!1&&g.current.size===1?g.current.values().next().value:void 0;if(r.positionStrategy===`auto`&&r.constraint!==`none`&&o!=null&&o.canNative&&o.el.parentElement===n&&((e=b.current)==null?b.current=F(n,o.el):e)){let e=o.content.getBoundingClientRect().height,t=o.el.getBoundingClientRect();if(t.height<=e+1&&e+r.offsetTop+Math.max(0,r.offsetBottom)<=window.innerHeight){let i=a&&t.top<=r.offsetTop?e:0;return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!!r.onStickyItemsHeightChange),T.current=null,y.current=!0,n.classList.remove(`can-sticky`),o.applyNative(r.offsetTop,r.baseZIndex),w.current!==i)return w.current=i,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,i)}}}b.current=!1}if(!a)return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!0),T.current=null,y.current){n.classList.remove(`can-sticky`);for(let e of g.current)e.apply(null);y.current=!1}if(w.current!==0)return w.current=0,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,0)}};let s=_.current;if(s)for(let e of s)e.rect=e.item.el.getBoundingClientRect();else s=_.current=[...g.current].map(e=>({item:e,rect:e.el.getBoundingClientRect()}));s.sort((e,t)=>{let n=e.rect.top-t.rect.top;return n===0?e.item.el.compareDocumentPosition(t.item.el)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1:n});let c=r.overflowBehavior===`scroll`,l=c?window.scrollY:0,u=c?T.current:null,d=0,f;if(c){if(u)d=Math.max(-u.maximum,Math.min(0,u.shift-(l-u.scrollY)));else{let e=s[0];if(e&&e.rect.top<=r.offsetTop){f=e.item.measure(e.rect);let t=f.height,n=Math.max(0,t+r.offsetTop+Math.max(0,r.offsetBottom)-window.innerHeight);d=Math.max(-n,Math.min(0,e.rect.top-r.offsetTop))}}}let p=c&&s.every(({item:e})=>e.mode===`replace`),m=r.offsetTop+d,v=0,x=s.map(({item:e,rect:t},n)=>{var r;let i=m-(p?d:0);if(t.top>i)return null;let a=(r=s[n+1])==null?void 0:r.rect.top;if(e.mode===`replace`&&a!==void 0&&a<i)return null;let o=n===0&&f?f:e.measure(t),c=e.mode===`replace`&&a!==void 0?Math.min(m,a-o.height):m;return v+=o.height,e.mode===`stack`&&(m+=o.height),{...o,top:c,index:n}}),C=null;if(c&&v>0){let e=Math.max(0,v+r.offsetTop+Math.max(0,r.offsetBottom)-window.innerHeight),t=Math.max(-e,d);for(let e of x)e&&(e.top+=t-d);C={scrollY:l,shift:t,maximum:e}}let D=r.constraint===`none`?0:Math.min(0,i.bottom-r.offsetTop-v-((t=C==null?void 0:C.shift)==null?0:t));return()=>{var e;if((e=S.current)==null||e.setScrollEnabled(!0),T.current=C,y.current=x.some(e=>e!==null),n.classList.toggle(`can-sticky`,y.current),s.forEach(({item:e},t)=>{let n=x[t];n&&(n.top+=D),e.apply(n)}),w.current!==v)return w.current=v,()=>{var e;return(e=r.onStickyItemsHeightChange)==null?void 0:e.call(r,v)}}},[]),k=(0,t.useCallback)(e=>{var t;b.current=null;for(let n of e)(t=v.current.get(n.target))==null||t.invalidate();D()},[D]),j=(0,t.useCallback)(()=>{b.current=null;for(let e of g.current)e.invalidate()},[]),M=(0,t.useCallback)(e=>(g.current.add(e),b.current=null,_.current=null,v.current.set(e.el,e),v.current.set(e.content,e),S.current&&(C.current.set(e.el,p(e.el,k)),C.current.set(e.content,p(e.content,k))),D(),()=>{var t,n;(t=C.current.get(e.el))==null||t(),(n=C.current.get(e.content))==null||n(),C.current.delete(e.el),C.current.delete(e.content),v.current.delete(e.el),v.current.delete(e.content),g.current.delete(e),b.current=null,_.current=null,D()}),[D,k]);(0,t.useEffect)(()=>{S.current=A(O,j);let e;if(typeof ResizeObserver<`u`){h.current&&(C.current.set(h.current,p(h.current,k)),e=x(h.current,()=>{j(),D()}));for(let e of g.current)C.current.set(e.el,p(e.el,k)),C.current.set(e.content,p(e.content,k))}let t=C.current;return()=>{var n;(n=S.current)==null||n.stop(),S.current=null,e==null||e();for(let e of t.values())e();t.clear()}},[O,j,D,k]),(0,t.useEffect)(()=>{b.current=null,E.current={offsetTop:n,offsetBottom:r,overflowBehavior:i,positionStrategy:a,baseZIndex:m,constraint:u,onStickyItemsHeightChange:s};for(let e of g.current)e.invalidate();D()});let N=(0,t.useMemo)(()=>({register:M,scheduleUpdate:D,baseZIndex:m,mode:c}),[M,D,m,c]);return t.default.createElement(l.Provider,{value:N},t.default.createElement(`div`,{...f,ref:h,className:[`oe-sticky-container`,d].filter(Boolean).join(` `)},e))}function F(e,t){if(typeof ResizeObserver>`u`||typeof CSS>`u`||typeof CSS.supports!=`function`||!CSS.supports(`position`,`sticky`))return!1;for(let n=e;n;n=n.parentElement){let r=getComputedStyle(n);if(n===e&&(r.display.includes(`grid`)||r.display.includes(`flex`)&&!r.flexDirection.startsWith(`column`))&&/^(normal|stretch)$/.test(r.alignItems)&&/^(auto|normal|stretch)$/.test(getComputedStyle(t).alignSelf)||/(auto|scroll|hidden|overlay)/.test(`${r.overflowX} ${r.overflowY}`))return!1}return!0}e.StickyContainer=P,e.StickyItem=j});
|
package/dist/scheduler.d.cts
CHANGED
package/dist/scheduler.d.ts
CHANGED
package/dist/style.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.oe-sticky-container,.oe-sticky-item{position:relative}.oe-sticky-content.is-sticky{position:fixed}
|
|
1
|
+
.oe-sticky-container,.oe-sticky-item{position:relative}.oe-sticky-content.is-sticky{position:fixed}.oe-sticky-item.is-native-sticky{top:var(--oe-sticky-top);z-index:var(--oe-sticky-z);position:-webkit-sticky;position:sticky}
|
|
2
2
|
/*$vite$:1*/
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-sticky-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "React components for stacked and replacing sticky section headers, with automatic height coordination and viewport offsets.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
8
8
|
"sticky",
|
|
9
|
+
"sticky-header",
|
|
10
|
+
"sticky-headers",
|
|
11
|
+
"sticky-section",
|
|
12
|
+
"stacked-headers",
|
|
9
13
|
"react-sticky",
|
|
10
14
|
"sticky-container",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
15
|
+
"typescript",
|
|
16
|
+
"nextjs"
|
|
13
17
|
],
|
|
14
18
|
"repository": {
|
|
15
19
|
"type": "git",
|
|
@@ -18,14 +22,14 @@
|
|
|
18
22
|
"bugs": {
|
|
19
23
|
"url": "https://github.com/oe/react-sticky-kit/issues"
|
|
20
24
|
},
|
|
21
|
-
"homepage": "https://
|
|
25
|
+
"homepage": "https://app.evecalm.com/react-sticky-kit/",
|
|
22
26
|
"license": "MIT",
|
|
23
27
|
"scripts": {
|
|
24
28
|
"dev": "vite",
|
|
25
29
|
"build": "vite build && tsc -p tsconfig.build.json && node scripts/build-types.mjs",
|
|
26
30
|
"preview": "vite preview",
|
|
27
31
|
"type-check": "tsc --noEmit",
|
|
28
|
-
"lint": "eslint src demo test scripts vite.config.ts vitest.config.ts playwright.config.ts",
|
|
32
|
+
"lint": "eslint src demo test scripts vite.config.ts vite.demo.config.ts vitest.config.ts playwright.config.ts",
|
|
29
33
|
"test": "vitest run",
|
|
30
34
|
"test:watch": "vitest",
|
|
31
35
|
"coverage": "vitest run --coverage",
|
|
@@ -33,7 +37,8 @@
|
|
|
33
37
|
"check:package": "node scripts/check-package.mjs",
|
|
34
38
|
"test:browser": "playwright test",
|
|
35
39
|
"prepublishOnly": "pnpm type-check && pnpm lint && pnpm test && pnpm build && pnpm check:package",
|
|
36
|
-
"check:compatibility": "node scripts/check-compatibility.mjs"
|
|
40
|
+
"check:compatibility": "node scripts/check-compatibility.mjs",
|
|
41
|
+
"build:demo": "vite build --config vite.demo.config.ts"
|
|
37
42
|
},
|
|
38
43
|
"files": [
|
|
39
44
|
"dist"
|