@layr/react-integration
Version:
React integration for Layr
213 lines (212 loc) • 9.25 kB
TypeScript
import { RoutableComponent } from '@layr/routable';
import { Navigator } from '@layr/navigator';
import React from 'react';
/**
* A React component providing sensible defaults for a web app.
*
* You should use this component once at the top of your app.
*
* Note that if you use [Boostr](https://boostr.dev/) to manage your app development, this component will be automatically mounted, so you don't have to use it explicitly in your code.
*
* The main point of this component is to provide the default behavior of high-level hooks such as [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) or [`useAction()`](https://layrjs.com/docs/v2/reference/react-integration#use-action-react-hook):
*
* - `useData()` will render `null` while the `getter()` function is running, and, in the case an error is thrown, a `<div>` containing an error message will be rendered.
* - `useAction()` will prevent the user from interacting with any UI element in the browser page while the `handler()` function is running, and, in the case an error is thrown, the browser's `alert()` function will be called to display the error message.
*
* @examplelink See an example of use in the [`BrowserNavigatorView`](https://layrjs.com/docs/v2/reference/react-integration#browser-navigator-view-react-component) React component.
*
* @category React Components
* @reactcomponent
*/
export declare function BrowserRootView({ children, ...customization }: {
children: React.ReactNode;
} & Partial<Customization>): React.JSX.Element;
export declare const NavigatorContext: React.Context<Navigator | undefined>;
/**
* A React component providing a [`BrowserNavigator`](https://layrjs.com/docs/v2/reference/browser-navigator#browser-navigator-class) to your app.
*
* You should use this component once at the top of your app after the [`BrowserRootView`](https://layrjs.com/docs/v2/reference/react-integration#browser-root-view-react-component) component.
*
* Note that if you use [Boostr](https://boostr.dev/) to manage your app development, this component will be automatically mounted, so you don't have to use it explicitly in your code.
*
* @param props.rootComponent The root Layr component of your app. Note that this Layr component should be [`Routable`](https://layrjs.com/docs/v2/reference/routable#routable-component-class).
*
* @example
* ```
* // JS
*
* import React, {Fragment} from 'react';
* import ReactDOM from 'react-dom';
* import {Component} from '@layr/component';
* import {Routable} from '@layr/routable';
* import {BrowserRootView, BrowserNavigatorView, layout, page} from '@layr/react-integration';
*
* class Application extends Routable(Component) {
* // `@layout('/')` is a shortcut for `@wrapper('/') @view()`
* ﹫layout('/') static MainLayout({children}) {
* return (
* <>
* <this.HomePage.Link>
* <h1>My App</h1>
* </this.HomePage.Link>
*
* {children()} // Renders the subcomponents using this layout
* </>
* );
* }
*
* // `@page('[/]')` is a shortcut for `@route('[/]') @view()`
* ﹫page('[/]') static HomePage() {
* return <p>Hello, World!</p>;
* }
* }
*
* // Note that you don't need the following code when you use Boostr
* ReactDOM.render(
* <BrowserRootView>
* <BrowserNavigatorView rootComponent={Application} />
* </BrowserRootView>,
* // Your `index.html` page should contain `<div id="root"></div>`
* document.getElementById('root')
* );
* ```
*
* @example
* ```
* // TS
*
* import React, {Fragment} from 'react';
* import ReactDOM from 'react-dom';
* import {Component} from '@layr/component';
* import {Routable} from '@layr/routable';
* import {BrowserRootView, BrowserNavigatorView, layout, page} from '@layr/react-integration';
*
* class Application extends Routable(Component) {
* // `@layout('/')` is a shortcut for `@wrapper('/') @view()`
* ﹫layout('/') static MainLayout({children}: {children: () => any}) {
* return (
* <>
* <this.HomePage.Link>
* <h1>My App</h1>
* </this.HomePage.Link>
*
* {children()} // Renders the subcomponents using this layout
* </>
* );
* }
*
* // `@page('[/]')` is a shortcut for `@route('[/]') @view()`
* ﹫page('[/]') static HomePage() {
* return <p>Hello, World!</p>;
* }
* }
*
* // Note that you don't need the following code when you use Boostr
* ReactDOM.render(
* <BrowserRootView>
* <BrowserNavigatorView rootComponent={Application} />
* </BrowserRootView>,
* // Your `index.html` page should contain `<div id="root"></div>`
* document.getElementById('root')
* );
* ```
*
* @category React Components
* @reactcomponent
*/
export declare function BrowserNavigatorView({ rootComponent }: {
rootComponent: RoutableComponent;
}): React.JSX.Element | null;
/**
* A hook allowing you to get the [`Navigator`](https://layrjs.com/docs/v2/reference/navigator#navigator-class) used in your app.
*
* @returns A [`Navigator`](https://layrjs.com/docs/v2/reference/navigator#navigator-class) instance.
*
* @example
* ```
* import {Component} from '﹫layr/component';
* import {Routable} from '﹫layr/routable';
* import React from 'react';
* import {view, useNavigator} from '﹫layr/react-integration';
*
* import logo from '../assets/app-logo.svg';
*
* class Application extends Routable(Component) {
* // ...
*
* ﹫view() static LogoView() {
* const navigator = useNavigator();
*
* return <img src={logo} onClick={() => { navigator.navigate('/); }} />;
* }
* }
* ```
*
* @category High-Level Hooks
* @reacthook
*/
export declare function useNavigator(): Navigator;
export type Customization = {
dataPlaceholder: () => JSX.Element | null;
errorRenderer: (error: Error) => JSX.Element | null;
actionWrapper: (actionHandler: (...args: any[]) => Promise<any>, args: any[]) => Promise<any>;
errorNotifier: (error: Error) => Promise<void>;
};
export declare const CustomizationContext: React.Context<Customization | undefined>;
export declare function useCustomization(): Customization;
/**
* A React component allowing you to customize the behavior of high-level hooks such as [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) or [`useAction()`](https://layrjs.com/docs/v2/reference/react-integration#use-action-react-hook).
*
* @param [props.dataPlaceholder] A function returning a React element (or `null`) that is rendered while the `getter()` function of the [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) hook is running. A typical use case is to render a spinner.
* @param [props.errorRenderer] A function returning a React element (or `null`) that is rendered when the `getter()` function of the [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) hook throws an error. The `errorRenderer()` function receives the error as first parameter. A typical use case is to render an error message.
* @param [props.actionWrapper] An asynchronous function allowing you to wrap the `handler()` function of the [`useAction()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) hook. The `actionWrapper()` function receives the `handler()` function as first parameter, should execute it, and return its result. A typical use case is to lock the screen while the `handler()` function is running so the user cannot interact with any UI element.
* @param [props.errorNotifier] An asynchronous function that is executed when the `handler()` function of the [`useAction()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) hook throws an error. The `errorNotifier()` function receives the error as first parameter. A typical use case is to display an error alert dialog.
*
* @example
* ```
* <Customizer
* dataPlaceholder={() => {
* // Renders a custom `LoadingSpinner` component
* return <LoadingSpinner />;
* }}
* errorRenderer={(error) => {
* // Renders a custom `ErrorMessage` component
* return <ErrorMessage>{error}</ErrorMessage>;
* }}
* actionWrapper={async (actionHandler, args) => {
* // Do whatever you want here (e.g., custom screen locking)
* try {
* return await actionHandler(...args);
* } finally {
* // Do whatever you want here (e.g., custom screen unlocking)
* }
* }}
* errorNotifier={async (error) => {
* // Calls a custom `alert()` asynchronous function
* await alert(error.message);
* }}
* >
* <YourChildComponent />
* </Customizer>
* ```
*
* @category React Components
* @reactcomponent
*/
export declare function Customizer({ children, ...customization }: Partial<Customization> & {
children: React.ReactNode;
}): React.JSX.Element;
export declare class BrowserActionView extends React.Component<{
children?: React.ReactNode;
}, {
count: number;
activeElement: Element | null;
}> {
state: {
count: number;
activeElement: null;
};
open(): void;
close(): void;
render(): {} | null;
}