react-sticky-kit 0.1.4 → 0.1.5
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 +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/react-sticky.es.js +86 -78
- package/dist/react-sticky.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ export default function Example() {
|
|
|
74
74
|
### `<StickyItem />`
|
|
75
75
|
| Prop | Type | Default | Description |
|
|
76
76
|
|---------|--------------------------------------|---------|---------------------------------------------|
|
|
77
|
-
| `mode` | `'replace' \| 'stack' \| 'none'` | | Sticky mode for this item (overrides
|
|
77
|
+
| `mode` | `'replace' \| 'stack' \| 'none'` | | Sticky mode for this item (overrides StickyContainer) |
|
|
78
78
|
|
|
79
79
|
## Sticky Modes
|
|
80
80
|
- **replace**: Only one sticky item is visible at a time, replacing the previous.
|
|
@@ -90,7 +90,11 @@ pnpm install
|
|
|
90
90
|
pnpm dev
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
Open [http://localhost:5173](http://localhost:5173) and switch between demo pages to explore all features and edge cases
|
|
93
|
+
Open [http://localhost:5173](http://localhost:5173) and switch between demo pages to explore all features and edge cases:
|
|
94
|
+
* [iOS Contact](http://localhost:5173/#ios-contact) a dead simple iOS contact clone
|
|
95
|
+
* [Mixed mode](http://localhost:5173/#mixed-mode) mix replace/stack/none mode
|
|
96
|
+
* [Nested](http://localhost:5173/#dynamic-height) nest sticky containers
|
|
97
|
+
* [Dynamic sticky items](http://localhost:5173/#nested) dynamic sticky items(add/remove)
|
|
94
98
|
|
|
95
99
|
## License
|
|
96
100
|
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export declare interface IStickyContainerProps extends default_2.HTMLAttributes<
|
|
|
30
30
|
export declare interface IStickyItemProps extends default_2.HTMLAttributes<HTMLDivElement> {
|
|
31
31
|
children: default_2.ReactNode;
|
|
32
32
|
/**
|
|
33
|
-
* Sticky mode for this item. Defaults to the
|
|
33
|
+
* Sticky mode for this item. Defaults to the StickyContainer's mode if not specified.
|
|
34
34
|
*/
|
|
35
35
|
mode?: IStickyMode;
|
|
36
36
|
}
|
package/dist/react-sticky.es.js
CHANGED
|
@@ -1,111 +1,119 @@
|
|
|
1
1
|
import { jsx as R } from "react/jsx-runtime";
|
|
2
|
-
import { createContext as b, useContext as
|
|
3
|
-
const x = 20,
|
|
4
|
-
function
|
|
5
|
-
return
|
|
2
|
+
import { createContext as b, useContext as T, useRef as S, useState as Z, useEffect as E, useCallback as w, useMemo as L } from "react";
|
|
3
|
+
const x = 20, N = 200, $ = b(null);
|
|
4
|
+
function _() {
|
|
5
|
+
return T($);
|
|
6
6
|
}
|
|
7
|
-
function M({ mode:
|
|
8
|
-
const e =
|
|
7
|
+
function M({ mode: c, children: o, className: p, ...k }) {
|
|
8
|
+
const e = _(), C = S(null), I = S(null), [r, t] = Z(!1), n = S({
|
|
9
9
|
fixedOffsetTop: (e == null ? void 0 : e.fixedOffsetTop) || 0,
|
|
10
10
|
isSticky: r,
|
|
11
11
|
baseZIndex: (e == null ? void 0 : e.baseZIndex) || x
|
|
12
12
|
});
|
|
13
|
-
return
|
|
14
|
-
const u =
|
|
15
|
-
if (!e || !f || !u ||
|
|
16
|
-
|
|
13
|
+
return n.current.baseZIndex = (e == null ? void 0 : e.baseZIndex) || x, n.current.fixedOffsetTop = (e == null ? void 0 : e.fixedOffsetTop) || 0, n.current.isSticky = r, E(() => {
|
|
14
|
+
const u = I.current, f = C.current, a = c || (e == null ? void 0 : e.mode);
|
|
15
|
+
if (!e || !f || !u || a === "none" || !a || !e.register) {
|
|
16
|
+
t(!1);
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
const
|
|
19
|
+
const l = {
|
|
20
20
|
el: f,
|
|
21
|
-
update: (
|
|
22
|
-
if (!
|
|
23
|
-
return
|
|
24
|
-
if (i <=
|
|
25
|
-
const
|
|
26
|
-
let v =
|
|
27
|
-
if (
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
21
|
+
update: (d, i, y, m, H) => {
|
|
22
|
+
if (!d)
|
|
23
|
+
return n.current.isSticky && t(!1), 0;
|
|
24
|
+
if (i <= y) {
|
|
25
|
+
const h = u.getBoundingClientRect().height;
|
|
26
|
+
let v = y;
|
|
27
|
+
if (a === "replace" && typeof m < "u") {
|
|
28
|
+
const g = m - (y + h);
|
|
29
|
+
if (g < 0 && (v = y + g, g + h < 0))
|
|
30
|
+
return n.current.isSticky && t(!1), 0;
|
|
31
31
|
}
|
|
32
|
-
return
|
|
32
|
+
return f.style.height = `${h}px`, n.current.isSticky || t(!0), u.style.top = `${v}px`, u.style.width = `${f.offsetWidth}px`, u.style.zIndex = `${n.current.baseZIndex + (a === "replace" ? -H : H)}`, a === "replace" ? 0 : h;
|
|
33
33
|
} else
|
|
34
|
-
|
|
34
|
+
t(!1);
|
|
35
35
|
return 0;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
-
return e.register(
|
|
39
|
-
}, [e == null ? void 0 : e.mode, e == null ? void 0 : e.register,
|
|
40
|
-
const u =
|
|
41
|
-
if (!r || !u || !f || !
|
|
38
|
+
return e.register(l);
|
|
39
|
+
}, [e == null ? void 0 : e.mode, e == null ? void 0 : e.register, c]), E(() => {
|
|
40
|
+
const u = C.current, f = I.current, a = e == null ? void 0 : e.updateStickyItemsHeight;
|
|
41
|
+
if (!r || !u || !f || !a)
|
|
42
42
|
return;
|
|
43
|
-
const
|
|
43
|
+
const s = a(f.getBoundingClientRect().height);
|
|
44
44
|
return () => {
|
|
45
|
-
O(u, ["height"]), O(f, ["top", "z-index", "width"]),
|
|
45
|
+
O(u, ["height"]), O(f, ["top", "z-index", "width"]), s();
|
|
46
46
|
};
|
|
47
|
-
}, [r, e == null ? void 0 : e.updateStickyItemsHeight]), /* @__PURE__ */ R("div", { className: "oe-sticky-item " + (
|
|
47
|
+
}, [r, e == null ? void 0 : e.updateStickyItemsHeight]), /* @__PURE__ */ R("div", { className: "oe-sticky-item " + (p || ""), ...k, ref: C, children: /* @__PURE__ */ R("div", { className: "oe-sticky-content " + (r ? "is-sticky" : ""), ref: I, children: o }) });
|
|
48
48
|
}
|
|
49
|
-
function O(
|
|
50
|
-
o.forEach((
|
|
51
|
-
|
|
49
|
+
function O(c, o) {
|
|
50
|
+
o.forEach((p) => {
|
|
51
|
+
c.style.removeProperty(p);
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
function P({
|
|
55
|
-
children:
|
|
55
|
+
children: c,
|
|
56
56
|
offsetTop: o = 0,
|
|
57
|
-
baseZIndex:
|
|
58
|
-
onStickyItemsHeightChange:
|
|
57
|
+
baseZIndex: p,
|
|
58
|
+
onStickyItemsHeightChange: k,
|
|
59
59
|
defaultMode: e = "replace",
|
|
60
|
-
...
|
|
60
|
+
...C
|
|
61
61
|
}) {
|
|
62
|
-
const
|
|
62
|
+
const I = S(null), r = S([]), t = S({
|
|
63
63
|
fixedOffsetTop: o,
|
|
64
64
|
defaultMode: e,
|
|
65
65
|
stickyItemsHeight: 0,
|
|
66
|
-
onStickyItemsHeightChange:
|
|
66
|
+
onStickyItemsHeightChange: k,
|
|
67
|
+
lastCanSticky: !1
|
|
67
68
|
});
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
69
|
+
t.current.onStickyItemsHeightChange = k;
|
|
70
|
+
const n = w(() => {
|
|
71
|
+
const s = I.current;
|
|
72
|
+
if (!s)
|
|
72
73
|
return;
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
const l = s.getBoundingClientRect(), d = t.current, i = d.fixedOffsetTop, y = d.stickyItemsHeight, m = !(l.top > i || l.bottom < i);
|
|
75
|
+
if (!m) {
|
|
76
|
+
t.current.lastCanSticky !== m && (s.classList.toggle("can-sticky", !1), r.current.forEach((g) => g.update(!1, 0, 0, 0, 0)), t.current.lastCanSticky = m);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
t.current.lastCanSticky = m, y > 0 && s.classList.toggle("can-sticky", !0);
|
|
80
|
+
let H = i, h = l.bottom - (i + y);
|
|
81
|
+
h > 0 && (h = 0);
|
|
82
|
+
const v = r.current.map((g) => g.el.getBoundingClientRect().top);
|
|
83
|
+
r.current.forEach((g, B) => {
|
|
84
|
+
H += g.update(m, v[B], H + h, v[B + 1], B);
|
|
79
85
|
});
|
|
80
|
-
}, []), u = w((
|
|
81
|
-
const
|
|
82
|
-
return
|
|
83
|
-
var
|
|
84
|
-
(i = (
|
|
86
|
+
}, []), u = w((s) => {
|
|
87
|
+
const l = t.current.stickyItemsHeight + s;
|
|
88
|
+
return t.current.stickyItemsHeight = l, setTimeout(() => {
|
|
89
|
+
var d, i;
|
|
90
|
+
(i = (d = t.current).onStickyItemsHeightChange) == null || i.call(d, l);
|
|
85
91
|
}, 0), () => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
var i,
|
|
89
|
-
(
|
|
92
|
+
const d = t.current.stickyItemsHeight - s;
|
|
93
|
+
t.current.stickyItemsHeight = d, setTimeout(() => {
|
|
94
|
+
var i, y;
|
|
95
|
+
(y = (i = t.current).onStickyItemsHeightChange) == null || y.call(i, d);
|
|
90
96
|
}, 0);
|
|
91
97
|
};
|
|
92
98
|
}, []);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}),
|
|
102
|
-
|
|
99
|
+
E(() => {
|
|
100
|
+
t.current.fixedOffsetTop = o, t.current.defaultMode = e, setTimeout(() => {
|
|
101
|
+
n();
|
|
102
|
+
}, 10);
|
|
103
|
+
}, [o, e, n]);
|
|
104
|
+
const f = w((s) => (r.current.push(s), r.current = A(r.current), n(), () => {
|
|
105
|
+
r.current = r.current.filter((l) => l !== s), n();
|
|
106
|
+
}), [n]);
|
|
107
|
+
E(() => (window.addEventListener("scroll", n, { passive: !0 }), window.addEventListener("resize", n, { passive: !0 }), () => {
|
|
108
|
+
window.removeEventListener("scroll", n), window.removeEventListener("resize", n);
|
|
109
|
+
}), [n]);
|
|
110
|
+
const a = L(() => z(p), [p]);
|
|
103
111
|
return /* @__PURE__ */ R(
|
|
104
112
|
$.Provider,
|
|
105
113
|
{
|
|
106
114
|
value: {
|
|
107
115
|
register: f,
|
|
108
|
-
baseZIndex:
|
|
116
|
+
baseZIndex: a,
|
|
109
117
|
updateStickyItemsHeight: u,
|
|
110
118
|
fixedOffsetTop: o,
|
|
111
119
|
mode: e
|
|
@@ -113,22 +121,22 @@ function P({
|
|
|
113
121
|
children: /* @__PURE__ */ R(
|
|
114
122
|
"div",
|
|
115
123
|
{
|
|
116
|
-
...
|
|
117
|
-
ref:
|
|
124
|
+
...C,
|
|
125
|
+
ref: I,
|
|
118
126
|
className: "oe-sticky-container",
|
|
119
|
-
children:
|
|
127
|
+
children: c
|
|
120
128
|
}
|
|
121
129
|
)
|
|
122
130
|
}
|
|
123
131
|
);
|
|
124
132
|
}
|
|
125
|
-
function z(
|
|
126
|
-
return typeof
|
|
133
|
+
function z(c) {
|
|
134
|
+
return typeof c > "u" ? N : Math.max(Number(c) || 0, x);
|
|
127
135
|
}
|
|
128
|
-
function A(
|
|
129
|
-
return
|
|
130
|
-
const
|
|
131
|
-
return
|
|
136
|
+
function A(c) {
|
|
137
|
+
return c.sort((o, p) => {
|
|
138
|
+
const k = o.el.getBoundingClientRect(), e = p.el.getBoundingClientRect();
|
|
139
|
+
return k.top - e.top;
|
|
132
140
|
});
|
|
133
141
|
}
|
|
134
142
|
export {
|
package/dist/react-sticky.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(g,k){typeof exports=="object"&&typeof module<"u"?k(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],k):(g=typeof globalThis<"u"?globalThis:g||self,k(g.ReactSticky={},g.jsxRuntime,g.React))})(this,function(g,k,s){"use strict";const B=s.createContext(null);function N(){return s.useContext(B)}const $="";function O({mode:u,children:o,className:m,...E}){const e=N(),R=s.useRef(null),C=s.useRef(null),[i,t]=s.useState(!1),n=s.useRef({fixedOffsetTop:(e==null?void 0:e.fixedOffsetTop)||0,isSticky:i,baseZIndex:(e==null?void 0:e.baseZIndex)||20});return n.current.baseZIndex=(e==null?void 0:e.baseZIndex)||20,n.current.fixedOffsetTop=(e==null?void 0:e.fixedOffsetTop)||0,n.current.isSticky=i,s.useEffect(()=>{const f=C.current,l=R.current,d=u||(e==null?void 0:e.mode);if(!e||!l||!f||d==="none"||!d||!e.register){t(!1);return}const a={el:l,update:(y,c,p,I,H)=>{if(!y)return n.current.isSticky&&t(!1),0;if(c<=p){const S=f.getBoundingClientRect().height;let _=p;if(d==="replace"&&typeof I<"u"){const h=I-(p+S);if(h<0&&(_=p+h,h+S<0))return n.current.isSticky&&t(!1),0}return l.style.height=`${S}px`,n.current.isSticky||t(!0),f.style.top=`${_}px`,f.style.width=`${l.offsetWidth}px`,f.style.zIndex=`${n.current.baseZIndex+(d==="replace"?-H:H)}`,d==="replace"?0:S}else t(!1);return 0}};return e.register(a)},[e==null?void 0:e.mode,e==null?void 0:e.register,u]),s.useEffect(()=>{const f=R.current,l=C.current,d=e==null?void 0:e.updateStickyItemsHeight;if(!i||!f||!l||!d)return;const r=d(l.getBoundingClientRect().height);return()=>{x(f,["height"]),x(l,["top","z-index","width"]),r()}},[i,e==null?void 0:e.updateStickyItemsHeight]),k.jsx("div",{className:"oe-sticky-item "+(m||""),...E,ref:R,children:k.jsx("div",{className:"oe-sticky-content "+(i?"is-sticky":""),ref:C,children:o})})}function x(u,o){o.forEach(m=>{u.style.removeProperty(m)})}function T({children:u,offsetTop:o=0,baseZIndex:m,onStickyItemsHeightChange:E,defaultMode:e="replace",...R}){const C=s.useRef(null),i=s.useRef([]),t=s.useRef({fixedOffsetTop:o,defaultMode:e,stickyItemsHeight:0,onStickyItemsHeightChange:E,lastCanSticky:!1});t.current.onStickyItemsHeightChange=E;const n=s.useCallback(()=>{const r=C.current;if(!r)return;const a=r.getBoundingClientRect(),y=t.current,c=y.fixedOffsetTop,p=y.stickyItemsHeight,I=!(a.top>c||a.bottom<c);if(!I){t.current.lastCanSticky!==I&&(r.classList.toggle("can-sticky",!1),i.current.forEach(h=>h.update(!1,0,0,0,0)),t.current.lastCanSticky=I);return}t.current.lastCanSticky=I,p>0&&r.classList.toggle("can-sticky",!0);let H=c,S=a.bottom-(c+p);S>0&&(S=0);const _=i.current.map(h=>h.el.getBoundingClientRect().top);i.current.forEach((h,v)=>{H+=h.update(I,_[v],H+S,_[v+1],v)})},[]),f=s.useCallback(r=>{const a=t.current.stickyItemsHeight+r;return t.current.stickyItemsHeight=a,setTimeout(()=>{var y,c;(c=(y=t.current).onStickyItemsHeightChange)==null||c.call(y,a)},0),()=>{const y=t.current.stickyItemsHeight-r;t.current.stickyItemsHeight=y,setTimeout(()=>{var c,p;(p=(c=t.current).onStickyItemsHeightChange)==null||p.call(c,y)},0)}},[]);s.useEffect(()=>{t.current.fixedOffsetTop=o,t.current.defaultMode=e,setTimeout(()=>{n()},10)},[o,e,n]);const l=s.useCallback(r=>(i.current.push(r),i.current=b(i.current),n(),()=>{i.current=i.current.filter(a=>a!==r),n()}),[n]);s.useEffect(()=>(window.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",n,{passive:!0}),()=>{window.removeEventListener("scroll",n),window.removeEventListener("resize",n)}),[n]);const d=s.useMemo(()=>Z(m),[m]);return k.jsx(B.Provider,{value:{register:l,baseZIndex:d,updateStickyItemsHeight:f,fixedOffsetTop:o,mode:e},children:k.jsx("div",{...R,ref:C,className:"oe-sticky-container",children:u})})}function Z(u){return typeof u>"u"?200:Math.max(Number(u)||0,20)}function b(u){return u.sort((o,m)=>{const E=o.el.getBoundingClientRect(),e=m.el.getBoundingClientRect();return E.top-e.top})}g.StickyContainer=T,g.StickyItem=O,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.oe-sticky-container
|
|
1
|
+
.oe-sticky-container{position:relative}.oe-sticky-container.can-sticky .oe-sticky-content.is-sticky{position:fixed}.oe-sticky-item{position:relative}.oe-sticky-content{will-change:top,position}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-sticky-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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": [
|