/**
* LazyComponent - Universal lazy loading wrapper
*
* Provides consistent Suspense handling for lazy-loaded components
* Works in any React environment: Next.js, Vite, Wails, CRA
*/
'use client';
import React, { Suspense, ReactNode, ComponentType, lazy } from 'react';
// Default loading spinner
export const DefaultLoader = () => (
);
// Minimal loader for inline components
export const InlineLoader = () => (
Loading...
);
// Full-screen loader
export const FullScreenLoader = () => (
);
export interface LazyWrapperProps {
children: ReactNode;
fallback?: ReactNode;
}
/**
* Suspense wrapper with default fallback
*/
export function LazyWrapper({ children, fallback }: LazyWrapperProps) {
return (
}>
{children}
);
}
/**
* Create a lazy-loaded component with Suspense wrapper built-in
*
* @example
* ```tsx
* const HeavyComponent = createLazyComponent(
* () => import('./HeavyComponent'),
*
* );
*
* // Usage - no need to wrap in Suspense
*
* ```
*/
export function createLazyComponent>(
importFn: () => Promise<{ default: T }>,
fallback?: ReactNode
) {
const LazyComponent = lazy(importFn);
return function WrappedLazyComponent(props: React.ComponentProps) {
return (
}>
);
};
}
/**
* Create a lazy-loaded component from a named export
*
* @example
* ```tsx
* const NamedComponent = createLazyNamedComponent(
* () => import('./module'),
* 'NamedExport',
*
* );
* ```
*/
export function createLazyNamedComponent<
T extends Record>,
K extends keyof T
>(
importFn: () => Promise,
exportName: K,
fallback?: ReactNode
) {
const LazyComponent = lazy(() =>
importFn().then((mod) => ({ default: mod[exportName] }))
);
return function WrappedLazyComponent(props: React.ComponentProps) {
return (
}>
);
};
}