forgeframe 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.
@@ -0,0 +1,2419 @@
1
+ const h = {
2
+ /** String prop type */
3
+ STRING: "string",
4
+ /** Object prop type */
5
+ OBJECT: "object",
6
+ /** Function prop type - serialized for cross-domain calls */
7
+ FUNCTION: "function",
8
+ /** Boolean prop type */
9
+ BOOLEAN: "boolean",
10
+ /** Number prop type */
11
+ NUMBER: "number",
12
+ /** Array prop type */
13
+ ARRAY: "array"
14
+ }, f = {
15
+ /** Render component in an iframe */
16
+ IFRAME: "iframe",
17
+ /** Render component in a popup window */
18
+ POPUP: "popup"
19
+ }, p = {
20
+ /** Emitted when rendering starts */
21
+ RENDER: "render",
22
+ /** Emitted when component is fully rendered and initialized */
23
+ RENDERED: "rendered",
24
+ /** Emitted when prerender (loading) phase starts */
25
+ PRERENDER: "prerender",
26
+ /** Emitted when prerender phase completes */
27
+ PRERENDERED: "prerendered",
28
+ /** Emitted when component becomes visible */
29
+ DISPLAY: "display",
30
+ /** Emitted when an error occurs */
31
+ ERROR: "error",
32
+ /** Emitted when component is closing */
33
+ CLOSE: "close",
34
+ /** Emitted when component is destroyed */
35
+ DESTROY: "destroy",
36
+ /** Emitted when props are updated */
37
+ PROPS: "props",
38
+ /** Emitted when component is resized */
39
+ RESIZE: "resize",
40
+ /** Emitted when component receives focus */
41
+ FOCUS: "focus"
42
+ }, I = {
43
+ /** Default JSON serialization */
44
+ JSON: "json",
45
+ /** Base64 encoding for binary or large data */
46
+ BASE64: "base64",
47
+ /** Dot notation for nested objects (e.g., "a.b.c=value") */
48
+ DOTIFY: "dotify"
49
+ }, T = {
50
+ /** Request message expecting a response */
51
+ REQUEST: "request",
52
+ /** Response to a previous request */
53
+ RESPONSE: "response"
54
+ }, l = {
55
+ /** Child initialization complete */
56
+ INIT: "forgeframe_init",
57
+ /** Props update from parent to child */
58
+ PROPS: "forgeframe_props",
59
+ /** Close request from child */
60
+ CLOSE: "forgeframe_close",
61
+ /** Resize request from child */
62
+ RESIZE: "forgeframe_resize",
63
+ /** Focus request from child */
64
+ FOCUS: "forgeframe_focus",
65
+ /** Show request from child */
66
+ SHOW: "forgeframe_show",
67
+ /** Hide request from child */
68
+ HIDE: "forgeframe_hide",
69
+ /** Error report from child */
70
+ ERROR: "forgeframe_error",
71
+ /** Data export from child to parent */
72
+ EXPORT: "forgeframe_export",
73
+ /** Cross-domain function call */
74
+ CALL: "forgeframe_call",
75
+ /** Parent export from child context */
76
+ PARENT_EXPORT: "forgeframe_parent_export",
77
+ /** Get sibling components request */
78
+ GET_SIBLINGS: "forgeframe_get_siblings"
79
+ }, N = "__forgeframe__", re = "1.0.0";
80
+ class ne {
81
+ /**
82
+ * Internal storage for event listeners mapped by event name.
83
+ * @internal
84
+ */
85
+ listeners = /* @__PURE__ */ new Map();
86
+ /**
87
+ * Subscribes a handler to a specific event.
88
+ *
89
+ * @typeParam T - The type of data expected by the event handler
90
+ * @param event - The name of the event to subscribe to
91
+ * @param handler - The callback function to invoke when the event is emitted
92
+ * @returns A function that, when called, unsubscribes the handler from the event
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const unsubscribe = emitter.on<{ userId: string }>('login', (data) => {
97
+ * console.log('User logged in:', data.userId);
98
+ * });
99
+ * ```
100
+ *
101
+ * @public
102
+ */
103
+ on(e, r) {
104
+ return this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(r), () => this.off(e, r);
105
+ }
106
+ /**
107
+ * Subscribes a handler to an event that will automatically unsubscribe after the first invocation.
108
+ *
109
+ * @typeParam T - The type of data expected by the event handler
110
+ * @param event - The name of the event to subscribe to
111
+ * @param handler - The callback function to invoke once when the event is emitted
112
+ * @returns A function that, when called, unsubscribes the handler before it fires
113
+ *
114
+ * @remarks
115
+ * This is useful for one-time event handling, such as waiting for an initialization
116
+ * event or a single response.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * emitter.once('ready', () => {
121
+ * console.log('Component is ready!');
122
+ * });
123
+ * ```
124
+ *
125
+ * @public
126
+ */
127
+ once(e, r) {
128
+ const n = (i) => (this.off(e, n), r(i));
129
+ return this.on(e, n);
130
+ }
131
+ /**
132
+ * Emits an event, invoking all registered handlers with the provided data.
133
+ *
134
+ * @typeParam T - The type of data to pass to event handlers
135
+ * @param event - The name of the event to emit
136
+ * @param data - Optional data to pass to all registered handlers
137
+ *
138
+ * @remarks
139
+ * Handlers are invoked synchronously in the order they were registered.
140
+ * If a handler throws an error, it is caught and logged to the console,
141
+ * allowing subsequent handlers to still execute.
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * emitter.emit('userAction', { action: 'click', target: 'button' });
146
+ * ```
147
+ *
148
+ * @public
149
+ */
150
+ emit(e, r) {
151
+ const n = this.listeners.get(e);
152
+ if (n)
153
+ for (const i of n)
154
+ try {
155
+ const s = i(r);
156
+ s && typeof s == "object" && "catch" in s && typeof s.catch == "function" && s.catch((o) => {
157
+ console.error(`Error in async event handler for "${e}":`, o);
158
+ });
159
+ } catch (s) {
160
+ console.error(`Error in event handler for "${e}":`, s);
161
+ }
162
+ }
163
+ /**
164
+ * Unsubscribes a handler from an event, or removes all handlers for the event.
165
+ *
166
+ * @param event - The name of the event to unsubscribe from
167
+ * @param handler - The specific handler to remove. If not provided, all handlers for the event are removed.
168
+ *
169
+ * @remarks
170
+ * When a specific handler is removed and it was the last handler for that event,
171
+ * the event entry is cleaned up from the internal map.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Remove a specific handler
176
+ * emitter.off('message', myHandler);
177
+ *
178
+ * // Remove all handlers for an event
179
+ * emitter.off('message');
180
+ * ```
181
+ *
182
+ * @public
183
+ */
184
+ off(e, r) {
185
+ if (!r) {
186
+ this.listeners.delete(e);
187
+ return;
188
+ }
189
+ const n = this.listeners.get(e);
190
+ n && (n.delete(r), n.size === 0 && this.listeners.delete(e));
191
+ }
192
+ /**
193
+ * Removes all event listeners from the emitter.
194
+ *
195
+ * @remarks
196
+ * This method is typically called during component cleanup or disposal
197
+ * to ensure no memory leaks from lingering event subscriptions.
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * // Clean up all listeners when component is destroyed
202
+ * emitter.removeAllListeners();
203
+ * ```
204
+ *
205
+ * @public
206
+ */
207
+ removeAllListeners() {
208
+ this.listeners.clear();
209
+ }
210
+ /**
211
+ * Returns the number of listeners registered for a specific event.
212
+ *
213
+ * @param event - The name of the event to check
214
+ * @returns The number of handlers currently subscribed to the event
215
+ *
216
+ * @remarks
217
+ * This method is primarily useful for debugging and testing purposes
218
+ * to verify that subscriptions are being properly managed.
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * console.log(`Active listeners: ${emitter.listenerCount('message')}`);
223
+ * ```
224
+ *
225
+ * @public
226
+ */
227
+ listenerCount(e) {
228
+ return this.listeners.get(e)?.size ?? 0;
229
+ }
230
+ }
231
+ function we() {
232
+ const t = Date.now().toString(36), e = Math.random().toString(36).slice(2, 11);
233
+ return `${t}_${e}`;
234
+ }
235
+ function v() {
236
+ return Math.random().toString(36).slice(2, 11);
237
+ }
238
+ class Ee {
239
+ /**
240
+ * Array of registered cleanup tasks awaiting execution.
241
+ * @internal
242
+ */
243
+ tasks = [];
244
+ /**
245
+ * Flag indicating whether cleanup has already been performed.
246
+ * @internal
247
+ */
248
+ cleaned = !1;
249
+ /**
250
+ * Registers a cleanup task to be executed when {@link cleanup} is called.
251
+ *
252
+ * @param task - The cleanup function to register
253
+ *
254
+ * @remarks
255
+ * If cleanup has already been performed, the task is executed immediately
256
+ * rather than being registered. This ensures late-registered tasks are
257
+ * still handled appropriately.
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * cleanup.register(() => {
262
+ * eventEmitter.removeAllListeners();
263
+ * });
264
+ *
265
+ * cleanup.register(async () => {
266
+ * await database.close();
267
+ * });
268
+ * ```
269
+ *
270
+ * @public
271
+ */
272
+ register(e) {
273
+ if (this.cleaned) {
274
+ try {
275
+ e();
276
+ } catch (r) {
277
+ console.error("Error in cleanup task:", r);
278
+ }
279
+ return;
280
+ }
281
+ this.tasks.push(e);
282
+ }
283
+ /**
284
+ * Executes all registered cleanup tasks in LIFO order.
285
+ *
286
+ * @returns A Promise that resolves when all cleanup tasks have completed
287
+ *
288
+ * @remarks
289
+ * Tasks are executed in reverse order of registration (LIFO pattern).
290
+ * Each task is awaited individually, and errors are caught and logged
291
+ * to prevent one failing task from blocking subsequent cleanup operations.
292
+ * Calling this method multiple times has no effect after the first call.
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * // In a component's destroy lifecycle
297
+ * async destroy() {
298
+ * await this.cleanupManager.cleanup();
299
+ * }
300
+ * ```
301
+ *
302
+ * @public
303
+ */
304
+ async cleanup() {
305
+ if (this.cleaned) return;
306
+ this.cleaned = !0;
307
+ const e = this.tasks.reverse();
308
+ this.tasks = [];
309
+ for (const r of e)
310
+ try {
311
+ await r();
312
+ } catch (n) {
313
+ console.error("Error in cleanup task:", n);
314
+ }
315
+ }
316
+ /**
317
+ * Checks whether cleanup has already been performed.
318
+ *
319
+ * @returns `true` if {@link cleanup} has been called, `false` otherwise
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * if (!cleanupManager.isCleaned()) {
324
+ * // Safe to register more tasks
325
+ * cleanupManager.register(myTask);
326
+ * }
327
+ * ```
328
+ *
329
+ * @public
330
+ */
331
+ isCleaned() {
332
+ return this.cleaned;
333
+ }
334
+ /**
335
+ * Resets the manager to its initial state, allowing it to be reused.
336
+ *
337
+ * @remarks
338
+ * This method clears all registered tasks and resets the cleaned flag.
339
+ * It is primarily intended for testing scenarios or cases where the
340
+ * manager needs to be reused after cleanup.
341
+ *
342
+ * @example
343
+ * ```typescript
344
+ * // In a test teardown
345
+ * afterEach(() => {
346
+ * cleanupManager.reset();
347
+ * });
348
+ * ```
349
+ *
350
+ * @public
351
+ */
352
+ reset() {
353
+ this.tasks = [], this.cleaned = !1;
354
+ }
355
+ }
356
+ function ie() {
357
+ let t, e;
358
+ return { promise: new Promise((n, i) => {
359
+ t = n, e = i;
360
+ }), resolve: t, reject: e };
361
+ }
362
+ function Ce(t, e, r = "Operation timed out") {
363
+ return new Promise((n, i) => {
364
+ const s = setTimeout(() => {
365
+ i(new Error(`${r} (${e}ms)`));
366
+ }, e);
367
+ t.then((o) => {
368
+ clearTimeout(s), n(o);
369
+ }).catch((o) => {
370
+ clearTimeout(s), i(o);
371
+ });
372
+ });
373
+ }
374
+ const A = "forgeframe:";
375
+ function F(t) {
376
+ return A + JSON.stringify(t);
377
+ }
378
+ function Pe(t) {
379
+ if (typeof t != "string" || !t.startsWith(A)) return null;
380
+ try {
381
+ const e = t.slice(A.length), r = JSON.parse(e);
382
+ return !r.id || !r.type || !r.name || !r.source ? null : r;
383
+ } catch {
384
+ return null;
385
+ }
386
+ }
387
+ function X(t, e, r, n) {
388
+ return {
389
+ id: t,
390
+ type: T.REQUEST,
391
+ name: e,
392
+ data: r,
393
+ source: n
394
+ };
395
+ }
396
+ function Re(t, e, r, n) {
397
+ return {
398
+ id: t,
399
+ type: T.RESPONSE,
400
+ name: "response",
401
+ data: e,
402
+ source: r,
403
+ error: n ? {
404
+ message: n.message,
405
+ stack: n.stack
406
+ } : void 0
407
+ };
408
+ }
409
+ class se {
410
+ /**
411
+ * Creates a new Messenger instance.
412
+ *
413
+ * @param uid - Unique identifier for this messenger
414
+ * @param win - The window to listen for messages on
415
+ * @param domain - The origin domain of this messenger
416
+ * @param trustedDomains - Optional domains to trust for incoming messages
417
+ */
418
+ constructor(e, r = window, n = window.location.origin, i) {
419
+ this.uid = e, this.win = r, this.domain = n, this.allowedOrigins.add(n), i && this.addTrustedDomain(i), this.setupListener();
420
+ }
421
+ /** @internal */
422
+ pending = /* @__PURE__ */ new Map();
423
+ /** @internal */
424
+ handlers = /* @__PURE__ */ new Map();
425
+ /** @internal */
426
+ listener = null;
427
+ /** @internal */
428
+ destroyed = !1;
429
+ /** @internal */
430
+ allowedOrigins = /* @__PURE__ */ new Set();
431
+ /** @internal */
432
+ allowedOriginPatterns = [];
433
+ /**
434
+ * Adds a trusted domain that can send messages to this messenger.
435
+ *
436
+ * @param domain - Domain pattern to trust (string, RegExp, or array)
437
+ */
438
+ addTrustedDomain(e) {
439
+ if (Array.isArray(e))
440
+ for (const r of e)
441
+ this.allowedOrigins.add(r);
442
+ else e instanceof RegExp ? this.allowedOriginPatterns.push(e) : this.allowedOrigins.add(e);
443
+ }
444
+ /**
445
+ * Checks if an origin is trusted.
446
+ *
447
+ * @param origin - The origin to check
448
+ * @returns True if the origin is trusted
449
+ * @internal
450
+ */
451
+ isOriginTrusted(e) {
452
+ if (this.allowedOrigins.has(e))
453
+ return !0;
454
+ for (const r of this.allowedOriginPatterns)
455
+ if (r.test(e))
456
+ return !0;
457
+ return !1;
458
+ }
459
+ /**
460
+ * Sends a message and waits for a response.
461
+ *
462
+ * @typeParam T - The data type being sent
463
+ * @typeParam R - The expected response type
464
+ * @param targetWin - The target window to send to
465
+ * @param targetDomain - The target origin domain
466
+ * @param name - The message name/type
467
+ * @param data - Optional data payload
468
+ * @param timeout - Timeout in milliseconds (default: 10000)
469
+ * @returns Promise resolving to the response data
470
+ * @throws Error if messenger is destroyed or timeout occurs
471
+ */
472
+ async send(e, r, n, i, s = 1e4) {
473
+ if (this.destroyed)
474
+ throw new Error("Messenger has been destroyed");
475
+ const o = v(), a = X(o, n, i, {
476
+ uid: this.uid,
477
+ domain: this.domain
478
+ }), c = ie(), d = setTimeout(() => {
479
+ this.pending.delete(o), c.reject(new Error(`Message "${n}" timed out after ${s}ms`));
480
+ }, s);
481
+ this.pending.set(o, {
482
+ deferred: c,
483
+ timeout: d
484
+ });
485
+ try {
486
+ e.postMessage(F(a), r);
487
+ } catch (u) {
488
+ throw this.pending.delete(o), clearTimeout(d), u;
489
+ }
490
+ return c.promise;
491
+ }
492
+ /**
493
+ * Sends a one-way message without waiting for a response.
494
+ *
495
+ * @typeParam T - The data type being sent
496
+ * @param targetWin - The target window to send to
497
+ * @param targetDomain - The target origin domain
498
+ * @param name - The message name/type
499
+ * @param data - Optional data payload
500
+ * @throws Error if messenger is destroyed
501
+ */
502
+ post(e, r, n, i) {
503
+ if (this.destroyed)
504
+ throw new Error("Messenger has been destroyed");
505
+ const s = v(), o = X(s, n, i, {
506
+ uid: this.uid,
507
+ domain: this.domain
508
+ });
509
+ e.postMessage(F(o), r);
510
+ }
511
+ /**
512
+ * Registers a handler for incoming messages of a specific type.
513
+ *
514
+ * @typeParam T - The expected data type of incoming messages
515
+ * @typeParam R - The return type of the handler
516
+ * @param name - The message name/type to handle
517
+ * @param handler - The handler function
518
+ * @returns Function to unregister the handler
519
+ */
520
+ on(e, r) {
521
+ return this.handlers.set(e, r), () => this.handlers.delete(e);
522
+ }
523
+ /**
524
+ * Sets up the postMessage event listener.
525
+ * @internal
526
+ */
527
+ setupListener() {
528
+ this.listener = (e) => {
529
+ if (e.source === this.win || !this.isOriginTrusted(e.origin))
530
+ return;
531
+ const r = Pe(e.data);
532
+ r && this.handleMessage(r, e.source, e.origin);
533
+ }, this.win.addEventListener("message", this.listener);
534
+ }
535
+ /**
536
+ * Processes a received message.
537
+ * @internal
538
+ */
539
+ async handleMessage(e, r, n) {
540
+ if (e.type === T.RESPONSE) {
541
+ const i = this.pending.get(e.id);
542
+ if (i)
543
+ if (this.pending.delete(e.id), clearTimeout(i.timeout), e.error) {
544
+ const s = new Error(e.error.message);
545
+ s.stack = e.error.stack, i.deferred.reject(s);
546
+ } else
547
+ i.deferred.resolve(e.data);
548
+ return;
549
+ }
550
+ if (e.type === T.REQUEST) {
551
+ const i = this.handlers.get(e.name);
552
+ if (!i)
553
+ return;
554
+ let s, o;
555
+ try {
556
+ s = await i(e.data, e.source);
557
+ } catch (c) {
558
+ o = c instanceof Error ? c : new Error(String(c));
559
+ }
560
+ const a = Re(
561
+ e.id,
562
+ s,
563
+ { uid: this.uid, domain: this.domain },
564
+ o
565
+ );
566
+ try {
567
+ r.postMessage(F(a), n);
568
+ } catch {
569
+ }
570
+ }
571
+ }
572
+ /**
573
+ * Cleans up the messenger and releases resources.
574
+ *
575
+ * @remarks
576
+ * Removes the message listener, rejects all pending requests,
577
+ * and clears all handlers.
578
+ */
579
+ destroy() {
580
+ if (!this.destroyed) {
581
+ this.destroyed = !0, this.listener && (this.win.removeEventListener("message", this.listener), this.listener = null);
582
+ for (const e of this.pending.values())
583
+ clearTimeout(e.timeout), e.deferred.reject(new Error("Messenger destroyed"));
584
+ this.pending.clear(), this.handlers.clear();
585
+ }
586
+ }
587
+ /**
588
+ * Checks if the messenger has been destroyed.
589
+ *
590
+ * @returns True if destroy() has been called
591
+ */
592
+ isDestroyed() {
593
+ return this.destroyed;
594
+ }
595
+ }
596
+ const J = 500;
597
+ class $ {
598
+ /**
599
+ * Creates a new FunctionBridge instance.
600
+ *
601
+ * @param messenger - The messenger to use for cross-domain calls
602
+ */
603
+ constructor(e) {
604
+ this.messenger = e, this.setupCallHandler();
605
+ }
606
+ /** @internal */
607
+ localFunctions = /* @__PURE__ */ new Map();
608
+ /** @internal */
609
+ remoteFunctions = /* @__PURE__ */ new Map();
610
+ /**
611
+ * Tracks function IDs from the current serialization batch.
612
+ * Used for cleanup of stale references when props are updated.
613
+ * @internal
614
+ */
615
+ currentBatchIds = /* @__PURE__ */ new Set();
616
+ /**
617
+ * Serializes a local function to a transferable reference.
618
+ *
619
+ * @param fn - The function to serialize
620
+ * @param name - Optional name for debugging
621
+ * @returns A function reference that can be sent across domains
622
+ */
623
+ serialize(e, r) {
624
+ if (this.localFunctions.size >= J) {
625
+ const i = this.localFunctions.keys().next().value;
626
+ i && this.localFunctions.delete(i);
627
+ }
628
+ const n = v();
629
+ return this.localFunctions.set(n, e), this.currentBatchIds.add(n), {
630
+ __type__: "function",
631
+ __id__: n,
632
+ __name__: r || e.name || "anonymous"
633
+ };
634
+ }
635
+ /**
636
+ * Deserializes a function reference to a callable wrapper.
637
+ *
638
+ * @remarks
639
+ * The returned function, when called, will invoke the original function
640
+ * in the remote window via postMessage and return the result.
641
+ *
642
+ * @param ref - The function reference to deserialize
643
+ * @param targetWin - The window containing the original function
644
+ * @param targetDomain - The origin of the target window
645
+ * @returns A callable wrapper function
646
+ */
647
+ deserialize(e, r, n) {
648
+ const i = `${e.__id__}`, s = this.remoteFunctions.get(i);
649
+ if (s) return s;
650
+ if (this.remoteFunctions.size >= J) {
651
+ const a = this.remoteFunctions.keys().next().value;
652
+ a && this.remoteFunctions.delete(a);
653
+ }
654
+ const o = async (...a) => this.messenger.send(r, n, l.CALL, {
655
+ id: e.__id__,
656
+ args: a
657
+ });
658
+ return Object.defineProperty(o, "name", {
659
+ value: e.__name__,
660
+ configurable: !0
661
+ }), this.remoteFunctions.set(i, o), o;
662
+ }
663
+ /**
664
+ * Type guard to check if a value is a function reference.
665
+ *
666
+ * @param value - The value to check
667
+ * @returns True if the value is a FunctionRef
668
+ */
669
+ static isFunctionRef(e) {
670
+ return typeof e == "object" && e !== null && e.__type__ === "function" && typeof e.__id__ == "string";
671
+ }
672
+ /**
673
+ * Sets up the handler for incoming function call messages.
674
+ * @internal
675
+ */
676
+ setupCallHandler() {
677
+ this.messenger.on(
678
+ l.CALL,
679
+ async ({ id: e, args: r }) => {
680
+ const n = this.localFunctions.get(e);
681
+ if (!n)
682
+ throw new Error(`Function with id "${e}" not found`);
683
+ return n(...r);
684
+ }
685
+ );
686
+ }
687
+ /**
688
+ * Removes a local function reference.
689
+ *
690
+ * @param id - The function reference ID to remove
691
+ */
692
+ removeLocal(e) {
693
+ this.localFunctions.delete(e);
694
+ }
695
+ /**
696
+ * Starts a new serialization batch.
697
+ *
698
+ * @remarks
699
+ * Call this before serializing a new set of props. After serialization,
700
+ * call {@link finishBatch} to clean up functions from previous batches.
701
+ *
702
+ * @example
703
+ * ```typescript
704
+ * bridge.startBatch();
705
+ * const serialized = serializeFunctions(props, bridge);
706
+ * bridge.finishBatch();
707
+ * ```
708
+ */
709
+ startBatch() {
710
+ this.currentBatchIds.clear();
711
+ }
712
+ /**
713
+ * Finishes the current batch and removes functions not in this batch.
714
+ *
715
+ * @remarks
716
+ * This cleans up function references from previous prop updates that
717
+ * are no longer needed, preventing memory leaks.
718
+ *
719
+ * @param keepPrevious - If true, keeps previous batch functions (default: false)
720
+ */
721
+ finishBatch(e = !1) {
722
+ if (e) {
723
+ this.currentBatchIds.clear();
724
+ return;
725
+ }
726
+ for (const r of this.localFunctions.keys())
727
+ this.currentBatchIds.has(r) || this.localFunctions.delete(r);
728
+ this.currentBatchIds.clear();
729
+ }
730
+ /**
731
+ * Clears all remote function references.
732
+ *
733
+ * @remarks
734
+ * Call this when the remote window is no longer accessible
735
+ * (e.g., closed or navigated away).
736
+ */
737
+ clearRemote() {
738
+ this.remoteFunctions.clear();
739
+ }
740
+ /**
741
+ * Returns the current number of registered local functions.
742
+ * Useful for debugging and monitoring.
743
+ */
744
+ get localFunctionCount() {
745
+ return this.localFunctions.size;
746
+ }
747
+ /**
748
+ * Returns the current number of cached remote functions.
749
+ * Useful for debugging and monitoring.
750
+ */
751
+ get remoteFunctionCount() {
752
+ return this.remoteFunctions.size;
753
+ }
754
+ /**
755
+ * Cleans up all function references.
756
+ */
757
+ destroy() {
758
+ this.localFunctions.clear(), this.remoteFunctions.clear(), this.currentBatchIds.clear();
759
+ }
760
+ }
761
+ function k(t, e, r = /* @__PURE__ */ new WeakSet()) {
762
+ if (typeof t == "function")
763
+ return e.serialize(t);
764
+ if (Array.isArray(t)) {
765
+ if (r.has(t))
766
+ throw new Error("Circular reference detected in props - arrays cannot contain circular references");
767
+ return r.add(t), t.map((n) => k(n, e, r));
768
+ }
769
+ if (typeof t == "object" && t !== null) {
770
+ if (r.has(t))
771
+ throw new Error("Circular reference detected in props - objects cannot contain circular references");
772
+ r.add(t);
773
+ const n = {};
774
+ for (const [i, s] of Object.entries(t))
775
+ n[i] = k(s, e, r);
776
+ return n;
777
+ }
778
+ return t;
779
+ }
780
+ function z(t, e, r, n, i = /* @__PURE__ */ new WeakSet()) {
781
+ if ($.isFunctionRef(t))
782
+ return e.deserialize(t, r, n);
783
+ if (Array.isArray(t)) {
784
+ if (i.has(t))
785
+ throw new Error("Circular reference detected in serialized props");
786
+ return i.add(t), t.map(
787
+ (s) => z(s, e, r, n, i)
788
+ );
789
+ }
790
+ if (typeof t == "object" && t !== null) {
791
+ if (i.has(t))
792
+ throw new Error("Circular reference detected in serialized props");
793
+ i.add(t);
794
+ const s = {};
795
+ for (const [o, a] of Object.entries(t))
796
+ s[o] = z(a, e, r, n, i);
797
+ return s;
798
+ }
799
+ return t;
800
+ }
801
+ function W(t = window) {
802
+ try {
803
+ return t.location.origin;
804
+ } catch {
805
+ return "";
806
+ }
807
+ }
808
+ function oe(t, e = window) {
809
+ try {
810
+ return t.location.origin === e.location.origin;
811
+ } catch {
812
+ return !1;
813
+ }
814
+ }
815
+ function ae(t, e) {
816
+ return typeof t == "string" ? t === "*" ? !0 : t === e : t instanceof RegExp ? t.test(e) : Array.isArray(t) ? t.some((r) => ae(r, e)) : !1;
817
+ }
818
+ function ce(t) {
819
+ if (!t) return !0;
820
+ try {
821
+ return t.closed;
822
+ } catch {
823
+ return !0;
824
+ }
825
+ }
826
+ function Oe(t = window) {
827
+ try {
828
+ return t.opener;
829
+ } catch {
830
+ return null;
831
+ }
832
+ }
833
+ function be(t = window) {
834
+ try {
835
+ const e = t.parent;
836
+ return e && e !== t ? e : null;
837
+ } catch {
838
+ return null;
839
+ }
840
+ }
841
+ function _e(t = window) {
842
+ try {
843
+ return t.parent !== t;
844
+ } catch {
845
+ return !0;
846
+ }
847
+ }
848
+ function Ie(t = window) {
849
+ try {
850
+ return t.opener !== null && t.opener !== void 0;
851
+ } catch {
852
+ return !1;
853
+ }
854
+ }
855
+ const G = 32 * 1024;
856
+ function Te(t) {
857
+ const e = Ne(t);
858
+ return `${N}${e}`;
859
+ }
860
+ function le(t) {
861
+ if (!t || !t.startsWith(N))
862
+ return null;
863
+ const e = t.slice(N.length);
864
+ return Se(e);
865
+ }
866
+ function de(t = window) {
867
+ try {
868
+ return t.name.startsWith(N);
869
+ } catch {
870
+ return !1;
871
+ }
872
+ }
873
+ function Y(t, e = window) {
874
+ return le(e.name)?.tag === t;
875
+ }
876
+ function Ne(t) {
877
+ try {
878
+ const e = JSON.stringify(t), r = btoa(encodeURIComponent(e)), n = new Blob([r]).size;
879
+ if (n > G)
880
+ throw new Error(
881
+ `Payload size (${Math.round(n / 1024)}KB) exceeds maximum allowed size (${G / 1024}KB). Consider reducing the amount of data passed via props.`
882
+ );
883
+ return r;
884
+ } catch (e) {
885
+ throw e instanceof Error && e.message.includes("Payload size") ? e : new Error(`Failed to encode payload: ${e}`);
886
+ }
887
+ }
888
+ function Se(t) {
889
+ try {
890
+ const e = decodeURIComponent(atob(t));
891
+ return JSON.parse(e);
892
+ } catch {
893
+ return null;
894
+ }
895
+ }
896
+ function xe(t) {
897
+ return {
898
+ uid: t.uid,
899
+ tag: t.tag,
900
+ version: re,
901
+ context: t.context,
902
+ parentDomain: t.parentDomain,
903
+ props: t.props,
904
+ exports: t.exports,
905
+ children: t.children
906
+ };
907
+ }
908
+ function De(t = window) {
909
+ return le(t.name);
910
+ }
911
+ const V = 100, y = /* @__PURE__ */ new Map();
912
+ function Fe() {
913
+ const t = [];
914
+ for (const [e, r] of y.entries())
915
+ ce(r) && t.push(e);
916
+ for (const e of t)
917
+ y.delete(e);
918
+ }
919
+ function ve(t, e) {
920
+ if (y.size >= V && Fe(), y.size >= V) {
921
+ const r = y.keys().next().value;
922
+ r && y.delete(r);
923
+ }
924
+ y.set(t, e);
925
+ }
926
+ function Ae(t) {
927
+ y.delete(t);
928
+ }
929
+ const E = {
930
+ uid: {
931
+ type: h.STRING,
932
+ required: !1,
933
+ sendToChild: !0
934
+ },
935
+ tag: {
936
+ type: h.STRING,
937
+ required: !1,
938
+ sendToChild: !0
939
+ },
940
+ dimensions: {
941
+ type: h.OBJECT,
942
+ required: !1,
943
+ sendToChild: !1,
944
+ default: () => ({ width: "100%", height: "100%" })
945
+ },
946
+ timeout: {
947
+ type: h.NUMBER,
948
+ required: !1,
949
+ sendToChild: !1,
950
+ default: () => 1e4
951
+ },
952
+ cspNonce: {
953
+ type: h.STRING,
954
+ required: !1,
955
+ sendToChild: !0
956
+ },
957
+ // Lifecycle callbacks - functions sent to child
958
+ onDisplay: {
959
+ type: h.FUNCTION,
960
+ required: !1,
961
+ sendToChild: !1
962
+ },
963
+ onRendered: {
964
+ type: h.FUNCTION,
965
+ required: !1,
966
+ sendToChild: !1
967
+ },
968
+ onRender: {
969
+ type: h.FUNCTION,
970
+ required: !1,
971
+ sendToChild: !1
972
+ },
973
+ onPrerendered: {
974
+ type: h.FUNCTION,
975
+ required: !1,
976
+ sendToChild: !1
977
+ },
978
+ onPrerender: {
979
+ type: h.FUNCTION,
980
+ required: !1,
981
+ sendToChild: !1
982
+ },
983
+ onClose: {
984
+ type: h.FUNCTION,
985
+ required: !1,
986
+ sendToChild: !1
987
+ },
988
+ onDestroy: {
989
+ type: h.FUNCTION,
990
+ required: !1,
991
+ sendToChild: !1
992
+ },
993
+ onResize: {
994
+ type: h.FUNCTION,
995
+ required: !1,
996
+ sendToChild: !1
997
+ },
998
+ onFocus: {
999
+ type: h.FUNCTION,
1000
+ required: !1,
1001
+ sendToChild: !1
1002
+ },
1003
+ onError: {
1004
+ type: h.FUNCTION,
1005
+ required: !1,
1006
+ sendToChild: !1
1007
+ },
1008
+ onProps: {
1009
+ type: h.FUNCTION,
1010
+ required: !1,
1011
+ sendToChild: !1
1012
+ }
1013
+ };
1014
+ function Z(t, e, r) {
1015
+ const n = {
1016
+ ...E,
1017
+ ...e
1018
+ }, i = {};
1019
+ for (const [s, o] of Object.entries(n)) {
1020
+ const a = o;
1021
+ let c;
1022
+ const d = a.alias, u = s in t, g = d && d in t;
1023
+ u ? c = t[s] : g ? c = t[d] : a.value ? c = a.value(r) : a.default !== void 0 && (c = typeof a.default == "function" ? a.default(r) : a.default), c !== void 0 && a.decorate && (c = a.decorate({ value: c, props: i })), i[s] = c;
1024
+ }
1025
+ return i;
1026
+ }
1027
+ function ke(t, e) {
1028
+ const r = {
1029
+ ...E,
1030
+ ...e
1031
+ };
1032
+ for (const [n, i] of Object.entries(r)) {
1033
+ const s = i, o = t[n];
1034
+ if (s.required && o === void 0)
1035
+ throw new Error(`Prop "${n}" is required but was not provided`);
1036
+ if (o !== void 0) {
1037
+ if (!ze(o, s.type))
1038
+ throw new Error(
1039
+ `Prop "${n}" expected type "${s.type}" but got "${typeof o}"`
1040
+ );
1041
+ s.validate && s.validate({ value: o, props: t });
1042
+ }
1043
+ }
1044
+ }
1045
+ function ze(t, e) {
1046
+ switch (e) {
1047
+ case h.STRING:
1048
+ return typeof t == "string";
1049
+ case h.NUMBER:
1050
+ return typeof t == "number";
1051
+ case h.BOOLEAN:
1052
+ return typeof t == "boolean";
1053
+ case h.FUNCTION:
1054
+ return typeof t == "function";
1055
+ case h.ARRAY:
1056
+ return Array.isArray(t);
1057
+ case h.OBJECT:
1058
+ return typeof t == "object" && t !== null && !Array.isArray(t);
1059
+ default:
1060
+ return !0;
1061
+ }
1062
+ }
1063
+ function K(t, e, r, n) {
1064
+ const i = {
1065
+ ...E,
1066
+ ...e
1067
+ }, s = {};
1068
+ for (const [o, a] of Object.entries(i)) {
1069
+ const c = a, d = t[o];
1070
+ if (c.sendToChild === !1 || c.sameDomain && !n) continue;
1071
+ if (c.trustedDomains) {
1072
+ const g = c.trustedDomains;
1073
+ if (!ae(g, r)) continue;
1074
+ }
1075
+ let u = d;
1076
+ c.childDecorate && d !== void 0 && (u = c.childDecorate({ value: d, props: t })), s[o] = u;
1077
+ }
1078
+ return s;
1079
+ }
1080
+ function We(t, e) {
1081
+ const r = new URLSearchParams(), n = {
1082
+ ...E,
1083
+ ...e
1084
+ };
1085
+ for (const [i, s] of Object.entries(n)) {
1086
+ const o = s, a = t[i];
1087
+ if (a === void 0 || o.type === h.FUNCTION || !o.queryParam) continue;
1088
+ const c = typeof o.queryParam == "string" ? o.queryParam : i;
1089
+ let d;
1090
+ typeof o.queryParam == "function" ? d = o.queryParam({ value: a }) : typeof a == "object" ? d = JSON.stringify(a) : d = String(a), r.set(c, d);
1091
+ }
1092
+ return r;
1093
+ }
1094
+ function he(t, e = "") {
1095
+ const r = [];
1096
+ for (const [n, i] of Object.entries(t)) {
1097
+ const s = e ? `${e}.${n}` : n;
1098
+ if (i !== null && typeof i == "object" && !Array.isArray(i))
1099
+ r.push(he(i, s));
1100
+ else {
1101
+ const o = encodeURIComponent(JSON.stringify(i));
1102
+ r.push(`${s}=${o}`);
1103
+ }
1104
+ }
1105
+ return r.filter(Boolean).join("&");
1106
+ }
1107
+ function $e(t) {
1108
+ const e = {};
1109
+ if (!t) return e;
1110
+ const r = t.split("&");
1111
+ for (const n of r) {
1112
+ const [i, s] = n.split("=");
1113
+ if (!i || s === void 0) continue;
1114
+ let o;
1115
+ try {
1116
+ o = JSON.parse(decodeURIComponent(s));
1117
+ } catch {
1118
+ o = decodeURIComponent(s);
1119
+ }
1120
+ const a = i.split(".");
1121
+ let c = e;
1122
+ for (let d = 0; d < a.length - 1; d++) {
1123
+ const u = a[d];
1124
+ (!(u in c) || typeof c[u] != "object") && (c[u] = {}), c = c[u];
1125
+ }
1126
+ c[a[a.length - 1]] = o;
1127
+ }
1128
+ return e;
1129
+ }
1130
+ function Me(t) {
1131
+ return typeof t == "object" && t !== null && t.__type__ === "dotify" && typeof t.__value__ == "string";
1132
+ }
1133
+ function Q(t, e, r) {
1134
+ const n = {
1135
+ ...E,
1136
+ ...e
1137
+ }, i = {};
1138
+ for (const [s, o] of Object.entries(t)) {
1139
+ if (o === void 0) continue;
1140
+ const a = n[s];
1141
+ i[s] = Ue(o, a, r);
1142
+ }
1143
+ return i;
1144
+ }
1145
+ function Ue(t, e, r) {
1146
+ if (typeof t == "function")
1147
+ return r.serialize(t);
1148
+ const n = e?.serialization ?? I.JSON;
1149
+ if (n === I.BASE64 && typeof t == "object") {
1150
+ const i = JSON.stringify(t);
1151
+ return {
1152
+ __type__: "base64",
1153
+ __value__: btoa(encodeURIComponent(i))
1154
+ };
1155
+ }
1156
+ return n === I.DOTIFY && typeof t == "object" && t !== null && !Array.isArray(t) ? {
1157
+ __type__: "dotify",
1158
+ __value__: he(t)
1159
+ } : k(t, r);
1160
+ }
1161
+ function ee(t, e, r, n, i, s) {
1162
+ const o = {
1163
+ ...E,
1164
+ ...e
1165
+ }, a = {};
1166
+ for (const [c, d] of Object.entries(t)) {
1167
+ const u = o[c];
1168
+ a[c] = Le(
1169
+ d,
1170
+ u,
1171
+ r,
1172
+ n,
1173
+ i,
1174
+ s
1175
+ );
1176
+ }
1177
+ return a;
1178
+ }
1179
+ function Le(t, e, r, n, i, s) {
1180
+ if (qe(t))
1181
+ try {
1182
+ const o = decodeURIComponent(atob(t.__value__));
1183
+ return JSON.parse(o);
1184
+ } catch {
1185
+ return t;
1186
+ }
1187
+ if (Me(t))
1188
+ try {
1189
+ return $e(t.__value__);
1190
+ } catch {
1191
+ return t;
1192
+ }
1193
+ return z(t, n, i, s);
1194
+ }
1195
+ function qe(t) {
1196
+ return typeof t == "object" && t !== null && t.__type__ === "base64" && typeof t.__value__ == "string";
1197
+ }
1198
+ function w(t, e = "100%") {
1199
+ return t === void 0 ? e : typeof t == "number" ? `${t}px` : t;
1200
+ }
1201
+ function S(t, e) {
1202
+ if (t === void 0) return e;
1203
+ if (typeof t == "number") return t;
1204
+ const r = parseInt(t, 10);
1205
+ return isNaN(r) ? e : r;
1206
+ }
1207
+ function Be(t) {
1208
+ try {
1209
+ t.src = "about:blank", t.parentNode?.removeChild(t);
1210
+ } catch {
1211
+ }
1212
+ }
1213
+ function je(t, e) {
1214
+ Je(t, e);
1215
+ }
1216
+ function He(t) {
1217
+ t.style.display = "", t.style.visibility = "visible";
1218
+ }
1219
+ function te(t) {
1220
+ t.style.display = "none", t.style.visibility = "hidden";
1221
+ }
1222
+ function Xe(t) {
1223
+ try {
1224
+ t.focus(), t.contentWindow?.focus();
1225
+ } catch {
1226
+ }
1227
+ }
1228
+ function Je(t, e) {
1229
+ e.width !== void 0 && (t.style.width = w(e.width)), e.height !== void 0 && (t.style.height = w(e.height));
1230
+ }
1231
+ class ue extends Error {
1232
+ constructor(e = "Popup blocked by browser") {
1233
+ super(e), this.name = "PopupOpenError";
1234
+ }
1235
+ }
1236
+ function Ge(t) {
1237
+ const { url: e, name: r, dimensions: n } = t, i = S(n.width, 500), s = S(n.height, 500), o = Math.floor(window.screenX + (window.outerWidth - i) / 2), a = Math.floor(window.screenY + (window.outerHeight - s) / 2), c = [
1238
+ `width=${i}`,
1239
+ `height=${s}`,
1240
+ `left=${o}`,
1241
+ `top=${a}`,
1242
+ "menubar=no",
1243
+ "toolbar=no",
1244
+ "location=yes",
1245
+ // Required for security
1246
+ "status=no",
1247
+ "resizable=yes",
1248
+ "scrollbars=yes"
1249
+ ].join(","), d = window.open(e, r, c);
1250
+ if (!d || Ze(d))
1251
+ throw new ue();
1252
+ return d;
1253
+ }
1254
+ function Ye(t) {
1255
+ try {
1256
+ t.closed || t.close();
1257
+ } catch {
1258
+ }
1259
+ }
1260
+ function Ve(t) {
1261
+ try {
1262
+ t.closed || t.focus();
1263
+ } catch {
1264
+ }
1265
+ }
1266
+ function Ze(t) {
1267
+ if (!t) return !0;
1268
+ try {
1269
+ return !!(t.closed || t.innerHeight === 0 || t.innerWidth === 0);
1270
+ } catch {
1271
+ return !0;
1272
+ }
1273
+ }
1274
+ function Ke(t, e, r = {}) {
1275
+ const {
1276
+ initialInterval: n = 100,
1277
+ // Start fast to catch quick closes
1278
+ maxInterval: i = 2e3,
1279
+ // Cap at 2 seconds
1280
+ multiplier: s = 1.5
1281
+ // Exponential backoff multiplier
1282
+ } = r;
1283
+ let o = n, a, c = !1;
1284
+ const d = () => {
1285
+ try {
1286
+ e();
1287
+ } catch (g) {
1288
+ console.error("Error in popup close callback:", g);
1289
+ }
1290
+ }, u = () => {
1291
+ if (!c) {
1292
+ try {
1293
+ if (t.closed) {
1294
+ d();
1295
+ return;
1296
+ }
1297
+ } catch {
1298
+ d();
1299
+ return;
1300
+ }
1301
+ o = Math.min(o * s, i), a = setTimeout(u, o);
1302
+ }
1303
+ };
1304
+ return a = setTimeout(u, o), () => {
1305
+ c = !0, clearTimeout(a);
1306
+ };
1307
+ }
1308
+ function Qe(t, e) {
1309
+ try {
1310
+ const r = S(e.width, t.outerWidth), n = S(
1311
+ e.height,
1312
+ t.outerHeight
1313
+ );
1314
+ t.resizeTo(r, n);
1315
+ } catch {
1316
+ }
1317
+ }
1318
+ function et(t) {
1319
+ const { doc: e, dimensions: r, uid: n, tag: i } = t, s = e.createElement("div");
1320
+ return s.id = `forgeframe-container-${n}`, s.setAttribute("data-forgeframe-tag", i), Object.assign(s.style, {
1321
+ display: "inline-block",
1322
+ position: "relative",
1323
+ width: w(r.width),
1324
+ height: w(r.height),
1325
+ overflow: "hidden"
1326
+ }), s;
1327
+ }
1328
+ function tt(t) {
1329
+ const { doc: e, dimensions: r, cspNonce: n } = t, i = e.createElement("div");
1330
+ Object.assign(i.style, {
1331
+ display: "flex",
1332
+ alignItems: "center",
1333
+ justifyContent: "center",
1334
+ width: w(r.width),
1335
+ height: w(r.height),
1336
+ backgroundColor: "#f5f5f5",
1337
+ position: "absolute",
1338
+ top: "0",
1339
+ left: "0",
1340
+ zIndex: "100"
1341
+ });
1342
+ const s = e.createElement("div");
1343
+ Object.assign(s.style, {
1344
+ width: "40px",
1345
+ height: "40px",
1346
+ border: "3px solid #e0e0e0",
1347
+ borderTopColor: "#3498db",
1348
+ borderRadius: "50%",
1349
+ animation: "forgeframe-spin 1s linear infinite"
1350
+ });
1351
+ const o = e.createElement("style");
1352
+ return n && o.setAttribute("nonce", n), o.textContent = `
1353
+ @keyframes forgeframe-spin {
1354
+ to { transform: rotate(360deg); }
1355
+ }
1356
+ `, i.appendChild(o), i.appendChild(s), i;
1357
+ }
1358
+ function rt(t, e = 200) {
1359
+ return new Promise((r) => {
1360
+ t.style.opacity = "0", t.style.transition = `opacity ${e}ms ease-in`, t.offsetHeight, t.style.opacity = "1", setTimeout(r, e);
1361
+ });
1362
+ }
1363
+ function nt(t, e = 200) {
1364
+ return new Promise((r) => {
1365
+ t.style.transition = `opacity ${e}ms ease-out`, t.style.opacity = "0", setTimeout(r, e);
1366
+ });
1367
+ }
1368
+ async function it(t, e, r) {
1369
+ e && (await nt(e, 150), e.remove()), r.style.display = "", r.style.visibility = "visible", r.style.opacity = "0", await rt(r, 150);
1370
+ }
1371
+ class M {
1372
+ /** Event emitter for lifecycle events. */
1373
+ event;
1374
+ /** Arbitrary state storage for the component instance. */
1375
+ state = {};
1376
+ /** Data exported by the child component. */
1377
+ exports;
1378
+ /** Data exported from the parent by the child. */
1379
+ parentExports;
1380
+ /** @internal */
1381
+ _uid;
1382
+ /**
1383
+ * Unique instance identifier.
1384
+ * @readonly
1385
+ */
1386
+ get uid() {
1387
+ return this._uid;
1388
+ }
1389
+ /** @internal */
1390
+ options;
1391
+ /** @internal */
1392
+ props;
1393
+ /** @internal */
1394
+ context;
1395
+ /** @internal */
1396
+ messenger;
1397
+ /** @internal */
1398
+ bridge;
1399
+ /** @internal */
1400
+ cleanup;
1401
+ /** @internal */
1402
+ childWindow = null;
1403
+ /** @internal */
1404
+ iframe = null;
1405
+ /** @internal */
1406
+ container = null;
1407
+ /** @internal */
1408
+ prerenderElement = null;
1409
+ /** @internal */
1410
+ initPromise = null;
1411
+ /** @internal */
1412
+ rendered = !1;
1413
+ /** @internal */
1414
+ destroyed = !1;
1415
+ /**
1416
+ * Creates a new ParentComponent instance.
1417
+ *
1418
+ * @param options - Component configuration options
1419
+ * @param props - Initial props to pass to the component
1420
+ */
1421
+ constructor(e, r = {}) {
1422
+ this._uid = we(), this.options = this.normalizeOptions(e), this.context = this.options.defaultContext, this.event = new ne(), this.cleanup = new Ee();
1423
+ const n = this.buildTrustedDomains();
1424
+ this.messenger = new se(this.uid, window, W(), n), this.bridge = new $(this.messenger);
1425
+ const i = this.createPropContext();
1426
+ this.props = Z(r, this.options.props, i), this.setupMessageHandlers(), this.setupCleanup();
1427
+ }
1428
+ /**
1429
+ * Builds the list of trusted domains for messenger communication.
1430
+ * @internal
1431
+ */
1432
+ buildTrustedDomains() {
1433
+ const e = [], r = typeof this.options.url == "function" ? this.options.url(this.props) : this.options.url;
1434
+ try {
1435
+ const n = new URL(r);
1436
+ e.push(n.origin);
1437
+ } catch {
1438
+ }
1439
+ if (this.options.domain) {
1440
+ if (typeof this.options.domain == "string")
1441
+ e.push(this.options.domain);
1442
+ else if (Array.isArray(this.options.domain))
1443
+ e.push(...this.options.domain);
1444
+ else if (this.options.domain instanceof RegExp)
1445
+ return this.options.domain;
1446
+ }
1447
+ return e.length > 0 ? e : void 0;
1448
+ }
1449
+ /**
1450
+ * Renders the component into a DOM container.
1451
+ *
1452
+ * @remarks
1453
+ * This is the primary method for displaying the component. It creates
1454
+ * an iframe or popup, establishes communication with the child, and
1455
+ * handles the prerender/render lifecycle.
1456
+ *
1457
+ * @param container - CSS selector or HTMLElement to render into
1458
+ * @param context - Override the default rendering context (iframe or popup)
1459
+ * @throws Error if component was already destroyed or rendered
1460
+ *
1461
+ * @example
1462
+ * ```typescript
1463
+ * await instance.render('#container');
1464
+ * await instance.render(document.getElementById('target'), 'popup');
1465
+ * ```
1466
+ */
1467
+ async render(e, r) {
1468
+ if (this.destroyed)
1469
+ throw new Error("Component has been destroyed");
1470
+ if (this.rendered)
1471
+ throw new Error("Component has already been rendered");
1472
+ this.context = r ?? this.options.defaultContext, this.checkEligibility(), ke(this.props, this.options.props), this.container = this.resolveContainer(e), this.event.emit(p.PRERENDER), this.callPropCallback("onPrerender"), await this.prerender(), this.event.emit(p.PRERENDERED), this.callPropCallback("onPrerendered"), this.event.emit(p.RENDER), this.callPropCallback("onRender"), await this.open(), await this.waitForChild(), this.context === f.IFRAME && this.iframe && this.prerenderElement && (await it(
1473
+ this.container,
1474
+ this.prerenderElement,
1475
+ this.iframe
1476
+ ), this.prerenderElement = null), this.rendered = !0, this.event.emit(p.RENDERED), this.callPropCallback("onRendered"), this.event.emit(p.DISPLAY), this.callPropCallback("onDisplay");
1477
+ }
1478
+ /**
1479
+ * Renders the component into a container in a different window.
1480
+ *
1481
+ * @remarks
1482
+ * Currently delegates to regular render. Full cross-window rendering
1483
+ * would require additional complexity.
1484
+ *
1485
+ * @param _win - Target window (currently unused)
1486
+ * @param container - CSS selector or HTMLElement to render into
1487
+ * @param context - Override the default rendering context
1488
+ */
1489
+ async renderTo(e, r, n) {
1490
+ return this.render(r, n);
1491
+ }
1492
+ /**
1493
+ * Closes and destroys the component.
1494
+ *
1495
+ * @remarks
1496
+ * Emits the 'close' event before destruction. Safe to call multiple times.
1497
+ */
1498
+ async close() {
1499
+ this.destroyed || (this.event.emit(p.CLOSE), await this.destroy());
1500
+ }
1501
+ /**
1502
+ * Focuses the component window.
1503
+ *
1504
+ * @remarks
1505
+ * For iframes, focuses the iframe element. For popups, brings the window to front.
1506
+ */
1507
+ async focus() {
1508
+ this.context === f.IFRAME && this.iframe ? Xe(this.iframe) : this.context === f.POPUP && this.childWindow && Ve(this.childWindow), this.event.emit(p.FOCUS), this.callPropCallback("onFocus");
1509
+ }
1510
+ /**
1511
+ * Resizes the component to the specified dimensions.
1512
+ *
1513
+ * @param dimensions - New width and height for the component
1514
+ */
1515
+ async resize(e) {
1516
+ this.context === f.IFRAME && this.iframe ? je(this.iframe, e) : this.context === f.POPUP && this.childWindow && Qe(this.childWindow, e), this.event.emit(p.RESIZE, e), this.callPropCallback("onResize", e);
1517
+ }
1518
+ /**
1519
+ * Shows the component if hidden.
1520
+ *
1521
+ * @remarks
1522
+ * Only applicable to iframe context.
1523
+ */
1524
+ async show() {
1525
+ this.context === f.IFRAME && this.iframe && He(this.iframe);
1526
+ }
1527
+ /**
1528
+ * Hides the component.
1529
+ *
1530
+ * @remarks
1531
+ * Only applicable to iframe context.
1532
+ */
1533
+ async hide() {
1534
+ this.context === f.IFRAME && this.iframe && te(this.iframe);
1535
+ }
1536
+ /**
1537
+ * Updates the component props and sends them to the child.
1538
+ *
1539
+ * @remarks
1540
+ * Props are normalized and serialized before being sent to the child window.
1541
+ *
1542
+ * @param newProps - Partial props object to merge with existing props
1543
+ */
1544
+ async updateProps(e) {
1545
+ const r = this.createPropContext();
1546
+ if (this.props = Z(
1547
+ { ...this.props, ...e },
1548
+ this.options.props,
1549
+ r
1550
+ ), this.childWindow && !ce(this.childWindow)) {
1551
+ const n = this.getChildDomain(), i = K(
1552
+ this.props,
1553
+ this.options.props,
1554
+ n,
1555
+ oe(this.childWindow)
1556
+ ), s = Q(
1557
+ i,
1558
+ this.options.props,
1559
+ this.bridge
1560
+ );
1561
+ await this.messenger.send(
1562
+ this.childWindow,
1563
+ n,
1564
+ l.PROPS,
1565
+ s
1566
+ );
1567
+ }
1568
+ this.event.emit(p.PROPS, this.props), this.callPropCallback("onProps", this.props);
1569
+ }
1570
+ /**
1571
+ * Creates a clone of this instance with the same props.
1572
+ *
1573
+ * @returns A new unrendered component instance with identical configuration
1574
+ */
1575
+ clone() {
1576
+ return new M(this.options, this.props);
1577
+ }
1578
+ /**
1579
+ * Checks if the component is eligible to render based on the eligible option.
1580
+ *
1581
+ * @returns True if eligible or no eligibility check defined
1582
+ */
1583
+ isEligible() {
1584
+ return this.options.eligible ? this.options.eligible({ props: this.props }).eligible : !0;
1585
+ }
1586
+ /**
1587
+ * Normalizes component options with default values.
1588
+ * @internal
1589
+ */
1590
+ normalizeOptions(e) {
1591
+ return {
1592
+ ...e,
1593
+ props: e.props ?? {},
1594
+ defaultContext: e.defaultContext ?? f.IFRAME,
1595
+ dimensions: typeof e.dimensions == "function" ? e.dimensions(this.props) : e.dimensions ?? { width: "100%", height: "100%" },
1596
+ timeout: e.timeout ?? 1e4,
1597
+ children: e.children
1598
+ };
1599
+ }
1600
+ /**
1601
+ * Creates the prop context passed to prop callbacks and validators.
1602
+ * @internal
1603
+ */
1604
+ createPropContext() {
1605
+ return {
1606
+ props: this.props,
1607
+ state: this.state,
1608
+ close: () => this.close(),
1609
+ focus: () => this.focus(),
1610
+ onError: (e) => this.handleError(e),
1611
+ container: this.container,
1612
+ uid: this.uid,
1613
+ tag: this.options.tag
1614
+ };
1615
+ }
1616
+ /**
1617
+ * Resolves a container selector or element to an HTMLElement.
1618
+ * @internal
1619
+ */
1620
+ resolveContainer(e) {
1621
+ if (!e)
1622
+ throw new Error("Container is required for rendering");
1623
+ if (typeof e == "string") {
1624
+ const r = document.querySelector(e);
1625
+ if (!r)
1626
+ throw new Error(`Container "${e}" not found`);
1627
+ return r;
1628
+ }
1629
+ return e;
1630
+ }
1631
+ /**
1632
+ * Checks eligibility and throws if component cannot render.
1633
+ * @internal
1634
+ */
1635
+ checkEligibility() {
1636
+ if (!this.options.eligible) return;
1637
+ const e = this.options.eligible({ props: this.props });
1638
+ if (!e.eligible)
1639
+ throw new Error(`Component not eligible: ${e.reason ?? "Unknown reason"}`);
1640
+ }
1641
+ /**
1642
+ * Creates and displays the prerender (loading) content.
1643
+ * @internal
1644
+ */
1645
+ async prerender() {
1646
+ if (!this.container) return;
1647
+ const e = this.options.prerenderTemplate ?? tt, r = this.options.containerTemplate ?? et, n = this.options.dimensions, i = this.props.cspNonce;
1648
+ if (this.context === f.IFRAME) {
1649
+ const c = this.buildWindowName();
1650
+ this.iframe = this.createIframeElement(c), te(this.iframe);
1651
+ }
1652
+ const s = {
1653
+ uid: this.uid,
1654
+ tag: this.options.tag,
1655
+ context: this.context,
1656
+ dimensions: n,
1657
+ props: this.props,
1658
+ doc: document,
1659
+ container: this.container,
1660
+ frame: this.iframe,
1661
+ prerenderFrame: null,
1662
+ close: () => this.close(),
1663
+ focus: () => this.focus(),
1664
+ cspNonce: i
1665
+ };
1666
+ this.prerenderElement = e(s);
1667
+ const o = {
1668
+ uid: this.uid,
1669
+ tag: this.options.tag,
1670
+ context: this.context,
1671
+ dimensions: n,
1672
+ props: this.props,
1673
+ doc: document,
1674
+ container: this.container,
1675
+ frame: this.iframe,
1676
+ prerenderFrame: this.prerenderElement,
1677
+ close: () => this.close(),
1678
+ focus: () => this.focus(),
1679
+ cspNonce: i
1680
+ }, a = r(o);
1681
+ a && (this.container.appendChild(a), this.container = a), this.prerenderElement && !this.prerenderElement.parentNode && this.container.appendChild(this.prerenderElement), this.iframe && !this.iframe.parentNode && this.container.appendChild(this.iframe);
1682
+ }
1683
+ /**
1684
+ * Creates an iframe element without setting src (for prerender phase).
1685
+ * The window name is set immediately as it carries the payload for the child.
1686
+ * @internal
1687
+ */
1688
+ createIframeElement(e) {
1689
+ const r = document.createElement("iframe"), n = this.options.dimensions, i = typeof this.options.attributes == "function" ? this.options.attributes(this.props) : this.options.attributes ?? {}, s = typeof this.options.style == "function" ? this.options.style(this.props) : this.options.style ?? {};
1690
+ r.name = e, r.setAttribute("frameborder", "0"), r.setAttribute("allowtransparency", "true"), r.setAttribute("scrolling", "auto"), n.width !== void 0 && (r.style.width = typeof n.width == "number" ? `${n.width}px` : n.width), n.height !== void 0 && (r.style.height = typeof n.height == "number" ? `${n.height}px` : n.height);
1691
+ for (const [o, a] of Object.entries(i))
1692
+ a !== void 0 && (typeof a == "boolean" ? a && r.setAttribute(o, "") : r.setAttribute(o, a));
1693
+ for (const [o, a] of Object.entries(s)) {
1694
+ if (a === void 0) continue;
1695
+ const c = typeof a == "number" ? `${a}px` : a;
1696
+ r.style.setProperty(
1697
+ o.replace(/([A-Z])/g, "-$1").toLowerCase(),
1698
+ String(c)
1699
+ );
1700
+ }
1701
+ return i.sandbox || r.setAttribute(
1702
+ "sandbox",
1703
+ "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
1704
+ ), r;
1705
+ }
1706
+ /**
1707
+ * Opens the child window (iframe or popup).
1708
+ * @internal
1709
+ */
1710
+ async open() {
1711
+ const e = this.buildUrl();
1712
+ if (this.context === f.IFRAME) {
1713
+ if (!this.iframe)
1714
+ throw new Error("Iframe not created during prerender");
1715
+ this.iframe.src = e, this.childWindow = this.iframe.contentWindow;
1716
+ } else {
1717
+ const r = this.buildWindowName();
1718
+ this.childWindow = Ge({
1719
+ url: e,
1720
+ name: r,
1721
+ dimensions: this.options.dimensions
1722
+ });
1723
+ const n = Ke(this.childWindow, () => {
1724
+ this.destroy();
1725
+ });
1726
+ this.cleanup.register(n);
1727
+ }
1728
+ this.childWindow && ve(this.uid, this.childWindow);
1729
+ }
1730
+ /**
1731
+ * Builds the URL for the child window including query parameters.
1732
+ * @internal
1733
+ */
1734
+ buildUrl() {
1735
+ const e = typeof this.options.url == "function" ? this.options.url(this.props) : this.options.url, n = We(this.props, this.options.props).toString();
1736
+ if (!n) return e;
1737
+ const i = e.includes("?") ? "&" : "?";
1738
+ return `${e}${i}${n}`;
1739
+ }
1740
+ /**
1741
+ * Builds the window.name payload for the child window.
1742
+ * @internal
1743
+ */
1744
+ buildWindowName() {
1745
+ const e = this.getChildDomain(), r = K(
1746
+ this.props,
1747
+ this.options.props,
1748
+ e,
1749
+ !1
1750
+ // Assume cross-domain for initial payload
1751
+ ), n = Q(
1752
+ r,
1753
+ this.options.props,
1754
+ this.bridge
1755
+ ), i = this.buildChildrenRefs(), s = xe({
1756
+ uid: this.uid,
1757
+ tag: this.options.tag,
1758
+ context: this.context,
1759
+ parentDomain: W(),
1760
+ props: n,
1761
+ exports: this.createParentExports(),
1762
+ children: i
1763
+ });
1764
+ return Te(s);
1765
+ }
1766
+ /**
1767
+ * Builds component references for nested child components.
1768
+ * @internal
1769
+ */
1770
+ buildChildrenRefs() {
1771
+ if (!this.options.children) return;
1772
+ const e = this.options.children({ props: this.props }), r = {};
1773
+ for (const [n, i] of Object.entries(e)) {
1774
+ const s = i;
1775
+ r[n] = {
1776
+ tag: s.tag ?? n,
1777
+ url: typeof s.url == "function" ? s.url.toString() : s.url ?? ""
1778
+ };
1779
+ }
1780
+ return Object.keys(r).length > 0 ? r : void 0;
1781
+ }
1782
+ /**
1783
+ * Creates the exports object sent to the child.
1784
+ * @internal
1785
+ */
1786
+ createParentExports() {
1787
+ return {
1788
+ init: l.INIT,
1789
+ close: l.CLOSE,
1790
+ resize: l.RESIZE,
1791
+ show: l.SHOW,
1792
+ hide: l.HIDE,
1793
+ onError: l.ERROR,
1794
+ updateProps: l.PROPS,
1795
+ export: l.EXPORT
1796
+ };
1797
+ }
1798
+ /**
1799
+ * Extracts the origin domain from the component URL.
1800
+ * @internal
1801
+ */
1802
+ getChildDomain() {
1803
+ const e = typeof this.options.url == "function" ? this.options.url(this.props) : this.options.url;
1804
+ try {
1805
+ return new URL(e, window.location.origin).origin;
1806
+ } catch {
1807
+ return "*";
1808
+ }
1809
+ }
1810
+ /**
1811
+ * Waits for the child to send the init message.
1812
+ * @internal
1813
+ */
1814
+ async waitForChild() {
1815
+ this.initPromise = ie();
1816
+ try {
1817
+ await Ce(
1818
+ this.initPromise.promise,
1819
+ this.options.timeout,
1820
+ `Child component "${this.options.tag}" (uid: ${this._uid}) did not initialize within ${this.options.timeout}ms. Check that the child page loads correctly and calls the initialization code.`
1821
+ );
1822
+ } catch (e) {
1823
+ throw this.handleError(e), e;
1824
+ }
1825
+ }
1826
+ /**
1827
+ * Sets up message handlers for child communication.
1828
+ * @internal
1829
+ */
1830
+ setupMessageHandlers() {
1831
+ this.messenger.on(l.INIT, () => (this.initPromise && this.initPromise.resolve(), { success: !0 })), this.messenger.on(l.CLOSE, async () => (await this.close(), { success: !0 })), this.messenger.on(l.RESIZE, async (e) => (await this.resize(e), { success: !0 })), this.messenger.on(l.FOCUS, async () => (await this.focus(), { success: !0 })), this.messenger.on(l.SHOW, async () => (await this.show(), { success: !0 })), this.messenger.on(l.HIDE, async () => (await this.hide(), { success: !0 })), this.messenger.on(
1832
+ l.ERROR,
1833
+ async (e) => {
1834
+ const r = new Error(e.message);
1835
+ return r.stack = e.stack, this.handleError(r), { success: !0 };
1836
+ }
1837
+ ), this.messenger.on(l.EXPORT, async (e) => (this.exports = e, { success: !0 })), this.messenger.on(l.PARENT_EXPORT, async (e) => (this.parentExports = e, { success: !0 })), this.messenger.on(
1838
+ l.GET_SIBLINGS,
1839
+ async (e) => {
1840
+ const r = [], n = lt(e.tag);
1841
+ if (n)
1842
+ for (const i of n.instances)
1843
+ i.uid !== e.uid && r.push({
1844
+ uid: i.uid,
1845
+ tag: e.tag,
1846
+ exports: i.exports
1847
+ });
1848
+ return r;
1849
+ }
1850
+ );
1851
+ }
1852
+ /**
1853
+ * Registers cleanup handlers for the instance.
1854
+ * @internal
1855
+ */
1856
+ setupCleanup() {
1857
+ this.cleanup.register(() => {
1858
+ this.messenger.destroy(), this.bridge.destroy(), this.event.removeAllListeners(), Ae(this.uid);
1859
+ });
1860
+ }
1861
+ /**
1862
+ * Handles errors by emitting events and calling callbacks.
1863
+ * @internal
1864
+ */
1865
+ handleError(e) {
1866
+ this.event.emit(p.ERROR, e), this.callPropCallback("onError", e);
1867
+ }
1868
+ /**
1869
+ * Calls a prop callback if it exists.
1870
+ * @internal
1871
+ */
1872
+ callPropCallback(e, ...r) {
1873
+ const n = this.props[e];
1874
+ if (typeof n == "function")
1875
+ try {
1876
+ const i = n(...r);
1877
+ i && typeof i == "object" && "catch" in i && typeof i.catch == "function" && i.catch((s) => {
1878
+ console.error(`Error in async ${e} callback:`, s);
1879
+ });
1880
+ } catch (i) {
1881
+ console.error(`Error in ${e} callback:`, i);
1882
+ }
1883
+ }
1884
+ /**
1885
+ * Destroys the component and cleans up all resources.
1886
+ * @internal
1887
+ */
1888
+ async destroy() {
1889
+ this.destroyed || (this.destroyed = !0, this.initPromise && (this.initPromise.reject(
1890
+ new Error(`Component "${this.options.tag}" was destroyed before initialization completed`)
1891
+ ), this.initPromise = null), this.iframe && (Be(this.iframe), this.iframe = null), this.context === f.POPUP && this.childWindow && Ye(this.childWindow), this.childWindow = null, this.prerenderElement && (this.prerenderElement.remove(), this.prerenderElement = null), await this.cleanup.cleanup(), this.event.emit(p.DESTROY), this.callPropCallback("onDestroy"));
1892
+ }
1893
+ }
1894
+ class st {
1895
+ /**
1896
+ * Creates a new ChildComponent instance.
1897
+ *
1898
+ * @param payload - The payload parsed from window.name
1899
+ * @param propDefinitions - Optional prop definitions for deserialization
1900
+ */
1901
+ constructor(e, r = {}) {
1902
+ this.propDefinitions = r, this.uid = e.uid, this.tag = e.tag, this.parentDomain = e.parentDomain, this.event = new ne(), this.messenger = new se(this.uid, window, W(), this.parentDomain), this.setupMessageHandlers(), this.parentWindow = this.resolveParentWindow(), this.bridge = new $(this.messenger), this.xprops = this.buildXProps(e), window.xprops = this.xprops, this.sendInit();
1903
+ }
1904
+ /** The xprops object containing props and control methods. */
1905
+ xprops;
1906
+ /** Event emitter for lifecycle events. */
1907
+ event;
1908
+ /** @internal */
1909
+ uid;
1910
+ /** @internal */
1911
+ tag;
1912
+ /** @internal */
1913
+ parentWindow;
1914
+ /** @internal */
1915
+ parentDomain;
1916
+ /** @internal */
1917
+ messenger;
1918
+ /** @internal */
1919
+ bridge;
1920
+ /** @internal */
1921
+ propsHandlers = /* @__PURE__ */ new Set();
1922
+ /** @internal */
1923
+ parentProps;
1924
+ /** @internal */
1925
+ initError = null;
1926
+ /**
1927
+ * Returns the xprops object.
1928
+ *
1929
+ * @returns The xprops object with props and control methods
1930
+ */
1931
+ getProps() {
1932
+ return this.xprops;
1933
+ }
1934
+ /**
1935
+ * Resolves the parent window reference (iframe parent or popup opener).
1936
+ * @internal
1937
+ */
1938
+ resolveParentWindow() {
1939
+ if (_e()) {
1940
+ const e = be();
1941
+ if (e) return e;
1942
+ }
1943
+ if (Ie()) {
1944
+ const e = Oe();
1945
+ if (e) return e;
1946
+ }
1947
+ throw new Error("Could not resolve parent window");
1948
+ }
1949
+ /**
1950
+ * Builds the xprops object with deserialized props and control methods.
1951
+ * @internal
1952
+ */
1953
+ buildXProps(e) {
1954
+ const r = ee(
1955
+ e.props,
1956
+ this.propDefinitions,
1957
+ this.messenger,
1958
+ this.bridge,
1959
+ this.parentWindow,
1960
+ this.parentDomain
1961
+ );
1962
+ return this.parentProps = r, {
1963
+ ...r,
1964
+ uid: this.uid,
1965
+ tag: this.tag,
1966
+ close: () => this.close(),
1967
+ focus: () => this.focus(),
1968
+ resize: (n) => this.resize(n),
1969
+ show: () => this.show(),
1970
+ hide: () => this.hide(),
1971
+ onProps: (n) => this.onProps(n),
1972
+ onError: (n) => this.onError(n),
1973
+ getParent: () => this.parentWindow,
1974
+ getParentDomain: () => this.parentDomain,
1975
+ export: (n) => this.exportData(n),
1976
+ parent: {
1977
+ props: this.parentProps,
1978
+ export: (n) => this.parentExport(n)
1979
+ },
1980
+ getSiblings: (n) => this.getSiblings(n),
1981
+ children: this.buildChildComponents(e.children)
1982
+ };
1983
+ }
1984
+ /**
1985
+ * Sends initialization message to the parent.
1986
+ * @internal
1987
+ */
1988
+ async sendInit() {
1989
+ try {
1990
+ await this.messenger.send(
1991
+ this.parentWindow,
1992
+ this.parentDomain,
1993
+ l.INIT,
1994
+ { uid: this.uid, tag: this.tag }
1995
+ );
1996
+ } catch (e) {
1997
+ const r = e instanceof Error ? e : new Error(String(e));
1998
+ this.initError = r, this.event.emit(p.ERROR, {
1999
+ type: "init_failed",
2000
+ message: `Failed to initialize child component: ${r.message}`,
2001
+ error: r
2002
+ }), console.error("Failed to send init message:", e);
2003
+ }
2004
+ }
2005
+ /**
2006
+ * Returns the initialization error if one occurred.
2007
+ *
2008
+ * @returns The initialization error or null if successful
2009
+ */
2010
+ getInitError() {
2011
+ return this.initError;
2012
+ }
2013
+ /**
2014
+ * Requests the parent to close this component.
2015
+ * @internal
2016
+ */
2017
+ async close() {
2018
+ await this.messenger.send(
2019
+ this.parentWindow,
2020
+ this.parentDomain,
2021
+ l.CLOSE,
2022
+ {}
2023
+ );
2024
+ }
2025
+ /**
2026
+ * Focuses this window and notifies the parent.
2027
+ * @internal
2028
+ */
2029
+ async focus() {
2030
+ window.focus(), await this.messenger.send(
2031
+ this.parentWindow,
2032
+ this.parentDomain,
2033
+ l.FOCUS,
2034
+ {}
2035
+ );
2036
+ }
2037
+ /**
2038
+ * Requests the parent to resize this component.
2039
+ * @internal
2040
+ */
2041
+ async resize(e) {
2042
+ await this.messenger.send(
2043
+ this.parentWindow,
2044
+ this.parentDomain,
2045
+ l.RESIZE,
2046
+ e
2047
+ );
2048
+ }
2049
+ /**
2050
+ * Requests the parent to show this component.
2051
+ * @internal
2052
+ */
2053
+ async show() {
2054
+ await this.messenger.send(
2055
+ this.parentWindow,
2056
+ this.parentDomain,
2057
+ l.SHOW,
2058
+ {}
2059
+ );
2060
+ }
2061
+ /**
2062
+ * Requests the parent to hide this component.
2063
+ * @internal
2064
+ */
2065
+ async hide() {
2066
+ await this.messenger.send(
2067
+ this.parentWindow,
2068
+ this.parentDomain,
2069
+ l.HIDE,
2070
+ {}
2071
+ );
2072
+ }
2073
+ /**
2074
+ * Subscribes to prop updates from the parent.
2075
+ * @internal
2076
+ */
2077
+ onProps(e) {
2078
+ return this.propsHandlers.add(e), {
2079
+ cancel: () => this.propsHandlers.delete(e)
2080
+ };
2081
+ }
2082
+ /**
2083
+ * Reports an error to the parent.
2084
+ * @internal
2085
+ */
2086
+ async onError(e) {
2087
+ await this.messenger.send(
2088
+ this.parentWindow,
2089
+ this.parentDomain,
2090
+ l.ERROR,
2091
+ {
2092
+ message: e.message,
2093
+ stack: e.stack
2094
+ }
2095
+ );
2096
+ }
2097
+ /**
2098
+ * Exports data or methods to the parent.
2099
+ * @internal
2100
+ */
2101
+ async exportData(e) {
2102
+ await this.messenger.send(
2103
+ this.parentWindow,
2104
+ this.parentDomain,
2105
+ l.EXPORT,
2106
+ e
2107
+ );
2108
+ }
2109
+ /**
2110
+ * Exports data to the parent for bidirectional communication.
2111
+ * @internal
2112
+ */
2113
+ async parentExport(e) {
2114
+ await this.messenger.send(
2115
+ this.parentWindow,
2116
+ this.parentDomain,
2117
+ l.PARENT_EXPORT,
2118
+ e
2119
+ );
2120
+ }
2121
+ /**
2122
+ * Gets information about sibling component instances.
2123
+ * @internal
2124
+ */
2125
+ async getSiblings(e) {
2126
+ return await this.messenger.send(
2127
+ this.parentWindow,
2128
+ this.parentDomain,
2129
+ l.GET_SIBLINGS,
2130
+ { uid: this.uid, tag: this.tag, options: e }
2131
+ ) ?? [];
2132
+ }
2133
+ /**
2134
+ * Builds child component factories from refs passed by the parent.
2135
+ * @internal
2136
+ */
2137
+ buildChildComponents(e) {
2138
+ if (!e) return;
2139
+ const r = {};
2140
+ for (const [n, i] of Object.entries(e))
2141
+ try {
2142
+ r[n] = fe({
2143
+ tag: i.tag,
2144
+ url: i.url,
2145
+ props: i.props,
2146
+ dimensions: i.dimensions,
2147
+ defaultContext: i.defaultContext
2148
+ });
2149
+ } catch (s) {
2150
+ console.warn(`Failed to create child component "${n}":`, s);
2151
+ }
2152
+ return Object.keys(r).length > 0 ? r : void 0;
2153
+ }
2154
+ /**
2155
+ * Sets up message handlers for parent communication.
2156
+ * @internal
2157
+ */
2158
+ setupMessageHandlers() {
2159
+ this.messenger.on(l.PROPS, (e) => {
2160
+ try {
2161
+ const r = ee(
2162
+ e,
2163
+ this.propDefinitions,
2164
+ this.messenger,
2165
+ this.bridge,
2166
+ this.parentWindow,
2167
+ this.parentDomain
2168
+ );
2169
+ Object.assign(this.xprops, r);
2170
+ for (const n of this.propsHandlers)
2171
+ try {
2172
+ n(r);
2173
+ } catch (i) {
2174
+ console.error("Error in props handler:", i);
2175
+ }
2176
+ return this.event.emit(p.PROPS, r), { success: !0 };
2177
+ } catch (r) {
2178
+ const n = r instanceof Error ? r : new Error(String(r));
2179
+ throw console.error("Error deserializing props:", n), this.event.emit(p.ERROR, n), n;
2180
+ }
2181
+ });
2182
+ }
2183
+ /**
2184
+ * Destroys the child component and cleans up resources.
2185
+ */
2186
+ destroy() {
2187
+ this.messenger.destroy(), this.bridge.destroy(), this.event.removeAllListeners(), this.propsHandlers.clear();
2188
+ }
2189
+ }
2190
+ let _ = null;
2191
+ function pe(t) {
2192
+ if (_)
2193
+ return _;
2194
+ if (!de())
2195
+ return null;
2196
+ const e = De();
2197
+ return e ? (_ = new st(
2198
+ e,
2199
+ t
2200
+ ), _) : (console.error("Failed to parse ForgeFrame payload from window.name"), null);
2201
+ }
2202
+ function ot() {
2203
+ return de();
2204
+ }
2205
+ function at() {
2206
+ return window.xprops;
2207
+ }
2208
+ const P = /* @__PURE__ */ new Map();
2209
+ function ct(t) {
2210
+ if (!t.tag)
2211
+ throw new Error("Component tag is required");
2212
+ if (!/^[a-z][a-z0-9-]*$/.test(t.tag))
2213
+ throw new Error(
2214
+ `Invalid component tag "${t.tag}". Must start with lowercase letter and contain only lowercase letters, numbers, and hyphens.`
2215
+ );
2216
+ if (!t.url)
2217
+ throw new Error("Component url is required");
2218
+ if (typeof t.url == "string")
2219
+ try {
2220
+ new URL(t.url, window.location.origin);
2221
+ } catch {
2222
+ throw new Error(
2223
+ `Invalid component URL "${t.url}". Must be a valid absolute or relative URL.`
2224
+ );
2225
+ }
2226
+ if (P.has(t.tag))
2227
+ throw new Error(`Component "${t.tag}" is already registered`);
2228
+ }
2229
+ function fe(t) {
2230
+ ct(t);
2231
+ const e = [];
2232
+ let r;
2233
+ if (Y(t.tag)) {
2234
+ const i = pe(t.props);
2235
+ i && (r = i.xprops);
2236
+ }
2237
+ const n = function(i = {}) {
2238
+ const s = new M(t, i);
2239
+ return e.push(s), s.event.once("destroy", () => {
2240
+ const o = e.indexOf(s);
2241
+ o !== -1 && e.splice(o, 1);
2242
+ }), s;
2243
+ };
2244
+ return n.instances = e, n.isChild = () => Y(t.tag), n.xprops = r, n.canRenderTo = async (i) => {
2245
+ try {
2246
+ return !!(oe(i) || t.domain);
2247
+ } catch {
2248
+ return !1;
2249
+ }
2250
+ }, P.set(t.tag, n), n;
2251
+ }
2252
+ function lt(t) {
2253
+ return P.get(t);
2254
+ }
2255
+ async function dt(t) {
2256
+ await t.close();
2257
+ }
2258
+ async function me(t) {
2259
+ const e = P.get(t);
2260
+ if (!e) return;
2261
+ const r = [...e.instances];
2262
+ await Promise.all(r.map((n) => n.close()));
2263
+ }
2264
+ async function ht() {
2265
+ const t = Array.from(P.keys());
2266
+ await Promise.all(t.map((e) => me(e)));
2267
+ }
2268
+ function ut(t, e) {
2269
+ const { React: r } = e, { createElement: n, useRef: i, useEffect: s, useState: o, forwardRef: a } = r, c = a(
2270
+ function(g, R) {
2271
+ const {
2272
+ onRendered: U,
2273
+ onError: O,
2274
+ onClose: L,
2275
+ context: ye,
2276
+ className: q,
2277
+ style: B,
2278
+ ...x
2279
+ } = g, b = i(null), D = i(null), [j, ge] = o(null);
2280
+ return s(() => {
2281
+ const C = b.current;
2282
+ if (!C) return;
2283
+ const m = t(x);
2284
+ return D.current = m, U && m.event.once("rendered", U), L && m.event.once("close", L), O && m.event.on("error", O), m.render(C, ye).catch((H) => {
2285
+ ge(H), O?.(H);
2286
+ }), () => {
2287
+ m.close().catch(() => {
2288
+ }), D.current = null;
2289
+ };
2290
+ }, []), s(() => {
2291
+ const C = D.current;
2292
+ C && C.updateProps(x).catch((m) => {
2293
+ O?.(m);
2294
+ });
2295
+ }, [JSON.stringify(x)]), s(() => {
2296
+ R && typeof R == "object" && b.current && (R.current = b.current);
2297
+ }, [R]), j ? n(
2298
+ "div",
2299
+ {
2300
+ className: q,
2301
+ style: { color: "red", padding: "16px", ...B }
2302
+ },
2303
+ `Error: ${j.message}`
2304
+ ) : n("div", {
2305
+ ref: b,
2306
+ className: q,
2307
+ style: {
2308
+ display: "inline-block",
2309
+ ...B
2310
+ }
2311
+ });
2312
+ }
2313
+ ), d = `ForgeFrame(${t.name || "Component"})`;
2314
+ return c.displayName = d, c;
2315
+ }
2316
+ function pt(t) {
2317
+ return function(r) {
2318
+ return ut(r, { React: t });
2319
+ };
2320
+ }
2321
+ pe();
2322
+ const ft = {
2323
+ /**
2324
+ * Create a new component definition.
2325
+ *
2326
+ * @remarks
2327
+ * This is the main entry point for defining components. Returns a
2328
+ * component factory function that can be called to create instances.
2329
+ *
2330
+ * @example
2331
+ * ```typescript
2332
+ * const MyComponent = ForgeFrame.create({
2333
+ * tag: 'my-component',
2334
+ * url: 'https://example.com/component',
2335
+ * props: {
2336
+ * onLogin: { type: ForgeFrame.PROP_TYPE.FUNCTION },
2337
+ * },
2338
+ * });
2339
+ *
2340
+ * const instance = MyComponent({ onLogin: (user) => {} });
2341
+ * await instance.render('#container');
2342
+ * ```
2343
+ */
2344
+ create: fe,
2345
+ /**
2346
+ * Destroy a single component instance.
2347
+ *
2348
+ * @param instance - The component instance to destroy
2349
+ */
2350
+ destroy: dt,
2351
+ /**
2352
+ * Destroy all instances of a specific component by tag.
2353
+ *
2354
+ * @param tag - The component tag name
2355
+ */
2356
+ destroyComponents: me,
2357
+ /**
2358
+ * Destroy all ForgeFrame component instances.
2359
+ */
2360
+ destroyAll: ht,
2361
+ /**
2362
+ * Check if the current window is a child component context.
2363
+ *
2364
+ * @returns True if running inside a ForgeFrame iframe/popup
2365
+ */
2366
+ isChild: ot,
2367
+ /**
2368
+ * Get xprops from the current child window.
2369
+ *
2370
+ * @returns The xprops object if in child context, undefined otherwise
2371
+ */
2372
+ getXProps: at,
2373
+ /**
2374
+ * Prop type constants for defining component props.
2375
+ * @see {@link PROP_TYPE}
2376
+ */
2377
+ PROP_TYPE: h,
2378
+ /**
2379
+ * Serialization strategy constants.
2380
+ * @see {@link PROP_SERIALIZATION}
2381
+ */
2382
+ PROP_SERIALIZATION: I,
2383
+ /**
2384
+ * Rendering context constants (IFRAME, POPUP).
2385
+ * @see {@link CONTEXT}
2386
+ */
2387
+ CONTEXT: f,
2388
+ /**
2389
+ * Lifecycle event name constants.
2390
+ * @see {@link EVENT}
2391
+ */
2392
+ EVENT: p,
2393
+ /**
2394
+ * Error thrown when popup window fails to open.
2395
+ */
2396
+ PopupOpenError: ue,
2397
+ /**
2398
+ * Current library version.
2399
+ */
2400
+ VERSION: re
2401
+ };
2402
+ export {
2403
+ f as CONTEXT,
2404
+ p as EVENT,
2405
+ ft as ForgeFrame,
2406
+ I as PROP_SERIALIZATION,
2407
+ h as PROP_TYPE,
2408
+ ue as PopupOpenError,
2409
+ re as VERSION,
2410
+ fe as create,
2411
+ ut as createReactDriver,
2412
+ ft as default,
2413
+ dt as destroy,
2414
+ ht as destroyAll,
2415
+ me as destroyComponents,
2416
+ at as getXProps,
2417
+ ot as isChild,
2418
+ pt as withReactDriver
2419
+ };