motimeline 2.11.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 +58 -6
- package/dist/moTimeline.cjs +3 -3
- package/dist/moTimeline.css +2 -2
- package/dist/moTimeline.js +88 -57
- package/dist/moTimeline.umd.js +3 -3
- package/package.json +42 -42
- package/src/moTimeline.css +318 -310
- package/src/moTimeline.js +583 -521
package/README.md
CHANGED
|
@@ -19,7 +19,10 @@ 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()`
|
|
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
|
|
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.
|
|
23
26
|
- **Bootstrap compatible** — wrap the `<ul>` in a Bootstrap `.container`, no config needed
|
|
24
27
|
- **ESM · CJS · UMD** — works with any bundler or as a plain `<script>` tag
|
|
25
28
|
|
|
@@ -155,6 +158,7 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
155
158
|
| Attribute | Element | Description |
|
|
156
159
|
|---|---|---|
|
|
157
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. |
|
|
158
162
|
|
|
159
163
|
---
|
|
160
164
|
|
|
@@ -178,6 +182,7 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
178
182
|
| `mo-card-body` | `<div>` | Text content area. Padding and typography when `mo-theme` is active. |
|
|
179
183
|
| `mo-meta` | `<p>` | Date / subtitle line inside a card body. Muted colour, smaller font. |
|
|
180
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. |
|
|
181
186
|
|
|
182
187
|
---
|
|
183
188
|
|
|
@@ -186,11 +191,13 @@ The library injects classes and elements into your markup. Here is what a fully
|
|
|
186
191
|
```js
|
|
187
192
|
const tl = new MoTimeline(elementOrSelector, options);
|
|
188
193
|
|
|
189
|
-
tl.refresh();
|
|
190
|
-
tl.initNewItems();
|
|
191
|
-
tl.addItems(items);
|
|
192
|
-
tl.insertItem(item, index);
|
|
193
|
-
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
|
|
194
201
|
```
|
|
195
202
|
|
|
196
203
|
### insertItem
|
|
@@ -218,7 +225,8 @@ tl.addItems([
|
|
|
218
225
|
text: "Kicked off the roadmap.", // body paragraph
|
|
219
226
|
banner: "images/banner.jpg", // img.mo-banner (optional)
|
|
220
227
|
avatar: "images/avatar.jpg", // img.mo-avatar (optional)
|
|
221
|
-
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
|
|
222
230
|
},
|
|
223
231
|
]);
|
|
224
232
|
|
|
@@ -373,6 +381,41 @@ const tl = new MoTimeline('#my-timeline', {
|
|
|
373
381
|
|
|
374
382
|
Slots are injected after each `addItems()` call, so they work seamlessly with infinite scroll.
|
|
375
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
|
+
|
|
376
419
|
## Infinite scroll recipe
|
|
377
420
|
|
|
378
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.
|
|
@@ -465,6 +508,15 @@ No framework option needed. Wrap the `<ul>` inside a Bootstrap `.container`:
|
|
|
465
508
|
|
|
466
509
|
## Changelog
|
|
467
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
|
+
|
|
517
|
+
### v2.12.0
|
|
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.
|
|
519
|
+
|
|
468
520
|
### v2.11.0
|
|
469
521
|
- 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
522
|
|
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 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},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 v = (l, e, t) =>
|
|
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,12 +27,12 @@ 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
|
-
},
|
|
31
|
-
function
|
|
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
|
+
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);
|
|
@@ -45,7 +45,7 @@ function p(l) {
|
|
|
45
45
|
gppu: l.offsetTop + l.offsetHeight
|
|
46
46
|
} : { o: 0, h: 0, gppu: 0 };
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function w(l, e) {
|
|
49
49
|
const t = [];
|
|
50
50
|
let s = l.previousElementSibling;
|
|
51
51
|
for (; s; )
|
|
@@ -55,7 +55,7 @@ function b(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[
|
|
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,51 +109,81 @@ 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
|
+
}
|
|
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));
|
|
127
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
|
-
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());
|
|
131
137
|
});
|
|
132
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
|
+
}
|
|
133
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
|
+
}
|
|
134
164
|
_getData() {
|
|
135
165
|
return h.get(this.element);
|
|
136
166
|
}
|
|
137
167
|
_setDivider() {
|
|
138
168
|
const e = this._getData();
|
|
139
|
-
e && (e.col = e.columnCount[
|
|
169
|
+
e && (e.col = e.columnCount[b()], this.element.classList.toggle("mo-twocol", e.col > 1));
|
|
140
170
|
}
|
|
141
171
|
_initItems() {
|
|
142
172
|
const e = this.element, t = this._getData();
|
|
143
173
|
if (!t) return;
|
|
144
|
-
const s = t.lastItemIdx,
|
|
145
|
-
if (
|
|
146
|
-
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) => {
|
|
147
177
|
i.id || (i.id = "moT" + crypto.randomUUID() + "_" + (a + s)), i.classList.add("mo-item", "js-mo-item");
|
|
148
178
|
}), this._setDivider(), t.randomFullWidth) {
|
|
149
179
|
const i = t.randomFullWidth === !0 ? 0.33 : t.randomFullWidth;
|
|
150
|
-
|
|
180
|
+
o.forEach((a) => {
|
|
151
181
|
!a.classList.contains("mo-fullwidth") && Math.random() < i && a.classList.add("mo-fullwidth", "js-mo-fullwidth");
|
|
152
182
|
});
|
|
153
183
|
}
|
|
154
|
-
|
|
184
|
+
o.forEach((i, a) => {
|
|
155
185
|
t.showBadge && this._createBadge(i, a + s + 1), t.showArrow && this._createArrow(i);
|
|
156
|
-
}), 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) => {
|
|
157
187
|
i.querySelectorAll("img").forEach((a) => {
|
|
158
188
|
a.complete || a.addEventListener("load", this._resizeHandler, { once: !0 });
|
|
159
189
|
});
|
|
@@ -161,6 +191,7 @@ const f = class f {
|
|
|
161
191
|
}
|
|
162
192
|
}
|
|
163
193
|
_setPostPosition(e) {
|
|
194
|
+
if (e.classList.contains("mo-filtered-out")) return;
|
|
164
195
|
if (e.classList.contains("mo-fullwidth")) {
|
|
165
196
|
e.classList.remove("mo-inverted", "js-mo-inverted", "mo-offset");
|
|
166
197
|
return;
|
|
@@ -172,7 +203,7 @@ const f = class f {
|
|
|
172
203
|
if (!e) return null;
|
|
173
204
|
const t = this._getData();
|
|
174
205
|
if (!t) return null;
|
|
175
|
-
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);
|
|
176
207
|
let c = 0, d = 0;
|
|
177
208
|
if (s > 1) {
|
|
178
209
|
i.gppu > n.o + 1 && (c = 1), a.gppu > i.gppu && (c = 0);
|
|
@@ -182,24 +213,24 @@ const f = class f {
|
|
|
182
213
|
return { lr: c, badge_offset: d };
|
|
183
214
|
}
|
|
184
215
|
_createBadge(e, t) {
|
|
185
|
-
const s = this._getData(),
|
|
186
|
-
if (
|
|
187
|
-
|
|
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";
|
|
188
219
|
else if (s.showCounterStyle === "image") {
|
|
189
|
-
const
|
|
190
|
-
|
|
220
|
+
const o = document.createElement("img");
|
|
221
|
+
o.className = "mo-badge-icon", o.alt = "", o.src = e.dataset.moIcon || S, r.appendChild(o);
|
|
191
222
|
} else
|
|
192
|
-
|
|
193
|
-
e.prepend(
|
|
223
|
+
r.textContent = t;
|
|
224
|
+
e.prepend(r);
|
|
194
225
|
}
|
|
195
226
|
_createItemElement(e) {
|
|
196
227
|
const t = document.createElement("li");
|
|
197
|
-
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));
|
|
198
229
|
const s = document.createElement("div");
|
|
199
230
|
s.className = "mo-card";
|
|
200
|
-
const
|
|
201
|
-
if (
|
|
202
|
-
|
|
231
|
+
const r = this._getData();
|
|
232
|
+
if (r && typeof r.renderCard == "function")
|
|
233
|
+
r.renderCard(e, s);
|
|
203
234
|
else {
|
|
204
235
|
if (e.banner) {
|
|
205
236
|
const i = document.createElement("div");
|
|
@@ -211,20 +242,20 @@ const f = class f {
|
|
|
211
242
|
}
|
|
212
243
|
s.appendChild(i);
|
|
213
244
|
}
|
|
214
|
-
const
|
|
215
|
-
if (
|
|
245
|
+
const o = document.createElement("div");
|
|
246
|
+
if (o.className = "mo-card-body", e.title) {
|
|
216
247
|
const i = document.createElement("h3");
|
|
217
|
-
i.textContent = e.title,
|
|
248
|
+
i.textContent = e.title, o.appendChild(i);
|
|
218
249
|
}
|
|
219
250
|
if (e.meta) {
|
|
220
251
|
const i = document.createElement("p");
|
|
221
|
-
i.className = "mo-meta", i.textContent = e.meta,
|
|
252
|
+
i.className = "mo-meta", i.textContent = e.meta, o.appendChild(i);
|
|
222
253
|
}
|
|
223
254
|
if (e.text) {
|
|
224
255
|
const i = document.createElement("p");
|
|
225
|
-
i.textContent = e.text,
|
|
256
|
+
i.textContent = e.text, o.appendChild(i);
|
|
226
257
|
}
|
|
227
|
-
s.appendChild(
|
|
258
|
+
s.appendChild(o);
|
|
228
259
|
}
|
|
229
260
|
return t.appendChild(s), t;
|
|
230
261
|
}
|
|
@@ -235,19 +266,19 @@ const f = class f {
|
|
|
235
266
|
_injectAdSlots(e) {
|
|
236
267
|
const t = this._getData();
|
|
237
268
|
if (!t || !t.adSlots || !e.length) return;
|
|
238
|
-
const { mode: s, interval:
|
|
269
|
+
const { mode: s, interval: r, style: o } = t.adSlots, i = o === "fullwidth", a = this.element;
|
|
239
270
|
let n = !1;
|
|
240
271
|
if (s === "every_n")
|
|
241
272
|
e.forEach((c, d) => {
|
|
242
|
-
if ((t._adRealCount + d + 1) %
|
|
273
|
+
if ((t._adRealCount + d + 1) % r === 0) {
|
|
243
274
|
const m = this._createAdSlot(i);
|
|
244
275
|
c.after(m), m.dataset.moAdPosition = String(Array.from(a.children).indexOf(m)), this._adObserver && this._adObserver.observe(m), i && (n = !0);
|
|
245
276
|
}
|
|
246
277
|
});
|
|
247
278
|
else if (s === "random") {
|
|
248
|
-
let c = t._adRealCount %
|
|
279
|
+
let c = t._adRealCount % r, d = 0;
|
|
249
280
|
for (; d < e.length; ) {
|
|
250
|
-
const m =
|
|
281
|
+
const m = r - c, u = e.slice(d, d + m);
|
|
251
282
|
if (u.length === m) {
|
|
252
283
|
const E = u[Math.floor(Math.random() * u.length)], g = this._createAdSlot(i);
|
|
253
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;
|
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}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"}})});
|