motimeline 2.3.0 → 2.4.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 +26 -3
- package/dist/moTimeline.cjs +3 -3
- package/dist/moTimeline.css +1 -1
- package/dist/moTimeline.js +112 -71
- package/dist/moTimeline.umd.js +3 -3
- package/package.json +1 -1
- package/src/moTimeline.css +2 -4
- package/src/moTimeline.js +64 -1
package/README.md
CHANGED
|
@@ -111,9 +111,28 @@ import 'motimeline/dist/moTimeline.css';
|
|
|
111
111
|
```js
|
|
112
112
|
const tl = new MoTimeline(elementOrSelector, options);
|
|
113
113
|
|
|
114
|
-
tl.refresh();
|
|
115
|
-
tl.initNewItems();
|
|
116
|
-
tl.
|
|
114
|
+
tl.refresh(); // re-layout all items (called automatically on resize)
|
|
115
|
+
tl.initNewItems(); // pick up manually appended <li> elements
|
|
116
|
+
tl.addItems(items); // create and append <li> from an array of item objects (or JSON string)
|
|
117
|
+
tl.destroy(); // remove listeners and reset DOM classes
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### addItems — item schema
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
tl.addItems([
|
|
124
|
+
{
|
|
125
|
+
title: "Project kickoff", // <h3> heading
|
|
126
|
+
meta: "January 2024", // date / subtitle line
|
|
127
|
+
text: "Kicked off the roadmap.", // body paragraph
|
|
128
|
+
banner: "images/banner.jpg", // img.mo-banner (optional)
|
|
129
|
+
avatar: "images/avatar.jpg", // img.mo-avatar (optional)
|
|
130
|
+
icon: "images/icon.svg" // data-mo-icon on <li>, used by showCounterStyle:'image'
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
// A JSON string is also accepted:
|
|
135
|
+
tl.addItems('[{"title":"From JSON","meta":"Today","text":"Parsed automatically."}]');
|
|
117
136
|
```
|
|
118
137
|
|
|
119
138
|
---
|
|
@@ -157,6 +176,10 @@ No framework option needed. Wrap the `<ul>` inside a Bootstrap `.container`:
|
|
|
157
176
|
|
|
158
177
|
## Changelog
|
|
159
178
|
|
|
179
|
+
### v2.4.0
|
|
180
|
+
- Added `addItems(items)` — creates and appends `<li>` elements from an array of item objects or a JSON string, then initializes them in one batch
|
|
181
|
+
- Badges and arrows now hidden in single-column mode (center-line elements have no meaning without a center line)
|
|
182
|
+
|
|
160
183
|
### v2.3.0
|
|
161
184
|
- Added `showCounter` (opacity toggle) and `showCounterStyle` (`'counter'` | `'image'`) badge options
|
|
162
185
|
- `data-mo-icon` attribute on `<li>` sets a custom icon in image mode; built-in flat SVG used as fallback
|
package/dist/moTimeline.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
* moTimeline v2.
|
|
1
|
+
"use strict";var _=Object.defineProperty;var b=(o,e,t)=>e in o?_(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var p=(o,e,t)=>b(o,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});/*!
|
|
2
|
+
* moTimeline v2.4.0
|
|
3
3
|
* Responsive two-column timeline layout library
|
|
4
4
|
* https://github.com/MattOpen/moTimeline
|
|
5
5
|
* MIT License
|
|
6
|
-
*/const
|
|
6
|
+
*/const c=new WeakMap,w={columnCount:{xs:1,sm:2,md:2,lg:2},badgeShow:!1,arrowShow:!1,theme:!1,showCounter:!0,showCounterStyle:"counter"},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 v(){const o=window.innerWidth;return o<600?"xs":o<992?"sm":o<1200?"md":"lg"}function I(o,e=100){let t;return(...s)=>{clearTimeout(t),t=setTimeout(()=>o(...s),e)}}function m(o){return o?{o:o.offsetTop,h:o.offsetHeight,gppu:o.offsetTop+o.offsetHeight}:{o:0,h:0,gppu:0}}function E(o,e){const t=[];let s=o.previousElementSibling;for(;s;)(!e||s.matches(e))&&t.push(s),s=s.previousElementSibling;return t}const l=class l{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({},w,t),this.settings.columnCount=Object.assign({},w.columnCount,t.columnCount),this._resizeHandler=I(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(c.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});c.set(e,t),l.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),Array.from(e.children).length!==0&&(this._initItems(),this._initialized=!0,window.addEventListener("resize",this._resizeHandler))}refresh(){l.instances.forEach(e=>{const t=e.element,s=c.get(t);s&&(s.col=s.columnCount[v()],e._setDivider(),Array.from(t.children).forEach(i=>{e._setPostPosition(i)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}destroy(){window.removeEventListener("resize",this._resizeHandler),c.delete(this.element),l.instances.delete(this),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return c.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[v()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const s=t.lastItemIdx,i=Array.from(e.children),n=i.slice(s);n.length!==0&&(n.forEach((r,a)=>{r.id||(r.id="moT"+crypto.randomUUID()+"_"+(a+s)),r.classList.add("mo-item","js-mo-item")}),this._setDivider(),n.forEach((r,a)=>{t.badgeShow&&this._createBadge(r,a+s+1),t.arrowShow&&this._createArrow(r)}),t.lastItemIdx=i.length,c.set(e,t),this.refresh())}_setPostPosition(e){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,i=E(e,".js-mo-inverted")[0]||null,n=E(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,r=m(n),a=m(i),u=m(e);let h=0,f=0;if(s>1){r.gppu>u.o&&(h=1),a.gppu>r.gppu&&(h=0);const g=e.previousElementSibling;g&&Math.abs(u.o-m(g).o)<40&&(f=1)}return{lr:h,badge_offset:f}}_createBadge(e,t){const s=this._getData(),i=document.createElement("span");if(i.className="mo-badge js-mo-badge",s.showCounter||(i.style.opacity="0"),s.showCounterStyle==="image"){const n=document.createElement("img");n.className="mo-badge-icon",n.alt="",n.src=e.dataset.moIcon||C,i.appendChild(n)}else i.textContent=t;e.prepend(i)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const s=document.createElement("div");if(s.className="mo-card",e.banner){const n=document.createElement("div");n.className="mo-card-image";const r=document.createElement("img");if(r.className="mo-banner",r.src=e.banner,r.alt="",n.appendChild(r),e.avatar){const a=document.createElement("img");a.className="mo-avatar",a.src=e.avatar,a.alt="",n.appendChild(a)}s.appendChild(n)}const i=document.createElement("div");if(i.className="mo-card-body",e.title){const n=document.createElement("h3");n.textContent=e.title,i.appendChild(n)}if(e.meta){const n=document.createElement("p");n.className="mo-meta",n.textContent=e.meta,i.appendChild(n)}if(e.text){const n=document.createElement("p");n.textContent=e.text,i.appendChild(n)}return s.appendChild(i),t.appendChild(s),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}};p(l,"instances",new Set);let d=l;exports.MoTimeline=d;exports.default=d;
|
package/dist/moTimeline.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* moTimeline v2.3.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-badge{align-items:center;background:var(--mo-badge-bg);border-radius:50%;color:var(--mo-badge-color);display:flex;font-size:var(--mo-badge-font-size);font-weight:700;height:var(--mo-badge-size);justify-content:center;min-width:var(--mo-badge-size);overflow:hidden;position:absolute;top:18px;z-index:2}.mo-badge .mo-badge-icon{border-radius:50%;height:100%;object-fit:cover;width:100%}.mo-timeline.mo-twocol>.mo-item:not(.mo-inverted) .mo-badge{left:auto;right:calc(var(--mo-badge-size) / -2)}.mo-timeline.mo-twocol>.mo-item.mo-inverted .mo-badge{left:calc(var(--mo-badge-size) / -2);right:auto}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-badge{top:calc(18px + var(--mo-badge-size) + 10px)}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-arrow{top:calc(26px + var(--mo-badge-size) + 10px)}.mo-timeline:not(.mo-twocol)>.mo-item .mo-badge{
|
|
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-badge{align-items:center;background:var(--mo-badge-bg);border-radius:50%;color:var(--mo-badge-color);display:flex;font-size:var(--mo-badge-font-size);font-weight:700;height:var(--mo-badge-size);justify-content:center;min-width:var(--mo-badge-size);overflow:hidden;position:absolute;top:18px;z-index:2}.mo-badge .mo-badge-icon{border-radius:50%;height:100%;object-fit:cover;width:100%}.mo-timeline.mo-twocol>.mo-item:not(.mo-inverted) .mo-badge{left:auto;right:calc(var(--mo-badge-size) / -2)}.mo-timeline.mo-twocol>.mo-item.mo-inverted .mo-badge{left:calc(var(--mo-badge-size) / -2);right:auto}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-badge{top:calc(18px + var(--mo-badge-size) + 10px)}.mo-timeline.mo-twocol>.mo-item.mo-offset .mo-arrow{top:calc(26px + var(--mo-badge-size) + 10px)}.mo-timeline:not(.mo-twocol)>.mo-item .mo-badge{display:none}.mo-arrow{border:8px solid transparent;display:block;height:0;position:absolute;top:26px;width:0;z-index:1}.mo-timeline.mo-twocol>.mo-item:not(.mo-inverted) .mo-arrow{border-left:8px solid var(--mo-arrow-color);border-right:none;left:auto;right:0}.mo-timeline.mo-twocol>.mo-item.mo-inverted .mo-arrow{border-right:8px solid var(--mo-arrow-color);border-left:none;left:0;right:auto}.mo-timeline:not(.mo-twocol)>.mo-item .mo-arrow{display:none}.mo-theme>.mo-item .mo-card{background:#fff;border-radius:8px;box-shadow:0 2px 14px #0000001a;margin:.5rem 1.25rem .5rem .5rem;overflow:hidden;position:relative}.mo-theme>.mo-item.mo-inverted .mo-card{margin:.5rem .5rem .5rem 1.25rem}.mo-theme>.mo-item .mo-banner{display:block;height:160px;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:-22px;box-shadow:0 2px 8px #0000002e;height:50px;object-fit:cover;position:absolute;right:14px;width:50px;z-index:1}.mo-theme>.mo-item.mo-inverted .mo-avatar{left:14px;right:auto}.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:#e5e7eb;right:10px}.mo-theme.mo-twocol>.mo-item.mo-inverted .mo-arrow{border-right-color:#e5e7eb;left:10px}.mo-theme .mo-badge{background:#fff;border:2px solid var(--mo-line-color);box-shadow:0 2px 6px #0000001a;color:#374151}
|
package/dist/moTimeline.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var g = (
|
|
1
|
+
var _ = Object.defineProperty;
|
|
2
|
+
var C = (o, e, t) => e in o ? _(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
|
|
3
|
+
var g = (o, e, t) => C(o, typeof e != "symbol" ? e + "" : e, t);
|
|
4
4
|
/*!
|
|
5
|
-
* moTimeline v2.
|
|
5
|
+
* moTimeline v2.4.0
|
|
6
6
|
* Responsive two-column timeline layout library
|
|
7
7
|
* https://github.com/MattOpen/moTimeline
|
|
8
8
|
* MIT License
|
|
9
9
|
*/
|
|
10
|
-
const
|
|
10
|
+
const c = /* @__PURE__ */ new WeakMap(), p = {
|
|
11
11
|
columnCount: { xs: 1, sm: 2, md: 2, lg: 2 },
|
|
12
12
|
badgeShow: !1,
|
|
13
13
|
arrowShow: !1,
|
|
@@ -15,113 +15,154 @@ const a = /* @__PURE__ */ new WeakMap(), p = {
|
|
|
15
15
|
showCounter: !0,
|
|
16
16
|
showCounterStyle: "counter"
|
|
17
17
|
// 'counter' | 'image'
|
|
18
|
-
},
|
|
18
|
+
}, b = "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>";
|
|
19
19
|
function w() {
|
|
20
|
-
const
|
|
21
|
-
return
|
|
20
|
+
const o = window.innerWidth;
|
|
21
|
+
return o < 600 ? "xs" : o < 992 ? "sm" : o < 1200 ? "md" : "lg";
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
let
|
|
23
|
+
function I(o, e = 100) {
|
|
24
|
+
let t;
|
|
25
25
|
return (...s) => {
|
|
26
|
-
clearTimeout(
|
|
26
|
+
clearTimeout(t), t = setTimeout(() => o(...s), e);
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
function m(
|
|
30
|
-
return
|
|
31
|
-
o:
|
|
32
|
-
h:
|
|
33
|
-
gppu:
|
|
29
|
+
function m(o) {
|
|
30
|
+
return o ? {
|
|
31
|
+
o: o.offsetTop,
|
|
32
|
+
h: o.offsetHeight,
|
|
33
|
+
gppu: o.offsetTop + o.offsetHeight
|
|
34
34
|
} : { o: 0, h: 0, gppu: 0 };
|
|
35
35
|
}
|
|
36
|
-
function v(
|
|
37
|
-
const
|
|
38
|
-
let s =
|
|
36
|
+
function v(o, e) {
|
|
37
|
+
const t = [];
|
|
38
|
+
let s = o.previousElementSibling;
|
|
39
39
|
for (; s; )
|
|
40
|
-
(!
|
|
41
|
-
return
|
|
40
|
+
(!e || s.matches(e)) && t.push(s), s = s.previousElementSibling;
|
|
41
|
+
return t;
|
|
42
42
|
}
|
|
43
|
-
const
|
|
44
|
-
constructor(
|
|
45
|
-
if (typeof
|
|
46
|
-
this.element =
|
|
43
|
+
const l = class l {
|
|
44
|
+
constructor(e, t = {}) {
|
|
45
|
+
if (typeof e == "string" && (e = document.querySelector(e)), !e) throw new Error("moTimeline: element not found");
|
|
46
|
+
this.element = e, this.settings = Object.assign({}, p, t), this.settings.columnCount = Object.assign({}, p.columnCount, t.columnCount), this._resizeHandler = I(() => this.refresh(), 100), this._initialized = !1, this.init();
|
|
47
47
|
}
|
|
48
48
|
init() {
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
49
|
+
const e = this.element;
|
|
50
|
+
if (c.has(e)) {
|
|
51
51
|
this.refresh();
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
54
|
+
const t = Object.assign({}, this.settings, { lastItemIdx: 0 });
|
|
55
|
+
c.set(e, t), l.instances.add(this), e.classList.add("mo-timeline"), t.theme && e.classList.add("mo-theme"), Array.from(e.children).length !== 0 && (this._initItems(), this._initialized = !0, window.addEventListener("resize", this._resizeHandler));
|
|
56
56
|
}
|
|
57
57
|
refresh() {
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
s && (s.col = s.columnCount[w()],
|
|
61
|
-
|
|
58
|
+
l.instances.forEach((e) => {
|
|
59
|
+
const t = e.element, s = c.get(t);
|
|
60
|
+
s && (s.col = s.columnCount[w()], e._setDivider(), Array.from(t.children).forEach((i) => {
|
|
61
|
+
e._setPostPosition(i);
|
|
62
62
|
}));
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
initNewItems() {
|
|
66
66
|
this._initItems();
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Create <li> elements from an array of item objects (or a JSON string) and
|
|
70
|
+
* append them to the timeline, then initialize them in one batch.
|
|
71
|
+
*
|
|
72
|
+
* Item shape:
|
|
73
|
+
* { title, meta, text, banner, avatar, icon }
|
|
74
|
+
* — banner / avatar / icon are all optional
|
|
75
|
+
* — icon sets data-mo-icon on the <li> for showCounterStyle:'image'
|
|
76
|
+
*/
|
|
77
|
+
addItems(e) {
|
|
78
|
+
typeof e == "string" && (e = JSON.parse(e)), e.forEach((t) => this.element.appendChild(this._createItemElement(t))), this._initItems();
|
|
79
|
+
}
|
|
68
80
|
destroy() {
|
|
69
|
-
window.removeEventListener("resize", this._resizeHandler),
|
|
70
|
-
|
|
81
|
+
window.removeEventListener("resize", this._resizeHandler), c.delete(this.element), l.instances.delete(this), this.element.classList.remove("mo-timeline", "mo-theme", "mo-twocol"), Array.from(this.element.children).forEach((e) => {
|
|
82
|
+
e.classList.remove("mo-item", "js-mo-item", "mo-inverted", "js-mo-inverted", "mo-offset"), e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach((t) => t.remove());
|
|
71
83
|
});
|
|
72
84
|
}
|
|
73
85
|
// ─── Private ────────────────────────────────────────────────────────────────
|
|
74
86
|
_getData() {
|
|
75
|
-
return
|
|
87
|
+
return c.get(this.element);
|
|
76
88
|
}
|
|
77
89
|
_setDivider() {
|
|
78
|
-
const
|
|
79
|
-
|
|
90
|
+
const e = this._getData();
|
|
91
|
+
e && (e.col = e.columnCount[w()], this.element.classList.toggle("mo-twocol", e.col > 1));
|
|
80
92
|
}
|
|
81
93
|
_initItems() {
|
|
82
|
-
const
|
|
83
|
-
if (!
|
|
84
|
-
const s =
|
|
85
|
-
n.length !== 0 && (n.forEach((r,
|
|
86
|
-
r.id || (r.id = "moT" + crypto.randomUUID() + "_" + (
|
|
87
|
-
}), this._setDivider(), n.forEach((r,
|
|
88
|
-
|
|
89
|
-
}),
|
|
94
|
+
const e = this.element, t = this._getData();
|
|
95
|
+
if (!t) return;
|
|
96
|
+
const s = t.lastItemIdx, i = Array.from(e.children), n = i.slice(s);
|
|
97
|
+
n.length !== 0 && (n.forEach((r, a) => {
|
|
98
|
+
r.id || (r.id = "moT" + crypto.randomUUID() + "_" + (a + s)), r.classList.add("mo-item", "js-mo-item");
|
|
99
|
+
}), this._setDivider(), n.forEach((r, a) => {
|
|
100
|
+
t.badgeShow && this._createBadge(r, a + s + 1), t.arrowShow && this._createArrow(r);
|
|
101
|
+
}), t.lastItemIdx = i.length, c.set(e, t), this.refresh());
|
|
90
102
|
}
|
|
91
|
-
_setPostPosition(
|
|
92
|
-
const
|
|
93
|
-
|
|
103
|
+
_setPostPosition(e) {
|
|
104
|
+
const t = this._getLeftOrRight(e);
|
|
105
|
+
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));
|
|
94
106
|
}
|
|
95
|
-
_getLeftOrRight(
|
|
96
|
-
if (!t) return null;
|
|
97
|
-
const e = this._getData();
|
|
107
|
+
_getLeftOrRight(e) {
|
|
98
108
|
if (!e) return null;
|
|
99
|
-
const
|
|
100
|
-
|
|
109
|
+
const t = this._getData();
|
|
110
|
+
if (!t) return null;
|
|
111
|
+
const s = t.col, i = v(e, ".js-mo-inverted")[0] || null, n = v(e, ".js-mo-item:not(.js-mo-inverted)")[0] || null, r = m(n), a = m(i), h = m(e);
|
|
112
|
+
let d = 0, f = 0;
|
|
101
113
|
if (s > 1) {
|
|
102
|
-
r.gppu >
|
|
103
|
-
const u =
|
|
104
|
-
u && Math.abs(
|
|
114
|
+
r.gppu > h.o && (d = 1), a.gppu > r.gppu && (d = 0);
|
|
115
|
+
const u = e.previousElementSibling;
|
|
116
|
+
u && Math.abs(h.o - m(u).o) < 40 && (f = 1);
|
|
105
117
|
}
|
|
106
|
-
return { lr:
|
|
118
|
+
return { lr: d, badge_offset: f };
|
|
107
119
|
}
|
|
108
|
-
_createBadge(
|
|
109
|
-
const s = this._getData(),
|
|
110
|
-
if (
|
|
120
|
+
_createBadge(e, t) {
|
|
121
|
+
const s = this._getData(), i = document.createElement("span");
|
|
122
|
+
if (i.className = "mo-badge js-mo-badge", s.showCounter || (i.style.opacity = "0"), s.showCounterStyle === "image") {
|
|
111
123
|
const n = document.createElement("img");
|
|
112
|
-
n.className = "mo-badge-icon", n.alt = "", n.src =
|
|
124
|
+
n.className = "mo-badge-icon", n.alt = "", n.src = e.dataset.moIcon || b, i.appendChild(n);
|
|
113
125
|
} else
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
i.textContent = t;
|
|
127
|
+
e.prepend(i);
|
|
128
|
+
}
|
|
129
|
+
_createItemElement(e) {
|
|
130
|
+
const t = document.createElement("li");
|
|
131
|
+
e.icon && (t.dataset.moIcon = e.icon);
|
|
132
|
+
const s = document.createElement("div");
|
|
133
|
+
if (s.className = "mo-card", e.banner) {
|
|
134
|
+
const n = document.createElement("div");
|
|
135
|
+
n.className = "mo-card-image";
|
|
136
|
+
const r = document.createElement("img");
|
|
137
|
+
if (r.className = "mo-banner", r.src = e.banner, r.alt = "", n.appendChild(r), e.avatar) {
|
|
138
|
+
const a = document.createElement("img");
|
|
139
|
+
a.className = "mo-avatar", a.src = e.avatar, a.alt = "", n.appendChild(a);
|
|
140
|
+
}
|
|
141
|
+
s.appendChild(n);
|
|
142
|
+
}
|
|
143
|
+
const i = document.createElement("div");
|
|
144
|
+
if (i.className = "mo-card-body", e.title) {
|
|
145
|
+
const n = document.createElement("h3");
|
|
146
|
+
n.textContent = e.title, i.appendChild(n);
|
|
147
|
+
}
|
|
148
|
+
if (e.meta) {
|
|
149
|
+
const n = document.createElement("p");
|
|
150
|
+
n.className = "mo-meta", n.textContent = e.meta, i.appendChild(n);
|
|
151
|
+
}
|
|
152
|
+
if (e.text) {
|
|
153
|
+
const n = document.createElement("p");
|
|
154
|
+
n.textContent = e.text, i.appendChild(n);
|
|
155
|
+
}
|
|
156
|
+
return s.appendChild(i), t.appendChild(s), t;
|
|
116
157
|
}
|
|
117
|
-
_createArrow(
|
|
118
|
-
const
|
|
119
|
-
|
|
158
|
+
_createArrow(e) {
|
|
159
|
+
const t = document.createElement("span");
|
|
160
|
+
t.className = "mo-arrow js-mo-arrow", e.prepend(t);
|
|
120
161
|
}
|
|
121
162
|
};
|
|
122
|
-
g(
|
|
123
|
-
let
|
|
163
|
+
g(l, "instances", /* @__PURE__ */ new Set());
|
|
164
|
+
let E = l;
|
|
124
165
|
export {
|
|
125
|
-
|
|
126
|
-
|
|
166
|
+
E as MoTimeline,
|
|
167
|
+
E as default
|
|
127
168
|
};
|
package/dist/moTimeline.umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(
|
|
2
|
-
* moTimeline v2.
|
|
1
|
+
(function(a,o){typeof exports=="object"&&typeof module<"u"?o(exports):typeof define=="function"&&define.amd?define(["exports"],o):(a=typeof globalThis<"u"?globalThis:a||self,o(a.MoTimeline={}))})(this,function(a){"use strict";var I=Object.defineProperty;var y=(a,o,m)=>o in a?I(a,o,{enumerable:!0,configurable:!0,writable:!0,value:m}):a[o]=m;var _=(a,o,m)=>y(a,typeof o!="symbol"?o+"":o,m);/*!
|
|
2
|
+
* moTimeline v2.4.0
|
|
3
3
|
* Responsive two-column timeline layout library
|
|
4
4
|
* https://github.com/MattOpen/moTimeline
|
|
5
5
|
* MIT License
|
|
6
|
-
*/const
|
|
6
|
+
*/const o=new WeakMap,m={columnCount:{xs:1,sm:2,md:2,lg:2},badgeShow:!1,arrowShow:!1,theme:!1,showCounter:!0,showCounterStyle:"counter"},b="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 g(){const c=window.innerWidth;return c<600?"xs":c<992?"sm":c<1200?"md":"lg"}function C(c,e=100){let t;return(...n)=>{clearTimeout(t),t=setTimeout(()=>c(...n),e)}}function h(c){return c?{o:c.offsetTop,h:c.offsetHeight,gppu:c.offsetTop+c.offsetHeight}:{o:0,h:0,gppu:0}}function p(c,e){const t=[];let n=c.previousElementSibling;for(;n;)(!e||n.matches(e))&&t.push(n),n=n.previousElementSibling;return t}const d=class d{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({},m,t),this.settings.columnCount=Object.assign({},m.columnCount,t.columnCount),this._resizeHandler=C(()=>this.refresh(),100),this._initialized=!1,this.init()}init(){const e=this.element;if(o.has(e)){this.refresh();return}const t=Object.assign({},this.settings,{lastItemIdx:0});o.set(e,t),d.instances.add(this),e.classList.add("mo-timeline"),t.theme&&e.classList.add("mo-theme"),Array.from(e.children).length!==0&&(this._initItems(),this._initialized=!0,window.addEventListener("resize",this._resizeHandler))}refresh(){d.instances.forEach(e=>{const t=e.element,n=o.get(t);n&&(n.col=n.columnCount[g()],e._setDivider(),Array.from(t.children).forEach(i=>{e._setPostPosition(i)}))})}initNewItems(){this._initItems()}addItems(e){typeof e=="string"&&(e=JSON.parse(e)),e.forEach(t=>this.element.appendChild(this._createItemElement(t))),this._initItems()}destroy(){window.removeEventListener("resize",this._resizeHandler),o.delete(this.element),d.instances.delete(this),this.element.classList.remove("mo-timeline","mo-theme","mo-twocol"),Array.from(this.element.children).forEach(e=>{e.classList.remove("mo-item","js-mo-item","mo-inverted","js-mo-inverted","mo-offset"),e.querySelectorAll(".js-mo-badge, .js-mo-arrow").forEach(t=>t.remove())})}_getData(){return o.get(this.element)}_setDivider(){const e=this._getData();e&&(e.col=e.columnCount[g()],this.element.classList.toggle("mo-twocol",e.col>1))}_initItems(){const e=this.element,t=this._getData();if(!t)return;const n=t.lastItemIdx,i=Array.from(e.children),s=i.slice(n);s.length!==0&&(s.forEach((r,l)=>{r.id||(r.id="moT"+crypto.randomUUID()+"_"+(l+n)),r.classList.add("mo-item","js-mo-item")}),this._setDivider(),s.forEach((r,l)=>{t.badgeShow&&this._createBadge(r,l+n+1),t.arrowShow&&this._createArrow(r)}),t.lastItemIdx=i.length,o.set(e,t),this.refresh())}_setPostPosition(e){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 n=t.col,i=p(e,".js-mo-inverted")[0]||null,s=p(e,".js-mo-item:not(.js-mo-inverted)")[0]||null,r=h(s),l=h(i),w=h(e);let u=0,v=0;if(n>1){r.gppu>w.o&&(u=1),l.gppu>r.gppu&&(u=0);const E=e.previousElementSibling;E&&Math.abs(w.o-h(E).o)<40&&(v=1)}return{lr:u,badge_offset:v}}_createBadge(e,t){const n=this._getData(),i=document.createElement("span");if(i.className="mo-badge js-mo-badge",n.showCounter||(i.style.opacity="0"),n.showCounterStyle==="image"){const s=document.createElement("img");s.className="mo-badge-icon",s.alt="",s.src=e.dataset.moIcon||b,i.appendChild(s)}else i.textContent=t;e.prepend(i)}_createItemElement(e){const t=document.createElement("li");e.icon&&(t.dataset.moIcon=e.icon);const n=document.createElement("div");if(n.className="mo-card",e.banner){const s=document.createElement("div");s.className="mo-card-image";const r=document.createElement("img");if(r.className="mo-banner",r.src=e.banner,r.alt="",s.appendChild(r),e.avatar){const l=document.createElement("img");l.className="mo-avatar",l.src=e.avatar,l.alt="",s.appendChild(l)}n.appendChild(s)}const i=document.createElement("div");if(i.className="mo-card-body",e.title){const s=document.createElement("h3");s.textContent=e.title,i.appendChild(s)}if(e.meta){const s=document.createElement("p");s.className="mo-meta",s.textContent=e.meta,i.appendChild(s)}if(e.text){const s=document.createElement("p");s.textContent=e.text,i.appendChild(s)}return n.appendChild(i),t.appendChild(n),t}_createArrow(e){const t=document.createElement("span");t.className="mo-arrow js-mo-arrow",e.prepend(t)}};_(d,"instances",new Set);let f=d;a.MoTimeline=f,a.default=f,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/package.json
CHANGED
package/src/moTimeline.css
CHANGED
|
@@ -113,11 +113,9 @@
|
|
|
113
113
|
top: calc(26px + var(--mo-badge-size) + 10px);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
/* Single column: badge
|
|
116
|
+
/* Single column: hide badge (center-line elements have no meaning without a center line) */
|
|
117
117
|
.mo-timeline:not(.mo-twocol) > .mo-item .mo-badge {
|
|
118
|
-
|
|
119
|
-
left: auto;
|
|
120
|
-
top: 12px;
|
|
118
|
+
display: none;
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
/* ── Arrow — triangle pointing FROM card TOWARD center line ─── */
|
package/src/moTimeline.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* moTimeline v2.
|
|
2
|
+
* moTimeline v2.4.0
|
|
3
3
|
* Responsive two-column timeline layout library
|
|
4
4
|
* https://github.com/MattOpen/moTimeline
|
|
5
5
|
* MIT License
|
|
@@ -124,6 +124,21 @@ export class MoTimeline {
|
|
|
124
124
|
this._initItems();
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Create <li> elements from an array of item objects (or a JSON string) and
|
|
129
|
+
* append them to the timeline, then initialize them in one batch.
|
|
130
|
+
*
|
|
131
|
+
* Item shape:
|
|
132
|
+
* { title, meta, text, banner, avatar, icon }
|
|
133
|
+
* — banner / avatar / icon are all optional
|
|
134
|
+
* — icon sets data-mo-icon on the <li> for showCounterStyle:'image'
|
|
135
|
+
*/
|
|
136
|
+
addItems(items) {
|
|
137
|
+
if (typeof items === 'string') items = JSON.parse(items);
|
|
138
|
+
items.forEach((item) => this.element.appendChild(this._createItemElement(item)));
|
|
139
|
+
this._initItems();
|
|
140
|
+
}
|
|
141
|
+
|
|
127
142
|
destroy() {
|
|
128
143
|
window.removeEventListener('resize', this._resizeHandler);
|
|
129
144
|
instanceData.delete(this.element);
|
|
@@ -248,6 +263,54 @@ export class MoTimeline {
|
|
|
248
263
|
el.prepend(span);
|
|
249
264
|
}
|
|
250
265
|
|
|
266
|
+
_createItemElement(item) {
|
|
267
|
+
const li = document.createElement('li');
|
|
268
|
+
if (item.icon) li.dataset.moIcon = item.icon;
|
|
269
|
+
|
|
270
|
+
const card = document.createElement('div');
|
|
271
|
+
card.className = 'mo-card';
|
|
272
|
+
|
|
273
|
+
if (item.banner) {
|
|
274
|
+
const wrap = document.createElement('div');
|
|
275
|
+
wrap.className = 'mo-card-image';
|
|
276
|
+
const banner = document.createElement('img');
|
|
277
|
+
banner.className = 'mo-banner';
|
|
278
|
+
banner.src = item.banner;
|
|
279
|
+
banner.alt = '';
|
|
280
|
+
wrap.appendChild(banner);
|
|
281
|
+
if (item.avatar) {
|
|
282
|
+
const avatar = document.createElement('img');
|
|
283
|
+
avatar.className = 'mo-avatar';
|
|
284
|
+
avatar.src = item.avatar;
|
|
285
|
+
avatar.alt = '';
|
|
286
|
+
wrap.appendChild(avatar);
|
|
287
|
+
}
|
|
288
|
+
card.appendChild(wrap);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const body = document.createElement('div');
|
|
292
|
+
body.className = 'mo-card-body';
|
|
293
|
+
if (item.title) {
|
|
294
|
+
const h = document.createElement('h3');
|
|
295
|
+
h.textContent = item.title;
|
|
296
|
+
body.appendChild(h);
|
|
297
|
+
}
|
|
298
|
+
if (item.meta) {
|
|
299
|
+
const m = document.createElement('p');
|
|
300
|
+
m.className = 'mo-meta';
|
|
301
|
+
m.textContent = item.meta;
|
|
302
|
+
body.appendChild(m);
|
|
303
|
+
}
|
|
304
|
+
if (item.text) {
|
|
305
|
+
const p = document.createElement('p');
|
|
306
|
+
p.textContent = item.text;
|
|
307
|
+
body.appendChild(p);
|
|
308
|
+
}
|
|
309
|
+
card.appendChild(body);
|
|
310
|
+
li.appendChild(card);
|
|
311
|
+
return li;
|
|
312
|
+
}
|
|
313
|
+
|
|
251
314
|
_createArrow(el) {
|
|
252
315
|
const span = document.createElement('span');
|
|
253
316
|
span.className = 'mo-arrow js-mo-arrow';
|