@hadyfayed/filament-react-wrapper
Version:
Enterprise React integration for Laravel/Filament - Smart asset loading, 90%+ React-PHP function mapping, no-plugin Filament integration
603 lines (591 loc) • 17.8 kB
JavaScript
import require$$0 from 'react-dom';
import { j as jsxRuntimeExports } from './state-management-CLPmisQN.js';
import React from 'react';
function _mergeNamespaces(n, m) {
for (var i = 0; i < m.length; i++) {
const e = m[i];
if (typeof e !== 'string' && !Array.isArray(e)) { for (const k in e) {
if (k !== 'default' && !(k in n)) {
const d = Object.getOwnPropertyDescriptor(e, k);
if (d) {
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: () => e[k]
});
}
}
} }
}
return Object.freeze(Object.defineProperty(n, Symbol.toStringTag, { value: 'Module' }));
}
var client$1 = {};
var hasRequiredClient;
function requireClient () {
if (hasRequiredClient) return client$1;
hasRequiredClient = 1;
var m = require$$0;
if (process.env.NODE_ENV === 'production') {
client$1.createRoot = m.createRoot;
client$1.hydrateRoot = m.hydrateRoot;
} else {
var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
client$1.createRoot = function(c, o) {
i.usingClientEntryPoint = true;
try {
return m.createRoot(c, o);
} finally {
i.usingClientEntryPoint = false;
}
};
client$1.hydrateRoot = function(c, h, o) {
i.usingClientEntryPoint = true;
try {
return m.hydrateRoot(c, h, o);
} finally {
i.usingClientEntryPoint = false;
}
};
}
return client$1;
}
var clientExports = requireClient();
const client = /*#__PURE__*/_mergeNamespaces({
__proto__: null
}, [clientExports]);
class ReactErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
console.error("React component error:", error, errorInfo);
this.props.onError?.(error);
}
render() {
if (this.state.hasError) {
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 border border-red-300 rounded-md bg-red-50", children: [
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-red-800 font-medium", children: "Component Error" }),
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-red-600 text-sm mt-1", children: this.state.error?.message || "An unexpected error occurred" }),
/* @__PURE__ */ jsxRuntimeExports.jsx(
"button",
{
onClick: () => this.setState({ hasError: false, error: void 0 }),
className: "mt-2 px-3 py-1 bg-red-600 text-white text-sm rounded hover:bg-red-700",
children: "Retry"
}
)
] });
}
return this.props.children;
}
}
const UniversalReactWrapper = React.memo(
({ componentName, componentProps, onDataChange, onError }) => {
const componentDef = React.useMemo(() => {
return componentRegistry.get(componentName);
}, [componentName]);
const Component = React.useMemo(() => {
if (!componentDef) return null;
if (componentDef.isAsync) {
return React.lazy(
componentDef.component
);
} else {
return componentDef.component;
}
}, [componentDef]);
const mergedProps = React.useMemo(
() => ({
...componentDef?.defaultProps || {},
...componentProps,
onDataChange
}),
[componentDef?.defaultProps, componentProps, onDataChange]
);
if (!componentDef || !Component) {
const error = new Error(
`Component "${componentName}" not found in registry`
);
onError?.(error);
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 border border-yellow-300 rounded-md bg-yellow-50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-yellow-800", children: [
'Component "',
componentName,
'" not found. Available components:',
" ",
componentRegistry.getComponentNames().join(", ") || "None"
] }) });
}
return /* @__PURE__ */ jsxRuntimeExports.jsx(ReactErrorBoundary, { onError, children: /* @__PURE__ */ jsxRuntimeExports.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Component, { ...mergedProps }) }) });
},
(prevProps, nextProps) => {
if (prevProps.componentName !== nextProps.componentName) {
return false;
}
try {
if (prevProps.componentProps === nextProps.componentProps) {
return true;
}
const prevKeys = Object.keys(prevProps.componentProps || {});
const nextKeys = Object.keys(nextProps.componentProps || {});
if (prevKeys.length !== nextKeys.length) {
return false;
}
if (prevKeys.length < 10) {
return JSON.stringify(prevProps.componentProps) === JSON.stringify(nextProps.componentProps);
}
return prevKeys.every(
(key) => prevProps.componentProps[key] === nextProps.componentProps[key]
);
} catch {
return prevProps.componentProps === nextProps.componentProps;
}
}
);
class UniversalReactRenderer {
roots = /* @__PURE__ */ new Map();
containers = /* @__PURE__ */ new Map();
/**
* Render a React component in the specified container
*/
render({
component,
props = {},
statePath,
containerId,
onDataChange,
onError
}) {
try {
const container = document.getElementById(containerId);
if (!container) {
throw new Error(`Container element with ID "${containerId}" not found`);
}
let root = this.roots.get(containerId);
if (!root) {
root = clientExports.createRoot(container);
this.roots.set(containerId, root);
this.containers.set(containerId, container);
}
const handleDataChange = (data) => {
if (onDataChange) {
onDataChange(data);
}
if (statePath && window.workflowDataSync) {
window.workflowDataSync(statePath, data);
}
};
root.render(
/* @__PURE__ */ jsxRuntimeExports.jsx(
UniversalReactWrapper,
{
componentName: component,
componentProps: props,
onDataChange: handleDataChange,
onError,
statePath
}
)
);
} catch (error) {
console.error("Error rendering React component:", error);
onError?.(error);
}
}
/**
* Update props for an already rendered component
*/
updateProps(containerId, newProps) {
const root = this.roots.get(containerId);
const container = this.containers.get(containerId);
if (!root || !container) {
console.warn(
`No rendered component found for container "${containerId}"`
);
return;
}
const existingData = container.dataset;
this.render({
component: existingData.component || "",
props: newProps,
statePath: existingData.statePath,
containerId
});
}
/**
* Unmount a React component
*/
unmount(containerId) {
const root = this.roots.get(containerId);
if (root) {
root.unmount();
this.roots.delete(containerId);
this.containers.delete(containerId);
}
}
/**
* Check if a component is rendered in the specified container
*/
isRendered(containerId) {
return this.roots.has(containerId);
}
/**
* Unmount all rendered components
*/
unmountAll() {
for (const [containerId] of this.roots) {
this.unmount(containerId);
}
}
/**
* Get list of active container IDs
*/
getActiveContainers() {
return Array.from(this.roots.keys());
}
/**
* Check if a container has an active React component
*/
hasActiveComponent(containerId) {
return this.roots.has(containerId);
}
}
const universalReactRenderer = new UniversalReactRenderer();
if (typeof window !== "undefined") {
window.addEventListener("beforeunload", () => {
universalReactRenderer.unmountAll();
});
}
if (typeof window !== "undefined") {
window.universalReactRenderer = universalReactRenderer;
}
class EventSystem {
listeners = /* @__PURE__ */ new Map();
on(event, callback, priority = 10) {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event).push({ callback, priority });
this.listeners.get(event).sort((a, b) => b.priority - a.priority);
}
off(event, callback) {
const listeners = this.listeners.get(event);
if (listeners) {
const index = listeners.findIndex((l) => l.callback === callback);
if (index !== -1) {
listeners.splice(index, 1);
}
}
}
emit(event, data) {
const listeners = this.listeners.get(event);
if (!listeners) return data;
let result = data;
for (const listener of listeners) {
try {
const returned = listener.callback(result);
if (returned !== void 0) {
result = returned;
}
} catch (error) {
console.error(`Error in event listener for ${event}:`, error);
}
}
return result;
}
hasListeners(event) {
return this.listeners.has(event) && this.listeners.get(event).length > 0;
}
clear() {
this.listeners.clear();
}
getListenerCount(event) {
if (event) {
return this.listeners.get(event)?.length || 0;
}
return Array.from(this.listeners.values()).reduce(
(total, arr) => total + arr.length,
0
);
}
}
class ReactComponentRegistry {
components = /* @__PURE__ */ new Map();
events = new EventSystem();
extensions = /* @__PURE__ */ new Map();
middleware = [];
// Component factory for future extensibility
// private componentFactory: ComponentFactoryManager =
// new ComponentFactoryManager();
/**
* Register a React component with enhanced features
*/
register(definition) {
this.events.emit("component:registering", { definition });
if (definition.config?.dependencies) {
for (const dep of definition.config.dependencies) {
if (!this.has(dep)) {
console.warn(
`Component ${definition.name} depends on ${dep} which is not registered`
);
}
}
}
const isAsyncImport = typeof definition.component === "function" && !(definition.component.prototype && definition.component.prototype.isReactComponent);
let processedComponent = definition.component;
if (isAsyncImport && definition.isAsync !== false && !definition.isAsync) {
console.warn(
`Component ${definition.name} appears to be an async import but lazy loading is disabled in bundled mode. Ensure all components are imported synchronously.`
);
definition.isAsync = true;
}
for (const middleware of this.middleware) {
const context = {
registry: this,
hooks: this.createHookManager(),
config: definition.config || {},
metadata: definition.metadata || {}
};
try {
const result = middleware(
processedComponent,
definition.defaultProps || {},
context
);
if (result instanceof Promise) {
result.then((comp) => processedComponent = comp).catch((error) => {
console.error(`Error in async middleware for ${definition.name}:`, error);
});
} else {
processedComponent = result;
}
} catch (error) {
console.error(`Error in middleware for ${definition.name}:`, error);
}
}
const processedDefinition = {
...definition,
component: processedComponent,
isAsync: definition.isAsync,
config: {
lazy: false,
cache: false,
ssr: false,
preload: false,
...definition.config
}
};
this.components.set(definition.name, processedDefinition);
this.events.emit("component:registered", {
definition: processedDefinition
});
}
/**
* Get a registered component by name
*/
get(name) {
const definition = this.components.get(name);
if (definition) {
this.events.emit("component:accessed", { name, definition });
}
return definition;
}
/**
* Create a component instance with processing
*/
create(name, props = {}) {
const definition = this.get(name);
if (!definition) {
console.error(`Component ${name} not found in registry`);
return null;
}
const mergedProps = { ...definition.defaultProps, ...props };
let component = definition.component;
if (definition.config?.middleware) {
for (const middleware of definition.config.middleware) {
const context = {
registry: this,
hooks: this.createHookManager(),
config: definition.config,
metadata: definition.metadata || {}
};
if (typeof component === "function" && !component.then && (component.prototype?.isReactComponent || typeof component === "function" && !component.prototype?.isReactComponent)) {
component = middleware(
component,
mergedProps,
context
);
}
}
}
this.events.emit("component:created", {
name,
props: mergedProps,
component
});
if (typeof component === "function" && !component.then && (component.prototype?.isReactComponent || typeof component === "function" && !component.prototype?.isReactComponent)) {
return component;
}
console.error(`Component ${name} is not a valid React component`);
return () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
"Invalid component: ",
name
] });
}
/**
* Register an extension
*/
registerExtension(name, extension) {
this.extensions.set(name, extension);
this.events.emit("extension:registered", { name, extension });
}
/**
* Add global middleware
*/
addMiddleware(middleware) {
this.middleware.push(middleware);
}
/**
* Get all registered components with filtering
*/
getAll(filter) {
if (!filter) {
return new Map(this.components);
}
const filtered = /* @__PURE__ */ new Map();
this.components.forEach((definition, name) => {
let include = true;
if (filter.category && definition.metadata?.category !== filter.category) {
include = false;
}
if (filter.tag && !definition.metadata?.tags?.includes(filter.tag)) {
include = false;
}
if (filter.name && !filter.name.test(name)) {
include = false;
}
if (include) {
filtered.set(name, definition);
}
});
return filtered;
}
/**
* Check if a component is registered
*/
has(name) {
return this.components.has(name);
}
/**
* Unregister a component
*/
unregister(name) {
if (this.components.has(name)) {
this.events.emit("component:unregistering", { name });
const result = this.components.delete(name);
this.events.emit("component:unregistered", { name });
return result;
}
return false;
}
/**
* Clear all registered components
*/
clear() {
this.events.emit("registry:clearing");
this.components.clear();
this.events.emit("registry:cleared");
}
/**
* Get list of registered component names
*/
getComponentNames() {
return Array.from(this.components.keys());
}
/**
* Get component statistics
*/
getStats() {
const stats = {
totalComponents: this.components.size,
categoryCounts: {},
tagCounts: {}
};
this.components.forEach((definition) => {
const category = definition.metadata?.category || "uncategorized";
stats.categoryCounts[category] = (stats.categoryCounts[category] || 0) + 1;
if (definition.metadata?.tags) {
for (const tag of definition.metadata.tags) {
stats.tagCounts[tag] = (stats.tagCounts[tag] || 0) + 1;
}
}
});
return stats;
}
/**
* Add event listener
*/
on(event, callback, priority) {
this.events.on(event, callback, priority);
}
/**
* Remove event listener
*/
off(event, callback) {
this.events.off(event, callback);
}
/**
* Mount a component to a DOM container (for Blade template compatibility)
*/
mount(componentName, containerId, props = {}) {
try {
universalReactRenderer.render({
component: componentName,
props,
containerId,
onDataChange: props.onDataChange,
onError: (error) => {
console.error(`Error mounting component ${componentName}:`, error);
}
});
} catch (error) {
console.error(`Failed to mount component ${componentName}:`, error);
}
}
/**
* Unmount a component from a DOM container
*/
unmount(containerId) {
try {
universalReactRenderer.unmount(containerId);
} catch (error) {
console.error(`Failed to unmount component:`, error);
}
}
/**
* Create hook manager for component context
*/
createHookManager() {
return {
addHook: (event, callback, priority) => {
this.events.on(event, callback, priority);
},
removeHook: (event, callback) => {
this.events.off(event, callback);
},
executeHooks: (event, data) => {
return this.events.emit(event, data);
}
};
}
}
const componentRegistry = new ReactComponentRegistry();
function registerComponents(definitions) {
definitions.forEach((definition) => {
componentRegistry.register(definition);
});
}
export { componentRegistry as a, client as c, registerComponents as r, universalReactRenderer as u };
//# sourceMappingURL=component-system-Bjje-CZe.js.map