UNPKG

@ithinkdt/naive

Version:

iThinkDT Naive UI

306 lines (268 loc) 11.8 kB
import { ref, computed, defineComponent, useSlots, h, nextTick, provide, watch, markRaw, defineAsyncComponent, Teleport, } from 'vue' import { useRouter } from 'vue-router' import { asyncComputed } from '@vueuse/core' import { NConfigProvider, NLoadingBarProvider, modalProps, NGlobalStyle, NNotificationProvider, useNotification, NMessageProvider, useMessage, NDialogProvider, useDialog, drawerContentProps, NScrollbar, } from 'ithinkdt-ui' import zhCN from 'ithinkdt-ui/es/locales/common/zhCN' import dateZhCN from 'ithinkdt-ui/es/locales/date/zhCN' import { useI18n, lang, useTheme, $notice, Route, useAuth, modals } from '@ithinkdt/core' import { TooltipProvider } from '../directives/tooltip' import { SpinProvider } from '../directives/spin' export let message export let dialog export let notification const NModal = defineAsyncComponent(() => import('./lazy.js').then((m) => m.NModal)) const NDrawer = defineAsyncComponent(() => import('./lazy.js').then((m) => m.NDrawer)) const NDrawerContent = defineAsyncComponent(() => import('./lazy.js').then((m) => m.NDrawerContent)) const NWatermark = defineAsyncComponent(() => import('./lazy.js').then((m) => m.NWatermark)) const Inject = defineComponent({ name: 'DtNaiveUIInject', setup() { message = useMessage() dialog = useDialog() notification = useNotification() const slots = useSlots() return slots.default }, }) const ModalProvider = defineComponent({ name: 'DtNaiveUIModalProvider', setup() { const inited = Symbol() return () => modals.map((modal) => { if (!modal[inited]) { modal.__date = (Date.now() % 1_000_000) + '-' + Math.floor(Math.random() * 1000) modal.visible = false modal.show = () => { modal.visible = true } modal.hide = () => { // eslint-disable-next-line unicorn/no-null modal.visible = null } modal.close = () => { modal.visible = false } modal[inited] = markRaw( defineComponent({ provide: { __modal: modal }, render: () => { const { type = 'dialog', onClose, content: _1, __destroyed: _2, show: _3, hide: _4, destroy: _5, visible: _6, nativeScrollbar, wrap, class: cls, style, ...props } = modal const node = typeof modal.content === 'function' ? { default: modal.content } : modal.content if (type === 'drawer') { const drawerBind = { class: cls, style, }, contentBind = { nativeScrollbar: nativeScrollbar ?? false, } for (const k of Object.keys(props)) { if (k in drawerContentProps) { contentBind[k] = modal[k] } else { drawerBind[k] = modal[k] } } return ( <NDrawer {...drawerBind} show={modal.visible || false} onUpdateShow={(show) => { modal.visible = show if (!show) return onClose?.() }} maskClosable={modal.closable !== false && modal.maskClosable} > {wrap === false ? ( node.default() ) : ( <NDrawerContent {...contentBind}>{node}</NDrawerContent> )} </NDrawer> ) } const modalBind = type === 'dialog' ? { preset: 'card' } : {} for (const k of Object.keys(props)) { if (Object.hasOwn(modalProps, k)) { modalBind[k] = modal[k] } } if (typeof modalBind.contentStyle === 'string') { modalBind.contentStyle = 'display: flex; flex-direction: column; overflow: hidden;' + modalBind.contentStyle } else { if (!modalBind.contentStyle) { modalBind.contentStyle = {} } modalBind.contentStyle.display = 'flex' modalBind.contentStyle.flexDirection = 'column' modalBind.contentStyle.overflow = 'auto' } if (!nativeScrollbar) { const _def = node.default node.default = () => ( <div> <NScrollbar style="display: flex; flex-direction: column;"> <div>{_def?.()}</div> </NScrollbar> </div> ) } return ( <NModal {...modalBind} class={cls} show={modal.visible || false} style={{ ...style, width: typeof modal.width === 'number' ? modal.width + 'px' : modal.width, maxHeight: style?.maxHeight ?? `calc(80vh - 20px)`, }} onClose={onClose} onUpdateShow={(v) => (modal.visible = v)} displayDirective={modal.visible === null ? 'show' : modalBind.displayDirective} maskClosable={modal.closable !== false && modal.maskClosable} autoFocus={false} > {node} </NModal> ) }, }), ) } if (modal.__destroyed) return return h(modal[inited], { key: modal.__date }) }) }, }) export const DtNaiveUI = defineComponent({ name: 'DtNaiveUI', setup() { const { t, locale } = useI18n() const nConfig = computed(() => { const isZhCN = locale.value === lang.zhCN return { locale: isZhCN ? zhCN : undefined, dateLocale: isZhCN ? dateZhCN : undefined, } }) const auth = useAuth() provide('__INJECTED_AUTH__', auth) const theme = useTheme() provide('__INJECTED_THEME__', theme) const router = useRouter() watch( [() => theme.isDark, () => auth.user, () => auth.app], ([isDark, user, app]) => { if (theme.watermark === false) return theme.watermark = theme._watermark?.({ isDark, user, app }) ?? undefined }, { immediate: true }, ) const slots = useSlots() const loadingbarInst = ref() router.beforeEach(() => { loadingbarInst.value?.start() }) router.afterEach(async (to) => { await nextTick() if (to.name === Route.NOT_FOUND || theme.currentPage?.error) { loadingbarInst.value?.error() } else { loadingbarInst.value?.finish() } }) router.onError(() => { // TODO 优化提示 $notice({ type: 'error', title: t('sys.tip'), content: t('sys.error.500'), }) loadingbarInst.value?.error() }) const Content = () => ( <NMessageProvider keepAliveOnHover> <NNotificationProvider> <NDialogProvider> <NLoadingBarProvider ref={loadingbarInst}> <Inject>{slots}</Inject> {theme.watermark && !router.currentRoute.value?.meta.hideWatermark ? ( <NWatermark fullscreen cross {...theme.watermark} /> ) : undefined} <ModalProvider /> <TooltipProvider /> <Teleport to="body"> <SpinProvider /> </Teleport> </NLoadingBarProvider> </NDialogProvider> </NNotificationProvider> </NMessageProvider> ) const themeOverrides = computed(() => ({ ...theme.naiveThemeOverrides, common: theme.vars, })) const darkTheme = asyncComputed(() => import('ithinkdt-ui/es/themes/dark').then((m) => m.darkTheme)) return () => { return ( <NConfigProvider abstract preflight-style-disabled locale={nConfig.value.locale} dateLocale={nConfig.value.dateLocale} // eslint-disable-next-line unicorn/no-null theme={theme.isDark ? darkTheme.value : null} themeOverrides={themeOverrides.value} > <NGlobalStyle /> <Content /> </NConfigProvider> ) } }, })