wuespace/telestion-client

View on GitHub
packages/telestion-client-common/src/components/dialogs/dialog.tsx

Summary

Maintainability
A
3 hrs
Test Coverage
import { useCallback, useState } from 'react';
import {
    Button,
    ButtonGroup,
    Content,
    Dialog as RSDialog,
    Divider,
    Footer,
    Heading
} from '@adobe/react-spectrum';
import { DialogConfig } from '../../hooks';
import { Entry } from './entry';

/**
 * React Props of {@link Dialog}
 *
 * For more information about React Props, please look here:
 * {@link https://reactjs.org/docs/components-and-props.html}
 *
 * @see {@link Dialog}
 * @see {@link https://reactjs.org/docs/components-and-props.html}
 */
export interface DialogProps<T> {
    /**
     * The configuration of the dialog
     * given via the {@link DialogState.show} function.
     */
    config: DialogConfig<T>;

    /**
     * A handler to confirm the opened dialog.
     * @param final - the final state which the resolved promise return
     */
    onConfirm: (final: T) => void;

    /**
     * A handler to cancel the opened dialog.
     */
    onCancel: () => void;
}

/**
 * Renders the custom dialog for the dialog context.
 *
 * @see {@link DialogContext}
 * @see {@link DialogProps}
 *
 * @example
 * ```ts
 * const dialog: Dialog = {...};
 * const { config, isOpen, onCancel, onConfirm } = dialog;
 *
 * return (
 *     <DialogContainer type="modal" onDismiss={onCancel}>
 *         {isOpen && (
 *             <Dialog config={config} onConfirm={onConfirm} onCancel={onCancel} />
 *         )}
 *     </DialogContainer>
 * );
 * ```
 */
export function Dialog<T>({ config, onConfirm, onCancel }: DialogProps<T>) {
    const [state, setState] = useState(config.initialState);

    const setPartial = useCallback<(partial: Partial<T>) => void>(
        partial => setState(prevState => ({ ...prevState, ...partial })),
        []
    );

    return (
        <RSDialog data-testid="telestionClientDialog">
            <Heading data-testid="telestionClientDialog-title">
                <Entry state={state} setPartial={setPartial}>
                    {config.title}
                </Entry>
            </Heading>
            {config.header && (
                <Content data-testid="telestionClientDialog-header">
                    <Entry state={state} setPartial={setPartial} textify>
                        {config.header}
                    </Entry>
                </Content>
            )}
            <Divider />
            <Content data-testid="telestionClientDialog-content">
                <Entry state={state} setPartial={setPartial} textify>
                    {config.content}
                </Entry>
            </Content>
            {config.footer && (
                <Footer data-testid="telestionClientDialog-footer">
                    <Entry state={state} setPartial={setPartial} textify>
                        {config.footer}
                    </Entry>
                </Footer>
            )}
            <ButtonGroup data-testid="telestionClientDialog-buttons">
                <Button
                    variant="secondary"
                    onPress={onCancel}
                    data-testid="telestionClientDialog-button--cancel"
                >
                    Cancel
                </Button>
                <Button
                    variant="cta"
                    onPress={() => onConfirm(state)}
                    data-testid="telestionClientDialog-button--confirm"
                >
                    Confirm
                </Button>
            </ButtonGroup>
        </RSDialog>
    );
}