motimeline 2.11.0 → 2.12.0

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
@@ -20,6 +20,8 @@ Responsive two-column timeline layout library — plain JavaScript, zero depende
20
20
  - **Optional theme** — built-in card theme with image banners and overlapping avatars
21
21
  - **CSS custom properties** — override colors and sizes with one line of CSS
22
22
  - **Dynamic items** — append, insert, or inject `<li>` elements at any time via `initNewItems()`, `addItems()`, or `insertItem()`
23
+ - **Custom card renderer** — pass `renderCard(item, cardEl)` to inject any HTML, vanilla JS, or full React components into each card slot; the library handles everything else
24
+ - **Publisher-ready ad slots** — the most publisher-friendly timeline on npm: `adSlots` injects viewport-triggered `<li>` placeholders at configurable cadences (`every_n` or `random`), fires `onEnterViewport` exactly once per slot at ≥ 50% visibility, works seamlessly with infinite scroll, and cleans up on `destroy()`. Drop in AdSense, house ads, or any network with three lines of code.
23
25
  - **Bootstrap compatible** — wrap the `<ul>` in a Bootstrap `.container`, no config needed
24
26
  - **ESM · CJS · UMD** — works with any bundler or as a plain `<script>` tag
25
27
 
@@ -190,6 +192,7 @@ tl.refresh(); // re-layout all items (called automatically on resi
190
192
  tl.initNewItems(); // pick up manually appended <li> elements
191
193
  tl.addItems(items); // create and append <li> from an array of item objects (or JSON string)
192
194
  tl.insertItem(item, index); // insert a single item at a specific index (or random if omitted)
195
+ tl.clear(); // remove all items and ad slots, reset counters — instance stays alive
193
196
  tl.destroy(); // remove listeners and reset DOM classes
194
197
  ```
195
198
 
@@ -465,6 +468,9 @@ No framework option needed. Wrap the `<ul>` inside a Bootstrap `.container`:
465
468
 
466
469
  ## Changelog
467
470
 
471
+ ### v2.12.0
472
+ - New method `clear()` — removes all `.mo-item` and `.mo-ad-slot` elements from the container and resets internal counters (`lastItemIdx`, `_adRealCount`) without destroying the instance. Active `IntersectionObserver`s are disconnected but kept alive so they re-observe items added by the next `addItems()` call. Use this in React wrappers to reinitialize timeline content when props change without recreating the instance.
473
+
468
474
  ### v2.11.0
469
475
  - New option `adSlots` — inject ad slot `<li>` placeholders at configurable positions (`every_n` or `random` mode) and receive an `onEnterViewport(slotEl, position)` callback exactly once per slot when ≥ 50% of it is visible. Works with `addItems()` and infinite scroll. Slots are removed on `tl.destroy()`. See **Ad slots** section.
470
476
 
@@ -1,6 +1,6 @@
1
1
  "use strict";var C=Object.defineProperty;var S=(l,e,t)=>e in l?C(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var _=(l,e,t)=>S(l,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});/*!
2
- * moTimeline v2.11.0
2
+ * moTimeline v2.12.0
3
3
  * Responsive two-column timeline layout library
4
4
  * https://github.com/MattOpen/moTimeline
5
5
  * MIT License
6
- */const h=new WeakMap,b={columnCount:{xs:1,sm:2,md:2,lg:2},showBadge:!1,showArrow:!1,theme:!1,showCounterStyle:"counter",cardBorderRadius:"8px",avatarSize:"50px",cardMargin:"0.5rem 1.25rem 0.5rem 0.5rem",cardMarginInverted:"0.5rem 0.5rem 0.5rem 1.25rem",cardMarginFullWidth:"0.5rem",randomFullWidth:0,animate:!1,renderCard:null,adSlots:null},A="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%234f46e5'/><circle cx='12' cy='12' r='4.5' fill='white'/></svg>";function w(){const l=window.innerWidth;return l<600?"xs":l<992?"sm":l<1200?"md":"lg"}function I(l,e=100){let t;return(...s)=>{clearTimeout(t),t=setTimeout(()=>l(...s),e)}}function p(l){return l?{o:l.offsetTop,h:l.offsetHeight,gppu:l.offsetTop+l.offsetHeight}:{o:0,h:0,gppu:0}}function y(l,e){const t=[];let s=l.previousElementSibling;for(;s;)(!e||s.matches(e))&&t.push(s),s=s.previousElementSibling;return t}const f=class f{constructor(e,t={}){if(typeof e=="string"&&(e=document.querySelector(e)),!e)throw new Error("moTimeline: element not found");this.element=e,this.settings=Object.assign({},b,t),this.settings.columnCount=Object.assign({},b.columnCount,t.columnCount),this._resizeHandler=I(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(h.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});if(h.set(e,t),f.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),e.style.setProperty("--mo-card-border-radius",t.cardBorderRadius),e.style.setProperty("--mo-avatar-size",t.avatarSize),e.style.setProperty("--mo-card-margin",t.cardMargin),e.style.setProperty("--mo-card-margin-inverted",t.cardMarginInverted),e.style.setProperty("--mo-card-margin-fullwidth",t.cardMarginFullWidth),t.animate){const s=t.animate===!0?"fade":t.animate;e.classList.add("mo-animate",`mo-animate-${s}`),this._observer=new IntersectionObserver(o=>{o.forEach(r=>{r.isIntersecting&&(r.target.classList.add("mo-visible"),this._observer.unobserve(r.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(o=>{o.isIntersecting&&(this._adObserver.unobserve(o.target),t.adSlots.onEnterViewport(o.target,Number(o.target.dataset.moAdPosition)))})},{threshold:.5}))),this._initialized=!0,window.addEventListener("resize",this._resizeHandler),Array.from(e.children).length>0&&this._initItems()}refresh(){f.instances.forEach(e=>{const t=e.element,s=h.get(t);s&&(s.col=s.columnCount[w()],e._setDivider(),Array.from(t.children).forEach(o=>{e._setPostPosition(o)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}insertItem(e,t){const s=this.element,o=this._getData();if(!o)return;const r=this._createItemElement(e),i=Array.from(s.children).filter(n=>n.classList.contains("js-mo-item")),a=t==null?Math.floor(Math.random()*(i.length+1)):Math.max(0,Math.min(t,i.length));if(a>=i.length?s.appendChild(r):s.insertBefore(r,i[a]),r.id||(r.id="moT"+crypto.randomUUID()+"_"+a),r.classList.add("mo-item","js-mo-item"),e.fullWidth)r.classList.add("mo-fullwidth","js-mo-fullwidth");else if(o.randomFullWidth){const n=o.randomFullWidth===!0?.33:o.randomFullWidth;Math.random()<n&&r.classList.add("mo-fullwidth","js-mo-fullwidth")}return o.showBadge&&this._createBadge(r,a+1),o.showArrow&&this._createArrow(r),o.showBadge&&o.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((n,c)=>{const d=n.querySelector(".js-mo-badge");d&&(d.textContent=c+1)}),o.lastItemIdx=Array.from(s.children).length,h.set(s,o),this.refresh(),this._observeItems([r]),r.querySelectorAll("img").forEach(n=>{n.complete||n.addEventListener("load",this._resizeHandler,{once:!0})}),r}destroy(){window.removeEventListener("resize",this._resizeHandler),this._observer&&(this._observer.disconnect(),this._observer=null),this._adObserver&&(this._adObserver.disconnect(),this._adObserver=null),Array.from(this.element.querySelectorAll(".mo-ad-slot")).forEach(e=>e.remove()),h.delete(this.element),f.instances.delete(this),this.element.style.removeProperty("--mo-card-border-radius"),this.element.style.removeProperty("--mo-avatar-size"),this.element.style.removeProperty("--mo-card-margin"),this.element.style.removeProperty("--mo-card-margin-inverted"),this.element.style.removeProperty("--mo-card-margin-fullwidth"),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol","mo-animate","mo-animate-fade","mo-animate-slide"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset","mo-fullwidth","js-mo-fullwidth","mo-visible"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return h.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[w()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,o=Array.from(e.children),r=o.slice(s);if(r.length!==0){if(r.forEach((i,a)=>{i.id||(i.id="moT"+crypto.randomUUID()+"_"+(a+s)),i.classList.add("mo-item","js-mo-item")}),this._setDivider(),t.randomFullWidth){const i=t.randomFullWidth===!0?.33:t.randomFullWidth;r.forEach(a=>{!a.classList.contains("mo-fullwidth")&&Math.random()<i&&a.classList.add("mo-fullwidth","js-mo-fullwidth")})}r.forEach((i,a)=>{t.showBadge&&this._createBadge(i,a+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=o.length,h.set(e,t),this.refresh(),this._observeItems(r),this._injectAdSlots(r),r.forEach(i=>{i.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-fullwidth")){e.classList.remove("mo-inverted","js-mo-inverted","mo-offset");return}const t=this._getLeftOrRight(e);t&&(e.classList.toggle("mo-inverted",t.lr>0),e.classList.toggle("js-mo-inverted",t.lr>0),e.classList.toggle("mo-offset",t.badge_offset>0))}_getLeftOrRight(e){if(!e)return null;const t=this._getData();if(!t)return null;const s=t.col,o=y(e,".js-mo-inverted")[0]||null,r=y(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,i=p(r),a=p(o),n=p(e);let c=0,d=0;if(s>1){i.gppu>n.o+1&&(c=1),a.gppu>i.gppu&&(c=0);const m=e.previousElementSibling;m&&Math.abs(n.o-p(m).o)<40&&(d=1)}return{lr:c,badge_offset:d}}_createBadge(e,t){const s=this._getData(),o=document.createElement("span");if(o.className="mo-badge js-mo-badge",s.showCounterStyle==="none")o.style.opacity="0";else if(s.showCounterStyle==="image"){const r=document.createElement("img");r.className="mo-badge-icon",r.alt="",r.src=e.dataset.moIcon||A,o.appendChild(r)}else o.textContent=t;e.prepend(o)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const s=document.createElement("div");s.className="mo-card";const o=this._getData();if(o&&typeof o.renderCard=="function")o.renderCard(e,s);else{if(e.banner){const i=document.createElement("div");i.className="mo-card-image";const a=document.createElement("img");if(a.className="mo-banner",a.src=e.banner,a.alt="",i.appendChild(a),e.avatar){const n=document.createElement("img");n.className="mo-avatar",n.src=e.avatar,n.alt="",i.appendChild(n)}s.appendChild(i)}const r=document.createElement("div");if(r.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,r.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,r.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,r.appendChild(i)}s.appendChild(r)}return t.appendChild(s),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}_injectAdSlots(e){const t=this._getData();if(!t||!t.adSlots||!e.length)return;const{mode:s,interval:o,style:r}=t.adSlots,i=r==="fullwidth",a=this.element;let n=!1;if(s==="every_n")e.forEach((c,d)=>{if((t._adRealCount+d+1)%o===0){const m=this._createAdSlot(i);c.after(m),m.dataset.moAdPosition=String(Array.from(a.children).indexOf(m)),this._adObserver&&this._adObserver.observe(m),i&&(n=!0)}});else if(s==="random"){let c=t._adRealCount%o,d=0;for(;d<e.length;){const m=o-c,u=e.slice(d,d+m);if(u.length===m){const E=u[Math.floor(Math.random()*u.length)],g=this._createAdSlot(i);E.after(g),g.dataset.moAdPosition=String(Array.from(a.children).indexOf(g)),this._adObserver&&this._adObserver.observe(g),i&&(n=!0),c=0}else c+=u.length;d+=m}}t._adRealCount+=e.length,n&&this.refresh()}_createAdSlot(e){const t=document.createElement("li");return t.className="mo-ad-slot",e&&t.classList.add("mo-fullwidth"),t}_observeItems(e){this._observer&&e.forEach(t=>{t.classList.contains("mo-visible")||this._observer.observe(t)})}};_(f,"instances",new Set);let v=f;exports.MoTimeline=v;exports.default=v;
6
+ */const h=new WeakMap,b={columnCount:{xs:1,sm:2,md:2,lg:2},showBadge:!1,showArrow:!1,theme:!1,showCounterStyle:"counter",cardBorderRadius:"8px",avatarSize:"50px",cardMargin:"0.5rem 1.25rem 0.5rem 0.5rem",cardMarginInverted:"0.5rem 0.5rem 0.5rem 1.25rem",cardMarginFullWidth:"0.5rem",randomFullWidth:0,animate:!1,renderCard:null,adSlots:null},A="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%234f46e5'/><circle cx='12' cy='12' r='4.5' fill='white'/></svg>";function w(){const l=window.innerWidth;return l<600?"xs":l<992?"sm":l<1200?"md":"lg"}function I(l,e=100){let t;return(...s)=>{clearTimeout(t),t=setTimeout(()=>l(...s),e)}}function v(l){return l?{o:l.offsetTop,h:l.offsetHeight,gppu:l.offsetTop+l.offsetHeight}:{o:0,h:0,gppu:0}}function y(l,e){const t=[];let s=l.previousElementSibling;for(;s;)(!e||s.matches(e))&&t.push(s),s=s.previousElementSibling;return t}const f=class f{constructor(e,t={}){if(typeof e=="string"&&(e=document.querySelector(e)),!e)throw new Error("moTimeline: element not found");this.element=e,this.settings=Object.assign({},b,t),this.settings.columnCount=Object.assign({},b.columnCount,t.columnCount),this._resizeHandler=I(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(h.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});if(h.set(e,t),f.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),e.style.setProperty("--mo-card-border-radius",t.cardBorderRadius),e.style.setProperty("--mo-avatar-size",t.avatarSize),e.style.setProperty("--mo-card-margin",t.cardMargin),e.style.setProperty("--mo-card-margin-inverted",t.cardMarginInverted),e.style.setProperty("--mo-card-margin-fullwidth",t.cardMarginFullWidth),t.animate){const s=t.animate===!0?"fade":t.animate;e.classList.add("mo-animate",`mo-animate-${s}`),this._observer=new IntersectionObserver(o=>{o.forEach(r=>{r.isIntersecting&&(r.target.classList.add("mo-visible"),this._observer.unobserve(r.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(o=>{o.isIntersecting&&(this._adObserver.unobserve(o.target),t.adSlots.onEnterViewport(o.target,Number(o.target.dataset.moAdPosition)))})},{threshold:.5}))),this._initialized=!0,window.addEventListener("resize",this._resizeHandler),Array.from(e.children).length>0&&this._initItems()}refresh(){f.instances.forEach(e=>{const t=e.element,s=h.get(t);s&&(s.col=s.columnCount[w()],e._setDivider(),Array.from(t.children).forEach(o=>{e._setPostPosition(o)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}insertItem(e,t){const s=this.element,o=this._getData();if(!o)return;const r=this._createItemElement(e),i=Array.from(s.children).filter(n=>n.classList.contains("js-mo-item")),a=t==null?Math.floor(Math.random()*(i.length+1)):Math.max(0,Math.min(t,i.length));if(a>=i.length?s.appendChild(r):s.insertBefore(r,i[a]),r.id||(r.id="moT"+crypto.randomUUID()+"_"+a),r.classList.add("mo-item","js-mo-item"),e.fullWidth)r.classList.add("mo-fullwidth","js-mo-fullwidth");else if(o.randomFullWidth){const n=o.randomFullWidth===!0?.33:o.randomFullWidth;Math.random()<n&&r.classList.add("mo-fullwidth","js-mo-fullwidth")}return o.showBadge&&this._createBadge(r,a+1),o.showArrow&&this._createArrow(r),o.showBadge&&o.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((n,c)=>{const d=n.querySelector(".js-mo-badge");d&&(d.textContent=c+1)}),o.lastItemIdx=Array.from(s.children).length,h.set(s,o),this.refresh(),this._observeItems([r]),r.querySelectorAll("img").forEach(n=>{n.complete||n.addEventListener("load",this._resizeHandler,{once:!0})}),r}clear(){const e=this._getData();e&&(this._observer&&this._observer.disconnect(),this._adObserver&&this._adObserver.disconnect(),Array.from(this.element.children).forEach(t=>{(t.classList.contains("js-mo-item")||t.classList.contains("mo-ad-slot"))&&t.remove()}),e.lastItemIdx=0,e.adSlots&&(e._adRealCount=0))}destroy(){window.removeEventListener("resize",this._resizeHandler),this._observer&&(this._observer.disconnect(),this._observer=null),this._adObserver&&(this._adObserver.disconnect(),this._adObserver=null),Array.from(this.element.querySelectorAll(".mo-ad-slot")).forEach(e=>e.remove()),h.delete(this.element),f.instances.delete(this),this.element.style.removeProperty("--mo-card-border-radius"),this.element.style.removeProperty("--mo-avatar-size"),this.element.style.removeProperty("--mo-card-margin"),this.element.style.removeProperty("--mo-card-margin-inverted"),this.element.style.removeProperty("--mo-card-margin-fullwidth"),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol","mo-animate","mo-animate-fade","mo-animate-slide"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset","mo-fullwidth","js-mo-fullwidth","mo-visible"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return h.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[w()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,o=Array.from(e.children),r=o.slice(s);if(r.length!==0){if(r.forEach((i,a)=>{i.id||(i.id="moT"+crypto.randomUUID()+"_"+(a+s)),i.classList.add("mo-item","js-mo-item")}),this._setDivider(),t.randomFullWidth){const i=t.randomFullWidth===!0?.33:t.randomFullWidth;r.forEach(a=>{!a.classList.contains("mo-fullwidth")&&Math.random()<i&&a.classList.add("mo-fullwidth","js-mo-fullwidth")})}r.forEach((i,a)=>{t.showBadge&&this._createBadge(i,a+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=o.length,h.set(e,t),this.refresh(),this._observeItems(r),this._injectAdSlots(r),r.forEach(i=>{i.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-fullwidth")){e.classList.remove("mo-inverted","js-mo-inverted","mo-offset");return}const t=this._getLeftOrRight(e);t&&(e.classList.toggle("mo-inverted",t.lr>0),e.classList.toggle("js-mo-inverted",t.lr>0),e.classList.toggle("mo-offset",t.badge_offset>0))}_getLeftOrRight(e){if(!e)return null;const t=this._getData();if(!t)return null;const s=t.col,o=y(e,".js-mo-inverted")[0]||null,r=y(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,i=v(r),a=v(o),n=v(e);let c=0,d=0;if(s>1){i.gppu>n.o+1&&(c=1),a.gppu>i.gppu&&(c=0);const m=e.previousElementSibling;m&&Math.abs(n.o-v(m).o)<40&&(d=1)}return{lr:c,badge_offset:d}}_createBadge(e,t){const s=this._getData(),o=document.createElement("span");if(o.className="mo-badge js-mo-badge",s.showCounterStyle==="none")o.style.opacity="0";else if(s.showCounterStyle==="image"){const r=document.createElement("img");r.className="mo-badge-icon",r.alt="",r.src=e.dataset.moIcon||A,o.appendChild(r)}else o.textContent=t;e.prepend(o)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const s=document.createElement("div");s.className="mo-card";const o=this._getData();if(o&&typeof o.renderCard=="function")o.renderCard(e,s);else{if(e.banner){const i=document.createElement("div");i.className="mo-card-image";const a=document.createElement("img");if(a.className="mo-banner",a.src=e.banner,a.alt="",i.appendChild(a),e.avatar){const n=document.createElement("img");n.className="mo-avatar",n.src=e.avatar,n.alt="",i.appendChild(n)}s.appendChild(i)}const r=document.createElement("div");if(r.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,r.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,r.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,r.appendChild(i)}s.appendChild(r)}return t.appendChild(s),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}_injectAdSlots(e){const t=this._getData();if(!t||!t.adSlots||!e.length)return;const{mode:s,interval:o,style:r}=t.adSlots,i=r==="fullwidth",a=this.element;let n=!1;if(s==="every_n")e.forEach((c,d)=>{if((t._adRealCount+d+1)%o===0){const m=this._createAdSlot(i);c.after(m),m.dataset.moAdPosition=String(Array.from(a.children).indexOf(m)),this._adObserver&&this._adObserver.observe(m),i&&(n=!0)}});else if(s==="random"){let c=t._adRealCount%o,d=0;for(;d<e.length;){const m=o-c,u=e.slice(d,d+m);if(u.length===m){const E=u[Math.floor(Math.random()*u.length)],g=this._createAdSlot(i);E.after(g),g.dataset.moAdPosition=String(Array.from(a.children).indexOf(g)),this._adObserver&&this._adObserver.observe(g),i&&(n=!0),c=0}else c+=u.length;d+=m}}t._adRealCount+=e.length,n&&this.refresh()}_createAdSlot(e){const t=document.createElement("li");return t.className="mo-ad-slot",e&&t.classList.add("mo-fullwidth"),t}_observeItems(e){this._observer&&e.forEach(t=>{t.classList.contains("mo-visible")||this._observer.observe(t)})}};_(f,"instances",new Set);let p=f;exports.MoTimeline=p;exports.default=p;
@@ -1,3 +1,3 @@
1
1
  /*!
2
- * moTimeline v2.11.0 — CSS
2
+ * moTimeline v2.12.0 — CSS
3
3
  */:root{--mo-line-color: #dde1e7;--mo-badge-bg: #4f46e5;--mo-badge-color: #fff;--mo-badge-size: 26px;--mo-badge-font-size: 12px;--mo-arrow-color: #dde1e7}.mo-timeline{display:block;list-style:none;margin:0;padding:0;position:relative;width:100%}.mo-timeline:after{content:"";display:table;clear:both}.mo-timeline.mo-twocol:before{background-color:var(--mo-line-color);bottom:0;content:"";left:50%;margin-left:-1.5px;position:absolute;top:0;width:3px;z-index:0}.mo-timeline>.mo-item{box-sizing:border-box;display:block;float:left;position:relative;width:50%}.mo-timeline:not(.mo-twocol)>.mo-item{float:none;width:100%}.mo-timeline>.mo-item.mo-inverted{float:right}.mo-timeline.mo-twocol>.mo-item.mo-fullwidth{clear:both;float:none;width:100%}.mo-theme>.mo-item.mo-fullwidth .mo-card{margin:var(--mo-card-margin-fullwidth, .5rem)}.mo-timeline.mo-twocol>.mo-item.mo-fullwidth .mo-badge,.mo-timeline.mo-twocol>.mo-item.mo-fullwidth .mo-arrow{display:none}.mo-badge{align-items:center;background:var(--mo-badge-bg);border-radius:50%;color:var(--mo-badge-color);display:flex;font-size:var(--mo-badge-font-size);font-weight:700;height:var(--mo-badge-size);justify-content:center;min-width:var(--mo-badge-size);overflow:hidden;position:absolute;top:18px;z-index:2}.mo-badge .mo-badge-icon{border-radius:50%;height:100%;object-fit:cover;width:100%}.mo-timeline.mo-twocol>.mo-item:not(.mo-inverted) .mo-badge{left:auto;right:calc(var(--mo-badge-size) / -2)}.mo-timeline.mo-twocol>.mo-item.mo-inverted .mo-badge{left:calc(var(--mo-badge-size) / -2);right:auto}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-badge{top:calc(18px + var(--mo-badge-size) + 10px)}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-arrow{top:calc(26px + var(--mo-badge-size) + 10px)}.mo-timeline:not(.mo-twocol)>.mo-item .mo-badge{display:none}.mo-arrow{border:8px solid transparent;display:block;height:0;position:absolute;top:26px;width:0;z-index:1}.mo-timeline.mo-twocol>.mo-item:not(.mo-inverted) .mo-arrow{border-left:8px solid var(--mo-arrow-color);border-right:none;left:auto;right:0}.mo-timeline.mo-twocol>.mo-item.mo-inverted .mo-arrow{border-right:8px solid var(--mo-arrow-color);border-left:none;left:0;right:auto}.mo-timeline:not(.mo-twocol)>.mo-item .mo-arrow{display:none}.mo-theme{--mo-arrow-color: #fff}.mo-theme>.mo-item .mo-card{background:#fff;border-radius:var(--mo-card-border-radius, 8px);box-shadow:0 2px 14px #0000001a;margin:var(--mo-card-margin, .5rem 1.25rem .5rem .5rem);position:relative}.mo-theme>.mo-item.mo-inverted .mo-card{margin:var(--mo-card-margin-inverted, .5rem .5rem .5rem 1.25rem)}.mo-theme>.mo-item .mo-banner{border-radius:var(--mo-card-border-radius, 8px) var(--mo-card-border-radius, 8px) 0 0;display:block;max-height:240px;object-fit:cover;width:100%}.mo-theme>.mo-item .mo-card-image{overflow:visible;position:relative}.mo-theme>.mo-item .mo-avatar{border:3px solid #fff;border-radius:50%;bottom:calc(var(--mo-avatar-size, 50px) * -.44);box-shadow:0 2px 8px #0000002e;height:var(--mo-avatar-size, 50px);object-fit:cover;position:absolute;right:14px;width:var(--mo-avatar-size, 50px);z-index:1}.mo-theme>.mo-item .mo-card-body{padding:1.75rem 1rem 1rem}.mo-theme>.mo-item .mo-card-body h3{font-size:1rem;font-weight:700;margin:0 0 .3rem}.mo-theme>.mo-item .mo-card-body .mo-meta{color:#9ca3af;font-size:.75rem;margin-bottom:.5rem}.mo-theme>.mo-item .mo-card-body p{color:#6b7280;font-size:.875rem;line-height:1.55;margin:0}.mo-theme.mo-twocol>.mo-item:not(.mo-inverted) .mo-arrow{border-left-color:var(--mo-arrow-color);right:12px}.mo-theme.mo-twocol>.mo-item.mo-inverted .mo-arrow{border-right-color:var(--mo-arrow-color);left:12px}.mo-theme .mo-badge{background:#fff;border:2px solid var(--mo-line-color);box-shadow:0 2px 6px #0000001a;color:#374151}.mo-timeline.mo-animate>.mo-item{transition:opacity var(--mo-animate-duration, .5s) ease,transform var(--mo-animate-duration, .5s) ease}.mo-timeline.mo-animate-fade>.mo-item{opacity:0}.mo-timeline.mo-animate-slide>.mo-item:not(.mo-inverted){opacity:0;transform:translate(-40px)}.mo-timeline.mo-animate-slide>.mo-item.mo-inverted{opacity:0;transform:translate(40px)}.mo-timeline:not(.mo-twocol).mo-animate-slide>.mo-item{transform:translate(-40px)}.mo-timeline.mo-animate>.mo-item.mo-visible{opacity:1;transform:translate(0)}.mo-timeline>.mo-item.mo-ad-slot{min-height:100px}
@@ -1,8 +1,8 @@
1
1
  var C = Object.defineProperty;
2
2
  var A = (l, e, t) => e in l ? C(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var v = (l, e, t) => A(l, typeof e != "symbol" ? e + "" : e, t);
3
+ var p = (l, e, t) => A(l, typeof e != "symbol" ? e + "" : e, t);
4
4
  /*!
5
- * moTimeline v2.11.0
5
+ * moTimeline v2.12.0
6
6
  * Responsive two-column timeline layout library
7
7
  * https://github.com/MattOpen/moTimeline
8
8
  * MIT License
@@ -28,7 +28,7 @@ const h = /* @__PURE__ */ new WeakMap(), _ = {
28
28
  adSlots: null
29
29
  // { mode, interval, style, onEnterViewport } — see docs
30
30
  }, I = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%234f46e5'/><circle cx='12' cy='12' r='4.5' fill='white'/></svg>";
31
- function w() {
31
+ function b() {
32
32
  const l = window.innerWidth;
33
33
  return l < 600 ? "xs" : l < 992 ? "sm" : l < 1200 ? "md" : "lg";
34
34
  }
@@ -38,14 +38,14 @@ function S(l, e = 100) {
38
38
  clearTimeout(t), t = setTimeout(() => l(...s), e);
39
39
  };
40
40
  }
41
- function p(l) {
41
+ function v(l) {
42
42
  return l ? {
43
43
  o: l.offsetTop,
44
44
  h: l.offsetHeight,
45
45
  gppu: l.offsetTop + l.offsetHeight
46
46
  } : { o: 0, h: 0, gppu: 0 };
47
47
  }
48
- function b(l, e) {
48
+ function w(l, e) {
49
49
  const t = [];
50
50
  let s = l.previousElementSibling;
51
51
  for (; s; )
@@ -81,7 +81,7 @@ const f = class f {
81
81
  refresh() {
82
82
  f.instances.forEach((e) => {
83
83
  const t = e.element, s = h.get(t);
84
- s && (s.col = s.columnCount[w()], e._setDivider(), Array.from(t.children).forEach((o) => {
84
+ s && (s.col = s.columnCount[b()], e._setDivider(), Array.from(t.children).forEach((o) => {
85
85
  e._setPostPosition(o);
86
86
  }));
87
87
  });
@@ -125,6 +125,12 @@ const f = class f {
125
125
  n.complete || n.addEventListener("load", this._resizeHandler, { once: !0 });
126
126
  }), r;
127
127
  }
128
+ clear() {
129
+ const e = this._getData();
130
+ e && (this._observer && this._observer.disconnect(), this._adObserver && this._adObserver.disconnect(), Array.from(this.element.children).forEach((t) => {
131
+ (t.classList.contains("js-mo-item") || t.classList.contains("mo-ad-slot")) && t.remove();
132
+ }), e.lastItemIdx = 0, e.adSlots && (e._adRealCount = 0));
133
+ }
128
134
  destroy() {
129
135
  window.removeEventListener("resize", this._resizeHandler), this._observer && (this._observer.disconnect(), this._observer = null), this._adObserver && (this._adObserver.disconnect(), this._adObserver = null), Array.from(this.element.querySelectorAll(".mo-ad-slot")).forEach((e) => e.remove()), h.delete(this.element), f.instances.delete(this), this.element.style.removeProperty("--mo-card-border-radius"), this.element.style.removeProperty("--mo-avatar-size"), this.element.style.removeProperty("--mo-card-margin"), this.element.style.removeProperty("--mo-card-margin-inverted"), this.element.style.removeProperty("--mo-card-margin-fullwidth"), this.element.classList.remove("mo-timeline", "mo-theme", "mo-twocol", "mo-animate", "mo-animate-fade", "mo-animate-slide"), Array.from(this.element.children).forEach((e) => {
130
136
  e.classList.remove("mo-item", "js-mo-item", "mo-inverted", "js-mo-inverted", "mo-offset", "mo-fullwidth", "js-mo-fullwidth", "mo-visible"), e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach((t) => t.remove());
@@ -136,7 +142,7 @@ const f = class f {
136
142
  }
137
143
  _setDivider() {
138
144
  const e = this._getData();
139
- e && (e.col = e.columnCount[w()], this.element.classList.toggle("mo-twocol", e.col > 1));
145
+ e && (e.col = e.columnCount[b()], this.element.classList.toggle("mo-twocol", e.col > 1));
140
146
  }
141
147
  _initItems() {
142
148
  const e = this.element, t = this._getData();
@@ -172,12 +178,12 @@ const f = class f {
172
178
  if (!e) return null;
173
179
  const t = this._getData();
174
180
  if (!t) return null;
175
- const s = t.col, o = b(e, ".js-mo-inverted")[0] || null, r = b(e, ".js-mo-item:not(.js-mo-inverted)")[0] || null, i = p(r), a = p(o), n = p(e);
181
+ const s = t.col, o = w(e, ".js-mo-inverted")[0] || null, r = w(e, ".js-mo-item:not(.js-mo-inverted)")[0] || null, i = v(r), a = v(o), n = v(e);
176
182
  let c = 0, d = 0;
177
183
  if (s > 1) {
178
184
  i.gppu > n.o + 1 && (c = 1), a.gppu > i.gppu && (c = 0);
179
185
  const m = e.previousElementSibling;
180
- m && Math.abs(n.o - p(m).o) < 40 && (d = 1);
186
+ m && Math.abs(n.o - v(m).o) < 40 && (d = 1);
181
187
  }
182
188
  return { lr: c, badge_offset: d };
183
189
  }
@@ -268,7 +274,7 @@ const f = class f {
268
274
  });
269
275
  }
270
276
  };
271
- v(f, "instances", /* @__PURE__ */ new Set());
277
+ p(f, "instances", /* @__PURE__ */ new Set());
272
278
  let y = f;
273
279
  export {
274
280
  y as MoTimeline,
@@ -1,6 +1,6 @@
1
1
  (function(d,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(d=typeof globalThis<"u"?globalThis:d||self,l(d.MoTimeline={}))})(this,function(d){"use strict";var I=Object.defineProperty;var L=(d,l,u)=>l in d?I(d,l,{enumerable:!0,configurable:!0,writable:!0,value:u}):d[l]=u;var E=(d,l,u)=>L(d,typeof l!="symbol"?l+"":l,u);/*!
2
- * moTimeline v2.11.0
2
+ * moTimeline v2.12.0
3
3
  * Responsive two-column timeline layout library
4
4
  * https://github.com/MattOpen/moTimeline
5
5
  * MIT License
6
- */const l=new WeakMap,u={columnCount:{xs:1,sm:2,md:2,lg:2},showBadge:!1,showArrow:!1,theme:!1,showCounterStyle:"counter",cardBorderRadius:"8px",avatarSize:"50px",cardMargin:"0.5rem 1.25rem 0.5rem 0.5rem",cardMarginInverted:"0.5rem 0.5rem 0.5rem 1.25rem",cardMarginFullWidth:"0.5rem",randomFullWidth:0,animate:!1,renderCard:null,adSlots:null},C="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%234f46e5'/><circle cx='12' cy='12' r='4.5' fill='white'/></svg>";function w(){const c=window.innerWidth;return c<600?"xs":c<992?"sm":c<1200?"md":"lg"}function S(c,e=100){let t;return(...s)=>{clearTimeout(t),t=setTimeout(()=>c(...s),e)}}function p(c){return c?{o:c.offsetTop,h:c.offsetHeight,gppu:c.offsetTop+c.offsetHeight}:{o:0,h:0,gppu:0}}function y(c,e){const t=[];let s=c.previousElementSibling;for(;s;)(!e||s.matches(e))&&t.push(s),s=s.previousElementSibling;return t}const g=class g{constructor(e,t={}){if(typeof e=="string"&&(e=document.querySelector(e)),!e)throw new Error("moTimeline: element not found");this.element=e,this.settings=Object.assign({},u,t),this.settings.columnCount=Object.assign({},u.columnCount,t.columnCount),this._resizeHandler=S(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(l.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});if(l.set(e,t),g.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),e.style.setProperty("--mo-card-border-radius",t.cardBorderRadius),e.style.setProperty("--mo-avatar-size",t.avatarSize),e.style.setProperty("--mo-card-margin",t.cardMargin),e.style.setProperty("--mo-card-margin-inverted",t.cardMarginInverted),e.style.setProperty("--mo-card-margin-fullwidth",t.cardMarginFullWidth),t.animate){const s=t.animate===!0?"fade":t.animate;e.classList.add("mo-animate",`mo-animate-${s}`),this._observer=new IntersectionObserver(o=>{o.forEach(r=>{r.isIntersecting&&(r.target.classList.add("mo-visible"),this._observer.unobserve(r.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(o=>{o.isIntersecting&&(this._adObserver.unobserve(o.target),t.adSlots.onEnterViewport(o.target,Number(o.target.dataset.moAdPosition)))})},{threshold:.5}))),this._initialized=!0,window.addEventListener("resize",this._resizeHandler),Array.from(e.children).length>0&&this._initItems()}refresh(){g.instances.forEach(e=>{const t=e.element,s=l.get(t);s&&(s.col=s.columnCount[w()],e._setDivider(),Array.from(t.children).forEach(o=>{e._setPostPosition(o)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}insertItem(e,t){const s=this.element,o=this._getData();if(!o)return;const r=this._createItemElement(e),i=Array.from(s.children).filter(a=>a.classList.contains("js-mo-item")),n=t==null?Math.floor(Math.random()*(i.length+1)):Math.max(0,Math.min(t,i.length));if(n>=i.length?s.appendChild(r):s.insertBefore(r,i[n]),r.id||(r.id="moT"+crypto.randomUUID()+"_"+n),r.classList.add("mo-item","js-mo-item"),e.fullWidth)r.classList.add("mo-fullwidth","js-mo-fullwidth");else if(o.randomFullWidth){const a=o.randomFullWidth===!0?.33:o.randomFullWidth;Math.random()<a&&r.classList.add("mo-fullwidth","js-mo-fullwidth")}return o.showBadge&&this._createBadge(r,n+1),o.showArrow&&this._createArrow(r),o.showBadge&&o.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((a,h)=>{const m=a.querySelector(".js-mo-badge");m&&(m.textContent=h+1)}),o.lastItemIdx=Array.from(s.children).length,l.set(s,o),this.refresh(),this._observeItems([r]),r.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})}),r}destroy(){window.removeEventListener("resize",this._resizeHandler),this._observer&&(this._observer.disconnect(),this._observer=null),this._adObserver&&(this._adObserver.disconnect(),this._adObserver=null),Array.from(this.element.querySelectorAll(".mo-ad-slot")).forEach(e=>e.remove()),l.delete(this.element),g.instances.delete(this),this.element.style.removeProperty("--mo-card-border-radius"),this.element.style.removeProperty("--mo-avatar-size"),this.element.style.removeProperty("--mo-card-margin"),this.element.style.removeProperty("--mo-card-margin-inverted"),this.element.style.removeProperty("--mo-card-margin-fullwidth"),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol","mo-animate","mo-animate-fade","mo-animate-slide"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset","mo-fullwidth","js-mo-fullwidth","mo-visible"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return l.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[w()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,o=Array.from(e.children),r=o.slice(s);if(r.length!==0){if(r.forEach((i,n)=>{i.id||(i.id="moT"+crypto.randomUUID()+"_"+(n+s)),i.classList.add("mo-item","js-mo-item")}),this._setDivider(),t.randomFullWidth){const i=t.randomFullWidth===!0?.33:t.randomFullWidth;r.forEach(n=>{!n.classList.contains("mo-fullwidth")&&Math.random()<i&&n.classList.add("mo-fullwidth","js-mo-fullwidth")})}r.forEach((i,n)=>{t.showBadge&&this._createBadge(i,n+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=o.length,l.set(e,t),this.refresh(),this._observeItems(r),this._injectAdSlots(r),r.forEach(i=>{i.querySelectorAll("img").forEach(n=>{n.complete||n.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-fullwidth")){e.classList.remove("mo-inverted","js-mo-inverted","mo-offset");return}const t=this._getLeftOrRight(e);t&&(e.classList.toggle("mo-inverted",t.lr>0),e.classList.toggle("js-mo-inverted",t.lr>0),e.classList.toggle("mo-offset",t.badge_offset>0))}_getLeftOrRight(e){if(!e)return null;const t=this._getData();if(!t)return null;const s=t.col,o=y(e,".js-mo-inverted")[0]||null,r=y(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,i=p(r),n=p(o),a=p(e);let h=0,m=0;if(s>1){i.gppu>a.o+1&&(h=1),n.gppu>i.gppu&&(h=0);const f=e.previousElementSibling;f&&Math.abs(a.o-p(f).o)<40&&(m=1)}return{lr:h,badge_offset:m}}_createBadge(e,t){const s=this._getData(),o=document.createElement("span");if(o.className="mo-badge js-mo-badge",s.showCounterStyle==="none")o.style.opacity="0";else if(s.showCounterStyle==="image"){const r=document.createElement("img");r.className="mo-badge-icon",r.alt="",r.src=e.dataset.moIcon||C,o.appendChild(r)}else o.textContent=t;e.prepend(o)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const s=document.createElement("div");s.className="mo-card";const o=this._getData();if(o&&typeof o.renderCard=="function")o.renderCard(e,s);else{if(e.banner){const i=document.createElement("div");i.className="mo-card-image";const n=document.createElement("img");if(n.className="mo-banner",n.src=e.banner,n.alt="",i.appendChild(n),e.avatar){const a=document.createElement("img");a.className="mo-avatar",a.src=e.avatar,a.alt="",i.appendChild(a)}s.appendChild(i)}const r=document.createElement("div");if(r.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,r.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,r.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,r.appendChild(i)}s.appendChild(r)}return t.appendChild(s),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}_injectAdSlots(e){const t=this._getData();if(!t||!t.adSlots||!e.length)return;const{mode:s,interval:o,style:r}=t.adSlots,i=r==="fullwidth",n=this.element;let a=!1;if(s==="every_n")e.forEach((h,m)=>{if((t._adRealCount+m+1)%o===0){const f=this._createAdSlot(i);h.after(f),f.dataset.moAdPosition=String(Array.from(n.children).indexOf(f)),this._adObserver&&this._adObserver.observe(f),i&&(a=!0)}});else if(s==="random"){let h=t._adRealCount%o,m=0;for(;m<e.length;){const f=o-h,_=e.slice(m,m+f);if(_.length===f){const A=_[Math.floor(Math.random()*_.length)],b=this._createAdSlot(i);A.after(b),b.dataset.moAdPosition=String(Array.from(n.children).indexOf(b)),this._adObserver&&this._adObserver.observe(b),i&&(a=!0),h=0}else h+=_.length;m+=f}}t._adRealCount+=e.length,a&&this.refresh()}_createAdSlot(e){const t=document.createElement("li");return t.className="mo-ad-slot",e&&t.classList.add("mo-fullwidth"),t}_observeItems(e){this._observer&&e.forEach(t=>{t.classList.contains("mo-visible")||this._observer.observe(t)})}};E(g,"instances",new Set);let v=g;d.MoTimeline=v,d.default=v,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
6
+ */const l=new WeakMap,u={columnCount:{xs:1,sm:2,md:2,lg:2},showBadge:!1,showArrow:!1,theme:!1,showCounterStyle:"counter",cardBorderRadius:"8px",avatarSize:"50px",cardMargin:"0.5rem 1.25rem 0.5rem 0.5rem",cardMarginInverted:"0.5rem 0.5rem 0.5rem 1.25rem",cardMarginFullWidth:"0.5rem",randomFullWidth:0,animate:!1,renderCard:null,adSlots:null},C="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%234f46e5'/><circle cx='12' cy='12' r='4.5' fill='white'/></svg>";function w(){const c=window.innerWidth;return c<600?"xs":c<992?"sm":c<1200?"md":"lg"}function S(c,e=100){let t;return(...s)=>{clearTimeout(t),t=setTimeout(()=>c(...s),e)}}function p(c){return c?{o:c.offsetTop,h:c.offsetHeight,gppu:c.offsetTop+c.offsetHeight}:{o:0,h:0,gppu:0}}function y(c,e){const t=[];let s=c.previousElementSibling;for(;s;)(!e||s.matches(e))&&t.push(s),s=s.previousElementSibling;return t}const g=class g{constructor(e,t={}){if(typeof e=="string"&&(e=document.querySelector(e)),!e)throw new Error("moTimeline: element not found");this.element=e,this.settings=Object.assign({},u,t),this.settings.columnCount=Object.assign({},u.columnCount,t.columnCount),this._resizeHandler=S(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(l.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});if(l.set(e,t),g.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),e.style.setProperty("--mo-card-border-radius",t.cardBorderRadius),e.style.setProperty("--mo-avatar-size",t.avatarSize),e.style.setProperty("--mo-card-margin",t.cardMargin),e.style.setProperty("--mo-card-margin-inverted",t.cardMarginInverted),e.style.setProperty("--mo-card-margin-fullwidth",t.cardMarginFullWidth),t.animate){const s=t.animate===!0?"fade":t.animate;e.classList.add("mo-animate",`mo-animate-${s}`),this._observer=new IntersectionObserver(o=>{o.forEach(r=>{r.isIntersecting&&(r.target.classList.add("mo-visible"),this._observer.unobserve(r.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(o=>{o.isIntersecting&&(this._adObserver.unobserve(o.target),t.adSlots.onEnterViewport(o.target,Number(o.target.dataset.moAdPosition)))})},{threshold:.5}))),this._initialized=!0,window.addEventListener("resize",this._resizeHandler),Array.from(e.children).length>0&&this._initItems()}refresh(){g.instances.forEach(e=>{const t=e.element,s=l.get(t);s&&(s.col=s.columnCount[w()],e._setDivider(),Array.from(t.children).forEach(o=>{e._setPostPosition(o)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}insertItem(e,t){const s=this.element,o=this._getData();if(!o)return;const r=this._createItemElement(e),i=Array.from(s.children).filter(a=>a.classList.contains("js-mo-item")),n=t==null?Math.floor(Math.random()*(i.length+1)):Math.max(0,Math.min(t,i.length));if(n>=i.length?s.appendChild(r):s.insertBefore(r,i[n]),r.id||(r.id="moT"+crypto.randomUUID()+"_"+n),r.classList.add("mo-item","js-mo-item"),e.fullWidth)r.classList.add("mo-fullwidth","js-mo-fullwidth");else if(o.randomFullWidth){const a=o.randomFullWidth===!0?.33:o.randomFullWidth;Math.random()<a&&r.classList.add("mo-fullwidth","js-mo-fullwidth")}return o.showBadge&&this._createBadge(r,n+1),o.showArrow&&this._createArrow(r),o.showBadge&&o.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((a,h)=>{const m=a.querySelector(".js-mo-badge");m&&(m.textContent=h+1)}),o.lastItemIdx=Array.from(s.children).length,l.set(s,o),this.refresh(),this._observeItems([r]),r.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})}),r}clear(){const e=this._getData();e&&(this._observer&&this._observer.disconnect(),this._adObserver&&this._adObserver.disconnect(),Array.from(this.element.children).forEach(t=>{(t.classList.contains("js-mo-item")||t.classList.contains("mo-ad-slot"))&&t.remove()}),e.lastItemIdx=0,e.adSlots&&(e._adRealCount=0))}destroy(){window.removeEventListener("resize",this._resizeHandler),this._observer&&(this._observer.disconnect(),this._observer=null),this._adObserver&&(this._adObserver.disconnect(),this._adObserver=null),Array.from(this.element.querySelectorAll(".mo-ad-slot")).forEach(e=>e.remove()),l.delete(this.element),g.instances.delete(this),this.element.style.removeProperty("--mo-card-border-radius"),this.element.style.removeProperty("--mo-avatar-size"),this.element.style.removeProperty("--mo-card-margin"),this.element.style.removeProperty("--mo-card-margin-inverted"),this.element.style.removeProperty("--mo-card-margin-fullwidth"),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol","mo-animate","mo-animate-fade","mo-animate-slide"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset","mo-fullwidth","js-mo-fullwidth","mo-visible"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return l.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[w()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,o=Array.from(e.children),r=o.slice(s);if(r.length!==0){if(r.forEach((i,n)=>{i.id||(i.id="moT"+crypto.randomUUID()+"_"+(n+s)),i.classList.add("mo-item","js-mo-item")}),this._setDivider(),t.randomFullWidth){const i=t.randomFullWidth===!0?.33:t.randomFullWidth;r.forEach(n=>{!n.classList.contains("mo-fullwidth")&&Math.random()<i&&n.classList.add("mo-fullwidth","js-mo-fullwidth")})}r.forEach((i,n)=>{t.showBadge&&this._createBadge(i,n+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=o.length,l.set(e,t),this.refresh(),this._observeItems(r),this._injectAdSlots(r),r.forEach(i=>{i.querySelectorAll("img").forEach(n=>{n.complete||n.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-fullwidth")){e.classList.remove("mo-inverted","js-mo-inverted","mo-offset");return}const t=this._getLeftOrRight(e);t&&(e.classList.toggle("mo-inverted",t.lr>0),e.classList.toggle("js-mo-inverted",t.lr>0),e.classList.toggle("mo-offset",t.badge_offset>0))}_getLeftOrRight(e){if(!e)return null;const t=this._getData();if(!t)return null;const s=t.col,o=y(e,".js-mo-inverted")[0]||null,r=y(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,i=p(r),n=p(o),a=p(e);let h=0,m=0;if(s>1){i.gppu>a.o+1&&(h=1),n.gppu>i.gppu&&(h=0);const f=e.previousElementSibling;f&&Math.abs(a.o-p(f).o)<40&&(m=1)}return{lr:h,badge_offset:m}}_createBadge(e,t){const s=this._getData(),o=document.createElement("span");if(o.className="mo-badge js-mo-badge",s.showCounterStyle==="none")o.style.opacity="0";else if(s.showCounterStyle==="image"){const r=document.createElement("img");r.className="mo-badge-icon",r.alt="",r.src=e.dataset.moIcon||C,o.appendChild(r)}else o.textContent=t;e.prepend(o)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const s=document.createElement("div");s.className="mo-card";const o=this._getData();if(o&&typeof o.renderCard=="function")o.renderCard(e,s);else{if(e.banner){const i=document.createElement("div");i.className="mo-card-image";const n=document.createElement("img");if(n.className="mo-banner",n.src=e.banner,n.alt="",i.appendChild(n),e.avatar){const a=document.createElement("img");a.className="mo-avatar",a.src=e.avatar,a.alt="",i.appendChild(a)}s.appendChild(i)}const r=document.createElement("div");if(r.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,r.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,r.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,r.appendChild(i)}s.appendChild(r)}return t.appendChild(s),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}_injectAdSlots(e){const t=this._getData();if(!t||!t.adSlots||!e.length)return;const{mode:s,interval:o,style:r}=t.adSlots,i=r==="fullwidth",n=this.element;let a=!1;if(s==="every_n")e.forEach((h,m)=>{if((t._adRealCount+m+1)%o===0){const f=this._createAdSlot(i);h.after(f),f.dataset.moAdPosition=String(Array.from(n.children).indexOf(f)),this._adObserver&&this._adObserver.observe(f),i&&(a=!0)}});else if(s==="random"){let h=t._adRealCount%o,m=0;for(;m<e.length;){const f=o-h,_=e.slice(m,m+f);if(_.length===f){const A=_[Math.floor(Math.random()*_.length)],b=this._createAdSlot(i);A.after(b),b.dataset.moAdPosition=String(Array.from(n.children).indexOf(b)),this._adObserver&&this._adObserver.observe(b),i&&(a=!0),h=0}else h+=_.length;m+=f}}t._adRealCount+=e.length,a&&this.refresh()}_createAdSlot(e){const t=document.createElement("li");return t.className="mo-ad-slot",e&&t.classList.add("mo-fullwidth"),t}_observeItems(e){this._observer&&e.forEach(t=>{t.classList.contains("mo-visible")||this._observer.observe(t)})}};E(g,"instances",new Set);let v=g;d.MoTimeline=v,d.default=v,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "motimeline",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "description": "Responsive two-column timeline layout library. Plain JavaScript, no dependencies.",
5
5
  "main": "./dist/moTimeline.cjs",
6
6
  "module": "./dist/moTimeline.js",
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * moTimeline v2.11.0 — CSS
2
+ * moTimeline v2.12.0 — CSS
3
3
  */
4
4
 
5
5
  /* ── CSS custom properties (easy override) ─────────────────── */
package/src/moTimeline.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * moTimeline v2.11.0
2
+ * moTimeline v2.12.0
3
3
  * Responsive two-column timeline layout library
4
4
  * https://github.com/MattOpen/moTimeline
5
5
  * MIT License
@@ -235,6 +235,26 @@ export class MoTimeline {
235
235
  return newEl;
236
236
  }
237
237
 
238
+ clear() {
239
+ const data = this._getData();
240
+ if (!data) return;
241
+
242
+ // Disconnect observers — they remain alive and will re-observe new items
243
+ if (this._observer) this._observer.disconnect();
244
+ if (this._adObserver) this._adObserver.disconnect();
245
+
246
+ // Remove all library-managed elements (real items + ad slots)
247
+ Array.from(this.element.children).forEach((child) => {
248
+ if (child.classList.contains('js-mo-item') || child.classList.contains('mo-ad-slot')) {
249
+ child.remove();
250
+ }
251
+ });
252
+
253
+ // Reset counters — ready for a fresh addItems() call
254
+ data.lastItemIdx = 0;
255
+ if (data.adSlots) data._adRealCount = 0;
256
+ }
257
+
238
258
  destroy() {
239
259
  window.removeEventListener('resize', this._resizeHandler);
240
260
  if (this._observer) {