diff --git a/components/lib/passthrough/index.js b/components/lib/passthrough/index.js index e00cf4406..4c63d173b 100644 --- a/components/lib/passthrough/index.js +++ b/components/lib/passthrough/index.js @@ -1,19 +1,46 @@ +import { ObjectUtils } from 'primevue/utils'; import { mergeProps } from 'vue'; -// @todo: Improve this method -export const usePassThrough = (theme, pt = {}, { merge = false }) => { - const newTheme = { ...theme }; - const componentNames = Object.keys(pt); +export const usePassThrough = (pt1 = {}, pt2 = {}, { merge = true, useMergeProps = false, ignoredKeysOnMerge = [], customizer = undefined } = {}) => { + const newPT = { ...pt1 }; - return componentNames.reduce((t, n) => { - if (!merge) { - t[n] = pt[n]; - } else { - t[n] = Object.entries(pt[n]).reduce((_t, [sk, sv]) => { - return mergeProps(t[n][sk], sv); - }, {}); - } + if (merge) { + const getPTClassValue = (value) => (ObjectUtils.isString(value) || ObjectUtils.isArray(value) ? { class: value } : value); - return t; - }, newTheme); + const setOptionValue = (to, from, nestedKey, ignoredKey) => { + const keys = nestedKey.split('.'); + const key = keys.shift(); + const getValue = (value) => (ObjectUtils.isFunction(customizer) ? customizer({ key, to, from, value }) : value); + + if (!!ignoredKey && ignoredKey.endsWith(key)) { + !!key && (to[key] = getValue(from[key])); + } else { + const matched = [Object.keys(to[key] || {}), Object.keys(from[key] || {})].flat().some((k) => k.match(/^(class|style|on(.+))/)); + + if (matched) { + to[key] = getValue(useMergeProps ? mergeProps(getPTClassValue(to[key]), getPTClassValue(from[key])) : { ...getPTClassValue(to[key]), ...getPTClassValue(from[key]) }); + } else if (ObjectUtils.isNotEmpty(from[key])) { + to[key] = { ...to[key] }; + setOptionValue(to[key], from[key], keys.join('.'), ignoredKey); + } else if (!!key) { + to[key] = getValue(from[key]); + } + } + }; + + const nestedKeys = ObjectUtils.nestedKeys(pt2); + + nestedKeys.forEach((nestedKey) => { + setOptionValue( + newPT, + pt2, + nestedKey, + ignoredKeysOnMerge.find((k) => (k.indexOf('.') > 0 ? nestedKey.startsWith(k) : nestedKey.split('.')[0] === k)) + ); + }); + } else { + Object.keys(pt2).forEach((key) => (newPT[key] = pt2[key])); + } + + return newPT; }; diff --git a/components/lib/utils/ObjectUtils.js b/components/lib/utils/ObjectUtils.js index ff3dd9fe1..1b665c797 100755 --- a/components/lib/utils/ObjectUtils.js +++ b/components/lib/utils/ObjectUtils.js @@ -286,5 +286,15 @@ export default { } return index; + }, + + nestedKeys(obj = {}, parentKey = '') { + return Object.entries(obj).reduce((o, [key, value]) => { + const currentKey = parentKey ? `${parentKey}.${key}` : key; + + this.isObject(value) ? (o = o.concat(this.nestedKeys(value, currentKey))) : o.push(currentKey); + + return o; + }, []); } };