56 lines
1.4 KiB
Vue
56 lines
1.4 KiB
Vue
<template>
|
|
<span v-for="toComponent of componentArray" :key="toComponent.name">
|
|
<component
|
|
v-if="toComponent?.component"
|
|
:is="mix(toComponent).component"
|
|
v-bind="mix(toComponent).attrs"
|
|
v-on="mix(toComponent).event ?? {}"
|
|
v-model="model"
|
|
/>
|
|
</span>
|
|
</template>
|
|
<script setup>
|
|
import { computed, defineModel } from 'vue';
|
|
|
|
const model = defineModel();
|
|
const $props = defineProps({
|
|
prop: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
components: {
|
|
type: Object,
|
|
default: () => {},
|
|
},
|
|
value: {
|
|
type: [Object, Number, String],
|
|
default: () => {},
|
|
},
|
|
});
|
|
|
|
const componentArray = computed(() => {
|
|
if (typeof $props.prop === 'object') return [$props.prop];
|
|
return $props.prop;
|
|
});
|
|
|
|
function mix(toComponent) {
|
|
const { component, attrs, event } = toComponent;
|
|
const customComponent = $props.components[component];
|
|
return {
|
|
component: customComponent?.component ?? component,
|
|
attrs: {
|
|
...toValueAttrs(attrs),
|
|
...toValueAttrs(customComponent?.attrs),
|
|
...toComponent,
|
|
...toValueAttrs(customComponent?.forceAttrs),
|
|
},
|
|
event: event ?? customComponent?.event,
|
|
};
|
|
}
|
|
|
|
function toValueAttrs(attrs) {
|
|
if (!attrs) return;
|
|
return typeof attrs == 'function' ? attrs($props.value) : attrs;
|
|
}
|
|
</script>
|