@gaddario98/react-pages
Version:
A powerful, performance-optimized React component library for creating dynamic pages that work seamlessly across web (React DOM) and React Native with integrated form management, query handling, SEO metadata, lazy loading, and content rendering.
1,213 lines (1,187 loc) • 59.9 kB
TypeScript
import * as react_hook_form from 'react-hook-form';
import { FieldValues, UseFormSetValue, DefaultValues, Path } from 'react-hook-form';
import * as react from 'react';
import react__default, { ComponentProps, ReactNode, ComponentType, Suspense } from 'react';
import * as _gaddario98_react_queries from '@gaddario98/react-queries';
import { QueriesArray, MultipleQueryResponse, AllMutation, QueryDefinition, MutationConfig, QueryProps, QueryAtIndex, ExtractQuery } from '@gaddario98/react-queries';
import * as _gaddario98_react_form from '@gaddario98/react-form';
import { FormManagerConfig, Submit, FormManager, FormElements } from '@gaddario98/react-form';
import { AuthState } from '@gaddario98/react-auth';
import { ExtractorCache } from '@gaddario98/utiles';
import * as react_jsx_runtime from 'react/jsx-runtime';
/**
* Metadata Configuration Types
* Custom metadata system replacing react-helmet-async
* Platform-agnostic: works on web, React Native, and SSR
*/
/**
* Context passed to dynamic metadata evaluator functions
* Provides access to form values, queries, and page state
*/
interface MetadataEvaluatorContext<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Current form values */
formValues?: Partial<F>;
/** All query results mapped by key */
allQuery?: Record<string, any>;
/** All mutations mapped by key */
allMutation?: Record<string, any>;
/** Namespace for i18n */
ns?: string;
/** Page ID */
pageId?: string;
/** Page config */
pageConfig?: PageProps<F, Q>;
}
interface MetaTag {
/** For <meta name="..." content="..." /> */
name?: string;
/** For <meta property="og:..." content="..." /> */
property?: string;
/** For <meta http-equiv="..." content="..." /> */
httpEquiv?: string;
/** Meta tag content */
content: string;
/** Unique identifier for updating existing tags */
id?: string;
}
/**
* Open Graph Configuration (Facebook, LinkedIn, Twitter/X)
*/
interface OpenGraphConfig<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
type?: "website" | "article" | "product" | "profile";
title?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
description?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** URL to preview image (must be absolute) */
image?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** Canonical URL */
url?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
siteName?: string;
/** Locale (e.g., "en_US", "it_IT") */
locale?: string;
}
/**
* Structured Data Configuration (schema.org JSON-LD)
*/
interface StructuredDataConfig<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
type: "Article" | "Product" | "WebPage" | "FAQPage" | "Organization" | "Person";
schema: Record<string, unknown> | ((context: MetadataEvaluatorContext<F, Q>) => Record<string, unknown>);
}
/**
* AI Crawler Hints (for AI search engines and LLMs)
*/
interface AIHintsConfig<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Content classification (e.g., "documentation", "tutorial", "reference") */
contentClassification?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** Hints for AI models (e.g., ["code-heavy", "technical"]) */
modelHints?: string[] | ((context: MetadataEvaluatorContext<F, Q>) => string[]);
/** Additional context for AI understanding */
contextualInfo?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** Exclude this page from AI crawler indexing */
excludeFromIndexing?: boolean;
}
/**
* Robots Configuration (indexing directives)
*/
interface RobotsConfig {
/** Prevent indexing */
noindex?: boolean;
/** Don't follow links */
nofollow?: boolean;
/** Don't cache page */
noarchive?: boolean;
/** Don't show snippets in search results */
nosnippet?: boolean;
/** Image preview size in search results */
maxImagePreview?: "none" | "standard" | "large";
/** Max snippet length in search results */
maxSnippet?: number;
}
/**
* Complete Metadata Configuration (Generic over F and Q for dynamic metadata)
*/
interface MetadataConfig<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Page title - sets document.title on web */
title?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** Page description meta tag */
description?: string | ((context: MetadataEvaluatorContext<F, Q>) => string);
/** HTML lang attribute (e.g., "en", "it") */
documentLang?: string;
/** Keywords for SEO */
keywords?: string[] | ((context: MetadataEvaluatorContext<F, Q>) => string[]);
openGraph?: OpenGraphConfig<F, Q>;
structuredData?: StructuredDataConfig<F, Q>;
aiHints?: AIHintsConfig<F, Q>;
robots?: RobotsConfig;
customMeta?: MetaTag[] | ((context: MetadataEvaluatorContext<F, Q>) => MetaTag[]);
otherMetaTags?: MetaTag[] | ((context: MetadataEvaluatorContext<F, Q>) => MetaTag[]);
disableIndexing?: boolean;
/** @deprecated Use openGraph.image instead */
ogImage?: string;
/** @deprecated Use openGraph.title instead */
ogTitle?: string;
/** @deprecated Use openGraph.url instead */
canonical?: string;
/** @deprecated Use documentLang instead */
lang?: string;
/** Author meta tag */
author?: string;
/** Viewport meta tag (defaults to "width=device-width, initial-scale=1") */
viewport?: string;
/** Theme color for browser UI */
themeColor?: string;
}
interface MetadataProvider {
/** Apply metadata configuration to the page */
setMetadata: (config: MetadataConfig) => void;
/** Get current metadata configuration */
getMetadata: () => MetadataConfig;
/** Reset all metadata to defaults */
resetMetadata: () => void;
}
/**
* Configuration for lazy loading and code splitting behavior
* Enables deferred component loading to reduce initial bundle size
*/
interface LazyLoadingConfig {
/** Enable lazy loading (default: true) */
enabled?: boolean;
/** Preload on hover for interactive elements (default: false) */
preloadOnHover?: boolean;
/** Preload on focus for keyboard navigation (default: false) */
preloadOnFocus?: boolean;
/** Preload after render with delay (in ms, default: undefined - no delay) */
preloadAfterRender?: number;
/** Fallback component to show while loading (default: null) */
suspenseFallback?: React.ReactNode;
/** Custom error boundary component for lazy-loaded modules */
errorBoundary?: React.ComponentType<{
error: Error;
retry: () => void;
}>;
/** Maximum time to wait before showing error state (in ms, default: 30000) */
timeout?: number;
/** Log performance metrics for lazy loading (development only) */
logMetrics?: boolean;
/** IntersectionObserver threshold (0-1, default: 0.1) - alias for intersectionThreshold */
threshold?: number | number[];
/** IntersectionObserver threshold (0-1, default: 0.1) */
intersectionThreshold?: number | number[];
/** IntersectionObserver root margin (default: "100px") - alias for intersectionRootMargin */
rootMargin?: string;
/** IntersectionObserver root margin (default: "100px") */
intersectionRootMargin?: string;
/** Trigger type for lazy loading: viewport (IntersectionObserver), interaction (manual), or conditional (based on function) */
trigger?: "viewport" | "interaction" | "conditional";
/** Conditional function to determine if content should load (for trigger: "conditional") */
condition?: (context: MetadataEvaluatorContext) => boolean;
/** Placeholder component to show before lazy content loads */
placeholder?: React.ReactNode;
}
/**
* Custom Metadata Configuration System
* Replaces react-helmet-async with ~1KB native implementation
* Platform-agnostic: Web, React Native, and SSR support
*/
/**
* Apply metadata configuration to the page
* @param config - Metadata configuration object
*/
declare const setMetadata: (config: MetadataConfig) => void;
/**
* Get current metadata configuration (T073)
* Useful for SSR framework integration, testing, and debugging
*
* @example SSR with Next.js App Router
* ```typescript
* import { getMetadata } from '@gaddario98/react-pages';
*
* export async function generateMetadata() {
* const metadata = getMetadata();
* return {
* title: metadata.title,
* description: metadata.description,
* openGraph: {
* title: metadata.openGraph?.title,
* description: metadata.openGraph?.description,
* images: metadata.openGraph?.image ? [metadata.openGraph.image] : undefined,
* url: metadata.openGraph?.url,
* type: metadata.openGraph?.type as any,
* locale: metadata.openGraph?.locale,
* siteName: metadata.openGraph?.siteName,
* },
* };
* }
* ```
*
* @example SSR with Remix
* ```typescript
* import { getMetadata } from '@gaddario98/react-pages';
*
* export const meta: MetaFunction = () => {
* const metadata = getMetadata();
* return [
* { title: metadata.title },
* { name: 'description', content: metadata.description },
* { property: 'og:title', content: metadata.openGraph?.title },
* { property: 'og:description', content: metadata.openGraph?.description },
* ];
* };
* ```
*/
declare const getMetadata: () => MetadataConfig;
/**
* Reset all metadata to defaults
* Removes dynamically-added meta tags on web
*/
declare const resetMetadata: () => void;
interface DefaultContainerProps<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
children?: React.JSX.Element[];
allContents: (ContentItem<F, Q> | FormManagerConfig<F> | Submit<F>)[];
handleRefresh?: () => Promise<void>;
hasQueries: boolean;
viewSettings?: ViewSettings;
pageId?: string;
}
interface PageConfigProps {
HeaderContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: Omit<DefaultContainerProps<F, Q>, "viewSettings"> & ViewSettings["header"]) => React.ReactNode;
FooterContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: Omit<DefaultContainerProps<F, Q>, "viewSettings"> & ViewSettings["footer"]) => React.ReactNode;
BodyContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: DefaultContainerProps<F, Q>) => React.ReactNode;
authPageImage: string;
authPageProps: PageProps;
isLogged: (val: AuthState | null) => boolean;
ItemsContainer: (props: {
children: React.ReactNode;
}) => React.ReactNode;
LoaderComponent?: (props: {
loading?: boolean;
message?: string;
ns?: string;
}) => React.ReactNode;
PageContainer: (props: {
children: React.ReactNode;
id: string;
}) => React.ReactNode;
meta?: {
title?: string;
description?: string;
};
defaultMetadata: MetadataConfig;
setMetadata: (config: MetadataConfig) => void;
getMetadata: () => MetadataConfig;
resetMetadata: () => void;
lazyLoading: LazyLoadingConfig;
}
declare function getPageConfig(): PageConfigProps;
declare const pageConfig: PageConfigProps;
declare const setPageConfig: (config: Partial<PageConfigProps>) => void;
type MappedProps<F extends FieldValues, Q extends QueriesArray> = {
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
formValues: F;
setValue: UseFormSetValue<F>;
};
type MappedItemsFunction<F extends FieldValues, Q extends QueriesArray, ComponentType> = (props: MappedProps<F, Q>) => ComponentType;
/**
* Context passed to lifecycle callbacks
* Provides access to form, queries, mutations, and utilities
*/
type LifecycleContext$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = MappedProps<F, Q> & {
ns?: string;
pageId?: string;
pageConfig?: PageProps<F, Q>;
};
type Items<F extends FieldValues, Q extends QueriesArray> = {
type: "custom";
component: React.JSX.Element | ((props: MappedProps<F, Q>) => React.JSX.Element);
index?: number;
usedBoxes?: number;
renderInFooter?: boolean;
renderInHeader?: boolean;
hidden?: boolean;
usedQueries?: Array<Q[number]["key"]>;
usedFormValues?: Array<keyof F>;
isDraggable?: boolean;
isInDraggableView?: boolean;
key?: string;
lazy?: boolean;
lazyTrigger?: "viewport" | "interaction" | "conditional";
lazyCondition?: MappedItemsFunction<F, Q, boolean>;
};
type ContainerItem<F extends FieldValues, Q extends QueriesArray> = {
type: "container";
component?: typeof pageConfig.ItemsContainer;
items: ContentItemsType<F, Q>;
index?: number;
usedBoxes?: number;
renderInFooter?: boolean;
renderInHeader?: boolean;
hidden?: boolean;
usedQueries?: Array<Q[number]["key"]>;
usedFormValues?: Array<keyof F>;
isDraggable?: boolean;
isInDraggableView?: boolean;
key?: string;
lazy?: boolean;
lazyTrigger?: "viewport" | "interaction" | "conditional";
lazyCondition?: MappedItemsFunction<F, Q, boolean>;
};
type ContentItem<F extends FieldValues, Q extends QueriesArray> = Items<F, Q> | ContainerItem<F, Q>;
type MappedContents<F extends FieldValues, Q extends QueriesArray> = MappedItemsFunction<F, Q, ContentItem<F, Q>[]>;
type ContentItemsType<F extends FieldValues, Q extends QueriesArray = QueriesArray> = ContentItem<F, Q>[] | MappedContents<F, Q>;
type FormPageProps<F extends FieldValues, Q extends QueriesArray> = Omit<ComponentProps<typeof FormManager<F>>, "updateFormValues" | "submit" | "data"> & {
defaultValueQueryKey?: string[];
defaultValueQueryMap?: (props: ExtractQuery<Q>["response"]) => DefaultValues<F>;
submit?: Array<Submit<F>> | MappedItemsFunction<F, Q, Array<Submit<F>>>;
index?: number;
usedQueries?: Array<Q[number]["key"]>;
data?: Array<FormManagerConfig<F> | MappedItemsFunction<F, Q, FormManagerConfig<F>>>;
debounceDelay?: number;
};
type MappedQueryProps<F extends FieldValues, Q extends QueriesArray> = Omit<MappedProps<F, Q>, "allMutation" | "allQuery">;
type SingleQueryConfig<F extends FieldValues, Q extends QueryDefinition<any, any, any, any, any>> = Q extends QueryDefinition<infer K, infer T, infer P, infer R, infer C> ? T extends "mutation" ? {
type: "mutation";
mutationConfig: ((props: MappedQueryProps<F, Q[]>) => MutationConfig<P, R, C>) | MutationConfig<P, R, C>;
key: K;
} : {
type: "query";
queryConfig?: ((props: MappedQueryProps<F, Q[]>) => Omit<QueryProps<K, R>, "keyToMap">) | Omit<QueryProps<K, R>, "keyToMap">;
key: K;
} : never;
type QueryPageConfigArray<F extends FieldValues, Q extends QueriesArray> = {
[I in keyof Q]: SingleQueryConfig<F, QueryAtIndex<Q, I>>;
};
interface PageProps<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
id: string;
ns?: string;
contents?: ContentItemsType<F, Q>;
queries?: QueryPageConfigArray<F, Q>;
form?: FormPageProps<F, Q>;
viewSettings?: MappedItemsFunction<F, Q, ViewSettings> | ViewSettings;
meta?: MetadataConfig<F, Q>;
lazyLoading?: LazyLoadingConfig;
platformOverrides?: PlatformOverrides<F, Q>;
onValuesChange?: MappedItemsFunction<F, Q, void>;
lifecycleCallbacks?: {
onMountComplete?: (context: LifecycleContext$1<F, Q>) => void | Promise<void>;
onQuerySuccess?: (context: LifecycleContext$1<F, Q>, queryKey: string, data: unknown) => void | Promise<void>;
onQueryError?: (context: LifecycleContext$1<F, Q>, queryKey: string, error: Error) => void | Promise<void>;
onFormSubmit?: (context: LifecycleContext$1<F, Q>, result: unknown) => void | Promise<void>;
onValuesChange?: MappedItemsFunction<F, Q, void>;
};
customConfig?: Record<string, unknown>;
enableAuthControl?: boolean;
}
/**
* Platform-specific configuration overrides (proper type with PageProps reference)
* Allows different behavior on web vs React Native
*/
type PlatformOverrides<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = {
/** Web-specific overrides (React DOM) */
web?: Partial<PageProps<F, Q>>;
/** React Native-specific overrides */
native?: Partial<PageProps<F, Q>>;
};
type ViewSettings = {
withoutPadding?: boolean;
header?: {
withoutPadding?: boolean;
};
footer?: {
withoutPadding?: boolean;
};
disableRefreshing?: boolean;
customLayoutComponent?: typeof pageConfig.BodyContainer;
customPageContainer?: typeof pageConfig.PageContainer;
};
type UsePageConfigReturn = {
formControl: any;
formValues: any;
};
/**
* Dependency Graph Node
* Tracks which queries, form values, and mutations a component depends on
*/
interface DependencyNode {
componentId: string;
usedQueries: string[];
usedFormValues: string[];
usedMutations: string[];
parentComponent: string | null;
childComponents: string[];
}
/**
* Dependency Graph
* Maps component IDs to their dependency nodes for selective re-rendering
*/
interface DependencyGraph {
nodes: Map<string, DependencyNode>;
addNode: (node: DependencyNode) => void;
getNode: (componentId: string) => DependencyNode | undefined;
getAffectedComponents: (changedKeys: string[]) => string[];
}
/**
* Memoization Cache Types
* For tracking memoized computations and their cache hits
*/
interface MemoizationCacheStats {
hits: number;
misses: number;
size: number;
maxSize: number;
}
interface UseDataExtractorProps<F extends FieldValues, Q extends QueriesArray> {
formValues: F;
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
}
declare function useDataExtractor<F extends FieldValues, Q extends QueriesArray>({ allQuery, allMutation, formValues }: UseDataExtractorProps<F, Q>): {
extractQuery: (usedKeys: Array<keyof MultipleQueryResponse<Q>>) => MultipleQueryResponse<Q>;
extractMutations: (usedKeys: Array<keyof AllMutation<Q>>) => AllMutation<Q>;
extractFormValues: (usedKeys: Array<keyof F>) => F;
clearCache: () => void;
cacheRefs: {
queryCacheRef: react.MutableRefObject<ExtractorCache<Partial<MultipleQueryResponse<Q>>>>;
mutationCacheRef: react.MutableRefObject<ExtractorCache<Partial<AllMutation<Q>>>>;
formValuesCacheRef: react.MutableRefObject<ExtractorCache<Partial<F>>>;
};
};
declare const useFormPage: <F extends FieldValues, Q extends QueriesArray>({ form, }: {
form?: FormPageProps<F, Q>;
}) => {
formValues: F;
rawFormValues: F;
formControl: react_hook_form.UseFormReturn<F, any, F>;
setValue: (name: Path<F>, value: any, options?: Parameters<react_hook_form.UseFormSetValue<F>>[2]) => Promise<void>;
};
/**
* Metadata Configuration Types
* Custom metadata system replacing react-helmet-async
* Platform-agnostic: works on web, React Native, and SSR
*/
/**
* Context passed to dynamic metadata evaluator functions
* Provides access to form values, queries, and page state
*/
interface MetadataEvaluatorContext$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Current form values */
formValues?: Partial<F>;
/** All query results mapped by key */
allQuery?: Record<string, any>;
/** All mutations mapped by key */
allMutation?: Record<string, any>;
/** Namespace for i18n */
ns?: string;
/** Page ID */
pageId?: string;
/** Page config */
pageConfig?: PageProps$1<F, Q>;
}
interface MetaTag$1 {
/** For <meta name="..." content="..." /> */
name?: string;
/** For <meta property="og:..." content="..." /> */
property?: string;
/** For <meta http-equiv="..." content="..." /> */
httpEquiv?: string;
/** Meta tag content */
content: string;
/** Unique identifier for updating existing tags */
id?: string;
}
/**
* Open Graph Configuration (Facebook, LinkedIn, Twitter/X)
*/
interface OpenGraphConfig$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
type?: "website" | "article" | "product" | "profile";
title?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
description?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** URL to preview image (must be absolute) */
image?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** Canonical URL */
url?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
siteName?: string;
/** Locale (e.g., "en_US", "it_IT") */
locale?: string;
}
/**
* Structured Data Configuration (schema.org JSON-LD)
*/
interface StructuredDataConfig$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
type: "Article" | "Product" | "WebPage" | "FAQPage" | "Organization" | "Person";
schema: Record<string, unknown> | ((context: MetadataEvaluatorContext$1<F, Q>) => Record<string, unknown>);
}
/**
* AI Crawler Hints (for AI search engines and LLMs)
*/
interface AIHintsConfig$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Content classification (e.g., "documentation", "tutorial", "reference") */
contentClassification?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** Hints for AI models (e.g., ["code-heavy", "technical"]) */
modelHints?: string[] | ((context: MetadataEvaluatorContext$1<F, Q>) => string[]);
/** Additional context for AI understanding */
contextualInfo?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** Exclude this page from AI crawler indexing */
excludeFromIndexing?: boolean;
}
/**
* Robots Configuration (indexing directives)
*/
interface RobotsConfig$1 {
/** Prevent indexing */
noindex?: boolean;
/** Don't follow links */
nofollow?: boolean;
/** Don't cache page */
noarchive?: boolean;
/** Don't show snippets in search results */
nosnippet?: boolean;
/** Image preview size in search results */
maxImagePreview?: "none" | "standard" | "large";
/** Max snippet length in search results */
maxSnippet?: number;
}
/**
* Complete Metadata Configuration (Generic over F and Q for dynamic metadata)
*/
interface MetadataConfig$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Page title - sets document.title on web */
title?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** Page description meta tag */
description?: string | ((context: MetadataEvaluatorContext$1<F, Q>) => string);
/** HTML lang attribute (e.g., "en", "it") */
documentLang?: string;
/** Keywords for SEO */
keywords?: string[] | ((context: MetadataEvaluatorContext$1<F, Q>) => string[]);
openGraph?: OpenGraphConfig$1<F, Q>;
structuredData?: StructuredDataConfig$1<F, Q>;
aiHints?: AIHintsConfig$1<F, Q>;
robots?: RobotsConfig$1;
customMeta?: MetaTag$1[] | ((context: MetadataEvaluatorContext$1<F, Q>) => MetaTag$1[]);
otherMetaTags?: MetaTag$1[] | ((context: MetadataEvaluatorContext$1<F, Q>) => MetaTag$1[]);
disableIndexing?: boolean;
/** @deprecated Use openGraph.image instead */
ogImage?: string;
/** @deprecated Use openGraph.title instead */
ogTitle?: string;
/** @deprecated Use openGraph.url instead */
canonical?: string;
/** @deprecated Use documentLang instead */
lang?: string;
/** Author meta tag */
author?: string;
/** Viewport meta tag (defaults to "width=device-width, initial-scale=1") */
viewport?: string;
/** Theme color for browser UI */
themeColor?: string;
}
/**
* Configuration for lazy loading and code splitting behavior
* Enables deferred component loading to reduce initial bundle size
*/
interface LazyLoadingConfig$1 {
/** Enable lazy loading (default: true) */
enabled?: boolean;
/** Preload on hover for interactive elements (default: false) */
preloadOnHover?: boolean;
/** Preload on focus for keyboard navigation (default: false) */
preloadOnFocus?: boolean;
/** Preload after render with delay (in ms, default: undefined - no delay) */
preloadAfterRender?: number;
/** Fallback component to show while loading (default: null) */
suspenseFallback?: React.ReactNode;
/** Custom error boundary component for lazy-loaded modules */
errorBoundary?: React.ComponentType<{
error: Error;
retry: () => void;
}>;
/** Maximum time to wait before showing error state (in ms, default: 30000) */
timeout?: number;
/** Log performance metrics for lazy loading (development only) */
logMetrics?: boolean;
/** IntersectionObserver threshold (0-1, default: 0.1) - alias for intersectionThreshold */
threshold?: number | number[];
/** IntersectionObserver threshold (0-1, default: 0.1) */
intersectionThreshold?: number | number[];
/** IntersectionObserver root margin (default: "100px") - alias for intersectionRootMargin */
rootMargin?: string;
/** IntersectionObserver root margin (default: "100px") */
intersectionRootMargin?: string;
/** Trigger type for lazy loading: viewport (IntersectionObserver), interaction (manual), or conditional (based on function) */
trigger?: "viewport" | "interaction" | "conditional";
/** Conditional function to determine if content should load (for trigger: "conditional") */
condition?: (context: MetadataEvaluatorContext$1) => boolean;
/** Placeholder component to show before lazy content loads */
placeholder?: React.ReactNode;
}
interface DefaultContainerProps$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
children?: React.JSX.Element[];
allContents: (ContentItem$1<F, Q> | FormManagerConfig<F> | Submit<F>)[];
handleRefresh?: () => Promise<void>;
hasQueries: boolean;
viewSettings?: ViewSettings$1;
pageId?: string;
}
interface PageConfigProps$1 {
HeaderContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: Omit<DefaultContainerProps$1<F, Q>, "viewSettings"> & ViewSettings$1["header"]) => React.ReactNode;
FooterContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: Omit<DefaultContainerProps$1<F, Q>, "viewSettings"> & ViewSettings$1["footer"]) => React.ReactNode;
BodyContainer: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: DefaultContainerProps$1<F, Q>) => React.ReactNode;
authPageImage: string;
authPageProps: PageProps$1;
isLogged: (val: AuthState | null) => boolean;
ItemsContainer: (props: {
children: React.ReactNode;
}) => React.ReactNode;
LoaderComponent?: (props: {
loading?: boolean;
message?: string;
ns?: string;
}) => React.ReactNode;
PageContainer: (props: {
children: React.ReactNode;
id: string;
}) => React.ReactNode;
meta?: {
title?: string;
description?: string;
};
defaultMetadata: MetadataConfig$1;
setMetadata: (config: MetadataConfig$1) => void;
getMetadata: () => MetadataConfig$1;
resetMetadata: () => void;
lazyLoading: LazyLoadingConfig$1;
}
declare const pageConfig$1: PageConfigProps$1;
type MappedProps$1<F extends FieldValues, Q extends QueriesArray> = {
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
formValues: F;
setValue: UseFormSetValue<F>;
};
type MappedItemsFunction$1<F extends FieldValues, Q extends QueriesArray, ComponentType> = (props: MappedProps$1<F, Q>) => ComponentType;
/**
* Context passed to lifecycle callbacks
* Provides access to form, queries, mutations, and utilities
*/
type LifecycleContext$2<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = MappedProps$1<F, Q> & {
ns?: string;
pageId?: string;
pageConfig?: PageProps$1<F, Q>;
};
type Items$1<F extends FieldValues, Q extends QueriesArray> = {
type: "custom";
component: React.JSX.Element | ((props: MappedProps$1<F, Q>) => React.JSX.Element);
index?: number;
usedBoxes?: number;
renderInFooter?: boolean;
renderInHeader?: boolean;
hidden?: boolean;
usedQueries?: Array<Q[number]["key"]>;
usedFormValues?: Array<keyof F>;
isDraggable?: boolean;
isInDraggableView?: boolean;
key?: string;
lazy?: boolean;
lazyTrigger?: "viewport" | "interaction" | "conditional";
lazyCondition?: MappedItemsFunction$1<F, Q, boolean>;
};
type ContainerItem$1<F extends FieldValues, Q extends QueriesArray> = {
type: "container";
component?: typeof pageConfig$1.ItemsContainer;
items: ContentItemsType$1<F, Q>;
index?: number;
usedBoxes?: number;
renderInFooter?: boolean;
renderInHeader?: boolean;
hidden?: boolean;
usedQueries?: Array<Q[number]["key"]>;
usedFormValues?: Array<keyof F>;
isDraggable?: boolean;
isInDraggableView?: boolean;
key?: string;
lazy?: boolean;
lazyTrigger?: "viewport" | "interaction" | "conditional";
lazyCondition?: MappedItemsFunction$1<F, Q, boolean>;
};
type ContentItem$1<F extends FieldValues, Q extends QueriesArray> = Items$1<F, Q> | ContainerItem$1<F, Q>;
type MappedContents$1<F extends FieldValues, Q extends QueriesArray> = MappedItemsFunction$1<F, Q, ContentItem$1<F, Q>[]>;
type ContentItemsType$1<F extends FieldValues, Q extends QueriesArray = QueriesArray> = ContentItem$1<F, Q>[] | MappedContents$1<F, Q>;
type FormPageProps$1<F extends FieldValues, Q extends QueriesArray> = Omit<ComponentProps<typeof FormManager<F>>, "updateFormValues" | "submit" | "data"> & {
defaultValueQueryKey?: string[];
defaultValueQueryMap?: (props: ExtractQuery<Q>["response"]) => DefaultValues<F>;
submit?: Array<Submit<F>> | MappedItemsFunction$1<F, Q, Array<Submit<F>>>;
index?: number;
usedQueries?: Array<Q[number]["key"]>;
data?: Array<FormManagerConfig<F> | MappedItemsFunction$1<F, Q, FormManagerConfig<F>>>;
debounceDelay?: number;
};
type MappedQueryProps$1<F extends FieldValues, Q extends QueriesArray> = Omit<MappedProps$1<F, Q>, "allMutation" | "allQuery">;
type SingleQueryConfig$1<F extends FieldValues, Q extends QueryDefinition<any, any, any, any, any>> = Q extends QueryDefinition<infer K, infer T, infer P, infer R, infer C> ? T extends "mutation" ? {
type: "mutation";
mutationConfig: ((props: MappedQueryProps$1<F, Q[]>) => MutationConfig<P, R, C>) | MutationConfig<P, R, C>;
key: K;
} : {
type: "query";
queryConfig?: ((props: MappedQueryProps$1<F, Q[]>) => Omit<QueryProps<K, R>, "keyToMap">) | Omit<QueryProps<K, R>, "keyToMap">;
key: K;
} : never;
type QueryPageConfigArray$1<F extends FieldValues, Q extends QueriesArray> = {
[I in keyof Q]: SingleQueryConfig$1<F, QueryAtIndex<Q, I>>;
};
interface PageProps$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
id: string;
ns?: string;
contents?: ContentItemsType$1<F, Q>;
queries?: QueryPageConfigArray$1<F, Q>;
form?: FormPageProps$1<F, Q>;
viewSettings?: MappedItemsFunction$1<F, Q, ViewSettings$1> | ViewSettings$1;
meta?: MetadataConfig$1<F, Q>;
lazyLoading?: LazyLoadingConfig$1;
platformOverrides?: PlatformOverrides$1<F, Q>;
onValuesChange?: MappedItemsFunction$1<F, Q, void>;
lifecycleCallbacks?: {
onMountComplete?: (context: LifecycleContext$2<F, Q>) => void | Promise<void>;
onQuerySuccess?: (context: LifecycleContext$2<F, Q>, queryKey: string, data: unknown) => void | Promise<void>;
onQueryError?: (context: LifecycleContext$2<F, Q>, queryKey: string, error: Error) => void | Promise<void>;
onFormSubmit?: (context: LifecycleContext$2<F, Q>, result: unknown) => void | Promise<void>;
onValuesChange?: MappedItemsFunction$1<F, Q, void>;
};
customConfig?: Record<string, unknown>;
enableAuthControl?: boolean;
}
/**
* Platform-specific configuration overrides (proper type with PageProps reference)
* Allows different behavior on web vs React Native
*/
type PlatformOverrides$1<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = {
/** Web-specific overrides (React DOM) */
web?: Partial<PageProps$1<F, Q>>;
/** React Native-specific overrides */
native?: Partial<PageProps$1<F, Q>>;
};
type ViewSettings$1 = {
withoutPadding?: boolean;
header?: {
withoutPadding?: boolean;
};
footer?: {
withoutPadding?: boolean;
};
disableRefreshing?: boolean;
customLayoutComponent?: typeof pageConfig$1.BodyContainer;
customPageContainer?: typeof pageConfig$1.PageContainer;
};
/**
* Lifecycle Callbacks Hook (T074)
* Provides lifecycle event definitions and management for pages
* Enables developers to respond to key lifecycle events
*
* @module hooks/useLifecycleCallbacks
*/
/**
* Context passed to lifecycle callbacks
* Contains all data and methods available during the lifecycle event
*/
interface LifecycleContext<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Form values at time of event */
formValues: F;
/** Form setValue function */
setValue: UseFormSetValue<F>;
/** All query data */
allQuery: MultipleQueryResponse<Q>;
/** All mutations */
allMutation: AllMutation<Q>;
/** Page ID */
pageId?: string;
/** Namespace for i18n */
ns?: string;
}
/**
* Lifecycle callback fired when page mount is complete and all required queries have resolved
* Useful for initializing third-party libraries, analytics, or dependent data fetches
*/
type OnMountCompleteCallback<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = (context: LifecycleContext<F, Q>) => void | Promise<void>;
/**
* Lifecycle callback fired when an individual query succeeds
* Useful for updating local state, triggering dependent operations
*/
type OnQuerySuccessCallback<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = (context: LifecycleContext<F, Q>, queryKey: string, data: any) => void | Promise<void>;
/**
* Lifecycle callback fired when a query fails
* Useful for error handling, retry logic, fallback data loading
*/
type OnQueryErrorCallback<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = (context: LifecycleContext<F, Q>, queryKey: string, error: Error) => void | Promise<void>;
/**
* Lifecycle callback fired after form submission
* Useful for post-submit validation, success messages, redirects
*/
type OnFormSubmitCallback<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = (context: LifecycleContext<F, Q>, result: any) => void | Promise<void>;
/**
* Lifecycle callback fired when form values change
* Useful for dependent calculations, validation, auto-save
* Note: Can be debounced via useFormPage configuration
*/
type OnValuesChangeCallback<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> = MappedItemsFunction<F, Q, void>;
/**
* Complete lifecycle callback configuration for a page
*/
interface LifecycleCallbacks<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
/** Fired when page mount is complete and all required queries resolve */
onMountComplete?: OnMountCompleteCallback<F, Q>;
/** Fired on individual query success (receives queryKey and data) */
onQuerySuccess?: OnQuerySuccessCallback<F, Q>;
/** Fired on query failure (receives queryKey and error) */
onQueryError?: OnQueryErrorCallback<F, Q>;
/** Fired after form submission */
onFormSubmit?: OnFormSubmitCallback<F, Q>;
/** Fired when form values change (can be debounced) */
onValuesChange?: OnValuesChangeCallback<F, Q>;
}
declare const usePageConfig: <F extends FieldValues, Q extends QueriesArray>({ queries, form, ns, onValuesChange, viewSettings, meta, lazyLoading, platformOverrides, lifecycleCallbacks, customConfig, }: {
queries: QueryPageConfigArray<F, Q>;
form?: FormPageProps<F, Q>;
ns: string;
onValuesChange?: MappedItemsFunction<F, Q, void>;
viewSettings?: MappedItemsFunction<F, Q, ViewSettings> | ViewSettings;
meta?: MetadataConfig<F, Q>;
lazyLoading?: LazyLoadingConfig;
platformOverrides?: PlatformOverrides<F, Q>;
lifecycleCallbacks?: LifecycleCallbacks<F, Q>;
customConfig?: Record<string, any>;
}) => Record<string, any>;
interface GenerateContentProps<F extends FieldValues, Q extends QueriesArray> {
pageId: string;
ns?: string;
contents: ContentItemsType<F, Q>;
pageConfig: ReturnType<typeof usePageConfig<F, Q>>;
}
declare const useGenerateContent: <F extends FieldValues, Q extends QueriesArray>({ pageId, ns, contents, pageConfig, }: GenerateContentProps<F, Q>) => {
header: JSX.Element[];
body: JSX.Element[];
footer: JSX.Element[];
allContents: (ContentItem$1<F, Q> | _gaddario98_react_form.FormManagerConfig<F> | _gaddario98_react_form.Submit<F, _gaddario98_react_form.SubmitKeysArg<F>>)[];
};
interface GenerateContentRenderProps<F extends FieldValues, Q extends QueriesArray> {
contents?: ContentItemsType<F, Q>;
ns?: string;
pageId: string;
formValues: F;
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
isAllQueryMapped?: boolean;
formData: false | {
elements: FormElements[];
formContents: (FormManagerConfig<F> | Submit<F>)[];
};
setValue: UseFormSetValue<F>;
renderComponent: (props: {
content: ContentItem<F, Q>;
ns: string;
formValues: F;
pageId: string;
allMutation: AllMutation<Q>;
allQuery: MultipleQueryResponse<Q>;
setValue: UseFormSetValue<F>;
key: string;
}) => JSX.Element;
}
interface Elements {
index: number;
element: JSX.Element;
renderInFooter: boolean;
renderInHeader: boolean;
key: string;
}
declare const useGenerateContentRender: <F extends FieldValues, Q extends QueriesArray>({ pageId, ns, contents, allMutation, allQuery, formValues, isAllQueryMapped, formData, setValue, renderComponent, }: GenerateContentRenderProps<F, Q>) => {
components: {
element: JSX.Element;
index: number;
renderInFooter: boolean;
renderInHeader: boolean;
key: string;
}[];
allContents: (ContentItem<F, Q> | FormManagerConfig<F> | Submit<F, _gaddario98_react_form.SubmitKeysArg<F>>)[];
getAffectedComponents: (changedKeys: string[]) => string[];
};
declare const usePageUtiles: () => {
getContentProps: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: ContentItem<F, Q>) => ContentItem<F, Q>;
getContentItems: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>(props: ContentItem<F, Q>[]) => ContentItem<F, Q>[];
};
/**
* Specialized hook for managing queries and mutations
* Handles query processing, loading states, and key mapping
* Enhanced in 2.0: Uses useMemoizedProps for stable query/mutation references
* @param queries - Array of query configurations
* @param formValues - Current form values
* @param setValue - Form setValue function
* @returns Query management state and utilities with stable references
*/
declare function usePageQueries<F extends FieldValues, Q extends QueriesArray>({ queries, formValues, setValue, }: {
queries: QueryPageConfigArray<F, Q>;
formValues: F;
setValue: any;
}): {
allMutation: _gaddario98_react_queries.AllMutation<Q>;
allQuery: _gaddario98_react_queries.MultipleQueryResponse<Q>;
isAllQueryMapped: boolean;
isLoading: boolean;
queryKeys: (string[] | undefined)[];
hasQueries: boolean;
queriesKeys: string[];
};
/**
* Specialized hook for managing view settings
* Optimized to prevent unnecessary re-renders
* @param viewSettings - View settings configuration (static or function)
* @param allQuery - All query results
* @param allMutation - All mutation handlers
* @param formValues - Current form values
* @param setValue - Form setValue function
* @returns Processed view settings
*/
declare function useViewSettings<F extends FieldValues, Q extends QueriesArray>({ viewSettings, allQuery, allMutation, formValues, setValue, }: {
viewSettings?: MappedItemsFunction<F, Q, ViewSettings> | ViewSettings;
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
formValues: F;
setValue: any;
}): ViewSettings;
/**
* Specialized hook for managing form data processing
* Uses optimized caches to prevent unnecessary re-renders
* @param form - Form configuration
* @param isAllQueryMapped - Whether all queries are mapped
* @param formValues - Current form values
* @param extractMutationsHandle - Extracted mutations
* @param extractQueryHandle - Extracted queries
* @param setValue - Form setValue function
* @returns Processed form data and submit handlers
*/
declare function useFormData<F extends FieldValues, Q extends QueriesArray>({ form, isAllQueryMapped, formValues, extractMutationsHandle, extractQueryHandle, setValue, }: {
form?: FormPageProps<F, Q>;
isAllQueryMapped: boolean;
formValues: F;
extractMutationsHandle: AllMutation<Q>;
extractQueryHandle: MultipleQueryResponse<Q>;
setValue: any;
}): {
mappedFormData: FormManagerConfig<F>[];
formSubmit: Submit<F, _gaddario98_react_form.SubmitKeysArg<F>>[];
};
/**
* Main page generator component that orchestrates page rendering
* Handles authentication, content generation, and layout management
* @param enableAuthControl - Whether to enable authentication control
* @param meta - Page metadata configuration
* @param props - Additional page properties
*/
declare const PageGenerator: <F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray>({ enableAuthControl, meta, ...props }: PageProps<F, Q>) => react_jsx_runtime.JSX.Element;
interface Props<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
content: ContentItem<F, Q>;
ns: string;
formValues: F;
pageId: string;
allQuery: MultipleQueryResponse<Q>;
allMutation: AllMutation<Q>;
setValue: UseFormSetValue<F>;
}
interface ContentProps<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> extends Omit<Props<F, Q>, "content"> {
content: Items<F, Q>;
}
interface ItemContainerProps<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> extends Omit<Props<F, Q>, "content"> {
content: ContainerItem<F, Q>;
}
interface ContentListProps<F extends FieldValues = FieldValues, Q extends QueriesArray = QueriesArray> {
contents: Required<PageProps<F, Q>>["contents"];
ns?: PageProps<F, Q>["ns"];
queries: Required<PageProps<F, Q>>["queries"];
prefix?: string;
form?: PageProps<F, Q>["form"];
pageId: string;
}
/**
* Optimized shallow equality check for objects and functions
* @param objA - First object to compare
* @param objB - Second object to compare
* @returns True if objects are shallow equal
*/
declare function shallowEqual(objA: any, objB: any): boolean;
/**
* Checks if a value is stable for React dependency arrays
* @param value - Value to check for stability
* @returns True if value is considered stable
*/
declare function isStableValue(value: any): boolean;
/**
* Creates an optimized dependency array by filtering unstable values
* @param deps - Array of dependencies to optimize
* @returns Filtered array of stable dependencies
*/
declare function optimizeDeps(deps: any[]): any[];
/**
* Custom prop comparator for React.memo() to prevent unnecessary re-renders
* Compares props shallowly and ignores function references if they have the same name
* @param prevProps - Previous component props
* @param nextProps - Next component props
* @returns True if props are equal (component should NOT re-render)
*/
declare function memoPropsComparator<P extends Record<string, any>>(prevProps: Readonly<P>, nextProps: Readonly<P>): boolean;
/**
* Deep equality check for complex objects
* Use sparingly - prefer shallow equality for performance
* Uses fast-deep-equal library for optimized deep comparison with circular reference protection
* @param objA - First object
* @param objB - Second object
* @returns True if objects are deeply equal
*/
declare function deepEqual(objA: any, objB: any): boolean;
/**
* Memoization cache for expensive computations
* Simple LRU cache with configurable size
*/
declare class MemoizationCache<K, V> {
private cache;
private maxSize;
constructor(maxSize?: number);
get(key: K): V | undefined;
set(key: K, value: V): void;
has(key: K): boolean;
clear(): void;
}
/**
* Creates a memoized function with custom cache key generator
* @param fn - Function to memoize
* @param cacheKeyFn - Optional function to generate cache key from arguments
* @returns Memoized function
*/
declare function memoize<Args extends any[], Result>(fn: (...args: Args) => Result, cacheKeyFn?: (...args: Args) => string): (...args: Args) => Result;
/**
* Configuration Merge Utility (T084)
* Provides deep merging of configuration objects with proper precedence
* Handles arrays, objects, and primitives correctly
*
* @module utils/merge
*/
/**
* Options for controlling merge behavior
*/
interface MergeOptions {
/** If true, arrays are concatenated instead of replaced (default: false) */
concatArrays?: boolean;
/** If true, null/undefined values overwrite existing values (default: false) */
overwriteWithEmpty?: boolean;
/** Maximum depth for recursion to prevent infinite loops (default: 10) */
maxDepth?: number;
/** Keys to skip during merge */
skipKeys?: Set<string>;
}
/**
* Deep merge of multiple objects with precedence from left to right
* Later objects override earlier ones, with special handling for nested objects
*
* @param objects - Objects to merge (left to right precedence)
* @param options - Merge options
* @returns Merged object
*
* @example
* ```typescript
* const defaults = { theme: 'light', nested: { color: 'black' } };
* const overrides = { theme: 'dark', nested: { fontSize: 14 } };
* const result = deepMerge(defaults, overrides);
* // Result: { theme: 'dark', nested: { color: 'black', fontSize: 14 } }
* ```
*/
declare function deepMerge<T extends Record<string, any>>(...objects: (T | undefined | null)[]): T;
/**
* Deep merge with custom options
* @param target - Target object to merge into
* @param sources - Source objects to merge
* @param options - Merge options
* @returns Merged object
*/
declare function deepMergeWithOptions<T extends Record<string, any>>(target: T, sources: T[], options?: MergeOptions): T;
/**
* Shallow merge of objects (only top-level keys)
* @param objects - Objects to merge
* @returns Merged object
*/
declare function shallowMerge<T extends Record<string, any>>(...objects: (T | undefined | null)[]): T;
/**
* Merge arrays of objects by a key (useful for config arrays)
* @param baseArray - Base array
* @param overrideArray - Array to merge in
* @param keyName - Key to match on
* @returns Merged array
*
* @example
* ```typescript
* const base = [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }];
* const override = [{ id: 'a', name: 'Alicia' }, { id: 'c', name: 'Charlie' }];
* const result = mergeArraysByKey(base, override, 'id');
* // Result: [{ id: 'a', name: 'Alicia' }, { id: 'b', name: 'Bob' }, { id: 'c', name: 'Charlie' }]
* ```
*/
declare function mergeArraysByKey<T extends Record<string, any>>(baseArray: T[], overrideArray: T[], keyName: string): T[];
/**
* Check if two objects are deeply equal
* Useful for detecting if a merge actually changed anything
* Note: Use the fast-deep-equal version from optimization.ts instead
* @deprecated - Use deepEqual from utils/optimization.ts instead
* @param obj1 - First object
* @param obj2 - Second object
* @returns True if objects are deeply equal
*/
declare function deepEqualFallback(obj1: any, obj2: any): boolean;
/**
* Stable Cache for memoizing objects across renders
* Prevents unnecessary object creation in hooks
*
* @example
* ```typescript
* const cache = useRef(new StableCache<FormConfig>());
* const formConfig = cache.current.getOrSet('key', () => createConfig());
* ```
*/
declare class StableCache<T> {
private cache;
/**
* Get value from cache, or set it if not present
* @param key - Cache key
* @param factory - Function to create value if not cached
* @returns Cached or newly created value
*/
getOrSet(key: string, factory: () => T): T;
/**
* Get value from cache
* @param key - Cache key
* @returns Cached value or undefined
*/
get(key: string): T | undefined;
/**
* Set value in cache
* @param key - Cache key
* @param value - Value to cache
*/
set(key: string, value: T): void;
/**
* Check if key exists in cache
* @param key - Cache key
* @returns True if key exists
*/
has(key: string): boolean;
/**
* Clear all cached values
*/
clear(): void;
/**
* Get cache size
* @returns Number of cached items
*/
size(): number;
}
/**
* Configuration for lazy loading behavior
*/
interface LazyLoadConfig {
/** Whether to enable lazy loading (default: true) */
enabled?: boolean;
/** Preload on hover (only for interactive elements