react-atom-trigger 2.0.3 → 2.0.6

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/MIGRATION.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  The biggest change is simple: `AtomTrigger` does its own observation now. In `v1.x` you had to pass scroll state and dimensions in from the outside. In `v2.x` you pass callbacks and, when needed, a root element.
6
6
 
7
+ The supported React range for `v2` remains the published peer range: React `16.8` through `19.x`.
8
+
7
9
  ## Before you start
8
10
 
9
11
  This is not just a prop rename release.
package/README.md CHANGED
@@ -36,12 +36,18 @@ npm install react-atom-trigger
36
36
  yarn add react-atom-trigger
37
37
  ```
38
38
 
39
+ The published package does not enforce a specific Node.js engine.
40
+ Runtime compatibility is determined by your React version, browser target and bundler setup.
41
+
42
+ The public React compatibility contract for `v2` is the published peer range: React `16.8` through
43
+ `19.x`.
44
+
39
45
  ## How it works
40
46
 
41
47
  `react-atom-trigger` uses a mixed approach.
42
48
 
43
49
  - Geometry is the real source of truth for `enter` and `leave`.
44
- - `IntersectionObserver` is only there to wake things up when the browser notices a layout shift.
50
+ - `IntersectionObserver` is only there to wake things up when the browser notices a nearby layout shift.
45
51
  - `rootMargin` logic is handled by the library itself, so it stays consistent and does not depend on native observer quirks.
46
52
 
47
53
  In practice this means `AtomTrigger` reacts to:
@@ -50,7 +56,7 @@ In practice this means `AtomTrigger` reacts to:
50
56
  - window resize
51
57
  - root resize
52
58
  - sentinel resize
53
- - layout shifts that move the observed element even if no scroll event happened
59
+ - nearby layout shifts that move the observed element even if no scroll event happened
54
60
 
55
61
  This is the main reason `v2` can support custom margin-aware behavior and still react to browser-driven layout changes.
56
62
 
@@ -129,6 +135,10 @@ element:
129
135
 
130
136
  If the ref never reaches a DOM node, child mode cannot observe anything.
131
137
 
138
+ If a custom child renders a placeholder first and only exposes its DOM node a moment later,
139
+ `AtomTrigger` waits briefly before showing the missing-ref warning so normal async mount flows do
140
+ not get flagged too early.
141
+
132
142
  ## API
133
143
 
134
144
  ```ts
@@ -160,6 +170,7 @@ interface AtomTriggerProps {
160
170
  - `threshold`: a number from `0` to `1`. It affects `enter`, not `leave`.
161
171
  - `root`: use a specific DOM element as the visible area.
162
172
  - `rootRef`: same idea as `root`, but better when the container is created in JSX. If both are passed, `rootRef` wins.
173
+ - `root` / `rootRef`: if you pass one explicitly but it is still `null`, observation pauses until that real root exists. It does not silently fall back to the viewport.
163
174
  - `rootMargin`: expand or shrink the effective root. String values use `IntersectionObserver`-style syntax. A four-number array is treated as `[top, right, bottom, left]` in pixels.
164
175
  - `className`: applies only to the internal sentinel.
165
176
 
@@ -218,14 +229,20 @@ useViewportSize(options?: {
218
229
  }): { width: number; height: number }
219
230
  ```
220
231
 
221
- Both hooks are SSR-safe. Default throttling is `16ms`.
232
+ Both hooks are SSR-safe and hydration-safe across the supported React range. During hydration, the first client render matches the server snapshot and then refreshes from the live source, including the compat path used when React does not expose `useSyncExternalStore`. Default throttling is `16ms`.
233
+
234
+ If you pass `enabled={false}`, the hook pauses its listeners but keeps the latest value it already knows.
235
+ It does not fake a reset back to zero.
236
+ When you enable it again, it reads from the source immediately and then continues updating as usual.
222
237
 
223
238
  ## Notes
224
239
 
225
240
  - In sentinel mode, `threshold` is usually only interesting if your sentinel has real width or height. The default sentinel is almost point-like.
241
+ - The internal sentinel intentionally uses a non-block display so it behaves like a point-like marker instead of stretching into a full-width placeholder.
226
242
  - Child mode needs exactly one top-level child and any custom component used there needs to pass the received ref through to a DOM element.
227
243
  - In React 19, a plain function component can also work in child mode if it passes the received `ref` prop through to a DOM element.
228
- - `rootMargin` is handled by the library geometry logic. `IntersectionObserver` is only used as a wake-up signal for layout shifts.
244
+ - If you pass `root` or `rootRef` explicitly and it is not ready yet, observation pauses instead of falling back to the viewport.
245
+ - `rootMargin` is handled by the library geometry logic. `IntersectionObserver` is only used as a nearby wake-up signal for layout shifts.
229
246
 
230
247
  ## Migration from v1
231
248
 
@@ -288,11 +305,17 @@ Quick way to tweak it in the browser.
288
305
  pnpm install
289
306
  pnpm lint
290
307
  pnpm test
308
+ pnpm test:coverage
291
309
  pnpm test:storybook
292
310
  pnpm build
293
311
  pnpm format:check
294
312
  ```
295
313
 
314
+ Coverage note:
315
+
316
+ - `pnpm test:coverage` is the official unit coverage signal used in CI and Codecov.
317
+ - `pnpm test:storybook` is a separate browser regression gate and is not merged into the official coverage number.
318
+
296
319
  ## Storybook (Static Build)
297
320
 
298
321
  Build:
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- import e from"react";const t=new Set;function n(){if(typeof process>`u`||!process.env)return null;let e=`production`;return e===`development`||e===`production`?e:null}function r(e){n()===`development`&&(t.has(e)||(t.add(e),typeof console<`u`&&console.warn&&console.warn(e)))}const i=Symbol.for(`react.forward_ref`),a=Symbol.for(`react.memo`);function o(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function s(e){if(typeof e==`string`||typeof e==`function`)return!0;if(typeof e!=`object`||!e)return!1;let t=e;return t.$$typeof===i?!0:t.$$typeof===a&&t.type?s(t.type):!1}function c(t,n,r,i){return t?n===1?r?i===e.Fragment?`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`:(!i||s(i),null):`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`:null}function l(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function u(e){return typeof e==`string`?e:l(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):(e==null||r(`[react-atom-trigger] Invalid rootMargin array ${JSON.stringify(e)}. Use exactly four finite numbers: [top, right, bottom, left]. Falling back to 0px.`),`0px`)}function d(e,t){let n=e.trim();if(!n||/^[+-]?0(?:\.0+)?$/.test(n))return 0;let i=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!i)return r(`[react-atom-trigger] Invalid rootMargin token "${n}". Use px, % or 0. Falling back to 0px.`),0;let[,a,o]=i,s=Number.parseFloat(a);return o===`%`?s/100*t:s}function f(e,t,n){let i=e.trim().split(/\s+/).filter(Boolean);if(i.length>4)return r(`[react-atom-trigger] Invalid rootMargin "${e}". Use 1 to 4 values in IntersectionObserver order. Falling back to 0px.`),{top:0,right:0,bottom:0,left:0};let[a=`0px`,o=a,s=a,c=o]=i;return{top:d(a,n),right:d(o,t),bottom:d(s,n),left:d(c,t)}}function p(e,t){let n=f(t,e.width,e.height);return new DOMRect(e.left-n.left,e.top-n.top,e.width+n.left+n.right,e.height+n.top+n.bottom)}function m(e){let t=e.width>0?e.width:1,n=e.height>0?e.height:1;return t===e.width&&n===e.height?e:new DOMRect(e.left,e.top,t,n)}function h(e,t){let n=Math.max(e.left,t.left),r=Math.max(e.top,t.top),i=Math.min(e.right,t.right),a=Math.min(e.bottom,t.bottom);return i<=n||a<=r?new DOMRect(0,0,0,0):new DOMRect(n,r,i-n,a-r)}function g(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function _(e){return Math.min(1,Math.max(0,e))}function v(e){return Array.isArray(e)?(r("[react-atom-trigger] `threshold` expects a single number in v2. Using the first finite numeric entry."),_(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0)):e==null?0:typeof e!=`number`||!Number.isFinite(e)?(r("[react-atom-trigger] `threshold` must be a finite number between 0 and 1. Falling back to 0."),0):((e<0||e>1)&&r("[react-atom-trigger] `threshold` should be between 0 and 1. Values are clamped."),_(e))}function y(e,t){if(!e)return`unknown`;let n=t.left-e.left,r=t.top-e.top;return n===0&&r===0?`stationary`:Math.abs(r)>=Math.abs(n)?r<0?`up`:`down`:n<0?`left`:`right`}function b(e){if(e.isIntersecting)return`inside`;let t=e.boundingClientRect,n=e.rootBounds?.top??0,r=e.rootBounds?.bottom??window.innerHeight,i=e.rootBounds?.left??0,a=e.rootBounds?.right??window.innerWidth;return t.bottom<=n?`above`:t.top>=r?`below`:t.right<=i?`left`:t.left>=a?`right`:`outside`}const x=new WeakMap;function S(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function C(e){return e===window||typeof Window<`u`&&e instanceof Window}function w(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function T(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function E(e){e.previousTriggerActive=void 0,e.previousRect=null}function D(e,t,n,r){let i=m(e.node.getBoundingClientRect()),a=p(t,e.rootMargin),o=h(i,a),s=g(i,o),c=s>0,l=e.previousTriggerActive,u=l===!0||e.threshold===0?c:s>=e.threshold,d=e.previousRect&&(n===`root-change`||r)?`stationary`:y(e.previousRect,i);e.previousRect=i,e.previousTriggerActive=u;let f=Date.now(),_={target:e.node,rootBounds:a,boundingClientRect:i,intersectionRect:o,isIntersecting:c,intersectionRatio:s,source:`geometry`},v=l===void 0;if(v&&(!e.fireOnInitialVisible||!u)||l===u)return;let x=u?`enter`:`leave`;if(!w(x,e.counts,e.once,e.oncePerDirection))return;let S=x===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=S;let C={type:x,isInitial:v,entry:_,counts:S,movementDirection:d,position:b(_),timestamp:f};e.onEvent?.(C),x===`enter`?e.onEnter?.(C):e.onLeave?.(C),T(e)&&e.dispose?.()}function O(e){let t={registrations:new Set,rafId:0,pendingSampleCause:null,previousBaseRootBounds:null,resizeObserver:null,intersectionObserver:null,queueSample:()=>{},cleanup:()=>{}},n=()=>{if(t.rafId=0,t.registrations.size===0){t.pendingSampleCause=null;return}let n=t.pendingSampleCause??`geometry-change`;t.pendingSampleCause=null;let r=C(e)?S():e.getBoundingClientRect(),i=t.previousBaseRootBounds!==null&&(t.previousBaseRootBounds.top!==r.top||t.previousBaseRootBounds.left!==r.left||t.previousBaseRootBounds.width!==r.width||t.previousBaseRootBounds.height!==r.height);for(let e of t.registrations)D(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{if((t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId!==0)return;t.rafId=-1;let r=window.requestAnimationFrame(()=>{t.rafId=0,n()});t.rafId===-1&&(t.rafId=r)},i=()=>{r(`scroll`)},a=()=>{r(`root-change`)};return e.addEventListener(`scroll`,i,{passive:!0}),window.addEventListener(`resize`,a),typeof ResizeObserver<`u`&&(t.resizeObserver=new ResizeObserver(a),C(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:C(e)?null:e,rootMargin:`200% 200% 200% 200%`,threshold:0})),t.queueSample=r,t.cleanup=()=>{t.rafId!==0&&(cancelAnimationFrame(t.rafId),t.rafId=0),e.removeEventListener(`scroll`,i),window.removeEventListener(`resize`,a),t.resizeObserver?.disconnect(),t.intersectionObserver?.disconnect(),t.pendingSampleCause=null,t.previousBaseRootBounds=null},t}function k(e){let t=x.get(e);if(t)return t;let n=O(e);return x.set(e,n),n}function A(e,t){let n=k(e),r=!1;n.registrations.add(t),n.resizeObserver?.observe(t.node),n.intersectionObserver?.observe(t.node),n.queueSample();let i=()=>{r||(r=!0,n.registrations.delete(t),n.resizeObserver?.unobserve(t.node),n.intersectionObserver?.unobserve(t.node),t.dispose=void 0,n.registrations.size===0&&(n.cleanup(),x.delete(e)))};return t.dispose=i,i}function j(e,t){return t?t.current:e||(typeof window>`u`?null:window)}const M={display:`table`},N=({onEnter:t,onLeave:n,onEvent:i,children:a,once:s=!1,oncePerDirection:l=!1,fireOnInitialVisible:d=!1,disabled:f=!1,threshold:p=0,root:m=null,rootRef:h,rootMargin:g=`0px`,className:_})=>{let y=e.useRef(null),[b,x]=e.useState(null),S=e.useRef(null),C=e.useRef(null),w=e.useRef(null),T=e.useRef(null),D=u(g),O=v(p),k=a!=null,N=e.Children.count(a),P=N===1&&e.isValidElement(a)?a:null,F=c(k,N,P,P?P.type:null),I=F||!P?null:P,L=I?.props.ref,R=e.useCallback(e=>{if(o(L,e),e===null){S.current=null,x(e=>e===null?e:null);return}if(e instanceof Element){S.current=e,x(t=>t===e?t:e);return}S.current=null,x(e=>e===null?e:null),r(`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`)},[L]);return e.useEffect(()=>{r(`[react-atom-trigger] v2 uses a new internal observation engine. If you upgraded from v1.x, verify trigger behavior for timing, threshold and rootMargin.`)},[]),e.useEffect(()=>{k&&_&&r("[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.")},[_,k]),e.useEffect(()=>{F&&r(F)},[F]),e.useEffect(()=>{if(typeof window>`u`||!k||!I||F||b)return;let e=window.setTimeout(()=>{S.current||r(`[react-atom-trigger] Child mode expects a DOM element or a component that forwards its ref to a DOM element. Observation is disabled for this render.`)},0);return()=>{window.clearTimeout(e)}},[b,I,k,F]),e.useEffect(()=>{let e=C.current;e&&(e.onEnter=t,e.onLeave=n,e.onEvent=i)},[t,n,i]),e.useEffect(()=>{if(typeof window>`u`)return;let e=k?b:y.current,r=j(m,h);if(!e){C.current&&E(C.current),w.current?.(),w.current=null,T.current=null;return}C.current?(C.current.node=e,C.current.rootMargin=D,C.current.threshold=O,C.current.once=s,C.current.oncePerDirection=l,C.current.fireOnInitialVisible=d):C.current={node:e,rootMargin:D,threshold:O,once:s,oncePerDirection:l,fireOnInitialVisible:d,onEnter:t,onLeave:n,onEvent:i,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}};let a=C.current;if(f||!r){E(a),w.current?.(),w.current=null,T.current=null;return}let o=T.current,c={node:e,target:r,rootMargin:D,threshold:O,once:s,oncePerDirection:l,fireOnInitialVisible:d};(!o||o.node!==c.node||o.target!==c.target||o.rootMargin!==c.rootMargin||o.threshold!==c.threshold||o.once!==c.once||o.oncePerDirection!==c.oncePerDirection||o.fireOnInitialVisible!==c.fireOnInitialVisible)&&(E(a),w.current?.(),w.current=A(r,a),T.current=c)},[f,D,O,s,l,d,b,m,h?.current,k]),e.useEffect(()=>()=>{w.current?.(),w.current=null,T.current=null},[]),k?I?e.cloneElement(I,{ref:R}):e.createElement(e.Fragment,null,a):e.createElement(`div`,{ref:y,style:M,className:_})},P={x:0,y:0},F=typeof window>`u`?e.useEffect:e.useLayoutEffect;function I(e,t){let n=null,r=null,i=()=>{n&&(clearTimeout(n),n=null),r=Date.now(),e()};return{schedule:()=>{if(t<=0){i();return}let e=Date.now();if(r===null||e-r>=t){i();return}n||(n=setTimeout(()=>{i()},t-(e-r)))},cancel:()=>{n&&(clearTimeout(n),n=null)}}}function L(){return typeof window>`u`?{width:0,height:0}:{width:window.innerWidth,height:window.innerHeight}}function R(e){return!!(e&&typeof e==`object`&&!(typeof Window<`u`&&e instanceof Window)&&`current`in e)}function z(e){return R(e)?e.current:e||(typeof window>`u`?null:window)}function B(e){return e===window||typeof Window<`u`&&e instanceof Window}function V(e){if(B(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function H(t){let[n,r]=e.useState(L);return e.useEffect(()=>{if(typeof window>`u`||t?.enabled===!1)return;let e=t?.throttleMs??16;r(L());let n=I(()=>{r(L())},e);return window.addEventListener(`resize`,n.schedule,{passive:t?.passive}),()=>{n.cancel(),window.removeEventListener(`resize`,n.schedule)}},[t?.enabled,t?.passive,t?.throttleMs]),n}function U(t){let n=t?.target,r=R(n),[i,a]=e.useState(()=>{let e=z(n);return e?V(e):P}),[o,s]=e.useState(()=>r?z(n):null);F(()=>{if(!r)return;let e=z(n);s(t=>t===e?t:e)});let c=r?o:z(n);return e.useEffect(()=>{if(t?.enabled===!1){a(P);return}if(!c){a(P);return}let e=t?.throttleMs??16;a(V(c));let n=I(()=>{a(V(c))},e);return c.addEventListener(`scroll`,n.schedule,{passive:t?.passive}),()=>{n.cancel(),c.removeEventListener(`scroll`,n.schedule)}},[t?.enabled,t?.passive,t?.throttleMs,c]),i}export{N as AtomTrigger,U as useScrollPosition,H as useViewportSize};
1
+ import e from"react";const t=new Set;function n(){if(typeof process>`u`||!process.env)return null;let e=`production`;return e===`development`||e===`production`?e:null}function r(e){return(Object.prototype.hasOwnProperty.call(e??{},`nodeEnv`)?e?.nodeEnv??null:n())===`development`}function i(e){r()&&(t.has(e)||(t.add(e),typeof console<`u`&&console.warn&&console.warn(e)))}function a(e){return!!(e&&typeof e==`object`&&`nodeType`in e&&e.nodeType===1&&`getBoundingClientRect`in e&&typeof e.getBoundingClientRect==`function`&&`addEventListener`in e&&typeof e.addEventListener==`function`&&`removeEventListener`in e&&typeof e.removeEventListener==`function`)}function o(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function s(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function c(e){if(!e||typeof e!=`object`&&typeof e!=`function`)return;let t=Object.getOwnPropertyDescriptor(e,`ref`);if(!(!t||!(`value`in t)))return t.value}function l(e){if(!e)return;let t=c(e.props);return t===void 0?c(e):t}function u(t,n,r){return t?n===1?r?r.type===e.Fragment?`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`:null:`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`:null}function d({originalChildRef:t,hasObservedChild:n,invalidChildWarning:r,shouldWarnAboutMissingDomRef:o}){let[c,l]=e.useState(null),u=e.useRef(null),d=e.useCallback(()=>{u.current=null,l(e=>e===null?e:null)},[]),f=e.useCallback(e=>{if(s(t,e),e===null){d();return}if(a(e)){u.current=e,l(t=>t===e?t:e);return}d(),i(`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`)},[d,t]);return e.useEffect(()=>{if(typeof window>`u`||!(n&&!r&&!c&&o))return;let e=window.setTimeout(()=>{u.current||i(`[react-atom-trigger] Child mode expects a DOM element or a component that forwards its ref to a DOM element. Observation is disabled for this render.`)},16);return()=>{window.clearTimeout(e)}},[n,r,c,o]),{childNode:c,attachObservedChildRef:f}}function f(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function p(e){return typeof e==`string`?e:f(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):(e==null||i(`[react-atom-trigger] Invalid rootMargin array ${JSON.stringify(e)}. Use exactly four finite numbers: [top, right, bottom, left]. Falling back to 0px.`),`0px`)}function m(e,t){let n=e.trim();if(!n||/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return i(`[react-atom-trigger] Invalid rootMargin token "${n}". Use px, % or 0. Falling back to 0px.`),0;let[,a,o]=r,s=Number.parseFloat(a);return o===`%`?s/100*t:s}function h(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return i(`[react-atom-trigger] Invalid rootMargin "${e}". Use 1 to 4 values in IntersectionObserver order. Falling back to 0px.`),{top:0,right:0,bottom:0,left:0};let[a=`0px`,o=a,s=a,c=o]=r;return{top:m(a,n),right:m(o,t),bottom:m(s,n),left:m(c,t)}}function g(e,t){let n=h(t,e.width,e.height);return new DOMRect(e.left-n.left,e.top-n.top,e.width+n.left+n.right,e.height+n.top+n.bottom)}function _(e){let t=e.width>0?e.width:1,n=e.height>0?e.height:1;return t===e.width&&n===e.height?e:new DOMRect(e.left,e.top,t,n)}function v(e,t){let n=Math.max(e.left,t.left),r=Math.max(e.top,t.top),i=Math.min(e.right,t.right),a=Math.min(e.bottom,t.bottom);return i<=n||a<=r?new DOMRect(0,0,0,0):new DOMRect(n,r,i-n,a-r)}function y(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function b(e){return Math.min(1,Math.max(0,e))}function x(e){return Array.isArray(e)?(i("[react-atom-trigger] `threshold` expects a single number in v2. Using the first finite numeric entry."),b(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0)):e==null?0:typeof e!=`number`||!Number.isFinite(e)?(i("[react-atom-trigger] `threshold` must be a finite number between 0 and 1. Falling back to 0."),0):((e<0||e>1)&&i("[react-atom-trigger] `threshold` should be between 0 and 1. Values are clamped."),b(e))}function S(e,t){if(!e)return`unknown`;let n=t.left-e.left,r=t.top-e.top;return n===0&&r===0?`stationary`:Math.abs(r)>=Math.abs(n)?r<0?`up`:`down`:n<0?`left`:`right`}function C(e){if(e.isIntersecting)return`inside`;let t=e.boundingClientRect,n=e.rootBounds?.top??0,r=e.rootBounds?.bottom??window.innerHeight,i=e.rootBounds?.left??0,a=e.rootBounds?.right??window.innerWidth;return t.bottom<=n?`above`:t.top>=r?`below`:t.right<=i?`left`:t.left>=a?`right`:`outside`}function w(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function T(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function E(e){e.previousTriggerActive=void 0,e.previousRect=null}function D(e,t,n,r){let i=_(e.node.getBoundingClientRect()),a=g(t,e.rootMargin),o=v(i,a),s=y(i,o),c=s>0,l=e.previousTriggerActive,u=l===!0||e.threshold===0?c:s>=e.threshold,d=e.previousRect&&(n===`root-change`||r)?`stationary`:S(e.previousRect,i);e.previousRect=i,e.previousTriggerActive=u;let f=Date.now(),p={target:e.node,rootBounds:a,boundingClientRect:i,intersectionRect:o,isIntersecting:c,intersectionRatio:s,source:`geometry`},m=l===void 0;if(m&&(!e.fireOnInitialVisible||!u)||l===u)return;let h=u?`enter`:`leave`;if(!w(h,e.counts,e.once,e.oncePerDirection))return;let b=h===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=b;let x={type:h,isInitial:m,entry:p,counts:b,movementDirection:d,position:C(p),timestamp:f};e.onEvent?.(x),h===`enter`?e.onEnter?.(x):e.onLeave?.(x),T(e)&&e.dispose?.()}const O=new WeakMap;function k(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function A(e){return e===window||o(e)}function j(e){let t={registrations:new Set,rafId:0,pendingSampleCause:null,previousBaseRootBounds:null,resizeObserver:null,intersectionObserver:null,queueSample:()=>{},cleanup:()=>{}},n=()=>{if(t.rafId=0,t.registrations.size===0){t.pendingSampleCause=null;return}let n=t.pendingSampleCause??`geometry-change`;t.pendingSampleCause=null;let r=A(e)?k():e.getBoundingClientRect(),i=t.previousBaseRootBounds!==null&&(t.previousBaseRootBounds.top!==r.top||t.previousBaseRootBounds.left!==r.left||t.previousBaseRootBounds.width!==r.width||t.previousBaseRootBounds.height!==r.height);for(let e of t.registrations)D(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{if((t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId!==0)return;t.rafId=-1;let r=window.requestAnimationFrame(()=>{t.rafId=0,n()});t.rafId===-1&&(t.rafId=r)},i=()=>{r(`scroll`)},a=()=>{r(`root-change`)};return e.addEventListener(`scroll`,i,{passive:!0}),window.addEventListener(`resize`,a),typeof ResizeObserver<`u`&&(t.resizeObserver=new ResizeObserver(a),A(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:A(e)?null:e,rootMargin:`200% 200% 200% 200%`,threshold:0})),t.queueSample=r,t.cleanup=()=>{t.rafId!==0&&(cancelAnimationFrame(t.rafId),t.rafId=0),e.removeEventListener(`scroll`,i),window.removeEventListener(`resize`,a),t.resizeObserver?.disconnect(),t.intersectionObserver?.disconnect(),t.pendingSampleCause=null,t.previousBaseRootBounds=null},t}function ee(e){let t=O.get(e);if(t)return t;let n=j(e);return O.set(e,n),n}function te(e,t){let n=ee(e),r=!1,i=t.node;n.registrations.add(t),n.resizeObserver?.observe(i),n.intersectionObserver?.observe(i),n.queueSample();let a=()=>{r||(r=!0,n.registrations.delete(t),n.resizeObserver?.unobserve(i),n.intersectionObserver?.unobserve(i),t.dispose=void 0,n.registrations.size===0&&(n.cleanup(),O.delete(e)))};return t.dispose=a,a}function ne(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function M(e,t){e.node=t.node,e.rootMargin=t.rootMargin,e.threshold=t.threshold,e.once=t.once,e.oncePerDirection=t.oncePerDirection,e.fireOnInitialVisible=t.fireOnInitialVisible}function re(e,t){e.onEnter=t.onEnter,e.onLeave=t.onLeave,e.onEvent=t.onEvent}function N(e){e.dispose?.(),e.dispose=null,e.binding=null}function ie(e){return{node:e.node,rootMargin:e.rootMargin,threshold:e.threshold,once:e.once,oncePerDirection:e.oncePerDirection,fireOnInitialVisible:e.fireOnInitialVisible}}function ae(e,t){return!!(e&&e.node===t.node&&e.target===t.target&&e.rootMargin===t.rootMargin&&e.threshold===t.threshold&&e.once===t.once&&e.oncePerDirection===t.oncePerDirection&&e.fireOnInitialVisible===t.fireOnInitialVisible)}function P(e,t){return{registration:ne(e,t),binding:null,dispose:null}}function F(e,t){re(e.registration,t)}function I(e,t){let n=e.registration;if(!t.node){E(n),N(e);return}let r=ie({node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible});if(t.disabled||!t.target){N(e),M(n,r),E(n);return}let i={...r,target:t.target};if(ae(e.binding,i)){M(n,r);return}E(n),N(e),M(n,r),e.dispose=te(t.target,n),e.binding=i}function L(e){N(e)}function R(e){let t=e.kind===`rootRef`?"[react-atom-trigger] `rootRef.current` must resolve to a real DOM element. Observation is paused until it does.":"[react-atom-trigger] `root` must be a real DOM element when provided. Observation is paused until it is.",{target:n}=e;return n==null?null:a(n)?n:(i(t),null)}function z(t){let n=t!==void 0,[r,i]=e.useState(()=>n?t.current:null);return e.useEffect(()=>{if(!n)return;let e=t.current;i(t=>t===e?t:e)}),n?r:void 0}function B(e){switch(e.kind){case`rootRef`:case`root`:return R(e);case`viewport`:return typeof window>`u`?null:window}}const V={display:`table`},oe=({onEnter:t,onLeave:n,onEvent:r,children:a,once:o=!1,oncePerDirection:s=!1,fireOnInitialVisible:c=!1,disabled:f=!1,threshold:m=0,root:h,rootRef:g,rootMargin:_=`0px`,className:v})=>{let y=e.useRef(null),b=e.useRef(null),S=z(g),C=p(_),w=x(m),T=a!=null,E=e.Children.count(a),D=E===1&&e.isValidElement(a)?a:null,O=u(T,E,D),k=O||!D?null:D,{childNode:A,attachObservedChildRef:j}=d({originalChildRef:l(k),hasObservedChild:T,invalidChildWarning:O,shouldWarnAboutMissingDomRef:k!==null});return e.useEffect(()=>{T&&v&&i("[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.")},[v,T]),e.useEffect(()=>{O&&i(O)},[O]),e.useEffect(()=>{o&&s&&i("[react-atom-trigger] `once` and `oncePerDirection` were both provided. `once` takes precedence.")},[o,s]),e.useEffect(()=>{let e=b.current;e&&F(e,{onEnter:t,onLeave:n,onEvent:r})},[t,n,r]),e.useEffect(()=>{if(typeof window>`u`)return;let e=T?A:y.current,i=B(g===void 0?h===void 0?{kind:`viewport`}:{kind:`root`,target:h}:{kind:`rootRef`,target:S});if(!e){b.current&&I(b.current,{disabled:!1,node:null,target:i,rootMargin:C,threshold:w,once:o,oncePerDirection:s,fireOnInitialVisible:c});return}b.current||(b.current=P({node:e,rootMargin:C,threshold:w,once:o,oncePerDirection:s,fireOnInitialVisible:c},{onEnter:t,onLeave:n,onEvent:r})),I(b.current,{disabled:f,node:e,target:i,rootMargin:C,threshold:w,once:o,oncePerDirection:s,fireOnInitialVisible:c})},[f,C,w,o,s,c,A,h,g,S,T]),e.useEffect(()=>()=>{b.current&&(L(b.current),b.current=null)},[]),T?k?e.cloneElement(k,{ref:j}):e.createElement(e.Fragment,null,a):e.createElement(`div`,{ref:y,style:V,className:v})},H=e.useSyncExternalStore,se=typeof window>`u`?e.useEffect:e.useLayoutEffect;function U(t,n,r){if(H)return H(t,n,r);let[i,a]=e.useState(()=>r()),o=e.useRef(i);return se(()=>{let e=()=>{let e=n();Object.is(o.current,e)||(o.current=e,a(e))};return e(),t(e)},[t,n]),i}function W(e,t,n){return n(e.current,t)?e.current:(e.current=t,t)}const G={x:0,y:0},K={width:0,height:0},ce=typeof window>`u`?e.useEffect:e.useLayoutEffect;function q(e,t){let n=null,r=null,i=()=>{n&&(clearTimeout(n),n=null),r=Date.now(),e()};return{schedule:()=>{if(t<=0){i();return}let e=Date.now();if(r===null||e-r>=t){i();return}n||(n=setTimeout(()=>{i()},t-(e-r)))},cancel:()=>{n&&(clearTimeout(n),n=null)}}}function J(){return typeof window>`u`?K:{width:window.innerWidth,height:window.innerHeight}}function Y(e){return!!(e&&typeof e==`object`&&!o(e)&&`current`in e)}function X(e){return Y(e)?e.current:e||(typeof window>`u`?null:window)}function le(e){return e===window||o(e)}function Z(e){if(le(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function ue(e){let t=X(e);return t?Z(t):G}function Q(e,t){return e.x===t.x&&e.y===t.y}function $(e,t){return e.width===t.width&&e.height===t.height}function de(t){let n=t?.enabled!==!1,r=t?.passive,i=t?.throttleMs??16,a=e.useRef(J()),o=e.useCallback(()=>typeof window>`u`?K:n?W(a,J(),$):a.current,[n]);return U(e.useCallback(e=>{if(typeof window>`u`||!n)return()=>{};let t=q(()=>{let t=J();$(a.current,t)||(a.current=t,e())},i);return window.addEventListener(`resize`,t.schedule,{passive:r}),()=>{t.cancel(),window.removeEventListener(`resize`,t.schedule)}},[n,r,i]),o,()=>K)}function fe(t){let n=t?.target,r=Y(n),i=t?.enabled!==!1,a=t?.passive,o=t?.throttleMs??16,s=e.useRef(ue(n)),[c,l]=e.useState(()=>r?X(n):null);ce(()=>{if(!r)return;let e=X(n);l(t=>t===e?t:e)});let u=r?c:X(n),d=e.useCallback(()=>i?u?W(s,Z(u),Q):W(s,G,Q):s.current,[i,u]);return U(e.useCallback(e=>{if(!i||!u)return()=>{};let t=q(()=>{let t=Z(u);Q(s.current,t)||(s.current=t,e())},o);return u.addEventListener(`scroll`,t.schedule,{passive:a}),()=>{t.cancel(),u.removeEventListener(`scroll`,t.schedule)}},[i,a,u,o]),d,()=>G)}export{oe as AtomTrigger,fe as useScrollPosition,de as useViewportSize};
package/lib/index.umd.js CHANGED
@@ -1 +1 @@
1
- (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.reactAtomTrigger={},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?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t);let l=new Set;function u(){if(typeof process>`u`||!process.env)return null;let e=`production`;return e===`development`||e===`production`?e:null}function d(e){u()===`development`&&(l.has(e)||(l.add(e),typeof console<`u`&&console.warn&&console.warn(e)))}let f=Symbol.for(`react.forward_ref`),p=Symbol.for(`react.memo`);function m(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function h(e){if(typeof e==`string`||typeof e==`function`)return!0;if(typeof e!=`object`||!e)return!1;let t=e;return t.$$typeof===f?!0:t.$$typeof===p&&t.type?h(t.type):!1}function g(e,n,r,i){return e?n===1?r?i===t.default.Fragment?`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`:(!i||h(i),null):`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`:null}function _(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function v(e){return typeof e==`string`?e:_(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):(e==null||d(`[react-atom-trigger] Invalid rootMargin array ${JSON.stringify(e)}. Use exactly four finite numbers: [top, right, bottom, left]. Falling back to 0px.`),`0px`)}function y(e,t){let n=e.trim();if(!n||/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return d(`[react-atom-trigger] Invalid rootMargin token "${n}". Use px, % or 0. Falling back to 0px.`),0;let[,i,a]=r,o=Number.parseFloat(i);return a===`%`?o/100*t:o}function b(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return d(`[react-atom-trigger] Invalid rootMargin "${e}". Use 1 to 4 values in IntersectionObserver order. Falling back to 0px.`),{top:0,right:0,bottom:0,left:0};let[i=`0px`,a=i,o=i,s=a]=r;return{top:y(i,n),right:y(a,t),bottom:y(o,n),left:y(s,t)}}function x(e,t){let n=b(t,e.width,e.height);return new DOMRect(e.left-n.left,e.top-n.top,e.width+n.left+n.right,e.height+n.top+n.bottom)}function S(e){let t=e.width>0?e.width:1,n=e.height>0?e.height:1;return t===e.width&&n===e.height?e:new DOMRect(e.left,e.top,t,n)}function C(e,t){let n=Math.max(e.left,t.left),r=Math.max(e.top,t.top),i=Math.min(e.right,t.right),a=Math.min(e.bottom,t.bottom);return i<=n||a<=r?new DOMRect(0,0,0,0):new DOMRect(n,r,i-n,a-r)}function w(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function T(e){return Math.min(1,Math.max(0,e))}function E(e){return Array.isArray(e)?(d("[react-atom-trigger] `threshold` expects a single number in v2. Using the first finite numeric entry."),T(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0)):e==null?0:typeof e!=`number`||!Number.isFinite(e)?(d("[react-atom-trigger] `threshold` must be a finite number between 0 and 1. Falling back to 0."),0):((e<0||e>1)&&d("[react-atom-trigger] `threshold` should be between 0 and 1. Values are clamped."),T(e))}function D(e,t){if(!e)return`unknown`;let n=t.left-e.left,r=t.top-e.top;return n===0&&r===0?`stationary`:Math.abs(r)>=Math.abs(n)?r<0?`up`:`down`:n<0?`left`:`right`}function O(e){if(e.isIntersecting)return`inside`;let t=e.boundingClientRect,n=e.rootBounds?.top??0,r=e.rootBounds?.bottom??window.innerHeight,i=e.rootBounds?.left??0,a=e.rootBounds?.right??window.innerWidth;return t.bottom<=n?`above`:t.top>=r?`below`:t.right<=i?`left`:t.left>=a?`right`:`outside`}let k=new WeakMap;function A(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function j(e){return e===window||typeof Window<`u`&&e instanceof Window}function M(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function N(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function P(e){e.previousTriggerActive=void 0,e.previousRect=null}function F(e,t,n,r){let i=S(e.node.getBoundingClientRect()),a=x(t,e.rootMargin),o=C(i,a),s=w(i,o),c=s>0,l=e.previousTriggerActive,u=l===!0||e.threshold===0?c:s>=e.threshold,d=e.previousRect&&(n===`root-change`||r)?`stationary`:D(e.previousRect,i);e.previousRect=i,e.previousTriggerActive=u;let f=Date.now(),p={target:e.node,rootBounds:a,boundingClientRect:i,intersectionRect:o,isIntersecting:c,intersectionRatio:s,source:`geometry`},m=l===void 0;if(m&&(!e.fireOnInitialVisible||!u)||l===u)return;let h=u?`enter`:`leave`;if(!M(h,e.counts,e.once,e.oncePerDirection))return;let g=h===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=g;let _={type:h,isInitial:m,entry:p,counts:g,movementDirection:d,position:O(p),timestamp:f};e.onEvent?.(_),h===`enter`?e.onEnter?.(_):e.onLeave?.(_),N(e)&&e.dispose?.()}function I(e){let t={registrations:new Set,rafId:0,pendingSampleCause:null,previousBaseRootBounds:null,resizeObserver:null,intersectionObserver:null,queueSample:()=>{},cleanup:()=>{}},n=()=>{if(t.rafId=0,t.registrations.size===0){t.pendingSampleCause=null;return}let n=t.pendingSampleCause??`geometry-change`;t.pendingSampleCause=null;let r=j(e)?A():e.getBoundingClientRect(),i=t.previousBaseRootBounds!==null&&(t.previousBaseRootBounds.top!==r.top||t.previousBaseRootBounds.left!==r.left||t.previousBaseRootBounds.width!==r.width||t.previousBaseRootBounds.height!==r.height);for(let e of t.registrations)F(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{if((t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId!==0)return;t.rafId=-1;let r=window.requestAnimationFrame(()=>{t.rafId=0,n()});t.rafId===-1&&(t.rafId=r)},i=()=>{r(`scroll`)},a=()=>{r(`root-change`)};return e.addEventListener(`scroll`,i,{passive:!0}),window.addEventListener(`resize`,a),typeof ResizeObserver<`u`&&(t.resizeObserver=new ResizeObserver(a),j(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:j(e)?null:e,rootMargin:`200% 200% 200% 200%`,threshold:0})),t.queueSample=r,t.cleanup=()=>{t.rafId!==0&&(cancelAnimationFrame(t.rafId),t.rafId=0),e.removeEventListener(`scroll`,i),window.removeEventListener(`resize`,a),t.resizeObserver?.disconnect(),t.intersectionObserver?.disconnect(),t.pendingSampleCause=null,t.previousBaseRootBounds=null},t}function L(e){let t=k.get(e);if(t)return t;let n=I(e);return k.set(e,n),n}function R(e,t){let n=L(e),r=!1;n.registrations.add(t),n.resizeObserver?.observe(t.node),n.intersectionObserver?.observe(t.node),n.queueSample();let i=()=>{r||(r=!0,n.registrations.delete(t),n.resizeObserver?.unobserve(t.node),n.intersectionObserver?.unobserve(t.node),t.dispose=void 0,n.registrations.size===0&&(n.cleanup(),k.delete(e)))};return t.dispose=i,i}function z(e,t){return t?t.current:e||(typeof window>`u`?null:window)}let B={display:`table`},V=({onEnter:e,onLeave:n,onEvent:r,children:i,once:a=!1,oncePerDirection:o=!1,fireOnInitialVisible:s=!1,disabled:c=!1,threshold:l=0,root:u=null,rootRef:f,rootMargin:p=`0px`,className:h})=>{let _=t.default.useRef(null),[y,b]=t.default.useState(null),x=t.default.useRef(null),S=t.default.useRef(null),C=t.default.useRef(null),w=t.default.useRef(null),T=v(p),D=E(l),O=i!=null,k=t.default.Children.count(i),A=k===1&&t.default.isValidElement(i)?i:null,j=g(O,k,A,A?A.type:null),M=j||!A?null:A,N=M?.props.ref,F=t.default.useCallback(e=>{if(m(N,e),e===null){x.current=null,b(e=>e===null?e:null);return}if(e instanceof Element){x.current=e,b(t=>t===e?t:e);return}x.current=null,b(e=>e===null?e:null),d(`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`)},[N]);return t.default.useEffect(()=>{d(`[react-atom-trigger] v2 uses a new internal observation engine. If you upgraded from v1.x, verify trigger behavior for timing, threshold and rootMargin.`)},[]),t.default.useEffect(()=>{O&&h&&d("[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.")},[h,O]),t.default.useEffect(()=>{j&&d(j)},[j]),t.default.useEffect(()=>{if(typeof window>`u`||!O||!M||j||y)return;let e=window.setTimeout(()=>{x.current||d(`[react-atom-trigger] Child mode expects a DOM element or a component that forwards its ref to a DOM element. Observation is disabled for this render.`)},0);return()=>{window.clearTimeout(e)}},[y,M,O,j]),t.default.useEffect(()=>{let t=S.current;t&&(t.onEnter=e,t.onLeave=n,t.onEvent=r)},[e,n,r]),t.default.useEffect(()=>{if(typeof window>`u`)return;let t=O?y:_.current,i=z(u,f);if(!t){S.current&&P(S.current),C.current?.(),C.current=null,w.current=null;return}S.current?(S.current.node=t,S.current.rootMargin=T,S.current.threshold=D,S.current.once=a,S.current.oncePerDirection=o,S.current.fireOnInitialVisible=s):S.current={node:t,rootMargin:T,threshold:D,once:a,oncePerDirection:o,fireOnInitialVisible:s,onEnter:e,onLeave:n,onEvent:r,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}};let l=S.current;if(c||!i){P(l),C.current?.(),C.current=null,w.current=null;return}let d=w.current,p={node:t,target:i,rootMargin:T,threshold:D,once:a,oncePerDirection:o,fireOnInitialVisible:s};(!d||d.node!==p.node||d.target!==p.target||d.rootMargin!==p.rootMargin||d.threshold!==p.threshold||d.once!==p.once||d.oncePerDirection!==p.oncePerDirection||d.fireOnInitialVisible!==p.fireOnInitialVisible)&&(P(l),C.current?.(),C.current=R(i,l),w.current=p)},[c,T,D,a,o,s,y,u,f?.current,O]),t.default.useEffect(()=>()=>{C.current?.(),C.current=null,w.current=null},[]),O?M?t.default.cloneElement(M,{ref:F}):t.default.createElement(t.default.Fragment,null,i):t.default.createElement(`div`,{ref:_,style:B,className:h})},H={x:0,y:0},U=typeof window>`u`?t.default.useEffect:t.default.useLayoutEffect;function W(e,t){let n=null,r=null,i=()=>{n&&(clearTimeout(n),n=null),r=Date.now(),e()};return{schedule:()=>{if(t<=0){i();return}let e=Date.now();if(r===null||e-r>=t){i();return}n||(n=setTimeout(()=>{i()},t-(e-r)))},cancel:()=>{n&&(clearTimeout(n),n=null)}}}function G(){return typeof window>`u`?{width:0,height:0}:{width:window.innerWidth,height:window.innerHeight}}function K(e){return!!(e&&typeof e==`object`&&!(typeof Window<`u`&&e instanceof Window)&&`current`in e)}function q(e){return K(e)?e.current:e||(typeof window>`u`?null:window)}function J(e){return e===window||typeof Window<`u`&&e instanceof Window}function Y(e){if(J(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function X(e){let[n,r]=t.default.useState(G);return t.default.useEffect(()=>{if(typeof window>`u`||e?.enabled===!1)return;let t=e?.throttleMs??16;r(G());let n=W(()=>{r(G())},t);return window.addEventListener(`resize`,n.schedule,{passive:e?.passive}),()=>{n.cancel(),window.removeEventListener(`resize`,n.schedule)}},[e?.enabled,e?.passive,e?.throttleMs]),n}function Z(e){let n=e?.target,r=K(n),[i,a]=t.default.useState(()=>{let e=q(n);return e?Y(e):H}),[o,s]=t.default.useState(()=>r?q(n):null);U(()=>{if(!r)return;let e=q(n);s(t=>t===e?t:e)});let c=r?o:q(n);return t.default.useEffect(()=>{if(e?.enabled===!1){a(H);return}if(!c){a(H);return}let t=e?.throttleMs??16;a(Y(c));let n=W(()=>{a(Y(c))},t);return c.addEventListener(`scroll`,n.schedule,{passive:e?.passive}),()=>{n.cancel(),c.removeEventListener(`scroll`,n.schedule)}},[e?.enabled,e?.passive,e?.throttleMs,c]),i}e.AtomTrigger=V,e.useScrollPosition=Z,e.useViewportSize=X});
1
+ (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.reactAtomTrigger={},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?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t);let l=new Set;function u(){if(typeof process>`u`||!process.env)return null;let e=`production`;return e===`development`||e===`production`?e:null}function d(e){return(Object.prototype.hasOwnProperty.call(e??{},`nodeEnv`)?e?.nodeEnv??null:u())===`development`}function f(e){d()&&(l.has(e)||(l.add(e),typeof console<`u`&&console.warn&&console.warn(e)))}function p(e){return!!(e&&typeof e==`object`&&`nodeType`in e&&e.nodeType===1&&`getBoundingClientRect`in e&&typeof e.getBoundingClientRect==`function`&&`addEventListener`in e&&typeof e.addEventListener==`function`&&`removeEventListener`in e&&typeof e.removeEventListener==`function`)}function m(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function h(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function g(e){if(!e||typeof e!=`object`&&typeof e!=`function`)return;let t=Object.getOwnPropertyDescriptor(e,`ref`);if(!(!t||!(`value`in t)))return t.value}function _(e){if(!e)return;let t=g(e.props);return t===void 0?g(e):t}function v(e,n,r){return e?n===1?r?r.type===t.default.Fragment?`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`:null:`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`:null}function y({originalChildRef:e,hasObservedChild:n,invalidChildWarning:r,shouldWarnAboutMissingDomRef:i}){let[a,o]=t.default.useState(null),s=t.default.useRef(null),c=t.default.useCallback(()=>{s.current=null,o(e=>e===null?e:null)},[]),l=t.default.useCallback(t=>{if(h(e,t),t===null){c();return}if(p(t)){s.current=t,o(e=>e===t?e:t);return}c(),f(`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`)},[c,e]);return t.default.useEffect(()=>{if(typeof window>`u`||!(n&&!r&&!a&&i))return;let e=window.setTimeout(()=>{s.current||f(`[react-atom-trigger] Child mode expects a DOM element or a component that forwards its ref to a DOM element. Observation is disabled for this render.`)},16);return()=>{window.clearTimeout(e)}},[n,r,a,i]),{childNode:a,attachObservedChildRef:l}}function b(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function ee(e){return typeof e==`string`?e:b(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):(e==null||f(`[react-atom-trigger] Invalid rootMargin array ${JSON.stringify(e)}. Use exactly four finite numbers: [top, right, bottom, left]. Falling back to 0px.`),`0px`)}function x(e,t){let n=e.trim();if(!n||/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return f(`[react-atom-trigger] Invalid rootMargin token "${n}". Use px, % or 0. Falling back to 0px.`),0;let[,i,a]=r,o=Number.parseFloat(i);return a===`%`?o/100*t:o}function S(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return f(`[react-atom-trigger] Invalid rootMargin "${e}". Use 1 to 4 values in IntersectionObserver order. Falling back to 0px.`),{top:0,right:0,bottom:0,left:0};let[i=`0px`,a=i,o=i,s=a]=r;return{top:x(i,n),right:x(a,t),bottom:x(o,n),left:x(s,t)}}function C(e,t){let n=S(t,e.width,e.height);return new DOMRect(e.left-n.left,e.top-n.top,e.width+n.left+n.right,e.height+n.top+n.bottom)}function w(e){let t=e.width>0?e.width:1,n=e.height>0?e.height:1;return t===e.width&&n===e.height?e:new DOMRect(e.left,e.top,t,n)}function T(e,t){let n=Math.max(e.left,t.left),r=Math.max(e.top,t.top),i=Math.min(e.right,t.right),a=Math.min(e.bottom,t.bottom);return i<=n||a<=r?new DOMRect(0,0,0,0):new DOMRect(n,r,i-n,a-r)}function E(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function D(e){return Math.min(1,Math.max(0,e))}function te(e){return Array.isArray(e)?(f("[react-atom-trigger] `threshold` expects a single number in v2. Using the first finite numeric entry."),D(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0)):e==null?0:typeof e!=`number`||!Number.isFinite(e)?(f("[react-atom-trigger] `threshold` must be a finite number between 0 and 1. Falling back to 0."),0):((e<0||e>1)&&f("[react-atom-trigger] `threshold` should be between 0 and 1. Values are clamped."),D(e))}function O(e,t){if(!e)return`unknown`;let n=t.left-e.left,r=t.top-e.top;return n===0&&r===0?`stationary`:Math.abs(r)>=Math.abs(n)?r<0?`up`:`down`:n<0?`left`:`right`}function k(e){if(e.isIntersecting)return`inside`;let t=e.boundingClientRect,n=e.rootBounds?.top??0,r=e.rootBounds?.bottom??window.innerHeight,i=e.rootBounds?.left??0,a=e.rootBounds?.right??window.innerWidth;return t.bottom<=n?`above`:t.top>=r?`below`:t.right<=i?`left`:t.left>=a?`right`:`outside`}function A(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function ne(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function j(e){e.previousTriggerActive=void 0,e.previousRect=null}function re(e,t,n,r){let i=w(e.node.getBoundingClientRect()),a=C(t,e.rootMargin),o=T(i,a),s=E(i,o),c=s>0,l=e.previousTriggerActive,u=l===!0||e.threshold===0?c:s>=e.threshold,d=e.previousRect&&(n===`root-change`||r)?`stationary`:O(e.previousRect,i);e.previousRect=i,e.previousTriggerActive=u;let f=Date.now(),p={target:e.node,rootBounds:a,boundingClientRect:i,intersectionRect:o,isIntersecting:c,intersectionRatio:s,source:`geometry`},m=l===void 0;if(m&&(!e.fireOnInitialVisible||!u)||l===u)return;let h=u?`enter`:`leave`;if(!A(h,e.counts,e.once,e.oncePerDirection))return;let g=h===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=g;let _={type:h,isInitial:m,entry:p,counts:g,movementDirection:d,position:k(p),timestamp:f};e.onEvent?.(_),h===`enter`?e.onEnter?.(_):e.onLeave?.(_),ne(e)&&e.dispose?.()}let M=new WeakMap;function ie(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function N(e){return e===window||m(e)}function ae(e){let t={registrations:new Set,rafId:0,pendingSampleCause:null,previousBaseRootBounds:null,resizeObserver:null,intersectionObserver:null,queueSample:()=>{},cleanup:()=>{}},n=()=>{if(t.rafId=0,t.registrations.size===0){t.pendingSampleCause=null;return}let n=t.pendingSampleCause??`geometry-change`;t.pendingSampleCause=null;let r=N(e)?ie():e.getBoundingClientRect(),i=t.previousBaseRootBounds!==null&&(t.previousBaseRootBounds.top!==r.top||t.previousBaseRootBounds.left!==r.left||t.previousBaseRootBounds.width!==r.width||t.previousBaseRootBounds.height!==r.height);for(let e of t.registrations)re(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{if((t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId!==0)return;t.rafId=-1;let r=window.requestAnimationFrame(()=>{t.rafId=0,n()});t.rafId===-1&&(t.rafId=r)},i=()=>{r(`scroll`)},a=()=>{r(`root-change`)};return e.addEventListener(`scroll`,i,{passive:!0}),window.addEventListener(`resize`,a),typeof ResizeObserver<`u`&&(t.resizeObserver=new ResizeObserver(a),N(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:N(e)?null:e,rootMargin:`200% 200% 200% 200%`,threshold:0})),t.queueSample=r,t.cleanup=()=>{t.rafId!==0&&(cancelAnimationFrame(t.rafId),t.rafId=0),e.removeEventListener(`scroll`,i),window.removeEventListener(`resize`,a),t.resizeObserver?.disconnect(),t.intersectionObserver?.disconnect(),t.pendingSampleCause=null,t.previousBaseRootBounds=null},t}function oe(e){let t=M.get(e);if(t)return t;let n=ae(e);return M.set(e,n),n}function se(e,t){let n=oe(e),r=!1,i=t.node;n.registrations.add(t),n.resizeObserver?.observe(i),n.intersectionObserver?.observe(i),n.queueSample();let a=()=>{r||(r=!0,n.registrations.delete(t),n.resizeObserver?.unobserve(i),n.intersectionObserver?.unobserve(i),t.dispose=void 0,n.registrations.size===0&&(n.cleanup(),M.delete(e)))};return t.dispose=a,a}function ce(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function P(e,t){e.node=t.node,e.rootMargin=t.rootMargin,e.threshold=t.threshold,e.once=t.once,e.oncePerDirection=t.oncePerDirection,e.fireOnInitialVisible=t.fireOnInitialVisible}function le(e,t){e.onEnter=t.onEnter,e.onLeave=t.onLeave,e.onEvent=t.onEvent}function F(e){e.dispose?.(),e.dispose=null,e.binding=null}function ue(e){return{node:e.node,rootMargin:e.rootMargin,threshold:e.threshold,once:e.once,oncePerDirection:e.oncePerDirection,fireOnInitialVisible:e.fireOnInitialVisible}}function de(e,t){return!!(e&&e.node===t.node&&e.target===t.target&&e.rootMargin===t.rootMargin&&e.threshold===t.threshold&&e.once===t.once&&e.oncePerDirection===t.oncePerDirection&&e.fireOnInitialVisible===t.fireOnInitialVisible)}function I(e,t){return{registration:ce(e,t),binding:null,dispose:null}}function L(e,t){le(e.registration,t)}function R(e,t){let n=e.registration;if(!t.node){j(n),F(e);return}let r=ue({node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible});if(t.disabled||!t.target){F(e),P(n,r),j(n);return}let i={...r,target:t.target};if(de(e.binding,i)){P(n,r);return}j(n),F(e),P(n,r),e.dispose=se(t.target,n),e.binding=i}function z(e){F(e)}function B(e){let t=e.kind===`rootRef`?"[react-atom-trigger] `rootRef.current` must resolve to a real DOM element. Observation is paused until it does.":"[react-atom-trigger] `root` must be a real DOM element when provided. Observation is paused until it is.",{target:n}=e;return n==null?null:p(n)?n:(f(t),null)}function V(e){let n=e!==void 0,[r,i]=t.default.useState(()=>n?e.current:null);return t.default.useEffect(()=>{if(!n)return;let t=e.current;i(e=>e===t?e:t)}),n?r:void 0}function fe(e){switch(e.kind){case`rootRef`:case`root`:return B(e);case`viewport`:return typeof window>`u`?null:window}}let pe={display:`table`},me=({onEnter:e,onLeave:n,onEvent:r,children:i,once:a=!1,oncePerDirection:o=!1,fireOnInitialVisible:s=!1,disabled:c=!1,threshold:l=0,root:u,rootRef:d,rootMargin:p=`0px`,className:m})=>{let h=t.default.useRef(null),g=t.default.useRef(null),b=V(d),x=ee(p),S=te(l),C=i!=null,w=t.default.Children.count(i),T=w===1&&t.default.isValidElement(i)?i:null,E=v(C,w,T),D=E||!T?null:T,{childNode:O,attachObservedChildRef:k}=y({originalChildRef:_(D),hasObservedChild:C,invalidChildWarning:E,shouldWarnAboutMissingDomRef:D!==null});return t.default.useEffect(()=>{C&&m&&f("[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.")},[m,C]),t.default.useEffect(()=>{E&&f(E)},[E]),t.default.useEffect(()=>{a&&o&&f("[react-atom-trigger] `once` and `oncePerDirection` were both provided. `once` takes precedence.")},[a,o]),t.default.useEffect(()=>{let t=g.current;t&&L(t,{onEnter:e,onLeave:n,onEvent:r})},[e,n,r]),t.default.useEffect(()=>{if(typeof window>`u`)return;let t=C?O:h.current,i=fe(d===void 0?u===void 0?{kind:`viewport`}:{kind:`root`,target:u}:{kind:`rootRef`,target:b});if(!t){g.current&&R(g.current,{disabled:!1,node:null,target:i,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s});return}g.current||(g.current=I({node:t,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s},{onEnter:e,onLeave:n,onEvent:r})),R(g.current,{disabled:c,node:t,target:i,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s})},[c,x,S,a,o,s,O,u,d,b,C]),t.default.useEffect(()=>()=>{g.current&&(z(g.current),g.current=null)},[]),C?D?t.default.cloneElement(D,{ref:k}):t.default.createElement(t.default.Fragment,null,i):t.default.createElement(`div`,{ref:h,style:pe,className:m})},H=t.default.useSyncExternalStore,he=typeof window>`u`?t.default.useEffect:t.default.useLayoutEffect;function U(e,n,r){if(H)return H(e,n,r);let[i,a]=t.default.useState(()=>r()),o=t.default.useRef(i);return he(()=>{let t=()=>{let e=n();Object.is(o.current,e)||(o.current=e,a(e))};return t(),e(t)},[e,n]),i}function W(e,t,n){return n(e.current,t)?e.current:(e.current=t,t)}let G={x:0,y:0},K={width:0,height:0},ge=typeof window>`u`?t.default.useEffect:t.default.useLayoutEffect;function q(e,t){let n=null,r=null,i=()=>{n&&(clearTimeout(n),n=null),r=Date.now(),e()};return{schedule:()=>{if(t<=0){i();return}let e=Date.now();if(r===null||e-r>=t){i();return}n||(n=setTimeout(()=>{i()},t-(e-r)))},cancel:()=>{n&&(clearTimeout(n),n=null)}}}function J(){return typeof window>`u`?K:{width:window.innerWidth,height:window.innerHeight}}function Y(e){return!!(e&&typeof e==`object`&&!m(e)&&`current`in e)}function X(e){return Y(e)?e.current:e||(typeof window>`u`?null:window)}function _e(e){return e===window||m(e)}function Z(e){if(_e(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function ve(e){let t=X(e);return t?Z(t):G}function Q(e,t){return e.x===t.x&&e.y===t.y}function $(e,t){return e.width===t.width&&e.height===t.height}function ye(e){let n=e?.enabled!==!1,r=e?.passive,i=e?.throttleMs??16,a=t.default.useRef(J()),o=t.default.useCallback(()=>typeof window>`u`?K:n?W(a,J(),$):a.current,[n]);return U(t.default.useCallback(e=>{if(typeof window>`u`||!n)return()=>{};let t=q(()=>{let t=J();$(a.current,t)||(a.current=t,e())},i);return window.addEventListener(`resize`,t.schedule,{passive:r}),()=>{t.cancel(),window.removeEventListener(`resize`,t.schedule)}},[n,r,i]),o,()=>K)}function be(e){let n=e?.target,r=Y(n),i=e?.enabled!==!1,a=e?.passive,o=e?.throttleMs??16,s=t.default.useRef(ve(n)),[c,l]=t.default.useState(()=>r?X(n):null);ge(()=>{if(!r)return;let e=X(n);l(t=>t===e?t:e)});let u=r?c:X(n),d=t.default.useCallback(()=>i?u?W(s,Z(u),Q):W(s,G,Q):s.current,[i,u]);return U(t.default.useCallback(e=>{if(!i||!u)return()=>{};let t=q(()=>{let t=Z(u);Q(s.current,t)||(s.current=t,e())},o);return u.addEventListener(`scroll`,t.schedule,{passive:a}),()=>{t.cancel(),u.removeEventListener(`scroll`,t.schedule)}},[i,a,u,o]),d,()=>G)}e.AtomTrigger=me,e.useScrollPosition=be,e.useViewportSize=ye});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-atom-trigger",
3
- "version": "2.0.3",
3
+ "version": "2.0.6",
4
4
  "description": "Geometry-based scroll trigger for React with precise enter/leave control. A modern alternative to react-waypoint.",
5
5
  "keywords": [
6
6
  "intersection",
@@ -52,9 +52,12 @@
52
52
  "precommit:checks": "pnpm format:check && pnpm lint && pnpm test",
53
53
  "test": "pnpm test:all",
54
54
  "test:all": "pnpm test:unit && pnpm test:storybook",
55
- "test:coverage": "pnpm test:coverage:unit && pnpm test:coverage:storybook",
55
+ "test:coverage": "pnpm test:coverage:unit",
56
56
  "test:coverage:unit": "vitest run --project=unit --reporter=verbose --coverage.enabled=true --coverage.reportsDirectory=coverage/unit",
57
57
  "test:coverage:storybook": "vitest run --project=storybook --coverage.enabled=true --coverage.reportsDirectory=coverage/storybook",
58
+ "test:package-smoke": "node scripts/package-smoke.mjs",
59
+ "test:react-compat": "node scripts/react-compat-smoke.mjs",
60
+ "test:react-compat:matrix": "node scripts/react-compat-matrix.mjs",
58
61
  "test:unit": "vitest run --project=unit --reporter=verbose",
59
62
  "test:watch": "vitest --project=unit",
60
63
  "test:storybook": "vitest run --project=storybook",
@@ -89,9 +92,6 @@
89
92
  "peerDependencies": {
90
93
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
91
94
  },
92
- "engines": {
93
- "node": ">=20.19.0"
94
- },
95
95
  "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
96
96
  "pnpm": {
97
97
  "overrides": {