react-sticky-kit 0.2.1 โ 0.3.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 +77 -25
- package/dist/context.d.cts +29 -0
- package/dist/context.d.ts +29 -0
- package/dist/index.d.cts +34 -0
- package/dist/index.d.ts +34 -56
- package/dist/layout-observer.d.cts +2 -0
- package/dist/layout-observer.d.ts +2 -0
- package/dist/react-sticky.cjs +1 -0
- package/dist/react-sticky.es.js +323 -151
- package/dist/react-sticky.umd.js +1 -1
- package/dist/resize-observer.d.cts +3 -0
- package/dist/resize-observer.d.ts +3 -0
- package/dist/scheduler.d.cts +10 -0
- package/dist/scheduler.d.ts +10 -0
- package/dist/sticky-item.d.cts +8 -0
- package/dist/sticky-item.d.ts +8 -0
- package/dist/style.css +2 -1
- package/package.json +53 -33
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ A lightweight, flexible React sticky container and item component library. Easil
|
|
|
31
31
|
- ๐ฆ Simple API: `<StickyContainer>` and `<StickyItem>`
|
|
32
32
|
- ๐งฉ Supports `replace`, `stack`, and `none` sticky modes
|
|
33
33
|
- ๐ท๏ธ Customizable offset, z-index (baseZIndex), and sticky logic
|
|
34
|
-
- ๐ฅ๏ธ
|
|
34
|
+
- ๐ฅ๏ธ Viewport-relative sticky offsets, including updates on nested scroll events
|
|
35
35
|
- ๐ Supports SSR/SSG (Next.js, Gatsby, Astro, etc.)
|
|
36
36
|
- ๐งช Handles edge cases: empty sections, dynamic heights, zero-height headers, long headers, etc.
|
|
37
37
|
- โก๏ธ Written in TypeScript, fully typed
|
|
@@ -84,7 +84,7 @@ export default function Example() {
|
|
|
84
84
|
| `baseZIndex` | `number` | `200` | Base z-index for sticky items. Should be greater than the number of sticky items. |
|
|
85
85
|
| | | | In `replace` mode, z-index = baseZIndex - index; in `stack` mode, z-index = baseZIndex + index. |
|
|
86
86
|
| `onStickyItemsHeightChange` | `(height: number) => void` | | Callback when total sticky height changes |
|
|
87
|
-
| `constraint` | `'none'` | | Define the constraint for sticky behavior. 'none' = no
|
|
87
|
+
| `constraint` | `'none'` | | Define the constraint for sticky behavior. 'none' = no container boundary |
|
|
88
88
|
|
|
89
89
|
### `<StickyItem />`
|
|
90
90
|
| Prop | Type | Default | Description |
|
|
@@ -113,14 +113,9 @@ function Example() {
|
|
|
113
113
|
<div>Content...</div>
|
|
114
114
|
</StickyContainer>
|
|
115
115
|
|
|
116
|
-
{/* 2. No
|
|
116
|
+
{/* 2. No container boundary */}
|
|
117
117
|
<StickyContainer constraint="none">
|
|
118
|
-
<StickyItem><div>
|
|
119
|
-
<div>Content...</div>
|
|
120
|
-
</StickyContainer>
|
|
121
|
-
</div>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
118
|
+
<StickyItem><div>Sticky even after the container leaves</div></StickyItem>
|
|
124
119
|
<div>Content...</div>
|
|
125
120
|
</StickyContainer>
|
|
126
121
|
</div>
|
|
@@ -130,7 +125,7 @@ function Example() {
|
|
|
130
125
|
|
|
131
126
|
### Special behavior of `constraint="none"`
|
|
132
127
|
|
|
133
|
-
When you set `constraint="none"`, the sticky items will always stick when they reach the top of the viewport, regardless of their parent container's visibility.
|
|
128
|
+
When you set `constraint="none"`, the sticky items will always stick when they reach the top of the viewport, regardless of their parent container's visibility. Offsets remain relative to the viewport; this differs from native CSS `position: sticky`, which is constrained by its scrolling ancestor.
|
|
134
129
|
|
|
135
130
|
In contrast, the default behavior (without specifying a constraint) only makes items sticky when their parent container is visible in the viewport.
|
|
136
131
|
|
|
@@ -158,7 +153,7 @@ React Sticky Kit supports Server-Side Rendering (SSR) and Static Site Generation
|
|
|
158
153
|
### Next.js Example
|
|
159
154
|
|
|
160
155
|
```tsx
|
|
161
|
-
//
|
|
156
|
+
// app/page.tsx (Next.js App Router)
|
|
162
157
|
import { StickyContainer, StickyItem } from 'react-sticky-kit'
|
|
163
158
|
import 'react-sticky-kit/dist/style.css'
|
|
164
159
|
|
|
@@ -174,28 +169,85 @@ export default function Home() {
|
|
|
174
169
|
}
|
|
175
170
|
```
|
|
176
171
|
|
|
172
|
+
For Pages Router, import the global stylesheet from `pages/_app.tsx`.
|
|
173
|
+
|
|
177
174
|
### Astro Example
|
|
178
175
|
|
|
176
|
+
Create a React component containing both `StickyContainer` and `StickyItem`, then
|
|
177
|
+
hydrate it from Astro:
|
|
178
|
+
|
|
179
179
|
```astro
|
|
180
180
|
---
|
|
181
|
-
|
|
182
|
-
import
|
|
183
|
-
import 'react-sticky-kit/dist/style.css'
|
|
181
|
+
import StickyLayout from '../components/StickyLayout.tsx'
|
|
182
|
+
import 'react-sticky-kit/style'
|
|
184
183
|
---
|
|
184
|
+
<StickyLayout client:load />
|
|
185
|
+
```
|
|
185
186
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
187
|
+
## Compatibility and updates
|
|
188
|
+
|
|
189
|
+
React 17 and later are supported. Import the stylesheet explicitly, using either
|
|
190
|
+
`react-sticky-kit/style` or `react-sticky-kit/dist/style.css`. ESM, CommonJS and the
|
|
191
|
+
UMD browser build are available; UMD requires a global `React`.
|
|
192
|
+
|
|
193
|
+
The built entry points include `"use client"` for Next.js App Router. Pages Router
|
|
194
|
+
and server rendering remain supported; sticky layout is applied after mounting.
|
|
195
|
+
For Astro, wrap the sticky layout in a React component and hydrate that component
|
|
196
|
+
as a single island.
|
|
197
|
+
|
|
198
|
+
Sticky offsets use the viewport, even when an event comes from a nested scrolling
|
|
199
|
+
element. Ancestor transforms and overflow clipping can affect fixed positioning;
|
|
200
|
+
use native CSS `position: sticky` if you need offsets relative to a scrolling ancestor.
|
|
201
|
+
|
|
202
|
+
When available, `ResizeObserver` updates dynamic content heights and widths, and
|
|
203
|
+
tracks ancestor and preceding sibling sizes that can move the container. Shared,
|
|
204
|
+
scoped `MutationObserver` subscriptions refresh these observations when the surrounding
|
|
205
|
+
DOM structure or relevant classes/styles change. Observers and global scroll/resize
|
|
206
|
+
listeners are shared across containers. No continuous polling is used.
|
|
207
|
+
Without `ResizeObserver`, measurements update on scroll, window resize and component
|
|
208
|
+
commits. Native browser scroll anchoring can move the viewport when content above
|
|
209
|
+
it changes; sticky positions follow the resulting viewport.
|
|
210
|
+
|
|
211
|
+
Wrapper padding, borders and `box-sizing` are accounted for when preserving the
|
|
212
|
+
placeholder and content width. Definite inline heights are retained. Fixed headers
|
|
213
|
+
also follow horizontal scrolling. Per-item layout metrics are cached and invalidated
|
|
214
|
+
by observed dimension changes, window resize, relevant DOM changes and React
|
|
215
|
+
commits. Inactive or fully replaced headers do not have their content heights measured during scrolling.
|
|
216
|
+
`onStickyItemsHeightChange` reports the final total once per animation frame, after
|
|
217
|
+
all scheduled containers have applied their styles, when it changes, including zero when no items remain sticky. It does not emit transient
|
|
218
|
+
per-item totals or callbacks after the container unmounts.
|
|
219
|
+
|
|
220
|
+
## Performance
|
|
221
|
+
|
|
222
|
+
Scheduled containers share one animation frame. Their geometry reads finish before
|
|
223
|
+
any sticky styles are written, and unchanged layouts skip repeated style handling.
|
|
224
|
+
Inactive content heights are not measured.
|
|
225
|
+
Prefer grouping related sections in one container rather than mounting a container
|
|
226
|
+
for every row. Large numbers of simultaneously stacked headers still require
|
|
227
|
+
per-frame geometry reads. See the [performance audit](docs/performance.md) for
|
|
228
|
+
stress-test findings and limitations.
|
|
229
|
+
|
|
230
|
+
## Development
|
|
231
|
+
|
|
232
|
+
Use Node.js 22.22.2+ or 24.15.0+ and the pnpm version pinned in `package.json`.
|
|
233
|
+
The development tools require these versions; the published library keeps its
|
|
234
|
+
React 17+ peer dependency range and targets ES2018.
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
pnpm install --frozen-lockfile
|
|
238
|
+
pnpm type-check
|
|
239
|
+
pnpm lint
|
|
240
|
+
pnpm test
|
|
241
|
+
pnpm build
|
|
242
|
+
pnpm check:package
|
|
243
|
+
pnpm check:compatibility # installs the tarball with React 17, 18 and 19
|
|
244
|
+
pnpm exec playwright install --with-deps chromium firefox webkit
|
|
245
|
+
pnpm test:browser
|
|
197
246
|
```
|
|
198
247
|
|
|
248
|
+
TypeScript 6 is used for development while the ESLint TypeScript plugin supports
|
|
249
|
+
versions below 6.1. Generated declarations use the existing public component API.
|
|
250
|
+
|
|
199
251
|
## Publish steps
|
|
200
252
|
|
|
201
253
|
`pnpm pub`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const MIN_BASE_Z_INDEX = 20;
|
|
2
|
+
export declare const DEFAULT_BASE_Z_INDEX = 200;
|
|
3
|
+
/** Replace the previous item, stack below it, or disable sticky behavior. */
|
|
4
|
+
export type IStickyMode = 'replace' | 'stack' | 'none';
|
|
5
|
+
export interface IStickyItemMeasurement {
|
|
6
|
+
height: number;
|
|
7
|
+
wrapperHeight: number;
|
|
8
|
+
width: number;
|
|
9
|
+
left: number;
|
|
10
|
+
}
|
|
11
|
+
export interface IStickyItemHandle {
|
|
12
|
+
el: HTMLElement;
|
|
13
|
+
content: HTMLElement;
|
|
14
|
+
mode: Exclude<IStickyMode, 'none'>;
|
|
15
|
+
measure: (rect: DOMRect) => IStickyItemMeasurement;
|
|
16
|
+
invalidate: () => void;
|
|
17
|
+
apply: (layout: (IStickyItemMeasurement & {
|
|
18
|
+
top: number;
|
|
19
|
+
index: number;
|
|
20
|
+
}) | null) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface IStickyGroupContextValue {
|
|
23
|
+
baseZIndex: number;
|
|
24
|
+
register: (handle: IStickyItemHandle) => () => void;
|
|
25
|
+
scheduleUpdate: () => void;
|
|
26
|
+
mode: IStickyMode;
|
|
27
|
+
}
|
|
28
|
+
export declare const StickyGroupContext: import("react").Context<IStickyGroupContextValue | null>;
|
|
29
|
+
export declare function useStickyContext(): IStickyGroupContextValue | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const MIN_BASE_Z_INDEX = 20;
|
|
2
|
+
export declare const DEFAULT_BASE_Z_INDEX = 200;
|
|
3
|
+
/** Replace the previous item, stack below it, or disable sticky behavior. */
|
|
4
|
+
export type IStickyMode = 'replace' | 'stack' | 'none';
|
|
5
|
+
export interface IStickyItemMeasurement {
|
|
6
|
+
height: number;
|
|
7
|
+
wrapperHeight: number;
|
|
8
|
+
width: number;
|
|
9
|
+
left: number;
|
|
10
|
+
}
|
|
11
|
+
export interface IStickyItemHandle {
|
|
12
|
+
el: HTMLElement;
|
|
13
|
+
content: HTMLElement;
|
|
14
|
+
mode: Exclude<IStickyMode, 'none'>;
|
|
15
|
+
measure: (rect: DOMRect) => IStickyItemMeasurement;
|
|
16
|
+
invalidate: () => void;
|
|
17
|
+
apply: (layout: (IStickyItemMeasurement & {
|
|
18
|
+
top: number;
|
|
19
|
+
index: number;
|
|
20
|
+
}) | null) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface IStickyGroupContextValue {
|
|
23
|
+
baseZIndex: number;
|
|
24
|
+
register: (handle: IStickyItemHandle) => () => void;
|
|
25
|
+
scheduleUpdate: () => void;
|
|
26
|
+
mode: IStickyMode;
|
|
27
|
+
}
|
|
28
|
+
export declare const StickyGroupContext: import("react").Context<IStickyGroupContextValue | null>;
|
|
29
|
+
export declare function useStickyContext(): IStickyGroupContextValue | null;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type { IStickyMode } from './context.cjs';
|
|
3
|
+
export * from './sticky-item.cjs';
|
|
4
|
+
export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* The offset from the top of the viewport for sticky elements. Default is 0.
|
|
8
|
+
*/
|
|
9
|
+
offsetTop?: number;
|
|
10
|
+
/**
|
|
11
|
+
* base z-index for sticky items. Default is 200. minimum z-index is 20.
|
|
12
|
+
* * - When using the `replace` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` minus its index within the container.
|
|
13
|
+
* * - When using the `stack` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` plus its index.
|
|
14
|
+
* * should be greater than number of sticky items in the container.
|
|
15
|
+
* * use it when you need nest StickyContainer or need to change z-index of sticky items.
|
|
16
|
+
*/
|
|
17
|
+
baseZIndex?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Default sticky mode for the group. 'none' disables sticky behavior.
|
|
20
|
+
*/
|
|
21
|
+
defaultMode?: 'replace' | 'stack' | 'none';
|
|
22
|
+
/**
|
|
23
|
+
* Callback triggered when the total height of all currently sticky items changes.
|
|
24
|
+
* @param height The total height of all sticky items inside the container.
|
|
25
|
+
*/
|
|
26
|
+
onStickyItemsHeightChange?: (height: number) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Define the constraint for sticky behavior
|
|
29
|
+
* - undefined (default): Sticky items will stop being sticky when StickyContainer leaves viewport
|
|
30
|
+
* - 'none': No container boundary; offsets remain viewport-relative
|
|
31
|
+
*/
|
|
32
|
+
constraint?: 'none';
|
|
33
|
+
}
|
|
34
|
+
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,56 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
children:
|
|
6
|
-
/**
|
|
7
|
-
* The offset from the top of the viewport for sticky elements. Default is 0.
|
|
8
|
-
*/
|
|
9
|
-
offsetTop?: number;
|
|
10
|
-
/**
|
|
11
|
-
* base z-index for sticky items. Default is 200. minimum z-index is 20.
|
|
12
|
-
* * - When using the `replace` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` minus its index within the container.
|
|
13
|
-
* * - When using the `stack` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` plus its index.
|
|
14
|
-
* * should be greater than number of sticky items in the container.
|
|
15
|
-
* *
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*
|
|
30
|
-
* -
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export declare interface IStickyItemProps extends default_2.HTMLAttributes<HTMLDivElement> {
|
|
37
|
-
children: default_2.ReactNode;
|
|
38
|
-
/**
|
|
39
|
-
* Sticky mode for this item. Defaults to the StickyContainer's mode if not specified.
|
|
40
|
-
*/
|
|
41
|
-
mode?: IStickyMode;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Sticky mode:
|
|
46
|
-
* - 'replace': This item replaces the previous sticky item; its height is set to the previous sticky item's height.
|
|
47
|
-
* - 'stack': This item stacks on top of previous sticky items; its height is set to 0.
|
|
48
|
-
* - 'none': This item is not sticky.
|
|
49
|
-
*/
|
|
50
|
-
export declare type IStickyMode = 'replace' | 'stack' | 'none';
|
|
51
|
-
|
|
52
|
-
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, ...rest }: IStickyContainerProps): JSX.Element;
|
|
53
|
-
|
|
54
|
-
export declare function StickyItem({ mode, children, className, ...rest }: IStickyItemProps): JSX.Element;
|
|
55
|
-
|
|
56
|
-
export { }
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type { IStickyMode } from './context.js';
|
|
3
|
+
export * from './sticky-item.js';
|
|
4
|
+
export interface IStickyContainerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* The offset from the top of the viewport for sticky elements. Default is 0.
|
|
8
|
+
*/
|
|
9
|
+
offsetTop?: number;
|
|
10
|
+
/**
|
|
11
|
+
* base z-index for sticky items. Default is 200. minimum z-index is 20.
|
|
12
|
+
* * - When using the `replace` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` minus its index within the container.
|
|
13
|
+
* * - When using the `stack` mode, the z-index of a `StickyItem` is calculated as `baseZIndex` plus its index.
|
|
14
|
+
* * should be greater than number of sticky items in the container.
|
|
15
|
+
* * use it when you need nest StickyContainer or need to change z-index of sticky items.
|
|
16
|
+
*/
|
|
17
|
+
baseZIndex?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Default sticky mode for the group. 'none' disables sticky behavior.
|
|
20
|
+
*/
|
|
21
|
+
defaultMode?: 'replace' | 'stack' | 'none';
|
|
22
|
+
/**
|
|
23
|
+
* Callback triggered when the total height of all currently sticky items changes.
|
|
24
|
+
* @param height The total height of all sticky items inside the container.
|
|
25
|
+
*/
|
|
26
|
+
onStickyItemsHeightChange?: (height: number) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Define the constraint for sticky behavior
|
|
29
|
+
* - undefined (default): Sticky items will stop being sticky when StickyContainer leaves viewport
|
|
30
|
+
* - 'none': No container boundary; offsets remain viewport-relative
|
|
31
|
+
*/
|
|
32
|
+
constraint?: 'none';
|
|
33
|
+
}
|
|
34
|
+
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, className, ...rest }: IStickyContainerProps): React.ReactElement<any, any>;
|
|
@@ -0,0 +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;
|
package/dist/react-sticky.es.js
CHANGED
|
@@ -1,157 +1,329 @@
|
|
|
1
|
-
|
|
2
|
-
import { createContext as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import e, { createContext as t, useCallback as n, useContext as r, useEffect as i, useMemo as a, useRef as o } from "react";
|
|
3
|
+
//#region src/context.ts
|
|
4
|
+
var s = t(null);
|
|
5
|
+
function c() {
|
|
6
|
+
return r(s);
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const d = r - (s + i);
|
|
28
|
-
if (d < 0 && (p = s + d, d + i < 0))
|
|
29
|
-
return l.current.isSticky && o(!1), 0;
|
|
30
|
-
}
|
|
31
|
-
return a.style.height = `${i}px`, l.current.isSticky || o(!0), t.style.top = `${p}px`, t.style.width = `${a.offsetWidth}px`, t.style.zIndex = `${l.current.baseZIndex + (n === "replace" ? -u : u)}`, n === "replace" ? 0 : i;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
return e.register(x);
|
|
35
|
-
}, [e == null ? void 0 : e.mode, e == null ? void 0 : e.register, f]), E(() => {
|
|
36
|
-
const t = g.current, a = S.current, n = e == null ? void 0 : e.updateStickyItemsHeight;
|
|
37
|
-
if (!m || !t || !a || !n)
|
|
38
|
-
return;
|
|
39
|
-
const H = n(a.getBoundingClientRect().height);
|
|
40
|
-
return () => {
|
|
41
|
-
N(t, ["height"]), N(a, ["top", "z-index", "width"]), H();
|
|
42
|
-
};
|
|
43
|
-
}, [m, e == null ? void 0 : e.updateStickyItemsHeight]), /* @__PURE__ */ w("div", { className: "oe-sticky-item " + (h || ""), ...I, ref: g, children: /* @__PURE__ */ w("div", { className: "oe-sticky-content " + (m ? "is-sticky" : ""), ref: S, children: y }) });
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/resize-observer.ts
|
|
10
|
+
var l = /* @__PURE__ */ new Map(), u = null;
|
|
11
|
+
function d(e, t) {
|
|
12
|
+
if (typeof ResizeObserver > "u") return () => {};
|
|
13
|
+
u != null || (u = new ResizeObserver((e) => {
|
|
14
|
+
let t = /* @__PURE__ */ new Map();
|
|
15
|
+
for (let r of e) {
|
|
16
|
+
var n;
|
|
17
|
+
for (let e of (n = l.get(r.target)) == null ? [] : n) {
|
|
18
|
+
let n = t.get(e);
|
|
19
|
+
n ? n.push(r) : t.set(e, [r]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (let [e, n] of t) e(n);
|
|
23
|
+
}));
|
|
24
|
+
let n = l.get(e);
|
|
25
|
+
return n || (n = /* @__PURE__ */ new Set(), l.set(e, n), u.observe(e)), n.add(t), () => {
|
|
26
|
+
n.delete(t), n.size || (l.delete(e), u == null || u.unobserve(e)), l.size || (u == null || u.disconnect(), u = null);
|
|
27
|
+
};
|
|
44
28
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/layout-observer.ts
|
|
31
|
+
var f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = null, h = !1;
|
|
32
|
+
function g() {
|
|
33
|
+
for (let e of f.values()) e();
|
|
49
34
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
onStickyItemsHeightChange: I,
|
|
55
|
-
defaultMode: e = "replace",
|
|
56
|
-
constraint: g,
|
|
57
|
-
...S
|
|
58
|
-
}) {
|
|
59
|
-
const m = k(null), o = k([]), l = k(null), t = k({
|
|
60
|
-
fixedOffsetTop: y,
|
|
61
|
-
defaultMode: e,
|
|
62
|
-
stickyItemsHeight: 0,
|
|
63
|
-
onStickyItemsHeightChange: I,
|
|
64
|
-
lastCanSticky: !1
|
|
65
|
-
});
|
|
66
|
-
t.current.onStickyItemsHeightChange = I;
|
|
67
|
-
const a = v(() => {
|
|
68
|
-
var c;
|
|
69
|
-
return g === "none" ? {
|
|
70
|
-
top: -1 / 0,
|
|
71
|
-
bottom: 1 / 0,
|
|
72
|
-
left: -1 / 0,
|
|
73
|
-
right: 1 / 0,
|
|
74
|
-
width: 1 / 0,
|
|
75
|
-
height: 1 / 0,
|
|
76
|
-
x: 0,
|
|
77
|
-
y: 0,
|
|
78
|
-
toJSON: () => ({})
|
|
79
|
-
} : ((c = m.current) == null ? void 0 : c.getBoundingClientRect()) || { top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0, x: 0, y: 0, toJSON: () => ({}) };
|
|
80
|
-
}, [g]), n = v(() => {
|
|
81
|
-
const c = m.current;
|
|
82
|
-
!c || l.current || (l.current = requestAnimationFrame(() => {
|
|
83
|
-
l.current = null;
|
|
84
|
-
const s = a(), { fixedOffsetTop: r, stickyItemsHeight: u } = t.current;
|
|
85
|
-
let i;
|
|
86
|
-
if (g === "none" ? i = !0 : i = !(s.top > r || s.bottom < r), !i) {
|
|
87
|
-
t.current.lastCanSticky !== i && (c.classList.toggle("can-sticky", !1), o.current.forEach((C) => C.update(!1, 0, 0, 0, 0)), t.current.lastCanSticky = i);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
t.current.lastCanSticky = i, u > 0 && c.classList.toggle("can-sticky", !0);
|
|
91
|
-
let p, d = 0;
|
|
92
|
-
p = r, d = s.bottom - (r + u), d > 0 && (d = 0);
|
|
93
|
-
const b = o.current.map((C) => C.el.getBoundingClientRect().top);
|
|
94
|
-
o.current.forEach((C, R) => {
|
|
95
|
-
p += C.update(i, b[R], p + d, b[R + 1], R);
|
|
96
|
-
});
|
|
97
|
-
}));
|
|
98
|
-
}, [a, g]), H = v((c) => {
|
|
99
|
-
const s = t.current.stickyItemsHeight + c;
|
|
100
|
-
return t.current.stickyItemsHeight = s, setTimeout(() => {
|
|
101
|
-
var r, u;
|
|
102
|
-
(u = (r = t.current).onStickyItemsHeightChange) == null || u.call(r, s);
|
|
103
|
-
}, 0), () => {
|
|
104
|
-
const r = t.current.stickyItemsHeight - c;
|
|
105
|
-
t.current.stickyItemsHeight = r, setTimeout(() => {
|
|
106
|
-
var u, i;
|
|
107
|
-
(i = (u = t.current).onStickyItemsHeightChange) == null || i.call(u, r);
|
|
108
|
-
}, 0);
|
|
109
|
-
};
|
|
110
|
-
}, []);
|
|
111
|
-
E(() => {
|
|
112
|
-
t.current.fixedOffsetTop = y, t.current.defaultMode = e, setTimeout(() => {
|
|
113
|
-
n();
|
|
114
|
-
}, 10);
|
|
115
|
-
}, [y, e, n]);
|
|
116
|
-
const x = v((c) => (o.current.push(c), o.current = W(o.current), n(), () => {
|
|
117
|
-
o.current = o.current.filter((s) => s !== c), n();
|
|
118
|
-
}), [n]);
|
|
119
|
-
E(() => (window.addEventListener("scroll", n, { passive: !0 }), window.addEventListener("resize", n, { passive: !0 }), () => {
|
|
120
|
-
window.removeEventListener("scroll", n), window.removeEventListener("resize", n);
|
|
121
|
-
}), [n]);
|
|
122
|
-
const B = _(() => D(h), [h]);
|
|
123
|
-
return /* @__PURE__ */ w(
|
|
124
|
-
$.Provider,
|
|
125
|
-
{
|
|
126
|
-
value: {
|
|
127
|
-
register: x,
|
|
128
|
-
baseZIndex: B,
|
|
129
|
-
updateStickyItemsHeight: H,
|
|
130
|
-
fixedOffsetTop: y,
|
|
131
|
-
mode: e
|
|
132
|
-
},
|
|
133
|
-
children: /* @__PURE__ */ w(
|
|
134
|
-
"div",
|
|
135
|
-
{
|
|
136
|
-
...S,
|
|
137
|
-
ref: m,
|
|
138
|
-
className: "oe-sticky-container",
|
|
139
|
-
children: f
|
|
140
|
-
}
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
);
|
|
35
|
+
function _() {
|
|
36
|
+
h || (h = !0, Promise.resolve().then(() => {
|
|
37
|
+
h = !1, f.size && v();
|
|
38
|
+
}));
|
|
144
39
|
}
|
|
145
|
-
function
|
|
146
|
-
|
|
40
|
+
function v() {
|
|
41
|
+
let e = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set();
|
|
42
|
+
for (let n of f.keys()) for (let r = n; r != null && r.parentElement; r = r.parentElement) {
|
|
43
|
+
let n = r.parentElement;
|
|
44
|
+
e.add(n);
|
|
45
|
+
for (let t = r.previousElementSibling; t && !e.has(t); t = t.previousElementSibling) e.add(t);
|
|
46
|
+
if (t.has(n)) break;
|
|
47
|
+
t.add(n);
|
|
48
|
+
}
|
|
49
|
+
let n = [...p.keys()].filter((t) => !e.has(t));
|
|
50
|
+
n.length && (m == null || m.disconnect());
|
|
51
|
+
for (let e of n) p.get(e)(), p.delete(e);
|
|
52
|
+
for (let t of e) {
|
|
53
|
+
let e = !p.has(t);
|
|
54
|
+
e && p.set(t, d(t, g)), (e || n.length) && (m == null || m.observe(t, {
|
|
55
|
+
childList: !0,
|
|
56
|
+
attributes: !0,
|
|
57
|
+
attributeFilter: ["class", "style"]
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
147
60
|
}
|
|
148
|
-
function
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
61
|
+
function y(e, t) {
|
|
62
|
+
return f.set(e, t), !m && typeof MutationObserver < "u" && (m = new MutationObserver((e) => {
|
|
63
|
+
e.some((e) => e.type === "childList") && _(), g();
|
|
64
|
+
})), _(), () => {
|
|
65
|
+
if (f.delete(e), f.size) _();
|
|
66
|
+
else {
|
|
67
|
+
m == null || m.disconnect(), m = null;
|
|
68
|
+
for (let e of p.values()) e();
|
|
69
|
+
p.clear();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
153
72
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
73
|
+
//#endregion
|
|
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);
|
|
81
|
+
}
|
|
82
|
+
function T() {
|
|
83
|
+
for (let e of b) e.resize(), C(e);
|
|
84
|
+
}
|
|
85
|
+
function E() {
|
|
86
|
+
S = null;
|
|
87
|
+
let e = [...x];
|
|
88
|
+
x.clear();
|
|
89
|
+
let t = [], n = [], r = [];
|
|
90
|
+
for (let n of e) if (b.has(n)) try {
|
|
91
|
+
let e = n.read();
|
|
92
|
+
e && t.push({
|
|
93
|
+
client: n,
|
|
94
|
+
write: e
|
|
95
|
+
});
|
|
96
|
+
} catch (e) {
|
|
97
|
+
r.push(e);
|
|
98
|
+
}
|
|
99
|
+
for (let { client: e, write: i } of t) if (b.has(e)) try {
|
|
100
|
+
let t = i();
|
|
101
|
+
t && n.push({
|
|
102
|
+
client: e,
|
|
103
|
+
notify: t
|
|
104
|
+
});
|
|
105
|
+
} catch (e) {
|
|
106
|
+
r.push(e);
|
|
107
|
+
}
|
|
108
|
+
for (let { client: e, notify: t } of n) if (b.has(e)) try {
|
|
109
|
+
t();
|
|
110
|
+
} catch (e) {
|
|
111
|
+
r.push(e);
|
|
112
|
+
}
|
|
113
|
+
if (r.length) throw r[0];
|
|
114
|
+
}
|
|
115
|
+
function D(e, t) {
|
|
116
|
+
let n = {
|
|
117
|
+
read: e,
|
|
118
|
+
resize: t
|
|
119
|
+
};
|
|
120
|
+
return b.size || (window.addEventListener("scroll", w, {
|
|
121
|
+
passive: !0,
|
|
122
|
+
capture: !0
|
|
123
|
+
}), window.addEventListener("resize", T, { passive: !0 })), b.add(n), C(n), {
|
|
124
|
+
schedule: () => C(n),
|
|
125
|
+
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));
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/sticky-item.tsx
|
|
132
|
+
function O({ mode: t, children: n, className: r, ...a }) {
|
|
133
|
+
var s;
|
|
134
|
+
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
|
+
return i(() => {
|
|
136
|
+
let e = u.current, t = d.current;
|
|
137
|
+
if (!e || !t) return;
|
|
138
|
+
let n = typeof h == "number" ? `${h}px` : h == null ? "" : h;
|
|
139
|
+
if (k(e, "height", n), !f || !p || p === "none") return;
|
|
140
|
+
let r = h === void 0 || [
|
|
141
|
+
"auto",
|
|
142
|
+
"initial",
|
|
143
|
+
"unset",
|
|
144
|
+
"revert",
|
|
145
|
+
"revert-layer",
|
|
146
|
+
"fit-content",
|
|
147
|
+
"min-content",
|
|
148
|
+
"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;
|
|
152
|
+
for (let e of [
|
|
153
|
+
"top",
|
|
154
|
+
"left",
|
|
155
|
+
"width",
|
|
156
|
+
"z-index"
|
|
157
|
+
]) t.style.removeProperty(e);
|
|
158
|
+
}
|
|
159
|
+
}, s = null, c = {
|
|
160
|
+
el: e,
|
|
161
|
+
content: t,
|
|
162
|
+
mode: p,
|
|
163
|
+
apply: (n) => {
|
|
164
|
+
if (n === null) {
|
|
165
|
+
o();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
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")));
|
|
170
|
+
},
|
|
171
|
+
measure: (n) => {
|
|
172
|
+
s != null || (s = A(e, t));
|
|
173
|
+
let r = t.getBoundingClientRect().height;
|
|
174
|
+
return {
|
|
175
|
+
height: r,
|
|
176
|
+
wrapperHeight: r + s.heightInset,
|
|
177
|
+
width: Math.max(0, n.width - s.widthInset),
|
|
178
|
+
left: n.left + s.leftInset
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
invalidate: () => {
|
|
182
|
+
s = null, a = null;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
g.current = c;
|
|
186
|
+
let l = f(c);
|
|
187
|
+
return () => {
|
|
188
|
+
g.current = null, l(), o();
|
|
189
|
+
};
|
|
190
|
+
}, [
|
|
191
|
+
f,
|
|
192
|
+
p,
|
|
193
|
+
m,
|
|
194
|
+
h
|
|
195
|
+
]), i(() => {
|
|
196
|
+
var e;
|
|
197
|
+
(e = g.current) == null || e.invalidate(), _ == null || _();
|
|
198
|
+
}), /* @__PURE__ */ e.createElement("div", {
|
|
199
|
+
...a,
|
|
200
|
+
className: ["oe-sticky-item", r].filter(Boolean).join(" "),
|
|
201
|
+
ref: u
|
|
202
|
+
}, /* @__PURE__ */ e.createElement("div", {
|
|
203
|
+
className: "oe-sticky-content",
|
|
204
|
+
ref: d
|
|
205
|
+
}, n));
|
|
206
|
+
}
|
|
207
|
+
function k(e, t, n) {
|
|
208
|
+
e.style[t] !== n && (e.style[t] = n);
|
|
209
|
+
}
|
|
210
|
+
function A(e, t) {
|
|
211
|
+
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
|
+
return {
|
|
213
|
+
heightInset: n.boxSizing === "border-box" ? i(n.paddingTop) + i(n.paddingBottom) + i(n.borderTopWidth) + i(n.borderBottomWidth) : 0,
|
|
214
|
+
widthInset: a(n) + (r.boxSizing === "border-box" ? 0 : a(r)),
|
|
215
|
+
leftInset: i(n.paddingLeft) + i(n.borderLeftWidth)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#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({
|
|
222
|
+
offsetTop: r,
|
|
223
|
+
constraint: f,
|
|
224
|
+
onStickyItemsHeightChange: l
|
|
225
|
+
}), T = n(() => {
|
|
226
|
+
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;
|
|
238
|
+
}
|
|
239
|
+
if (C.current !== 0) return C.current = 0, () => {
|
|
240
|
+
var e;
|
|
241
|
+
return (e = n.onStickyItemsHeightChange) == null ? void 0 : e.call(n, 0);
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
let i = ((e = _.current) == null ? _.current = [...g.current] : e).map((e) => ({
|
|
245
|
+
item: e,
|
|
246
|
+
rect: e.el.getBoundingClientRect()
|
|
247
|
+
})).sort((e, t) => {
|
|
248
|
+
let n = e.rect.top - t.rect.top;
|
|
249
|
+
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) => {
|
|
251
|
+
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,
|
|
259
|
+
index: n
|
|
260
|
+
};
|
|
261
|
+
}), c = n.constraint === "none" ? 0 : Math.min(0, r.bottom - n.offsetTop - o);
|
|
262
|
+
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, () => {
|
|
267
|
+
var e;
|
|
268
|
+
return (e = n.onStickyItemsHeightChange) == null ? void 0 : e.call(n, o);
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
}, []), O = n((e) => {
|
|
272
|
+
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(), () => {
|
|
278
|
+
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]);
|
|
281
|
+
i(() => {
|
|
282
|
+
x.current = D(E, k);
|
|
283
|
+
let e;
|
|
284
|
+
if (typeof ResizeObserver < "u") {
|
|
285
|
+
h.current && (S.current.set(h.current, d(h.current, O)), e = y(h.current, () => {
|
|
286
|
+
k(), T();
|
|
287
|
+
}));
|
|
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));
|
|
289
|
+
}
|
|
290
|
+
let t = S.current;
|
|
291
|
+
return () => {
|
|
292
|
+
var n;
|
|
293
|
+
(n = x.current) == null || n.stop(), x.current = null, e == null || e();
|
|
294
|
+
for (let e of t.values()) e();
|
|
295
|
+
t.clear();
|
|
296
|
+
};
|
|
297
|
+
}, [
|
|
298
|
+
E,
|
|
299
|
+
k,
|
|
300
|
+
T,
|
|
301
|
+
O
|
|
302
|
+
]), i(() => {
|
|
303
|
+
w.current = {
|
|
304
|
+
offsetTop: r,
|
|
305
|
+
constraint: f,
|
|
306
|
+
onStickyItemsHeightChange: l
|
|
307
|
+
};
|
|
308
|
+
for (let e of g.current) e.invalidate();
|
|
309
|
+
T();
|
|
310
|
+
});
|
|
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
|
|
316
|
+
}), [
|
|
317
|
+
A,
|
|
318
|
+
T,
|
|
319
|
+
j,
|
|
320
|
+
u
|
|
321
|
+
]);
|
|
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(" ")
|
|
326
|
+
}, t));
|
|
327
|
+
}
|
|
328
|
+
//#endregion
|
|
329
|
+
export { j as StickyContainer, O as StickyItem };
|
package/dist/react-sticky.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
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});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Write = () => (() => void) | void;
|
|
2
|
+
type Client = {
|
|
3
|
+
read: () => Write | undefined;
|
|
4
|
+
resize: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function subscribeUpdates(read: Client['read'], invalidate: () => void): {
|
|
7
|
+
schedule: () => void;
|
|
8
|
+
stop: () => void;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Write = () => (() => void) | void;
|
|
2
|
+
type Client = {
|
|
3
|
+
read: () => Write | undefined;
|
|
4
|
+
resize: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function subscribeUpdates(read: Client['read'], invalidate: () => void): {
|
|
7
|
+
schedule: () => void;
|
|
8
|
+
stop: () => void;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type IStickyMode } from './context.cjs';
|
|
3
|
+
export interface IStickyItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
/** Sticky mode for this item. Defaults to the StickyContainer's mode. */
|
|
6
|
+
mode?: IStickyMode;
|
|
7
|
+
}
|
|
8
|
+
export declare function StickyItem({ mode, children, className, ...rest }: IStickyItemProps): React.ReactElement<any, any>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type IStickyMode } from './context.js';
|
|
3
|
+
export interface IStickyItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
/** Sticky mode for this item. Defaults to the StickyContainer's mode. */
|
|
6
|
+
mode?: IStickyMode;
|
|
7
|
+
}
|
|
8
|
+
export declare function StickyItem({ mode, children, className, ...rest }: IStickyItemProps): React.ReactElement<any, any>;
|
package/dist/style.css
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
.oe-sticky-container{position:relative}.oe-sticky-
|
|
1
|
+
.oe-sticky-container,.oe-sticky-item{position:relative}.oe-sticky-content.is-sticky{position:fixed}
|
|
2
|
+
/*$vite$:1*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-sticky-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A lightweight, flexible React sticky container and item component library supporting multiple sticky modes, advanced layouts, and edge cases.",
|
|
6
6
|
"keywords": [
|
|
@@ -22,26 +22,45 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"dev": "vite",
|
|
25
|
-
"build": "vite build",
|
|
25
|
+
"build": "vite build && tsc -p tsconfig.build.json && node scripts/build-types.mjs",
|
|
26
26
|
"preview": "vite preview",
|
|
27
27
|
"type-check": "tsc --noEmit",
|
|
28
|
-
"lint": "eslint src demo
|
|
28
|
+
"lint": "eslint src demo test scripts vite.config.ts vitest.config.ts playwright.config.ts",
|
|
29
29
|
"test": "vitest run",
|
|
30
30
|
"test:watch": "vitest",
|
|
31
31
|
"coverage": "vitest run --coverage",
|
|
32
|
-
"pub": "tsx ./scripts/publish.ts"
|
|
32
|
+
"pub": "tsx ./scripts/publish.ts",
|
|
33
|
+
"check:package": "node scripts/check-package.mjs",
|
|
34
|
+
"test:browser": "playwright test",
|
|
35
|
+
"prepublishOnly": "pnpm type-check && pnpm lint && pnpm test && pnpm build && pnpm check:package",
|
|
36
|
+
"check:compatibility": "node scripts/check-compatibility.mjs"
|
|
33
37
|
},
|
|
34
38
|
"files": [
|
|
35
39
|
"dist"
|
|
36
40
|
],
|
|
37
|
-
"main": "dist/react-sticky.
|
|
41
|
+
"main": "dist/react-sticky.cjs",
|
|
38
42
|
"module": "dist/react-sticky.es.js",
|
|
39
43
|
"types": "dist/index.d.ts",
|
|
40
44
|
"exports": {
|
|
41
45
|
".": {
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
"node": {
|
|
47
|
+
"import": {
|
|
48
|
+
"types": "./dist/index.d.cts",
|
|
49
|
+
"default": "./dist/react-sticky.cjs"
|
|
50
|
+
},
|
|
51
|
+
"require": {
|
|
52
|
+
"types": "./dist/index.d.cts",
|
|
53
|
+
"default": "./dist/react-sticky.cjs"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"import": {
|
|
57
|
+
"types": "./dist/index.d.ts",
|
|
58
|
+
"default": "./dist/react-sticky.es.js"
|
|
59
|
+
},
|
|
60
|
+
"require": {
|
|
61
|
+
"types": "./dist/index.d.cts",
|
|
62
|
+
"default": "./dist/react-sticky.cjs"
|
|
63
|
+
}
|
|
45
64
|
},
|
|
46
65
|
"./style": "./dist/style.css",
|
|
47
66
|
"./dist/style.css": "./dist/style.css"
|
|
@@ -52,33 +71,34 @@
|
|
|
52
71
|
},
|
|
53
72
|
"devDependencies": {
|
|
54
73
|
"@eslint/js": "^9.25.0",
|
|
55
|
-
"@
|
|
56
|
-
"@testing-library/
|
|
57
|
-
"@testing-library/
|
|
58
|
-
"@types/node": "^
|
|
59
|
-
"@types/react": "^19.
|
|
60
|
-
"@types/react-dom": "^19.
|
|
61
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
62
|
-
"@typescript-eslint/parser": "^8.
|
|
63
|
-
"@vitejs/plugin-react": "^
|
|
64
|
-
"@vitest/coverage-v8": "^
|
|
65
|
-
"eslint": "^9.
|
|
74
|
+
"@playwright/test": "^1.63.0",
|
|
75
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
76
|
+
"@testing-library/react": "^16.3.3",
|
|
77
|
+
"@types/node": "^24.19.1",
|
|
78
|
+
"@types/react": "^19.3.0",
|
|
79
|
+
"@types/react-dom": "^19.3.0",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^8.71.0",
|
|
81
|
+
"@typescript-eslint/parser": "^8.71.0",
|
|
82
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
83
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
84
|
+
"eslint": "^9.39.4",
|
|
66
85
|
"eslint-config-prettier": "^10.1.5",
|
|
67
86
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
68
87
|
"eslint-plugin-react": "^7.33.2",
|
|
69
|
-
"eslint-plugin-react-hooks": "^
|
|
88
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
70
89
|
"globals": "^16.0.0",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"react": "^19.
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"
|
|
83
|
-
|
|
90
|
+
"jsdom": "^30.1.1",
|
|
91
|
+
"react": "^19.3.0",
|
|
92
|
+
"react-dom": "^19.3.0",
|
|
93
|
+
"sass": "^1.105.1",
|
|
94
|
+
"tsx": "^4.23.15",
|
|
95
|
+
"typescript": "^6.0.3",
|
|
96
|
+
"vite": "^8.3.2",
|
|
97
|
+
"vitest": "^5.0.3"
|
|
98
|
+
},
|
|
99
|
+
"packageManager": "pnpm@12.8.1",
|
|
100
|
+
"sideEffects": [
|
|
101
|
+
"**/*.css",
|
|
102
|
+
"**/*.scss"
|
|
103
|
+
]
|
|
84
104
|
}
|