react-sticky-kit 0.1.6 โ 0.2.1
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 +54 -9
- package/dist/index.d.ts +7 -1
- package/dist/react-sticky.es.js +101 -86
- package/dist/react-sticky.umd.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +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
|
+
- ๐ฅ๏ธ Flexible reference containers (window, DOM elements, refs)
|
|
34
35
|
- ๐ Supports SSR/SSG (Next.js, Gatsby, Astro, etc.)
|
|
35
36
|
- ๐งช Handles edge cases: empty sections, dynamic heights, zero-height headers, long headers, etc.
|
|
36
37
|
- โก๏ธ Written in TypeScript, fully typed
|
|
@@ -76,13 +77,14 @@ export default function Example() {
|
|
|
76
77
|
## Props
|
|
77
78
|
|
|
78
79
|
### `<StickyContainer />`
|
|
79
|
-
| Prop | Type
|
|
80
|
-
|
|
81
|
-
| `offsetTop` | `number`
|
|
82
|
-
| `defaultMode` | `'replace' \| 'stack' \| 'none'`
|
|
83
|
-
| `baseZIndex` | `number`
|
|
84
|
-
| |
|
|
85
|
-
| `onStickyItemsHeightChange` | `(height: number) => void`
|
|
80
|
+
| Prop | Type | Default | Description |
|
|
81
|
+
|-----------------------------|------------------------------------------------------|-------------|---------------------------------------------------------------------------------------------|
|
|
82
|
+
| `offsetTop` | `number` | `0` | Offset from the top of the viewport |
|
|
83
|
+
| `defaultMode` | `'replace' \| 'stack' \| 'none'` | `'replace'` | Default sticky mode for all items |
|
|
84
|
+
| `baseZIndex` | `number` | `200` | Base z-index for sticky items. Should be greater than the number of sticky items. |
|
|
85
|
+
| | | | In `replace` mode, z-index = baseZIndex - index; in `stack` mode, z-index = baseZIndex + index. |
|
|
86
|
+
| `onStickyItemsHeightChange` | `(height: number) => void` | | Callback when total sticky height changes |
|
|
87
|
+
| `constraint` | `'none'` | | Define the constraint for sticky behavior. 'none' = no constraints (CSS-like behavior) |
|
|
86
88
|
|
|
87
89
|
### `<StickyItem />`
|
|
88
90
|
| Prop | Type | Default | Description |
|
|
@@ -94,6 +96,44 @@ export default function Example() {
|
|
|
94
96
|
- **stack**: Sticky items stack on top of each other.
|
|
95
97
|
- **none**: Sticky is disabled for this item.
|
|
96
98
|
|
|
99
|
+
## Constraint Behavior
|
|
100
|
+
|
|
101
|
+
The `constraint` prop allows you to control when sticky items should stop being sticky:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import React from 'react';
|
|
105
|
+
import { StickyContainer, StickyItem } from 'react-sticky-kit';
|
|
106
|
+
|
|
107
|
+
function Example() {
|
|
108
|
+
return (
|
|
109
|
+
<div>
|
|
110
|
+
{/* 1. Default: Container-based constraint */}
|
|
111
|
+
<StickyContainer>
|
|
112
|
+
<StickyItem><div>Sticky stops when container leaves viewport</div></StickyItem>
|
|
113
|
+
<div>Content...</div>
|
|
114
|
+
</StickyContainer>
|
|
115
|
+
|
|
116
|
+
{/* 2. No constraints (like CSS position:sticky) */}
|
|
117
|
+
<StickyContainer constraint="none">
|
|
118
|
+
<StickyItem><div>Always sticky like CSS position:sticky</div></StickyItem>
|
|
119
|
+
<div>Content...</div>
|
|
120
|
+
</StickyContainer>
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
<div>Content...</div>
|
|
125
|
+
</StickyContainer>
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Special behavior of `constraint="none"`
|
|
132
|
+
|
|
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. This exactly matches the behavior of native CSS `position: sticky`.
|
|
134
|
+
|
|
135
|
+
In contrast, the default behavior (without specifying a constraint) only makes items sticky when their parent container is visible in the viewport.
|
|
136
|
+
|
|
97
137
|
## Demo
|
|
98
138
|
|
|
99
139
|
Run the demo locally:
|
|
@@ -106,9 +146,10 @@ pnpm dev
|
|
|
106
146
|
Open [http://localhost:5173](http://localhost:5173) and switch between demo pages to explore all features and edge cases:
|
|
107
147
|
* [iOS Contact](http://localhost:5173/#ios-contact) a dead simple iOS contact clone
|
|
108
148
|
* [Mixed mode](http://localhost:5173/#mixed-mode) mix replace/stack/none mode
|
|
109
|
-
* [Nested](http://localhost:5173/#
|
|
110
|
-
* [Dynamic sticky items](http://localhost:5173/#
|
|
149
|
+
* [Nested](http://localhost:5173/#nested) nest sticky containers
|
|
150
|
+
* [Dynamic sticky items](http://localhost:5173/#dynamic) dynamic sticky items(add/remove)
|
|
111
151
|
* [Dynamic offsetTop](http://localhost:5173/#dynamic-offset) dynamic offsetTop that adapts to header height changes
|
|
152
|
+
* [Constraint Demo](http://localhost:5173/#constraint) demo showing different constraint options
|
|
112
153
|
|
|
113
154
|
## SSR/SSG Support
|
|
114
155
|
|
|
@@ -155,6 +196,10 @@ import 'react-sticky-kit/dist/style.css'
|
|
|
155
196
|
</html>
|
|
156
197
|
```
|
|
157
198
|
|
|
199
|
+
## Publish steps
|
|
200
|
+
|
|
201
|
+
`pnpm pub`
|
|
202
|
+
|
|
158
203
|
## License
|
|
159
204
|
|
|
160
205
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,12 @@ export declare interface IStickyContainerProps extends default_2.HTMLAttributes<
|
|
|
25
25
|
* @param height The total height of all sticky items inside the container.
|
|
26
26
|
*/
|
|
27
27
|
onStickyItemsHeightChange?: (height: number) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Define the constraint for sticky behavior
|
|
30
|
+
* - undefined (default): Sticky items will stop being sticky when StickyContainer leaves viewport
|
|
31
|
+
* - 'none': No constraints, similar to CSS position:sticky behavior
|
|
32
|
+
*/
|
|
33
|
+
constraint?: 'none';
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
export declare interface IStickyItemProps extends default_2.HTMLAttributes<HTMLDivElement> {
|
|
@@ -43,7 +49,7 @@ export declare interface IStickyItemProps extends default_2.HTMLAttributes<HTMLD
|
|
|
43
49
|
*/
|
|
44
50
|
export declare type IStickyMode = 'replace' | 'stack' | 'none';
|
|
45
51
|
|
|
46
|
-
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, ...rest }: IStickyContainerProps): JSX.Element;
|
|
52
|
+
export declare function StickyContainer({ children, offsetTop, baseZIndex, onStickyItemsHeightChange, defaultMode, constraint, ...rest }: IStickyContainerProps): JSX.Element;
|
|
47
53
|
|
|
48
54
|
export declare function StickyItem({ mode, children, className, ...rest }: IStickyItemProps): JSX.Element;
|
|
49
55
|
|
package/dist/react-sticky.es.js
CHANGED
|
@@ -1,142 +1,157 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { createContext as
|
|
3
|
-
const
|
|
4
|
-
function
|
|
5
|
-
return
|
|
1
|
+
import { jsx as w } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as Z, useContext as L, useRef as k, useState as T, useEffect as E, useCallback as v, useMemo as _ } from "react";
|
|
3
|
+
const O = 20, A = 200, $ = Z(null);
|
|
4
|
+
function z() {
|
|
5
|
+
return L($);
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
const e =
|
|
7
|
+
function M({ mode: f, children: y, className: h, ...I }) {
|
|
8
|
+
const e = z(), g = k(null), S = k(null), [m, o] = T(!1), l = k({
|
|
9
9
|
fixedOffsetTop: (e == null ? void 0 : e.fixedOffsetTop) || 0,
|
|
10
|
-
isSticky:
|
|
11
|
-
baseZIndex: (e == null ? void 0 : e.baseZIndex) ||
|
|
10
|
+
isSticky: m,
|
|
11
|
+
baseZIndex: (e == null ? void 0 : e.baseZIndex) || O
|
|
12
12
|
});
|
|
13
|
-
return
|
|
14
|
-
const
|
|
15
|
-
if (!e || !a || !
|
|
16
|
-
|
|
13
|
+
return l.current.baseZIndex = (e == null ? void 0 : e.baseZIndex) || O, l.current.fixedOffsetTop = (e == null ? void 0 : e.fixedOffsetTop) || 0, l.current.isSticky = m, E(() => {
|
|
14
|
+
const t = S.current, a = g.current, n = f || (e == null ? void 0 : e.mode);
|
|
15
|
+
if (!e || !a || !t || n === "none" || !n || !e.register) {
|
|
16
|
+
o(!1);
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
const
|
|
19
|
+
const x = {
|
|
20
20
|
el: a,
|
|
21
|
-
update: (
|
|
22
|
-
if (!
|
|
23
|
-
return
|
|
24
|
-
const
|
|
25
|
-
let
|
|
26
|
-
if (
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
return
|
|
21
|
+
update: (B, c, s, r, u) => {
|
|
22
|
+
if (!B || c > s)
|
|
23
|
+
return l.current.isSticky && o(!1), 0;
|
|
24
|
+
const i = t.getBoundingClientRect().height;
|
|
25
|
+
let p = s;
|
|
26
|
+
if (n === "replace" && typeof r < "u") {
|
|
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
30
|
}
|
|
31
|
-
return a.style.height = `${
|
|
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
32
|
}
|
|
33
33
|
};
|
|
34
|
-
return e.register(
|
|
35
|
-
}, [e == null ? void 0 : e.mode, e == null ? void 0 : e.register,
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
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
38
|
return;
|
|
39
|
-
const
|
|
39
|
+
const H = n(a.getBoundingClientRect().height);
|
|
40
40
|
return () => {
|
|
41
|
-
|
|
41
|
+
N(t, ["height"]), N(a, ["top", "z-index", "width"]), H();
|
|
42
42
|
};
|
|
43
|
-
}, [
|
|
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 }) });
|
|
44
44
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
function N(f, y) {
|
|
46
|
+
y.forEach((h) => {
|
|
47
|
+
f.style.removeProperty(h);
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
children:
|
|
52
|
-
offsetTop:
|
|
53
|
-
baseZIndex:
|
|
54
|
-
onStickyItemsHeightChange:
|
|
50
|
+
function P({
|
|
51
|
+
children: f,
|
|
52
|
+
offsetTop: y = 0,
|
|
53
|
+
baseZIndex: h,
|
|
54
|
+
onStickyItemsHeightChange: I,
|
|
55
55
|
defaultMode: e = "replace",
|
|
56
|
+
constraint: g,
|
|
56
57
|
...S
|
|
57
58
|
}) {
|
|
58
|
-
const
|
|
59
|
-
fixedOffsetTop:
|
|
59
|
+
const m = k(null), o = k([]), l = k(null), t = k({
|
|
60
|
+
fixedOffsetTop: y,
|
|
60
61
|
defaultMode: e,
|
|
61
62
|
stickyItemsHeight: 0,
|
|
62
|
-
onStickyItemsHeightChange:
|
|
63
|
+
onStickyItemsHeightChange: I,
|
|
63
64
|
lastCanSticky: !1
|
|
64
65
|
});
|
|
65
|
-
t.current.onStickyItemsHeightChange =
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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);
|
|
73
88
|
return;
|
|
74
89
|
}
|
|
75
|
-
t.current.lastCanSticky =
|
|
76
|
-
let
|
|
77
|
-
p > 0 && (
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
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);
|
|
81
96
|
});
|
|
82
97
|
}));
|
|
83
|
-
}, []),
|
|
84
|
-
const
|
|
85
|
-
return t.current.stickyItemsHeight =
|
|
86
|
-
var
|
|
87
|
-
(
|
|
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);
|
|
88
103
|
}, 0), () => {
|
|
89
|
-
const
|
|
90
|
-
t.current.stickyItemsHeight =
|
|
91
|
-
var
|
|
92
|
-
(
|
|
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);
|
|
93
108
|
}, 0);
|
|
94
109
|
};
|
|
95
110
|
}, []);
|
|
96
111
|
E(() => {
|
|
97
|
-
t.current.fixedOffsetTop =
|
|
112
|
+
t.current.fixedOffsetTop = y, t.current.defaultMode = e, setTimeout(() => {
|
|
98
113
|
n();
|
|
99
114
|
}, 10);
|
|
100
|
-
}, [
|
|
101
|
-
const
|
|
102
|
-
|
|
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();
|
|
103
118
|
}), [n]);
|
|
104
119
|
E(() => (window.addEventListener("scroll", n, { passive: !0 }), window.addEventListener("resize", n, { passive: !0 }), () => {
|
|
105
120
|
window.removeEventListener("scroll", n), window.removeEventListener("resize", n);
|
|
106
121
|
}), [n]);
|
|
107
|
-
const
|
|
108
|
-
return /* @__PURE__ */
|
|
122
|
+
const B = _(() => D(h), [h]);
|
|
123
|
+
return /* @__PURE__ */ w(
|
|
109
124
|
$.Provider,
|
|
110
125
|
{
|
|
111
126
|
value: {
|
|
112
|
-
register:
|
|
113
|
-
baseZIndex:
|
|
114
|
-
updateStickyItemsHeight:
|
|
115
|
-
fixedOffsetTop:
|
|
127
|
+
register: x,
|
|
128
|
+
baseZIndex: B,
|
|
129
|
+
updateStickyItemsHeight: H,
|
|
130
|
+
fixedOffsetTop: y,
|
|
116
131
|
mode: e
|
|
117
132
|
},
|
|
118
|
-
children: /* @__PURE__ */
|
|
133
|
+
children: /* @__PURE__ */ w(
|
|
119
134
|
"div",
|
|
120
135
|
{
|
|
121
136
|
...S,
|
|
122
|
-
ref:
|
|
137
|
+
ref: m,
|
|
123
138
|
className: "oe-sticky-container",
|
|
124
|
-
children:
|
|
139
|
+
children: f
|
|
125
140
|
}
|
|
126
141
|
)
|
|
127
142
|
}
|
|
128
143
|
);
|
|
129
144
|
}
|
|
130
|
-
function
|
|
131
|
-
return typeof
|
|
145
|
+
function D(f) {
|
|
146
|
+
return typeof f > "u" ? A : Math.max(Number(f) || 0, O);
|
|
132
147
|
}
|
|
133
|
-
function
|
|
134
|
-
return
|
|
135
|
-
const
|
|
136
|
-
return
|
|
148
|
+
function W(f) {
|
|
149
|
+
return f.sort((y, h) => {
|
|
150
|
+
const I = y.el.getBoundingClientRect(), e = h.el.getBoundingClientRect();
|
|
151
|
+
return I.top - e.top;
|
|
137
152
|
});
|
|
138
153
|
}
|
|
139
154
|
export {
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
P as StickyContainer,
|
|
156
|
+
M as StickyItem
|
|
142
157
|
};
|
package/dist/react-sticky.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(g,I){typeof exports=="object"&&typeof module<"u"?I(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],I):(g=typeof globalThis<"u"?globalThis:g||self,I(g.ReactSticky={},g.jsxRuntime,g.React))})(this,function(g,I,n){"use strict";const N=n.createContext(null);function w(){return n.useContext(N)}const L="";function O({mode:l,children:h,className:k,...E}){const e=w(),m=n.useRef(null),C=n.useRef(null),[p,o]=n.useState(!1),d=n.useRef({fixedOffsetTop:(e==null?void 0:e.fixedOffsetTop)||0,isSticky:p,baseZIndex:(e==null?void 0:e.baseZIndex)||20});return d.current.baseZIndex=(e==null?void 0:e.baseZIndex)||20,d.current.fixedOffsetTop=(e==null?void 0:e.fixedOffsetTop)||0,d.current.isSticky=p,n.useEffect(()=>{const t=C.current,a=m.current,i=l||(e==null?void 0:e.mode);if(!e||!a||!t||i==="none"||!i||!e.register){o(!1);return}const v={el:a,update:(B,c,u,r,f)=>{if(!B||c>u)return d.current.isSticky&&o(!1),0;const s=t.getBoundingClientRect().height;let S=u;if(i==="replace"&&typeof r<"u"){const y=r-(u+s);if(y<0&&(S=u+y,y+s<0))return d.current.isSticky&&o(!1),0}return a.style.height=`${s}px`,d.current.isSticky||o(!0),t.style.top=`${S}px`,t.style.width=`${a.offsetWidth}px`,t.style.zIndex=`${d.current.baseZIndex+(i==="replace"?-f:f)}`,i==="replace"?0:s}};return e.register(v)},[e==null?void 0:e.mode,e==null?void 0:e.register,l]),n.useEffect(()=>{const t=m.current,a=C.current,i=e==null?void 0:e.updateStickyItemsHeight;if(!p||!t||!a||!i)return;const _=i(a.getBoundingClientRect().height);return()=>{b(t,["height"]),b(a,["top","z-index","width"]),_()}},[p,e==null?void 0:e.updateStickyItemsHeight]),I.jsx("div",{className:"oe-sticky-item "+(k||""),...E,ref:m,children:I.jsx("div",{className:"oe-sticky-content "+(p?"is-sticky":""),ref:C,children:h})})}function b(l,h){h.forEach(k=>{l.style.removeProperty(k)})}function Z({children:l,offsetTop:h=0,baseZIndex:k,onStickyItemsHeightChange:E,defaultMode:e="replace",constraint:m,...C}){const p=n.useRef(null),o=n.useRef([]),d=n.useRef(null),t=n.useRef({fixedOffsetTop:h,defaultMode:e,stickyItemsHeight:0,onStickyItemsHeightChange:E,lastCanSticky:!1});t.current.onStickyItemsHeightChange=E;const a=n.useCallback(()=>{var c;return m==="none"?{top:-1/0,bottom:1/0,left:-1/0,right:1/0,width:1/0,height:1/0,x:0,y:0,toJSON:()=>({})}:((c=p.current)==null?void 0:c.getBoundingClientRect())||{top:0,bottom:0,left:0,right:0,width:0,height:0,x:0,y:0,toJSON:()=>({})}},[m]),i=n.useCallback(()=>{const c=p.current;!c||d.current||(d.current=requestAnimationFrame(()=>{d.current=null;const u=a(),{fixedOffsetTop:r,stickyItemsHeight:f}=t.current;let s;if(m==="none"?s=!0:s=!(u.top>r||u.bottom<r),!s){t.current.lastCanSticky!==s&&(c.classList.toggle("can-sticky",!1),o.current.forEach(R=>R.update(!1,0,0,0,0)),t.current.lastCanSticky=s);return}t.current.lastCanSticky=s,f>0&&c.classList.toggle("can-sticky",!0);let S,y=0;S=r,y=u.bottom-(r+f),y>0&&(y=0);const x=o.current.map(R=>R.el.getBoundingClientRect().top);o.current.forEach((R,H)=>{S+=R.update(s,x[H],S+y,x[H+1],H)})}))},[a,m]),_=n.useCallback(c=>{const u=t.current.stickyItemsHeight+c;return t.current.stickyItemsHeight=u,setTimeout(()=>{var r,f;(f=(r=t.current).onStickyItemsHeightChange)==null||f.call(r,u)},0),()=>{const r=t.current.stickyItemsHeight-c;t.current.stickyItemsHeight=r,setTimeout(()=>{var f,s;(s=(f=t.current).onStickyItemsHeightChange)==null||s.call(f,r)},0)}},[]);n.useEffect(()=>{t.current.fixedOffsetTop=h,t.current.defaultMode=e,setTimeout(()=>{i()},10)},[h,e,i]);const v=n.useCallback(c=>(o.current.push(c),o.current=A(o.current),i(),()=>{o.current=o.current.filter(u=>u!==c),i()}),[i]);n.useEffect(()=>(window.addEventListener("scroll",i,{passive:!0}),window.addEventListener("resize",i,{passive:!0}),()=>{window.removeEventListener("scroll",i),window.removeEventListener("resize",i)}),[i]);const B=n.useMemo(()=>T(k),[k]);return I.jsx(N.Provider,{value:{register:v,baseZIndex:B,updateStickyItemsHeight:_,fixedOffsetTop:h,mode:e},children:I.jsx("div",{...C,ref:p,className:"oe-sticky-container",children:l})})}function T(l){return typeof l>"u"?200:Math.max(Number(l)||0,20)}function A(l){return l.sort((h,k)=>{const E=h.el.getBoundingClientRect(),e=k.el.getBoundingClientRect();return E.top-e.top})}g.StickyContainer=Z,g.StickyItem=O,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-sticky-kit",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
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": [
|