@memberjunction/react-runtime 2.78.0 → 2.80.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.
@@ -1,249 +0,0 @@
1
- /**
2
- * @fileoverview React component wrapper utilities.
3
- * Provides HOCs and utilities for wrapping components with additional functionality.
4
- * @module @memberjunction/react-runtime/runtime
5
- */
6
-
7
- import { ComponentProps, ComponentLifecycle } from '../types';
8
-
9
- /**
10
- * Options for wrapping a component
11
- */
12
- export interface WrapperOptions {
13
- /** Component display name */
14
- displayName?: string;
15
- /** Enable performance monitoring */
16
- enableProfiling?: boolean;
17
- /** Enable props logging */
18
- logProps?: boolean;
19
- /** Lifecycle hooks */
20
- lifecycle?: ComponentLifecycle;
21
- /** Default props */
22
- defaultProps?: Partial<ComponentProps>;
23
- }
24
-
25
- /**
26
- * Wraps a React component with additional functionality
27
- * @param React - React library instance
28
- * @param Component - Component to wrap
29
- * @param options - Wrapper options
30
- * @returns Wrapped component
31
- */
32
- export function wrapComponent(React: any, Component: any, options: WrapperOptions = {}): any {
33
- const {
34
- displayName,
35
- enableProfiling = false,
36
- logProps = false,
37
- lifecycle = {},
38
- defaultProps = {}
39
- } = options;
40
-
41
- // Create wrapper component
42
- const WrappedComponent = React.forwardRef((props: any, ref: any) => {
43
- const mergedProps = { ...defaultProps, ...props };
44
-
45
- // Log props if enabled
46
- React.useEffect(() => {
47
- if (logProps) {
48
- console.log(`[${displayName || Component.name}] Props:`, mergedProps);
49
- }
50
- }, [mergedProps]);
51
-
52
- // Lifecycle: beforeMount
53
- React.useEffect(() => {
54
- if (lifecycle.beforeMount) {
55
- lifecycle.beforeMount();
56
- }
57
-
58
- // Lifecycle: afterMount
59
- if (lifecycle.afterMount) {
60
- lifecycle.afterMount();
61
- }
62
-
63
- // Lifecycle: beforeUnmount
64
- return () => {
65
- if (lifecycle.beforeUnmount) {
66
- lifecycle.beforeUnmount();
67
- }
68
- };
69
- }, []);
70
-
71
- // Lifecycle: beforeUpdate/afterUpdate
72
- const prevPropsRef = React.useRef(mergedProps);
73
- React.useEffect(() => {
74
- const prevProps = prevPropsRef.current;
75
-
76
- if (lifecycle.beforeUpdate) {
77
- lifecycle.beforeUpdate(prevProps, mergedProps);
78
- }
79
-
80
- // Schedule afterUpdate
81
- if (lifecycle.afterUpdate) {
82
- Promise.resolve().then(() => {
83
- lifecycle.afterUpdate!(prevProps, mergedProps);
84
- });
85
- }
86
-
87
- prevPropsRef.current = mergedProps;
88
- });
89
-
90
- // Render with profiling if enabled
91
- if (enableProfiling && React.Profiler) {
92
- return React.createElement(
93
- React.Profiler,
94
- {
95
- id: displayName || Component.name || 'WrappedComponent',
96
- onRender: (id: string, phase: string, actualDuration: number) => {
97
- console.log(`[Profiler] ${id} (${phase}): ${actualDuration.toFixed(2)}ms`);
98
- }
99
- },
100
- React.createElement(Component, { ...mergedProps, ref })
101
- );
102
- }
103
-
104
- return React.createElement(Component, { ...mergedProps, ref });
105
- });
106
-
107
- // Set display name
108
- WrappedComponent.displayName = displayName || `Wrapped(${Component.displayName || Component.name || 'Component'})`;
109
-
110
- return WrappedComponent;
111
- }
112
-
113
- /**
114
- * Creates a memoized version of a component
115
- * @param React - React library instance
116
- * @param Component - Component to memoize
117
- * @param propsAreEqual - Optional comparison function
118
- * @returns Memoized component
119
- */
120
- export function memoizeComponent(
121
- React: any,
122
- Component: any,
123
- propsAreEqual?: (prevProps: any, nextProps: any) => boolean
124
- ): any {
125
- return React.memo(Component, propsAreEqual);
126
- }
127
-
128
- /**
129
- * Creates a lazy-loaded component
130
- * @param React - React library instance
131
- * @param loader - Function that returns a promise resolving to the component
132
- * @param fallback - Optional loading fallback
133
- * @returns Lazy component
134
- */
135
- export function lazyComponent(
136
- React: any,
137
- loader: () => Promise<{ default: any }>,
138
- fallback?: any
139
- ): any {
140
- const LazyComponent = React.lazy(loader);
141
-
142
- if (fallback) {
143
- return (props: any) => React.createElement(
144
- React.Suspense,
145
- { fallback },
146
- React.createElement(LazyComponent, props)
147
- );
148
- }
149
-
150
- return LazyComponent;
151
- }
152
-
153
- /**
154
- * Injects additional props into a component
155
- * @param React - React library instance
156
- * @param Component - Component to inject props into
157
- * @param injectedProps - Props to inject
158
- * @returns Component with injected props
159
- */
160
- export function injectProps(React: any, Component: any, injectedProps: any): any {
161
- return React.forwardRef((props: any, ref: any) => {
162
- const mergedProps = { ...injectedProps, ...props };
163
- return React.createElement(Component, { ...mergedProps, ref });
164
- });
165
- }
166
-
167
- /**
168
- * Creates a component that renders conditionally
169
- * @param React - React library instance
170
- * @param Component - Component to render conditionally
171
- * @param condition - Condition function or boolean
172
- * @param fallback - Optional fallback component
173
- * @returns Conditional component
174
- */
175
- export function conditionalComponent(
176
- React: any,
177
- Component: any,
178
- condition: boolean | ((props: any) => boolean),
179
- fallback?: any
180
- ): any {
181
- return (props: any) => {
182
- const shouldRender = typeof condition === 'function' ? condition(props) : condition;
183
-
184
- if (shouldRender) {
185
- return React.createElement(Component, props);
186
- }
187
-
188
- return fallback || null;
189
- };
190
- }
191
-
192
- /**
193
- * Creates a component with default error handling
194
- * @param React - React library instance
195
- * @param Component - Component to wrap
196
- * @param errorHandler - Error handling function
197
- * @returns Component with error handling
198
- */
199
- export function withErrorHandler(
200
- React: any,
201
- Component: any,
202
- errorHandler: (error: Error) => void
203
- ): any {
204
- return class extends React.Component {
205
- componentDidCatch(error: Error, errorInfo: any) {
206
- errorHandler(error);
207
- }
208
-
209
- render() {
210
- return React.createElement(Component, this.props);
211
- }
212
- };
213
- }
214
-
215
- /**
216
- * Creates a portal wrapper component
217
- * @param React - React library instance
218
- * @param ReactDOM - ReactDOM library instance
219
- * @param Component - Component to render in portal
220
- * @param container - DOM container element or selector
221
- * @returns Portal component
222
- */
223
- export function portalComponent(
224
- React: any,
225
- ReactDOM: any,
226
- Component: any,
227
- container: Element | string
228
- ): any {
229
- return (props: any) => {
230
- const [mountNode, setMountNode] = React.useState(null as Element | null);
231
-
232
- React.useEffect(() => {
233
- const node = typeof container === 'string'
234
- ? document.querySelector(container)
235
- : container;
236
-
237
- setMountNode(node);
238
- }, []);
239
-
240
- if (!mountNode || !ReactDOM.createPortal) {
241
- return null;
242
- }
243
-
244
- return ReactDOM.createPortal(
245
- React.createElement(Component, props),
246
- mountNode
247
- );
248
- };
249
- }