lumiverse-spindle-types 0.5.11 → 0.5.13
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/package.json +1 -1
- package/src/dom.ts +116 -1
package/package.json
CHANGED
package/src/dom.ts
CHANGED
|
@@ -1,11 +1,48 @@
|
|
|
1
1
|
import type { RequestInitDTO } from "./api";
|
|
2
2
|
import type { SpindleComponentsHelper } from "./components";
|
|
3
3
|
|
|
4
|
+
/** A chat-message DOM element paired with its stable message id. */
|
|
5
|
+
export interface SpindleMessageElement {
|
|
6
|
+
/** Stable message id (matches the message's id in the host's data store). */
|
|
7
|
+
messageId: string;
|
|
8
|
+
/** Currently-mounted bubble root element for that message. */
|
|
9
|
+
element: Element;
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
/** DOM helper API provided to frontend extension modules. */
|
|
5
13
|
export interface SpindleDOMHelper {
|
|
6
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Inject sanitized HTML into the host document at the given target and
|
|
16
|
+
* return the wrapper element containing the parsed content.
|
|
17
|
+
*
|
|
18
|
+
* **Element identity is preserved across chat-list virtualization.**
|
|
19
|
+
* When the injection lands inside a chat-message bubble, the host
|
|
20
|
+
* registers the wrapper and *moves* (not recreates) it back into place
|
|
21
|
+
* when the bubble next mounts. That means form-control state, event
|
|
22
|
+
* listeners bound to the wrapper subtree, and any refs the extension is
|
|
23
|
+
* holding all survive scroll-away/scroll-back cycles. Extensions can
|
|
24
|
+
* cache the returned Element and trust it indefinitely until they
|
|
25
|
+
* explicitly retire it via `uninject()` or `cleanup()`.
|
|
26
|
+
*
|
|
27
|
+
* To deliberately remove an injection, call `uninject(wrapper)` — NOT
|
|
28
|
+
* `wrapper.remove()`. The latter detaches the wrapper but leaves the
|
|
29
|
+
* registry record in place, so the host will resurrect the wrapper on
|
|
30
|
+
* the next bubble remount.
|
|
31
|
+
*
|
|
32
|
+
* Injections outside any chat-message bubble (sidebar, modals, toolbar)
|
|
33
|
+
* are unaffected by virtualization and don't go through replay — they
|
|
34
|
+
* stay attached wherever the extension put them.
|
|
35
|
+
*/
|
|
7
36
|
inject(target: string | Element, html: string, position?: InsertPosition): Element;
|
|
8
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Retire an injection previously returned by `inject()`. Removes the
|
|
40
|
+
* wrapper from the DOM and drops its replay registration so the host
|
|
41
|
+
* won't restore it on future bubble remounts. No-op if the element
|
|
42
|
+
* isn't a recognised Spindle injection wrapper.
|
|
43
|
+
*/
|
|
44
|
+
uninject(element: Element): void;
|
|
45
|
+
|
|
9
46
|
/** Create a style element in the host document. Returns a removal function. */
|
|
10
47
|
addStyle(css: string): () => void;
|
|
11
48
|
|
|
@@ -24,6 +61,52 @@ export interface SpindleDOMHelper {
|
|
|
24
61
|
/** Query all matches inside the extension-owned host DOM. */
|
|
25
62
|
queryAll(selector: string): Element[];
|
|
26
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the chat message that contains the given DOM element. Walks
|
|
66
|
+
* up the DOM tree from `target` looking for the host's message-bubble
|
|
67
|
+
* anchor and returns the stable message id of the containing message,
|
|
68
|
+
* or `null` when `target` isn't inside any chat message (e.g. it's in
|
|
69
|
+
* the sidebar, a modal, or a floating widget).
|
|
70
|
+
*
|
|
71
|
+
* Prefer this over reading host-private DOM attributes directly — the
|
|
72
|
+
* underlying attribute name is an implementation detail of the host
|
|
73
|
+
* and may change; this method is the stable public contract.
|
|
74
|
+
*
|
|
75
|
+
* Typical use: an extension injects content into a message bubble and
|
|
76
|
+
* needs the stable id to persist per-message state, key event
|
|
77
|
+
* handlers on the message id, or call `ctx.messages.renderWidget()`
|
|
78
|
+
* with the right id.
|
|
79
|
+
*/
|
|
80
|
+
getMessageId(target: Element): string | null;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Find the chat-message bubble element currently mounted in the DOM
|
|
84
|
+
* for the given stable message id. Returns `null` when the message
|
|
85
|
+
* isn't currently rendered — the chat message list is virtualized, so
|
|
86
|
+
* only bubbles near the viewport (plus a small overscan window) have
|
|
87
|
+
* DOM at any moment.
|
|
88
|
+
*
|
|
89
|
+
* Typical use: extension wants to attach content to a specific known
|
|
90
|
+
* message id. If `null` comes back, the bubble isn't currently
|
|
91
|
+
* mounted. Injections previously made via `dom.inject()` against a
|
|
92
|
+
* bubble element are auto-replayed by the host (with the original
|
|
93
|
+
* Element identity preserved — see `inject()` for the full contract)
|
|
94
|
+
* when that bubble next mounts, so extensions don't need to re-inject
|
|
95
|
+
* on scroll themselves.
|
|
96
|
+
*/
|
|
97
|
+
findMessageElement(messageId: string): Element | null;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Enumerate every chat message bubble currently mounted in the DOM,
|
|
101
|
+
* paired with its stable message id. The returned list reflects only
|
|
102
|
+
* what the virtualizer has rendered (typically the viewport plus a
|
|
103
|
+
* small overscan window), so it changes as the user scrolls.
|
|
104
|
+
*
|
|
105
|
+
* Typical use: extension sweeps every visible message on setup or in
|
|
106
|
+
* response to a chat-changed event to apply per-message decoration.
|
|
107
|
+
*/
|
|
108
|
+
listMessageElements(): SpindleMessageElement[];
|
|
109
|
+
|
|
27
110
|
/** Remove all DOM created by the extension helper. */
|
|
28
111
|
cleanup(): void;
|
|
29
112
|
}
|
|
@@ -652,6 +735,38 @@ export interface SpindleFrontendContext {
|
|
|
652
735
|
): () => void;
|
|
653
736
|
/** Remove a previously rendered message widget. */
|
|
654
737
|
removeWidget(messageId: string, widgetId: string): void;
|
|
738
|
+
/**
|
|
739
|
+
* Get the latest (most recent) message id in the active chat, or
|
|
740
|
+
* `null` if the chat is empty / no chat is active. Reflects the
|
|
741
|
+
* full chat history — works even when the latest bubble is
|
|
742
|
+
* currently scrolled off-screen (the chat list is virtualized, so
|
|
743
|
+
* the DOM might not contain the bubble even though the message
|
|
744
|
+
* exists logically).
|
|
745
|
+
*
|
|
746
|
+
* Typical use: extensions that decorate or react to the most recent
|
|
747
|
+
* message (trackers, summarizers, "show last response details"
|
|
748
|
+
* widgets) call this on setup + on each new-message event to find
|
|
749
|
+
* the id they should target, then pair with `dom.findMessageElement`
|
|
750
|
+
* or `dom.inject()` to attach DOM content. Injections registered
|
|
751
|
+
* via `dom.inject()` auto-replay when the bubble next mounts so the
|
|
752
|
+
* extension doesn't have to re-attach on scroll itself.
|
|
753
|
+
*/
|
|
754
|
+
getLatestMessageId(): string | null;
|
|
755
|
+
/**
|
|
756
|
+
* Get the message id at the given chronological index in the
|
|
757
|
+
* active chat (0 = oldest, length-1 = newest). Negative indices
|
|
758
|
+
* count from the end Python-style: -1 = latest, -2 = second-
|
|
759
|
+
* latest. Returns `null` if the index is out of range or no chat
|
|
760
|
+
* is active.
|
|
761
|
+
*/
|
|
762
|
+
getMessageIdAtIndex(index: number): string | null;
|
|
763
|
+
/**
|
|
764
|
+
* Enumerate every message id in the active chat in chronological
|
|
765
|
+
* order (oldest first, newest last). Reflects the full chat
|
|
766
|
+
* history, not just messages currently mounted in the DOM. See
|
|
767
|
+
* `dom.listMessageElements()` for the mounted-only DOM view.
|
|
768
|
+
*/
|
|
769
|
+
listMessageIds(): string[];
|
|
655
770
|
};
|
|
656
771
|
characters: {
|
|
657
772
|
/** Read a character through the host app's authenticated API. */
|