@frontfactory/readmore 1.1.0 → 1.1.1
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/dist/readmore.js +25 -21
- package/package.json +2 -2
- package/dist/__tests__/readmore.test.d.ts +0 -1
- package/dist/readmore.js.map +0 -1
package/dist/readmore.js
CHANGED
|
@@ -12,14 +12,20 @@ var e = "readmore-clamp", t = "readmore-clamp--height", n = {
|
|
|
12
12
|
options;
|
|
13
13
|
#e = null;
|
|
14
14
|
#t = !1;
|
|
15
|
-
#n =
|
|
16
|
-
#r =
|
|
15
|
+
#n = null;
|
|
16
|
+
#r = null;
|
|
17
|
+
#i = () => {
|
|
18
|
+
this.#n !== null && clearTimeout(this.#n), this.#n = setTimeout(() => {
|
|
19
|
+
this.#n = null, this.#c();
|
|
20
|
+
}, 100);
|
|
21
|
+
};
|
|
22
|
+
#a = () => this.toggle();
|
|
17
23
|
constructor(e, t = {}) {
|
|
18
24
|
if (!(e instanceof HTMLElement)) throw TypeError("ReadMore: an HTMLElement is required.");
|
|
19
25
|
this.el = e, this.options = {
|
|
20
26
|
...n,
|
|
21
27
|
...t
|
|
22
|
-
}, this.#
|
|
28
|
+
}, this.#o();
|
|
23
29
|
}
|
|
24
30
|
static init(e, t) {
|
|
25
31
|
let n = typeof e == "string" ? document.querySelectorAll(e) : e;
|
|
@@ -31,43 +37,41 @@ var e = "readmore-clamp", t = "readmore-clamp--height", n = {
|
|
|
31
37
|
toggle() {
|
|
32
38
|
this.#t = !this.#t, this.el.classList.toggle(e, !this.#t), this.options.height != null && this.el.classList.toggle(t, !this.#t), this.el.classList.toggle(this.options.expandedClass, this.#t), this.#e && (this.#e.textContent = this.#t ? this.options.lessText : this.options.moreText);
|
|
33
39
|
let n = this.#t ? this.options.openingClass : this.options.closingClass, r = this.#t ? this.options.closingClass : this.options.openingClass;
|
|
34
|
-
this.el.classList.remove(r), this.#
|
|
40
|
+
this.el.classList.remove(r), this.#l(n), this.#t || this.#c();
|
|
35
41
|
}
|
|
36
42
|
destroy() {
|
|
37
|
-
window.removeEventListener("resize", this.#n), this.#
|
|
43
|
+
window.removeEventListener("resize", this.#i), this.#n !== null && (clearTimeout(this.#n), this.#n = null), this.#r &&= (this.el.removeEventListener("transitionend", this.#r), null), this.#d(), this.el.classList.remove(e, t, this.options.expandedClass, this.options.openingClass, this.options.closingClass), this.el.style.removeProperty("--readmore-lines"), this.el.style.removeProperty("--readmore-height");
|
|
38
44
|
}
|
|
39
|
-
#
|
|
40
|
-
this.options.height == null ? (this.el.style.setProperty("--readmore-lines", String(this.options.lines)), this.el.classList.add(e)) : (this.el.style.setProperty("--readmore-height", `${this.options.height}px`), this.el.classList.add(e, t)), window.addEventListener("resize", this.#
|
|
45
|
+
#o() {
|
|
46
|
+
this.options.height == null ? (this.el.style.setProperty("--readmore-lines", String(this.options.lines)), this.el.classList.add(e)) : (this.el.style.setProperty("--readmore-height", `${this.options.height}px`), this.el.classList.add(e, t)), window.addEventListener("resize", this.#i), this.#c();
|
|
41
47
|
}
|
|
42
|
-
#
|
|
48
|
+
#s() {
|
|
43
49
|
return this.el.scrollHeight - this.el.clientHeight > 1;
|
|
44
50
|
}
|
|
45
|
-
#
|
|
51
|
+
#c() {
|
|
46
52
|
if (this.#t) return;
|
|
47
|
-
let e = this.#
|
|
48
|
-
e && !this.#e ? this.#
|
|
53
|
+
let e = this.#s();
|
|
54
|
+
e && !this.#e ? this.#u() : !e && this.#e && this.#d();
|
|
49
55
|
}
|
|
50
|
-
#
|
|
51
|
-
this.el.classList.add(e);
|
|
56
|
+
#l(e) {
|
|
57
|
+
this.#r &&= (this.el.removeEventListener("transitionend", this.#r), null), this.el.classList.add(e);
|
|
52
58
|
let t = () => this.el.classList.remove(e);
|
|
53
59
|
if (!getComputedStyle(this.el).transitionDuration.split(",").some((e) => parseFloat(e) > 0)) {
|
|
54
60
|
setTimeout(t, 0);
|
|
55
61
|
return;
|
|
56
62
|
}
|
|
57
63
|
let n = (e) => {
|
|
58
|
-
e.target === this.el && (this.el.removeEventListener("transitionend", n), t());
|
|
64
|
+
e.target === this.el && (this.el.removeEventListener("transitionend", n), this.#r = null, t());
|
|
59
65
|
};
|
|
60
|
-
this.el.addEventListener("transitionend", n);
|
|
66
|
+
this.#r = n, this.el.addEventListener("transitionend", n);
|
|
61
67
|
}
|
|
62
|
-
#
|
|
68
|
+
#u() {
|
|
63
69
|
let e = document.createElement("button");
|
|
64
|
-
e.type = "button", e.className = this.options.buttonClass, e.textContent = this.options.moreText, e.addEventListener("click", this.#
|
|
70
|
+
e.type = "button", e.className = this.options.buttonClass, e.textContent = this.options.moreText, e.addEventListener("click", this.#a), this.el.insertAdjacentElement("afterend", e), this.#e = e;
|
|
65
71
|
}
|
|
66
|
-
#
|
|
67
|
-
this.#e &&= (this.#e.removeEventListener("click", this.#
|
|
72
|
+
#d() {
|
|
73
|
+
this.#e &&= (this.#e.removeEventListener("click", this.#a), this.#e.remove(), null);
|
|
68
74
|
}
|
|
69
75
|
};
|
|
70
76
|
//#endregion
|
|
71
77
|
export { r as ReadMore };
|
|
72
|
-
|
|
73
|
-
//# sourceMappingURL=readmore.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontfactory/readmore",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Lightweight plugin to clamp text to N lines with ellipsis and a read more action.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"node": ">=20.19"
|
|
19
19
|
},
|
|
20
20
|
"main": "./dist/readmore.js",
|
|
21
|
-
"module": "./dist/readmore.js",
|
|
22
21
|
"types": "./dist/readmore.d.ts",
|
|
23
22
|
"exports": {
|
|
24
23
|
".": {
|
|
@@ -38,6 +37,7 @@
|
|
|
38
37
|
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
39
38
|
"husky": "^9.1.7",
|
|
40
39
|
"jsdom": "^29.1.1",
|
|
40
|
+
"lightningcss": "^1.32.0",
|
|
41
41
|
"semantic-release": "^25.0.3",
|
|
42
42
|
"typescript": "^5.4.0",
|
|
43
43
|
"vite": "^8.0.11",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/readmore.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"readmore.js","names":["#refresh","#init","#expanded","#button","#applyTransientClass","#onResize","#unmountButton","#isOverflowing","#mountButton","#onClick"],"sources":["../src/readmore.ts"],"sourcesContent":["export interface ReadMoreOptions {\n lines?: number;\n height?: number;\n moreText?: string;\n lessText?: string;\n buttonClass?: string;\n expandedClass?: string;\n openingClass?: string;\n closingClass?: string;\n}\n\ntype ResolvedOptions = Required<Omit<ReadMoreOptions, 'height'>> & { height?: number };\n\nconst CLAMP_CLASS = 'readmore-clamp';\nconst CLAMP_HEIGHT_CLASS = 'readmore-clamp--height';\n\nconst DEFAULTS: ResolvedOptions = {\n lines: 3,\n moreText: 'Read more',\n lessText: 'Read less',\n buttonClass: 'readmore-btn',\n expandedClass: 'is-expanded',\n openingClass: 'is-opening',\n closingClass: 'is-closing'\n};\n\nexport class ReadMore {\n readonly el: HTMLElement;\n readonly options: ResolvedOptions;\n\n #button: HTMLButtonElement | null = null;\n #expanded = false;\n #onResize = (): void => this.#refresh();\n #onClick = (): void => this.toggle();\n\n constructor(element: HTMLElement, options: ReadMoreOptions = {}) {\n if (!(element instanceof HTMLElement)) {\n throw new TypeError('ReadMore: an HTMLElement is required.');\n }\n this.el = element;\n this.options = { ...DEFAULTS, ...options };\n this.#init();\n }\n\n static init(\n target: string | NodeListOf<HTMLElement> | HTMLElement[],\n options?: ReadMoreOptions\n ): ReadMore[] {\n const nodes =\n typeof target === 'string'\n ? document.querySelectorAll<HTMLElement>(target)\n : target;\n return Array.from(nodes).map((n) => new ReadMore(n, options));\n }\n\n get expanded(): boolean {\n return this.#expanded;\n }\n\n toggle(): void {\n this.#expanded = !this.#expanded;\n this.el.classList.toggle(CLAMP_CLASS, !this.#expanded);\n if (this.options.height != null) {\n this.el.classList.toggle(CLAMP_HEIGHT_CLASS, !this.#expanded);\n }\n this.el.classList.toggle(this.options.expandedClass, this.#expanded);\n if (this.#button) {\n this.#button.textContent = this.#expanded\n ? this.options.lessText\n : this.options.moreText;\n }\n const stateClass = this.#expanded ? this.options.openingClass : this.options.closingClass;\n const otherClass = this.#expanded ? this.options.closingClass : this.options.openingClass;\n this.el.classList.remove(otherClass);\n this.#applyTransientClass(stateClass);\n if (!this.#expanded) this.#refresh();\n }\n\n destroy(): void {\n window.removeEventListener('resize', this.#onResize);\n this.#unmountButton();\n this.el.classList.remove(\n CLAMP_CLASS,\n CLAMP_HEIGHT_CLASS,\n this.options.expandedClass,\n this.options.openingClass,\n this.options.closingClass\n );\n this.el.style.removeProperty('--readmore-lines');\n this.el.style.removeProperty('--readmore-height');\n }\n\n #init(): void {\n if (this.options.height != null) {\n this.el.style.setProperty('--readmore-height', `${ this.options.height }px`);\n this.el.classList.add(CLAMP_CLASS, CLAMP_HEIGHT_CLASS);\n } else {\n this.el.style.setProperty('--readmore-lines', String(this.options.lines));\n this.el.classList.add(CLAMP_CLASS);\n }\n window.addEventListener('resize', this.#onResize);\n this.#refresh();\n }\n\n #isOverflowing(): boolean {\n return this.el.scrollHeight - this.el.clientHeight > 1;\n }\n\n #refresh(): void {\n if (this.#expanded) return;\n const overflowing = this.#isOverflowing();\n if (overflowing && !this.#button) {\n this.#mountButton();\n } else if (!overflowing && this.#button) {\n this.#unmountButton();\n }\n }\n\n #applyTransientClass(stateClass: string): void {\n this.el.classList.add(stateClass);\n const remove = (): void => this.el.classList.remove(stateClass);\n const duration = getComputedStyle(this.el).transitionDuration;\n const hasTransition = duration\n .split(',')\n .some((d) => parseFloat(d) > 0);\n if (!hasTransition) {\n setTimeout(remove, 0);\n return;\n }\n const onEnd = (e: TransitionEvent): void => {\n if (e.target !== this.el) return;\n this.el.removeEventListener('transitionend', onEnd);\n remove();\n };\n this.el.addEventListener('transitionend', onEnd);\n }\n\n #mountButton(): void {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = this.options.buttonClass;\n btn.textContent = this.options.moreText;\n btn.addEventListener('click', this.#onClick);\n this.el.insertAdjacentElement('afterend', btn);\n this.#button = btn;\n }\n\n #unmountButton(): void {\n if (!this.#button) return;\n this.#button.removeEventListener('click', this.#onClick);\n this.#button.remove();\n this.#button = null;\n }\n}\n"],"mappings":"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"}
|