@anthusai/papyrus 1.12.0 → 1.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.
|
@@ -1,45 +1,61 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect
|
|
4
|
-
import { createPortal } from "react-dom";
|
|
3
|
+
import { useEffect } from "react";
|
|
5
4
|
|
|
6
5
|
type Excerpt = { issueId: string; text: string };
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
const EXCERPT_TOGGLE_THRESHOLD = 130;
|
|
8
|
+
|
|
9
|
+
function buildExcerptElement(text: string): HTMLElement {
|
|
10
|
+
const container = document.createElement("div");
|
|
11
|
+
container.className = "board-card-excerpt";
|
|
12
|
+
container.dataset.boardCardExcerpt = "";
|
|
13
|
+
container.dataset.expanded = "false";
|
|
14
|
+
const paragraph = document.createElement("p");
|
|
15
|
+
paragraph.textContent = text;
|
|
16
|
+
container.append(paragraph);
|
|
17
|
+
if (text.length > EXCERPT_TOGGLE_THRESHOLD) {
|
|
18
|
+
const toggle = document.createElement("button");
|
|
19
|
+
toggle.type = "button";
|
|
20
|
+
toggle.textContent = "More";
|
|
21
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
22
|
+
const flip = (event: Event) => {
|
|
23
|
+
event.stopPropagation();
|
|
24
|
+
const expanded = container.dataset.expanded !== "true";
|
|
25
|
+
container.dataset.expanded = String(expanded);
|
|
26
|
+
toggle.textContent = expanded ? "Less" : "More";
|
|
27
|
+
toggle.setAttribute("aria-expanded", String(expanded));
|
|
28
|
+
};
|
|
29
|
+
toggle.addEventListener("click", flip);
|
|
30
|
+
toggle.addEventListener("keydown", event => event.stopPropagation());
|
|
31
|
+
container.append(toggle);
|
|
32
|
+
}
|
|
33
|
+
return container;
|
|
14
34
|
}
|
|
15
35
|
|
|
16
36
|
/**
|
|
17
37
|
* Adds a short expandable excerpt under each card's headline. The Kanbus card has no excerpt slot,
|
|
18
|
-
* so each excerpt is
|
|
38
|
+
* so each excerpt is written into the card's content block once the card is on the page.
|
|
19
39
|
*/
|
|
20
40
|
export function BoardCardExcerpts({ excerpts, scope }: { excerpts: readonly Excerpt[]; scope: HTMLElement | null }) {
|
|
21
|
-
const [hosts, setHosts] = useState<{ host: HTMLElement; text: string }[]>([]);
|
|
22
41
|
useEffect(() => {
|
|
23
42
|
if (!scope) return;
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return [{ host, text }];
|
|
36
|
-
});
|
|
37
|
-
setHosts(previous => previous.length === found.length && previous.every((entry, index) => entry.host === found[index].host && entry.text === found[index].text) ? previous : found);
|
|
43
|
+
const textByIssueId = new Map(excerpts.map(({ issueId, text }) => [issueId, text]));
|
|
44
|
+
const place = () => {
|
|
45
|
+
for (const card of Array.from(scope.querySelectorAll<HTMLElement>(".issue-card"))) {
|
|
46
|
+
const text = textByIssueId.get(card.dataset.issueId ?? "");
|
|
47
|
+
const content = card.querySelector<HTMLElement>(".issue-card-content");
|
|
48
|
+
if (!text || !content) continue;
|
|
49
|
+
const existing = content.querySelector<HTMLElement>(":scope > [data-board-card-excerpt]");
|
|
50
|
+
if (existing && existing.querySelector("p")?.textContent === text) continue;
|
|
51
|
+
existing?.remove();
|
|
52
|
+
content.querySelector("h3")?.after(buildExcerptElement(text));
|
|
53
|
+
}
|
|
38
54
|
};
|
|
39
|
-
|
|
40
|
-
const observer = new MutationObserver(
|
|
55
|
+
place();
|
|
56
|
+
const observer = new MutationObserver(place);
|
|
41
57
|
observer.observe(scope, { childList: true, subtree: true });
|
|
42
58
|
return () => observer.disconnect();
|
|
43
59
|
}, [excerpts, scope]);
|
|
44
|
-
return
|
|
60
|
+
return null;
|
|
45
61
|
}
|
package/package.json
CHANGED
package/routes.manifest.json
CHANGED