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,223 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Child component implementation module.
4
+ *
5
+ * @remarks
6
+ * This module contains the ChildComponent class which runs inside the iframe
7
+ * or popup and handles communication with the parent window. It also provides
8
+ * utilities for detecting child context and accessing xprops.
9
+ */
10
+ import type { ChildProps, WindowNamePayload, PropsDefinition } from '../types';
11
+ import { EventEmitter } from '../events/emitter';
12
+ /**
13
+ * Child-side component implementation.
14
+ *
15
+ * @remarks
16
+ * This class runs inside the iframe or popup window and manages communication
17
+ * with the parent component. It provides the xprops object with props and
18
+ * control methods.
19
+ *
20
+ * @typeParam P - The props type passed from the parent
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // In child window
25
+ * const { email, onLogin, close } = window.xprops;
26
+ * console.log('Email:', email);
27
+ * onLogin({ id: 1, name: 'John' });
28
+ * close();
29
+ * ```
30
+ *
31
+ * @public
32
+ */
33
+ export declare class ChildComponent<P extends Record<string, unknown>> {
34
+ private propDefinitions;
35
+ /** The xprops object containing props and control methods. */
36
+ xprops: ChildProps<P>;
37
+ /** Event emitter for lifecycle events. */
38
+ event: EventEmitter;
39
+ /** @internal */
40
+ private uid;
41
+ /** @internal */
42
+ private tag;
43
+ /** @internal */
44
+ private parentWindow;
45
+ /** @internal */
46
+ private parentDomain;
47
+ /** @internal */
48
+ private messenger;
49
+ /** @internal */
50
+ private bridge;
51
+ /** @internal */
52
+ private propsHandlers;
53
+ /** @internal */
54
+ private parentProps;
55
+ /** @internal */
56
+ private initError;
57
+ /**
58
+ * Creates a new ChildComponent instance.
59
+ *
60
+ * @param payload - The payload parsed from window.name
61
+ * @param propDefinitions - Optional prop definitions for deserialization
62
+ */
63
+ constructor(payload: WindowNamePayload<P>, propDefinitions?: PropsDefinition<P>);
64
+ /**
65
+ * Returns the xprops object.
66
+ *
67
+ * @returns The xprops object with props and control methods
68
+ */
69
+ getProps(): ChildProps<P>;
70
+ /**
71
+ * Resolves the parent window reference (iframe parent or popup opener).
72
+ * @internal
73
+ */
74
+ private resolveParentWindow;
75
+ /**
76
+ * Builds the xprops object with deserialized props and control methods.
77
+ * @internal
78
+ */
79
+ private buildXProps;
80
+ /**
81
+ * Sends initialization message to the parent.
82
+ * @internal
83
+ */
84
+ private sendInit;
85
+ /**
86
+ * Returns the initialization error if one occurred.
87
+ *
88
+ * @returns The initialization error or null if successful
89
+ */
90
+ getInitError(): Error | null;
91
+ /**
92
+ * Requests the parent to close this component.
93
+ * @internal
94
+ */
95
+ private close;
96
+ /**
97
+ * Focuses this window and notifies the parent.
98
+ * @internal
99
+ */
100
+ private focus;
101
+ /**
102
+ * Requests the parent to resize this component.
103
+ * @internal
104
+ */
105
+ private resize;
106
+ /**
107
+ * Requests the parent to show this component.
108
+ * @internal
109
+ */
110
+ private show;
111
+ /**
112
+ * Requests the parent to hide this component.
113
+ * @internal
114
+ */
115
+ private hide;
116
+ /**
117
+ * Subscribes to prop updates from the parent.
118
+ * @internal
119
+ */
120
+ private onProps;
121
+ /**
122
+ * Reports an error to the parent.
123
+ * @internal
124
+ */
125
+ private onError;
126
+ /**
127
+ * Exports data or methods to the parent.
128
+ * @internal
129
+ */
130
+ private exportData;
131
+ /**
132
+ * Exports data to the parent for bidirectional communication.
133
+ * @internal
134
+ */
135
+ private parentExport;
136
+ /**
137
+ * Gets information about sibling component instances.
138
+ * @internal
139
+ */
140
+ private getSiblings;
141
+ /**
142
+ * Builds child component factories from refs passed by the parent.
143
+ * @internal
144
+ */
145
+ private buildChildComponents;
146
+ /**
147
+ * Sets up message handlers for parent communication.
148
+ * @internal
149
+ */
150
+ private setupMessageHandlers;
151
+ /**
152
+ * Destroys the child component and cleans up resources.
153
+ */
154
+ destroy(): void;
155
+ }
156
+ /**
157
+ * Initializes the child component if running in a ForgeFrame window.
158
+ *
159
+ * @remarks
160
+ * This function detects if the current window was created by ForgeFrame
161
+ * and sets up the child component with xprops. Returns null if not in
162
+ * a ForgeFrame child context.
163
+ *
164
+ * @typeParam P - The props type passed from the parent
165
+ * @param propDefinitions - Optional prop definitions for deserialization
166
+ * @returns The child component instance or null if not in a child window
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const child = initChild();
171
+ * if (child) {
172
+ * console.log('Running in ForgeFrame child context');
173
+ * console.log('Props:', child.xprops);
174
+ * }
175
+ * ```
176
+ *
177
+ * @public
178
+ */
179
+ export declare function initChild<P extends Record<string, unknown>>(propDefinitions?: PropsDefinition<P>): ChildComponent<P> | null;
180
+ /**
181
+ * Gets the current child component instance.
182
+ *
183
+ * @typeParam P - The props type passed from the parent
184
+ * @returns The child component instance or null if not initialized
185
+ *
186
+ * @public
187
+ */
188
+ export declare function getChild<P extends Record<string, unknown>>(): ChildComponent<P> | null;
189
+ /**
190
+ * Checks if the current window is a ForgeFrame child context.
191
+ *
192
+ * @returns True if running inside a ForgeFrame iframe or popup
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * if (isChild()) {
197
+ * console.log('Running in ForgeFrame child');
198
+ * }
199
+ * ```
200
+ *
201
+ * @public
202
+ */
203
+ export declare function isChild(): boolean;
204
+ /**
205
+ * Gets the xprops object from the window.
206
+ *
207
+ * @remarks
208
+ * This is a convenience function to access `window.xprops`.
209
+ *
210
+ * @typeParam P - The props type passed from the parent
211
+ * @returns The xprops object or undefined if not in a child context
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const xprops = getXProps();
216
+ * if (xprops) {
217
+ * xprops.onLogin({ id: 1, name: 'John' });
218
+ * }
219
+ * ```
220
+ *
221
+ * @public
222
+ */
223
+ export declare function getXProps<P extends Record<string, unknown>>(): ChildProps<P> | undefined;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Component factory and registry module.
4
+ *
5
+ * @remarks
6
+ * This module provides the main entry point for creating ForgeFrame components.
7
+ * It manages a global registry of all defined components and handles component
8
+ * creation, validation, and lifecycle management.
9
+ */
10
+ import type { ComponentOptions, ForgeFrameComponent, ForgeFrameComponentInstance } from '../types';
11
+ /**
12
+ * Creates a new ForgeFrame component definition.
13
+ *
14
+ * @remarks
15
+ * This is the main entry point for defining components. It creates a factory
16
+ * function that can be called with props to create component instances.
17
+ * Equivalent to zoid.create() for migration purposes.
18
+ *
19
+ * @typeParam P - The props type for the component
20
+ * @typeParam X - The exports type that the child can expose
21
+ * @param options - Component configuration options
22
+ * @returns A component factory function
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const LoginComponent = create({
27
+ * tag: 'login-component',
28
+ * url: 'https://auth.example.com/login',
29
+ * props: {
30
+ * email: { type: PROP_TYPE.STRING },
31
+ * onLogin: { type: PROP_TYPE.FUNCTION },
32
+ * },
33
+ * });
34
+ *
35
+ * const instance = LoginComponent({ email: 'user@example.com' });
36
+ * await instance.render('#container');
37
+ * ```
38
+ *
39
+ * @public
40
+ */
41
+ export declare function create<P extends Record<string, unknown> = Record<string, unknown>, X = unknown>(options: ComponentOptions<P>): ForgeFrameComponent<P, X>;
42
+ /**
43
+ * Retrieves a registered component by its tag name.
44
+ *
45
+ * @typeParam P - The props type for the component
46
+ * @typeParam X - The exports type that the child can expose
47
+ * @param tag - The unique tag identifier of the component
48
+ * @returns The component factory function, or undefined if not found
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const LoginComponent = getComponent('login-component');
53
+ * if (LoginComponent) {
54
+ * LoginComponent({ email: 'user@example.com' }).render('#container');
55
+ * }
56
+ * ```
57
+ *
58
+ * @public
59
+ */
60
+ export declare function getComponent<P extends Record<string, unknown> = Record<string, unknown>, X = unknown>(tag: string): ForgeFrameComponent<P, X> | undefined;
61
+ /**
62
+ * Destroys a single component instance.
63
+ *
64
+ * @remarks
65
+ * This closes the component and cleans up all associated resources.
66
+ *
67
+ * @typeParam P - The props type for the component
68
+ * @param instance - The component instance to destroy
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const instance = MyComponent({ prop: 'value' });
73
+ * await instance.render('#container');
74
+ * // Later...
75
+ * await destroy(instance);
76
+ * ```
77
+ *
78
+ * @public
79
+ */
80
+ export declare function destroy<P extends Record<string, unknown>>(instance: ForgeFrameComponentInstance<P>): Promise<void>;
81
+ /**
82
+ * Destroys all instances of a specific component.
83
+ *
84
+ * @remarks
85
+ * Useful for cleanup when a component type is no longer needed.
86
+ *
87
+ * @param tag - The component tag name to destroy all instances of
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * // Destroy all login component instances
92
+ * await destroyComponents('login-component');
93
+ * ```
94
+ *
95
+ * @public
96
+ */
97
+ export declare function destroyComponents(tag: string): Promise<void>;
98
+ /**
99
+ * Destroys all ForgeFrame component instances.
100
+ *
101
+ * @remarks
102
+ * This is a global cleanup function that destroys every component
103
+ * instance across all component types.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * // Clean up everything on page unload
108
+ * window.addEventListener('beforeunload', () => {
109
+ * destroyAll();
110
+ * });
111
+ * ```
112
+ *
113
+ * @public
114
+ */
115
+ export declare function destroyAll(): Promise<void>;
116
+ /**
117
+ * Removes a component from the registry.
118
+ *
119
+ * @remarks
120
+ * Primarily used for testing and cleanup. Does not destroy active instances.
121
+ *
122
+ * @param tag - The component tag to unregister
123
+ * @internal
124
+ */
125
+ export declare function unregisterComponent(tag: string): void;
126
+ /**
127
+ * Clears all components from the registry.
128
+ *
129
+ * @remarks
130
+ * Primarily used for testing and cleanup. Does not destroy active instances.
131
+ *
132
+ * @internal
133
+ */
134
+ export declare function clearComponents(): void;
135
+ export { isChild, getXProps } from './child';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Core module for ForgeFrame component creation and lifecycle management.
4
+ *
5
+ * @remarks
6
+ * This module provides the primary API for creating, managing, and destroying
7
+ * cross-domain components. It includes both parent-side (host page) and
8
+ * child-side (embedded page) functionality.
9
+ */
10
+ export { create, getComponent, destroy, destroyComponents, destroyAll, unregisterComponent, clearComponents, isChild, getXProps, } from './component';
11
+ export { ParentComponent } from './parent';
12
+ export { ChildComponent, initChild, getChild } from './child';
@@ -0,0 +1,262 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Parent component implementation module.
4
+ *
5
+ * @remarks
6
+ * This module contains the ParentComponent class which handles the host-side
7
+ * rendering and communication with child components embedded in iframes or popups.
8
+ */
9
+ import type { ComponentOptions, ForgeFrameComponentInstance, Dimensions } from '../types';
10
+ import type { ContextType } from '../constants';
11
+ import { EventEmitter } from '../events/emitter';
12
+ /**
13
+ * Parent-side component implementation.
14
+ *
15
+ * @remarks
16
+ * This class manages the lifecycle of a component from the host page perspective.
17
+ * It handles rendering the component into iframes or popups, communicating with
18
+ * the child window via postMessage, and managing component state.
19
+ *
20
+ * @typeParam P - The props type passed to the component
21
+ * @typeParam X - The exports type that the child can expose to the parent
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const instance = new ParentComponent(options, { email: 'user@example.com' });
26
+ * await instance.render('#container');
27
+ * ```
28
+ *
29
+ * @public
30
+ */
31
+ export declare class ParentComponent<P extends Record<string, unknown>, X = unknown> implements ForgeFrameComponentInstance<P, X> {
32
+ /** Event emitter for lifecycle events. */
33
+ event: EventEmitter;
34
+ /** Arbitrary state storage for the component instance. */
35
+ state: Record<string, unknown>;
36
+ /** Data exported by the child component. */
37
+ exports?: X;
38
+ /** Data exported from the parent by the child. */
39
+ parentExports?: unknown;
40
+ /** @internal */
41
+ private _uid;
42
+ /**
43
+ * Unique instance identifier.
44
+ * @readonly
45
+ */
46
+ get uid(): string;
47
+ /** @internal */
48
+ private options;
49
+ /** @internal */
50
+ private props;
51
+ /** @internal */
52
+ private context;
53
+ /** @internal */
54
+ private messenger;
55
+ /** @internal */
56
+ private bridge;
57
+ /** @internal */
58
+ private cleanup;
59
+ /** @internal */
60
+ private childWindow;
61
+ /** @internal */
62
+ private iframe;
63
+ /** @internal */
64
+ private container;
65
+ /** @internal */
66
+ private prerenderElement;
67
+ /** @internal */
68
+ private initPromise;
69
+ /** @internal */
70
+ private rendered;
71
+ /** @internal */
72
+ private destroyed;
73
+ /**
74
+ * Creates a new ParentComponent instance.
75
+ *
76
+ * @param options - Component configuration options
77
+ * @param props - Initial props to pass to the component
78
+ */
79
+ constructor(options: ComponentOptions<P>, props?: Partial<P>);
80
+ /**
81
+ * Builds the list of trusted domains for messenger communication.
82
+ * @internal
83
+ */
84
+ private buildTrustedDomains;
85
+ /**
86
+ * Renders the component into a DOM container.
87
+ *
88
+ * @remarks
89
+ * This is the primary method for displaying the component. It creates
90
+ * an iframe or popup, establishes communication with the child, and
91
+ * handles the prerender/render lifecycle.
92
+ *
93
+ * @param container - CSS selector or HTMLElement to render into
94
+ * @param context - Override the default rendering context (iframe or popup)
95
+ * @throws Error if component was already destroyed or rendered
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * await instance.render('#container');
100
+ * await instance.render(document.getElementById('target'), 'popup');
101
+ * ```
102
+ */
103
+ render(container?: string | HTMLElement, context?: ContextType): Promise<void>;
104
+ /**
105
+ * Renders the component into a container in a different window.
106
+ *
107
+ * @remarks
108
+ * Currently delegates to regular render. Full cross-window rendering
109
+ * would require additional complexity.
110
+ *
111
+ * @param _win - Target window (currently unused)
112
+ * @param container - CSS selector or HTMLElement to render into
113
+ * @param context - Override the default rendering context
114
+ */
115
+ renderTo(_win: Window, container?: string | HTMLElement, context?: ContextType): Promise<void>;
116
+ /**
117
+ * Closes and destroys the component.
118
+ *
119
+ * @remarks
120
+ * Emits the 'close' event before destruction. Safe to call multiple times.
121
+ */
122
+ close(): Promise<void>;
123
+ /**
124
+ * Focuses the component window.
125
+ *
126
+ * @remarks
127
+ * For iframes, focuses the iframe element. For popups, brings the window to front.
128
+ */
129
+ focus(): Promise<void>;
130
+ /**
131
+ * Resizes the component to the specified dimensions.
132
+ *
133
+ * @param dimensions - New width and height for the component
134
+ */
135
+ resize(dimensions: Dimensions): Promise<void>;
136
+ /**
137
+ * Shows the component if hidden.
138
+ *
139
+ * @remarks
140
+ * Only applicable to iframe context.
141
+ */
142
+ show(): Promise<void>;
143
+ /**
144
+ * Hides the component.
145
+ *
146
+ * @remarks
147
+ * Only applicable to iframe context.
148
+ */
149
+ hide(): Promise<void>;
150
+ /**
151
+ * Updates the component props and sends them to the child.
152
+ *
153
+ * @remarks
154
+ * Props are normalized and serialized before being sent to the child window.
155
+ *
156
+ * @param newProps - Partial props object to merge with existing props
157
+ */
158
+ updateProps(newProps: Partial<P>): Promise<void>;
159
+ /**
160
+ * Creates a clone of this instance with the same props.
161
+ *
162
+ * @returns A new unrendered component instance with identical configuration
163
+ */
164
+ clone(): ForgeFrameComponentInstance<P, X>;
165
+ /**
166
+ * Checks if the component is eligible to render based on the eligible option.
167
+ *
168
+ * @returns True if eligible or no eligibility check defined
169
+ */
170
+ isEligible(): boolean;
171
+ /**
172
+ * Normalizes component options with default values.
173
+ * @internal
174
+ */
175
+ private normalizeOptions;
176
+ /**
177
+ * Creates the prop context passed to prop callbacks and validators.
178
+ * @internal
179
+ */
180
+ private createPropContext;
181
+ /**
182
+ * Resolves a container selector or element to an HTMLElement.
183
+ * @internal
184
+ */
185
+ private resolveContainer;
186
+ /**
187
+ * Checks eligibility and throws if component cannot render.
188
+ * @internal
189
+ */
190
+ private checkEligibility;
191
+ /**
192
+ * Creates and displays the prerender (loading) content.
193
+ * @internal
194
+ */
195
+ private prerender;
196
+ /**
197
+ * Creates an iframe element without setting src (for prerender phase).
198
+ * The window name is set immediately as it carries the payload for the child.
199
+ * @internal
200
+ */
201
+ private createIframeElement;
202
+ /**
203
+ * Opens the child window (iframe or popup).
204
+ * @internal
205
+ */
206
+ private open;
207
+ /**
208
+ * Builds the URL for the child window including query parameters.
209
+ * @internal
210
+ */
211
+ private buildUrl;
212
+ /**
213
+ * Builds the window.name payload for the child window.
214
+ * @internal
215
+ */
216
+ private buildWindowName;
217
+ /**
218
+ * Builds component references for nested child components.
219
+ * @internal
220
+ */
221
+ private buildChildrenRefs;
222
+ /**
223
+ * Creates the exports object sent to the child.
224
+ * @internal
225
+ */
226
+ private createParentExports;
227
+ /**
228
+ * Extracts the origin domain from the component URL.
229
+ * @internal
230
+ */
231
+ private getChildDomain;
232
+ /**
233
+ * Waits for the child to send the init message.
234
+ * @internal
235
+ */
236
+ private waitForChild;
237
+ /**
238
+ * Sets up message handlers for child communication.
239
+ * @internal
240
+ */
241
+ private setupMessageHandlers;
242
+ /**
243
+ * Registers cleanup handlers for the instance.
244
+ * @internal
245
+ */
246
+ private setupCleanup;
247
+ /**
248
+ * Handles errors by emitting events and calling callbacks.
249
+ * @internal
250
+ */
251
+ private handleError;
252
+ /**
253
+ * Calls a prop callback if it exists.
254
+ * @internal
255
+ */
256
+ private callPropCallback;
257
+ /**
258
+ * Destroys the component and cleans up all resources.
259
+ * @internal
260
+ */
261
+ private destroy;
262
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * ForgeFrame Driver Module
3
+ *
4
+ * @remarks
5
+ * This module provides framework-specific drivers for integrating ForgeFrame
6
+ * components with popular UI frameworks like React. Drivers handle the lifecycle
7
+ * management, prop synchronization, and rendering of cross-domain components
8
+ * within the target framework's component model.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { createReactDriver, withReactDriver } from 'forgeframe/drivers';
13
+ * import type { ReactDriverOptions, ReactComponentProps } from 'forgeframe/drivers';
14
+ * ```
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+ export { createReactDriver, withReactDriver, type ReactDriverOptions, type ReactComponentProps, type ReactComponentType, } from './react';