Add form support to `Knob`

pull/6632/head
Mert Sincan 2024-10-21 14:25:46 +01:00
parent 112d3eca77
commit 387f86d0bb
4 changed files with 52 additions and 28 deletions

View File

@ -1,24 +1,16 @@
<script>
import BaseComponent from '@primevue/core/basecomponent';
import { $dt } from '@primeuix/styled';
import BaseEditableHolder from '@primevue/core/baseeditableholder';
import KnobStyle from 'primevue/knob/style';
export default {
name: 'BaseKnob',
extends: BaseComponent,
extends: BaseEditableHolder,
props: {
modelValue: {
type: Number,
default: null
},
size: {
type: Number,
default: 100
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false

View File

@ -119,11 +119,24 @@ export interface KnobProps {
* Value of the component.
*/
modelValue?: number | undefined;
/**
* The default value for the input when not controlled by `modelValue`.
*/
defaultValue?: any;
/**
* The name attribute for the element, typically used in form submissions.
*/
name?: string | undefined;
/**
* Size of the component in pixels.
* @defaultValue 100
*/
size?: number | undefined;
/**
* When present, it specifies that the component should have invalid state style.
* @defaultValue false
*/
invalid?: boolean | undefined;
/**
* When present, it specifies that the component should be disabled.
* @defaultValue false
@ -192,6 +205,10 @@ export interface KnobProps {
* Used to define a string that labels the element.
*/
ariaLabel?: string | undefined;
/**
* Form control object, typically used for handling validation and form state.
*/
formControl?: Record<string, any> | undefined;
/**
* It generates scoped CSS variables using design tokens for the component.
*/
@ -224,12 +241,17 @@ export interface KnobSlots {}
export interface KnobEmitsOptions {
/**
* Emitted when the value changes.
* @param {number} event - New value.
* @param {number} value - New value.
*/
'update:modelValue'(value: number): void;
/**
* Emitted when the value changes in uncontrolled mode.
* @param {number} value - New value.
*/
'value-change'(value: number): void;
/**
* Callback to invoke when the value changes.
* @param {number} event - New value
* @param {number} value - New value
*/
change(value: number): void;
}

View File

@ -8,10 +8,11 @@
:tabindex="readonly || disabled ? -1 : tabindex"
:aria-valuemin="min"
:aria-valuemax="max"
:aria-valuenow="modelValue"
:aria-valuenow="d_value"
:aria-labelledby="ariaLabelledby"
:aria-label="ariaLabel"
@click="onClick"
@blur="onBlur"
@keydown="onKeyDown"
@mousedown="onMouseDown"
@mouseup="onMouseUp"
@ -36,7 +37,7 @@ export default {
name: 'Knob',
extends: BaseKnob,
inheritAttrs: false,
emits: ['update:modelValue', 'change'],
emits: ['change'],
data() {
return {
radius: 40,
@ -64,13 +65,13 @@ export default {
let newValue = Math.round((mappedValue - this.min) / this.step) * this.step + this.min;
this.$emit('update:modelValue', newValue);
this.updateValue(newValue);
this.$emit('change', newValue);
},
updateModelValue(newValue) {
if (newValue > this.max) this.$emit('update:modelValue', this.max);
else if (newValue < this.min) this.$emit('update:modelValue', this.min);
else this.$emit('update:modelValue', newValue);
if (newValue > this.max) this.updateValue(this.max);
else if (newValue < this.min) this.updateValue(this.min);
else this.updateValue(newValue);
},
mapRange(x, inMin, inMax, outMin, outMax) {
return ((x - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
@ -80,6 +81,9 @@ export default {
this.updateValue(event.offsetX, event.offsetY);
}
},
onBlur(event) {
this.formField.onBlur?.(event);
},
onMouseDown(event) {
if (!this.disabled && !this.readonly) {
window.addEventListener('mousemove', this.onMouseMove);
@ -131,7 +135,7 @@ export default {
case 'ArrowUp': {
event.preventDefault();
this.updateModelValue(this.modelValue + this.step);
this.updateModelValue(this.d_value + this.step);
break;
}
@ -139,31 +143,31 @@ export default {
case 'ArrowDown': {
event.preventDefault();
this.updateModelValue(this.modelValue - this.step);
this.updateModelValue(this.d_value - this.step);
break;
}
case 'Home': {
event.preventDefault();
this.$emit('update:modelValue', this.min);
this.updateValue(this.min);
break;
}
case 'End': {
event.preventDefault();
this.$emit('update:modelValue', this.max);
this.updateValue(this.max);
break;
}
case 'PageUp': {
event.preventDefault();
this.updateModelValue(this.modelValue + 10);
this.updateModelValue(this.d_value + 10);
break;
}
case 'PageDown': {
event.preventDefault();
this.updateModelValue(this.modelValue - 10);
this.updateModelValue(this.d_value - 10);
break;
}
}
@ -182,7 +186,7 @@ export default {
else return this.mapRange(0, this.min, this.max, this.minRadians, this.maxRadians);
},
valueRadians() {
return this.mapRange(this.modelValue, this.min, this.max, this.minRadians, this.maxRadians);
return this.mapRange(this.d_value, this.min, this.max, this.minRadians, this.maxRadians);
},
minX() {
return this.midX + Math.cos(this.minRadians) * this.radius;
@ -216,9 +220,9 @@ export default {
},
valueToDisplay() {
if (typeof this.valueTemplate === 'string') {
return this.valueTemplate.replace(/{value}/g, this.modelValue);
return this.valueTemplate.replace(/{value}/g, this.d_value);
} else {
return this.valueTemplate(this.modelValue);
return this.valueTemplate(this.d_value);
}
}
}

View File

@ -37,7 +37,13 @@ const theme = ({ dt }) => `
`;
const classes = {
root: ({ props }) => ['p-knob p-component', { 'p-disabled': props.disabled }],
root: ({ instance, props }) => [
'p-knob p-component',
{
'p-disabled': props.disabled,
'p-invalid': instance.$invalid
}
],
range: 'p-knob-range',
value: 'p-knob-value',
text: 'p-knob-text'