@pixl-app/sdk 0.1.0 → 1.0.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/dist/client.d.ts CHANGED
@@ -1,194 +1,157 @@
1
- import type { SpotifyNowPlaying, StreamElementsProxyPath } from "./api-types/index.js";
1
+ import { type EventPayloads, type ChannelEvent, type ChannelEventType, type StreamConnected } from "./api-types/index.js";
2
2
  import { PixlChat } from "./chat.js";
3
- import { EventFeed, type FeedOptions } from "./feed.js";
3
+ import { PixlEvents } from "./events.js";
4
+ import { fontFamily, loadFont } from "./fonts.js";
5
+ import { type LiveValue } from "./live-value.js";
6
+ import { PixlSpotify } from "./spotify.js";
7
+ import { PixlStreamElements } from "./streamelements.js";
8
+ import { type ConnectionStatus } from "./stream.js";
4
9
  import { PixlTts } from "./tts.js";
5
- export type PixlStatus = "connecting" | "connected" | "disconnected" | "unauthorized" | "closed";
10
+ import { PixlTwitch } from "./twitch.js";
11
+ import { PixlWidget } from "./widget.js";
12
+ export type { ConnectionStatus };
13
+ /** Ein Event, wie es bei Handlern ankommt */
14
+ export type PixlEvent<T extends ChannelEventType = ChannelEventType> = ChannelEvent<T>;
15
+ /** Kanal, zu dem der Zugang gehört */
16
+ export type Channel = StreamConnected["channel"];
6
17
  export type PixlOptions = {
7
- /** API-Schlüssel (`pixl_…`), erstellt unter Einstellungen → API-Schlüssel */
8
- key: string;
9
- /**
10
- * Adresse der pixl-Instanz. Standard: der Server, von dem das SDK-Script
11
- * geladen wurde, sonst https://pixl.lennox.zip
12
- */
18
+ /** API-Schlüssel (`pixl_…`) aus „API & SDK“. In gehosteten Widgets setzt pixl den Zugang selbst. */
19
+ key?: string;
20
+ /** Adresse der pixl-Instanz. Standard: der Server, von dem das Script kam, sonst https://pixl.lennox.zip */
13
21
  baseUrl?: string;
14
- /** Stream automatisch verbinden (Standard: true). Sonst manuell per connect(). */
22
+ /** Ohne Server: Vorlagen für Live-Werte, Events per `sendTestEvent()`. Für Vorschauen und Entwicklung. */
23
+ demo?: boolean;
24
+ /** Live-Verbindung sofort aufbauen (Standard: true), sonst per `connect()` */
15
25
  autoConnect?: boolean;
16
- /**
17
- * Abbruch und Neuverbinden der Live-Verbindung in der Browser-Konsole melden
18
- * (Standard: true). Nur Wechsel, keine Events.
19
- */
26
+ /** Verbindungswechsel in der Konsole melden (Standard: true) */
20
27
  logs?: boolean;
28
+ /** @internal zum Testen */
29
+ fetch?: typeof fetch;
21
30
  };
22
- export type PixlEvent = {
23
- /** Event-Typ, z.B. `twitch.cheer` */
24
- event: string;
25
- /** Payload laut Event-Referenz */
26
- data: Record<string, unknown>;
27
- /** true bei erneut abgespielten Events aus dem Eventlog */
28
- replay: boolean;
29
- /** ID der Eventlog-Zeile (nur bei Events, die im Eventlog stehen) */
30
- id?: string;
31
- /** Zeitpunkt als ISO-String (nur bei Events, die im Eventlog stehen) */
32
- at?: string;
33
- /** true, wenn das Event aus der Historie nachgeladen wurde (nur bei feed()) */
34
- history?: boolean;
35
- };
36
- export type EventHandler = (data: Record<string, unknown>, event: PixlEvent) => void;
37
- export type StateHandler = (value: unknown, key: string) => void;
38
- export type EventsQuery = {
39
- /** Ab wann: Date, ISO-String, Unix-ms oder `"stream"` (Start des letzten Streams) */
40
- since?: Date | string | number;
41
- /** Bis wann (exklusiv) */
42
- until?: Date | string | number;
43
- /** Nur diese Event-Typen */
44
- types?: string[];
45
- /** Max. Anzahl pro Seite, 1 bis 200 (Standard 50) */
46
- limit?: number;
47
- /** `nextCursor` der vorherigen Seite */
48
- cursor?: string;
49
- };
50
- export type EventsPage = {
51
- events: {
52
- id: string;
53
- event: string;
54
- data: Record<string, unknown>;
55
- at: string;
56
- }[];
57
- nextCursor: string | null;
31
+ export type RequestOptions = {
32
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
33
+ query?: Record<string, string | number | boolean | undefined>;
34
+ body?: unknown;
35
+ /** Statt `body`: Datei oder Daten unverändert als Body (Content-Type aus dem Blob) */
36
+ raw?: Blob;
37
+ signal?: AbortSignal;
58
38
  };
59
- export type OrgInfo = {
60
- id: string;
61
- name: string;
62
- logo: string | null;
63
- twitchChannelLogin: string | null;
64
- /** Erlaubnisse des verwendeten Schlüssels, z.B. `["events:read"]` */
65
- scopes: string[];
66
- };
67
- export type SubCount = {
68
- /** Aktive Subs laut Twitch, inklusive des Streamers selbst (zählt Twitch so) */
69
- total: number;
70
- /** Sub-Punkte laut Twitch: Stufe 1 = 1, Stufe 2 = 2, Stufe 3 = 6 */
71
- points: number;
72
- /** Wann pixl die Zahl bei Twitch abgefragt hat (ISO-String) */
73
- at: string;
74
- };
75
- export declare class PixlApiError extends Error {
76
- status: number;
77
- /** Maschinenlesbarer Grund, falls der Server einen nennt (z.B. `quota` bei TTS) */
78
- problem?: string;
79
- constructor(status: number, message: string, problem?: string);
80
- }
81
- export declare function toQueryDate(value: Date | string | number): string;
82
39
  export declare class Pixl {
83
- /** Von global.ts gesetzt: Origin des geladenen SDK-Scripts */
40
+ /** @internal von global.ts gesetzt: Herkunft des Scripts */
84
41
  static defaultBaseUrl: string | undefined;
85
- readonly baseUrl: string;
86
- private readonly key;
87
- /** Text-to-Speech: vorlesen lassen und abspielen (siehe Doku "TTS") */
88
- readonly tts: PixlTts;
89
- /** Chat: Emotes als HTML, 7TV-Paints (siehe Doku "Chat") */
90
- readonly chat: PixlChat;
91
- private handlers;
92
- private stateHandlers;
93
- private statusHandlers;
94
- private states;
95
- private _status;
96
- private abort;
97
- private reconnectTimer;
98
- private watchdog;
99
- private attempt;
100
- private stopped;
101
- private readonly logs;
102
- private everConnected;
103
- private lostAt;
104
- constructor(options: PixlOptions);
42
+ private static sharedInstance;
105
43
  /**
106
- * Handler für einen Event-Typ registrieren (`"twitch.cheer"`), oder für alle
107
- * Events mit `"*"`. Gibt die Instanz zurück, Aufrufe lassen sich verketten.
44
+ * Gemeinsame Instanz der Seite, damit Bausteine (`@pixl-app/sdk/ui`) und eigener Code
45
+ * dieselbe Verbindung nutzen. Die erste mit `new Pixl()` erzeugte Instanz ist automatisch
46
+ * die gemeinsame, sonst entsteht sie hier.
108
47
  */
109
- on(event: string, handler: EventHandler): this;
110
- /** Handler wieder entfernen */
111
- off(event: string, handler: EventHandler): this;
48
+ static shared(options?: PixlOptions): Pixl;
112
49
  /**
113
- * State abonnieren. Der Handler läuft sofort mit dem aktuellen Wert (sobald
114
- * bekannt) und danach bei jeder Änderung.
50
+ * Schrift laden (Bunny Fonts, dieselben Schriften wie Google Fonts), z.B. eine feste Schrift im
51
+ * Code. Werte aus `font`-Feldern lädt `pixl.widget()` von selbst. `true`, sobald sie bereit ist,
52
+ * `false`, wenn es sie dort nicht gibt (dann gilt eine lokal installierte)
115
53
  */
116
- state(key: string, handler: StateHandler): this;
117
- /** State-Handler wieder entfernen */
118
- offState(key: string, handler: StateHandler): this;
119
- /** Zuletzt bekannter Wert eines States (undefined, solange unbekannt) */
120
- getState(key: string): unknown;
121
- get status(): PixlStatus;
122
- /** Statuswechsel beobachten. Gibt eine Funktion zum Abmelden zurück. */
123
- onStatus(handler: (status: PixlStatus) => void): () => void;
124
- private setStatus;
125
- /** Rohzugriff auf einen /api/v1-Endpoint (Pfad ohne /api/v1, z.B. `/events`) */
126
- request<T>(path: string, params?: Record<string, string | undefined>): Promise<T>;
54
+ static loadFont: typeof loadFont;
127
55
  /**
128
- * Wie request(), aber mit beliebiger Methode und Body (JSON) bzw. roher
129
- * Response. Für die TTS-Endpunkte, nicht Teil der öffentlichen Schnittstelle.
130
- * @internal
56
+ * Wert für CSS `font-family` mit Anführungszeichen und Ausweich-Schrift
57
+ * @example el.style.fontFamily = Pixl.fontFamily(font) // "Open Sans", sans-serif
131
58
  */
132
- _fetch(path: string, init?: {
133
- method?: string;
134
- json?: unknown;
135
- }): Promise<Response>;
136
- /** Eventlog abfragen (neueste zuerst, seitenweise) */
137
- events(query?: EventsQuery): Promise<EventsPage>;
138
- /** Infos zur Organisation, der der Schlüssel gehört, plus dessen Scopes */
139
- org(): Promise<OrgInfo>;
59
+ static fontFamily: typeof fontFamily;
60
+ readonly baseUrl: string;
61
+ /** true im Demo-Modus (kein Server) */
62
+ readonly demo: boolean;
63
+ /** Verbindungsstatus */
64
+ readonly status: LiveValue<ConnectionStatus>;
65
+ /** Kanal des Zugangs, null bis zur ersten Verbindung */
66
+ readonly channel: LiveValue<Channel | null>;
67
+ /** Erfüllt, sobald die Verbindung steht und alle Live-Werte geladen sind. Schlägt fehl bei ungültigem Zugang. */
68
+ readonly ready: Promise<void>;
69
+ /** Historie und Feed (Historie plus live) */
70
+ readonly events: PixlEvents;
71
+ /** Sub-Zahl, Hype Train, Umfrage, Vorhersage, Ziel, Spendenaktion, Werbepause */
72
+ readonly twitch: PixlTwitch;
73
+ /** Was gerade auf Spotify läuft */
74
+ readonly spotify: PixlSpotify;
75
+ /** Text-to-Speech: vorlesen lassen und abspielen */
76
+ readonly tts: PixlTts;
77
+ /** Chat: Emotes, Badges, 7TV-Paints */
78
+ readonly chat: PixlChat;
79
+ /** Lesender Zugriff auf den verbundenen StreamElements-Kanal */
80
+ readonly streamElements: PixlStreamElements;
140
81
  /**
141
- * Aktuelle Sub-Zahl direkt von Twitch, unabhängig vom Eventlog (höchstens 60 s alt).
142
- * Braucht einen Schlüssel mit `subs:read`. Änderungen kommen live als `subs.updated`
143
- * mit denselben Feldern.
82
+ * Felder des gehosteten Widgets als einfaches Objekt, immer auf dem aktuellen Stand
83
+ * (Steuerelemente vor Einstellungen, wie die CSS-Variablen `--pixl-…`). Mit einem normalen
84
+ * API-Schlüssel leer. Auf Änderungen hören: `pixl.widget().values.name.subscribe(…)`
85
+ * @example const { text, color } = pixl.fields
144
86
  */
145
- subs(): Promise<SubCount>;
87
+ readonly fields: Readonly<Record<string, unknown>>;
88
+ private key;
89
+ private readonly logs;
90
+ private widgetInstance;
91
+ private readonly control;
92
+ private readonly previewMode;
93
+ private readonly fetchImpl;
94
+ private readonly stream;
95
+ private readonly statusValue;
96
+ private readonly channelValue;
97
+ private readonly handlers;
98
+ private readonly internal;
99
+ private readonly connectHandlers;
100
+ private scopeList;
101
+ private readonly warnedScopes;
102
+ private warnedNoWidget;
103
+ private resolveReady;
104
+ private rejectReady;
105
+ private readySettled;
106
+ constructor(options?: PixlOptions);
146
107
  /**
147
- * Was gerade auf Spotify läuft: `{ playing, progressMs, at, track, addedBy }`.
148
- * Braucht einen Schlüssel mit `spotify:read` und das Modul Musik. Läuft nichts
149
- * (kein Gerät aktiv), ist `track` null. Änderungen (anderer Song, Play/Pause,
150
- * Sprung im Song) kommen live als `spotify.now_playing` mit denselben Feldern.
151
- * Den laufenden Fortschritt liefert `Pixl.progress(nowPlaying)`.
108
+ * Das gehostete Widget, zu dem der Zugang gehört: Einstellungen, Werte, Knöpfe, Listen.
109
+ * null mit einem normalen API-Schlüssel (Widgets gibt es nur gehostet).
152
110
  */
153
- nowPlaying(): Promise<SpotifyNowPlaying>;
111
+ widget(): PixlWidget | null;
112
+ /** Rechte des Zugangs, null bis zur ersten Verbindung */
113
+ get scopes(): readonly string[] | null;
154
114
  /**
155
- * Fortschritt in ms zum Zeitpunkt `now`, aus einer Messung von `nowPlaying()` bzw.
156
- * `spotify.now_playing`. Läuft der Song, wird ab `at` weitergerechnet, höchstens bis
157
- * zur Songlänge.
115
+ * Handler für einen Event-Typ, `"*"` für alle. Gibt eine Funktion zum Abmelden zurück.
116
+ * @example pixl.on("twitch.raid", (e) => show(`${e.data.user.name} raidet mit ${e.data.viewers}`))
158
117
  */
159
- static progress(nowPlaying: SpotifyNowPlaying, now?: number): number;
118
+ on<T extends ChannelEventType>(type: T, handler: (event: PixlEvent<T>) => void): () => void;
119
+ on(type: "*", handler: (event: PixlEvent) => void): () => void;
160
120
  /**
161
- * Lesender Zugriff auf den verbundenen StreamElements-Kanal, pixl reicht die
162
- * Anfrage mit dem hinterlegten Overlay Token weiter (der Token bleibt bei pixl).
163
- * Braucht einen Schlüssel mit `streamelements:read`. `params` gehen 1:1 als
164
- * Query-Parameter an StreamElements, die Antwort kommt unverändert zurück.
121
+ * Ein Event nur an diese Instanz schicken, mit der Vorlage des Typs und eigenen Feldern.
122
+ * `source` ist `test`. Geht auch ohne Verbindung und im Demo-Modus.
123
+ * @example pixl.sendTestEvent("twitch.raid", { viewers: 50 })
165
124
  */
166
- streamElements<T = unknown>(path: StreamElementsProxyPath, params?: Record<string, string | number | undefined>): Promise<T>;
167
- /** Aktuelle Werte aller States */
168
- fetchStates(): Promise<Record<string, unknown>>;
125
+ sendTestEvent<T extends ChannelEventType>(type: T, overrides?: Partial<EventPayloads[T]>): PixlEvent<T>;
126
+ /** Live-Verbindung aufbauen (passiert standardmäßig automatisch) */
127
+ connect(): void;
128
+ /** Verbindung trennen, alle Handler und Abonnements entfernen */
129
+ close(): void;
169
130
  /**
170
- * Alle Events seit `since` holen, über alle Seiten hinweg, älteste zuerst.
171
- * Für große Zeiträume entsprechend viele Requests (200 Events pro Seite).
131
+ * Rohzugriff auf `/api/v1` mit Zugang und Fehlerbehandlung, für alles ohne eigenen Bereich.
132
+ * @example await pixl.request("/subs")
172
133
  */
173
- fetchAllEvents(query?: Omit<EventsQuery, "cursor" | "limit">): Promise<EventsPage["events"]>;
134
+ request<T>(path: string, options?: RequestOptions): Promise<T>;
135
+ /** @internal Antwort als Response (Audio, Blobs) */
136
+ fetchRaw(path: string, options?: RequestOptions): Promise<Response>;
137
+ /** @internal Bereiche laden beim Verbinden ihren Stand (läuft bei jedem `connected`) */
138
+ _onConnect(fn: () => Promise<unknown> | void): void;
139
+ /** @internal Wie on(), aber ohne Scope-Warnung, für Bereiche des SDK */
140
+ _listen<T extends ChannelEventType>(type: T, handler: (event: PixlEvent<T>) => void): () => void;
141
+ private widgetOptions;
174
142
  /**
175
- * Historie + live in einem: `handler` bekommt erst alle Events seit `since`
176
- * (älteste zuerst, `event.history === true`), danach jedes neue live. Jedes
177
- * Event kommt genau einmal an, auch über Verbindungsabbrüche hinweg.
178
- * Rechnet selbst nichts, Summen o.ä. baut der Aufrufer im Handler.
143
+ * @internal Vorschau im Arbeitsplatz von pixl: Vorlesen läuft dort über eigene Wege und ist nur in der
144
+ * Vorschau zu hören (PixlTts)
179
145
  */
180
- feed(options: FeedOptions, handler: EventHandler): EventFeed;
181
- /** Live-Stream verbinden (passiert standardmäßig automatisch) */
182
- connect(): void;
183
- /** Stream trennen und nicht neu verbinden */
184
- disconnect(): void;
185
- private run;
186
- private log;
187
- private scheduleReconnect;
188
- private armWatchdog;
189
- private clearWatchdog;
190
- private readStream;
146
+ get _preview(): boolean;
147
+ /** @internal */
148
+ _log(message: string): void;
149
+ private handleMessage;
150
+ private handleWidgetMessage;
151
+ private listenToDashboard;
152
+ private handleConnected;
153
+ private handleStatus;
191
154
  private dispatch;
192
- private emit;
193
- private setState;
155
+ private checkScope;
156
+ private log;
194
157
  }
@@ -0,0 +1,17 @@
1
+ export type PixlErrorCode = "unauthorized" | "forbidden" | "missing_scope" | "module_disabled" | "rate_limited" | "not_found" | "invalid" | "network" | "demo" | "server";
2
+ export declare class PixlError extends Error {
3
+ readonly code: PixlErrorCode;
4
+ /** HTTP-Status, falls es eine Antwort gab */
5
+ readonly status?: number;
6
+ /** Fehlender Scope bei `missing_scope` */
7
+ readonly scope?: string;
8
+ /** Zusätzlicher Grund vom Server, z.B. `quota` bei TTS */
9
+ readonly problem?: string;
10
+ constructor(code: PixlErrorCode, message: string, extra?: {
11
+ status?: number;
12
+ scope?: string;
13
+ problem?: string;
14
+ });
15
+ }
16
+ /** @internal Fehler aus einer HTTP-Antwort */
17
+ export declare function errorFromResponse(res: Response): Promise<PixlError>;
@@ -0,0 +1,41 @@
1
+ import type { ChannelEventType } from "./api-types/index.js";
2
+ import type { Pixl, PixlEvent } from "./client.js";
3
+ import { EventFeed, type FeedOptions } from "./feed.js";
4
+ export type { FeedOptions };
5
+ /** Zeitpunkt: Date, ISO-String, Unix-ms oder `"stream"` (Start des letzten Streams) */
6
+ export type Since = Date | string | number;
7
+ export type HistoryQuery = {
8
+ /** Ab wann, Pflicht, damit nicht versehentlich das ganze Eventlog geladen wird */
9
+ since: Since;
10
+ /** Bis wann (exklusiv) */
11
+ until?: Date | string | number;
12
+ /** Nur diese Event-Typen */
13
+ types?: ChannelEventType[];
14
+ signal?: AbortSignal;
15
+ };
16
+ type Page = {
17
+ events: PixlEvent[];
18
+ nextCursor: string | null;
19
+ };
20
+ /** @internal */
21
+ export declare function toQueryDate(value: Since): string;
22
+ export declare class PixlEvents {
23
+ private readonly pixl;
24
+ constructor(pixl: Pixl);
25
+ /**
26
+ * Eventlog seit `since`, neueste zuerst, blättert selbst. Enthält nur Events, die im
27
+ * Eventlog stehen (keine Chat-Nachrichten, keine Zwischenstände). Scope `events:read`.
28
+ * @example for await (const e of pixl.events.list({ since: "stream" })) …
29
+ */
30
+ list(query: HistoryQuery): AsyncGenerator<PixlEvent, void, undefined>;
31
+ /** Wie `list()`, aber alles auf einmal und älteste zuerst */
32
+ all(query: HistoryQuery): Promise<PixlEvent[]>;
33
+ /**
34
+ * Historie plus live in einem: `handler` bekommt erst alle Events seit `since` (älteste
35
+ * zuerst, `source: "history"`), danach jedes neue. Jedes Event genau einmal, auch über
36
+ * Verbindungsabbrüche hinweg. Rechnet nichts, Summen baut der Handler.
37
+ */
38
+ feed(options: FeedOptions, handler: (event: PixlEvent) => void): EventFeed;
39
+ /** @internal Eine Seite der Historie */
40
+ fetchPage(query: HistoryQuery, cursor?: string): Promise<Page>;
41
+ }
package/dist/feed.d.ts CHANGED
@@ -1,51 +1,43 @@
1
- import type { EventHandler, Pixl } from "./client.js";
1
+ import type { ChannelEventType } from "./api-types/index.js";
2
+ import type { Pixl, PixlEvent } from "./client.js";
3
+ import type { PixlEvents, Since } from "./events.js";
4
+ import { type LiveValue } from "./live-value.js";
5
+ import { PixlError } from "./errors.js";
2
6
  export type FeedOptions = {
3
- /**
4
- * Ab wann die Historie geladen wird: Date, ISO-String, Unix-ms oder `"stream"`
5
- * (Start des letzten Streams). Pflicht, damit nicht versehentlich das
6
- * komplette Eventlog geladen wird.
7
- */
8
- since: Date | string | number;
7
+ /** Ab wann die Historie geladen wird, Pflicht (z.B. `"stream"`) */
8
+ since: Since;
9
9
  /** Nur diese Event-Typen (Historie und live) */
10
- types?: string[];
10
+ types?: ChannelEventType[];
11
11
  };
12
12
  /**
13
- * Historie + live, jedes Event genau einmal. Ablauf bei jedem (Re-)Connect:
13
+ * Historie plus live, jedes Event genau einmal. Ablauf bei jedem (Neu-)Verbinden:
14
14
  * 1. Live-Events ab jetzt puffern (der Stream steht bereits)
15
15
  * 2. Historie seit `since` laden und ausliefern, was noch nicht ausgeliefert ist
16
16
  * 3. Puffer abarbeiten, Doppelte (gleiche ID) überspringen, danach direkt live
17
- * Weil nach jedem Reconnect die Historie erneut abgeglichen wird, gehen auch
18
- * Events aus einer Verbindungslücke nicht verloren. Nach dem ersten Laden reichen
19
- * dafür die neuesten Seiten: geblättert wird nur bis kurz vor das neueste schon
20
- * ausgelieferte Event. Sonst lüde jedes Overlay nach einem Deploy die komplette
21
- * Historie seit `since` neu und liefe dabei ins Rate-Limit.
22
- * Schlägt das Laden fehl, wird es mit Backoff wiederholt, solange der Stream steht.
23
- *
24
- * Bewusst ohne jede Auswertung: was der Handler mit den Events macht (Summen,
25
- * Listen, Alerts), entscheidet der Aufrufer.
17
+ * Nach dem ersten Laden wird nur bis kurz vor das neueste ausgelieferte Event geblättert,
18
+ * sonst lüde jedes Overlay nach einem Deploy die ganze Historie neu (Rate-Limit).
26
19
  */
27
20
  export declare class EventFeed {
28
- /** true, sobald die Historie einmal komplett ausgeliefert wurde */
29
- ready: boolean;
30
- /** Letzter Fehler beim Laden der Historie */
31
- error: Error | null;
32
21
  private readonly pixl;
22
+ private readonly events;
23
+ private readonly handler;
24
+ /** true, sobald die Historie einmal komplett ausgeliefert wurde */
25
+ readonly ready: LiveValue<boolean>;
26
+ /** Letzter Fehler beim Laden der Historie, null wenn alles gut ging */
27
+ readonly error: LiveValue<PixlError | null>;
28
+ private readonly readyValue;
29
+ private readonly errorValue;
33
30
  private readonly since;
34
31
  private readonly types;
35
- private readonly handler;
36
32
  private readonly delivered;
37
- private readonly errorListeners;
38
33
  private buffer;
39
34
  private loadSeq;
40
35
  private stopped;
41
36
  private latestAt;
42
37
  private retryTimer;
43
38
  private retryAttempt;
44
- private readonly unsubscribeStatus;
45
- private readonly onEvent;
46
- constructor(pixl: Pixl, options: FeedOptions, handler: EventHandler);
47
- /** Fehler beim Laden der Historie beobachten (z.B. noch nie gestreamt bei since="stream") */
48
- onError(listener: (error: Error) => void): () => void;
39
+ private readonly unsubscribe;
40
+ constructor(pixl: Pixl, events: PixlEvents, options: FeedOptions, handler: (event: PixlEvent) => void);
49
41
  /** Feed beenden, der Handler wird danach nicht mehr aufgerufen */
50
42
  stop(): void;
51
43
  private load;
@@ -0,0 +1,19 @@
1
+ import type { WidgetState } from "./api-types/index.js";
2
+ /** Woher `loadFont` lädt */
3
+ export declare const FONT_HOST = "https://fonts.bunny.net";
4
+ /** Adresse des Stylesheets einer Schrift bei Bunny Fonts, mit allen Stärken */
5
+ export declare function fontStylesheetUrl(family: string): string;
6
+ /**
7
+ * Wert für CSS `font-family`: der Name in Anführungszeichen, dahinter eine Ausweich-Schrift.
8
+ * Leer → nur die Ausweich-Schrift.
9
+ * @example el.style.fontFamily = fontFamily(widget.get("font")) // "Open Sans", sans-serif
10
+ */
11
+ export declare function fontFamily(family: string | null | undefined, fallback?: string): string;
12
+ /**
13
+ * Schrift von Bunny Fonts laden (jede nur einmal). Erfüllt sich, sobald sie bereit ist, mit
14
+ * `true`, oder mit `false`, wenn Bunny Fonts sie nicht hat (dann gilt eine lokal installierte
15
+ * Schrift dieses Namens). Werte aus `font`-Feldern lädt `pixl.widget()` von selbst.
16
+ */
17
+ export declare function loadFont(family: string): Promise<boolean>;
18
+ /** Namen aus allen `font`-Feldern eines Stands, auch aus Einträgen von Listen */
19
+ export declare function fontsOf(state: WidgetState | null): string[];
@@ -0,0 +1,2 @@
1
+ /** @internal */
2
+ export declare function startFrameBridge(): void;