import React, { forwardRef, ElementRef, ComponentProps, ReactNode, Fragment, useRef, useState, useEffect, } from 'react' import { styled } from '~/theme' import { Text, Button, ScrollArea } from '~/components' import { useDialog } from './useDialog' import { useHotkeys } from '~/hooks' const Container = styled('div', { width: 632, // 520 maxHeight: 'calc(100vh - 30px)', display: 'flex', flexDirection: 'column', borderRadius: 4, boxShadow: '0px 8px 20px rgba(0, 0, 0, 0.12)', backgroundColor: '$Background2dp', variants: { mode: { dialog: { width: 520, }, }, }, }) const ScrollBody = styled('div', { paddingTop: '$$dialogPadding', paddingLeft: '$$dialogPadding', paddingRight: '$$dialogPadding', width: '100%', '&>:last-child': { paddingBottom: 24, }, }) const StyledButtons = styled('div', { position: 'sticky', bottom: 0, display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingTop: '$$dialogPadding', backgroundColor: '$Background2dp', paddingBottom: '$$dialogPadding', }) const ButtonsWithBorder = styled(StyledButtons, { borderTop: '1px solid $OtherDivider', marginTop: 48, paddingTop: 20, paddingLeft: 24, paddingRight: 24, marginLeft: 'calc(-1 * $$dialogPadding)', marginRight: 'calc(-1 * $$dialogPadding)', }) const ButtonSpacer = styled('div', { width: 16, }) const BodySpacer = styled('div', { height: 24, '&:first-child': { display: 'none', }, }) const Title = (props) => { return } const Body = ({ children }) => { if (typeof children === 'string') { return {children} } else if (Array.isArray(children)) { return ( <> {children.map((child, index) => ( {child} ))} ) } else { return ( <> {children} ) } } const Buttons = ({ children, border = null }) => { if (Array.isArray(children)) { children = children.map((child, index) => { return index ? ( {child} ) : ( child ) }) } return border ? ( {children} ) : ( {children} ) } const Confirm = ({ children = 'OK', onConfirm = () => {}, ...props }) => { const dialog = useDialog() const { current: myId } = useRef(dialog._id) const onClick = onConfirm ? async () => { if (!props.disabled && myId === dialog._id) { await onConfirm() dialog.close(myId) } } : () => { if (!props.disabled && myId === dialog._id) { dialog.close(myId) } } useHotkeys([['enter', onClick]]) return ( ) } const Cancel = ({ children = 'Cancel', onCancel = null, ...props }) => { const dialog = useDialog() const { current: myId } = useRef(dialog._id) const onClick = onCancel ? async () => { if (!props.disabled && myId === dialog._id) { await onCancel() dialog.close(myId) } } : () => { if (!props.disabled && myId === dialog._id) { dialog.close(myId) } } useHotkeys([['escape', onClick]]) return ( ) } export interface DialogProps extends ComponentProps { children?: ReactNode title?: string padding?: number } export const Dialog = Object.assign( forwardRef, DialogProps>( ({ children, title, padding = 24, style, ...props }, forwardedRef) => { if (typeof children === 'string') { if (!title) { title = children children = null } else { children = {children} } } const [go, setgo] = useState(false) useEffect(() => { const x = requestAnimationFrame(() => { setgo(true) }) return () => { cancelAnimationFrame(x) } }, []) return ( {title} {children} ) } ), { Title, Body, Buttons, Confirm, Cancel, } ) Dialog.displayName = 'Dialog'