mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 15:40:10 +00:00
[Feature] Add InputKnob component and integrate with FormItem (#2821)
This commit is contained in:
@@ -39,6 +39,7 @@ import { type Component, markRaw } from 'vue'
|
||||
import CustomFormValue from '@/components/common/CustomFormValue.vue'
|
||||
import FormColorPicker from '@/components/common/FormColorPicker.vue'
|
||||
import FormImageUpload from '@/components/common/FormImageUpload.vue'
|
||||
import InputKnob from '@/components/common/InputKnob.vue'
|
||||
import InputSlider from '@/components/common/InputSlider.vue'
|
||||
import UrlInput from '@/components/common/UrlInput.vue'
|
||||
import { FormItem } from '@/types/settingTypes'
|
||||
@@ -91,6 +92,8 @@ function getFormComponent(item: FormItem): Component {
|
||||
return InputNumber
|
||||
case 'slider':
|
||||
return InputSlider
|
||||
case 'knob':
|
||||
return InputKnob
|
||||
case 'combo':
|
||||
return Select
|
||||
case 'image':
|
||||
@@ -111,6 +114,11 @@ function getFormComponent(item: FormItem): Component {
|
||||
@apply w-20;
|
||||
}
|
||||
|
||||
.form-input :deep(.input-knob) .p-inputnumber input,
|
||||
.form-input :deep(.input-knob) .knob-part {
|
||||
@apply w-32;
|
||||
}
|
||||
|
||||
.form-input :deep(.p-inputtext),
|
||||
.form-input :deep(.p-select) {
|
||||
@apply w-44;
|
||||
|
||||
89
src/components/common/InputKnob.vue
Normal file
89
src/components/common/InputKnob.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="input-knob flex flex-row items-center gap-2">
|
||||
<Knob
|
||||
:modelValue="modelValue"
|
||||
@update:modelValue="updateValue"
|
||||
:valueTemplate="displayValue"
|
||||
class="knob-part"
|
||||
:class="knobClass"
|
||||
:min="min"
|
||||
:max="max"
|
||||
:step="step"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<InputNumber
|
||||
:modelValue="modelValue"
|
||||
@update:modelValue="updateValue"
|
||||
class="input-part"
|
||||
:max-fraction-digits="3"
|
||||
:class="inputClass"
|
||||
:min="min"
|
||||
:max="max"
|
||||
:step="step"
|
||||
:allowEmpty="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import InputNumber from 'primevue/inputnumber'
|
||||
import Knob from 'primevue/knob'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: number
|
||||
inputClass?: string
|
||||
knobClass?: string
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
resolution?: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: number): void
|
||||
}>()
|
||||
|
||||
const localValue = ref(props.modelValue)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
localValue.value = newValue
|
||||
}
|
||||
)
|
||||
|
||||
const updateValue = (newValue: number | null) => {
|
||||
if (newValue === null) {
|
||||
// If the input is cleared, reset to the minimum value or 0
|
||||
newValue = Number(props.min) || 0
|
||||
}
|
||||
|
||||
const min = Number(props.min ?? Number.NEGATIVE_INFINITY)
|
||||
const max = Number(props.max ?? Number.POSITIVE_INFINITY)
|
||||
const step = Number(props.step) || 1
|
||||
|
||||
// Ensure the value is within the allowed range
|
||||
newValue = Math.max(min, Math.min(max, newValue))
|
||||
|
||||
// Round to the nearest step
|
||||
newValue = Math.round(newValue / step) * step
|
||||
|
||||
// Update local value and emit change
|
||||
localValue.value = newValue
|
||||
emit('update:modelValue', newValue)
|
||||
}
|
||||
|
||||
const displayValue = (value: number): string => {
|
||||
updateValue(value)
|
||||
const stepString = props.step.toString()
|
||||
const resolution = stepString.includes('.')
|
||||
? stepString.split('.')[1].length
|
||||
: 0
|
||||
return value.toFixed(props.resolution ?? resolution)
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false
|
||||
})
|
||||
</script>
|
||||
@@ -4,6 +4,7 @@ export type SettingInputType =
|
||||
| 'boolean'
|
||||
| 'number'
|
||||
| 'slider'
|
||||
| 'knob'
|
||||
| 'combo'
|
||||
| 'text'
|
||||
| 'image'
|
||||
|
||||
Reference in New Issue
Block a user