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,169 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * ForgeFrame - Modern cross-domain component framework.
4
+ *
5
+ * @remarks
6
+ * A minimal, TypeScript-first alternative to zoid with zero runtime dependencies.
7
+ * Enables rendering components in iframes or popups across domains while
8
+ * seamlessly passing props (including functions) between parent and child.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import ForgeFrame from 'forgeframe';
13
+ *
14
+ * // Define a component
15
+ * const LoginComponent = ForgeFrame.create({
16
+ * tag: 'login-component',
17
+ * url: 'https://auth.example.com/login',
18
+ * props: {
19
+ * email: { type: ForgeFrame.PROP_TYPE.STRING },
20
+ * onLogin: { type: ForgeFrame.PROP_TYPE.FUNCTION },
21
+ * },
22
+ * });
23
+ *
24
+ * // Render the component
25
+ * LoginComponent({
26
+ * email: 'user@example.com',
27
+ * onLogin: (user) => console.log('Logged in:', user),
28
+ * }).render('#container');
29
+ * ```
30
+ */
31
+ import { create, destroy, destroyComponents, destroyAll, isChild, getXProps } from './core';
32
+ import { PopupOpenError } from './render/popup';
33
+ /**
34
+ * Main ForgeFrame API object.
35
+ *
36
+ * @remarks
37
+ * Provides a zoid-compatible interface for creating and managing
38
+ * cross-domain components. All methods and constants are accessible
39
+ * through this object.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import ForgeFrame from 'forgeframe';
44
+ *
45
+ * const Component = ForgeFrame.create({
46
+ * tag: 'my-component',
47
+ * url: '/component.html',
48
+ * });
49
+ * ```
50
+ *
51
+ * @public
52
+ */
53
+ export declare const ForgeFrame: {
54
+ /**
55
+ * Create a new component definition.
56
+ *
57
+ * @remarks
58
+ * This is the main entry point for defining components. Returns a
59
+ * component factory function that can be called to create instances.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const MyComponent = ForgeFrame.create({
64
+ * tag: 'my-component',
65
+ * url: 'https://example.com/component',
66
+ * props: {
67
+ * onLogin: { type: ForgeFrame.PROP_TYPE.FUNCTION },
68
+ * },
69
+ * });
70
+ *
71
+ * const instance = MyComponent({ onLogin: (user) => {} });
72
+ * await instance.render('#container');
73
+ * ```
74
+ */
75
+ readonly create: typeof create;
76
+ /**
77
+ * Destroy a single component instance.
78
+ *
79
+ * @param instance - The component instance to destroy
80
+ */
81
+ readonly destroy: typeof destroy;
82
+ /**
83
+ * Destroy all instances of a specific component by tag.
84
+ *
85
+ * @param tag - The component tag name
86
+ */
87
+ readonly destroyComponents: typeof destroyComponents;
88
+ /**
89
+ * Destroy all ForgeFrame component instances.
90
+ */
91
+ readonly destroyAll: typeof destroyAll;
92
+ /**
93
+ * Check if the current window is a child component context.
94
+ *
95
+ * @returns True if running inside a ForgeFrame iframe/popup
96
+ */
97
+ readonly isChild: typeof isChild;
98
+ /**
99
+ * Get xprops from the current child window.
100
+ *
101
+ * @returns The xprops object if in child context, undefined otherwise
102
+ */
103
+ readonly getXProps: typeof getXProps;
104
+ /**
105
+ * Prop type constants for defining component props.
106
+ * @see {@link PROP_TYPE}
107
+ */
108
+ readonly PROP_TYPE: {
109
+ readonly STRING: "string";
110
+ readonly OBJECT: "object";
111
+ readonly FUNCTION: "function";
112
+ readonly BOOLEAN: "boolean";
113
+ readonly NUMBER: "number";
114
+ readonly ARRAY: "array";
115
+ };
116
+ /**
117
+ * Serialization strategy constants.
118
+ * @see {@link PROP_SERIALIZATION}
119
+ */
120
+ readonly PROP_SERIALIZATION: {
121
+ readonly JSON: "json";
122
+ readonly BASE64: "base64";
123
+ readonly DOTIFY: "dotify";
124
+ };
125
+ /**
126
+ * Rendering context constants (IFRAME, POPUP).
127
+ * @see {@link CONTEXT}
128
+ */
129
+ readonly CONTEXT: {
130
+ readonly IFRAME: "iframe";
131
+ readonly POPUP: "popup";
132
+ };
133
+ /**
134
+ * Lifecycle event name constants.
135
+ * @see {@link EVENT}
136
+ */
137
+ readonly EVENT: {
138
+ readonly RENDER: "render";
139
+ readonly RENDERED: "rendered";
140
+ readonly PRERENDER: "prerender";
141
+ readonly PRERENDERED: "prerendered";
142
+ readonly DISPLAY: "display";
143
+ readonly ERROR: "error";
144
+ readonly CLOSE: "close";
145
+ readonly DESTROY: "destroy";
146
+ readonly PROPS: "props";
147
+ readonly RESIZE: "resize";
148
+ readonly FOCUS: "focus";
149
+ };
150
+ /**
151
+ * Error thrown when popup window fails to open.
152
+ */
153
+ readonly PopupOpenError: typeof PopupOpenError;
154
+ /**
155
+ * Current library version.
156
+ */
157
+ readonly VERSION: "1.0.0";
158
+ };
159
+ /**
160
+ * Default export of the ForgeFrame API object.
161
+ * @public
162
+ */
163
+ export default ForgeFrame;
164
+ export { create, destroy, destroyComponents, destroyAll, isChild, getXProps, } from './core';
165
+ export { PROP_TYPE, PROP_SERIALIZATION, CONTEXT, EVENT, VERSION, } from './constants';
166
+ export { PopupOpenError } from './render/popup';
167
+ export type { ComponentOptions, ForgeFrameComponent, ForgeFrameComponentInstance, ChildProps, PropDefinition, PropsDefinition, PropContext, TemplateContext, ContainerTemplate, PrerenderTemplate, Dimensions, DomainMatcher, AutoResizeOptions, IframeAttributes, IframeStyles, EligibilityResult, EventHandler, EventEmitterInterface, } from './types';
168
+ export type { PropType, ContextType, EventType, SerializationType, } from './constants';
169
+ export { createReactDriver, withReactDriver, type ReactDriverOptions, type ReactComponentProps, type ReactComponentType, } from './drivers/react';
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Built-in prop definitions for ForgeFrame components.
4
+ *
5
+ * @remarks
6
+ * This module defines the standard props that are automatically available
7
+ * to all ForgeFrame components, including identifiers, dimensions, and
8
+ * lifecycle callbacks.
9
+ */
10
+ import type { PropDefinition, Dimensions } from '../types';
11
+ /**
12
+ * Built-in props that are automatically provided to all components.
13
+ *
14
+ * @remarks
15
+ * These props are always available regardless of the component's prop definitions.
16
+ * They include component identifiers, dimensions, timeouts, and lifecycle callbacks.
17
+ *
18
+ * @public
19
+ */
20
+ export interface BuiltinProps {
21
+ /** Unique component instance identifier. */
22
+ uid: string;
23
+ /** Component tag name. */
24
+ tag: string;
25
+ /** Component dimensions. */
26
+ dimensions: Dimensions;
27
+ /** Initialization timeout in milliseconds. */
28
+ timeout: number;
29
+ /** CSP nonce for inline scripts/styles. */
30
+ cspNonce?: string;
31
+ /** Called when component becomes visible. */
32
+ onDisplay?: () => void;
33
+ /** Called when component is fully rendered. */
34
+ onRendered?: () => void;
35
+ /** Called when rendering starts. */
36
+ onRender?: () => void;
37
+ /** Called when prerender phase completes. */
38
+ onPrerendered?: () => void;
39
+ /** Called when prerender phase starts. */
40
+ onPrerender?: () => void;
41
+ /** Called when component is closing. */
42
+ onClose?: () => void;
43
+ /** Called when component is destroyed. */
44
+ onDestroy?: () => void;
45
+ /** Called when component is resized. */
46
+ onResize?: (dimensions: Dimensions) => void;
47
+ /** Called when component receives focus. */
48
+ onFocus?: () => void;
49
+ /** Called when an error occurs. */
50
+ onError?: (err: Error) => void;
51
+ /** Called when props are updated. */
52
+ onProps?: (props: Record<string, unknown>) => void;
53
+ }
54
+ /**
55
+ * Default prop definitions for all built-in props.
56
+ *
57
+ * @remarks
58
+ * These definitions specify the type, required status, and default values
59
+ * for built-in props.
60
+ *
61
+ * @public
62
+ */
63
+ export declare const BUILTIN_PROP_DEFINITIONS: Record<string, PropDefinition>;
64
+ /**
65
+ * Gets the default value for a prop type.
66
+ *
67
+ * @param type - The prop type string
68
+ * @returns The default value for that type
69
+ *
70
+ * @public
71
+ */
72
+ export declare function getDefaultForType(type: string): unknown;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Props handling module for ForgeFrame.
4
+ *
5
+ * @remarks
6
+ * This module handles prop normalization, validation, serialization, and
7
+ * deserialization for cross-domain component communication.
8
+ */
9
+ export { BUILTIN_PROP_DEFINITIONS, getDefaultForType, type BuiltinProps, } from './definitions';
10
+ export { normalizeProps, validateProps, getPropsForChild, propsToQueryParams, } from './normalize';
11
+ export { serializeProps, deserializeProps, cloneProps, } from './serialize';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Props normalization and validation module.
4
+ *
5
+ * @remarks
6
+ * This module handles merging user props with defaults, validating prop
7
+ * types, and filtering props for sending to child components.
8
+ */
9
+ import type { PropsDefinition, PropContext } from '../types';
10
+ /**
11
+ * Merges user props with defaults and computes derived values.
12
+ *
13
+ * @typeParam P - The props type
14
+ * @param userProps - Props provided by the user
15
+ * @param definitions - Prop definitions from component config
16
+ * @param context - Context for computed props
17
+ * @returns Normalized props object
18
+ *
19
+ * @public
20
+ */
21
+ export declare function normalizeProps<P extends Record<string, unknown>>(userProps: Partial<P>, definitions: PropsDefinition<P>, context: PropContext<P>): P;
22
+ /**
23
+ * Validates props against their definitions.
24
+ *
25
+ * @typeParam P - The props type
26
+ * @param props - Props to validate
27
+ * @param definitions - Prop definitions to validate against
28
+ * @throws Error if a required prop is missing or type is invalid
29
+ *
30
+ * @public
31
+ */
32
+ export declare function validateProps<P extends Record<string, unknown>>(props: P, definitions: PropsDefinition<P>): void;
33
+ /**
34
+ * Filters props for sending to the child component.
35
+ *
36
+ * @remarks
37
+ * Respects sendToChild, sameDomain, and trustedDomains settings.
38
+ *
39
+ * @typeParam P - The props type
40
+ * @param props - All props
41
+ * @param definitions - Prop definitions
42
+ * @param childDomain - The child's domain
43
+ * @param isSameDomain - Whether child is same domain as parent
44
+ * @returns Filtered props for the child
45
+ *
46
+ * @public
47
+ */
48
+ export declare function getPropsForChild<P extends Record<string, unknown>>(props: P, definitions: PropsDefinition<P>, childDomain: string, isSameDomain: boolean): Partial<P>;
49
+ /**
50
+ * Builds URL query parameters from props with queryParam option.
51
+ *
52
+ * @typeParam P - The props type
53
+ * @param props - Props to convert
54
+ * @param definitions - Prop definitions
55
+ * @returns URLSearchParams with query parameters
56
+ *
57
+ * @public
58
+ */
59
+ export declare function propsToQueryParams<P extends Record<string, unknown>>(props: P, definitions: PropsDefinition<P>): URLSearchParams;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Props serialization module for cross-domain transfer.
4
+ *
5
+ * @remarks
6
+ * This module handles serializing and deserializing props for transfer
7
+ * between parent and child windows across domain boundaries.
8
+ */
9
+ import type { PropsDefinition, SerializedProps } from '../types';
10
+ import { FunctionBridge } from '../communication/bridge';
11
+ import type { Messenger } from '../communication/messenger';
12
+ /**
13
+ * Serializes props for cross-domain transfer.
14
+ *
15
+ * @remarks
16
+ * Functions are converted to references, objects are JSON/base64/dotify encoded
17
+ * based on the prop definition's serialization setting.
18
+ *
19
+ * @typeParam P - The props type
20
+ * @param props - Props to serialize
21
+ * @param definitions - Prop definitions
22
+ * @param bridge - Function bridge for serializing functions
23
+ * @returns Serialized props ready for postMessage
24
+ *
25
+ * @public
26
+ */
27
+ export declare function serializeProps<P extends Record<string, unknown>>(props: P, definitions: PropsDefinition<P>, bridge: FunctionBridge): SerializedProps;
28
+ /**
29
+ * Deserializes props received from the parent.
30
+ *
31
+ * @remarks
32
+ * Function references are converted back to callable functions that
33
+ * invoke the original via postMessage.
34
+ *
35
+ * @typeParam P - The props type
36
+ * @param serialized - Serialized props from parent
37
+ * @param definitions - Prop definitions
38
+ * @param messenger - Messenger for function calls
39
+ * @param bridge - Function bridge for deserializing functions
40
+ * @param parentWin - Parent window reference
41
+ * @param parentDomain - Parent origin domain
42
+ * @returns Deserialized props
43
+ *
44
+ * @public
45
+ */
46
+ export declare function deserializeProps<P extends Record<string, unknown>>(serialized: SerializedProps, definitions: PropsDefinition<P>, messenger: Messenger, bridge: FunctionBridge, parentWin: Window, parentDomain: string): P;
47
+ /**
48
+ * Creates a deep clone of props.
49
+ *
50
+ * @remarks
51
+ * Functions are passed by reference, objects are deep cloned using
52
+ * structuredClone, and primitives are copied directly.
53
+ *
54
+ * @typeParam P - The props type
55
+ * @param props - Props to clone
56
+ * @returns Cloned props
57
+ *
58
+ * @public
59
+ */
60
+ export declare function cloneProps<P extends Record<string, unknown>>(props: P): P;
@@ -0,0 +1,213 @@
1
+ import type { Dimensions, IframeAttributes, IframeStyles } from '../types';
2
+ /**
3
+ * Configuration options for creating an iframe.
4
+ *
5
+ * @public
6
+ */
7
+ export interface IframeOptions {
8
+ /**
9
+ * The URL to load in the iframe.
10
+ */
11
+ url: string;
12
+ /**
13
+ * The name attribute for the iframe, used for targeting.
14
+ */
15
+ name: string;
16
+ /**
17
+ * The parent HTML element that will contain the iframe.
18
+ */
19
+ container: HTMLElement;
20
+ /**
21
+ * The width and height dimensions for the iframe.
22
+ */
23
+ dimensions: Dimensions;
24
+ /**
25
+ * Optional additional HTML attributes to set on the iframe element.
26
+ */
27
+ attributes?: IframeAttributes;
28
+ /**
29
+ * Optional CSS styles to apply to the iframe element.
30
+ */
31
+ style?: IframeStyles;
32
+ }
33
+ /**
34
+ * Creates an iframe element with the specified options and appends it to a container.
35
+ *
36
+ * @remarks
37
+ * This function creates a fully configured iframe with sensible defaults for
38
+ * security and appearance. It sets up sandbox restrictions, removes borders,
39
+ * and ensures cross-browser compatibility.
40
+ *
41
+ * The iframe is appended to the container before setting the `src` attribute,
42
+ * as some browsers require the iframe to be in the DOM before loading content.
43
+ *
44
+ * If no sandbox attribute is provided, a default secure sandbox policy is applied:
45
+ * `allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox`
46
+ *
47
+ * @param options - Configuration options for the iframe
48
+ * @returns The created HTMLIFrameElement, already appended to the container
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const iframe = createIframe({
53
+ * url: 'https://example.com/widget',
54
+ * name: 'my-widget',
55
+ * container: document.getElementById('widget-container')!,
56
+ * dimensions: { width: 400, height: 300 },
57
+ * attributes: { allow: 'payment' }
58
+ * });
59
+ * ```
60
+ *
61
+ * @public
62
+ */
63
+ export declare function createIframe(options: IframeOptions): HTMLIFrameElement;
64
+ /**
65
+ * Creates an iframe for displaying a prerender/loading state.
66
+ *
67
+ * @remarks
68
+ * This function creates a lightweight iframe intended to show a loading
69
+ * placeholder while the actual content iframe is being prepared. The iframe
70
+ * uses `srcdoc` with an empty HTML document, avoiding any external network requests.
71
+ *
72
+ * The prerender iframe uses a special reserved name `__forgeframe_prerender__`
73
+ * to distinguish it from content iframes.
74
+ *
75
+ * @param container - The parent HTML element to append the iframe to
76
+ * @param dimensions - The width and height for the prerender iframe
77
+ * @returns The created prerender HTMLIFrameElement
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const prerenderIframe = createPrerenderIframe(
82
+ * document.getElementById('container')!,
83
+ * { width: 400, height: 300 }
84
+ * );
85
+ * ```
86
+ *
87
+ * @public
88
+ */
89
+ export declare function createPrerenderIframe(container: HTMLElement, dimensions: Dimensions): HTMLIFrameElement;
90
+ /**
91
+ * Destroys an iframe by clearing its source and removing it from the DOM.
92
+ *
93
+ * @remarks
94
+ * This function performs a clean teardown of an iframe by first navigating
95
+ * it to `about:blank` to stop any ongoing loading or scripts, then removing
96
+ * it from its parent node. Any errors during cleanup are silently ignored
97
+ * to ensure the cleanup process completes without throwing.
98
+ *
99
+ * @param iframe - The iframe element to destroy
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const iframe = createIframe({ ... });
104
+ * // Later, when done with the iframe:
105
+ * destroyIframe(iframe);
106
+ * ```
107
+ *
108
+ * @public
109
+ */
110
+ export declare function destroyIframe(iframe: HTMLIFrameElement): void;
111
+ /**
112
+ * Resizes an iframe to the specified dimensions.
113
+ *
114
+ * @param iframe - The iframe element to resize
115
+ * @param dimensions - The new width and height to apply
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * resizeIframe(iframe, { width: 600, height: 400 });
120
+ * resizeIframe(iframe, { width: '100%', height: 'auto' });
121
+ * ```
122
+ *
123
+ * @public
124
+ */
125
+ export declare function resizeIframe(iframe: HTMLIFrameElement, dimensions: Dimensions): void;
126
+ /**
127
+ * Makes an iframe visible by resetting its display and visibility styles.
128
+ *
129
+ * @remarks
130
+ * This function clears the `display` style (reverting to default) and sets
131
+ * `visibility` to `'visible'`. Use this in conjunction with {@link hideIframe}
132
+ * to toggle iframe visibility.
133
+ *
134
+ * @param iframe - The iframe element to show
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * hideIframe(iframe);
139
+ * // Later:
140
+ * showIframe(iframe);
141
+ * ```
142
+ *
143
+ * @public
144
+ */
145
+ export declare function showIframe(iframe: HTMLIFrameElement): void;
146
+ /**
147
+ * Hides an iframe by setting display to none and visibility to hidden.
148
+ *
149
+ * @remarks
150
+ * This function sets both `display: none` and `visibility: hidden` to ensure
151
+ * the iframe is completely hidden and does not affect layout. Use
152
+ * {@link showIframe} to make the iframe visible again.
153
+ *
154
+ * @param iframe - The iframe element to hide
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * showIframe(iframe);
159
+ * // Later:
160
+ * hideIframe(iframe);
161
+ * ```
162
+ *
163
+ * @public
164
+ */
165
+ export declare function hideIframe(iframe: HTMLIFrameElement): void;
166
+ /**
167
+ * Attempts to focus an iframe and its content window.
168
+ *
169
+ * @remarks
170
+ * This function tries to focus both the iframe element itself and its
171
+ * `contentWindow`. Cross-origin restrictions may prevent focusing the
172
+ * content window, in which case errors are silently caught and ignored.
173
+ *
174
+ * @param iframe - The iframe element to focus
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * // Focus the iframe after user interaction
179
+ * button.addEventListener('click', () => {
180
+ * focusIframe(iframe);
181
+ * });
182
+ * ```
183
+ *
184
+ * @public
185
+ */
186
+ export declare function focusIframe(iframe: HTMLIFrameElement): void;
187
+ /**
188
+ * Retrieves the content dimensions from an iframe for auto-resize functionality.
189
+ *
190
+ * @remarks
191
+ * This function attempts to read the actual content dimensions from the iframe's
192
+ * document. It calculates the maximum of various dimension properties (`scrollWidth`,
193
+ * `offsetWidth`, `clientWidth`, etc.) from both the body and documentElement to
194
+ * ensure accurate measurements across different browsers.
195
+ *
196
+ * This function will return `null` if:
197
+ * - The iframe's content document is not accessible (cross-origin restrictions)
198
+ * - Any error occurs while reading dimensions
199
+ *
200
+ * @param iframe - The iframe element to measure
201
+ * @returns The content dimensions, or `null` if dimensions cannot be determined
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const dimensions = getIframeContentDimensions(iframe);
206
+ * if (dimensions) {
207
+ * resizeIframe(iframe, dimensions);
208
+ * }
209
+ * ```
210
+ *
211
+ * @public
212
+ */
213
+ export declare function getIframeContentDimensions(iframe: HTMLIFrameElement): Dimensions | null;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * Rendering utilities for ForgeFrame.
5
+ *
6
+ * This module provides functions for creating and managing iframes, popups,
7
+ * and their associated templates. It handles the visual rendering layer
8
+ * of ForgeFrame components.
9
+ *
10
+ * @remarks
11
+ * The render module is divided into three main areas:
12
+ * - **Iframe management** - Creating, destroying, and manipulating iframes
13
+ * - **Popup management** - Opening, closing, and monitoring popup windows
14
+ * - **Templates** - Default templates and styling utilities for containers
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { createIframe, openPopup, defaultContainerTemplate } from '@forgeframe/render';
19
+ *
20
+ * // Create an iframe
21
+ * const iframe = createIframe({
22
+ * url: 'https://example.com',
23
+ * name: 'my-iframe',
24
+ * container: document.body,
25
+ * dimensions: { width: 400, height: 300 }
26
+ * });
27
+ *
28
+ * // Open a popup
29
+ * const popup = openPopup({
30
+ * url: 'https://example.com',
31
+ * name: 'my-popup',
32
+ * dimensions: { width: 600, height: 400 }
33
+ * });
34
+ * ```
35
+ */
36
+ export { createIframe, createPrerenderIframe, destroyIframe, resizeIframe, showIframe, hideIframe, focusIframe, getIframeContentDimensions, type IframeOptions, } from './iframe';
37
+ export { openPopup, closePopup, focusPopup, isPopupBlocked, watchPopupClose, resizePopup, PopupOpenError, type PopupOptions, } from './popup';
38
+ export { defaultContainerTemplate, defaultPrerenderTemplate, applyDimensions, createStyleElement, fadeIn, fadeOut, swapPrerenderContent, } from './templates';