UNPKG

@blocklet/ui-react

Version:

Some useful front-end web components that can be used in Blocklets.

208 lines (199 loc) 7.66 kB
import { SessionContext } from '@arcblock/did-connect/lib/Session'; import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; import { translate } from '@arcblock/ux/lib/Locale/util'; import SessionPermission from '@arcblock/ux/lib/SessionPermission'; import { Icon } from '@iconify/react'; import { Close as CloseIcon } from '@mui/icons-material'; import { Box, ClickAwayListener, Fade, IconButton, Paper } from '@mui/material'; import { useMemoizedFn } from 'ahooks'; import PropTypes from 'prop-types'; import { use } from 'react'; import InstallerItem from './installer-item'; import translations from './locales'; import useComponentInstalled from './use-component-installed'; function ComponentInstaller({ warnIcon = null, did, noPermissionMute = false, onInstalled = null, onError = null, children, closeByOutSize = false, onClose = null, fallback = null, disabled = false, roles = ['owner', 'admin'], }) { const { locale } = useLocaleContext(); const t = useMemoizedFn((key, data = {}) => { return translate(translations, key, locale, 'en', data); }); const { installed, optComponents, installStatus, definedInBlockletYML } = useComponentInstalled({ did, onInstalled, onError, }); const sessionCtx = use(SessionContext); const handleClose = () => { onClose?.(false); }; if (disabled) { return children; } return ( <SessionPermission session={sessionCtx?.session} roles={roles}> {({ hasPermission }) => { if (installed) { return children; } if (noPermissionMute && !hasPermission) { return fallback || null; } if (typeof children === 'function') { return ( <> {fallback} {children({ hasPermission, optComponents, installStatus, })} </> ); } // not installed, but has permission, can install directly return ( <> {fallback} <ClickAwayListener onClickAway={(e) => { e.preventDefault(); e.stopPropagation(); if (closeByOutSize) { handleClose(); } }}> <Fade in timeout={350}> <Paper variant="outlined" sx={{ position: 'fixed', top: 20, right: 20, zIndex: 3000, borderRadius: 1.5, width: 400, maxWidth: '90vw', borderColor: 'divider', border: '0 !important', fontSize: '14px', textAlign: 'left', boxShadow: ({ palette }) => `0px 8px 16px 0px ${palette.grey[100]}, 0px 0px 0px 1px ${palette.grey[100]}`, }}> {!definedInBlockletYML ? ( <Box sx={{ display: 'flex', flexDirection: 'column' }}> <Box sx={{ padding: '20px 24px', marginLeft: 0, display: 'flex', alignItems: 'center', flexDirection: 'row', justifyContent: 'flex-start', }}> {warnIcon || <Icon icon="mdi:warning-box" style={{ color: 'yellowgreen', fontSize: 24 }} />} <Box sx={{ marginLeft: 1, fontSize: '16px', fontWeight: 'bold' }}> {t('componentInstallerTitle')} </Box> <Box sx={{ flex: 1 }} /> {onClose ? ( <IconButton variant="outlined" className="button" onClick={handleClose}> <CloseIcon /> </IconButton> ) : null} </Box> <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} /> <Box sx={{ padding: '20px 24px', marginTop: 0 }}> {t('componentInstallerNoDefinedInBlockletYML')}: {did} </Box> </Box> ) : ( <Box sx={{ display: 'flex', flexDirection: 'column' }}> <Box sx={{ padding: '20px 24px', marginLeft: 0, display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', }}> {warnIcon || <Icon icon="mdi:warning-box" style={{ color: 'yellowgreen', fontSize: 24 }} />} <Box sx={{ marginLeft: 1, fontSize: '16px', fontWeight: 'bold' }}> {t('componentInstallerTitle')} </Box> <Box sx={{ flex: 1 }} /> {onClose ? ( <IconButton variant="outlined" className="button" onClick={handleClose}> <CloseIcon /> </IconButton> ) : null} </Box> <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} /> <Box sx={{ maxHeight: '70vh', overflowY: 'auto' }}> {optComponents.map((optionalComponent, index) => { return ( <InstallerItem t={t} key={optionalComponent.meta?.did || index} hasPermission={hasPermission} index={index} optionalComponent={optionalComponent} installStatus={installStatus[optionalComponent.meta?.did]} /> ); })} </Box> {hasPermission ? null : ( <> <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} /> <Box sx={{ padding: '20px 24px' }}> <Box sx={{ opacity: 1 }}>{t('componentInstallerSuggestions')}</Box> </Box> </> )} </Box> )} </Paper> </Fade> </ClickAwayListener> </> ); }} </SessionPermission> ); } ComponentInstaller.propTypes = { disabled: PropTypes.bool, warnIcon: PropTypes.node, did: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).isRequired, noPermissionMute: PropTypes.bool, onInstalled: PropTypes.func, onError: PropTypes.func, children: PropTypes.any.isRequired, closeByOutSize: PropTypes.bool, onClose: PropTypes.func, fallback: PropTypes.node, roles: PropTypes.array, }; export default function WrapComponentInstaller(props) { if (window.blocklet) { return <ComponentInstaller {...props} />; } return props.children; } WrapComponentInstaller.propTypes = { ...ComponentInstaller.propTypes, children: PropTypes.any.isRequired, };