defaults.mjs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Composables
  2. import { useToggleScope } from "./toggleScope.mjs"; // Utilities
  3. import { computed, inject, provide, ref, shallowRef, unref, watchEffect } from 'vue';
  4. import { getCurrentInstance, injectSelf, mergeDeep, toKebabCase } from "../util/index.mjs"; // Types
  5. export const DefaultsSymbol = Symbol.for('vuetify:defaults');
  6. export function createDefaults(options) {
  7. return ref(options);
  8. }
  9. export function injectDefaults() {
  10. const defaults = inject(DefaultsSymbol);
  11. if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
  12. return defaults;
  13. }
  14. export function provideDefaults(defaults, options) {
  15. const injectedDefaults = injectDefaults();
  16. const providedDefaults = ref(defaults);
  17. const newDefaults = computed(() => {
  18. const disabled = unref(options?.disabled);
  19. if (disabled) return injectedDefaults.value;
  20. const scoped = unref(options?.scoped);
  21. const reset = unref(options?.reset);
  22. const root = unref(options?.root);
  23. let properties = mergeDeep(providedDefaults.value, {
  24. prev: injectedDefaults.value
  25. });
  26. if (scoped) return properties;
  27. if (reset || root) {
  28. const len = Number(reset || Infinity);
  29. for (let i = 0; i <= len; i++) {
  30. if (!properties || !('prev' in properties)) {
  31. break;
  32. }
  33. properties = properties.prev;
  34. }
  35. if (properties && typeof root === 'string' && root in properties) {
  36. properties = mergeDeep(mergeDeep(properties, {
  37. prev: properties
  38. }), properties[root]);
  39. }
  40. return properties;
  41. }
  42. return properties.prev ? mergeDeep(properties.prev, properties) : properties;
  43. });
  44. provide(DefaultsSymbol, newDefaults);
  45. return newDefaults;
  46. }
  47. function propIsDefined(vnode, prop) {
  48. return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
  49. }
  50. export function internalUseDefaults() {
  51. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  52. let name = arguments.length > 1 ? arguments[1] : undefined;
  53. let defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : injectDefaults();
  54. const vm = getCurrentInstance('useDefaults');
  55. name = name ?? vm.type.name ?? vm.type.__name;
  56. if (!name) {
  57. throw new Error('[Vuetify] Could not determine component name');
  58. }
  59. const componentDefaults = computed(() => defaults.value?.[props._as ?? name]);
  60. const _props = new Proxy(props, {
  61. get(target, prop) {
  62. const propValue = Reflect.get(target, prop);
  63. if (prop === 'class' || prop === 'style') {
  64. return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
  65. } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
  66. return componentDefaults.value?.[prop] ?? defaults.value?.global?.[prop] ?? propValue;
  67. }
  68. return propValue;
  69. }
  70. });
  71. const _subcomponentDefaults = shallowRef();
  72. watchEffect(() => {
  73. if (componentDefaults.value) {
  74. const subComponents = Object.entries(componentDefaults.value).filter(_ref => {
  75. let [key] = _ref;
  76. return key.startsWith(key[0].toUpperCase());
  77. });
  78. if (subComponents.length) _subcomponentDefaults.value = Object.fromEntries(subComponents);
  79. }
  80. });
  81. function provideSubDefaults() {
  82. // If subcomponent defaults are provided, override any
  83. // subcomponents provided by the component's setup function.
  84. // This uses injectSelf so must be done after the original setup to work.
  85. useToggleScope(_subcomponentDefaults, () => {
  86. provideDefaults(mergeDeep(injectSelf(DefaultsSymbol)?.value ?? {}, _subcomponentDefaults.value));
  87. });
  88. }
  89. return {
  90. props: _props,
  91. provideSubDefaults
  92. };
  93. }
  94. export function useDefaults() {
  95. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  96. let name = arguments.length > 1 ? arguments[1] : undefined;
  97. const {
  98. props: _props,
  99. provideSubDefaults
  100. } = internalUseDefaults(props, name);
  101. provideSubDefaults();
  102. return _props;
  103. }
  104. //# sourceMappingURL=defaults.mjs.map