index.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { computed, getCurrentInstance, inject, provide, ref, unref } from 'vue'
  2. import { configProviderContextKey } from '@kankan-components/tokens'
  3. import { debugWarn, keysOf } from '@kankan-components/utils'
  4. import type { MaybeRef } from '@vueuse/core'
  5. import type { App, Ref } from 'vue'
  6. import type { ConfigProviderContext } from '@kankan-components/tokens'
  7. // this is meant to fix global methods like `ElMessage(opts)`, this way we can inject current locale
  8. // into the component as default injection value.
  9. // refer to: https://github.com/element-plus/element-plus/issues/2610#issuecomment-887965266
  10. const globalConfig = ref<ConfigProviderContext>()
  11. export function useGlobalConfig<K extends keyof ConfigProviderContext, D extends ConfigProviderContext[K]>(key: K, defaultValue?: D): Ref<Exclude<ConfigProviderContext[K], undefined> | D>
  12. export function useGlobalConfig(): Ref<ConfigProviderContext>
  13. export function useGlobalConfig(key?: keyof ConfigProviderContext, defaultValue = undefined) {
  14. const config = getCurrentInstance() ? inject(configProviderContextKey, globalConfig) : globalConfig
  15. if (key) {
  16. return computed(() => config.value?.[key] ?? defaultValue)
  17. } else {
  18. return config
  19. }
  20. }
  21. export const provideGlobalConfig = (config: MaybeRef<ConfigProviderContext>, app?: App, global = false) => {
  22. const inSetup = !!getCurrentInstance()
  23. const oldConfig = inSetup ? useGlobalConfig() : undefined
  24. const provideFn = app?.provide ?? (inSetup ? provide : undefined)
  25. if (!provideFn) {
  26. debugWarn('provideGlobalConfig', 'provideGlobalConfig() can only be used inside setup().')
  27. return
  28. }
  29. const context = computed(() => {
  30. const cfg = unref(config)
  31. if (!oldConfig?.value) return cfg
  32. return mergeConfig(oldConfig.value, cfg)
  33. })
  34. provideFn(configProviderContextKey, context)
  35. if (global || !globalConfig.value) {
  36. globalConfig.value = context.value
  37. }
  38. return context
  39. }
  40. const mergeConfig = (a: ConfigProviderContext, b: ConfigProviderContext): ConfigProviderContext => {
  41. const keys = [...new Set([...keysOf(a), ...keysOf(b)])]
  42. const obj: Record<string, any> = {}
  43. for (const key of keys) {
  44. obj[key] = b[key] ?? a[key]
  45. }
  46. return obj
  47. }