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,225 @@
1
+ import type { ForgeFrameComponent } from '../types';
2
+ import type { ContextType } from '../constants';
3
+ /**
4
+ * Minimal React-like interface for driver compatibility.
5
+ *
6
+ * @remarks
7
+ * These are minimal type definitions to avoid requiring `@types/react` as a dependency.
8
+ * The driver only uses a subset of React's API, so any React-compatible library
9
+ * (such as Preact with compat) can be used as long as it implements these methods.
10
+ *
11
+ * @internal
12
+ */
13
+ interface ReactLike {
14
+ createElement: (type: unknown, props?: Record<string, unknown> | null, ...children: unknown[]) => unknown;
15
+ useRef: <T>(initial: T | null) => {
16
+ current: T | null;
17
+ };
18
+ useEffect: (effect: () => void | (() => void), deps?: unknown[]) => void;
19
+ useState: <T>(initial: T) => [T, (v: T) => void];
20
+ forwardRef: <T, P>(render: (props: P, ref: {
21
+ current: T | null;
22
+ } | null) => unknown) => unknown;
23
+ }
24
+ /**
25
+ * Props for the generated React component wrapper.
26
+ *
27
+ * @remarks
28
+ * These props are available on all React components created by the driver,
29
+ * in addition to the component-specific props defined in the ForgeFrame component.
30
+ *
31
+ * @typeParam _P - The component-specific props type (unused in base interface)
32
+ *
33
+ * @public
34
+ */
35
+ export interface ReactComponentProps<_P = unknown> {
36
+ /**
37
+ * Callback invoked when the component has finished rendering.
38
+ *
39
+ * @remarks
40
+ * This is called once the cross-domain component has been fully mounted
41
+ * and is visible to the user.
42
+ */
43
+ onRendered?: () => void;
44
+ /**
45
+ * Callback invoked when the component encounters an error.
46
+ *
47
+ * @param error - The error that occurred during rendering or operation
48
+ *
49
+ * @remarks
50
+ * Errors can occur during initial render, prop updates, or cross-domain communication.
51
+ */
52
+ onError?: (error: Error) => void;
53
+ /**
54
+ * Callback invoked when the component is closed.
55
+ *
56
+ * @remarks
57
+ * This is triggered when the cross-domain component is programmatically closed
58
+ * or when the user closes a popup window.
59
+ */
60
+ onClose?: () => void;
61
+ /**
62
+ * The rendering context for the component.
63
+ *
64
+ * @remarks
65
+ * Determines whether the component renders in an iframe or popup window.
66
+ * Defaults to the component's configured default context.
67
+ */
68
+ context?: ContextType;
69
+ /**
70
+ * CSS class name applied to the container element.
71
+ *
72
+ * @remarks
73
+ * The container is a `div` element that wraps the iframe or serves as
74
+ * the anchor point for popup positioning.
75
+ */
76
+ className?: string;
77
+ /**
78
+ * Inline styles applied to the container element.
79
+ *
80
+ * @remarks
81
+ * These styles are merged with the default container styles.
82
+ * The container defaults to `display: inline-block`.
83
+ */
84
+ style?: Record<string, string | number>;
85
+ }
86
+ /**
87
+ * Full props type combining driver props with component-specific props.
88
+ *
89
+ * @typeParam P - The component-specific props type from the ForgeFrame component
90
+ *
91
+ * @remarks
92
+ * This type merges {@link ReactComponentProps} with the component's own props,
93
+ * making all component props optional since they can have defaults.
94
+ *
95
+ * @internal
96
+ */
97
+ type FullReactComponentProps<P> = ReactComponentProps<P> & Partial<P>;
98
+ /**
99
+ * Configuration options for creating a React driver.
100
+ *
101
+ * @remarks
102
+ * The React instance must be provided to avoid bundling React with the driver.
103
+ * This allows the driver to work with any version of React that implements
104
+ * the required hooks and methods.
105
+ *
106
+ * @public
107
+ */
108
+ export interface ReactDriverOptions {
109
+ /**
110
+ * The React library instance to use for component creation.
111
+ *
112
+ * @remarks
113
+ * Must provide `createElement`, `useRef`, `useEffect`, `useState`, and `forwardRef`.
114
+ * Compatible with React 16.8+ and Preact with compat.
115
+ */
116
+ React: ReactLike;
117
+ }
118
+ /**
119
+ * Type definition for a React component created by the driver.
120
+ *
121
+ * @typeParam P - The props type for the component
122
+ *
123
+ * @remarks
124
+ * This interface represents the callable component function returned by
125
+ * {@link createReactDriver}. It includes an optional `displayName` for
126
+ * React DevTools integration.
127
+ *
128
+ * @public
129
+ */
130
+ export interface ReactComponentType<P> {
131
+ /**
132
+ * Renders the component with the given props.
133
+ *
134
+ * @param props - The component props
135
+ * @returns A React element (type varies by React version)
136
+ */
137
+ (props: P): unknown;
138
+ /**
139
+ * Display name shown in React DevTools.
140
+ *
141
+ * @remarks
142
+ * Automatically set to `ForgeFrame(ComponentName)` by the driver.
143
+ */
144
+ displayName?: string;
145
+ }
146
+ /**
147
+ * Creates a React component wrapper for a ForgeFrame cross-domain component.
148
+ *
149
+ * @typeParam P - The props type defined in the ForgeFrame component
150
+ * @typeParam X - The export type for data shared from the child component
151
+ *
152
+ * @param Component - The ForgeFrame component to wrap
153
+ * @param options - Configuration options including the React instance
154
+ *
155
+ * @returns A React component that renders the ForgeFrame component
156
+ *
157
+ * @remarks
158
+ * This function bridges ForgeFrame's cross-domain component system with React's
159
+ * component model. The returned component handles:
160
+ * - Mounting and unmounting lifecycle
161
+ * - Prop synchronization with the cross-domain component
162
+ * - Error boundary integration via the `onError` callback
163
+ * - Ref forwarding to the container element
164
+ *
165
+ * The component automatically cleans up the cross-domain connection when unmounted.
166
+ *
167
+ * @example
168
+ * ```tsx
169
+ * import React from 'react';
170
+ * import ForgeFrame from 'forgeframe';
171
+ * import { createReactDriver } from 'forgeframe/drivers/react';
172
+ *
173
+ * const LoginComponent = ForgeFrame.create({
174
+ * tag: 'login-component',
175
+ * url: 'https://example.com/login',
176
+ * props: {
177
+ * onLogin: { type: ForgeFrame.PROP_TYPE.FUNCTION },
178
+ * },
179
+ * });
180
+ *
181
+ * const LoginReact = createReactDriver(LoginComponent, { React });
182
+ *
183
+ * // Usage in JSX:
184
+ * <LoginReact onLogin={(user) => console.log(user)} />
185
+ * ```
186
+ *
187
+ * @public
188
+ */
189
+ export declare function createReactDriver<P extends Record<string, unknown>, X = unknown>(Component: ForgeFrameComponent<P, X>, options: ReactDriverOptions): ReactComponentType<FullReactComponentProps<P>>;
190
+ /**
191
+ * Creates a curried React driver factory with a pre-configured React instance.
192
+ *
193
+ * @param React - The React library instance to use for all created components
194
+ *
195
+ * @returns A function that creates React wrappers for ForgeFrame components
196
+ *
197
+ * @remarks
198
+ * This is a higher-order function that simplifies creating multiple React drivers
199
+ * with the same React instance. It returns a driver factory that can be reused
200
+ * across multiple ForgeFrame components.
201
+ *
202
+ * This pattern is useful when you have many ForgeFrame components and want to
203
+ * avoid passing the React instance repeatedly.
204
+ *
205
+ * @example
206
+ * ```tsx
207
+ * import React from 'react';
208
+ * import ForgeFrame from 'forgeframe';
209
+ * import { withReactDriver } from 'forgeframe/drivers/react';
210
+ *
211
+ * // Create a reusable driver factory
212
+ * const createDriver = withReactDriver(React);
213
+ *
214
+ * // Create multiple React components using the same factory
215
+ * const LoginComponent = ForgeFrame.create({ tag: 'login', url: '...' });
216
+ * const ProfileComponent = ForgeFrame.create({ tag: 'profile', url: '...' });
217
+ *
218
+ * const LoginReact = createDriver(LoginComponent);
219
+ * const ProfileReact = createDriver(ProfileComponent);
220
+ * ```
221
+ *
222
+ * @public
223
+ */
224
+ export declare function withReactDriver(React: ReactLike): <P extends Record<string, unknown>, X = unknown>(Component: ForgeFrameComponent<P, X>) => ReactComponentType<FullReactComponentProps<P>>;
225
+ export default createReactDriver;
@@ -0,0 +1,150 @@
1
+ import type { EventHandler, EventEmitterInterface } from '../types';
2
+ /**
3
+ * A simple typed event emitter for component lifecycle events.
4
+ *
5
+ * @remarks
6
+ * This class provides a lightweight publish-subscribe pattern implementation
7
+ * with support for typed events, one-time subscriptions, and automatic cleanup.
8
+ * It is used internally by ForgeFrame components for lifecycle event management.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const emitter = new EventEmitter();
13
+ *
14
+ * // Subscribe to an event
15
+ * const unsubscribe = emitter.on<string>('message', (data) => {
16
+ * console.log('Received:', data);
17
+ * });
18
+ *
19
+ * // Emit an event
20
+ * emitter.emit('message', 'Hello, World!');
21
+ *
22
+ * // Unsubscribe when done
23
+ * unsubscribe();
24
+ * ```
25
+ *
26
+ * @public
27
+ */
28
+ export declare class EventEmitter implements EventEmitterInterface {
29
+ /**
30
+ * Internal storage for event listeners mapped by event name.
31
+ * @internal
32
+ */
33
+ private listeners;
34
+ /**
35
+ * Subscribes a handler to a specific event.
36
+ *
37
+ * @typeParam T - The type of data expected by the event handler
38
+ * @param event - The name of the event to subscribe to
39
+ * @param handler - The callback function to invoke when the event is emitted
40
+ * @returns A function that, when called, unsubscribes the handler from the event
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const unsubscribe = emitter.on<{ userId: string }>('login', (data) => {
45
+ * console.log('User logged in:', data.userId);
46
+ * });
47
+ * ```
48
+ *
49
+ * @public
50
+ */
51
+ on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
52
+ /**
53
+ * Subscribes a handler to an event that will automatically unsubscribe after the first invocation.
54
+ *
55
+ * @typeParam T - The type of data expected by the event handler
56
+ * @param event - The name of the event to subscribe to
57
+ * @param handler - The callback function to invoke once when the event is emitted
58
+ * @returns A function that, when called, unsubscribes the handler before it fires
59
+ *
60
+ * @remarks
61
+ * This is useful for one-time event handling, such as waiting for an initialization
62
+ * event or a single response.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * emitter.once('ready', () => {
67
+ * console.log('Component is ready!');
68
+ * });
69
+ * ```
70
+ *
71
+ * @public
72
+ */
73
+ once<T = unknown>(event: string, handler: EventHandler<T>): () => void;
74
+ /**
75
+ * Emits an event, invoking all registered handlers with the provided data.
76
+ *
77
+ * @typeParam T - The type of data to pass to event handlers
78
+ * @param event - The name of the event to emit
79
+ * @param data - Optional data to pass to all registered handlers
80
+ *
81
+ * @remarks
82
+ * Handlers are invoked synchronously in the order they were registered.
83
+ * If a handler throws an error, it is caught and logged to the console,
84
+ * allowing subsequent handlers to still execute.
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * emitter.emit('userAction', { action: 'click', target: 'button' });
89
+ * ```
90
+ *
91
+ * @public
92
+ */
93
+ emit<T = unknown>(event: string, data?: T): void;
94
+ /**
95
+ * Unsubscribes a handler from an event, or removes all handlers for the event.
96
+ *
97
+ * @param event - The name of the event to unsubscribe from
98
+ * @param handler - The specific handler to remove. If not provided, all handlers for the event are removed.
99
+ *
100
+ * @remarks
101
+ * When a specific handler is removed and it was the last handler for that event,
102
+ * the event entry is cleaned up from the internal map.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * // Remove a specific handler
107
+ * emitter.off('message', myHandler);
108
+ *
109
+ * // Remove all handlers for an event
110
+ * emitter.off('message');
111
+ * ```
112
+ *
113
+ * @public
114
+ */
115
+ off(event: string, handler?: EventHandler): void;
116
+ /**
117
+ * Removes all event listeners from the emitter.
118
+ *
119
+ * @remarks
120
+ * This method is typically called during component cleanup or disposal
121
+ * to ensure no memory leaks from lingering event subscriptions.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * // Clean up all listeners when component is destroyed
126
+ * emitter.removeAllListeners();
127
+ * ```
128
+ *
129
+ * @public
130
+ */
131
+ removeAllListeners(): void;
132
+ /**
133
+ * Returns the number of listeners registered for a specific event.
134
+ *
135
+ * @param event - The name of the event to check
136
+ * @returns The number of handlers currently subscribed to the event
137
+ *
138
+ * @remarks
139
+ * This method is primarily useful for debugging and testing purposes
140
+ * to verify that subscriptions are being properly managed.
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * console.log(`Active listeners: ${emitter.listenerCount('message')}`);
145
+ * ```
146
+ *
147
+ * @public
148
+ */
149
+ listenerCount(event: string): number;
150
+ }