45 lines
1.9 KiB
JavaScript
45 lines
1.9 KiB
JavaScript
// Composables
|
|
import { useToggleScope } from "./toggleScope.mjs"; // Utilities
|
|
import { computed, ref, toRaw, watch } from 'vue';
|
|
import { getCurrentInstance, toKebabCase } from "../util/index.mjs"; // Types
|
|
// Composables
|
|
export function useProxiedModel(props, prop, defaultValue) {
|
|
let transformIn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : v => v;
|
|
let transformOut = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : v => v;
|
|
const vm = getCurrentInstance('useProxiedModel');
|
|
const internal = ref(props[prop] !== undefined ? props[prop] : defaultValue);
|
|
const kebabProp = toKebabCase(prop);
|
|
const checkKebab = kebabProp !== prop;
|
|
const isControlled = checkKebab ? computed(() => {
|
|
void props[prop];
|
|
return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
|
|
}) : computed(() => {
|
|
void props[prop];
|
|
return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
|
|
});
|
|
useToggleScope(() => !isControlled.value, () => {
|
|
watch(() => props[prop], val => {
|
|
internal.value = val;
|
|
});
|
|
});
|
|
const model = computed({
|
|
get() {
|
|
const externalValue = props[prop];
|
|
return transformIn(isControlled.value ? externalValue : internal.value);
|
|
},
|
|
set(internalValue) {
|
|
const newValue = transformOut(internalValue);
|
|
const value = toRaw(isControlled.value ? props[prop] : internal.value);
|
|
if (value === newValue || transformIn(value) === internalValue) {
|
|
return;
|
|
}
|
|
internal.value = newValue;
|
|
vm?.emit(`update:${prop}`, newValue);
|
|
}
|
|
});
|
|
Object.defineProperty(model, 'externalValue', {
|
|
get: () => isControlled.value ? props[prop] : internal.value
|
|
});
|
|
return model;
|
|
}
|
|
//# sourceMappingURL=proxiedModel.mjs.map
|