UNPKG

@blocklet/ui-react

Version:

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

114 lines (97 loc) 4.33 kB
import 'iconify-icon'; import { use, createElement } from 'react'; import PropTypes from 'prop-types'; // FIXME: 直接从 react 中 import Fragment 可能会在 vite 下出错,先暂时从 react/jsx-runtime 导入 Fragment 来跳过这个问题 import { Fragment } from 'react/jsx-runtime'; import { SessionContext } from '@arcblock/did-connect/lib/Session'; import SessionUser from '@arcblock/ux/lib/SessionUser'; import SessionBlocklet from '@arcblock/ux/lib/SessionBlocklet'; import LocaleSelector from '@arcblock/ux/lib/Locale/selector'; import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; import ThemeModeToggle from '@arcblock/ux/lib/Config/theme-mode-toggle'; import { SessionManagerProps } from '../types'; import { getLocalizedNavigation, filterNavByRole } from '../blocklets'; import NotificationAddon from './notification-addon'; import DomainWarning from './domain-warning'; const hasNotification = () => { const navigations = window?.blocklet?.navigation ?? []; return !!navigations.find((n) => n.id === '/userCenter/notification'); }; // eslint-disable-next-line no-shadow export default function HeaderAddons({ formattedBlocklet, addons = null, showDomainWarningDialog = true, sessionManagerProps = { showRole: true }, }) { const sessionCtx = use(SessionContext); const { locale, languages } = useLocaleContext() || {}; const { enableConnect = true, enableLocale = true } = formattedBlocklet; const authenticated = !!sessionCtx?.session?.user; let localizedNav = getLocalizedNavigation(formattedBlocklet?.navigation?.sessionManager, locale) || []; // 根据 role 筛选 nav 数据 localizedNav = filterNavByRole(localizedNav, sessionCtx?.session?.user?.role); const renderAddons = () => { // 不关心内置的 session manager 和 locale selector, 直接覆盖 UX Header 的 addons if (addons && typeof addons !== 'function') { return Array.isArray(addons) ? addons : [addons]; } let addonsArray = []; if (hasNotification()) { addonsArray.push(<NotificationAddon key="notification-addon" session={sessionCtx.session} />); } // 启用了多语言,且检测到了 locale context,且有多种语言可以切换 if (enableLocale && locale && languages.length > 1) { addonsArray.push(<LocaleSelector key="locale-selector" showText={false} />); } // 切换明暗主题 addonsArray.push(<ThemeModeToggle key="theme-mode-toggle" />); // 启用了连接钱包并且检测到了 session context if (enableConnect && sessionCtx) { const menu = []; if (authenticated) { const navList = localizedNav ? localizedNav.slice(0, 5) : []; navList.forEach((x) => { menu.push({ label: x.title, icon: x.icon ? <iconify-icon icon={x.icon} height={24} style={{ marginRight: 8 }} /> : null, component: 'a', href: x.link, key: x.link, }); }); } addonsArray.push(<SessionBlocklet key="session-blocklet" session={sessionCtx.session} locale={locale} />); addonsArray.push( <SessionUser key="session-user" session={sessionCtx.session} locale={locale} menu={menu} showRole {...sessionManagerProps} /> ); } if (typeof addons === 'function') { addonsArray = addons(addonsArray) || []; } return addonsArray; }; const renderedAddons = renderAddons(); const nodes = Array.isArray(renderedAddons) ? renderedAddons : [renderedAddons]; const mergedNodes = [ showDomainWarningDialog ? <DomainWarning session={sessionCtx?.session} locale={locale} /> : null, ...nodes, ].filter(Boolean); return createElement(Fragment, null, ...mergedNodes); } HeaderAddons.propTypes = { formattedBlocklet: PropTypes.object.isRequired, // 需要考虑 定制的 addons 与内置的 连接钱包/选择语言 addons 共存的情况 // - PropTypes.func: 可以把自定义 addons 插在 session-manager 或 locale-selector (如果存在的话) 前/中/后 // - PropTypes.node: 将 addons 原样传给 UX Header 组件 addons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), sessionManagerProps: SessionManagerProps, showDomainWarningDialog: PropTypes.bool, };