forgeframe 0.0.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.
@@ -0,0 +1,1008 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Type definitions for ForgeFrame cross-domain component framework.
4
+ *
5
+ * @remarks
6
+ * This module exports all the TypeScript interfaces and types used throughout
7
+ * the ForgeFrame library. These types enable type-safe component creation,
8
+ * prop handling, and cross-domain communication.
9
+ */
10
+ import type { ContextType, SerializationType, EventType } from './constants';
11
+ import type { StandardSchemaV1, InferOutput } from './props/schema';
12
+ /**
13
+ * Pattern for matching domains in security configurations.
14
+ *
15
+ * @remarks
16
+ * Can be a single domain string, a RegExp pattern, or an array of domain strings.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Single domain
21
+ * const domain: DomainMatcher = 'https://example.com';
22
+ *
23
+ * // RegExp pattern
24
+ * const pattern: DomainMatcher = /^https:\/\/.*\.example\.com$/;
25
+ *
26
+ * // Multiple domains
27
+ * const domains: DomainMatcher = ['https://a.com', 'https://b.com'];
28
+ * ```
29
+ *
30
+ * @public
31
+ */
32
+ export type DomainMatcher = string | RegExp | string[];
33
+ /**
34
+ * Component dimension specification.
35
+ *
36
+ * @remarks
37
+ * Dimensions can be specified as CSS values (strings) or pixel numbers.
38
+ *
39
+ * @public
40
+ */
41
+ export interface Dimensions {
42
+ /** Width of the component (e.g., '100%', 400, '500px') */
43
+ width?: string | number;
44
+ /** Height of the component (e.g., '100%', 300, '400px') */
45
+ height?: string | number;
46
+ }
47
+ /**
48
+ * Configuration for automatic component resizing.
49
+ *
50
+ * @remarks
51
+ * When enabled, the consumer will automatically resize the iframe
52
+ * based on the host content dimensions.
53
+ *
54
+ * @public
55
+ */
56
+ export interface AutoResizeOptions {
57
+ /** Enable automatic width resizing */
58
+ width?: boolean;
59
+ /** Enable automatic height resizing */
60
+ height?: boolean;
61
+ /** CSS selector of element to measure for auto-resize */
62
+ element?: string;
63
+ }
64
+ /**
65
+ * HTML attributes that can be applied to an iframe element.
66
+ *
67
+ * @remarks
68
+ * These attributes are passed directly to the iframe element when rendering.
69
+ *
70
+ * @public
71
+ */
72
+ export interface IframeAttributes {
73
+ /** Title attribute for accessibility */
74
+ title?: string;
75
+ /** Permissions policy (e.g., 'camera; microphone') */
76
+ allow?: string;
77
+ /** Allow fullscreen mode */
78
+ allowFullscreen?: boolean;
79
+ /** Loading strategy */
80
+ loading?: 'lazy' | 'eager';
81
+ /** Referrer policy */
82
+ referrerPolicy?: ReferrerPolicy;
83
+ /** Sandbox restrictions */
84
+ sandbox?: string;
85
+ /** Additional custom attributes */
86
+ [key: string]: string | boolean | undefined;
87
+ }
88
+ /**
89
+ * CSS styles that can be applied to the iframe element.
90
+ *
91
+ * @remarks
92
+ * These styles are applied directly to the iframe's style property.
93
+ * Common use cases include setting borders, shadows, border-radius, etc.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const styles: IframeStyles = {
98
+ * border: 'none',
99
+ * borderRadius: '8px',
100
+ * boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
101
+ * };
102
+ * ```
103
+ *
104
+ * @public
105
+ */
106
+ export interface IframeStyles {
107
+ /** CSS properties to apply to the iframe */
108
+ [key: string]: string | number | undefined;
109
+ }
110
+ /**
111
+ * Result of an eligibility check for component rendering.
112
+ *
113
+ * @public
114
+ */
115
+ export interface EligibilityResult {
116
+ /** Whether the component is eligible to render */
117
+ eligible: boolean;
118
+ /** Reason for ineligibility (if not eligible) */
119
+ reason?: string;
120
+ }
121
+ /**
122
+ * Context object passed to prop value functions and decorators.
123
+ *
124
+ * @typeParam P - The props type for the component
125
+ *
126
+ * @remarks
127
+ * This context provides access to component state and methods during
128
+ * prop normalization and decoration.
129
+ *
130
+ * @public
131
+ */
132
+ export interface PropContext<P> {
133
+ /** Current props values */
134
+ props: P;
135
+ /** Component state object */
136
+ state: Record<string, unknown>;
137
+ /** Close the component */
138
+ close: () => Promise<void>;
139
+ /** Focus the component */
140
+ focus: () => Promise<void>;
141
+ /** Report an error */
142
+ onError: (err: Error) => void;
143
+ /** Container element (null during prerender) */
144
+ container: HTMLElement | null;
145
+ /** Unique instance identifier */
146
+ uid: string;
147
+ /** Component tag name */
148
+ tag: string;
149
+ }
150
+ /**
151
+ * Definition for a single component prop.
152
+ *
153
+ * @typeParam T - The type of the prop value
154
+ * @typeParam P - The props type for the component
155
+ *
156
+ * @remarks
157
+ * Prop definitions control how individual props are validated, serialized,
158
+ * and passed between consumer and host components.
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * import { prop } from 'forgeframe';
163
+ *
164
+ * const propDef: PropDefinition<string> = {
165
+ * schema: prop.string(),
166
+ * required: true,
167
+ * default: 'hello',
168
+ * validate: ({ value }) => {
169
+ * if (value.length > 100) throw new Error('Too long');
170
+ * },
171
+ * };
172
+ * ```
173
+ *
174
+ * @public
175
+ */
176
+ export interface PropDefinition<T = unknown, P = Record<string, unknown>> {
177
+ /**
178
+ * Standard Schema validator for type checking and validation.
179
+ *
180
+ * @remarks
181
+ * Accepts any StandardSchemaV1-compliant schema including ForgeFrame's
182
+ * built-in `prop.*` schemas, Zod, Valibot, ArkType, and others.
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * import { prop } from 'forgeframe';
187
+ * import { z } from 'zod';
188
+ *
189
+ * const props = {
190
+ * // Using ForgeFrame's prop schemas
191
+ * name: prop.string().min(1),
192
+ * count: prop.number().default(0),
193
+ *
194
+ * // Or using Zod schemas
195
+ * email: { schema: z.string().email(), required: true },
196
+ * };
197
+ * ```
198
+ *
199
+ * @see https://standardschema.dev/
200
+ */
201
+ schema?: StandardSchemaV1<unknown, T>;
202
+ /** Whether the prop is required */
203
+ required?: boolean;
204
+ /** Default value or function returning default value */
205
+ default?: T | ((ctx: PropContext<P>) => T);
206
+ /** Function to compute the prop value */
207
+ value?: (ctx: PropContext<P>) => T;
208
+ /** Whether to send this prop to the host window (default: true) */
209
+ sendToHost?: boolean;
210
+ /** Only send if consumer and host are same domain */
211
+ sameDomain?: boolean;
212
+ /** List of trusted domains that can receive this prop */
213
+ trustedDomains?: DomainMatcher[];
214
+ /** Serialization strategy for cross-domain transfer */
215
+ serialization?: SerializationType;
216
+ /** Pass prop via URL query parameter */
217
+ queryParam?: boolean | string | ((opts: {
218
+ value: T;
219
+ }) => string);
220
+ /** Pass prop via POST body parameter */
221
+ bodyParam?: boolean | string | ((opts: {
222
+ value: T;
223
+ }) => string);
224
+ /** Validate the prop value (throw to reject) */
225
+ validate?: (opts: {
226
+ value: T;
227
+ props: P;
228
+ }) => void;
229
+ /** Transform the prop value in consumer context */
230
+ decorate?: (opts: {
231
+ value: T;
232
+ props: P;
233
+ }) => T;
234
+ /** Transform the prop value in host context */
235
+ hostDecorate?: (opts: {
236
+ value: T;
237
+ props: P;
238
+ }) => T;
239
+ /** Alternative name for the prop */
240
+ alias?: string;
241
+ }
242
+ /**
243
+ * Map of prop names to their definitions.
244
+ *
245
+ * @typeParam P - The props type for the component
246
+ *
247
+ * @public
248
+ */
249
+ export type PropsDefinition<P> = {
250
+ [K in keyof P]?: PropDefinition<P[K], P>;
251
+ };
252
+ /**
253
+ * Infers the output type from a Standard Schema.
254
+ *
255
+ * @typeParam S - The Standard Schema type
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * import { z } from 'zod';
260
+ * const schema = z.object({ name: z.string() });
261
+ * type User = InferSchemaOutput<typeof schema>; // { name: string }
262
+ * ```
263
+ *
264
+ * @public
265
+ */
266
+ export type InferSchemaOutput<S extends StandardSchemaV1> = InferOutput<S>;
267
+ /**
268
+ * Helper type for creating schema-based prop definitions with full type inference.
269
+ *
270
+ * @typeParam S - The Standard Schema type
271
+ * @typeParam P - The props type for the component
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * import { z } from 'zod';
276
+ *
277
+ * const userSchema = z.object({ name: z.string(), age: z.number() });
278
+ *
279
+ * type UserPropDef = SchemaPropDefinition<typeof userSchema>;
280
+ * // Equivalent to: PropDefinition<{ name: string; age: number }> with schema
281
+ * ```
282
+ *
283
+ * @public
284
+ */
285
+ export type SchemaPropDefinition<S extends StandardSchemaV1, P = Record<string, unknown>> = Omit<PropDefinition<InferOutput<S>, P>, 'type'> & {
286
+ schema: S;
287
+ };
288
+ export type { StandardSchemaV1 } from './props/schema';
289
+ /**
290
+ * Context object passed to container and prerender template functions.
291
+ *
292
+ * @typeParam P - The props type for the component
293
+ *
294
+ * @public
295
+ */
296
+ export interface TemplateContext<P = Record<string, unknown>> {
297
+ /** Unique instance identifier */
298
+ uid: string;
299
+ /** Component tag name */
300
+ tag: string;
301
+ /** Rendering context (iframe or popup) */
302
+ context: ContextType;
303
+ /** Component dimensions */
304
+ dimensions: Dimensions;
305
+ /** Current props */
306
+ props: P;
307
+ /** Document object for creating elements */
308
+ doc: Document;
309
+ /** Container element */
310
+ container: HTMLElement;
311
+ /** The iframe element (null for popup context) */
312
+ frame: HTMLIFrameElement | null;
313
+ /** The prerender/loading element (from prerenderTemplate) */
314
+ prerenderFrame: HTMLElement | null;
315
+ /** Close the component */
316
+ close: () => Promise<void>;
317
+ /** Focus the component */
318
+ focus: () => Promise<void>;
319
+ }
320
+ /**
321
+ * Function that creates a custom container element for the component.
322
+ *
323
+ * @typeParam P - The props type for the component
324
+ *
325
+ * @param ctx - Template context with component info
326
+ * @returns The container element or null to use default
327
+ *
328
+ * @public
329
+ */
330
+ export type ContainerTemplate<P = Record<string, unknown>> = (ctx: TemplateContext<P>) => HTMLElement | null;
331
+ /**
332
+ * Function that creates a custom prerender (loading) element.
333
+ *
334
+ * @typeParam P - The props type for the component
335
+ *
336
+ * @param ctx - Template context with component info
337
+ * @returns The prerender element or null for no prerender
338
+ *
339
+ * @public
340
+ */
341
+ export type PrerenderTemplate<P = Record<string, unknown>> = (ctx: TemplateContext<P>) => HTMLElement | null;
342
+ /**
343
+ * Function that returns nested components for composition.
344
+ *
345
+ * @typeParam P - The props type for the consumer component
346
+ *
347
+ * @remarks
348
+ * Nested components can be rendered within the host component's iframe/popup.
349
+ *
350
+ * @param props - Object containing the consumer's props
351
+ * @returns Map of nested component names to ForgeFrameComponent instances
352
+ *
353
+ * @public
354
+ */
355
+ export type ChildrenDefinition<P = Record<string, unknown>> = (props: {
356
+ props: P;
357
+ }) => Record<string, ForgeFrameComponent>;
358
+ /**
359
+ * Serializable reference to a host component for cross-domain transfer.
360
+ *
361
+ * @internal
362
+ */
363
+ export interface HostComponentRef {
364
+ /** Component tag name */
365
+ tag: string;
366
+ /** Component URL (or stringified function) */
367
+ url: string | ((props: Record<string, unknown>) => string);
368
+ /** Prop definitions */
369
+ props?: PropsDefinition<Record<string, unknown>>;
370
+ /** Default dimensions */
371
+ dimensions?: Dimensions;
372
+ /** Default rendering context */
373
+ defaultContext?: ContextType;
374
+ }
375
+ /**
376
+ * Configuration options for creating a component.
377
+ *
378
+ * @typeParam P - The props type for the component
379
+ *
380
+ * @remarks
381
+ * These options are passed to `ForgeFrame.create()` to define a new component.
382
+ *
383
+ * @example
384
+ * ```typescript
385
+ * import { prop } from 'forgeframe';
386
+ *
387
+ * const options: ComponentOptions<MyProps> = {
388
+ * tag: 'my-component',
389
+ * url: 'https://example.com/component',
390
+ * props: {
391
+ * name: prop.string().required(),
392
+ * },
393
+ * dimensions: { width: 400, height: 300 },
394
+ * };
395
+ * ```
396
+ *
397
+ * @public
398
+ */
399
+ export interface ComponentOptions<P = Record<string, unknown>> {
400
+ /**
401
+ * Unique tag name for the component.
402
+ *
403
+ * @remarks
404
+ * Must start with a lowercase letter and contain only lowercase letters,
405
+ * numbers, and hyphens.
406
+ */
407
+ tag: string;
408
+ /**
409
+ * URL of the host component page, or function that returns URL based on props.
410
+ */
411
+ url: string | ((props: P) => string);
412
+ /**
413
+ * Prop definitions for type checking and serialization.
414
+ */
415
+ props?: PropsDefinition<P>;
416
+ /**
417
+ * Default dimensions for the component.
418
+ */
419
+ dimensions?: Dimensions | ((props: P) => Dimensions);
420
+ /**
421
+ * Configuration for automatic resizing based on content.
422
+ */
423
+ autoResize?: AutoResizeOptions;
424
+ /**
425
+ * Default rendering context (iframe or popup).
426
+ * @defaultValue 'iframe'
427
+ */
428
+ defaultContext?: ContextType;
429
+ /**
430
+ * Allowed host domains for security validation.
431
+ */
432
+ domain?: DomainMatcher;
433
+ /**
434
+ * Restrict which consumer domains can embed this component.
435
+ */
436
+ allowedConsumerDomains?: DomainMatcher;
437
+ /**
438
+ * Custom container template function.
439
+ */
440
+ containerTemplate?: ContainerTemplate<P>;
441
+ /**
442
+ * Custom prerender (loading state) template function.
443
+ */
444
+ prerenderTemplate?: PrerenderTemplate<P>;
445
+ /**
446
+ * Function to check if component is eligible to render.
447
+ */
448
+ eligible?: (opts: {
449
+ props: P;
450
+ }) => EligibilityResult;
451
+ /**
452
+ * Function to validate props before rendering.
453
+ */
454
+ validate?: (opts: {
455
+ props: P;
456
+ }) => void;
457
+ /**
458
+ * Additional HTML attributes for the iframe/popup.
459
+ */
460
+ attributes?: IframeAttributes | ((props: P) => IframeAttributes);
461
+ /**
462
+ * CSS styles to apply to the iframe element.
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * style: {
467
+ * border: 'none',
468
+ * borderRadius: '8px',
469
+ * boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
470
+ * }
471
+ * ```
472
+ */
473
+ style?: IframeStyles | ((props: P) => IframeStyles);
474
+ /**
475
+ * Timeout in milliseconds for host initialization.
476
+ * @defaultValue 10000
477
+ */
478
+ timeout?: number;
479
+ /**
480
+ * Nested components that can be rendered within this component.
481
+ */
482
+ children?: ChildrenDefinition<P>;
483
+ }
484
+ /**
485
+ * Handler function for component events.
486
+ *
487
+ * @typeParam T - The type of data passed to the handler
488
+ *
489
+ * @public
490
+ */
491
+ export type EventHandler<T = unknown> = (data: T) => void | Promise<void>;
492
+ /**
493
+ * Event emitter interface for component lifecycle events.
494
+ *
495
+ * @public
496
+ */
497
+ export interface EventEmitterInterface {
498
+ /**
499
+ * Subscribe to an event.
500
+ *
501
+ * @param event - Event name to listen for
502
+ * @param handler - Handler function to call
503
+ * @returns Unsubscribe function
504
+ */
505
+ on<T = unknown>(event: EventType | string, handler: EventHandler<T>): () => void;
506
+ /**
507
+ * Subscribe to an event for a single emission.
508
+ *
509
+ * @param event - Event name to listen for
510
+ * @param handler - Handler function to call
511
+ * @returns Unsubscribe function
512
+ */
513
+ once<T = unknown>(event: EventType | string, handler: EventHandler<T>): () => void;
514
+ /**
515
+ * Emit an event with optional data.
516
+ *
517
+ * @param event - Event name to emit
518
+ * @param data - Data to pass to handlers
519
+ */
520
+ emit<T = unknown>(event: EventType | string, data?: T): void;
521
+ /**
522
+ * Unsubscribe a handler from an event.
523
+ *
524
+ * @param event - Event name
525
+ * @param handler - Handler to remove (optional, removes all if not provided)
526
+ */
527
+ off(event: EventType | string, handler?: EventHandler): void;
528
+ /**
529
+ * Remove all event listeners.
530
+ */
531
+ removeAllListeners(): void;
532
+ }
533
+ /**
534
+ * Instance of a rendered component.
535
+ *
536
+ * @typeParam P - The props type for the component
537
+ * @typeParam X - The type of exports from the host
538
+ *
539
+ * @remarks
540
+ * Component instances are created by calling the component factory function
541
+ * and provide methods to control the rendered component.
542
+ *
543
+ * @example
544
+ * ```typescript
545
+ * const instance = MyComponent({ name: 'World' });
546
+ * await instance.render('#container');
547
+ * await instance.updateProps({ name: 'Updated' });
548
+ * await instance.close();
549
+ * ```
550
+ *
551
+ * @public
552
+ */
553
+ export interface ForgeFrameComponentInstance<P = Record<string, unknown>, X = unknown> {
554
+ /**
555
+ * Unique instance identifier.
556
+ */
557
+ readonly uid: string;
558
+ /**
559
+ * Render the component into a container.
560
+ *
561
+ * @param container - CSS selector or element to render into
562
+ * @param context - Override the default context (iframe/popup)
563
+ * @returns Promise that resolves when rendering is complete
564
+ */
565
+ render(container?: string | HTMLElement, context?: ContextType): Promise<void>;
566
+ /**
567
+ * Render into a different window's container.
568
+ *
569
+ * @param win - Target window
570
+ * @param container - CSS selector or element in target window
571
+ * @param context - Override the default context
572
+ * @returns Promise that resolves when rendering is complete
573
+ */
574
+ renderTo(win: Window, container?: string | HTMLElement, context?: ContextType): Promise<void>;
575
+ /**
576
+ * Close and destroy the component.
577
+ *
578
+ * @returns Promise that resolves when closed
579
+ */
580
+ close(): Promise<void>;
581
+ /**
582
+ * Focus the component window.
583
+ *
584
+ * @returns Promise that resolves when focused
585
+ */
586
+ focus(): Promise<void>;
587
+ /**
588
+ * Resize the component to new dimensions.
589
+ *
590
+ * @param dimensions - New dimensions
591
+ * @returns Promise that resolves when resized
592
+ */
593
+ resize(dimensions: Dimensions): Promise<void>;
594
+ /**
595
+ * Show the component (if hidden).
596
+ *
597
+ * @returns Promise that resolves when shown
598
+ */
599
+ show(): Promise<void>;
600
+ /**
601
+ * Hide the component.
602
+ *
603
+ * @returns Promise that resolves when hidden
604
+ */
605
+ hide(): Promise<void>;
606
+ /**
607
+ * Update the component's props.
608
+ *
609
+ * @param props - Partial props to merge with existing
610
+ * @returns Promise that resolves when props are updated
611
+ */
612
+ updateProps(props: Partial<P>): Promise<void>;
613
+ /**
614
+ * Create a copy of this instance with the same props.
615
+ *
616
+ * @returns New component instance
617
+ */
618
+ clone(): ForgeFrameComponentInstance<P, X>;
619
+ /**
620
+ * Check if the component is eligible to render.
621
+ *
622
+ * @returns Whether the component can render
623
+ */
624
+ isEligible(): boolean;
625
+ /**
626
+ * Event emitter for subscribing to lifecycle events.
627
+ */
628
+ event: EventEmitterInterface;
629
+ /**
630
+ * Mutable state object for the component.
631
+ */
632
+ state: Record<string, unknown>;
633
+ /**
634
+ * Data exported from the host component via `hostProps.export()`.
635
+ */
636
+ exports?: X;
637
+ }
638
+ /**
639
+ * Component factory function and static properties.
640
+ *
641
+ * @typeParam P - The props type for the component
642
+ * @typeParam X - The type of exports from the host
643
+ *
644
+ * @remarks
645
+ * This is the return type of `ForgeFrame.create()`. It can be called as a
646
+ * function to create instances, and has static properties for host detection.
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * const MyComponent = ForgeFrame.create<MyProps>({ ... });
651
+ *
652
+ * // Create an instance
653
+ * const instance = MyComponent({ name: 'World' });
654
+ *
655
+ * // Check if we're in a host context
656
+ * if (MyComponent.isHost()) {
657
+ * const props = MyComponent.hostProps;
658
+ * }
659
+ * ```
660
+ *
661
+ * @public
662
+ */
663
+ export interface ForgeFrameComponent<P = Record<string, unknown>, X = unknown> {
664
+ /**
665
+ * Create a new component instance with props.
666
+ *
667
+ * @param props - Props to pass to the component
668
+ * @returns New component instance
669
+ */
670
+ (props?: P): ForgeFrameComponentInstance<P, X>;
671
+ /**
672
+ * Check if current window is a host instance of this component.
673
+ *
674
+ * @remarks
675
+ * A "host" is the embedded iframe or popup window that receives props
676
+ * from the consumer (the embedding app).
677
+ *
678
+ * @returns True if in host context
679
+ */
680
+ isHost(): boolean;
681
+ /**
682
+ * Check if current window is embedded by this component.
683
+ *
684
+ * @remarks
685
+ * This is an alias for {@link isHost} that uses more intuitive terminology.
686
+ *
687
+ * @returns True if in embedded context
688
+ */
689
+ isEmbedded(): boolean;
690
+ /**
691
+ * Get hostProps if in host context.
692
+ *
693
+ * @remarks
694
+ * Only available when `isHost()` returns true. Contains all props passed
695
+ * from the consumer plus built-in control methods.
696
+ */
697
+ hostProps?: HostProps<P>;
698
+ /**
699
+ * Check if we can render to a target window.
700
+ *
701
+ * @param win - Target window to check
702
+ * @returns Promise resolving to whether rendering is allowed
703
+ */
704
+ canRenderTo(win: Window): Promise<boolean>;
705
+ /**
706
+ * All active instances of this component.
707
+ */
708
+ instances: ForgeFrameComponentInstance<P, X>[];
709
+ }
710
+ /**
711
+ * Consumer namespace available in host via `hostProps.consumer`.
712
+ *
713
+ * @typeParam P - The props type for the component
714
+ *
715
+ * @remarks
716
+ * Provides bidirectional communication from host to consumer.
717
+ *
718
+ * @public
719
+ */
720
+ export interface ConsumerNamespace<P = Record<string, unknown>> {
721
+ /**
722
+ * Access consumer's props.
723
+ */
724
+ props: P;
725
+ /**
726
+ * Export data/methods from consumer context.
727
+ *
728
+ * @param data - Data to export
729
+ * @returns Promise that resolves when export is complete
730
+ */
731
+ export: <T>(data: T) => Promise<void>;
732
+ }
733
+ /**
734
+ * Information about a sibling component instance.
735
+ *
736
+ * @public
737
+ */
738
+ export interface SiblingInfo {
739
+ /** Unique instance ID */
740
+ uid: string;
741
+ /** Component tag name */
742
+ tag: string;
743
+ /** Exports from sibling (if any) */
744
+ exports?: unknown;
745
+ }
746
+ /**
747
+ * Options for getting peer component instances.
748
+ *
749
+ * @public
750
+ */
751
+ export interface GetPeerInstancesOptions {
752
+ /**
753
+ * If true, get peers from any consumer window (not just same consumer).
754
+ * @defaultValue false
755
+ */
756
+ anyConsumer?: boolean;
757
+ }
758
+ /**
759
+ * Built-in properties and methods available on hostProps.
760
+ *
761
+ * @typeParam P - The props type for the component
762
+ *
763
+ * @remarks
764
+ * These are the framework-provided properties that are always available
765
+ * on the hostProps object, regardless of user-defined props.
766
+ *
767
+ * @public
768
+ */
769
+ export interface HostPropsBuiltins<P = Record<string, unknown>> {
770
+ /** Unique instance ID */
771
+ uid: string;
772
+ /** Component tag name */
773
+ tag: string;
774
+ /**
775
+ * Close the component.
776
+ *
777
+ * @returns Promise that resolves when closed
778
+ */
779
+ close: () => Promise<void>;
780
+ /**
781
+ * Focus the component window.
782
+ *
783
+ * @returns Promise that resolves when focused
784
+ */
785
+ focus: () => Promise<void>;
786
+ /**
787
+ * Resize the component.
788
+ *
789
+ * @param dimensions - New dimensions
790
+ * @returns Promise that resolves when resized
791
+ */
792
+ resize: (dimensions: Dimensions) => Promise<void>;
793
+ /**
794
+ * Show the component (if hidden).
795
+ *
796
+ * @returns Promise that resolves when shown
797
+ */
798
+ show: () => Promise<void>;
799
+ /**
800
+ * Hide the component.
801
+ *
802
+ * @returns Promise that resolves when hidden
803
+ */
804
+ hide: () => Promise<void>;
805
+ /**
806
+ * Subscribe to prop updates from consumer.
807
+ *
808
+ * @param handler - Function called when props change
809
+ * @returns Object with cancel function to unsubscribe
810
+ */
811
+ onProps: (handler: (props: P) => void) => {
812
+ cancel: () => void;
813
+ };
814
+ /**
815
+ * Report an error to the consumer.
816
+ *
817
+ * @param err - Error to report
818
+ * @returns Promise that resolves when error is sent
819
+ */
820
+ onError: (err: Error) => Promise<void>;
821
+ /**
822
+ * Get a reference to the consumer window.
823
+ *
824
+ * @returns Consumer window object
825
+ */
826
+ getConsumer: () => Window;
827
+ /**
828
+ * Get the consumer window's domain.
829
+ *
830
+ * @returns Consumer domain string
831
+ */
832
+ getConsumerDomain: () => string;
833
+ /**
834
+ * Export data/methods to the consumer.
835
+ *
836
+ * @param exports - Data to export
837
+ * @returns Promise that resolves when export is complete
838
+ */
839
+ export: <X>(exports: X) => Promise<void>;
840
+ /**
841
+ * Consumer namespace for bidirectional communication.
842
+ */
843
+ consumer: ConsumerNamespace<P>;
844
+ /**
845
+ * Get peer component instances (other ForgeFrame components from the same consumer).
846
+ *
847
+ * @remarks
848
+ * Peer instances are other ForgeFrame component instances that share the same
849
+ * consumer window. This enables communication between multiple embedded components.
850
+ *
851
+ * @param options - Options for peer discovery
852
+ * @returns Promise resolving to array of peer info
853
+ */
854
+ getPeerInstances: (options?: GetPeerInstancesOptions) => Promise<SiblingInfo[]>;
855
+ /**
856
+ * Nested components available for rendering.
857
+ */
858
+ children?: Record<string, ForgeFrameComponent>;
859
+ }
860
+ /**
861
+ * Props object available in host window via `window.hostProps`.
862
+ *
863
+ * @typeParam P - The props type for the component
864
+ *
865
+ * @remarks
866
+ * The hostProps object (short for "host properties") contains all props passed
867
+ * from the consumer (the embedding app), plus built-in methods for controlling
868
+ * the component and communicating back to the consumer. User-defined props from
869
+ * P are properly typed, and built-in methods are always available.
870
+ *
871
+ * The name "hostProps" reflects that these are the props available to the host
872
+ * (the embedded iframe/popup), passed from the consumer (the embedding app).
873
+ *
874
+ * @example
875
+ * ```typescript
876
+ * // In host window with typed props
877
+ * interface MyProps {
878
+ * name: string;
879
+ * onSubmit: (data: { success: boolean }) => void;
880
+ * }
881
+ *
882
+ * const props = window.hostProps as HostProps<MyProps>;
883
+ *
884
+ * // User props are properly typed
885
+ * console.log(props.name); // string
886
+ *
887
+ * // Call consumer callbacks
888
+ * await props.onSubmit({ success: true });
889
+ *
890
+ * // Built-in methods are always available
891
+ * await props.resize({ width: 500, height: 400 });
892
+ * await props.close();
893
+ * ```
894
+ *
895
+ * @public
896
+ */
897
+ export type HostProps<P = Record<string, unknown>> = P & HostPropsBuiltins<P>;
898
+ /**
899
+ * Payload encoded in window.name for initial consumer-to-host data transfer.
900
+ *
901
+ * @typeParam _P - The props type (unused, for compatibility)
902
+ *
903
+ * @internal
904
+ */
905
+ export interface WindowNamePayload<_P = Record<string, unknown>> {
906
+ /** Consumer component instance UID */
907
+ uid: string;
908
+ /** Component tag name */
909
+ tag: string;
910
+ /** ForgeFrame version */
911
+ version: string;
912
+ /** Rendering context */
913
+ context: ContextType;
914
+ /** Consumer window domain */
915
+ consumerDomain: string;
916
+ /** Serialized props */
917
+ props: SerializedProps;
918
+ /** Consumer method message names */
919
+ exports: ConsumerExports;
920
+ /** Nested component references */
921
+ children?: Record<string, HostComponentRef>;
922
+ }
923
+ /**
924
+ * Serialized props ready for cross-domain transfer.
925
+ *
926
+ * @internal
927
+ */
928
+ export interface SerializedProps {
929
+ [key: string]: unknown;
930
+ }
931
+ /**
932
+ * Map of consumer methods to their message names.
933
+ *
934
+ * @internal
935
+ */
936
+ export interface ConsumerExports {
937
+ /** Init message name */
938
+ init: string;
939
+ /** Close message name */
940
+ close: string;
941
+ /** Resize message name */
942
+ resize: string;
943
+ /** Show message name */
944
+ show: string;
945
+ /** Hide message name */
946
+ hide: string;
947
+ /** Error message name */
948
+ onError: string;
949
+ /** Update props message name */
950
+ updateProps: string;
951
+ /** Export message name */
952
+ export: string;
953
+ }
954
+ /**
955
+ * Serialized function reference for cross-domain calls.
956
+ *
957
+ * @internal
958
+ */
959
+ export interface FunctionRef {
960
+ /** Type marker */
961
+ __type__: 'function';
962
+ /** Unique function ID */
963
+ __id__: string;
964
+ /** Function name for debugging */
965
+ __name__: string;
966
+ }
967
+ /**
968
+ * Cross-domain message structure.
969
+ *
970
+ * @internal
971
+ */
972
+ export interface Message {
973
+ /** Unique message ID */
974
+ id: string;
975
+ /** Message type */
976
+ type: 'request' | 'response' | 'ack';
977
+ /** Message name/action */
978
+ name: string;
979
+ /** Message payload */
980
+ data?: unknown;
981
+ /** Error information (for error responses) */
982
+ error?: {
983
+ message: string;
984
+ stack?: string;
985
+ };
986
+ /** Message source info */
987
+ source: {
988
+ uid: string;
989
+ domain: string;
990
+ };
991
+ }
992
+ /**
993
+ * Reference to a window for cross-domain communication.
994
+ *
995
+ * @internal
996
+ */
997
+ export type WindowRef = {
998
+ type: 'opener';
999
+ } | {
1000
+ type: 'parent';
1001
+ distance: number;
1002
+ } | {
1003
+ type: 'global';
1004
+ uid: string;
1005
+ } | {
1006
+ type: 'direct';
1007
+ win: Window;
1008
+ };