UNPKG

@100mslive/roomkit-react

Version:

![Banner](https://github.com/100mslive/web-sdks/blob/06c65259912db6ccd8617f2ecb6fef51429251ec/prebuilt-banner.png)

286 lines (275 loc) 8.44 kB
import React, { useRef } from 'react'; import { CheckIcon, CloudUploadIcon, CrossIcon } from '@100mslive/react-icons'; import { Button } from '../../Button'; import { Checkbox } from '../../Checkbox'; import { HorizontalDivider } from '../../Divider'; import { IconButton } from '../../IconButton'; import { Input } from '../../Input'; import { Label } from '../../Label'; import { Box, Flex } from '../../Layout'; import { Dialog } from '../../Modal'; import { Select } from '../../Select'; import { Switch } from '../../Switch'; import { Text } from '../../Text'; import { flexCenter } from '../../utils'; export const DialogContent = ({ Icon, title, closeable = true, children, css, iconCSS = {}, ...props }) => { return ( <Dialog.Portal> <Dialog.Overlay /> <Dialog.Content css={{ width: 'min(600px, 100%)', ...css }} {...props}> <Dialog.Title> <Flex justify="between"> <Flex align="center" css={{ mb: '$1' }}> {Icon ? ( <Flex css={{ mr: '$2', color: '$on_primary_high', ...flexCenter, ...iconCSS }}> <Icon /> </Flex> ) : null} <Text variant="h6" inline> {title} </Text> </Flex> {closeable && <Dialog.DefaultClose data-testid="dialoge_cross_icon" />} </Flex> </Dialog.Title> <HorizontalDivider css={{ mt: '0.8rem' }} /> <Box>{children}</Box> </Dialog.Content> </Dialog.Portal> ); }; export const ErrorDialog = ({ open = true, onOpenChange, title, children, ...props }) => { return ( <Dialog.Root open={open} onOpenChange={onOpenChange}> <DialogContent Icon={CrossIcon} title={title} onInteractOutside={e => e.preventDefault()} onEscapeKeyDown={e => e.preventDefault()} onPointerDownOutside={e => e.preventDefault()} closeable={false} iconCSS={{ color: '$alert_error_default' }} {...props} > <Box css={{ mt: '$lg' }}>{children}</Box> </DialogContent> </Dialog.Root> ); }; export const RequestDialog = ({ open = true, onOpenChange, title, body, actionText = 'Accept', onAction, Icon }) => ( <Dialog.Root open={open} onOpenChange={onOpenChange}> <Dialog.Portal> <Dialog.Overlay /> <Dialog.Content css={{ width: 'min(400px,80%)', p: '$10' }}> <Dialog.Title css={{ p: 0, display: 'flex', flexDirection: 'row', gap: '$md' }}> {Icon ? Icon : null} <Text variant="h6">{title}</Text> </Dialog.Title> {typeof body === 'string' ? ( <Text variant="md" css={{ fontWeight: 400, mt: '$4', mb: '$10', c: '$on_surface_medium', }} > {body} </Text> ) : ( <Box css={{ mt: '$4', mb: '$10' }}>{body}</Box> )} <Flex justify="center" align="center" css={{ width: '100%', gap: '$md' }}> <Box css={{ width: '50%' }}> <Dialog.Close css={{ width: '100%' }}> <Button variant="standard" outlined css={{ width: '100%' }}> Cancel </Button> </Dialog.Close> </Box> <Box css={{ width: '50%' }}> <Button variant="primary" css={{ width: '100%' }} onClick={onAction}> {actionText} </Button> </Box> </Flex> </Dialog.Content> </Dialog.Portal> </Dialog.Root> ); /** * a row of items which breaks into column on small screen. For example title on left and options to select * from on right for select component. */ export const DialogRow = ({ children, breakSm = false, css, justify = 'between' }) => { let finalCSS = { margin: '$10 0', w: '100%', }; if (breakSm) { finalCSS['@sm'] = { flexDirection: 'column', alignItems: 'flex-start', }; } if (css) { finalCSS = Object.assign(finalCSS, css); } return ( <Flex align="center" justify={justify} css={finalCSS}> {children} </Flex> ); }; export const DialogCol = ({ children, breakSm = false, css, align = 'center', justify = 'between', ...props }) => { let finalCSS = { margin: '$10 0', w: '100%', }; if (breakSm) { finalCSS['@sm'] = { alignItems: 'flex-start', }; } if (css) { finalCSS = Object.assign(finalCSS, css); } return ( <Flex direction="column" align={align} justify={justify} css={finalCSS} {...props}> {children} </Flex> ); }; /** * key field and label field are optional, option is directly used if not passed */ export const DialogSelect = ({ title, options, keyField, labelField, selected, onChange, ...props }) => { return ( <DialogRow breakSm> <Label>{title}</Label> <Select.Root data-testid={`dialog_select_${title}`} css={{ width: '70%', '@sm': { width: '100%' } }} {...props}> <Select.DefaultDownIcon /> <Select.Select onChange={e => onChange(e.target.value)} value={selected} css={{ width: '100%' }}> {options.map(option => { const id = keyField ? option[keyField] : option; const label = labelField ? option[labelField] : option; return ( <option value={id} key={id}> {label} </option> ); })} </Select.Select> </Select.Root> </DialogRow> ); }; export const DialogInput = ({ title, value, onChange, placeholder, disabled, type, ...props }) => { return ( <DialogRow breakSm> <Label>{title}</Label> <Input css={{ width: '70%', '@sm': { width: '100%' }, bg: '$surface_bright' }} value={value} onChange={e => onChange(e.target.value)} placeholder={placeholder} disabled={disabled} type={type} {...props} /> </DialogRow> ); }; export const DialogInputFile = ({ value, onChange, placeholder, disabled, type, ...props }) => { const inputRef = useRef(); return ( <DialogCol breakSm onClick={() => inputRef.current?.click()} css={{ justifyContent: 'center', position: 'relative', cursor: 'pointer', py: '$12', border: '1px dashed $border_bright', r: '$1', height: 'max(140px, 30%)', alignItems: 'center', m: '$6 0', }} gap="8" > <IconButton variant="standard" css={{ border: 'none', background: 'none', '&:hover': { border: 'none', background: 'none', bg: 'transparent !important', }, }} > <CloudUploadIcon style={{ width: '3rem', height: '3rem', }} /> </IconButton> <Flex direction="row"> <Input ref={inputRef} css={{ width: '70%', '@sm': { width: '100%' } }} value={value} onChange={e => onChange(e.target)} placeholder={placeholder} disabled={disabled} type={type} hidden={true} {...props} /> <IconButton variant="standard" css={{ background: 'none', border: 'none', textDecoration: 'underline', '&:hover': { background: 'none !important', border: 'none !important', }, }} > <Text variant="md">{placeholder}</Text> </IconButton> </Flex> </DialogCol> ); }; export const DialogSwitch = ({ title, value, onChange, disabled }) => { return ( <DialogRow> <Text>{title}</Text> <Flex justify="end" css={{ width: '70%' }}> <Switch checked={value} disabled={disabled} onCheckedChange={onChange} /> </Flex> </DialogRow> ); }; export const DialogCheckbox = ({ title, value, onChange, disabled, css, id }) => { return ( <DialogRow css={css}> <Label htmlFor={id} css={{ cursor: 'pointer' }}> {title} </Label> <Checkbox.Root checked={value} onCheckedChange={value => onChange(value)} disabled={disabled} id={id}> <Checkbox.Indicator> <CheckIcon width={16} height={16} /> </Checkbox.Indicator> </Checkbox.Root> </DialogRow> ); };