import type { App, ComponentPublicInstance, InjectionKey, reactive } from 'vue' // Plugins // import { Notification } from '@/components/UNotification/notification' // Composables import { createIcons, IconSymbol } from '@/composables/icons' import { createDefaults, DefaultsSymbol } from '@/composables/defaults' // Types import type { DefaultsOptions } from '@/composables/defaults' import type { IconOptions } from '@/composables/icons' export interface UntitledOptions { components?: Record defaults?: DefaultsOptions icons?: IconOptions } export function createUntitled(options: UntitledOptions = {}) { const { components } = options const defaults = createDefaults(options.defaults) const icons = createIcons(options.icons) return { install(app: App) { // Auto import all components for (const key in components) { app.component(key, (components as any)[key]) } app.provide(DefaultsSymbol, defaults) app.provide(IconSymbol, icons) // app.use(Notification) if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) { app.mixin({ computed: { $untitled() { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return reactive({ defaults: inject.call(this, DefaultsSymbol), icons: inject.call(this, IconSymbol), }) }, }, }) } }, defaults, icons, } } // Vue's inject() can only be used in setup function inject( this: ComponentPublicInstance, key: InjectionKey | string ) { const vm = this.$ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides if (provides && (key as any) in provides) { return provides[key as string] } }