UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

62 lines (61 loc) 2.72 kB
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { ArrowPathIcon } from "@heroicons/react/24/solid"; import { Component, createContext, use } from "react"; import { getMessage } from "../../util/error.js"; import { Card } from "../block/Card.js"; import { Subheading } from "../block/Subheading.js"; import { Button } from "../form/Button.js"; import { CenteredLayout } from "../layout/CenteredLayout.js"; import { Notice } from "../notice/Notice.js"; import { Page } from "../page/Page.js"; import { Flex } from "../style/Flex.js"; import { StatusIcon } from "./StatusIcon.js"; const RetryContext = createContext(undefined); RetryContext.displayName = "RetryContext"; const RETRY_CHILDREN = (_jsxs(_Fragment, { children: [_jsx(ArrowPathIcon, {}), "Retry"] })); export function RetryButton({ children = RETRY_CHILDREN, ...props }) { const retry = use(RetryContext); if (!retry) return null; return (_jsx(Button, { onClick: retry, ...props, children: children })); } /** * React component that provides an Error Boundary. * If an error occurs in any component under this, a general error will be shown to the user. */ export class Catcher extends Component { static defaultProps = { as: ErrorNotice, }; state = { reason: undefined, }; retry = () => { this.setState({ reason: undefined }); }; static getDerivedStateFromError(reason) { return { reason }; } render() { const { retry, state, props } = this; const { reason } = state; const { as: ErrorComponent, children } = props; if (!reason) return children; return (_jsx(RetryContext, { value: retry, children: _jsx(ErrorComponent, { reason: reason }) })); } } /** Catch errors in a page. */ export function PageCatcher({ children }) { return _jsx(Catcher, { as: ErrorPage, children: children }); } /** Output a `<Notice>` for an unknown error reason. */ export function ErrorNotice({ reason }) { const message = getMessage(reason) ?? "Unknown error"; return (_jsxs(Notice, { status: "error", children: [_jsx("p", { children: message }), _jsx(RetryButton, { small: true, fit: true })] })); } /** Output a `<Page>` with an error `<Card>` for an unknown error reason. */ export function ErrorPage({ reason }) { const message = getMessage(reason) ?? "Unknown error"; return (_jsx(Page, { title: "Error", children: _jsx(CenteredLayout, { children: _jsx(Card, { status: "error", children: _jsxs(Subheading, { children: [_jsxs(Flex, { left: true, children: [_jsx(StatusIcon, { status: "error", xlarge: true }), " ", message] }), _jsx(RetryButton, {})] }) }) }) })); }