@speechos/client 0.2.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/index.js ADDED
@@ -0,0 +1,259 @@
1
+ import { DEFAULT_HOST, events, events as events$1, getConfig, getConfig as getConfig$1, livekit, livekit as livekit$1, resetConfig, setConfig, setConfig as setConfig$1, state, state as state$1, transcriptStore, updateUserId } from "@speechos/core";
2
+
3
+ //#region src/form-detector.ts
4
+ /**
5
+ * Check if an element is a form field that we should track
6
+ */
7
+ function isFormField(element) {
8
+ if (!element || !(element instanceof HTMLElement)) return false;
9
+ const tagName = element.tagName.toLowerCase();
10
+ if (tagName === "input" || tagName === "textarea") {
11
+ if (tagName === "input") {
12
+ const type = element.type.toLowerCase();
13
+ const excludedTypes = [
14
+ "checkbox",
15
+ "radio",
16
+ "submit",
17
+ "button",
18
+ "reset",
19
+ "file",
20
+ "hidden"
21
+ ];
22
+ if (excludedTypes.includes(type)) return false;
23
+ }
24
+ return true;
25
+ }
26
+ if (element.isContentEditable || element.getAttribute("contenteditable") === "true") return true;
27
+ return false;
28
+ }
29
+ /**
30
+ * Form detector class that manages focus tracking
31
+ */
32
+ var FormDetector = class {
33
+ isActive = false;
34
+ focusHandler = null;
35
+ blurHandler = null;
36
+ /**
37
+ * Start detecting form field focus events
38
+ */
39
+ start() {
40
+ if (this.isActive) {
41
+ console.warn("FormDetector is already active");
42
+ return;
43
+ }
44
+ this.focusHandler = (event) => {
45
+ const target = event.target;
46
+ if (isFormField(target)) {
47
+ state$1.setFocusedElement(target);
48
+ state$1.show();
49
+ events$1.emit("form:focus", { element: target });
50
+ }
51
+ };
52
+ this.blurHandler = (event) => {
53
+ const target = event.target;
54
+ if (isFormField(target)) {
55
+ const relatedTarget = event.relatedTarget;
56
+ const widget = document.querySelector("speechos-widget");
57
+ const goingToFormField = isFormField(relatedTarget);
58
+ const goingToWidget = widget && (widget.contains(relatedTarget) || widget.shadowRoot?.contains(relatedTarget) || relatedTarget === widget);
59
+ if (goingToFormField || goingToWidget) return;
60
+ setTimeout(() => {
61
+ const activeElement = document.activeElement;
62
+ const isWidgetFocused = widget && (widget.contains(activeElement) || widget.shadowRoot?.contains(activeElement));
63
+ if (!isFormField(activeElement) && !isWidgetFocused) {
64
+ state$1.setFocusedElement(null);
65
+ state$1.hide();
66
+ events$1.emit("form:blur", { element: null });
67
+ }
68
+ }, 150);
69
+ }
70
+ };
71
+ document.addEventListener("focusin", this.focusHandler, true);
72
+ document.addEventListener("focusout", this.blurHandler, true);
73
+ this.isActive = true;
74
+ }
75
+ /**
76
+ * Stop detecting form field focus events
77
+ */
78
+ stop() {
79
+ if (!this.isActive) return;
80
+ if (this.focusHandler) {
81
+ document.removeEventListener("focusin", this.focusHandler, true);
82
+ this.focusHandler = null;
83
+ }
84
+ if (this.blurHandler) {
85
+ document.removeEventListener("focusout", this.blurHandler, true);
86
+ this.blurHandler = null;
87
+ }
88
+ state$1.setFocusedElement(null);
89
+ state$1.hide();
90
+ this.isActive = false;
91
+ }
92
+ /**
93
+ * Check if the detector is currently active
94
+ */
95
+ get active() {
96
+ return this.isActive;
97
+ }
98
+ };
99
+ const formDetector = new FormDetector();
100
+
101
+ //#endregion
102
+ //#region src/speechos.ts
103
+ /**
104
+ * Main SpeechOS class for initializing and managing the SDK with UI
105
+ */
106
+ var SpeechOS = class SpeechOS {
107
+ static instance = null;
108
+ static widgetElement = null;
109
+ static isInitialized = false;
110
+ /**
111
+ * Initialize the SpeechOS SDK
112
+ * @param config - Configuration options
113
+ * @returns Promise that resolves when initialization is complete
114
+ * @throws Error if configuration is invalid (e.g., missing apiKey)
115
+ */
116
+ static async init(config = {}) {
117
+ if (this.isInitialized) {
118
+ console.warn("SpeechOS is already initialized");
119
+ return;
120
+ }
121
+ try {
122
+ setConfig$1(config);
123
+ } catch (error) {
124
+ const errorMessage = error instanceof Error ? error.message : "Invalid configuration";
125
+ console.error(`[SpeechOS] Error: ${errorMessage} (init_config)`);
126
+ events$1.emit("error", {
127
+ code: "init_config",
128
+ message: errorMessage,
129
+ source: "init"
130
+ });
131
+ throw error;
132
+ }
133
+ const finalConfig = getConfig$1();
134
+ this.instance = new SpeechOS();
135
+ try {
136
+ if (finalConfig.debug) console.log("[SpeechOS] Fetching LiveKit token...");
137
+ await livekit$1.fetchToken();
138
+ if (finalConfig.debug) console.log("[SpeechOS] LiveKit token fetched successfully");
139
+ } catch (error) {
140
+ const errorMessage = error instanceof Error ? error.message : "Failed to fetch token";
141
+ console.error(`[SpeechOS] Error: ${errorMessage} (init_token_fetch)`);
142
+ events$1.emit("error", {
143
+ code: "init_token_fetch",
144
+ message: errorMessage,
145
+ source: "init"
146
+ });
147
+ }
148
+ formDetector.start();
149
+ this.mountWidget();
150
+ this.isInitialized = true;
151
+ if (finalConfig.debug) console.log("[SpeechOS] Initialized with config:", finalConfig);
152
+ }
153
+ /**
154
+ * Destroy the SpeechOS SDK and clean up resources
155
+ */
156
+ static async destroy() {
157
+ if (!this.isInitialized) {
158
+ console.warn("SpeechOS is not initialized");
159
+ return;
160
+ }
161
+ formDetector.stop();
162
+ await livekit$1.disconnect();
163
+ this.unmountWidget();
164
+ events$1.clear();
165
+ state$1.reset();
166
+ this.instance = null;
167
+ this.isInitialized = false;
168
+ const config = getConfig$1();
169
+ if (config.debug) console.log("[SpeechOS] Destroyed and cleaned up");
170
+ }
171
+ /**
172
+ * Check if SpeechOS is initialized
173
+ */
174
+ static get initialized() {
175
+ return this.isInitialized;
176
+ }
177
+ /**
178
+ * Get the current state
179
+ */
180
+ static getState() {
181
+ return state$1.getState();
182
+ }
183
+ /**
184
+ * Get the event emitter for external listeners
185
+ */
186
+ static get events() {
187
+ return events$1;
188
+ }
189
+ /**
190
+ * Mount the widget to the DOM
191
+ */
192
+ static mountWidget() {
193
+ if (this.widgetElement) {
194
+ console.warn("Widget is already mounted");
195
+ return;
196
+ }
197
+ const widget = document.createElement("speechos-widget");
198
+ this.widgetElement = widget;
199
+ document.body.appendChild(widget);
200
+ }
201
+ /**
202
+ * Unmount the widget from the DOM
203
+ */
204
+ static unmountWidget() {
205
+ if (this.widgetElement) {
206
+ this.widgetElement.remove();
207
+ this.widgetElement = null;
208
+ }
209
+ }
210
+ /**
211
+ * Show the widget programmatically
212
+ */
213
+ static show() {
214
+ state$1.show();
215
+ }
216
+ /**
217
+ * Hide the widget programmatically
218
+ */
219
+ static hide() {
220
+ state$1.hide();
221
+ }
222
+ /**
223
+ * Identify the current user
224
+ * Can be called after init() to associate sessions with a user identifier.
225
+ * Clears the cached token so the next voice session uses the new userId.
226
+ *
227
+ * @param userId - User identifier from your system (e.g., user ID, email)
228
+ *
229
+ * @example
230
+ * // Initialize SDK early
231
+ * SpeechOS.init({ apiKey: 'xxx' });
232
+ *
233
+ * // Later, after user logs in
234
+ * SpeechOS.identify('user_123');
235
+ */
236
+ static identify(userId) {
237
+ if (!this.isInitialized) {
238
+ console.warn("SpeechOS.identify() called before init(). Call init() first.");
239
+ return;
240
+ }
241
+ const config = getConfig$1();
242
+ updateUserId(userId);
243
+ livekit$1.clearToken();
244
+ if (config.debug) console.log(`[SpeechOS] User identified: ${userId}`);
245
+ }
246
+ /**
247
+ * Private constructor to prevent direct instantiation
248
+ */
249
+ constructor() {}
250
+ };
251
+
252
+ //#endregion
253
+ //#region src/index.ts
254
+ const VERSION = "0.1.0";
255
+ var src_default = SpeechOS;
256
+
257
+ //#endregion
258
+ export { DEFAULT_HOST, FormDetector, SpeechOS, VERSION, src_default as default, events, formDetector, getConfig, livekit, resetConfig, setConfig, state, transcriptStore };
259
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["element: Element | null","event: FocusEvent","formDetector: FormDetector","config: SpeechOSConfig","events","userId: string","SpeechOSClass"],"sources":["../src/form-detector.ts","../src/speechos.ts","../src/index.ts"],"sourcesContent":["/**\n * Form field focus detection for SpeechOS Client SDK\n * Detects when users focus on form fields and manages widget visibility\n */\n\nimport { events, state } from \"@speechos/core\";\n\n/**\n * Check if an element is a form field that we should track\n */\nfunction isFormField(element: Element | null): element is HTMLElement {\n if (!element || !(element instanceof HTMLElement)) {\n return false;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n // Check for input, textarea\n if (tagName === \"input\" || tagName === \"textarea\") {\n // Exclude certain input types that don't accept text\n if (tagName === \"input\") {\n const type = (element as HTMLInputElement).type.toLowerCase();\n const excludedTypes = [\n \"checkbox\",\n \"radio\",\n \"submit\",\n \"button\",\n \"reset\",\n \"file\",\n \"hidden\",\n ];\n if (excludedTypes.includes(type)) {\n return false;\n }\n }\n return true;\n }\n\n // Check for contenteditable\n if (\n element.isContentEditable ||\n element.getAttribute(\"contenteditable\") === \"true\"\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Form detector class that manages focus tracking\n */\nexport class FormDetector {\n private isActive = false;\n private focusHandler: ((event: FocusEvent) => void) | null = null;\n private blurHandler: ((event: FocusEvent) => void) | null = null;\n\n /**\n * Start detecting form field focus events\n */\n start(): void {\n if (this.isActive) {\n console.warn(\"FormDetector is already active\");\n return;\n }\n\n // Create event handlers\n this.focusHandler = (event: FocusEvent) => {\n const target = event.target as Element | null;\n\n if (isFormField(target)) {\n state.setFocusedElement(target);\n state.show();\n events.emit(\"form:focus\", { element: target });\n }\n };\n\n this.blurHandler = (event: FocusEvent) => {\n const target = event.target as Element | null;\n\n if (isFormField(target)) {\n // Check relatedTarget (where focus is going) immediately\n const relatedTarget = event.relatedTarget as Element | null;\n const widget = document.querySelector(\"speechos-widget\");\n\n // If focus is going to another form field or the widget, don't hide\n const goingToFormField = isFormField(relatedTarget);\n const goingToWidget =\n widget &&\n (widget.contains(relatedTarget) ||\n widget.shadowRoot?.contains(relatedTarget) ||\n relatedTarget === widget);\n\n if (goingToFormField || goingToWidget) {\n return;\n }\n\n // Delay hiding to allow for any edge cases\n setTimeout(() => {\n // Double-check: verify focus is still not on a form field or widget\n const activeElement = document.activeElement;\n const isWidgetFocused =\n widget &&\n (widget.contains(activeElement) ||\n widget.shadowRoot?.contains(activeElement));\n\n // Only hide if no form field is focused AND widget isn't focused\n if (!isFormField(activeElement) && !isWidgetFocused) {\n state.setFocusedElement(null);\n state.hide();\n events.emit(\"form:blur\", { element: null });\n }\n }, 150);\n }\n };\n\n // Attach listeners to document\n document.addEventListener(\"focusin\", this.focusHandler, true);\n document.addEventListener(\"focusout\", this.blurHandler, true);\n\n this.isActive = true;\n }\n\n /**\n * Stop detecting form field focus events\n */\n stop(): void {\n if (!this.isActive) {\n return;\n }\n\n // Remove event listeners\n if (this.focusHandler) {\n document.removeEventListener(\"focusin\", this.focusHandler, true);\n this.focusHandler = null;\n }\n\n if (this.blurHandler) {\n document.removeEventListener(\"focusout\", this.blurHandler, true);\n this.blurHandler = null;\n }\n\n // Reset state\n state.setFocusedElement(null);\n state.hide();\n\n this.isActive = false;\n }\n\n /**\n * Check if the detector is currently active\n */\n get active(): boolean {\n return this.isActive;\n }\n}\n\n// Export singleton instance\nexport const formDetector: FormDetector = new FormDetector();\n","/**\n * Main SpeechOS Client SDK class\n * Composes core logic with UI components\n */\n\nimport type { SpeechOSConfig, SpeechOSState, SpeechOSEventMap } from \"@speechos/core\";\nimport {\n setConfig,\n getConfig,\n updateUserId,\n state,\n events,\n livekit,\n SpeechOSEventEmitter,\n} from \"@speechos/core\";\nimport { formDetector } from \"./form-detector.js\";\nimport \"./ui/index.js\"; // Auto-registers components\n\n/**\n * Main SpeechOS class for initializing and managing the SDK with UI\n */\nexport class SpeechOS {\n private static instance: SpeechOS | null = null;\n private static widgetElement: HTMLElement | null = null;\n private static isInitialized = false;\n\n /**\n * Initialize the SpeechOS SDK\n * @param config - Configuration options\n * @returns Promise that resolves when initialization is complete\n * @throws Error if configuration is invalid (e.g., missing apiKey)\n */\n static async init(config: SpeechOSConfig = {}): Promise<void> {\n if (this.isInitialized) {\n console.warn(\"SpeechOS is already initialized\");\n return;\n }\n\n try {\n // Validate and set configuration\n setConfig(config);\n } catch (error) {\n // Configuration errors are fatal - log and re-throw\n const errorMessage =\n error instanceof Error ? error.message : \"Invalid configuration\";\n console.error(`[SpeechOS] Error: ${errorMessage} (init_config)`);\n\n // Emit error event before throwing\n events.emit(\"error\", {\n code: \"init_config\",\n message: errorMessage,\n source: \"init\",\n });\n\n throw error;\n }\n\n const finalConfig = getConfig();\n\n // Create singleton instance\n this.instance = new SpeechOS();\n\n // Fetch LiveKit token\n try {\n if (finalConfig.debug) {\n console.log(\"[SpeechOS] Fetching LiveKit token...\");\n }\n await livekit.fetchToken();\n if (finalConfig.debug) {\n console.log(\"[SpeechOS] LiveKit token fetched successfully\");\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Failed to fetch token\";\n console.error(`[SpeechOS] Error: ${errorMessage} (init_token_fetch)`);\n\n // Emit error event for consumers\n events.emit(\"error\", {\n code: \"init_token_fetch\",\n message: errorMessage,\n source: \"init\",\n });\n\n // Continue initialization even if token fetch fails\n // The token will be fetched again when needed\n }\n\n // Start form detection\n formDetector.start();\n\n // Create and mount widget\n this.mountWidget();\n\n this.isInitialized = true;\n\n // Log initialization in debug mode\n if (finalConfig.debug) {\n console.log(\"[SpeechOS] Initialized with config:\", finalConfig);\n }\n }\n\n /**\n * Destroy the SpeechOS SDK and clean up resources\n */\n static async destroy(): Promise<void> {\n if (!this.isInitialized) {\n console.warn(\"SpeechOS is not initialized\");\n return;\n }\n\n // Stop form detection\n formDetector.stop();\n\n // Disconnect from LiveKit (also clears token)\n await livekit.disconnect();\n\n // Remove widget from DOM\n this.unmountWidget();\n\n // Clear all event listeners\n events.clear();\n\n // Reset state\n state.reset();\n\n // Clear instance\n this.instance = null;\n this.isInitialized = false;\n\n const config = getConfig();\n if (config.debug) {\n console.log(\"[SpeechOS] Destroyed and cleaned up\");\n }\n }\n\n /**\n * Check if SpeechOS is initialized\n */\n static get initialized(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Get the current state\n */\n static getState(): SpeechOSState {\n return state.getState();\n }\n\n /**\n * Get the event emitter for external listeners\n */\n static get events(): SpeechOSEventEmitter {\n return events;\n }\n\n /**\n * Mount the widget to the DOM\n */\n private static mountWidget(): void {\n if (this.widgetElement) {\n console.warn(\"Widget is already mounted\");\n return;\n }\n\n // Create widget element\n const widget = document.createElement(\"speechos-widget\");\n this.widgetElement = widget;\n\n // Append to body\n document.body.appendChild(widget);\n }\n\n /**\n * Unmount the widget from the DOM\n */\n private static unmountWidget(): void {\n if (this.widgetElement) {\n this.widgetElement.remove();\n this.widgetElement = null;\n }\n }\n\n /**\n * Show the widget programmatically\n */\n static show(): void {\n state.show();\n }\n\n /**\n * Hide the widget programmatically\n */\n static hide(): void {\n state.hide();\n }\n\n /**\n * Identify the current user\n * Can be called after init() to associate sessions with a user identifier.\n * Clears the cached token so the next voice session uses the new userId.\n *\n * @param userId - User identifier from your system (e.g., user ID, email)\n *\n * @example\n * // Initialize SDK early\n * SpeechOS.init({ apiKey: 'xxx' });\n *\n * // Later, after user logs in\n * SpeechOS.identify('user_123');\n */\n static identify(userId: string): void {\n if (!this.isInitialized) {\n console.warn(\n \"SpeechOS.identify() called before init(). Call init() first.\"\n );\n return;\n }\n\n const config = getConfig();\n\n // Update the userId in config\n updateUserId(userId);\n\n // Clear cached token so next session gets a fresh one with the new userId\n livekit.clearToken();\n\n if (config.debug) {\n console.log(`[SpeechOS] User identified: ${userId}`);\n }\n }\n\n /**\n * Private constructor to prevent direct instantiation\n */\n private constructor() {\n // Singleton pattern - use SpeechOS.init() instead\n }\n}\n\n// Export singleton class as default\nexport default SpeechOS;\n","/**\n * @speechos/client\n *\n * Vanilla JS client SDK for embedding SpeechOS into web applications.\n * Includes Web Components UI and DOM-based form detection.\n */\n\nimport { SpeechOS as SpeechOSClass } from \"./speechos.js\";\n\n// Re-export everything from core\nexport {\n events,\n state,\n getConfig,\n setConfig,\n resetConfig,\n livekit,\n transcriptStore,\n DEFAULT_HOST,\n} from \"@speechos/core\";\n\nexport type {\n SpeechOSConfig,\n SpeechOSState,\n SpeechOSAction,\n SpeechOSEventMap,\n StateChangeCallback,\n UnsubscribeFn,\n RecordingState,\n TranscriptEntry,\n TranscriptAction,\n} from \"@speechos/core\";\n\n// Client-specific exports\nexport { formDetector, FormDetector } from \"./form-detector.js\";\n\n// Version\nexport const VERSION = \"0.1.0\";\n\n// Main SDK class\nexport { SpeechOSClass as SpeechOS };\nexport default SpeechOSClass;\n"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Main SpeechOS Client SDK class
3
+ * Composes core logic with UI components
4
+ */
5
+ import type { SpeechOSConfig, SpeechOSState } from "@speechos/core";
6
+ import { SpeechOSEventEmitter } from "@speechos/core";
7
+ import "./ui/index.js";
8
+ /**
9
+ * Main SpeechOS class for initializing and managing the SDK with UI
10
+ */
11
+ export declare class SpeechOS {
12
+ private static instance;
13
+ private static widgetElement;
14
+ private static isInitialized;
15
+ /**
16
+ * Initialize the SpeechOS SDK
17
+ * @param config - Configuration options
18
+ * @returns Promise that resolves when initialization is complete
19
+ * @throws Error if configuration is invalid (e.g., missing apiKey)
20
+ */
21
+ static init(config?: SpeechOSConfig): Promise<void>;
22
+ /**
23
+ * Destroy the SpeechOS SDK and clean up resources
24
+ */
25
+ static destroy(): Promise<void>;
26
+ /**
27
+ * Check if SpeechOS is initialized
28
+ */
29
+ static get initialized(): boolean;
30
+ /**
31
+ * Get the current state
32
+ */
33
+ static getState(): SpeechOSState;
34
+ /**
35
+ * Get the event emitter for external listeners
36
+ */
37
+ static get events(): SpeechOSEventEmitter;
38
+ /**
39
+ * Mount the widget to the DOM
40
+ */
41
+ private static mountWidget;
42
+ /**
43
+ * Unmount the widget from the DOM
44
+ */
45
+ private static unmountWidget;
46
+ /**
47
+ * Show the widget programmatically
48
+ */
49
+ static show(): void;
50
+ /**
51
+ * Hide the widget programmatically
52
+ */
53
+ static hide(): void;
54
+ /**
55
+ * Identify the current user
56
+ * Can be called after init() to associate sessions with a user identifier.
57
+ * Clears the cached token so the next voice session uses the new userId.
58
+ *
59
+ * @param userId - User identifier from your system (e.g., user ID, email)
60
+ *
61
+ * @example
62
+ * // Initialize SDK early
63
+ * SpeechOS.init({ apiKey: 'xxx' });
64
+ *
65
+ * // Later, after user logs in
66
+ * SpeechOS.identify('user_123');
67
+ */
68
+ static identify(userId: string): void;
69
+ /**
70
+ * Private constructor to prevent direct instantiation
71
+ */
72
+ private constructor();
73
+ }
74
+ export default SpeechOS;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Main SpeechOS Client SDK class
3
+ * Composes core logic with UI components
4
+ */
5
+ import type { SpeechOSConfig, SpeechOSState } from "@speechos/core";
6
+ import { SpeechOSEventEmitter } from "@speechos/core";
7
+ import "./ui/index.js";
8
+ /**
9
+ * Main SpeechOS class for initializing and managing the SDK with UI
10
+ */
11
+ export declare class SpeechOS {
12
+ private static instance;
13
+ private static widgetElement;
14
+ private static isInitialized;
15
+ /**
16
+ * Initialize the SpeechOS SDK
17
+ * @param config - Configuration options
18
+ * @returns Promise that resolves when initialization is complete
19
+ * @throws Error if configuration is invalid (e.g., missing apiKey)
20
+ */
21
+ static init(config?: SpeechOSConfig): Promise<void>;
22
+ /**
23
+ * Destroy the SpeechOS SDK and clean up resources
24
+ */
25
+ static destroy(): Promise<void>;
26
+ /**
27
+ * Check if SpeechOS is initialized
28
+ */
29
+ static get initialized(): boolean;
30
+ /**
31
+ * Get the current state
32
+ */
33
+ static getState(): SpeechOSState;
34
+ /**
35
+ * Get the event emitter for external listeners
36
+ */
37
+ static get events(): SpeechOSEventEmitter;
38
+ /**
39
+ * Mount the widget to the DOM
40
+ */
41
+ private static mountWidget;
42
+ /**
43
+ * Unmount the widget from the DOM
44
+ */
45
+ private static unmountWidget;
46
+ /**
47
+ * Show the widget programmatically
48
+ */
49
+ static show(): void;
50
+ /**
51
+ * Hide the widget programmatically
52
+ */
53
+ static hide(): void;
54
+ /**
55
+ * Identify the current user
56
+ * Can be called after init() to associate sessions with a user identifier.
57
+ * Clears the cached token so the next voice session uses the new userId.
58
+ *
59
+ * @param userId - User identifier from your system (e.g., user ID, email)
60
+ *
61
+ * @example
62
+ * // Initialize SDK early
63
+ * SpeechOS.init({ apiKey: 'xxx' });
64
+ *
65
+ * // Later, after user logs in
66
+ * SpeechOS.identify('user_123');
67
+ */
68
+ static identify(userId: string): void;
69
+ /**
70
+ * Private constructor to prevent direct instantiation
71
+ */
72
+ private constructor();
73
+ }
74
+ export default SpeechOS;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Action bubbles component
3
+ * Displays available actions (Dictate, Edit) above the mic button
4
+ */
5
+ import { LitElement, type CSSResultGroup } from "lit";
6
+ export declare class SpeechOSActionBubbles extends LitElement {
7
+ static styles: CSSResultGroup;
8
+ visible: boolean;
9
+ private actions;
10
+ private handleActionClick;
11
+ render(): import("lit").TemplateResult | string;
12
+ }
13
+ declare global {
14
+ interface HTMLElementTagNameMap {
15
+ "speechos-action-bubbles": SpeechOSActionBubbles;
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Action bubbles component
3
+ * Displays available actions (Dictate, Edit) above the mic button
4
+ */
5
+ import { LitElement, type CSSResultGroup } from "lit";
6
+ export declare class SpeechOSActionBubbles extends LitElement {
7
+ static styles: CSSResultGroup;
8
+ visible: boolean;
9
+ private actions;
10
+ private handleActionClick;
11
+ render(): import("lit").TemplateResult | string;
12
+ }
13
+ declare global {
14
+ interface HTMLElementTagNameMap {
15
+ "speechos-action-bubbles": SpeechOSActionBubbles;
16
+ }
17
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Icon imports and templates using inline SVG
3
+ */
4
+ import { type TemplateResult } from "lit";
5
+ /**
6
+ * Microphone icon for the main button
7
+ * Lucide Mic icon paths
8
+ */
9
+ export declare const micIcon: (size?: number) => TemplateResult;
10
+ /**
11
+ * Message square icon for dictate action
12
+ * Lucide MessageSquare icon paths
13
+ */
14
+ export declare const dictateIcon: (size?: number) => TemplateResult;
15
+ /**
16
+ * Pencil icon for edit action
17
+ * Lucide Pencil icon paths
18
+ */
19
+ export declare const editIcon: (size?: number) => TemplateResult;
20
+ /**
21
+ * Stop/Square icon for stopping recording
22
+ * Lucide Square icon (filled)
23
+ */
24
+ export declare const stopIcon: (size?: number) => TemplateResult;
25
+ /**
26
+ * Loader/spinner icon for connecting state
27
+ */
28
+ export declare const loaderIcon: (size?: number) => TemplateResult;
29
+ /**
30
+ * Check icon for "Keep" action
31
+ * Lucide Check icon paths
32
+ */
33
+ export declare const checkIcon: (size?: number) => TemplateResult;
34
+ /**
35
+ * Undo icon for "Undo" action
36
+ * Lucide Undo2 icon paths
37
+ */
38
+ export declare const undoIcon: (size?: number) => TemplateResult;
39
+ /**
40
+ * Refresh icon for "Continue editing" action
41
+ * Lucide RefreshCw icon paths
42
+ */
43
+ export declare const refreshIcon: (size?: number) => TemplateResult;
44
+ /**
45
+ * X icon for cancel action
46
+ * Lucide X icon paths
47
+ */
48
+ export declare const xIcon: (size?: number) => TemplateResult;
49
+ /**
50
+ * More vertical (three dots) icon for settings button
51
+ * Lucide MoreVertical icon paths
52
+ */
53
+ export declare const moreVerticalIcon: (size?: number) => TemplateResult;
54
+ /**
55
+ * Clipboard/list icon for transcripts tab
56
+ * Lucide ClipboardList icon paths
57
+ */
58
+ export declare const clipboardIcon: (size?: number) => TemplateResult;
59
+ /**
60
+ * Help circle icon for help tab
61
+ * Lucide HelpCircle icon paths
62
+ */
63
+ export declare const helpCircleIcon: (size?: number) => TemplateResult;
64
+ /**
65
+ * Info icon for about tab
66
+ * Lucide Info icon paths
67
+ */
68
+ export declare const infoIcon: (size?: number) => TemplateResult;
69
+ /**
70
+ * Settings/cog icon for settings tab
71
+ * Lucide Settings icon paths
72
+ */
73
+ export declare const settingsIcon: (size?: number) => TemplateResult;
74
+ /**
75
+ * Trash icon for delete action
76
+ * Lucide Trash2 icon paths
77
+ */
78
+ export declare const trashIcon: (size?: number) => TemplateResult;
79
+ /**
80
+ * External link icon
81
+ * Lucide ExternalLink icon paths
82
+ */
83
+ export declare const externalLinkIcon: (size?: number) => TemplateResult;
84
+ /**
85
+ * Copy icon
86
+ * Lucide Copy icon paths
87
+ */
88
+ export declare const copyIcon: (size?: number) => TemplateResult;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Icon imports and templates using inline SVG
3
+ */
4
+ import { type TemplateResult } from "lit";
5
+ /**
6
+ * Microphone icon for the main button
7
+ * Lucide Mic icon paths
8
+ */
9
+ export declare const micIcon: (size?: number) => TemplateResult;
10
+ /**
11
+ * Message square icon for dictate action
12
+ * Lucide MessageSquare icon paths
13
+ */
14
+ export declare const dictateIcon: (size?: number) => TemplateResult;
15
+ /**
16
+ * Pencil icon for edit action
17
+ * Lucide Pencil icon paths
18
+ */
19
+ export declare const editIcon: (size?: number) => TemplateResult;
20
+ /**
21
+ * Stop/Square icon for stopping recording
22
+ * Lucide Square icon (filled)
23
+ */
24
+ export declare const stopIcon: (size?: number) => TemplateResult;
25
+ /**
26
+ * Loader/spinner icon for connecting state
27
+ */
28
+ export declare const loaderIcon: (size?: number) => TemplateResult;
29
+ /**
30
+ * Check icon for "Keep" action
31
+ * Lucide Check icon paths
32
+ */
33
+ export declare const checkIcon: (size?: number) => TemplateResult;
34
+ /**
35
+ * Undo icon for "Undo" action
36
+ * Lucide Undo2 icon paths
37
+ */
38
+ export declare const undoIcon: (size?: number) => TemplateResult;
39
+ /**
40
+ * Refresh icon for "Continue editing" action
41
+ * Lucide RefreshCw icon paths
42
+ */
43
+ export declare const refreshIcon: (size?: number) => TemplateResult;
44
+ /**
45
+ * X icon for cancel action
46
+ * Lucide X icon paths
47
+ */
48
+ export declare const xIcon: (size?: number) => TemplateResult;
49
+ /**
50
+ * More vertical (three dots) icon for settings button
51
+ * Lucide MoreVertical icon paths
52
+ */
53
+ export declare const moreVerticalIcon: (size?: number) => TemplateResult;
54
+ /**
55
+ * Clipboard/list icon for transcripts tab
56
+ * Lucide ClipboardList icon paths
57
+ */
58
+ export declare const clipboardIcon: (size?: number) => TemplateResult;
59
+ /**
60
+ * Help circle icon for help tab
61
+ * Lucide HelpCircle icon paths
62
+ */
63
+ export declare const helpCircleIcon: (size?: number) => TemplateResult;
64
+ /**
65
+ * Info icon for about tab
66
+ * Lucide Info icon paths
67
+ */
68
+ export declare const infoIcon: (size?: number) => TemplateResult;
69
+ /**
70
+ * Settings/cog icon for settings tab
71
+ * Lucide Settings icon paths
72
+ */
73
+ export declare const settingsIcon: (size?: number) => TemplateResult;
74
+ /**
75
+ * Trash icon for delete action
76
+ * Lucide Trash2 icon paths
77
+ */
78
+ export declare const trashIcon: (size?: number) => TemplateResult;
79
+ /**
80
+ * External link icon
81
+ * Lucide ExternalLink icon paths
82
+ */
83
+ export declare const externalLinkIcon: (size?: number) => TemplateResult;
84
+ /**
85
+ * Copy icon
86
+ * Lucide Copy icon paths
87
+ */
88
+ export declare const copyIcon: (size?: number) => TemplateResult;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * UI module exports
3
+ * Lit-based Shadow DOM components
4
+ */
5
+ import "./widget.js";
6
+ import "./mic-button.js";
7
+ import "./action-bubbles.js";
8
+ import "./settings-button.js";
9
+ import "./settings-modal.js";
10
+ export { SpeechOSWidget } from "./widget.js";
11
+ export { SpeechOSMicButton } from "./mic-button.js";
12
+ export { SpeechOSActionBubbles } from "./action-bubbles.js";
13
+ export { SpeechOSSettingsButton } from "./settings-button.js";
14
+ export { SpeechOSSettingsModal } from "./settings-modal.js";
15
+ /**
16
+ * Register all custom elements
17
+ * This is automatically called when importing this module,
18
+ * but can be called explicitly if needed
19
+ */
20
+ export declare function registerComponents(): void;