@duboseweb/motus 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -318,36 +318,6 @@ npm run test:pack # pack, install into a throwaway project, assert it works
318
318
  npm run check:pkg # publint + are-the-types-wrong
319
319
  ```
320
320
 
321
- ### Releasing
322
-
323
- Publishing runs from CI on a version tag, using npm
324
- [trusted publishing](https://docs.npmjs.com/trusted-publishers) — there is no npm token stored
325
- anywhere, and npm generates a provenance attestation automatically, linking the published tarball
326
- to the exact commit and workflow that built it.
327
-
328
- Work lands on `develop`. `main` is protected and takes pull requests only, so the version bump is
329
- made on `develop` and the tag is cut from `main` after the merge:
330
-
331
- ```sh
332
- # on develop — bump the version without tagging yet
333
- npm version patch --no-git-tag-version # or minor / major
334
- git commit -am "Release v1.0.1"
335
- git push
336
-
337
- # open a pull request from develop to main and merge it
338
-
339
- git checkout main && git pull
340
- git tag v1.0.1
341
- git push origin v1.0.1 # this is what triggers the release
342
- ```
343
-
344
- Tags are not covered by the branch protection, so the final push is what starts the publish.
345
-
346
- The workflow refuses to publish if the tagged commit is not reachable from `main`, or if the tag
347
- and `package.json` disagree. It fails loudly rather than skipping, so a release that did not happen
348
- is never mistaken for one that did. `prepublishOnly` then runs lint, typecheck, tests, the build,
349
- `check:pkg` and the package smoke test before anything reaches the registry.
350
-
351
321
  ---
352
322
 
353
323
  ## License
package/dist/motus.cjs CHANGED
@@ -385,6 +385,18 @@ const getThreshold = (anchorPlacement) => {
385
385
  }
386
386
  };
387
387
 
388
+ /**
389
+ * The target sits entirely above the trigger zone.
390
+ *
391
+ * A reload restores the scroll position before `init()`, so the browser's first
392
+ * record for anything already scrolled past reports it as not intersecting. It
393
+ * will never cross the zone again, and the stylesheet keeps `[data-motus]`
394
+ * hidden until it animates — without this those sections stay blank. Reads the
395
+ * entry only: no layout. A null `rootBounds` (cross-origin iframe) is not past.
396
+ */
397
+ const isPast = (entry) => !entry.isIntersecting &&
398
+ entry.rootBounds !== null &&
399
+ entry.boundingClientRect.bottom <= entry.rootBounds.top;
388
400
  /**
389
401
  * Creates the IntersectionObservers for a set of resolved configs.
390
402
  *
@@ -411,7 +423,10 @@ windowHeight = window.innerHeight) => {
411
423
  if (!targets)
412
424
  return;
413
425
  for (const config of targets) {
414
- if (entry.isIntersecting) {
426
+ // A config that can animate out treats "past" as out, so it only reveals
427
+ // inside the zone. Everything else counts scrolling past as reaching it.
428
+ const reversible = config.mirror && !config.once;
429
+ if (entry.isIntersecting || (!reversible && isPast(entry))) {
415
430
  if (!config.animated) {
416
431
  addClasses(config.node, config.animatedClassNames);
417
432
  fireEvent(EVENT_IN, config.node, config.id);
@@ -419,7 +434,7 @@ windowHeight = window.innerHeight) => {
419
434
  setAnimated(config.node, true);
420
435
  }
421
436
  }
422
- else if (config.animated && config.mirror && !config.once) {
437
+ else if (config.animated && reversible) {
423
438
  removeClasses(config.node, config.animatedClassNames);
424
439
  fireEvent(EVENT_OUT, config.node, config.id);
425
440
  config.animated = false;
package/dist/motus.js CHANGED
@@ -381,6 +381,18 @@ const getThreshold = (anchorPlacement) => {
381
381
  }
382
382
  };
383
383
 
384
+ /**
385
+ * The target sits entirely above the trigger zone.
386
+ *
387
+ * A reload restores the scroll position before `init()`, so the browser's first
388
+ * record for anything already scrolled past reports it as not intersecting. It
389
+ * will never cross the zone again, and the stylesheet keeps `[data-motus]`
390
+ * hidden until it animates — without this those sections stay blank. Reads the
391
+ * entry only: no layout. A null `rootBounds` (cross-origin iframe) is not past.
392
+ */
393
+ const isPast = (entry) => !entry.isIntersecting &&
394
+ entry.rootBounds !== null &&
395
+ entry.boundingClientRect.bottom <= entry.rootBounds.top;
384
396
  /**
385
397
  * Creates the IntersectionObservers for a set of resolved configs.
386
398
  *
@@ -407,7 +419,10 @@ windowHeight = window.innerHeight) => {
407
419
  if (!targets)
408
420
  return;
409
421
  for (const config of targets) {
410
- if (entry.isIntersecting) {
422
+ // A config that can animate out treats "past" as out, so it only reveals
423
+ // inside the zone. Everything else counts scrolling past as reaching it.
424
+ const reversible = config.mirror && !config.once;
425
+ if (entry.isIntersecting || (!reversible && isPast(entry))) {
411
426
  if (!config.animated) {
412
427
  addClasses(config.node, config.animatedClassNames);
413
428
  fireEvent(EVENT_IN, config.node, config.id);
@@ -415,7 +430,7 @@ windowHeight = window.innerHeight) => {
415
430
  setAnimated(config.node, true);
416
431
  }
417
432
  }
418
- else if (config.animated && config.mirror && !config.once) {
433
+ else if (config.animated && reversible) {
419
434
  removeClasses(config.node, config.animatedClassNames);
420
435
  fireEvent(EVENT_OUT, config.node, config.id);
421
436
  config.animated = false;
package/dist/motus.umd.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! dwg-motus | MIT License | https://github.com/dubose-web/dwg-motus */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Motus=t()}(this,function(){"use strict";const e="data-motus",t="data-motus-inactive",n="motus-ready",o="--motus-duration",s="--motus-delay",a="--motus-easing",r="[dwg-motus]",i=Object.freeze({sm:576,md:768,lg:992,xl:1200,xxl:1400}),c=["sm","md","lg","xl","xxl"],u=Object.freeze({offset:120,delay:0,easing:"ease",duration:400,disable:"lg",breakpoints:i,once:!1,mirror:!1,anchorPlacement:"top-bottom",startEvent:"DOMContentLoaded",animatedClassName:"motus-animate",initClassName:"motus-init",useClassNames:!1,disableMutationObserver:!1,debounceDelay:50}),d=["top-bottom","top-center","top-top","center-bottom","center-center","center-top","bottom-bottom","bottom-center","bottom-top"];const l=()=>matchMedia("(pointer: coarse) and (hover: none) and (max-width: 767px)").matches,m=()=>matchMedia("(pointer: coarse) and (hover: none)").matches,b={"ease-in-back":"cubic-bezier(.6, -.28, .735, .045)","ease-out-back":"cubic-bezier(.175, .885, .32, 1.275)","ease-in-out-back":"cubic-bezier(.68, -.55, .265, 1.55)","ease-in-sine":"cubic-bezier(.47, 0, .745, .715)","ease-out-sine":"cubic-bezier(.39, .575, .565, 1)","ease-in-out-sine":"cubic-bezier(.445, .05, .55, .95)","ease-in-quad":"cubic-bezier(.55, .085, .68, .53)","ease-out-quad":"cubic-bezier(.25, .46, .45, .94)","ease-in-out-quad":"cubic-bezier(.455, .03, .515, .955)","ease-in-cubic":"cubic-bezier(.55, .055, .675, .19)","ease-out-cubic":"cubic-bezier(.215, .61, .355, 1)","ease-in-out-cubic":"cubic-bezier(.645, .045, .355, 1)","ease-in-quart":"cubic-bezier(.895, .03, .685, .22)","ease-out-quart":"cubic-bezier(.165, .84, .44, 1)","ease-in-out-quart":"cubic-bezier(.77, 0, .175, 1)"},f=e=>{var t;return null!==(t=b[e])&&void 0!==t?t:e},p=(e,t)=>{for(const n of t)e.classList.add(n)},v=(e,t)=>{for(const n of t)e.classList.remove(n)},h=(e,t,n)=>{const o={node:t};document.dispatchEvent(new CustomEvent(e,{detail:o})),n&&document.dispatchEvent(new CustomEvent(`${e}:${n}`,{detail:o}))},y=[o,s,a],g=e=>{if(e)for(const t of y)e.style.removeProperty(t)},w=e=>g(e);let $=new WeakMap;const E=(e,t)=>{$.set(e,t)},x=(e,t)=>t?e.classList.contains(t):!0===$.get(e);function N(t,n,o){const s=t.getAttribute((t=>`${e}-${t}`)(n));return"true"===s||"false"!==s&&(null!=s?s:o)}const M=(e,t)=>{const n=N(e,t);return"string"==typeof n?n:void 0},C=(e,t)=>{var n;const o=M(e,"anchor");if(!o)return e;if(t.has(o))return null!==(n=t.get(o))&&void 0!==n?n:e;let s=null;try{s=document.querySelector(o)}catch(e){console.warn(`${r} Invalid data-motus-anchor selector: ${o}`)}return t.set(o,s),null!=s?s:e},k=(t,n)=>{const r=new Map,i=n.animatedClassName?[n.animatedClassName]:[];return t.map(t=>{var c,u;const d=Boolean(N(t,"mirror",n.mirror)),l=Boolean(N(t,"once",n.once)),m=null!==(c=M(t,"id"))&&void 0!==c?c:null,b=null!==(u=M(t,"anchor-placement"))&&void 0!==u?u:n.anchorPlacement,p=Number(N(t,"offset",n.offset)),v=Number.isFinite(p)?p:n.offset;var h,y;h=t,(y={duration:M(t,"duration"),delay:M(t,"delay"),easing:M(t,"easing")}).duration&&h.style.setProperty(o,`${y.duration}ms`),y.delay&&h.style.setProperty(s,`${y.delay}ms`),y.easing&&h.style.setProperty(a,f(y.easing)),n.initClassName&&t.classList.add(n.initClassName);const g=n.useClassNames?t.getAttribute(e):null,w=g?i.concat(g.split(" ").filter(e=>""!==e)):i;return{node:t,observeTarget:C(t,r),mirror:d,once:l,id:m,animatedClassNames:w,animated:x(t,n.animatedClassName),anchorPlacement:b,offset:v}})},z=(e,t,n=window.innerHeight)=>{switch(e){case"top-center":case"center-center":case"bottom-center":{const e=Math.max(Math.round(n/2)-t,1);return`${-e}px 0px ${-e}px 0px`}case"top-top":case"center-top":case"bottom-top":return`${Math.max(t,1)}px 0px ${-(n-t)}px 0px`;default:return`0px 0px ${-t}px 0px`}},O=e=>{switch(e){case"center-bottom":case"center-center":case"center-top":return.5;default:return 0}},P=t=>{let n=!1;const o=new MutationObserver(o=>{if(n)return;o.some(t=>(t=>{for(const n of t){if(n.nodeType!==Node.ELEMENT_NODE)continue;const t=n;if(t.hasAttribute(e)||t.querySelector(`[${e}]`))return!0}return!1})(t.addedNodes))&&(n=!0,requestAnimationFrame(()=>{n=!1,t()}))});return o.observe(document.documentElement,{childList:!0,subtree:!0}),o},L=[...c,"phone","tablet","mobile"],q=e=>"number"==typeof e&&Number.isFinite(e)&&e>=0;let A=[],j=null,D=null,T=[],S=!1,I=null,F=Object.assign({},u);const U=(e,t,n)=>{e.addEventListener(t,n),T.push({target:e,event:t,fn:n})},H=()=>[...document.querySelectorAll(`[${e}]`)],B=e=>{const{disable:t}=e;return document.documentElement.hasAttribute("data-motus-disabled")||!0===t||"string"==typeof t&&t in e.breakpoints&&(n=e.breakpoints[t],matchMedia(`(max-width: ${n-.02}px)`).matches)||"mobile"===t&&m()||"phone"===t&&l()||"tablet"===t&&m()&&!l()||"function"==typeof t&&!0===t();var n},R=()=>{S&&(I=window.innerHeight,A=H(),null==j||j.disconnect(),j=((e,t=window.innerHeight)=>{let n=!1;const o=new Map,s=(e,t)=>{const n=t.targets.get(e.target);if(n){for(const t of n)e.isIntersecting?t.animated||(p(t.node,t.animatedClassNames),h("motus:in",t.node,t.id),t.animated=!0,E(t.node,!0)):t.animated&&t.mirror&&!t.once&&(v(t.node,t.animatedClassNames),h("motus:out",t.node,t.id),t.animated=!1,E(t.node,!1));n.every(e=>e.once&&e.animated)&&t.observer.unobserve(e.target)}};for(const a of e){if(a.once&&a.animated)continue;const e=`${a.anchorPlacement}-${a.offset}`;let r=o.get(e);if(!r){const i=new Map,c=new IntersectionObserver(e=>{if(n)for(const t of e)s(t,r);else r.buffered.push(...e)},{rootMargin:z(a.anchorPlacement,a.offset,t),threshold:O(a.anchorPlacement)});r={observer:c,targets:i,buffered:[]},o.set(e,r)}const i=r.targets.get(a.observeTarget);i?i.push(a):(r.targets.set(a.observeTarget,[a]),r.observer.observe(a.observeTarget))}return{disconnect:()=>{for(const e of o.values())e.observer.disconnect();o.clear()},activate:()=>{n=!0;for(const e of o.values()){const t=e.buffered.concat(e.observer.takeRecords());e.buffered.length=0;for(const n of t)s(n,e)}}}})(k(A,F),I),document.body.classList.contains(n)?null==j||j.activate():requestAnimationFrame(()=>{requestAnimationFrame(()=>{document.body.classList.add(n),null==j||j.activate()})}))},W=()=>{S=!0,R()},_=()=>{S&&I!==window.innerHeight&&R()},G=()=>{B(F)?J():S?(document.documentElement.removeAttribute(t),R()):Q(F)},J=()=>{var e;document.documentElement.setAttribute(t,""),null==D||D.disconnect(),D=null,null==j||j.disconnect(),j=null,null===(e=document.body)||void 0===e||e.classList.remove(n);for(const e of A)w(e),F.initClassName&&e.classList.remove(F.initClassName),F.animatedClassName&&e.classList.remove(F.animatedClassName);$=new WeakMap},K=()=>{J();for(const{target:e,event:t,fn:n}of T)e.removeEventListener(t,n);T=[],g(document.body),A=[],S=!1,I=null},Q=e=>(S&&K(),F=((e={})=>{const t=[];for(const n of Object.keys(e))n in u||t.push(`Unknown option "${n}".`);const n=Object.assign({},u,e);for(const e of["duration","delay","offset"])q(n[e])||(t.push(`"${e}" must be a non-negative number, received ${String(n[e])}. Using ${u[e]}.`),n[e]=u[e]);d.includes(n.anchorPlacement)||(t.push(`"anchorPlacement" must be one of ${d.join(", ")}. Using ${u.anchorPlacement}.`),n.anchorPlacement=u.anchorPlacement),"string"!=typeof n.disable||L.includes(n.disable)||(t.push(`"disable" must be a boolean, a function, or one of ${L.join(", ")}. Using ${String(u.disable)}.`),n.disable=u.disable),n.breakpoints=Object.assign({},u.breakpoints,e.breakpoints);for(const e of c){const o=n.breakpoints[e];("number"!=typeof o||!Number.isFinite(o)||o<=0)&&(t.push(`"breakpoints.${e}" must be a positive number, received ${String(o)}. Using ${u.breakpoints[e]}.`),n.breakpoints[e]=u.breakpoints[e])}"string"==typeof n.startEvent&&""!==n.startEvent||(t.push(`"startEvent" must be a non-empty string. Using ${u.startEvent}.`),n.startEvent=u.startEvent);const o=n.debounceDelay,s=Number.isFinite(o)?Math.min(500,Math.max(16,o)):u.debounceDelay;return s!==o&&t.push(`"debounceDelay" clamped from ${String(o)} to ${s} (allowed range 16–500ms).`),n.debounceDelay=s,t.length>0&&console.warn(`${r} Invalid options:\n - ${t.join("\n - ")}`),n})(e),document.documentElement.removeAttribute(t),"undefined"!=typeof window&&"function"==typeof window.IntersectionObserver&&"function"==typeof window.IntersectionObserverEntry&&"intersectionRatio"in window.IntersectionObserverEntry.prototype?(A=H(),B(F)?void J():(F.disableMutationObserver||(D=P(G)),(e=>{const{body:t}=document;t&&(t.style.setProperty(o,`${e.duration}ms`),t.style.setProperty(s,`${e.delay}ms`),t.style.setProperty(a,f(e.easing)))})(F),"DOMContentLoaded"===F.startEvent||"load"===F.startEvent?U(window,"load",()=>{S||W()}):U(document,F.startEvent,()=>W()),"DOMContentLoaded"!==F.startEvent||"complete"!==document.readyState&&"interactive"!==document.readyState||W(),U(window,"resize",function(e,t){let n;return(...o)=>{clearTimeout(n),n=setTimeout(()=>e(...o),t)}}(_,F.debounceDelay)),A)):(console.warn(`${r} IntersectionObserver is not supported in this browser; animations are disabled.`),void document.documentElement.setAttribute(t,"")));return Object.freeze({init:Q,refresh:()=>R(),refreshHard:G,destroy:K})});
2
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Motus=t()}(this,function(){"use strict";const e="data-motus",t="data-motus-inactive",n="motus-ready",o="--motus-duration",s="--motus-delay",a="--motus-easing",r="[dwg-motus]",i=Object.freeze({sm:576,md:768,lg:992,xl:1200,xxl:1400}),c=["sm","md","lg","xl","xxl"],u=Object.freeze({offset:120,delay:0,easing:"ease",duration:400,disable:"lg",breakpoints:i,once:!1,mirror:!1,anchorPlacement:"top-bottom",startEvent:"DOMContentLoaded",animatedClassName:"motus-animate",initClassName:"motus-init",useClassNames:!1,disableMutationObserver:!1,debounceDelay:50}),d=["top-bottom","top-center","top-top","center-bottom","center-center","center-top","bottom-bottom","bottom-center","bottom-top"];const l=()=>matchMedia("(pointer: coarse) and (hover: none) and (max-width: 767px)").matches,m=()=>matchMedia("(pointer: coarse) and (hover: none)").matches,b={"ease-in-back":"cubic-bezier(.6, -.28, .735, .045)","ease-out-back":"cubic-bezier(.175, .885, .32, 1.275)","ease-in-out-back":"cubic-bezier(.68, -.55, .265, 1.55)","ease-in-sine":"cubic-bezier(.47, 0, .745, .715)","ease-out-sine":"cubic-bezier(.39, .575, .565, 1)","ease-in-out-sine":"cubic-bezier(.445, .05, .55, .95)","ease-in-quad":"cubic-bezier(.55, .085, .68, .53)","ease-out-quad":"cubic-bezier(.25, .46, .45, .94)","ease-in-out-quad":"cubic-bezier(.455, .03, .515, .955)","ease-in-cubic":"cubic-bezier(.55, .055, .675, .19)","ease-out-cubic":"cubic-bezier(.215, .61, .355, 1)","ease-in-out-cubic":"cubic-bezier(.645, .045, .355, 1)","ease-in-quart":"cubic-bezier(.895, .03, .685, .22)","ease-out-quart":"cubic-bezier(.165, .84, .44, 1)","ease-in-out-quart":"cubic-bezier(.77, 0, .175, 1)"},f=e=>{var t;return null!==(t=b[e])&&void 0!==t?t:e},p=(e,t)=>{for(const n of t)e.classList.add(n)},v=(e,t)=>{for(const n of t)e.classList.remove(n)},h=(e,t,n)=>{const o={node:t};document.dispatchEvent(new CustomEvent(e,{detail:o})),n&&document.dispatchEvent(new CustomEvent(`${e}:${n}`,{detail:o}))},y=[o,s,a],g=e=>{if(e)for(const t of y)e.style.removeProperty(t)},w=e=>g(e);let $=new WeakMap;const E=(e,t)=>{$.set(e,t)},x=(e,t)=>t?e.classList.contains(t):!0===$.get(e);function N(t,n,o){const s=t.getAttribute((t=>`${e}-${t}`)(n));return"true"===s||"false"!==s&&(null!=s?s:o)}const C=(e,t)=>{const n=N(e,t);return"string"==typeof n?n:void 0},M=(e,t)=>{var n;const o=C(e,"anchor");if(!o)return e;if(t.has(o))return null!==(n=t.get(o))&&void 0!==n?n:e;let s=null;try{s=document.querySelector(o)}catch(e){console.warn(`${r} Invalid data-motus-anchor selector: ${o}`)}return t.set(o,s),null!=s?s:e},k=(t,n)=>{const r=new Map,i=n.animatedClassName?[n.animatedClassName]:[];return t.map(t=>{var c,u;const d=Boolean(N(t,"mirror",n.mirror)),l=Boolean(N(t,"once",n.once)),m=null!==(c=C(t,"id"))&&void 0!==c?c:null,b=null!==(u=C(t,"anchor-placement"))&&void 0!==u?u:n.anchorPlacement,p=Number(N(t,"offset",n.offset)),v=Number.isFinite(p)?p:n.offset;var h,y;h=t,(y={duration:C(t,"duration"),delay:C(t,"delay"),easing:C(t,"easing")}).duration&&h.style.setProperty(o,`${y.duration}ms`),y.delay&&h.style.setProperty(s,`${y.delay}ms`),y.easing&&h.style.setProperty(a,f(y.easing)),n.initClassName&&t.classList.add(n.initClassName);const g=n.useClassNames?t.getAttribute(e):null,w=g?i.concat(g.split(" ").filter(e=>""!==e)):i;return{node:t,observeTarget:M(t,r),mirror:d,once:l,id:m,animatedClassNames:w,animated:x(t,n.animatedClassName),anchorPlacement:b,offset:v}})},z=(e,t,n=window.innerHeight)=>{switch(e){case"top-center":case"center-center":case"bottom-center":{const e=Math.max(Math.round(n/2)-t,1);return`${-e}px 0px ${-e}px 0px`}case"top-top":case"center-top":case"bottom-top":return`${Math.max(t,1)}px 0px ${-(n-t)}px 0px`;default:return`0px 0px ${-t}px 0px`}},O=e=>{switch(e){case"center-bottom":case"center-center":case"center-top":return.5;default:return 0}},P=e=>!e.isIntersecting&&null!==e.rootBounds&&e.boundingClientRect.bottom<=e.rootBounds.top,L=t=>{let n=!1;const o=new MutationObserver(o=>{if(n)return;o.some(t=>(t=>{for(const n of t){if(n.nodeType!==Node.ELEMENT_NODE)continue;const t=n;if(t.hasAttribute(e)||t.querySelector(`[${e}]`))return!0}return!1})(t.addedNodes))&&(n=!0,requestAnimationFrame(()=>{n=!1,t()}))});return o.observe(document.documentElement,{childList:!0,subtree:!0}),o},q=[...c,"phone","tablet","mobile"],A=e=>"number"==typeof e&&Number.isFinite(e)&&e>=0;let j=[],D=null,T=null,I=[],S=!1,F=null,U=Object.assign({},u);const H=(e,t,n)=>{e.addEventListener(t,n),I.push({target:e,event:t,fn:n})},B=()=>[...document.querySelectorAll(`[${e}]`)],R=e=>{const{disable:t}=e;return document.documentElement.hasAttribute("data-motus-disabled")||!0===t||"string"==typeof t&&t in e.breakpoints&&(n=e.breakpoints[t],matchMedia(`(max-width: ${n-.02}px)`).matches)||"mobile"===t&&m()||"phone"===t&&l()||"tablet"===t&&m()&&!l()||"function"==typeof t&&!0===t();var n},W=()=>{S&&(F=window.innerHeight,j=B(),null==D||D.disconnect(),D=((e,t=window.innerHeight)=>{let n=!1;const o=new Map,s=(e,t)=>{const n=t.targets.get(e.target);if(n){for(const t of n){const n=t.mirror&&!t.once;e.isIntersecting||!n&&P(e)?t.animated||(p(t.node,t.animatedClassNames),h("motus:in",t.node,t.id),t.animated=!0,E(t.node,!0)):t.animated&&n&&(v(t.node,t.animatedClassNames),h("motus:out",t.node,t.id),t.animated=!1,E(t.node,!1))}n.every(e=>e.once&&e.animated)&&t.observer.unobserve(e.target)}};for(const a of e){if(a.once&&a.animated)continue;const e=`${a.anchorPlacement}-${a.offset}`;let r=o.get(e);if(!r){const i=new Map,c=new IntersectionObserver(e=>{if(n)for(const t of e)s(t,r);else r.buffered.push(...e)},{rootMargin:z(a.anchorPlacement,a.offset,t),threshold:O(a.anchorPlacement)});r={observer:c,targets:i,buffered:[]},o.set(e,r)}const i=r.targets.get(a.observeTarget);i?i.push(a):(r.targets.set(a.observeTarget,[a]),r.observer.observe(a.observeTarget))}return{disconnect:()=>{for(const e of o.values())e.observer.disconnect();o.clear()},activate:()=>{n=!0;for(const e of o.values()){const t=e.buffered.concat(e.observer.takeRecords());e.buffered.length=0;for(const n of t)s(n,e)}}}})(k(j,U),F),document.body.classList.contains(n)?null==D||D.activate():requestAnimationFrame(()=>{requestAnimationFrame(()=>{document.body.classList.add(n),null==D||D.activate()})}))},_=()=>{S=!0,W()},G=()=>{S&&F!==window.innerHeight&&W()},J=()=>{R(U)?K():S?(document.documentElement.removeAttribute(t),W()):V(U)},K=()=>{var e;document.documentElement.setAttribute(t,""),null==T||T.disconnect(),T=null,null==D||D.disconnect(),D=null,null===(e=document.body)||void 0===e||e.classList.remove(n);for(const e of j)w(e),U.initClassName&&e.classList.remove(U.initClassName),U.animatedClassName&&e.classList.remove(U.animatedClassName);$=new WeakMap},Q=()=>{K();for(const{target:e,event:t,fn:n}of I)e.removeEventListener(t,n);I=[],g(document.body),j=[],S=!1,F=null},V=e=>(S&&Q(),U=((e={})=>{const t=[];for(const n of Object.keys(e))n in u||t.push(`Unknown option "${n}".`);const n=Object.assign({},u,e);for(const e of["duration","delay","offset"])A(n[e])||(t.push(`"${e}" must be a non-negative number, received ${String(n[e])}. Using ${u[e]}.`),n[e]=u[e]);d.includes(n.anchorPlacement)||(t.push(`"anchorPlacement" must be one of ${d.join(", ")}. Using ${u.anchorPlacement}.`),n.anchorPlacement=u.anchorPlacement),"string"!=typeof n.disable||q.includes(n.disable)||(t.push(`"disable" must be a boolean, a function, or one of ${q.join(", ")}. Using ${String(u.disable)}.`),n.disable=u.disable),n.breakpoints=Object.assign({},u.breakpoints,e.breakpoints);for(const e of c){const o=n.breakpoints[e];("number"!=typeof o||!Number.isFinite(o)||o<=0)&&(t.push(`"breakpoints.${e}" must be a positive number, received ${String(o)}. Using ${u.breakpoints[e]}.`),n.breakpoints[e]=u.breakpoints[e])}"string"==typeof n.startEvent&&""!==n.startEvent||(t.push(`"startEvent" must be a non-empty string. Using ${u.startEvent}.`),n.startEvent=u.startEvent);const o=n.debounceDelay,s=Number.isFinite(o)?Math.min(500,Math.max(16,o)):u.debounceDelay;return s!==o&&t.push(`"debounceDelay" clamped from ${String(o)} to ${s} (allowed range 16–500ms).`),n.debounceDelay=s,t.length>0&&console.warn(`${r} Invalid options:\n - ${t.join("\n - ")}`),n})(e),document.documentElement.removeAttribute(t),"undefined"!=typeof window&&"function"==typeof window.IntersectionObserver&&"function"==typeof window.IntersectionObserverEntry&&"intersectionRatio"in window.IntersectionObserverEntry.prototype?(j=B(),R(U)?void K():(U.disableMutationObserver||(T=L(J)),(e=>{const{body:t}=document;t&&(t.style.setProperty(o,`${e.duration}ms`),t.style.setProperty(s,`${e.delay}ms`),t.style.setProperty(a,f(e.easing)))})(U),"DOMContentLoaded"===U.startEvent||"load"===U.startEvent?H(window,"load",()=>{S||_()}):H(document,U.startEvent,()=>_()),"DOMContentLoaded"!==U.startEvent||"complete"!==document.readyState&&"interactive"!==document.readyState||_(),H(window,"resize",function(e,t){let n;return(...o)=>{clearTimeout(n),n=setTimeout(()=>e(...o),t)}}(G,U.debounceDelay)),j)):(console.warn(`${r} IntersectionObserver is not supported in this browser; animations are disabled.`),void document.documentElement.setAttribute(t,"")));return Object.freeze({init:V,refresh:()=>W(),refreshHard:J,destroy:Q})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duboseweb/motus",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Animate on scroll via IntersectionObserver — modular, typed, zero dependencies",
5
5
  "author": "DuBose Web",
6
6
  "license": "MIT",