UNPKG

@layr/react-integration

Version:
213 lines (212 loc) 9.25 kB
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; }