@vyuh/react-extension-content
Version:
Content extension for the Vyuh Framework
375 lines (363 loc) • 11.7 kB
TypeScript
import * as react_jsx_runtime from 'react/jsx-runtime';
import { ContentItem, TypeDescriptor, LayoutConfiguration, SchemaItem, ExtensionDescriptor, ActionConfiguration, ConditionConfiguration, ContentModifierConfiguration, ExtensionBuilder, ItemType, ContentPlugin, ContentProvider } from '@vyuh/react-core';
import React, { ReactNode, Component, ErrorInfo } from 'react';
import { Observable } from 'rxjs';
/**
* Props for the DocumentLoader component
*/
interface DocumentLoaderProps<TContent extends ContentItem> {
/**
* Function to fetch content
* Returns either a Promise (one-time loading) or Observable (live updates)
*/
fetchContent: () => Promise<TContent | TContent[] | undefined> | Observable<TContent | TContent[] | undefined>;
/**
* Custom render function for the content
* If not provided, uses the content plugin's render method
*/
renderContent?: (content: TContent | TContent[] | undefined) => React.ReactNode;
/**
* Whether to allow refreshing the document
*/
allowRefresh?: boolean;
/**
* Error title to display when content fetching fails
*/
errorTitle?: string;
}
/**
* Component that loads and renders a document from the content provider
*/
declare function DocumentLoader<TContent extends ContentItem>({ fetchContent, renderContent: customRenderContent, allowRefresh, errorTitle, }: DocumentLoaderProps<TContent>): react_jsx_runtime.JSX.Element;
/**
* Creates a fetch function for fetching content by query
*/
declare function fetchSingleWithQuery<TContent extends ContentItem>(query: string, options?: {
params?: Record<string, any>;
live?: boolean;
}): () => any;
/**
* Creates a fetch function for fetching content by query
*/
declare function fetchMultipleWithQuery<TContent extends ContentItem>(query: string, options?: {
params?: Record<string, any>;
live?: boolean;
}): () => any;
/**
* Creates a fetch function for fetching content by ID
*/
declare function fetchWithId<TContent extends ContentItem>(documentId: string, options?: {
live?: boolean;
}): () => any;
/**
* Props for the RouteLoader component
*/
interface RouteLoaderProps {
/**
* The URL to fetch the route for
*/
url?: string;
/**
* The route ID to fetch the route for
*/
routeId?: string;
/**
* Whether to allow refreshing the route
*/
allowRefresh?: boolean;
/**
* Whether to use live updates (observable-based) instead of one-time loading
*/
live?: boolean;
}
/**
* A component that loads and renders a route from a URL or route ID
*/
declare function RouteLoader({ url, routeId, allowRefresh, live, }: RouteLoaderProps): react_jsx_runtime.JSX.Element;
/**
* Props for AsyncContentContainer
*/
interface AsyncContentContainerProps<T> {
/**
* Async function that loads the content
* Can return either a Promise or an Observable
*/
fetchContent: () => Promise<T | T[] | undefined> | Observable<T | T[] | undefined>;
/**
* Function to render the loaded content
*/
renderContent: (content: T | T[] | undefined) => React.ReactNode;
/**
* Error title to display when loading fails
*/
errorTitle?: string;
/**
* Callback function to invoke when retrying after an error
*/
onRetry?: () => void;
}
/**
* Generic component for loading and rendering async content with error handling
*/
declare function AsyncContentContainer<T>({ fetchContent, renderContent, errorTitle, onRetry, }: AsyncContentContainerProps<T>): React.ReactNode;
/**
* Descriptor for content types in the Vyuh system.
*
* Content descriptors define:
* - Metadata about a content type (schema type, title)
* - Available layouts for a content type
*
* They are used by ContentBuilder to initialize content types
* with their available configurations.
*/
declare class ContentDescriptor<TContent extends ContentItem = ContentItem> {
/**
* The schema type of the content
*/
readonly schemaType: string;
/**
* The title of the content
*/
readonly title: string;
/**
* Available layouts for this content type
*/
readonly layouts?: TypeDescriptor<LayoutConfiguration<TContent>>[];
/**
* The feature that registered this content descriptor
*/
private _sourceFeature?;
/**
* Get the source feature
*/
get sourceFeature(): string | undefined;
/**
* Creates a new content descriptor
*/
constructor({ schemaType, title, layouts, }: {
schemaType: string;
title: string;
layouts?: TypeDescriptor<LayoutConfiguration<TContent>>[];
});
/**
* Set the source feature
*/
setSourceFeature(featureName?: string): void;
/**
* Creates a default content descriptor with standard conventions
*/
static createDefault<TContent extends ContentItem = ContentItem>({ schemaType, title, }: {
schemaType: string;
title: string;
}): (layouts?: TypeDescriptor<LayoutConfiguration<TContent>>[]) => ContentDescriptor<TContent>;
}
/**
* Builder for configuring and managing content types and their layouts.
*
* ContentBuilder is responsible for:
* - Managing layout configurations for content types
* - Building content widgets
*/
declare class ContentBuilder<TContent extends ContentItem = ContentItem> implements SchemaItem {
/**
* The schema type for this builder
*/
readonly schemaType: string;
/**
* The default layout for this content type
*/
private _defaultLayout;
/**
* Get the default layout
*/
get defaultLayout(): LayoutConfiguration;
private readonly _defaultLayoutDescriptor;
/**
* Get the default layout descriptor
*/
get defaultLayoutDescriptor(): TypeDescriptor<LayoutConfiguration>;
/**
* The feature that registered this content builder
*/
private _sourceFeature?;
/**
* Get the source feature
*/
get sourceFeature(): string | undefined;
/**
* Set the source feature
*/
setSourceFeature(featureName?: string): void;
/**
* Creates a new content builder
*/
constructor({ schemaType, defaultLayout, defaultLayoutDescriptor, }: {
schemaType: string;
defaultLayout: LayoutConfiguration;
defaultLayoutDescriptor: TypeDescriptor<LayoutConfiguration>;
});
/**
* Initialize this content builder with the given content descriptors
*
* This method:
* 1. Collects all available layouts from descriptors
* 2. Combines them with the default layout
* 3. Registers any additional type descriptors
*
* @param descriptors Content descriptors for this content type
*/
init(descriptors: ContentDescriptor[]): void;
getLayout(content: TContent): LayoutConfiguration | undefined;
/**
* Build a widget for the given content item
*/
render(content: TContent, layout: LayoutConfiguration | undefined): React.ReactNode;
/**
* Set the default layout for this content builder
*/
setDefaultLayout(layout: LayoutConfiguration): void;
}
/**
* Descriptor for content extensions
*/
declare class ContentExtensionDescriptor extends ExtensionDescriptor {
static readonly extensionType = "vyuh.extension.content";
readonly type: string;
/**
* Content descriptors
*/
readonly contents?: ContentDescriptor[];
/**
* Content builders
*/
readonly contentBuilders?: ContentBuilder[];
/**
* Action configurations
*/
readonly actions?: TypeDescriptor<ActionConfiguration>[];
/**
* Condition configurations
*/
readonly conditions?: TypeDescriptor<ConditionConfiguration>[];
/**
* Content modifier configurations
*/
readonly contentModifiers?: TypeDescriptor<ContentModifierConfiguration>[];
/**
* Creates a new content extension descriptor
*/
constructor(props?: Partial<ContentExtensionDescriptor>);
/**
* Set the source feature for this extension descriptor
* This is called by the FeatureDescriptor when the extension is registered
*/
setSourceFeature(featureName: string): void;
}
/**
* Builder for content extensions
*/
declare class ContentExtensionBuilder extends ExtensionBuilder {
private typeMap;
constructor();
/**
* Build the content extension
*/
build(descriptors: ExtensionDescriptor[]): void;
registerItem<T extends SchemaItem>(itemType: ItemType<T>, descriptor: TypeDescriptor<T>): void;
/**
* Get a content builder by schema type
*/
getBuilder(schemaType: string): ContentBuilder | undefined;
/**
* Get an item by its schema type
*/
getItem<T extends SchemaItem>(itemType: ItemType<T>, schemaType: string | undefined): TypeDescriptor<T> | undefined;
/**
* Find the content plugin from the Vyuh store and attach to it
*/
private findAndAttachToContentPlugin;
/**
* Collect items of a specific type from extension descriptors
*/
private collectItems;
/**
* Initialize a type map for a specific item type
*/
private initTypeMap;
}
/**
* Default implementation of ContentPlugin.
*/
declare class DefaultContentPlugin extends ContentPlugin {
private extensionBuilder?;
constructor(provider: ContentProvider);
getItem<T extends SchemaItem>(itemType: ItemType<T>, schemaType: string): TypeDescriptor<T> | undefined;
registerItem<T extends SchemaItem>(itemType: ItemType<T>, descriptor: TypeDescriptor<T>): void;
/**
* Build content from a JSON object
*/
render(json: Record<string, any> | ContentItem, options?: {
layout: LayoutConfiguration;
}): React.ReactNode;
/**
* Attach an extension builder to this plugin
*/
attach(extBuilder: ExtensionBuilder): void;
dispose(): Promise<void>;
init(): Promise<void>;
}
/**
* Error Boundary component props
*/
interface ErrorBoundaryProps {
children: ReactNode;
title: string;
onRetry?: () => void;
FallbackComponent?: React.ComponentType<{
error: Error;
onRetry?: () => void;
}>;
}
/**
* Error Boundary component state
*/
interface ErrorBoundaryState {
hasError: boolean;
error: Error | null;
}
/**
* Error Boundary component to catch and handle errors in the component tree
*/
declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps);
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
componentDidCatch(error: Error, info: ErrorInfo): void;
private invokeRetry;
render(): ReactNode;
}
/**
* Base interface for all async resources
*/
interface IAsyncResource<T> {
read(): T;
dispose(): void;
isLive(): boolean;
}
/**
* Resource for suspense-based data fetching with Promises
*/
declare class AsyncResource<T> implements IAsyncResource<T> {
private result;
private error;
private status;
private promise;
constructor(source: Promise<T>);
private handlePromise;
read(): T;
dispose(): void;
/**
* Returns whether this resource is backed by an Observable (true) or a Promise (false)
*/
isLive(): boolean;
}
export { AsyncContentContainer, type AsyncContentContainerProps, AsyncResource, ContentBuilder, ContentDescriptor, ContentExtensionBuilder, ContentExtensionDescriptor, DefaultContentPlugin, DocumentLoader, type DocumentLoaderProps, ErrorBoundary, type ErrorBoundaryProps, RouteLoader, type RouteLoaderProps, fetchMultipleWithQuery, fetchSingleWithQuery, fetchWithId };