motimeline 2.12.0 → 2.13.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 +53 -7
- package/dist/moTimeline.cjs +3 -3
- package/dist/moTimeline.css +2 -2
- package/dist/moTimeline.js +82 -57
- package/dist/moTimeline.umd.js +3 -3
- package/package.json +42 -42
- package/src/moTimeline.css +318 -310
- package/src/moTimeline.js +583 -541
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ Responsive two-column timeline layout library — plain JavaScript, zero depende
|
|
|
19
19
|
- **Badges & arrows** — numbered badges on the center line, directional arrows
|
|
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
|
+
- **Category filtering** — tag items with `categories` and call `filterByCategory()` to show/hide by category; active filter persists automatically through lazy-loaded batches
|
|
22
23
|
- **Dynamic items** — append, insert, or inject `<li>` elements at any time via `initNewItems()`, `addItems()`, or `insertItem()`
|
|
23
24
|
- **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
25
|
- **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.
|
|
@@ -157,6 +158,7 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
157
158
|
| Attribute | Element | Description |
|
|
158
159
|
|---|---|---|
|
|
159
160
|
| `data-mo-icon` | `<li>` | URL of the image shown inside the badge when `showCounterStyle: 'image'`. Accepts any web-safe format including inline SVG data URIs. Falls back to a built-in SVG icon if absent. Also set automatically by `addItems()` when an `icon` field is provided. |
|
|
161
|
+
| `data-categories` | `<li>` | Space-separated list of category tokens this item belongs to (e.g. `"development architecture"`). Used by `filterByCategory()`. Set automatically by `addItems()` / `insertItem()` when a `categories` field is provided. Can also be set manually in HTML. |
|
|
160
162
|
|
|
161
163
|
---
|
|
162
164
|
|
|
@@ -180,6 +182,7 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
180
182
|
| `mo-card-body` | `<div>` | Text content area. Padding and typography when `mo-theme` is active. |
|
|
181
183
|
| `mo-meta` | `<p>` | Date / subtitle line inside a card body. Muted colour, smaller font. |
|
|
182
184
|
| `js-mo-item` · `js-mo-inverted` | `<li>` | JS-only selector mirrors of `mo-item` / `mo-inverted`. Use in your own JS queries to avoid coupling to styling class names. |
|
|
185
|
+
| `mo-filtered-out` | `<li>` | Added by `filterByCategory()` to items that do not match the active filter. Sets `display: none` and excludes the item from column-placement calculations. Removed when the filter is cleared or the item's category is selected. |
|
|
183
186
|
|
|
184
187
|
---
|
|
185
188
|
|
|
@@ -188,12 +191,13 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
188
191
|
```js
|
|
189
192
|
const tl = new MoTimeline(elementOrSelector, options);
|
|
190
193
|
|
|
191
|
-
tl.refresh();
|
|
192
|
-
tl.initNewItems();
|
|
193
|
-
tl.addItems(items);
|
|
194
|
-
tl.insertItem(item, index);
|
|
195
|
-
tl.
|
|
196
|
-
tl.
|
|
194
|
+
tl.refresh(); // re-layout all items (called automatically on resize)
|
|
195
|
+
tl.initNewItems(); // pick up manually appended <li> elements
|
|
196
|
+
tl.addItems(items); // create and append <li> from an array of item objects (or JSON string)
|
|
197
|
+
tl.insertItem(item, index); // insert a single item at a specific index (or random if omitted)
|
|
198
|
+
tl.filterByCategory(category); // show only items matching category; null / 'all' shows everything
|
|
199
|
+
tl.clear(); // remove all items and ad slots, reset counters — instance stays alive
|
|
200
|
+
tl.destroy(); // remove listeners and reset DOM classes
|
|
197
201
|
```
|
|
198
202
|
|
|
199
203
|
### insertItem
|
|
@@ -221,7 +225,8 @@ tl.addItems([
|
|
|
221
225
|
text: "Kicked off the roadmap.", // body paragraph
|
|
222
226
|
banner: "images/banner.jpg", // img.mo-banner (optional)
|
|
223
227
|
avatar: "images/avatar.jpg", // img.mo-avatar (optional)
|
|
224
|
-
icon:
|
|
228
|
+
icon: "images/icon.svg", // data-mo-icon on <li>, used by showCounterStyle:'image'
|
|
229
|
+
categories: ["development", "architecture"] // used by filterByCategory() — array or space-separated string
|
|
225
230
|
},
|
|
226
231
|
]);
|
|
227
232
|
|
|
@@ -376,6 +381,41 @@ const tl = new MoTimeline('#my-timeline', {
|
|
|
376
381
|
|
|
377
382
|
Slots are injected after each `addItems()` call, so they work seamlessly with infinite scroll.
|
|
378
383
|
|
|
384
|
+
## Category filter recipe
|
|
385
|
+
|
|
386
|
+
Tag items with `categories` (array or space-separated string) and wire `filterByCategory()` to your own filter buttons. The active filter is stored on the instance — items added later via `addItems()` are filtered automatically, making it fully compatible with infinite scroll.
|
|
387
|
+
|
|
388
|
+
```js
|
|
389
|
+
const tl = new MoTimeline('#my-timeline', { theme: true, showBadge: true });
|
|
390
|
+
|
|
391
|
+
// Load items with categories
|
|
392
|
+
tl.addItems([
|
|
393
|
+
{ title: 'API cleanup', meta: 'Jan 2025', text: '...', categories: ['development', 'architecture'] },
|
|
394
|
+
{ title: 'Sprint review', meta: 'Feb 2025', text: '...', categories: 'management' },
|
|
395
|
+
]);
|
|
396
|
+
|
|
397
|
+
// Wire filter buttons
|
|
398
|
+
document.querySelectorAll('.filters button').forEach(btn => {
|
|
399
|
+
btn.addEventListener('click', () => {
|
|
400
|
+
document.querySelectorAll('.filters button').forEach(b => b.classList.remove('active'));
|
|
401
|
+
btn.classList.add('active');
|
|
402
|
+
tl.filterByCategory(btn.dataset.cat); // pass null or 'all' to show everything
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Active filter persists through lazy-loaded batches
|
|
407
|
+
tl.addItems(moreItemsFromServer); // auto-filtered to match current selection
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Or set `data-categories` directly in HTML and use `initNewItems()`:
|
|
411
|
+
|
|
412
|
+
```html
|
|
413
|
+
<li data-categories="development architecture">...</li>
|
|
414
|
+
<li data-categories="management">...</li>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
379
419
|
## Infinite scroll recipe
|
|
380
420
|
|
|
381
421
|
moTimeline handles the layout — you own the data fetching. Wire an `IntersectionObserver` to a sentinel element below the list and call `addItems()` when it comes into view.
|
|
@@ -468,6 +508,12 @@ No framework option needed. Wrap the `<ul>` inside a Bootstrap `.container`:
|
|
|
468
508
|
|
|
469
509
|
## Changelog
|
|
470
510
|
|
|
511
|
+
### v2.13.0
|
|
512
|
+
- New: **category filtering** — tag items with `categories` (array or space-separated string) and call `filterByCategory(category)` to show only matching items. Pass `null` or `'all'` to clear the filter. The active filter is stored on the instance and applied automatically to items added via `addItems()` or `initNewItems()`, making it fully compatible with infinite scroll / server-side pagination. Column placement recalculates on every filter change so the two-column layout stays correct. New class `mo-filtered-out` is used internally (`display: none`) and new attribute `data-categories` is set on each `<li>`.
|
|
513
|
+
|
|
514
|
+
### v2.12.1
|
|
515
|
+
- Fix: badge width — use `width` instead of `min-width` to prevent oversized badges ([#8](https://github.com/MattOpen/moTimeline/issues/8))
|
|
516
|
+
|
|
471
517
|
### v2.12.0
|
|
472
518
|
- 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
519
|
|
package/dist/moTimeline.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
* moTimeline v2.
|
|
1
|
+
"use strict";var A=Object.defineProperty;var S=(l,e,t)=>e in l?A(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.13.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 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;
|
|
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},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 y(){const l=window.innerWidth;return l<600?"xs":l<992?"sm":l<1200?"md":"lg"}function L(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 w(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=L(()=>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(r=>{r.forEach(o=>{o.isIntersecting&&(o.target.classList.add("mo-visible"),this._observer.unobserve(o.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(r=>{r.isIntersecting&&(this._adObserver.unobserve(r.target),t.adSlots.onEnterViewport(r.target,Number(r.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[y()],e._setDivider(),Array.from(t.children).forEach(r=>{e._setPostPosition(r)}))})}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,r=this._getData();if(!r)return;const o=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(o):s.insertBefore(o,i[a]),o.id||(o.id="moT"+crypto.randomUUID()+"_"+a),o.classList.add("mo-item","js-mo-item"),e.fullWidth)o.classList.add("mo-fullwidth","js-mo-fullwidth");else if(r.randomFullWidth){const n=r.randomFullWidth===!0?.33:r.randomFullWidth;Math.random()<n&&o.classList.add("mo-fullwidth","js-mo-fullwidth")}return r.showBadge&&this._createBadge(o,a+1),r.showArrow&&this._createArrow(o),r.showBadge&&r.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((n,c)=>{const d=n.querySelector(".js-mo-badge");d&&(d.textContent=c+1)}),r.lastItemIdx=Array.from(s.children).length,h.set(s,r),this.refresh(),this._observeItems([o]),o.querySelectorAll("img").forEach(n=>{n.complete||n.addEventListener("load",this._resizeHandler,{once:!0})}),o}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","mo-filtered-out"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}filterByCategory(e){const t=this._getData();t&&(t._activeFilter=e==null||e===""||e==="all"?null:String(e),h.set(this.element,t),this._applyFilter(Array.from(this.element.querySelectorAll(".js-mo-item"))),this.refresh())}_applyFilter(e){const t=this._getData();if(!t)return;const s=t._activeFilter||null;e.forEach(r=>{if(!s)r.classList.remove("mo-filtered-out");else{const o=(r.dataset.categories||"").split(/\s+/).filter(Boolean);r.classList.toggle("mo-filtered-out",!o.includes(s))}})}_getData(){return h.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[y()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,r=Array.from(e.children),o=r.slice(s);if(o.length!==0){if(o.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;o.forEach(a=>{!a.classList.contains("mo-fullwidth")&&Math.random()<i&&a.classList.add("mo-fullwidth","js-mo-fullwidth")})}o.forEach((i,a)=>{t.showBadge&&this._createBadge(i,a+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=r.length,h.set(e,t),this._applyFilter(o),this.refresh(),this._observeItems(o),this._injectAdSlots(o),o.forEach(i=>{i.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-filtered-out"))return;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,r=w(e,".js-mo-inverted:not(.mo-filtered-out)")[0]||null,o=w(e,".js-mo-item:not(.js-mo-inverted):not(.mo-filtered-out)")[0]||null,i=v(o),a=v(r),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(),r=document.createElement("span");if(r.className="mo-badge js-mo-badge",s.showCounterStyle==="none")r.style.opacity="0";else if(s.showCounterStyle==="image"){const o=document.createElement("img");o.className="mo-badge-icon",o.alt="",o.src=e.dataset.moIcon||C,r.appendChild(o)}else r.textContent=t;e.prepend(r)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon),e.categories&&(t.dataset.categories=Array.isArray(e.categories)?e.categories.join(" "):String(e.categories));const s=document.createElement("div");s.className="mo-card";const r=this._getData();if(r&&typeof r.renderCard=="function")r.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 o=document.createElement("div");if(o.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,o.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,o.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,o.appendChild(i)}s.appendChild(o)}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:r,style:o}=t.adSlots,i=o==="fullwidth",a=this.element;let n=!1;if(s==="every_n")e.forEach((c,d)=>{if((t._adRealCount+d+1)%r===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%r,d=0;for(;d<e.length;){const m=r-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;
|
package/dist/moTimeline.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* moTimeline v2.
|
|
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;
|
|
2
|
+
* moTimeline v2.13.0 — CSS
|
|
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;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}.mo-timeline>.mo-item.mo-filtered-out{display:none}
|
package/dist/moTimeline.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
1
|
+
var A = Object.defineProperty;
|
|
2
|
+
var C = (l, e, t) => e in l ? A(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
|
|
3
|
+
var v = (l, e, t) => C(l, typeof e != "symbol" ? e + "" : e, t);
|
|
4
4
|
/*!
|
|
5
|
-
* moTimeline v2.
|
|
5
|
+
* moTimeline v2.13.0
|
|
6
6
|
* Responsive two-column timeline layout library
|
|
7
7
|
* https://github.com/MattOpen/moTimeline
|
|
8
8
|
* MIT License
|
|
@@ -27,18 +27,18 @@ const h = /* @__PURE__ */ new WeakMap(), _ = {
|
|
|
27
27
|
// (item, cardEl) => void — custom card renderer; skips built-in HTML
|
|
28
28
|
adSlots: null
|
|
29
29
|
// { mode, interval, style, onEnterViewport } — see docs
|
|
30
|
-
},
|
|
30
|
+
}, S = "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
31
|
function b() {
|
|
32
32
|
const l = window.innerWidth;
|
|
33
33
|
return l < 600 ? "xs" : l < 992 ? "sm" : l < 1200 ? "md" : "lg";
|
|
34
34
|
}
|
|
35
|
-
function
|
|
35
|
+
function L(l, e = 100) {
|
|
36
36
|
let t;
|
|
37
37
|
return (...s) => {
|
|
38
38
|
clearTimeout(t), t = setTimeout(() => l(...s), e);
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function
|
|
41
|
+
function p(l) {
|
|
42
42
|
return l ? {
|
|
43
43
|
o: l.offsetTop,
|
|
44
44
|
h: l.offsetHeight,
|
|
@@ -55,7 +55,7 @@ function w(l, e) {
|
|
|
55
55
|
const f = class f {
|
|
56
56
|
constructor(e, t = {}) {
|
|
57
57
|
if (typeof e == "string" && (e = document.querySelector(e)), !e) throw new Error("moTimeline: element not found");
|
|
58
|
-
this.element = e, this.settings = Object.assign({}, _, t), this.settings.columnCount = Object.assign({}, _.columnCount, t.columnCount), this._resizeHandler =
|
|
58
|
+
this.element = e, this.settings = Object.assign({}, _, t), this.settings.columnCount = Object.assign({}, _.columnCount, t.columnCount), this._resizeHandler = L(() => this.refresh(), 100), this._initialized = !1, this.init();
|
|
59
59
|
}
|
|
60
60
|
init() {
|
|
61
61
|
const e = this.element;
|
|
@@ -66,23 +66,23 @@ const f = class f {
|
|
|
66
66
|
const t = Object.assign({}, this.settings, { lastItemIdx: 0 });
|
|
67
67
|
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) {
|
|
68
68
|
const s = t.animate === !0 ? "fade" : t.animate;
|
|
69
|
-
e.classList.add("mo-animate", `mo-animate-${s}`), this._observer = new IntersectionObserver((
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
e.classList.add("mo-animate", `mo-animate-${s}`), this._observer = new IntersectionObserver((r) => {
|
|
70
|
+
r.forEach((o) => {
|
|
71
|
+
o.isIntersecting && (o.target.classList.add("mo-visible"), this._observer.unobserve(o.target));
|
|
72
72
|
});
|
|
73
73
|
}, { threshold: 0.1 });
|
|
74
74
|
}
|
|
75
75
|
t.adSlots && (t._adRealCount = 0, typeof t.adSlots.onEnterViewport == "function" && (this._adObserver = new IntersectionObserver((s) => {
|
|
76
|
-
s.forEach((
|
|
77
|
-
|
|
76
|
+
s.forEach((r) => {
|
|
77
|
+
r.isIntersecting && (this._adObserver.unobserve(r.target), t.adSlots.onEnterViewport(r.target, Number(r.target.dataset.moAdPosition)));
|
|
78
78
|
});
|
|
79
79
|
}, { threshold: 0.5 }))), this._initialized = !0, window.addEventListener("resize", this._resizeHandler), Array.from(e.children).length > 0 && this._initItems();
|
|
80
80
|
}
|
|
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[b()], e._setDivider(), Array.from(t.children).forEach((
|
|
85
|
-
e._setPostPosition(
|
|
84
|
+
s && (s.col = s.columnCount[b()], e._setDivider(), Array.from(t.children).forEach((r) => {
|
|
85
|
+
e._setPostPosition(r);
|
|
86
86
|
}));
|
|
87
87
|
});
|
|
88
88
|
}
|
|
@@ -109,21 +109,21 @@ const f = class f {
|
|
|
109
109
|
* @returns {HTMLElement} the inserted <li> element
|
|
110
110
|
*/
|
|
111
111
|
insertItem(e, t) {
|
|
112
|
-
const s = this.element,
|
|
113
|
-
if (!
|
|
114
|
-
const
|
|
115
|
-
if (a >= i.length ? s.appendChild(
|
|
116
|
-
|
|
117
|
-
else if (
|
|
118
|
-
const n =
|
|
119
|
-
Math.random() < n &&
|
|
112
|
+
const s = this.element, r = this._getData();
|
|
113
|
+
if (!r) return;
|
|
114
|
+
const o = 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));
|
|
115
|
+
if (a >= i.length ? s.appendChild(o) : s.insertBefore(o, i[a]), o.id || (o.id = "moT" + crypto.randomUUID() + "_" + a), o.classList.add("mo-item", "js-mo-item"), e.fullWidth)
|
|
116
|
+
o.classList.add("mo-fullwidth", "js-mo-fullwidth");
|
|
117
|
+
else if (r.randomFullWidth) {
|
|
118
|
+
const n = r.randomFullWidth === !0 ? 0.33 : r.randomFullWidth;
|
|
119
|
+
Math.random() < n && o.classList.add("mo-fullwidth", "js-mo-fullwidth");
|
|
120
120
|
}
|
|
121
|
-
return
|
|
121
|
+
return r.showBadge && this._createBadge(o, a + 1), r.showArrow && this._createArrow(o), r.showBadge && r.showCounterStyle === "counter" && Array.from(s.querySelectorAll(".js-mo-item")).forEach((n, c) => {
|
|
122
122
|
const d = n.querySelector(".js-mo-badge");
|
|
123
123
|
d && (d.textContent = c + 1);
|
|
124
|
-
}),
|
|
124
|
+
}), r.lastItemIdx = Array.from(s.children).length, h.set(s, r), this.refresh(), this._observeItems([o]), o.querySelectorAll("img").forEach((n) => {
|
|
125
125
|
n.complete || n.addEventListener("load", this._resizeHandler, { once: !0 });
|
|
126
|
-
}),
|
|
126
|
+
}), o;
|
|
127
127
|
}
|
|
128
128
|
clear() {
|
|
129
129
|
const e = this._getData();
|
|
@@ -133,10 +133,34 @@ const f = class f {
|
|
|
133
133
|
}
|
|
134
134
|
destroy() {
|
|
135
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) => {
|
|
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
|
+
e.classList.remove("mo-item", "js-mo-item", "mo-inverted", "js-mo-inverted", "mo-offset", "mo-fullwidth", "js-mo-fullwidth", "mo-visible", "mo-filtered-out"), e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach((t) => t.remove());
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Filter visible items by category.
|
|
141
|
+
* Pass null / 'all' / '' to show everything.
|
|
142
|
+
* The active filter is remembered and applied automatically to items added later.
|
|
143
|
+
*
|
|
144
|
+
* @param {string|null} category — value to match against data-categories on each item
|
|
145
|
+
*/
|
|
146
|
+
filterByCategory(e) {
|
|
147
|
+
const t = this._getData();
|
|
148
|
+
t && (t._activeFilter = e == null || e === "" || e === "all" ? null : String(e), h.set(this.element, t), this._applyFilter(Array.from(this.element.querySelectorAll(".js-mo-item"))), this.refresh());
|
|
149
|
+
}
|
|
139
150
|
// ─── Private ────────────────────────────────────────────────────────────────
|
|
151
|
+
_applyFilter(e) {
|
|
152
|
+
const t = this._getData();
|
|
153
|
+
if (!t) return;
|
|
154
|
+
const s = t._activeFilter || null;
|
|
155
|
+
e.forEach((r) => {
|
|
156
|
+
if (!s)
|
|
157
|
+
r.classList.remove("mo-filtered-out");
|
|
158
|
+
else {
|
|
159
|
+
const o = (r.dataset.categories || "").split(/\s+/).filter(Boolean);
|
|
160
|
+
r.classList.toggle("mo-filtered-out", !o.includes(s));
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
140
164
|
_getData() {
|
|
141
165
|
return h.get(this.element);
|
|
142
166
|
}
|
|
@@ -147,19 +171,19 @@ const f = class f {
|
|
|
147
171
|
_initItems() {
|
|
148
172
|
const e = this.element, t = this._getData();
|
|
149
173
|
if (!t) return;
|
|
150
|
-
const s = t.lastItemIdx,
|
|
151
|
-
if (
|
|
152
|
-
if (
|
|
174
|
+
const s = t.lastItemIdx, r = Array.from(e.children), o = r.slice(s);
|
|
175
|
+
if (o.length !== 0) {
|
|
176
|
+
if (o.forEach((i, a) => {
|
|
153
177
|
i.id || (i.id = "moT" + crypto.randomUUID() + "_" + (a + s)), i.classList.add("mo-item", "js-mo-item");
|
|
154
178
|
}), this._setDivider(), t.randomFullWidth) {
|
|
155
179
|
const i = t.randomFullWidth === !0 ? 0.33 : t.randomFullWidth;
|
|
156
|
-
|
|
180
|
+
o.forEach((a) => {
|
|
157
181
|
!a.classList.contains("mo-fullwidth") && Math.random() < i && a.classList.add("mo-fullwidth", "js-mo-fullwidth");
|
|
158
182
|
});
|
|
159
183
|
}
|
|
160
|
-
|
|
184
|
+
o.forEach((i, a) => {
|
|
161
185
|
t.showBadge && this._createBadge(i, a + s + 1), t.showArrow && this._createArrow(i);
|
|
162
|
-
}), t.lastItemIdx =
|
|
186
|
+
}), t.lastItemIdx = r.length, h.set(e, t), this._applyFilter(o), this.refresh(), this._observeItems(o), this._injectAdSlots(o), o.forEach((i) => {
|
|
163
187
|
i.querySelectorAll("img").forEach((a) => {
|
|
164
188
|
a.complete || a.addEventListener("load", this._resizeHandler, { once: !0 });
|
|
165
189
|
});
|
|
@@ -167,6 +191,7 @@ const f = class f {
|
|
|
167
191
|
}
|
|
168
192
|
}
|
|
169
193
|
_setPostPosition(e) {
|
|
194
|
+
if (e.classList.contains("mo-filtered-out")) return;
|
|
170
195
|
if (e.classList.contains("mo-fullwidth")) {
|
|
171
196
|
e.classList.remove("mo-inverted", "js-mo-inverted", "mo-offset");
|
|
172
197
|
return;
|
|
@@ -178,34 +203,34 @@ const f = class f {
|
|
|
178
203
|
if (!e) return null;
|
|
179
204
|
const t = this._getData();
|
|
180
205
|
if (!t) return null;
|
|
181
|
-
const s = t.col,
|
|
206
|
+
const s = t.col, r = w(e, ".js-mo-inverted:not(.mo-filtered-out)")[0] || null, o = w(e, ".js-mo-item:not(.js-mo-inverted):not(.mo-filtered-out)")[0] || null, i = p(o), a = p(r), n = p(e);
|
|
182
207
|
let c = 0, d = 0;
|
|
183
208
|
if (s > 1) {
|
|
184
209
|
i.gppu > n.o + 1 && (c = 1), a.gppu > i.gppu && (c = 0);
|
|
185
210
|
const m = e.previousElementSibling;
|
|
186
|
-
m && Math.abs(n.o -
|
|
211
|
+
m && Math.abs(n.o - p(m).o) < 40 && (d = 1);
|
|
187
212
|
}
|
|
188
213
|
return { lr: c, badge_offset: d };
|
|
189
214
|
}
|
|
190
215
|
_createBadge(e, t) {
|
|
191
|
-
const s = this._getData(),
|
|
192
|
-
if (
|
|
193
|
-
|
|
216
|
+
const s = this._getData(), r = document.createElement("span");
|
|
217
|
+
if (r.className = "mo-badge js-mo-badge", s.showCounterStyle === "none")
|
|
218
|
+
r.style.opacity = "0";
|
|
194
219
|
else if (s.showCounterStyle === "image") {
|
|
195
|
-
const
|
|
196
|
-
|
|
220
|
+
const o = document.createElement("img");
|
|
221
|
+
o.className = "mo-badge-icon", o.alt = "", o.src = e.dataset.moIcon || S, r.appendChild(o);
|
|
197
222
|
} else
|
|
198
|
-
|
|
199
|
-
e.prepend(
|
|
223
|
+
r.textContent = t;
|
|
224
|
+
e.prepend(r);
|
|
200
225
|
}
|
|
201
226
|
_createItemElement(e) {
|
|
202
227
|
const t = document.createElement("li");
|
|
203
|
-
e.icon && (t.dataset.moIcon = e.icon);
|
|
228
|
+
e.icon && (t.dataset.moIcon = e.icon), e.categories && (t.dataset.categories = Array.isArray(e.categories) ? e.categories.join(" ") : String(e.categories));
|
|
204
229
|
const s = document.createElement("div");
|
|
205
230
|
s.className = "mo-card";
|
|
206
|
-
const
|
|
207
|
-
if (
|
|
208
|
-
|
|
231
|
+
const r = this._getData();
|
|
232
|
+
if (r && typeof r.renderCard == "function")
|
|
233
|
+
r.renderCard(e, s);
|
|
209
234
|
else {
|
|
210
235
|
if (e.banner) {
|
|
211
236
|
const i = document.createElement("div");
|
|
@@ -217,20 +242,20 @@ const f = class f {
|
|
|
217
242
|
}
|
|
218
243
|
s.appendChild(i);
|
|
219
244
|
}
|
|
220
|
-
const
|
|
221
|
-
if (
|
|
245
|
+
const o = document.createElement("div");
|
|
246
|
+
if (o.className = "mo-card-body", e.title) {
|
|
222
247
|
const i = document.createElement("h3");
|
|
223
|
-
i.textContent = e.title,
|
|
248
|
+
i.textContent = e.title, o.appendChild(i);
|
|
224
249
|
}
|
|
225
250
|
if (e.meta) {
|
|
226
251
|
const i = document.createElement("p");
|
|
227
|
-
i.className = "mo-meta", i.textContent = e.meta,
|
|
252
|
+
i.className = "mo-meta", i.textContent = e.meta, o.appendChild(i);
|
|
228
253
|
}
|
|
229
254
|
if (e.text) {
|
|
230
255
|
const i = document.createElement("p");
|
|
231
|
-
i.textContent = e.text,
|
|
256
|
+
i.textContent = e.text, o.appendChild(i);
|
|
232
257
|
}
|
|
233
|
-
s.appendChild(
|
|
258
|
+
s.appendChild(o);
|
|
234
259
|
}
|
|
235
260
|
return t.appendChild(s), t;
|
|
236
261
|
}
|
|
@@ -241,19 +266,19 @@ const f = class f {
|
|
|
241
266
|
_injectAdSlots(e) {
|
|
242
267
|
const t = this._getData();
|
|
243
268
|
if (!t || !t.adSlots || !e.length) return;
|
|
244
|
-
const { mode: s, interval:
|
|
269
|
+
const { mode: s, interval: r, style: o } = t.adSlots, i = o === "fullwidth", a = this.element;
|
|
245
270
|
let n = !1;
|
|
246
271
|
if (s === "every_n")
|
|
247
272
|
e.forEach((c, d) => {
|
|
248
|
-
if ((t._adRealCount + d + 1) %
|
|
273
|
+
if ((t._adRealCount + d + 1) % r === 0) {
|
|
249
274
|
const m = this._createAdSlot(i);
|
|
250
275
|
c.after(m), m.dataset.moAdPosition = String(Array.from(a.children).indexOf(m)), this._adObserver && this._adObserver.observe(m), i && (n = !0);
|
|
251
276
|
}
|
|
252
277
|
});
|
|
253
278
|
else if (s === "random") {
|
|
254
|
-
let c = t._adRealCount %
|
|
279
|
+
let c = t._adRealCount % r, d = 0;
|
|
255
280
|
for (; d < e.length; ) {
|
|
256
|
-
const m =
|
|
281
|
+
const m = r - c, u = e.slice(d, d + m);
|
|
257
282
|
if (u.length === m) {
|
|
258
283
|
const E = u[Math.floor(Math.random() * u.length)], g = this._createAdSlot(i);
|
|
259
284
|
E.after(g), g.dataset.moAdPosition = String(Array.from(a.children).indexOf(g)), this._adObserver && this._adObserver.observe(g), i && (n = !0), c = 0;
|
|
@@ -274,7 +299,7 @@ const f = class f {
|
|
|
274
299
|
});
|
|
275
300
|
}
|
|
276
301
|
};
|
|
277
|
-
|
|
302
|
+
v(f, "instances", /* @__PURE__ */ new Set());
|
|
278
303
|
let y = f;
|
|
279
304
|
export {
|
|
280
305
|
y as MoTimeline,
|
package/dist/moTimeline.umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(d,
|
|
2
|
-
* moTimeline v2.
|
|
1
|
+
(function(d,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(d=typeof globalThis<"u"?globalThis:d||self,n(d.MoTimeline={}))})(this,function(d){"use strict";var L=Object.defineProperty;var I=(d,n,u)=>n in d?L(d,n,{enumerable:!0,configurable:!0,writable:!0,value:u}):d[n]=u;var E=(d,n,u)=>I(d,typeof n!="symbol"?n+"":n,u);/*!
|
|
2
|
+
* moTimeline v2.13.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}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"}})});
|
|
6
|
+
*/const n=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},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 y(){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 w(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(n.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});if(n.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(r=>{r.forEach(o=>{o.isIntersecting&&(o.target.classList.add("mo-visible"),this._observer.unobserve(o.target))})},{threshold:.1})}t.adSlots&&(t._adRealCount=0,typeof t.adSlots.onEnterViewport=="function"&&(this._adObserver=new IntersectionObserver(s=>{s.forEach(r=>{r.isIntersecting&&(this._adObserver.unobserve(r.target),t.adSlots.onEnterViewport(r.target,Number(r.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=n.get(t);s&&(s.col=s.columnCount[y()],e._setDivider(),Array.from(t.children).forEach(r=>{e._setPostPosition(r)}))})}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,r=this._getData();if(!r)return;const o=this._createItemElement(e),i=Array.from(s.children).filter(l=>l.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(o):s.insertBefore(o,i[a]),o.id||(o.id="moT"+crypto.randomUUID()+"_"+a),o.classList.add("mo-item","js-mo-item"),e.fullWidth)o.classList.add("mo-fullwidth","js-mo-fullwidth");else if(r.randomFullWidth){const l=r.randomFullWidth===!0?.33:r.randomFullWidth;Math.random()<l&&o.classList.add("mo-fullwidth","js-mo-fullwidth")}return r.showBadge&&this._createBadge(o,a+1),r.showArrow&&this._createArrow(o),r.showBadge&&r.showCounterStyle==="counter"&&Array.from(s.querySelectorAll(".js-mo-item")).forEach((l,h)=>{const m=l.querySelector(".js-mo-badge");m&&(m.textContent=h+1)}),r.lastItemIdx=Array.from(s.children).length,n.set(s,r),this.refresh(),this._observeItems([o]),o.querySelectorAll("img").forEach(l=>{l.complete||l.addEventListener("load",this._resizeHandler,{once:!0})}),o}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()),n.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","mo-filtered-out"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}filterByCategory(e){const t=this._getData();t&&(t._activeFilter=e==null||e===""||e==="all"?null:String(e),n.set(this.element,t),this._applyFilter(Array.from(this.element.querySelectorAll(".js-mo-item"))),this.refresh())}_applyFilter(e){const t=this._getData();if(!t)return;const s=t._activeFilter||null;e.forEach(r=>{if(!s)r.classList.remove("mo-filtered-out");else{const o=(r.dataset.categories||"").split(/\s+/).filter(Boolean);r.classList.toggle("mo-filtered-out",!o.includes(s))}})}_getData(){return n.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[y()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,r=Array.from(e.children),o=r.slice(s);if(o.length!==0){if(o.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;o.forEach(a=>{!a.classList.contains("mo-fullwidth")&&Math.random()<i&&a.classList.add("mo-fullwidth","js-mo-fullwidth")})}o.forEach((i,a)=>{t.showBadge&&this._createBadge(i,a+s+1),t.showArrow&&this._createArrow(i)}),t.lastItemIdx=r.length,n.set(e,t),this._applyFilter(o),this.refresh(),this._observeItems(o),this._injectAdSlots(o),o.forEach(i=>{i.querySelectorAll("img").forEach(a=>{a.complete||a.addEventListener("load",this._resizeHandler,{once:!0})})})}}_setPostPosition(e){if(e.classList.contains("mo-filtered-out"))return;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,r=w(e,".js-mo-inverted:not(.mo-filtered-out)")[0]||null,o=w(e,".js-mo-item:not(.js-mo-inverted):not(.mo-filtered-out)")[0]||null,i=p(o),a=p(r),l=p(e);let h=0,m=0;if(s>1){i.gppu>l.o+1&&(h=1),a.gppu>i.gppu&&(h=0);const f=e.previousElementSibling;f&&Math.abs(l.o-p(f).o)<40&&(m=1)}return{lr:h,badge_offset:m}}_createBadge(e,t){const s=this._getData(),r=document.createElement("span");if(r.className="mo-badge js-mo-badge",s.showCounterStyle==="none")r.style.opacity="0";else if(s.showCounterStyle==="image"){const o=document.createElement("img");o.className="mo-badge-icon",o.alt="",o.src=e.dataset.moIcon||A,r.appendChild(o)}else r.textContent=t;e.prepend(r)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon),e.categories&&(t.dataset.categories=Array.isArray(e.categories)?e.categories.join(" "):String(e.categories));const s=document.createElement("div");s.className="mo-card";const r=this._getData();if(r&&typeof r.renderCard=="function")r.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 l=document.createElement("img");l.className="mo-avatar",l.src=e.avatar,l.alt="",i.appendChild(l)}s.appendChild(i)}const o=document.createElement("div");if(o.className="mo-card-body",e.title){const i=document.createElement("h3");i.textContent=e.title,o.appendChild(i)}if(e.meta){const i=document.createElement("p");i.className="mo-meta",i.textContent=e.meta,o.appendChild(i)}if(e.text){const i=document.createElement("p");i.textContent=e.text,o.appendChild(i)}s.appendChild(o)}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:r,style:o}=t.adSlots,i=o==="fullwidth",a=this.element;let l=!1;if(s==="every_n")e.forEach((h,m)=>{if((t._adRealCount+m+1)%r===0){const f=this._createAdSlot(i);h.after(f),f.dataset.moAdPosition=String(Array.from(a.children).indexOf(f)),this._adObserver&&this._adObserver.observe(f),i&&(l=!0)}});else if(s==="random"){let h=t._adRealCount%r,m=0;for(;m<e.length;){const f=r-h,_=e.slice(m,m+f);if(_.length===f){const C=_[Math.floor(Math.random()*_.length)],b=this._createAdSlot(i);C.after(b),b.dataset.moAdPosition=String(Array.from(a.children).indexOf(b)),this._adObserver&&this._adObserver.observe(b),i&&(l=!0),h=0}else h+=_.length;m+=f}}t._adRealCount+=e.length,l&&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"}})});
|