index.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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<
  12. K extends keyof ConfigProviderContext,
  13. D extends ConfigProviderContext[K]
  14. >(
  15. key: K,
  16. defaultValue?: D
  17. ): Ref<Exclude<ConfigProviderContext[K], undefined> | D>
  18. export function useGlobalConfig(): Ref<ConfigProviderContext>
  19. export function useGlobalConfig(
  20. key?: keyof ConfigProviderContext,
  21. defaultValue = undefined
  22. ) {
  23. const config = getCurrentInstance()
  24. ? inject(configProviderContextKey, globalConfig)
  25. : globalConfig
  26. if (key) {
  27. return computed(() => config.value?.[key] ?? defaultValue)
  28. } else {
  29. return config
  30. }
  31. }
  32. export const provideGlobalConfig = (
  33. config: MaybeRef<ConfigProviderContext>,
  34. app?: App,
  35. global = false
  36. ) => {
  37. const inSetup = !!getCurrentInstance()
  38. const oldConfig = inSetup ? useGlobalConfig() : undefined
  39. const provideFn = app?.provide ?? (inSetup ? provide : undefined)
  40. if (!provideFn) {
  41. debugWarn(
  42. 'provideGlobalConfig',
  43. 'provideGlobalConfig() can only be used inside setup().'
  44. )
  45. return
  46. }
  47. const context = computed(() => {
  48. const cfg = unref(config)
  49. if (!oldConfig?.value) return cfg
  50. return mergeConfig(oldConfig.value, cfg)
  51. })
  52. provideFn(configProviderContextKey, context)
  53. if (global || !globalConfig.value) {
  54. globalConfig.value = context.value
  55. }
  56. return context
  57. }
  58. const mergeConfig = (
  59. a: ConfigProviderContext,
  60. b: ConfigProviderContext
  61. ): ConfigProviderContext => {
  62. const keys = [...new Set([...keysOf(a), ...keysOf(b)])]
  63. const obj: Record<string, any> = {}
  64. for (const key of keys) {
  65. obj[key] = b[key] ?? a[key]
  66. }
  67. return obj
  68. }