@corti/embedded-web 0.1.0-alpha.1

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +273 -0
  3. package/dist/CortiEmbedded.d.ts +102 -0
  4. package/dist/CortiEmbedded.js +452 -0
  5. package/dist/CortiEmbedded.js.map +1 -0
  6. package/dist/bundle.js +96 -0
  7. package/dist/corti-embedded.d.ts +1 -0
  8. package/dist/corti-embedded.js +5 -0
  9. package/dist/corti-embedded.js.map +1 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.js +5 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/internal-types.d.ts +231 -0
  14. package/dist/internal-types.js +2 -0
  15. package/dist/internal-types.js.map +1 -0
  16. package/dist/public-types.d.ts +238 -0
  17. package/dist/public-types.js +2 -0
  18. package/dist/public-types.js.map +1 -0
  19. package/dist/react/CortiEmbeddedReact.d.ts +25 -0
  20. package/dist/react/CortiEmbeddedReact.js +28 -0
  21. package/dist/react/CortiEmbeddedReact.js.map +1 -0
  22. package/dist/react/index.d.ts +2 -0
  23. package/dist/react/index.js +2 -0
  24. package/dist/react/index.js.map +1 -0
  25. package/dist/styles/base.d.ts +4 -0
  26. package/dist/styles/base.js +10 -0
  27. package/dist/styles/base.js.map +1 -0
  28. package/dist/styles/container-styles.d.ts +1 -0
  29. package/dist/styles/container-styles.js +35 -0
  30. package/dist/styles/container-styles.js.map +1 -0
  31. package/dist/styles/theme.d.ts +2 -0
  32. package/dist/styles/theme.js +101 -0
  33. package/dist/styles/theme.js.map +1 -0
  34. package/dist/tsconfig.tsbuildinfo +1 -0
  35. package/dist/utils/PostMessageHandler.d.ts +119 -0
  36. package/dist/utils/PostMessageHandler.js +353 -0
  37. package/dist/utils/PostMessageHandler.js.map +1 -0
  38. package/dist/utils/baseUrl.d.ts +1 -0
  39. package/dist/utils/baseUrl.js +25 -0
  40. package/dist/utils/baseUrl.js.map +1 -0
  41. package/dist/utils/embedUrl.d.ts +2 -0
  42. package/dist/utils/embedUrl.js +23 -0
  43. package/dist/utils/embedUrl.js.map +1 -0
  44. package/dist/utils/errorFormatter.d.ts +10 -0
  45. package/dist/utils/errorFormatter.js +163 -0
  46. package/dist/utils/errorFormatter.js.map +1 -0
  47. package/dist/web-bundle.js +89 -0
  48. package/dist/web-index.d.ts +3 -0
  49. package/dist/web-index.js +3 -0
  50. package/dist/web-index.js.map +1 -0
  51. package/package.json +129 -0
@@ -0,0 +1,452 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, LitElement } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { baseStyles } from './styles/base.js';
10
+ import { containerStyles } from './styles/container-styles.js';
11
+ import { validateAndNormalizeBaseURL } from './utils/baseUrl.js';
12
+ import { buildEmbeddedUrl, isRealEmbeddedLoad } from './utils/embedUrl.js';
13
+ import { formatError } from './utils/errorFormatter.js';
14
+ import { PostMessageHandler, } from './utils/PostMessageHandler.js';
15
+ export class CortiEmbedded extends LitElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.visibility = 'hidden';
19
+ this.postMessageHandler = null;
20
+ this.normalizedBaseURL = null;
21
+ }
22
+ connectedCallback() {
23
+ super.connectedCallback();
24
+ // Ensure baseURL is provided
25
+ if (!this.baseURL) {
26
+ this.dispatchErrorEvent({
27
+ message: 'baseURL is required',
28
+ });
29
+ return;
30
+ }
31
+ // Validate and normalize the initial baseURL early (fail fast)
32
+ try {
33
+ this.normalizedBaseURL = validateAndNormalizeBaseURL(this.baseURL);
34
+ }
35
+ catch (error) {
36
+ this.dispatchErrorEvent({
37
+ message: error.message || 'Invalid baseURL',
38
+ });
39
+ throw error;
40
+ }
41
+ }
42
+ disconnectedCallback() {
43
+ super.disconnectedCallback();
44
+ if (this.postMessageHandler) {
45
+ this.postMessageHandler.destroy();
46
+ this.postMessageHandler = null;
47
+ }
48
+ }
49
+ async setupPostMessageHandler() {
50
+ // Prevent multiple setups
51
+ if (this.postMessageHandler) {
52
+ return;
53
+ }
54
+ const iframe = this.getIframe();
55
+ if (iframe?.contentWindow) {
56
+ const callbacks = {
57
+ onReady: () => {
58
+ this.dispatchPublicEvent('ready', undefined);
59
+ },
60
+ onAuthChanged: payload => {
61
+ this.dispatchPublicEvent('auth-changed', { user: payload.user });
62
+ },
63
+ onInteractionCreated: payload => {
64
+ this.dispatchPublicEvent('interaction-created', {
65
+ interaction: payload.interaction,
66
+ });
67
+ },
68
+ onRecordingStarted: () => {
69
+ this.dispatchPublicEvent('recording-started', undefined);
70
+ },
71
+ onRecordingStopped: () => {
72
+ this.dispatchPublicEvent('recording-stopped', undefined);
73
+ },
74
+ onDocumentGenerated: payload => {
75
+ this.dispatchPublicEvent('document-generated', {
76
+ document: payload.document,
77
+ });
78
+ },
79
+ onDocumentUpdated: payload => {
80
+ this.dispatchPublicEvent('document-updated', {
81
+ document: payload.document,
82
+ });
83
+ },
84
+ onNavigationChanged: payload => {
85
+ this.dispatchPublicEvent('navigation-changed', {
86
+ path: payload.path,
87
+ });
88
+ },
89
+ onUsage: payload => {
90
+ this.dispatchPublicEvent('usage', {
91
+ creditsConsumed: payload.creditsConsumed,
92
+ });
93
+ },
94
+ onError: error => {
95
+ this.dispatchErrorEvent(error);
96
+ },
97
+ };
98
+ this.postMessageHandler = new PostMessageHandler(iframe, callbacks);
99
+ }
100
+ else {
101
+ this.dispatchErrorEvent({
102
+ message: 'No iframe or contentWindow available',
103
+ });
104
+ }
105
+ }
106
+ dispatchPublicEvent(event, data) {
107
+ this.dispatchEvent(new CustomEvent(event, { detail: data }));
108
+ }
109
+ dispatchErrorEvent(error) {
110
+ this.dispatchPublicEvent('error', error);
111
+ }
112
+ isRealIframeLoad(iframe) {
113
+ const src = iframe.getAttribute('src') || '';
114
+ if (!this.normalizedBaseURL)
115
+ return false;
116
+ return isRealEmbeddedLoad(src, this.normalizedBaseURL);
117
+ }
118
+ async handleIframeLoad(event) {
119
+ const iframe = event.target;
120
+ if (!iframe) {
121
+ return;
122
+ }
123
+ // Only initialize on real URL load, ignore about:blank
124
+ if (!this.isRealIframeLoad(iframe)) {
125
+ return;
126
+ }
127
+ try {
128
+ await this.setupPostMessageHandler();
129
+ }
130
+ catch (error) {
131
+ this.dispatchErrorEvent({
132
+ message: `Failed to setup PostMessageHandler on iframe load: ${error}`,
133
+ });
134
+ }
135
+ }
136
+ getIframe() {
137
+ return this.shadowRoot?.querySelector('iframe') || null;
138
+ }
139
+ updated(changedProps) {
140
+ super.updated(changedProps);
141
+ if (changedProps.has('baseURL')) {
142
+ // Validate baseURL and normalize; fail fast on invalid input
143
+ try {
144
+ this.normalizedBaseURL = validateAndNormalizeBaseURL(this.baseURL);
145
+ }
146
+ catch (error) {
147
+ // Tear down and clear iframe to avoid keeping an old origin active
148
+ if (this.postMessageHandler) {
149
+ this.postMessageHandler.destroy();
150
+ this.postMessageHandler = null;
151
+ }
152
+ const iframe = this.getIframe();
153
+ if (iframe) {
154
+ iframe.setAttribute('src', 'about:blank');
155
+ }
156
+ this.dispatchErrorEvent({
157
+ message: error.message || 'Invalid baseURL',
158
+ });
159
+ return;
160
+ }
161
+ // Tear down existing handler and re-point iframe to new URL
162
+ if (this.postMessageHandler) {
163
+ this.postMessageHandler.destroy();
164
+ this.postMessageHandler = null;
165
+ }
166
+ const iframe = this.getIframe();
167
+ if (iframe) {
168
+ const expected = this.normalizedBaseURL
169
+ ? buildEmbeddedUrl(this.normalizedBaseURL)
170
+ : '';
171
+ if (iframe.getAttribute('src') !== expected) {
172
+ iframe.setAttribute('src', expected);
173
+ iframe.setAttribute('allow', `microphone ${expected}; camera ${expected}; device-capture ${expected}; display-capture ${expected}`);
174
+ }
175
+ }
176
+ }
177
+ }
178
+ // Public API Implementation
179
+ /**
180
+ * Authenticate with the Corti system
181
+ * @param credentials Authentication credentials
182
+ * @returns Promise resolving to user information
183
+ */
184
+ async auth(credentials) {
185
+ if (!this.postMessageHandler) {
186
+ throw new Error('Component not ready');
187
+ }
188
+ try {
189
+ const payload = {
190
+ access_token: credentials.access_token,
191
+ token_type: credentials.token_type,
192
+ expires_at: credentials.expires_at,
193
+ expires_in: credentials.expires_in,
194
+ refresh_expires_in: credentials.refresh_expires_in,
195
+ refresh_token: credentials.refresh_token,
196
+ id_token: credentials.id_token,
197
+ 'not-before-policy': credentials['not-before-policy'],
198
+ session_state: credentials.session_state,
199
+ scope: credentials.scope,
200
+ profile: credentials.profile,
201
+ mode: credentials.mode,
202
+ };
203
+ const user = await this.postMessageHandler.auth(payload);
204
+ return user;
205
+ }
206
+ catch (error) {
207
+ const formattedError = formatError(error, 'Authentication failed');
208
+ this.dispatchErrorEvent(formattedError);
209
+ throw new Error(JSON.stringify(formattedError));
210
+ }
211
+ }
212
+ /**
213
+ * Create a new interaction
214
+ * @param encounter Encounter request data
215
+ * @returns Promise resolving to interaction details
216
+ */
217
+ async createInteraction(encounter) {
218
+ if (!this.postMessageHandler) {
219
+ throw new Error('Component not ready');
220
+ }
221
+ try {
222
+ const response = await this.postMessageHandler.createInteraction(encounter);
223
+ return {
224
+ id: response.id,
225
+ createdAt: response.createdAt,
226
+ };
227
+ }
228
+ catch (error) {
229
+ const formattedError = formatError(error, 'Failed to create interaction');
230
+ this.dispatchErrorEvent(formattedError);
231
+ throw new Error(JSON.stringify(formattedError));
232
+ }
233
+ }
234
+ /**
235
+ * Configure the current session
236
+ * @param config Session configuration
237
+ * @returns Promise that resolves when configuration is complete
238
+ */
239
+ async configureSession(config) {
240
+ if (!this.postMessageHandler) {
241
+ throw new Error('Component not ready');
242
+ }
243
+ try {
244
+ const payload = {
245
+ defaultLanguage: config.defaultLanguage,
246
+ defaultOutputLanguage: config.defaultOutputLanguage,
247
+ defaultTemplateKey: config.defaultTemplateKey,
248
+ defaultMode: config.defaultMode,
249
+ };
250
+ await this.postMessageHandler.configureSession(payload);
251
+ }
252
+ catch (error) {
253
+ const formattedError = formatError(error, 'Failed to configure session');
254
+ this.dispatchErrorEvent(formattedError);
255
+ throw new Error(JSON.stringify(formattedError));
256
+ }
257
+ }
258
+ /**
259
+ * Add facts to the current session
260
+ * @param facts Array of facts to add
261
+ * @returns Promise that resolves when facts are added
262
+ */
263
+ async addFacts(facts) {
264
+ if (!this.postMessageHandler) {
265
+ throw new Error('Component not ready');
266
+ }
267
+ try {
268
+ const payload = { facts };
269
+ await this.postMessageHandler.addFacts(payload);
270
+ }
271
+ catch (error) {
272
+ const formattedError = formatError(error, 'Failed to add facts');
273
+ this.dispatchErrorEvent(formattedError);
274
+ throw new Error(JSON.stringify(formattedError));
275
+ }
276
+ }
277
+ /**
278
+ * Navigate to a specific path within the embedded UI
279
+ * @param path Path to navigate to
280
+ * @returns Promise that resolves when navigation is complete
281
+ */
282
+ async navigate(path) {
283
+ if (!this.postMessageHandler) {
284
+ throw new Error('Component not ready');
285
+ }
286
+ try {
287
+ const payload = { path };
288
+ await this.postMessageHandler.navigate(payload);
289
+ }
290
+ catch (error) {
291
+ const formattedError = formatError(error, 'Failed to navigate');
292
+ this.dispatchErrorEvent(formattedError);
293
+ throw new Error(JSON.stringify(formattedError));
294
+ }
295
+ }
296
+ /**
297
+ * Start recording
298
+ * @returns Promise that resolves when recording starts
299
+ */
300
+ async startRecording() {
301
+ if (!this.postMessageHandler) {
302
+ throw new Error('Component not ready');
303
+ }
304
+ try {
305
+ await this.postMessageHandler.startRecording();
306
+ }
307
+ catch (error) {
308
+ const formattedError = formatError(error, 'Failed to start recording');
309
+ this.dispatchErrorEvent(formattedError);
310
+ throw new Error(JSON.stringify(formattedError));
311
+ }
312
+ }
313
+ /**
314
+ * Stop recording
315
+ * @returns Promise that resolves when recording stops
316
+ */
317
+ async stopRecording() {
318
+ if (!this.postMessageHandler) {
319
+ throw new Error('Component not ready');
320
+ }
321
+ try {
322
+ await this.postMessageHandler.stopRecording();
323
+ }
324
+ catch (error) {
325
+ const formattedError = formatError(error, 'Failed to stop recording');
326
+ this.dispatchErrorEvent(formattedError);
327
+ throw new Error(JSON.stringify(formattedError));
328
+ }
329
+ }
330
+ /**
331
+ * Get current component status
332
+ * @returns Promise resolving to current status
333
+ */
334
+ async getStatus() {
335
+ if (!this.postMessageHandler) {
336
+ return {
337
+ ready: false,
338
+ auth: {
339
+ authenticated: false,
340
+ user: undefined,
341
+ },
342
+ currentUrl: undefined,
343
+ interaction: undefined,
344
+ };
345
+ }
346
+ try {
347
+ return await this.postMessageHandler.getStatus();
348
+ }
349
+ catch (error) {
350
+ const formattedError = formatError(error, 'Failed to get status');
351
+ this.dispatchErrorEvent(formattedError);
352
+ throw new Error(JSON.stringify(formattedError));
353
+ }
354
+ }
355
+ /**
356
+ * Configure the component
357
+ * @param config Component configuration
358
+ * @returns Promise that resolves when configuration is applied
359
+ */
360
+ async configure(config) {
361
+ if (!this.postMessageHandler) {
362
+ throw new Error('Component not ready');
363
+ }
364
+ try {
365
+ return await this.postMessageHandler.configure(config);
366
+ }
367
+ catch (error) {
368
+ const formattedError = formatError(error, 'Failed to configure component');
369
+ this.dispatchErrorEvent(formattedError);
370
+ throw new Error(JSON.stringify(formattedError));
371
+ }
372
+ }
373
+ /**
374
+ * Set authentication credentials without triggering auth flow
375
+ * @param credentials Authentication credentials to store
376
+ * @returns Promise that resolves when credentials are set
377
+ */
378
+ async setCredentials(credentials) {
379
+ if (!this.postMessageHandler) {
380
+ throw new Error('Component not ready');
381
+ }
382
+ try {
383
+ if (!credentials.password) {
384
+ throw new Error('Password is required');
385
+ }
386
+ await this.postMessageHandler.setCredentials(credentials);
387
+ }
388
+ catch (error) {
389
+ const formattedError = formatError(error, 'Failed to set credentials');
390
+ this.dispatchErrorEvent(formattedError);
391
+ throw new Error(JSON.stringify(formattedError));
392
+ }
393
+ }
394
+ /**
395
+ * Show the embedded UI
396
+ */
397
+ show() {
398
+ this.visibility = 'visible';
399
+ }
400
+ /**
401
+ * Hide the embedded UI
402
+ */
403
+ hide() {
404
+ this.visibility = 'hidden';
405
+ }
406
+ /**
407
+ * Check the current status of the iframe and PostMessageHandler
408
+ * Useful for debugging
409
+ * @deprecated Use getStatus() instead
410
+ */
411
+ getDebugStatus() {
412
+ const iframe = this.getIframe();
413
+ return {
414
+ ready: iframe?.contentDocument?.readyState === 'complete',
415
+ iframeExists: !!iframe,
416
+ iframeSrc: iframe?.src,
417
+ iframeContentWindow: !!iframe?.contentWindow,
418
+ iframeContentDocument: !!iframe?.contentDocument,
419
+ iframeReadyState: iframe?.contentDocument?.readyState,
420
+ postMessageHandlerExists: !!this.postMessageHandler,
421
+ postMessageHandlerReady: this.postMessageHandler?.ready || false,
422
+ baseURL: this.baseURL,
423
+ };
424
+ }
425
+ render() {
426
+ // Don't render if baseURL is not provided
427
+ if (!this.baseURL) {
428
+ return html `<div>baseURL is required</div>`;
429
+ }
430
+ return html `
431
+ <iframe
432
+ src=${buildEmbeddedUrl(validateAndNormalizeBaseURL(this.baseURL))}
433
+ title="Corti Embedded UI"
434
+ sandbox=${'allow-forms allow-modals allow-scripts allow-same-origin'}
435
+ allow="microphone *; camera *; device-capture *; display-capture *"
436
+ @load=${(event) => this.handleIframeLoad(event)}
437
+ @unload=${() => this.postMessageHandler?.destroy()}
438
+ style=${this.visibility === 'hidden'
439
+ ? 'display: none;'
440
+ : 'display: block;'}
441
+ ></iframe>
442
+ `;
443
+ }
444
+ }
445
+ CortiEmbedded.styles = [baseStyles, containerStyles];
446
+ __decorate([
447
+ property({ type: String, reflect: true })
448
+ ], CortiEmbedded.prototype, "visibility", void 0);
449
+ __decorate([
450
+ property({ type: String, reflect: true })
451
+ ], CortiEmbedded.prototype, "baseURL", void 0);
452
+ //# sourceMappingURL=CortiEmbedded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CortiEmbedded.js","sourceRoot":"","sources":["../src/CortiEmbedded.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport type { Corti } from '@corti/sdk';\nimport { html, LitElement, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport type {\n AddFactsPayload,\n AuthPayload,\n ConfigureAppPayload,\n ConfigureSessionPayload,\n NavigatePayload,\n SetCredentialsPayload,\n} from './internal-types.js';\nimport type {\n AuthCredentials,\n ComponentStatus,\n ConfigureAppResponsePayload,\n CortiEmbeddedAPI,\n EmbeddedEventData,\n InteractionDetails,\n InteractionPayload,\n SessionConfig,\n User,\n} from './public-types.js';\nimport { baseStyles } from './styles/base.js';\nimport { containerStyles } from './styles/container-styles.js';\nimport { validateAndNormalizeBaseURL } from './utils/baseUrl.js';\nimport { buildEmbeddedUrl, isRealEmbeddedLoad } from './utils/embedUrl.js';\nimport { formatError } from './utils/errorFormatter.js';\nimport {\n PostMessageHandler,\n type PostMessageHandlerCallbacks,\n} from './utils/PostMessageHandler.js';\n\nexport class CortiEmbedded extends LitElement implements CortiEmbeddedAPI {\n static styles = [baseStyles, containerStyles];\n\n @property({ type: String, reflect: true })\n visibility = 'hidden';\n\n @property({ type: String, reflect: true })\n baseURL!: string;\n\n private postMessageHandler: PostMessageHandler | null = null;\n\n private normalizedBaseURL: string | null = null;\n\n connectedCallback() {\n super.connectedCallback();\n\n // Ensure baseURL is provided\n if (!this.baseURL) {\n this.dispatchErrorEvent({\n message: 'baseURL is required',\n });\n return;\n }\n\n // Validate and normalize the initial baseURL early (fail fast)\n try {\n this.normalizedBaseURL = validateAndNormalizeBaseURL(this.baseURL);\n } catch (error) {\n this.dispatchErrorEvent({\n message: (error as Error).message || 'Invalid baseURL',\n });\n throw error;\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n if (this.postMessageHandler) {\n this.postMessageHandler.destroy();\n this.postMessageHandler = null;\n }\n }\n\n private async setupPostMessageHandler() {\n // Prevent multiple setups\n if (this.postMessageHandler) {\n return;\n }\n\n const iframe = this.getIframe();\n\n if (iframe?.contentWindow) {\n const callbacks: PostMessageHandlerCallbacks = {\n onReady: () => {\n this.dispatchPublicEvent('ready', undefined);\n },\n onAuthChanged: payload => {\n this.dispatchPublicEvent('auth-changed', { user: payload.user });\n },\n onInteractionCreated: payload => {\n this.dispatchPublicEvent('interaction-created', {\n interaction: payload.interaction,\n });\n },\n onRecordingStarted: () => {\n this.dispatchPublicEvent('recording-started', undefined);\n },\n onRecordingStopped: () => {\n this.dispatchPublicEvent('recording-stopped', undefined);\n },\n onDocumentGenerated: payload => {\n this.dispatchPublicEvent('document-generated', {\n document: payload.document,\n });\n },\n onDocumentUpdated: payload => {\n this.dispatchPublicEvent('document-updated', {\n document: payload.document,\n });\n },\n onNavigationChanged: payload => {\n this.dispatchPublicEvent('navigation-changed', {\n path: payload.path,\n });\n },\n onUsage: payload => {\n this.dispatchPublicEvent('usage', {\n creditsConsumed: payload.creditsConsumed,\n });\n },\n onError: error => {\n this.dispatchErrorEvent(error);\n },\n };\n\n this.postMessageHandler = new PostMessageHandler(iframe, callbacks);\n } else {\n this.dispatchErrorEvent({\n message: 'No iframe or contentWindow available',\n });\n }\n }\n\n private dispatchPublicEvent<K extends keyof EmbeddedEventData>(\n event: K,\n data: EmbeddedEventData[K],\n ) {\n this.dispatchEvent(new CustomEvent(event, { detail: data }));\n }\n\n private dispatchErrorEvent(error: {\n message: string;\n code?: string;\n details?: unknown;\n }) {\n this.dispatchPublicEvent('error', error);\n }\n\n private isRealIframeLoad(iframe: HTMLIFrameElement): boolean {\n const src = iframe.getAttribute('src') || '';\n if (!this.normalizedBaseURL) return false;\n return isRealEmbeddedLoad(src, this.normalizedBaseURL);\n }\n\n private async handleIframeLoad(event: Event) {\n const iframe = event.target as HTMLIFrameElement | null;\n if (!iframe) {\n return;\n }\n // Only initialize on real URL load, ignore about:blank\n if (!this.isRealIframeLoad(iframe)) {\n return;\n }\n try {\n await this.setupPostMessageHandler();\n } catch (error) {\n this.dispatchErrorEvent({\n message: `Failed to setup PostMessageHandler on iframe load: ${error}`,\n });\n }\n }\n\n private getIframe(): HTMLIFrameElement | null {\n return this.shadowRoot?.querySelector('iframe') || null;\n }\n\n protected updated(changedProps: PropertyValues) {\n super.updated(changedProps);\n if (changedProps.has('baseURL')) {\n // Validate baseURL and normalize; fail fast on invalid input\n try {\n this.normalizedBaseURL = validateAndNormalizeBaseURL(this.baseURL);\n } catch (error) {\n // Tear down and clear iframe to avoid keeping an old origin active\n if (this.postMessageHandler) {\n this.postMessageHandler.destroy();\n this.postMessageHandler = null;\n }\n const iframe = this.getIframe();\n if (iframe) {\n iframe.setAttribute('src', 'about:blank');\n }\n this.dispatchErrorEvent({\n message: (error as Error).message || 'Invalid baseURL',\n });\n return;\n }\n // Tear down existing handler and re-point iframe to new URL\n if (this.postMessageHandler) {\n this.postMessageHandler.destroy();\n this.postMessageHandler = null;\n }\n const iframe = this.getIframe();\n if (iframe) {\n const expected = this.normalizedBaseURL\n ? buildEmbeddedUrl(this.normalizedBaseURL)\n : '';\n if (iframe.getAttribute('src') !== expected) {\n iframe.setAttribute('src', expected);\n iframe.setAttribute(\n 'allow',\n `microphone ${expected}; camera ${expected}; device-capture ${expected}; display-capture ${expected}`,\n );\n }\n }\n }\n }\n\n // Public API Implementation\n /**\n * Authenticate with the Corti system\n * @param credentials Authentication credentials\n * @returns Promise resolving to user information\n */\n async auth(credentials: AuthCredentials): Promise<User> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n const payload: AuthPayload = {\n access_token: credentials.access_token,\n token_type: credentials.token_type,\n expires_at: credentials.expires_at,\n expires_in: credentials.expires_in,\n refresh_expires_in: credentials.refresh_expires_in,\n refresh_token: credentials.refresh_token,\n id_token: credentials.id_token,\n 'not-before-policy': credentials['not-before-policy'],\n session_state: credentials.session_state,\n scope: credentials.scope,\n profile: credentials.profile,\n mode: credentials.mode,\n };\n\n const user = await this.postMessageHandler.auth(payload);\n return user;\n } catch (error) {\n const formattedError = formatError(error, 'Authentication failed');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Create a new interaction\n * @param encounter Encounter request data\n * @returns Promise resolving to interaction details\n */\n async createInteraction(\n encounter: InteractionPayload,\n ): Promise<InteractionDetails> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n const response =\n await this.postMessageHandler.createInteraction(encounter);\n return {\n id: response.id,\n createdAt: response.createdAt,\n };\n } catch (error) {\n const formattedError = formatError(error, 'Failed to create interaction');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Configure the current session\n * @param config Session configuration\n * @returns Promise that resolves when configuration is complete\n */\n async configureSession(config: SessionConfig): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n const payload: ConfigureSessionPayload = {\n defaultLanguage: config.defaultLanguage,\n defaultOutputLanguage: config.defaultOutputLanguage,\n defaultTemplateKey: config.defaultTemplateKey,\n defaultMode: config.defaultMode,\n };\n\n await this.postMessageHandler.configureSession(payload);\n } catch (error) {\n const formattedError = formatError(error, 'Failed to configure session');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Add facts to the current session\n * @param facts Array of facts to add\n * @returns Promise that resolves when facts are added\n */\n async addFacts(facts: Corti.FactsCreateInput[]): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n const payload: AddFactsPayload = { facts };\n await this.postMessageHandler.addFacts(payload);\n } catch (error) {\n const formattedError = formatError(error, 'Failed to add facts');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Navigate to a specific path within the embedded UI\n * @param path Path to navigate to\n * @returns Promise that resolves when navigation is complete\n */\n async navigate(path: string): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n const payload: NavigatePayload = { path };\n await this.postMessageHandler.navigate(payload);\n } catch (error) {\n const formattedError = formatError(error, 'Failed to navigate');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Start recording\n * @returns Promise that resolves when recording starts\n */\n async startRecording(): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n await this.postMessageHandler.startRecording();\n } catch (error) {\n const formattedError = formatError(error, 'Failed to start recording');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Stop recording\n * @returns Promise that resolves when recording stops\n */\n async stopRecording(): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n await this.postMessageHandler.stopRecording();\n } catch (error) {\n const formattedError = formatError(error, 'Failed to stop recording');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Get current component status\n * @returns Promise resolving to current status\n */\n async getStatus(): Promise<ComponentStatus> {\n if (!this.postMessageHandler) {\n return {\n ready: false,\n auth: {\n authenticated: false,\n user: undefined,\n },\n currentUrl: undefined,\n interaction: undefined,\n };\n }\n\n try {\n return await this.postMessageHandler.getStatus();\n } catch (error) {\n const formattedError = formatError(error, 'Failed to get status');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Configure the component\n * @param config Component configuration\n * @returns Promise that resolves when configuration is applied\n */\n async configure(\n config: ConfigureAppPayload,\n ): Promise<ConfigureAppResponsePayload> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n return await this.postMessageHandler.configure(config);\n } catch (error) {\n const formattedError = formatError(\n error,\n 'Failed to configure component',\n );\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Set authentication credentials without triggering auth flow\n * @param credentials Authentication credentials to store\n * @returns Promise that resolves when credentials are set\n */\n async setCredentials(credentials: SetCredentialsPayload): Promise<void> {\n if (!this.postMessageHandler) {\n throw new Error('Component not ready');\n }\n\n try {\n if (!credentials.password) {\n throw new Error('Password is required');\n }\n await this.postMessageHandler.setCredentials(credentials);\n } catch (error) {\n const formattedError = formatError(error, 'Failed to set credentials');\n this.dispatchErrorEvent(formattedError);\n throw new Error(JSON.stringify(formattedError));\n }\n }\n\n /**\n * Show the embedded UI\n */\n show(): void {\n this.visibility = 'visible';\n }\n\n /**\n * Hide the embedded UI\n */\n hide(): void {\n this.visibility = 'hidden';\n }\n\n /**\n * Check the current status of the iframe and PostMessageHandler\n * Useful for debugging\n * @deprecated Use getStatus() instead\n */\n getDebugStatus() {\n const iframe = this.getIframe();\n return {\n ready: iframe?.contentDocument?.readyState === 'complete',\n iframeExists: !!iframe,\n iframeSrc: iframe?.src,\n iframeContentWindow: !!iframe?.contentWindow,\n iframeContentDocument: !!iframe?.contentDocument,\n iframeReadyState: iframe?.contentDocument?.readyState,\n postMessageHandlerExists: !!this.postMessageHandler,\n postMessageHandlerReady: this.postMessageHandler?.ready || false,\n baseURL: this.baseURL,\n };\n }\n\n render() {\n // Don't render if baseURL is not provided\n if (!this.baseURL) {\n return html`<div>baseURL is required</div>`;\n }\n\n return html`\n <iframe\n src=${buildEmbeddedUrl(validateAndNormalizeBaseURL(this.baseURL))}\n title=\"Corti Embedded UI\"\n sandbox=${'allow-forms allow-modals allow-scripts allow-same-origin' as any}\n allow=\"microphone *; camera *; device-capture *; display-capture *\"\n @load=${(event: Event) => this.handleIframeLoad(event)}\n @unload=${() => this.postMessageHandler?.destroy()}\n style=${this.visibility === 'hidden'\n ? 'display: none;'\n : 'display: block;'}\n ></iframe>\n `;\n }\n}\n"]}