lumiverse-spindle-types 0.5.11 → 0.5.12

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/dom.ts +84 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumiverse-spindle-types",
3
- "version": "0.5.11",
3
+ "version": "0.5.12",
4
4
  "types": "./src/index.ts",
5
5
  "keywords": [
6
6
  "lumiverse",
package/src/dom.ts CHANGED
@@ -1,6 +1,14 @@
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
  /** Inject sanitized HTML into the host document at the given target. */
@@ -24,6 +32,50 @@ export interface SpindleDOMHelper {
24
32
  /** Query all matches inside the extension-owned host DOM. */
25
33
  queryAll(selector: string): Element[];
26
34
 
35
+ /**
36
+ * Resolve the chat message that contains the given DOM element. Walks
37
+ * up the DOM tree from `target` looking for the host's message-bubble
38
+ * anchor and returns the stable message id of the containing message,
39
+ * or `null` when `target` isn't inside any chat message (e.g. it's in
40
+ * the sidebar, a modal, or a floating widget).
41
+ *
42
+ * Prefer this over reading host-private DOM attributes directly — the
43
+ * underlying attribute name is an implementation detail of the host
44
+ * and may change; this method is the stable public contract.
45
+ *
46
+ * Typical use: an extension injects content into a message bubble and
47
+ * needs the stable id to persist per-message state, key event
48
+ * handlers on the message id, or call `ctx.messages.renderWidget()`
49
+ * with the right id.
50
+ */
51
+ getMessageId(target: Element): string | null;
52
+
53
+ /**
54
+ * Find the chat-message bubble element currently mounted in the DOM
55
+ * for the given stable message id. Returns `null` when the message
56
+ * isn't currently rendered — the chat message list is virtualized, so
57
+ * only bubbles near the viewport (plus a small overscan window) have
58
+ * DOM at any moment.
59
+ *
60
+ * Typical use: extension wants to attach content to a specific known
61
+ * message id. If `null` comes back, the bubble isn't currently
62
+ * mounted. Injections previously made via `dom.inject()` against a
63
+ * bubble element are auto-replayed by the host when that bubble next
64
+ * mounts, so extensions don't need to re-inject on scroll themselves.
65
+ */
66
+ findMessageElement(messageId: string): Element | null;
67
+
68
+ /**
69
+ * Enumerate every chat message bubble currently mounted in the DOM,
70
+ * paired with its stable message id. The returned list reflects only
71
+ * what the virtualizer has rendered (typically the viewport plus a
72
+ * small overscan window), so it changes as the user scrolls.
73
+ *
74
+ * Typical use: extension sweeps every visible message on setup or in
75
+ * response to a chat-changed event to apply per-message decoration.
76
+ */
77
+ listMessageElements(): SpindleMessageElement[];
78
+
27
79
  /** Remove all DOM created by the extension helper. */
28
80
  cleanup(): void;
29
81
  }
@@ -652,6 +704,38 @@ export interface SpindleFrontendContext {
652
704
  ): () => void;
653
705
  /** Remove a previously rendered message widget. */
654
706
  removeWidget(messageId: string, widgetId: string): void;
707
+ /**
708
+ * Get the latest (most recent) message id in the active chat, or
709
+ * `null` if the chat is empty / no chat is active. Reflects the
710
+ * full chat history — works even when the latest bubble is
711
+ * currently scrolled off-screen (the chat list is virtualized, so
712
+ * the DOM might not contain the bubble even though the message
713
+ * exists logically).
714
+ *
715
+ * Typical use: extensions that decorate or react to the most recent
716
+ * message (trackers, summarizers, "show last response details"
717
+ * widgets) call this on setup + on each new-message event to find
718
+ * the id they should target, then pair with `dom.findMessageElement`
719
+ * or `dom.inject()` to attach DOM content. Injections registered
720
+ * via `dom.inject()` auto-replay when the bubble next mounts so the
721
+ * extension doesn't have to re-attach on scroll itself.
722
+ */
723
+ getLatestMessageId(): string | null;
724
+ /**
725
+ * Get the message id at the given chronological index in the
726
+ * active chat (0 = oldest, length-1 = newest). Negative indices
727
+ * count from the end Python-style: -1 = latest, -2 = second-
728
+ * latest. Returns `null` if the index is out of range or no chat
729
+ * is active.
730
+ */
731
+ getMessageIdAtIndex(index: number): string | null;
732
+ /**
733
+ * Enumerate every message id in the active chat in chronological
734
+ * order (oldest first, newest last). Reflects the full chat
735
+ * history, not just messages currently mounted in the DOM. See
736
+ * `dom.listMessageElements()` for the mounted-only DOM view.
737
+ */
738
+ listMessageIds(): string[];
655
739
  };
656
740
  characters: {
657
741
  /** Read a character through the host app's authenticated API. */