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 CHANGED
@@ -24,62 +24,117 @@
24
24
  </a>
25
25
  </p>
26
26
 
27
- A lightweight, flexible React sticky container and item component library. Easily create sticky headers, sections, and advanced sticky layouts with support for multiple modes and edge cases.
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
- ## Features
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
- - ๐Ÿ“ฆ Simple API: `<StickyContainer>` and `<StickyItem>`
32
- - ๐Ÿงฉ Supports `replace`, `stack`, and `none` sticky modes
33
- - ๐Ÿท๏ธ Customizable offset, z-index (baseZIndex), and sticky logic
34
- - ๐Ÿ–ฅ๏ธ Viewport-relative sticky offsets, including updates on nested scroll events
35
- - ๐Ÿ”„ Supports SSR/SSG (Next.js, Gatsby, Astro, etc.)
36
- - ๐Ÿงช Handles edge cases: empty sections, dynamic heights, zero-height headers, long headers, etc.
37
- - โšก๏ธ Written in TypeScript, fully typed
38
- - ๐Ÿงช Includes demo pages for real-world scenarios
36
+ ## See the behavior
37
+
38
+ | Replace section headings | Stack reached headings |
39
+ | --- | --- |
40
+ | ![Replacing section headers while scrolling](docs/assets/replace.gif) | ![Stacking section headers while scrolling](docs/assets/stack.gif) |
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
- ## Demo
51
- - [Apple iOS Contact App](https://codesandbox.io/p/sandbox/dreamy-hofstadter-v9dzfz)
80
+ ## Quick start: replacing section headers
52
81
 
53
- ## Usage
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
- // !! Import styles for sticky components
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 Example() {
89
+ export default function Sections() {
62
90
  return (
63
- <StickyContainer offsetTop={48} defaultMode="stack" baseZIndex={300}>
64
- <StickyItem>
65
- <div>Sticky Header</div>
66
- </StickyItem>
67
- <div>Content...</div>
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
- ## Demo
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
 
@@ -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>;
@@ -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;
@@ -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 C(e) {
77
- b.has(e) && (x.add(e), S != null || (S = requestAnimationFrame(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 b) e.resize(), C(e);
80
+ for (let e of x) w(e);
84
81
  }
85
82
  function E() {
86
- S = null;
87
- let e = [...x];
88
- x.clear();
89
- let t = [], n = [], r = [];
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
- r.push(e);
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
- r.push(e);
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
- r.push(e);
113
+ var o;
114
+ ((o = r) == null ? r = [] : o).push(e);
112
115
  }
113
- if (r.length) throw r[0];
116
+ if (r) throw r[0];
114
117
  }
115
- function D(e, t) {
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", w, {
123
+ return b.size || (window.addEventListener("scroll", T, {
121
124
  passive: !0,
122
125
  capture: !0
123
- }), window.addEventListener("resize", T, { passive: !0 })), b.add(n), C(n), {
124
- schedule: () => C(n),
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), !x.size && S !== null && (cancelAnimationFrame(S), S = null), b.size || (window.removeEventListener("scroll", w, !0), window.removeEventListener("resize", T));
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 O({ mode: t, children: n, className: r, ...a }) {
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 (k(e, "height", n), !f || !p || p === "none") return;
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, a = null, t.classList.remove("is-sticky"), e.style.height = n;
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
- }, s = null, c = {
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
- o();
175
+ c();
166
176
  return;
167
177
  }
168
- let { top: s, wrapperHeight: c, width: l, left: u, index: d } = n;
169
- a && a.top === s && a.wrapperHeight === c && a.width === l && a.left === u && a.index === d || (a = n, r && k(e, "height", `${c}px`), k(t, "top", `${s}px`), k(t, "left", `${u}px`), k(t, "width", `${l}px`), k(t, "zIndex", `${(m == null ? 200 : m) + (p === "replace" ? -d : d)}`), i || (i = !0, t.classList.add("is-sticky")));
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
- s != null || (s = A(e, t));
183
+ l != null || (l = j(e, t));
173
184
  let r = t.getBoundingClientRect().height;
174
185
  return {
175
186
  height: r,
176
- wrapperHeight: r + s.heightInset,
177
- width: Math.max(0, n.width - s.widthInset),
178
- left: n.left + s.leftInset
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
- s = null, a = null;
193
+ l = null, s = null;
183
194
  }
184
195
  };
185
- g.current = c;
186
- let l = f(c);
196
+ g.current = _;
197
+ let v = f(_);
187
198
  return () => {
188
- g.current = null, l(), o();
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
- var e;
197
- (e = g.current) == null || e.invalidate(), _ == null || _();
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 k(e, t, n) {
222
+ function A(e, t, n) {
208
223
  e.style[t] !== n && (e.style[t] = n);
209
224
  }
210
- function A(e, t) {
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 j({ children: t, offsetTop: r = 0, baseZIndex: c, onStickyItemsHeightChange: l, defaultMode: u = "replace", constraint: f, className: p, ...m }) {
221
- let h = o(null), g = o(/* @__PURE__ */ new Set()), _ = o(null), v = o(/* @__PURE__ */ new Map()), b = o(!1), x = o(null), S = o(/* @__PURE__ */ new Map()), C = o(0), w = o({
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
- constraint: f,
224
- onStickyItemsHeightChange: l
225
- }), T = n(() => {
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 = x.current) == null ? void 0 : e.schedule();
228
- }, []), E = n(() => {
229
- var e;
230
- let t = h.current;
231
- if (!t) return;
232
- let n = w.current, r = t.getBoundingClientRect();
233
- if (!(n.constraint === "none" || r.top <= n.offsetTop && r.bottom >= n.offsetTop)) return () => {
234
- if (b.current) {
235
- t.classList.remove("can-sticky");
236
- for (let e of g.current) e.apply(null);
237
- b.current = !1;
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 (C.current !== 0) return C.current = 0, () => {
273
+ if (k.current !== 0) return k.current = 0, () => {
240
274
  var e;
241
- return (e = n.onStickyItemsHeightChange) == null ? void 0 : e.call(n, 0);
275
+ return (e = r.onStickyItemsHeightChange) == null ? void 0 : e.call(r, 0);
242
276
  };
243
277
  };
244
- let i = ((e = _.current) == null ? _.current = [...g.current] : e).map((e) => ({
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
- })).sort((e, t) => {
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
- }), a = n.offsetTop, o = 0, s = i.map(({ item: e, rect: t }, n) => {
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
- if (t.top > a) return null;
253
- let s = (r = i[n + 1]) == null ? void 0 : r.rect.top;
254
- if (e.mode === "replace" && s !== void 0 && s < a) return null;
255
- let c = e.measure(t), l = e.mode === "replace" && s !== void 0 ? Math.min(a, s - c.height) : a;
256
- return o += c.height, e.mode === "stack" && (a += c.height), {
257
- ...c,
258
- top: l,
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
- }), c = n.constraint === "none" ? 0 : Math.min(0, r.bottom - n.offsetTop - o);
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
- if (b.current = s.some((e) => e !== null), t.classList.toggle("can-sticky", b.current), i.forEach(({ item: e }, t) => {
264
- let n = s[t];
265
- n && (n.top += c), e.apply(n);
266
- }), C.current !== o) return C.current = o, () => {
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 = n.onStickyItemsHeightChange) == null ? void 0 : e.call(n, o);
330
+ return (e = r.onStickyItemsHeightChange) == null ? void 0 : e.call(r, h);
269
331
  };
270
332
  };
271
- }, []), O = n((e) => {
333
+ }, []), F = n((e) => {
272
334
  var t;
273
- for (let n of e) (t = v.current.get(n.target)) == null || t.invalidate();
274
- T();
275
- }, [T]), k = n(() => {
276
- for (let e of g.current) e.invalidate();
277
- }, []), A = n((e) => (g.current.add(e), _.current = null, v.current.set(e.el, e), v.current.set(e.content, e), x.current && (S.current.set(e.el, d(e.el, O)), S.current.set(e.content, d(e.content, O))), T(), () => {
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 = S.current.get(e.el)) == null || t(), (n = S.current.get(e.content)) == null || n(), S.current.delete(e.el), S.current.delete(e.content), v.current.delete(e.el), v.current.delete(e.content), g.current.delete(e), _.current = null, T();
280
- }), [T, O]);
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
- x.current = D(E, k);
346
+ E.current = O(P, I);
283
347
  let e;
284
348
  if (typeof ResizeObserver < "u") {
285
- h.current && (S.current.set(h.current, d(h.current, O)), e = y(h.current, () => {
286
- k(), T();
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 g.current) S.current.set(e.el, d(e.el, O)), S.current.set(e.content, d(e.content, O));
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 = S.current;
354
+ let t = D.current;
291
355
  return () => {
292
356
  var n;
293
- (n = x.current) == null || n.stop(), x.current = null, e == null || e();
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
- E,
299
- k,
300
- T,
301
- O
362
+ P,
363
+ I,
364
+ M,
365
+ F
302
366
  ]), i(() => {
303
- w.current = {
367
+ T.current = null, j.current = {
304
368
  offsetTop: r,
305
- constraint: f,
306
- onStickyItemsHeightChange: l
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 g.current) e.invalidate();
309
- T();
376
+ for (let e of x.current) e.invalidate();
377
+ M();
310
378
  });
311
- let j = c === void 0 ? 200 : Math.max(Number(c) || 0, 20), M = a(() => ({
312
- register: A,
313
- scheduleUpdate: T,
314
- baseZIndex: j,
315
- mode: u
379
+ let R = a(() => ({
380
+ register: L,
381
+ scheduleUpdate: M,
382
+ baseZIndex: v,
383
+ mode: m
316
384
  }), [
317
- A,
318
- T,
319
- j,
320
- u
385
+ L,
386
+ M,
387
+ v,
388
+ m
321
389
  ]);
322
- return /* @__PURE__ */ e.createElement(s.Provider, { value: M }, /* @__PURE__ */ e.createElement("div", {
323
- ...m,
324
- ref: h,
325
- className: ["oe-sticky-container", p].filter(Boolean).join(" ")
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 { j as StickyContainer, O as StickyItem };
405
+ export { M as StickyContainer, k as StickyItem };
@@ -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});
@@ -5,6 +5,7 @@ type Client = {
5
5
  };
6
6
  export declare function subscribeUpdates(read: Client['read'], invalidate: () => void): {
7
7
  schedule: () => void;
8
+ setScrollEnabled: (enabled: boolean) => void;
8
9
  stop: () => void;
9
10
  };
10
11
  export {};
@@ -5,6 +5,7 @@ type Client = {
5
5
  };
6
6
  export declare function subscribeUpdates(read: Client['read'], invalidate: () => void): {
7
7
  schedule: () => void;
8
+ setScrollEnabled: (enabled: boolean) => void;
8
9
  stop: () => void;
9
10
  };
10
11
  export {};
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.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
- "description": "A lightweight, flexible React sticky container and item component library supporting multiple sticky modes, advanced layouts, and edge cases.",
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
- "sticky-item",
12
- "z-index"
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://github.com/oe/react-sticky-kit#readme",
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"