@frontfactory/readmore 1.1.1 → 1.3.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 +5 -3
- package/dist/readmore.d.ts +4 -1
- package/dist/readmore.js +25 -22
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -53,7 +53,8 @@ Or instantiate against a single element:
|
|
|
53
53
|
const el = document.querySelector<HTMLElement>('#bio');
|
|
54
54
|
|
|
55
55
|
if (el) new ReadMore(el, {
|
|
56
|
-
lines: 4
|
|
56
|
+
lines: 4,
|
|
57
|
+
onToggle: (expanded) => console.log('expanded:', expanded)
|
|
57
58
|
});
|
|
58
59
|
```
|
|
59
60
|
|
|
@@ -61,14 +62,15 @@ if (el) new ReadMore(el, {
|
|
|
61
62
|
|
|
62
63
|
| Option | Type | Default | Description |
|
|
63
64
|
|-----------------|----------|------------------|--------------------------------------------------------------------|
|
|
64
|
-
| `lines` | `number` | `3` | Number of lines to clamp to. Ignored if `height` is set.
|
|
65
|
-
| `height` | `number` | — | Max height in pixels. Takes precedence over `lines
|
|
65
|
+
| `lines` | `number` | `3` | Number of lines to clamp to (min `1`). Ignored if `height` is set. |
|
|
66
|
+
| `height` | `number` | — | Max height in pixels (min `1`). Takes precedence over `lines`. |
|
|
66
67
|
| `moreText` | `string` | `'Read more'` | Label of the button when the text is collapsed. |
|
|
67
68
|
| `lessText` | `string` | `'Read less'` | Label of the button when the text is expanded. |
|
|
68
69
|
| `buttonClass` | `string` | `'readmore-btn'` | Class applied to the toggle button. |
|
|
69
70
|
| `expandedClass` | `string` | `'is-expanded'` | Class applied to the target element while expanded. |
|
|
70
71
|
| `openingClass` | `string` | `'is-opening'` | Transient class applied while expanding, removed after transition. |
|
|
71
72
|
| `closingClass` | `string` | `'is-closing'` | Transient class applied while collapsing, removed after transition.|
|
|
73
|
+
| `onToggle` | `(expanded: boolean) => void` | — | Callback fired after each toggle with the current `expanded` state. |
|
|
72
74
|
|
|
73
75
|
## API
|
|
74
76
|
|
package/dist/readmore.d.ts
CHANGED
|
@@ -7,9 +7,11 @@ export interface ReadMoreOptions {
|
|
|
7
7
|
expandedClass?: string;
|
|
8
8
|
openingClass?: string;
|
|
9
9
|
closingClass?: string;
|
|
10
|
+
onToggle?: (expanded: boolean) => void;
|
|
10
11
|
}
|
|
11
|
-
type ResolvedOptions = Required<Omit<ReadMoreOptions, 'height'>> & {
|
|
12
|
+
type ResolvedOptions = Required<Omit<ReadMoreOptions, 'height' | 'onToggle'>> & {
|
|
12
13
|
height?: number;
|
|
14
|
+
onToggle?: (expanded: boolean) => void;
|
|
13
15
|
};
|
|
14
16
|
export declare class ReadMore {
|
|
15
17
|
#private;
|
|
@@ -19,6 +21,7 @@ export declare class ReadMore {
|
|
|
19
21
|
static init(target: string | NodeListOf<HTMLElement> | HTMLElement[], options?: ReadMoreOptions): ReadMore[];
|
|
20
22
|
get expanded(): boolean;
|
|
21
23
|
toggle(): void;
|
|
24
|
+
static getInstance(element: HTMLElement): ReadMore | undefined;
|
|
22
25
|
destroy(): void;
|
|
23
26
|
}
|
|
24
27
|
export {};
|
package/dist/readmore.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/readmore.ts
|
|
2
|
-
var e = "readmore-clamp", t = "readmore-clamp--height", n = {
|
|
2
|
+
var e = "readmore-clamp", t = "readmore-clamp--height", n = /* @__PURE__ */ new WeakMap(), r = 0, i = {
|
|
3
3
|
lines: 3,
|
|
4
4
|
moreText: "Read more",
|
|
5
5
|
lessText: "Read less",
|
|
@@ -7,43 +7,45 @@ var e = "readmore-clamp", t = "readmore-clamp--height", n = {
|
|
|
7
7
|
expandedClass: "is-expanded",
|
|
8
8
|
openingClass: "is-opening",
|
|
9
9
|
closingClass: "is-closing"
|
|
10
|
-
},
|
|
10
|
+
}, a = class a {
|
|
11
11
|
el;
|
|
12
12
|
options;
|
|
13
13
|
#e = null;
|
|
14
14
|
#t = !1;
|
|
15
|
-
#n =
|
|
16
|
-
#r
|
|
17
|
-
#i =
|
|
18
|
-
this.#n !== null && clearTimeout(this.#n), this.#n = setTimeout(() => {
|
|
19
|
-
this.#n = null, this.#c();
|
|
20
|
-
}, 100);
|
|
21
|
-
};
|
|
15
|
+
#n = !1;
|
|
16
|
+
#r;
|
|
17
|
+
#i = null;
|
|
22
18
|
#a = () => this.toggle();
|
|
23
19
|
constructor(e, t = {}) {
|
|
24
20
|
if (!(e instanceof HTMLElement)) throw TypeError("ReadMore: an HTMLElement is required.");
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
if (n.has(e)) throw Error("ReadMore: element is already initialized. Call destroy() first.");
|
|
22
|
+
if (this.el = e, this.options = {
|
|
23
|
+
...i,
|
|
27
24
|
...t
|
|
28
|
-
}, this
|
|
25
|
+
}, this.options.height != null && this.options.height <= 0) throw RangeError("ReadMore: height must be greater than 0.");
|
|
26
|
+
if (this.options.lines < 1) throw RangeError("ReadMore: lines must be at least 1.");
|
|
27
|
+
this.#r = new ResizeObserver(() => this.#c()), n.set(e, this), this.#o();
|
|
29
28
|
}
|
|
30
29
|
static init(e, t) {
|
|
31
30
|
let n = typeof e == "string" ? document.querySelectorAll(e) : e;
|
|
32
|
-
return Array.from(n).map((e) => new
|
|
31
|
+
return Array.from(n).map((e) => new a(e, t));
|
|
33
32
|
}
|
|
34
33
|
get expanded() {
|
|
35
34
|
return this.#t;
|
|
36
35
|
}
|
|
37
36
|
toggle() {
|
|
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);
|
|
37
|
+
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, this.#e.setAttribute("aria-expanded", String(this.#t)));
|
|
39
38
|
let n = this.#t ? this.options.openingClass : this.options.closingClass, r = this.#t ? this.options.closingClass : this.options.openingClass;
|
|
40
|
-
this.el.classList.remove(r), this.#l(n), this.#t || this.#c();
|
|
39
|
+
this.el.classList.remove(r), this.#l(n), this.#t || this.#c(), this.options.onToggle?.(this.#t);
|
|
40
|
+
}
|
|
41
|
+
static getInstance(e) {
|
|
42
|
+
return n.get(e);
|
|
41
43
|
}
|
|
42
44
|
destroy() {
|
|
43
|
-
|
|
45
|
+
n.delete(this.el), this.#r.disconnect(), this.#i &&= (this.el.removeEventListener("transitionend", this.#i), 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"), this.#n &&= (this.el.removeAttribute("id"), !1);
|
|
44
46
|
}
|
|
45
47
|
#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)),
|
|
48
|
+
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)), this.#r.observe(this.el), this.#c();
|
|
47
49
|
}
|
|
48
50
|
#s() {
|
|
49
51
|
return this.el.scrollHeight - this.el.clientHeight > 1;
|
|
@@ -54,24 +56,25 @@ var e = "readmore-clamp", t = "readmore-clamp--height", n = {
|
|
|
54
56
|
e && !this.#e ? this.#u() : !e && this.#e && this.#d();
|
|
55
57
|
}
|
|
56
58
|
#l(e) {
|
|
57
|
-
this.#
|
|
59
|
+
this.#i &&= (this.el.removeEventListener("transitionend", this.#i), null), this.el.classList.add(e);
|
|
58
60
|
let t = () => this.el.classList.remove(e);
|
|
59
61
|
if (!getComputedStyle(this.el).transitionDuration.split(",").some((e) => parseFloat(e) > 0)) {
|
|
60
62
|
setTimeout(t, 0);
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
let n = (e) => {
|
|
64
|
-
e.target === this.el && (this.el.removeEventListener("transitionend", n), this.#
|
|
66
|
+
e.target === this.el && (this.el.removeEventListener("transitionend", n), this.#i = null, t());
|
|
65
67
|
};
|
|
66
|
-
this.#
|
|
68
|
+
this.#i = n, this.el.addEventListener("transitionend", n);
|
|
67
69
|
}
|
|
68
70
|
#u() {
|
|
71
|
+
this.el.id || (this.el.id = `readmore-${++r}`, this.#n = !0);
|
|
69
72
|
let e = document.createElement("button");
|
|
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;
|
|
73
|
+
e.type = "button", e.className = this.options.buttonClass, e.textContent = this.options.moreText, e.setAttribute("aria-expanded", "false"), e.setAttribute("aria-controls", this.el.id), e.addEventListener("click", this.#a), this.el.insertAdjacentElement("afterend", e), this.#e = e;
|
|
71
74
|
}
|
|
72
75
|
#d() {
|
|
73
76
|
this.#e &&= (this.#e.removeEventListener("click", this.#a), this.#e.remove(), null);
|
|
74
77
|
}
|
|
75
78
|
};
|
|
76
79
|
//#endregion
|
|
77
|
-
export {
|
|
80
|
+
export { a as ReadMore };
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontfactory/readmore",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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": {
|
|
7
7
|
"dev": "vite",
|
|
8
|
+
"lint:js": "eslint --fix .",
|
|
8
9
|
"build": "vite build",
|
|
9
10
|
"preview": "vite preview",
|
|
10
11
|
"typecheck": "tsc --noEmit",
|
|
@@ -30,21 +31,25 @@
|
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@commitlint/cli": "^20.5.3",
|
|
32
33
|
"@commitlint/config-conventional": "^20.5.3",
|
|
34
|
+
"@front-factory/eslint-config": "^2.4.2",
|
|
33
35
|
"@semantic-release/changelog": "^6.0.3",
|
|
34
36
|
"@semantic-release/git": "^10.0.1",
|
|
35
37
|
"@semantic-release/github": "^12.0.6",
|
|
36
38
|
"@vitest/coverage-v8": "^4.1.5",
|
|
37
39
|
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
40
|
+
"eslint": "^10.3.0",
|
|
38
41
|
"husky": "^9.1.7",
|
|
39
42
|
"jsdom": "^29.1.1",
|
|
40
43
|
"lightningcss": "^1.32.0",
|
|
41
44
|
"semantic-release": "^25.0.3",
|
|
42
45
|
"typescript": "^5.4.0",
|
|
46
|
+
"typescript-eslint": "^8.59.2",
|
|
43
47
|
"vite": "^8.0.11",
|
|
44
48
|
"vite-plugin-dts": "^5.0.0",
|
|
45
49
|
"vite-plugin-static-copy": "^4.1.0",
|
|
46
50
|
"vitest": "^4.1.5"
|
|
47
51
|
},
|
|
52
|
+
"sideEffects": false,
|
|
48
53
|
"files": [
|
|
49
54
|
"dist"
|
|
50
55
|
],
|