[Refactor] Extract 'FormItem' and 'SettingItem' (#1619)

* Extract SettingItem component

* Extract GeneralSettingItem

* Rename to FormItem

* nit

* nit
This commit is contained in:
Chenlei Hu
2024-11-20 15:10:17 -05:00
committed by GitHub
parent 4f3693e322
commit f34d50da3d
5 changed files with 152 additions and 102 deletions

View File

@@ -0,0 +1,25 @@
<template>
<div ref="container"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
const props = defineProps<{
renderFunction: () => HTMLElement
}>()
const container = ref<HTMLElement | null>(null)
function renderContent() {
if (container.value) {
container.value.innerHTML = ''
const element = props.renderFunction()
container.value.appendChild(element)
}
}
onMounted(renderContent)
watch(() => props.renderFunction, renderContent)
</script>

View File

@@ -0,0 +1,102 @@
<!-- A generalized form item for rendering in a form. -->
<template>
<div class="form-label flex flex-grow items-center">
<span class="text-[var(--p-text-muted-color)]">
<slot name="name-prefix"></slot>
{{ props.item.name }}
<i
v-if="props.item.tooltip"
class="pi pi-info-circle bg-transparent"
v-tooltip="props.item.tooltip"
/>
<slot name="name-suffix"></slot>
</span>
</div>
<div class="form-input flex justify-end">
<component
:is="markRaw(getFormComponent(props.item))"
:id="props.id"
v-model:modelValue="formValue"
v-bind="getFormAttrs(props.item)"
/>
</div>
</template>
<script setup lang="ts">
import { FormItem } from '@/types/settingTypes'
import { markRaw, type Component } from 'vue'
import InputText from 'primevue/inputtext'
import InputNumber from 'primevue/inputnumber'
import Select from 'primevue/select'
import ToggleSwitch from 'primevue/toggleswitch'
import CustomFormValue from '@/components/common/CustomFormValue.vue'
import InputSlider from '@/components/common/InputSlider.vue'
const formValue = defineModel<any>('formValue')
const props = withDefaults(
defineProps<{
item: FormItem
id: string | undefined
}>(),
{
id: undefined
}
)
function getFormAttrs(item: FormItem) {
const attrs = { ...(item.attrs || {}) }
const inputType = item.type
if (typeof inputType === 'function') {
attrs['renderFunction'] = () =>
inputType(
props.item.name,
(v: any) => (formValue.value = v),
formValue.value,
item.attrs
)
}
switch (item.type) {
case 'combo':
attrs['options'] =
typeof item.options === 'function'
? item.options(formValue.value)
: item.options
if (typeof item.options[0] !== 'string') {
attrs['optionLabel'] = 'text'
attrs['optionValue'] = 'value'
}
break
}
return attrs
}
function getFormComponent(item: FormItem): Component {
if (typeof item.type === 'function') {
return CustomFormValue
}
switch (item.type) {
case 'boolean':
return ToggleSwitch
case 'number':
return InputNumber
case 'slider':
return InputSlider
case 'combo':
return Select
default:
return InputText
}
}
</script>
<style scoped>
.form-input :deep(.input-slider) .p-inputnumber input,
.form-input :deep(.input-slider) .slider-part {
@apply w-20;
}
.form-input :deep(.p-inputtext),
.form-input :deep(.p-select) {
@apply w-44;
}
</style>