react-atom-trigger 2.0.11 → 2.1.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/MIGRATION.md CHANGED
@@ -36,16 +36,18 @@ The new version samples geometry internally, so some edge timing can feel a bit
36
36
 
37
37
  ## Hook and type changes
38
38
 
39
- | v1.x | v2.x |
40
- | -------------------------------------- | --------------------------------------------- |
41
- | `useWindowScroll` | `useScrollPosition()` |
42
- | `useContainerScroll({ containerRef })` | `useScrollPosition({ target: containerRef })` |
43
- | `useWindowDimensions` | `useViewportSize()` |
44
- | `Options` | `ListenerOptions` |
45
- | `ScrollEvent` | removed |
46
- | `Dimensions` | removed |
47
- | `DebugInfo` | removed |
48
- | `log` | removed |
39
+ `v2.1` no longer exports scroll or viewport helper hooks. `AtomTrigger` does its own observation internally, so these hooks are not needed for normal trigger usage.
40
+
41
+ | v1.x | v2.1.x |
42
+ | -------------------------------------- | ----------------------------------------- |
43
+ | `useWindowScroll` | removed, use your app's own scroll hook |
44
+ | `useContainerScroll({ containerRef })` | removed, use your app's own scroll hook |
45
+ | `useWindowDimensions` | removed, use your app's own viewport hook |
46
+ | `Options` | removed |
47
+ | `ScrollEvent` | removed |
48
+ | `Dimensions` | removed |
49
+ | `DebugInfo` | removed |
50
+ | `log` | removed |
49
51
 
50
52
  ## Common upgrades
51
53
 
@@ -222,30 +224,6 @@ After migrating, please check it in the actual UI. `rootMargin` is the place whe
222
224
  />
223
225
  ```
224
226
 
225
- ## Small hook examples
226
-
227
- ### Replace `useWindowScroll`
228
-
229
- ```tsx
230
- const position = useScrollPosition();
231
- console.log(position.y);
232
- ```
233
-
234
- ### Replace `useContainerScroll`
235
-
236
- ```tsx
237
- const containerRef = React.useRef<HTMLDivElement>(null);
238
- const position = useScrollPosition({ target: containerRef });
239
- console.log(position.y);
240
- ```
241
-
242
- ### Replace `useWindowDimensions`
243
-
244
- ```tsx
245
- const viewport = useViewportSize();
246
- console.log(viewport.height);
247
- ```
248
-
249
227
  ## Final check
250
228
 
251
229
  Your migration is probably done when all of these are true:
@@ -253,5 +231,5 @@ Your migration is probably done when all of these are true:
253
231
  1. No `AtomTrigger` still passes `scrollEvent`, `dimensions`, `behavior`, `callback`, `getDebugInfo`, `triggerOnce` or `offset`.
254
232
  2. Trigger handlers now use `onEnter`, `onLeave` and/or `onEvent`.
255
233
  3. Custom containers use `root` or `rootRef`.
256
- 4. Hook imports were moved to `useScrollPosition` and `useViewportSize`.
234
+ 4. Old helper hook imports were removed or replaced with hooks from your own codebase.
257
235
  5. You checked the real UI, not only TypeScript errors, especially around `threshold` and `rootMargin`.
package/README.md CHANGED
@@ -3,12 +3,27 @@
3
3
  [![codecov](https://codecov.io/gh/innrvoice/react-atom-trigger/branch/master/graph/badge.svg)](https://codecov.io/gh/innrvoice/react-atom-trigger)
4
4
  [![bundle size](https://codecov.io/github/innrvoice/react-atom-trigger/branch/master/graph/bundle/react-atom-trigger-esm/badge.svg)](https://app.codecov.io/github/innrvoice/react-atom-trigger/bundles/master/react-atom-trigger-esm)
5
5
 
6
- `react-atom-trigger` helps with the usual "run some code when this thing enters or leaves view" problem.
7
- It is a lightweight React alternative to `react-waypoint`, written in TypeScript.
6
+ `react-atom-trigger` helps with the usual "run some code when this thing enters or leaves view" problem in React.
8
7
 
9
- ## v2 is a breaking release
8
+ It is designed for scroll-triggered UI and viewport-based interactions, focusing on predictable enter/leave behavior in real layouts where scroll, resize and layout shifts all affect visibility.
10
9
 
11
- If you are coming from `v1.x`, please check [MIGRATION.md](./MIGRATION.md).
10
+ It is a lightweight React alternative to `react-waypoint`.
11
+
12
+ It can also be used as a higher-level alternative to React Intersection Observer based solutions when you need more predictable scroll-trigger behavior.
13
+
14
+ ## Typical use cases
15
+
16
+ - scroll-driven UI (sticky headers, scene transitions)
17
+ - triggering animations with precise timing
18
+ - layouts with dynamic content or frequent reflows
19
+ - containers with custom scroll roots
20
+
21
+ ## Breaking changes
22
+
23
+ `v2` is a breaking release. If you are coming from `v1.x`, please check
24
+ [MIGRATION.md](./MIGRATION.md).
25
+
26
+ `v2.1` removes the helper hooks `useScrollPosition` and `useViewportSize`. `AtomTrigger` does its own observation and does not depend on those hooks.
12
27
 
13
28
  If you want to stay on the old API:
14
29
 
@@ -47,7 +62,7 @@ The public React compatibility contract for `v2` is the published peer range: Re
47
62
  `react-atom-trigger` uses a mixed approach.
48
63
 
49
64
  - Geometry is the real source of truth for `enter` and `leave`.
50
- - `IntersectionObserver` is only there to wake things up when the browser notices a nearby layout shift.
65
+ - `IntersectionObserver` is only there to wake things up when the browser notices a nearby layout shift. You can think of it as: IntersectionObserver wakes things up, geometry decides what actually happened.
51
66
  - `rootMargin` logic is handled by the library itself, so it stays consistent and does not depend on native observer quirks.
52
67
 
53
68
  In practice this means `AtomTrigger` reacts to:
@@ -58,7 +73,28 @@ In practice this means `AtomTrigger` reacts to:
58
73
  - sentinel resize
59
74
  - nearby layout shifts that move the observed element even if no scroll event happened
60
75
 
61
- This is the main reason `v2` can support custom margin-aware behavior and still react to browser-driven layout changes.
76
+ This allows it to support margin-aware behavior while still reacting to browser-driven changes.
77
+
78
+ ## When to use vs react-intersection-observer
79
+
80
+ `react-intersection-observer` is a lightweight React wrapper around the browser’s IntersectionObserver API.
81
+
82
+ It is a great fit when:
83
+
84
+ - you only need to know if something is visible
85
+ - async observer timing is acceptable
86
+ - you want a simple hook like `useInView`
87
+
88
+ However, IntersectionObserver is designed as an asynchronous visibility signal managed by the browser. It does not provide exact geometry-based control over enter/leave transitions.
89
+
90
+ In fast scroll or layout-heavy UIs, this can lead to missed intermediate states or non-intuitive enter/leave timing.
91
+
92
+ Use `react-atom-trigger` when:
93
+
94
+ - you need predictable enter/leave behavior
95
+ - layout shifts should be handled consistently
96
+ - margins and thresholds must behave the same across cases
97
+ - visibility should be derived from actual element geometry rather than observer callbacks
62
98
 
63
99
  ## Quick start
64
100
 
@@ -208,33 +244,6 @@ The payload is library-owned geometry data. It is not a native `IntersectionObse
208
244
  `isInitial` is `true` only for the synthetic first `enter` created by
209
245
  `fireOnInitialVisible`.
210
246
 
211
- ## Hooks
212
-
213
- For someone who wants everything out-of-the-box, `useScrollPosition` and `useViewportSize` are also available.
214
-
215
- ```ts
216
- useScrollPosition(options?: {
217
- target?: Window | HTMLElement | React.RefObject<HTMLElement | null>;
218
- passive?: boolean;
219
- throttleMs?: number;
220
- enabled?: boolean;
221
- }): { x: number; y: number }
222
- ```
223
-
224
- ```ts
225
- useViewportSize(options?: {
226
- passive?: boolean;
227
- throttleMs?: number;
228
- enabled?: boolean;
229
- }): { width: number; height: number }
230
- ```
231
-
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.
237
-
238
247
  ## Notes
239
248
 
240
249
  - In sentinel mode, `threshold` is usually only interesting if your sentinel has real width or height. The default sentinel is almost point-like.
@@ -252,8 +261,7 @@ The short version:
252
261
  2. `behavior` is gone.
253
262
  3. `triggerOnce` became `once` or `oncePerDirection`.
254
263
  4. `scrollEvent`, `dimensions` and `offset` are gone.
255
- 5. `useWindowScroll` / `useContainerScroll` became `useScrollPosition`.
256
- 6. `useWindowDimensions` became `useViewportSize`.
264
+ 5. Legacy helper hooks are no longer exported in `v2.1`. Use your app's own scroll or viewport hooks when needed.
257
265
 
258
266
  For the real upgrade notes and examples, see [MIGRATION.md](./MIGRATION.md).
259
267
 
package/lib/index.d.ts CHANGED
@@ -46,24 +46,4 @@ interface AtomTriggerProps {
46
46
  //#region src/AtomTrigger.d.ts
47
47
  declare const AtomTrigger: React.FC<AtomTriggerProps>;
48
48
  //#endregion
49
- //#region src/utils.d.ts
50
- type ScrollPosition = {
51
- x: number;
52
- y: number;
53
- };
54
- type ViewportSize = {
55
- width: number;
56
- height: number;
57
- };
58
- type ListenerOptions = {
59
- passive?: boolean;
60
- throttleMs?: number;
61
- enabled?: boolean;
62
- };
63
- type UseScrollPositionOptions = ListenerOptions & {
64
- target?: Window | HTMLElement | React.RefObject<HTMLElement | null>;
65
- };
66
- declare function useViewportSize(options?: ListenerOptions): ViewportSize;
67
- declare function useScrollPosition(options?: UseScrollPositionOptions): ScrollPosition;
68
- //#endregion
69
- export { AtomTrigger, type AtomTriggerEntry, type AtomTriggerEvent, type AtomTriggerProps, type ListenerOptions, type MovementDirection, type RootMarginTuple, type ScrollPosition, type TriggerCounts, type TriggerPosition, type TriggerType, type UseScrollPositionOptions, type ViewportSize, useScrollPosition, useViewportSize };
49
+ export { AtomTrigger, type AtomTriggerEntry, type AtomTriggerEvent, type AtomTriggerProps, type MovementDirection, type RootMarginTuple, type TriggerCounts, type TriggerPosition, type TriggerType };
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- import e from"react";const t={invalidChildCount:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`,invalidChildElement:`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`,unsupportedChildRef:`[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.`,fragmentChild:`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`,nonDomChildRef:`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`,childModeClassName:"[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.",conflictingOnceModes:"[react-atom-trigger] `once` and `oncePerDirection` were both provided. `once` takes precedence.",invalidRoot:"[react-atom-trigger] `root` must be a real DOM element when provided. Observation is paused until it is.",invalidRootRef:"[react-atom-trigger] `rootRef.current` must resolve to a real DOM element. Observation is paused until it does."};function n(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 r(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function i(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function a(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 o(e){if(!e)return;let t=a(e.props);return t===void 0?a(e):t}function s(n,r,i){return n?r===1?i?i.type===e.Fragment?t.fragmentChild:null:t.invalidChildElement:t.invalidChildCount:null}function c({originalChildRef:t,hasObservedChild:r,invalidChildWarning:a,shouldWarnAboutMissingDomRef:o}){let[s,c]=e.useState(null),l=e.useRef(null),u=e.useCallback(()=>{l.current=null,c(e=>e===null?e:null)},[]),d=e.useCallback(e=>{if(i(t,e),e===null){u();return}if(n(e)){l.current=e,c(t=>t===e?t:e);return}u()},[u,t]);return e.useEffect(()=>{if(typeof window>`u`||!(r&&!a&&!s&&o))return;let e=window.setTimeout(()=>{l.current},16);return()=>{window.clearTimeout(e)}},[r,a,s,o]),{childNode:s,attachObservedChildRef:d}}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(` `):`0px`}function d(e,t){let n=e.trim();if(/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return 0;let[,i,a]=r,o=Number.parseFloat(i);return a===`%`?o/100*t:o}function f(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return{top:0,right:0,bottom:0,left:0};let[i=`0px`,a=i,o=i,s=a]=r;return{top:d(i,n),right:d(a,t),bottom:d(o,n),left:d(s,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)?_(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0):e==null||typeof e!=`number`||!Number.isFinite(e)?0:_(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`}function x(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function S(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function C(e){e.previousTriggerActive=void 0,e.previousRect=null}function w(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 C=u?`enter`:`leave`;if(!x(C,e.counts,e.once,e.oncePerDirection))return;let w=C===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=w;let T={type:C,isInitial:v,entry:_,counts:w,movementDirection:d,position:b(_),timestamp:f};e.onEvent?.(T),C===`enter`?e.onEnter?.(T):e.onLeave?.(T),S(e)&&e.unsubscribe?.()}const T=new WeakMap;function E(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function D(e){return e===window||r(e)}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=D(e)?E():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)w(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{(t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId===0&&(t.rafId=window.requestAnimationFrame(()=>{t.rafId=0,n()}))},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),D(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:D(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=T.get(e);if(t)return t;let n=O(e);return T.set(e,n),n}function A(e,t){let n=k(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.unsubscribe=void 0,n.registrations.size===0&&(n.cleanup(),T.delete(e)))};return t.unsubscribe=a,a}function j(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function M(e){e.unsubscribe?.(),e.unsubscribe=null,e.subscription=null}function N(e,t){return{registration:j(e,t),subscription:null,unsubscribe:null}}function P(e,t){e.registration.onEnter=t.onEnter,e.registration.onLeave=t.onLeave,e.registration.onEvent=t.onEvent}function F(e,t){let n=e.registration;if(!t.node){C(n),M(e);return}let r={node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible};if(t.disabled||!t.target){M(e),Object.assign(n,r),C(n);return}let i={...r,target:t.target};if(e.subscription!==null&&e.subscription.node===i.node&&e.subscription.target===i.target&&e.subscription.rootMargin===i.rootMargin&&e.subscription.threshold===i.threshold&&e.subscription.once===i.once&&e.subscription.oncePerDirection===i.oncePerDirection&&e.subscription.fireOnInitialVisible===i.fireOnInitialVisible){Object.assign(n,r);return}C(n),M(e),Object.assign(n,r),e.unsubscribe=A(t.target,n),e.subscription=i}function I(e){M(e)}function L(e){e.kind===`rootRef`?t.invalidRootRef:t.invalidRoot;let{target:r}=e;return r==null?null:n(r)?r:null}function R(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 z(e){switch(e.kind){case`rootRef`:case`root`:return L(e);case`viewport`:return typeof window>`u`?null:window}}const B={display:`table`},V=({onEnter:t,onLeave:n,onEvent:r,children:i,once:a=!1,oncePerDirection:l=!1,fireOnInitialVisible:d=!1,disabled:f=!1,threshold:p=0,root:m,rootRef:h,rootMargin:g=`0px`,className:_})=>{let y=e.useRef(null),b=e.useRef(null),x=R(h),S=u(g),C=v(p),w=i!=null,T=e.Children.count(i),E=T===1&&e.isValidElement(i)?i:null,D=s(w,T,E),O=D||!E?null:E,{childNode:k,attachObservedChildRef:A}=c({originalChildRef:o(O),hasObservedChild:w,invalidChildWarning:D,shouldWarnAboutMissingDomRef:O!==null});return e.useEffect(()=>{},[_,w]),e.useEffect(()=>{},[D]),e.useEffect(()=>{},[a,l]),e.useEffect(()=>{let e=b.current;e&&P(e,{onEnter:t,onLeave:n,onEvent:r})},[t,n,r]),e.useEffect(()=>{if(typeof window>`u`)return;let e=w?k:y.current,i=z(h===void 0?m===void 0?{kind:`viewport`}:{kind:`root`,target:m}:{kind:`rootRef`,target:x});if(!e){b.current&&F(b.current,{disabled:!1,node:null,target:i,rootMargin:S,threshold:C,once:a,oncePerDirection:l,fireOnInitialVisible:d});return}b.current||(b.current=N({node:e,rootMargin:S,threshold:C,once:a,oncePerDirection:l,fireOnInitialVisible:d},{onEnter:t,onLeave:n,onEvent:r})),F(b.current,{disabled:f,node:e,target:i,rootMargin:S,threshold:C,once:a,oncePerDirection:l,fireOnInitialVisible:d})},[f,S,C,a,l,d,k,m,h,x,w]),e.useEffect(()=>()=>{b.current&&(I(b.current),b.current=null)},[]),w?O?e.cloneElement(O,{ref:A}):e.createElement(e.Fragment,null,i):e.createElement(`div`,{ref:y,style:B,className:_})};function H(t,n,r){let i=e.useSyncExternalStore;if(i)return i(t,n,r);let[a,o]=e.useState(()=>r()),s=e.useRef(a);return(typeof window>`u`?e.useEffect:e.useLayoutEffect)(()=>{let e=()=>{let e=n();Object.is(s.current,e)||(s.current=e,o(e))};return e(),t(e)},[t,n]),a}function U(e,t,n){return n(e.current,t)?e.current:(e.current=t,t)}const W={x:0,y:0},G={width:0,height:0};function K(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 q(){return typeof window>`u`?G:{width:window.innerWidth,height:window.innerHeight}}function J(e){return!!(e&&typeof e==`object`&&!r(e)&&`current`in e)}function Y(e){return J(e)?e.current:e||(typeof window>`u`?null:window)}function X(e){return e===window||r(e)}function Z(e){if(X(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function ee(e){let t=Y(e);return t?Z(t):W}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 te(t){let n=t?.enabled!==!1,r=t?.passive,i=t?.throttleMs??16,a=e.useRef(q()),o=e.useCallback(()=>typeof window>`u`?G:n?U(a,q(),$):a.current,[n]);return H(e.useCallback(e=>{if(typeof window>`u`||!n)return()=>{};let t=K(()=>{let t=q();$(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,()=>G)}function ne(t){let n=t?.target,r=J(n),i=t?.enabled!==!1,a=t?.passive,o=t?.throttleMs??16,s=e.useRef(ee(n)),[c,l]=e.useState(()=>r?Y(n):null);(typeof window>`u`?e.useEffect:e.useLayoutEffect)(()=>{if(!r)return;let e=Y(n);l(t=>t===e?t:e)});let u=r?c:Y(n),d=e.useCallback(()=>i?u?U(s,Z(u),Q):U(s,W,Q):s.current,[i,u]);return H(e.useCallback(e=>{if(!i||!u)return()=>{};let t=K(()=>{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,()=>W)}export{V as AtomTrigger,ne as useScrollPosition,te as useViewportSize};
1
+ import e from"react";function t(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 n(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function r(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function i(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 a(e){if(!e)return;let t=i(e.props);return t===void 0?i(e):t}function o(t,n,r){return t?n===1?r?r.type===e.Fragment?`fragmentChild`:null:`invalidChildElement`:`invalidChildCount`:null}function s({originalChildRef:n,hasObservedChild:i,invalidChildWarning:a,shouldWarnAboutMissingDomRef:o}){let[s,c]=e.useState(null),l=e.useRef(null),u=e.useCallback(()=>{l.current=null,c(e=>e===null?e:null)},[]),d=e.useCallback(e=>{if(r(n,e),e===null){u();return}if(t(e)){l.current=e,c(t=>t===e?t:e);return}u()},[u,n]);return e.useEffect(()=>{if(typeof window>`u`||!(i&&!a&&!s&&o))return;let e=window.setTimeout(()=>{l.current},16);return()=>{window.clearTimeout(e)}},[i,a,s,o]),{childNode:s,attachObservedChildRef:d}}function c(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function l(e){return typeof e==`string`?e:c(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):`0px`}function u(e,t){let n=e.trim();if(/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return 0;let[,i,a]=r,o=Number.parseFloat(i);return a===`%`?o/100*t:o}function d(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return{top:0,right:0,bottom:0,left:0};let[i=`0px`,a=i,o=i,s=a]=r;return{top:u(i,n),right:u(a,t),bottom:u(o,n),left:u(s,t)}}function f(e,t){let n=d(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 p(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 m(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 h(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function g(e){return Math.min(1,Math.max(0,e))}function _(e){return e==null||typeof e!=`number`||!Number.isFinite(e)?0:g(e)}function v(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 y(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 b(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function x(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function S(e){e.previousTriggerActive=void 0,e.previousRect=null}function C(e,t,n,r){let i=p(e.node.getBoundingClientRect()),a=f(t,e.rootMargin),o=m(i,a),s=h(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`:v(e.previousRect,i);e.previousRect=i,e.previousTriggerActive=u;let g=Date.now(),_={target:e.node,rootBounds:a,boundingClientRect:i,intersectionRect:o,isIntersecting:c,intersectionRatio:s,source:`geometry`},S=l===void 0;if(S&&(!e.fireOnInitialVisible||!u)||l===u)return;let C=u?`enter`:`leave`;if(!b(C,e.counts,e.once,e.oncePerDirection))return;let w=C===`enter`?{...e.counts,entered:e.counts.entered+1}:{...e.counts,left:e.counts.left+1};e.counts=w;let T={type:C,isInitial:S,entry:_,counts:w,movementDirection:d,position:y(_),timestamp:g};e.onEvent?.(T),C===`enter`?e.onEnter?.(T):e.onLeave?.(T),x(e)&&e.unsubscribe?.()}const w=new WeakMap;function T(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function E(e){return e===window||n(e)}function D(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=E(e)?T():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)C(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{(t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId===0&&(t.rafId=window.requestAnimationFrame(()=>{t.rafId=0,n()}))},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),E(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:E(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 O(e){let t=w.get(e);if(t)return t;let n=D(e);return w.set(e,n),n}function k(e,t){let n=O(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.unsubscribe=void 0,n.registrations.size===0&&(n.cleanup(),w.delete(e)))};return t.unsubscribe=a,a}function A(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function j(e){e.unsubscribe?.(),e.unsubscribe=null,e.subscription=null}function M(e,t){return{registration:A(e,t),subscription:null,unsubscribe:null}}function N(e,t){e.registration.onEnter=t.onEnter,e.registration.onLeave=t.onLeave,e.registration.onEvent=t.onEvent}function P(e,t){let n=e.registration;if(!t.node){S(n),j(e);return}let r={node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible};if(t.disabled||!t.target){j(e),Object.assign(n,r),S(n);return}let i={...r,target:t.target};if(e.subscription!==null&&e.subscription.node===i.node&&e.subscription.target===i.target&&e.subscription.rootMargin===i.rootMargin&&e.subscription.threshold===i.threshold&&e.subscription.once===i.once&&e.subscription.oncePerDirection===i.oncePerDirection&&e.subscription.fireOnInitialVisible===i.fireOnInitialVisible){Object.assign(n,r);return}S(n),j(e),Object.assign(n,r),e.unsubscribe=k(t.target,n),e.subscription=i}function F(e){j(e)}function I(e){e.kind;let{target:n}=e;return n==null?null:t(n)?n:null}function L(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 R(e){switch(e.kind){case`rootRef`:case`root`:return I(e);case`viewport`:return typeof window>`u`?null:window}}const z={display:`table`},B=({onEnter:t,onLeave:n,onEvent:r,children:i,once:c=!1,oncePerDirection:u=!1,fireOnInitialVisible:d=!1,disabled:f=!1,threshold:p=0,root:m,rootRef:h,rootMargin:g=`0px`,className:v})=>{let y=e.useRef(null),b=e.useRef(null),x=L(h),S=l(g),C=_(p),w=i!=null,T=e.Children.count(i),E=T===1&&e.isValidElement(i)?i:null,D=o(w,T,E),O=D||!E?null:E,{childNode:k,attachObservedChildRef:A}=s({originalChildRef:a(O),hasObservedChild:w,invalidChildWarning:D,shouldWarnAboutMissingDomRef:O!==null});return e.useEffect(()=>{},[v,w]),e.useEffect(()=>{},[D]),e.useEffect(()=>{},[c,u]),e.useEffect(()=>{let e=b.current;e&&N(e,{onEnter:t,onLeave:n,onEvent:r})},[t,n,r]),e.useEffect(()=>{if(typeof window>`u`)return;let e=w?k:y.current,i=R(h===void 0?m===void 0?{kind:`viewport`}:{kind:`root`,target:m}:{kind:`rootRef`,target:x});if(!e){b.current&&P(b.current,{disabled:!1,node:null,target:i,rootMargin:S,threshold:C,once:c,oncePerDirection:u,fireOnInitialVisible:d});return}b.current||(b.current=M({node:e,rootMargin:S,threshold:C,once:c,oncePerDirection:u,fireOnInitialVisible:d},{onEnter:t,onLeave:n,onEvent:r})),P(b.current,{disabled:f,node:e,target:i,rootMargin:S,threshold:C,once:c,oncePerDirection:u,fireOnInitialVisible:d})},[f,S,C,c,u,d,k,m,h,x,w]),e.useEffect(()=>()=>{b.current&&(F(b.current),b.current=null)},[]),w?O?e.cloneElement(O,{ref:A}):e.createElement(e.Fragment,null,i):e.createElement(`div`,{ref:y,style:z,className:v})};export{B as AtomTrigger};
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={invalidChildCount:`[react-atom-trigger] Child mode expects exactly one top-level React element. Observation is disabled for this render.`,invalidChildElement:`[react-atom-trigger] Child mode expects a React element child. Observation is disabled for this render.`,unsupportedChildRef:`[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.`,fragmentChild:`[react-atom-trigger] Child mode does not support React.Fragment. Wrap the content in a single DOM element. Observation is disabled for this render.`,nonDomChildRef:`[react-atom-trigger] Child mode requires the child ref to resolve to a DOM element. Observation is disabled for this render.`,childModeClassName:"[react-atom-trigger] `className` only applies to the internal sentinel. In child mode, style the child element directly.",conflictingOnceModes:"[react-atom-trigger] `once` and `oncePerDirection` were both provided. `once` takes precedence.",invalidRoot:"[react-atom-trigger] `root` must be a real DOM element when provided. Observation is paused until it is.",invalidRootRef:"[react-atom-trigger] `rootRef.current` must resolve to a real DOM element. Observation is paused until it does."};function u(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 d(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function f(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function p(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 m(e){if(!e)return;let t=p(e.props);return t===void 0?p(e):t}function h(e,n,r){return e?n===1?r?r.type===t.default.Fragment?l.fragmentChild:null:l.invalidChildElement:l.invalidChildCount:null}function g({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(f(e,t),t===null){c();return}if(u(t)){s.current=t,o(e=>e===t?e:t);return}c()},[c,e]);return t.default.useEffect(()=>{if(typeof window>`u`||!(n&&!r&&!a&&i))return;let e=window.setTimeout(()=>{s.current},16);return()=>{window.clearTimeout(e)}},[n,r,a,i]),{childNode:a,attachObservedChildRef:l}}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(` `):`0px`}function y(e,t){let n=e.trim();if(/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return 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{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 ee(e){return Array.isArray(e)?T(e.find(e=>typeof e==`number`&&Number.isFinite(e))??0):e==null||typeof e!=`number`||!Number.isFinite(e)?0:T(e)}function E(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 D(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 O(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function k(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function A(e){e.previousTriggerActive=void 0,e.previousRect=null}function te(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`:E(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(!O(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:D(p),timestamp:f};e.onEvent?.(_),h===`enter`?e.onEnter?.(_):e.onLeave?.(_),k(e)&&e.unsubscribe?.()}let j=new WeakMap;function M(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function N(e){return e===window||d(e)}function P(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)?M():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)te(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{(t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId===0&&(t.rafId=window.requestAnimationFrame(()=>{t.rafId=0,n()}))},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 F(e){let t=j.get(e);if(t)return t;let n=P(e);return j.set(e,n),n}function ne(e,t){let n=F(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.unsubscribe=void 0,n.registrations.size===0&&(n.cleanup(),j.delete(e)))};return t.unsubscribe=a,a}function re(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function I(e){e.unsubscribe?.(),e.unsubscribe=null,e.subscription=null}function ie(e,t){return{registration:re(e,t),subscription:null,unsubscribe:null}}function ae(e,t){e.registration.onEnter=t.onEnter,e.registration.onLeave=t.onLeave,e.registration.onEvent=t.onEvent}function L(e,t){let n=e.registration;if(!t.node){A(n),I(e);return}let r={node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible};if(t.disabled||!t.target){I(e),Object.assign(n,r),A(n);return}let i={...r,target:t.target};if(e.subscription!==null&&e.subscription.node===i.node&&e.subscription.target===i.target&&e.subscription.rootMargin===i.rootMargin&&e.subscription.threshold===i.threshold&&e.subscription.once===i.once&&e.subscription.oncePerDirection===i.oncePerDirection&&e.subscription.fireOnInitialVisible===i.fireOnInitialVisible){Object.assign(n,r);return}A(n),I(e),Object.assign(n,r),e.unsubscribe=ne(t.target,n),e.subscription=i}function oe(e){I(e)}function se(e){e.kind===`rootRef`?l.invalidRootRef:l.invalidRoot;let{target:t}=e;return t==null?null:u(t)?t:null}function R(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 z(e){switch(e.kind){case`rootRef`:case`root`:return se(e);case`viewport`:return 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,rootRef:d,rootMargin:f=`0px`,className:p})=>{let _=t.default.useRef(null),y=t.default.useRef(null),b=R(d),x=v(f),S=ee(l),C=i!=null,w=t.default.Children.count(i),T=w===1&&t.default.isValidElement(i)?i:null,E=h(C,w,T),D=E||!T?null:T,{childNode:O,attachObservedChildRef:k}=g({originalChildRef:m(D),hasObservedChild:C,invalidChildWarning:E,shouldWarnAboutMissingDomRef:D!==null});return t.default.useEffect(()=>{},[p,C]),t.default.useEffect(()=>{},[E]),t.default.useEffect(()=>{},[a,o]),t.default.useEffect(()=>{let t=y.current;t&&ae(t,{onEnter:e,onLeave:n,onEvent:r})},[e,n,r]),t.default.useEffect(()=>{if(typeof window>`u`)return;let t=C?O:_.current,i=z(d===void 0?u===void 0?{kind:`viewport`}:{kind:`root`,target:u}:{kind:`rootRef`,target:b});if(!t){y.current&&L(y.current,{disabled:!1,node:null,target:i,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s});return}y.current||(y.current=ie({node:t,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s},{onEnter:e,onLeave:n,onEvent:r})),L(y.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(()=>()=>{y.current&&(oe(y.current),y.current=null)},[]),C?D?t.default.cloneElement(D,{ref:k}):t.default.createElement(t.default.Fragment,null,i):t.default.createElement(`div`,{ref:_,style:B,className:p})};function H(e,n,r){let i=t.default.useSyncExternalStore;if(i)return i(e,n,r);let[a,o]=t.default.useState(()=>r()),s=t.default.useRef(a);return(typeof window>`u`?t.default.useEffect:t.default.useLayoutEffect)(()=>{let t=()=>{let e=n();Object.is(s.current,e)||(s.current=e,o(e))};return t(),e(t)},[e,n]),a}function U(e,t,n){return n(e.current,t)?e.current:(e.current=t,t)}let W={x:0,y:0},G={width:0,height:0};function K(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 q(){return typeof window>`u`?G:{width:window.innerWidth,height:window.innerHeight}}function J(e){return!!(e&&typeof e==`object`&&!d(e)&&`current`in e)}function Y(e){return J(e)?e.current:e||(typeof window>`u`?null:window)}function ce(e){return e===window||d(e)}function X(e){if(ce(e))return{x:e.scrollX,y:e.scrollY};let t=e;return{x:t.scrollLeft,y:t.scrollTop}}function le(e){let t=Y(e);return t?X(t):W}function Z(e,t){return e.x===t.x&&e.y===t.y}function Q(e,t){return e.width===t.width&&e.height===t.height}function $(e){let n=e?.enabled!==!1,r=e?.passive,i=e?.throttleMs??16,a=t.default.useRef(q()),o=t.default.useCallback(()=>typeof window>`u`?G:n?U(a,q(),Q):a.current,[n]);return H(t.default.useCallback(e=>{if(typeof window>`u`||!n)return()=>{};let t=K(()=>{let t=q();Q(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,()=>G)}function ue(e){let n=e?.target,r=J(n),i=e?.enabled!==!1,a=e?.passive,o=e?.throttleMs??16,s=t.default.useRef(le(n)),[c,l]=t.default.useState(()=>r?Y(n):null);(typeof window>`u`?t.default.useEffect:t.default.useLayoutEffect)(()=>{if(!r)return;let e=Y(n);l(t=>t===e?t:e)});let u=r?c:Y(n),d=t.default.useCallback(()=>i?u?U(s,X(u),Z):U(s,W,Z):s.current,[i,u]);return H(t.default.useCallback(e=>{if(!i||!u)return()=>{};let t=K(()=>{let t=X(u);Z(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,()=>W)}e.AtomTrigger=V,e.useScrollPosition=ue,e.useViewportSize=$});
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);function l(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 u(e){return!!(e&&typeof e==`object`&&`window`in e&&e.window===e)}function d(e,t){if(e){if(typeof e==`function`){e(t);return}e.current=t}}function f(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 p(e){if(!e)return;let t=f(e.props);return t===void 0?f(e):t}function m(e,n,r){return e?n===1?r?r.type===t.default.Fragment?`fragmentChild`:null:`invalidChildElement`:`invalidChildCount`:null}function h({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)},[]),u=t.default.useCallback(t=>{if(d(e,t),t===null){c();return}if(l(t)){s.current=t,o(e=>e===t?e:t);return}c()},[c,e]);return t.default.useEffect(()=>{if(typeof window>`u`||!(n&&!r&&!a&&i))return;let e=window.setTimeout(()=>{s.current},16);return()=>{window.clearTimeout(e)}},[n,r,a,i]),{childNode:a,attachObservedChildRef:u}}function g(e){return Array.isArray(e)&&e.length===4&&e.every(e=>typeof e==`number`&&Number.isFinite(e))}function _(e){return typeof e==`string`?e:g(e)?e.map(e=>`${Object.is(e,-0)?0:e}px`).join(` `):`0px`}function v(e,t){let n=e.trim();if(/^[+-]?0(?:\.0+)?$/.test(n))return 0;let r=n.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(px|%)$/);if(!r)return 0;let[,i,a]=r,o=Number.parseFloat(i);return a===`%`?o/100*t:o}function y(e,t,n){let r=e.trim().split(/\s+/).filter(Boolean);if(r.length>4)return{top:0,right:0,bottom:0,left:0};let[i=`0px`,a=i,o=i,s=a]=r;return{top:v(i,n),right:v(a,t),bottom:v(o,n),left:v(s,t)}}function b(e,t){let n=y(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 x(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 S(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 C(e,t){let n=e.width*e.height;return n<=0?0:t.width*t.height/n}function w(e){return Math.min(1,Math.max(0,e))}function T(e){return e==null||typeof e!=`number`||!Number.isFinite(e)?0:w(e)}function E(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 D(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 O(e,t,n,r){return!(n&&t.entered+t.left>0||r&&(e===`enter`&&t.entered>0||e===`leave`&&t.left>0))}function k(e){return e.once?e.counts.entered+e.counts.left>0:e.oncePerDirection?e.counts.entered>0&&e.counts.left>0:!1}function A(e){e.previousTriggerActive=void 0,e.previousRect=null}function j(e,t,n,r){let i=x(e.node.getBoundingClientRect()),a=b(t,e.rootMargin),o=S(i,a),s=C(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`:E(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(!O(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:D(p),timestamp:f};e.onEvent?.(_),h===`enter`?e.onEnter?.(_):e.onLeave?.(_),k(e)&&e.unsubscribe?.()}let M=new WeakMap;function N(){return new DOMRect(0,0,window.innerWidth,window.innerHeight)}function P(e){return e===window||u(e)}function F(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=P(e)?N():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)j(e,r,n,i);t.previousBaseRootBounds=new DOMRect(r.left,r.top,r.width,r.height)},r=(e=`geometry-change`)=>{(t.pendingSampleCause===null||t.pendingSampleCause===`geometry-change`&&e!==`geometry-change`||t.pendingSampleCause===`root-change`&&e===`scroll`)&&(t.pendingSampleCause=e),t.rafId===0&&(t.rafId=window.requestAnimationFrame(()=>{t.rafId=0,n()}))},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),P(e)||t.resizeObserver.observe(e)),typeof IntersectionObserver<`u`&&(t.intersectionObserver=new IntersectionObserver(()=>{r(`geometry-change`)},{root:P(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 I(e){let t=M.get(e);if(t)return t;let n=F(e);return M.set(e,n),n}function L(e,t){let n=I(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.unsubscribe=void 0,n.registrations.size===0&&(n.cleanup(),M.delete(e)))};return t.unsubscribe=a,a}function R(e,t){return{...e,...t,previousTriggerActive:void 0,previousRect:null,counts:{entered:0,left:0}}}function z(e){e.unsubscribe?.(),e.unsubscribe=null,e.subscription=null}function B(e,t){return{registration:R(e,t),subscription:null,unsubscribe:null}}function V(e,t){e.registration.onEnter=t.onEnter,e.registration.onLeave=t.onLeave,e.registration.onEvent=t.onEvent}function H(e,t){let n=e.registration;if(!t.node){A(n),z(e);return}let r={node:t.node,rootMargin:t.rootMargin,threshold:t.threshold,once:t.once,oncePerDirection:t.oncePerDirection,fireOnInitialVisible:t.fireOnInitialVisible};if(t.disabled||!t.target){z(e),Object.assign(n,r),A(n);return}let i={...r,target:t.target};if(e.subscription!==null&&e.subscription.node===i.node&&e.subscription.target===i.target&&e.subscription.rootMargin===i.rootMargin&&e.subscription.threshold===i.threshold&&e.subscription.once===i.once&&e.subscription.oncePerDirection===i.oncePerDirection&&e.subscription.fireOnInitialVisible===i.fireOnInitialVisible){Object.assign(n,r);return}A(n),z(e),Object.assign(n,r),e.unsubscribe=L(t.target,n),e.subscription=i}function U(e){z(e)}function W(e){e.kind;let{target:t}=e;return t==null?null:l(t)?t:null}function G(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 K(e){switch(e.kind){case`rootRef`:case`root`:return W(e);case`viewport`:return typeof window>`u`?null:window}}let q={display:`table`};e.AtomTrigger=({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:f=`0px`,className:g})=>{let v=t.default.useRef(null),y=t.default.useRef(null),b=G(d),x=_(f),S=T(l),C=i!=null,w=t.default.Children.count(i),E=w===1&&t.default.isValidElement(i)?i:null,D=m(C,w,E),O=D||!E?null:E,{childNode:k,attachObservedChildRef:A}=h({originalChildRef:p(O),hasObservedChild:C,invalidChildWarning:D,shouldWarnAboutMissingDomRef:O!==null});return t.default.useEffect(()=>{},[g,C]),t.default.useEffect(()=>{},[D]),t.default.useEffect(()=>{},[a,o]),t.default.useEffect(()=>{let t=y.current;t&&V(t,{onEnter:e,onLeave:n,onEvent:r})},[e,n,r]),t.default.useEffect(()=>{if(typeof window>`u`)return;let t=C?k:v.current,i=K(d===void 0?u===void 0?{kind:`viewport`}:{kind:`root`,target:u}:{kind:`rootRef`,target:b});if(!t){y.current&&H(y.current,{disabled:!1,node:null,target:i,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s});return}y.current||(y.current=B({node:t,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s},{onEnter:e,onLeave:n,onEvent:r})),H(y.current,{disabled:c,node:t,target:i,rootMargin:x,threshold:S,once:a,oncePerDirection:o,fireOnInitialVisible:s})},[c,x,S,a,o,s,k,u,d,b,C]),t.default.useEffect(()=>()=>{y.current&&(U(y.current),y.current=null)},[]),C?O?t.default.cloneElement(O,{ref:A}):t.default.createElement(t.default.Fragment,null,i):t.default.createElement(`div`,{ref:v,style:q,className:g})}});
package/package.json CHANGED
@@ -1,15 +1,22 @@
1
1
  {
2
2
  "name": "react-atom-trigger",
3
- "version": "2.0.11",
4
- "description": "Geometry-based scroll trigger for React with precise enter/leave control. A modern alternative to react-waypoint.",
3
+ "version": "2.1.1",
4
+ "description": "Geometry-based scroll trigger for React with predictable enter/leave behavior. A modern alternative to react-waypoint and React Intersection Observer solutions.",
5
5
  "keywords": [
6
- "intersection",
7
- "observer",
8
- "on-scroll",
6
+ "element visibility",
7
+ "in view",
8
+ "intersection observer",
9
9
  "react",
10
+ "react intersection observer",
11
+ "react waypoint alternative",
10
12
  "scroll",
11
- "scroll-into-view",
12
- "v2"
13
+ "scroll animation",
14
+ "scroll detection",
15
+ "scroll trigger",
16
+ "scroll-trigger",
17
+ "viewport",
18
+ "visibility",
19
+ "waypoint"
13
20
  ],
14
21
  "homepage": "https://atomtrigger.dev",
15
22
  "bugs": {