mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-12 00:20:15 +00:00
Add min-fraction-digits and max-fraction-digits props to InputNumber component to allow typing decimal values. Without these props, users could not manually type values like "0.8" even though the increment buttons worked correctly. This aligns the input-only variant with the slider variant which already had these props configured. fix https://github.com/Comfy-Org/ComfyUI_frontend/issues/7016 ## Screenshots (if applicable) https://github.com/user-attachments/assets/fa205023-13c4-45ac-874b-b241808cf56d ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7033-fix-Add-fraction-digits-props-to-number-input-widget-2b96d73d36508124ac65e466802bbb0c) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
120 lines
3.3 KiB
Vue
120 lines
3.3 KiB
Vue
<script setup lang="ts">
|
|
import InputNumber from 'primevue/inputnumber'
|
|
import { computed } from 'vue'
|
|
|
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
|
import { cn } from '@/utils/tailwindUtil'
|
|
import {
|
|
INPUT_EXCLUDED_PROPS,
|
|
filterWidgetProps
|
|
} from '@/utils/widgetPropFilter'
|
|
|
|
import { WidgetInputBaseClass } from './layout'
|
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
|
|
|
const props = defineProps<{
|
|
widget: SimplifiedWidget<number>
|
|
}>()
|
|
|
|
const modelValue = defineModel<number>({ default: 0 })
|
|
|
|
const filteredProps = computed(() =>
|
|
filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)
|
|
)
|
|
|
|
// Get the precision value for proper number formatting
|
|
const precision = computed(() => {
|
|
const p = props.widget.options?.precision
|
|
// Treat negative or non-numeric precision as undefined
|
|
return typeof p === 'number' && p >= 0 ? p : undefined
|
|
})
|
|
|
|
// Calculate the step value based on precision or widget options
|
|
const stepValue = computed(() => {
|
|
// Use step2 (correct input spec value) instead of step (legacy 10x value)
|
|
if (props.widget.options?.step2 !== undefined) {
|
|
return Number(props.widget.options.step2)
|
|
}
|
|
// Otherwise, derive from precision
|
|
if (precision.value !== undefined) {
|
|
if (precision.value === 0) {
|
|
return 1
|
|
}
|
|
// For precision > 0, step = 1 / (10^precision)
|
|
// precision 1 → 0.1, precision 2 → 0.01, etc.
|
|
return Number((1 / Math.pow(10, precision.value)).toFixed(precision.value))
|
|
}
|
|
// Default to 'any' for unrestricted stepping
|
|
return 0
|
|
})
|
|
|
|
// Disable grouping separators by default unless explicitly enabled by the node author
|
|
const useGrouping = computed(() => {
|
|
return props.widget.options?.useGrouping === true
|
|
})
|
|
|
|
// Check if increment/decrement buttons should be disabled due to precision limits
|
|
const buttonsDisabled = computed(() => {
|
|
const currentValue = modelValue.value ?? 0
|
|
return (
|
|
!Number.isFinite(currentValue) ||
|
|
Math.abs(currentValue) > Number.MAX_SAFE_INTEGER
|
|
)
|
|
})
|
|
|
|
const buttonTooltip = computed(() => {
|
|
if (buttonsDisabled.value) {
|
|
return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)'
|
|
}
|
|
return null
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<WidgetLayoutField :widget>
|
|
<InputNumber
|
|
v-model="modelValue"
|
|
v-tooltip="buttonTooltip"
|
|
v-bind="filteredProps"
|
|
fluid
|
|
button-layout="horizontal"
|
|
size="small"
|
|
variant="outlined"
|
|
:step="stepValue"
|
|
:min-fraction-digits="precision"
|
|
:max-fraction-digits="precision"
|
|
:use-grouping="useGrouping"
|
|
:class="cn(WidgetInputBaseClass, 'grow text-xs')"
|
|
:aria-label="widget.name"
|
|
:show-buttons="!buttonsDisabled"
|
|
:pt="{
|
|
root: {
|
|
class:
|
|
'[&>input]:bg-transparent [&>input]:border-0 [&>input]:truncate [&>input]:min-w-[4ch]'
|
|
},
|
|
decrementButton: {
|
|
class: 'w-8 border-0'
|
|
},
|
|
incrementButton: {
|
|
class: 'w-8 border-0'
|
|
}
|
|
}"
|
|
>
|
|
<template #incrementicon>
|
|
<span class="pi pi-plus text-sm" />
|
|
</template>
|
|
<template #decrementicon>
|
|
<span class="pi pi-minus text-sm" />
|
|
</template>
|
|
</InputNumber>
|
|
</WidgetLayoutField>
|
|
</template>
|
|
|
|
<style scoped>
|
|
:deep(.p-inputnumber-input) {
|
|
height: 1.625rem;
|
|
margin: 1px 0;
|
|
box-shadow: none;
|
|
}
|
|
</style>
|