Add form support to `Knob`
parent
112d3eca77
commit
387f86d0bb
|
@ -1,24 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import BaseComponent from '@primevue/core/basecomponent';
|
|
||||||
import { $dt } from '@primeuix/styled';
|
import { $dt } from '@primeuix/styled';
|
||||||
|
import BaseEditableHolder from '@primevue/core/baseeditableholder';
|
||||||
import KnobStyle from 'primevue/knob/style';
|
import KnobStyle from 'primevue/knob/style';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BaseKnob',
|
name: 'BaseKnob',
|
||||||
extends: BaseComponent,
|
extends: BaseEditableHolder,
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
|
||||||
type: Number,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
size: {
|
size: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 100
|
default: 100
|
||||||
},
|
},
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
readonly: {
|
readonly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
|
|
@ -119,11 +119,24 @@ export interface KnobProps {
|
||||||
* Value of the component.
|
* Value of the component.
|
||||||
*/
|
*/
|
||||||
modelValue?: number | undefined;
|
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.
|
* Size of the component in pixels.
|
||||||
* @defaultValue 100
|
* @defaultValue 100
|
||||||
*/
|
*/
|
||||||
size?: number | undefined;
|
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.
|
* When present, it specifies that the component should be disabled.
|
||||||
* @defaultValue false
|
* @defaultValue false
|
||||||
|
@ -192,6 +205,10 @@ export interface KnobProps {
|
||||||
* Used to define a string that labels the element.
|
* Used to define a string that labels the element.
|
||||||
*/
|
*/
|
||||||
ariaLabel?: string | undefined;
|
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.
|
* It generates scoped CSS variables using design tokens for the component.
|
||||||
*/
|
*/
|
||||||
|
@ -224,12 +241,17 @@ export interface KnobSlots {}
|
||||||
export interface KnobEmitsOptions {
|
export interface KnobEmitsOptions {
|
||||||
/**
|
/**
|
||||||
* Emitted when the value changes.
|
* Emitted when the value changes.
|
||||||
* @param {number} event - New value.
|
* @param {number} value - New value.
|
||||||
*/
|
*/
|
||||||
'update:modelValue'(value: number): void;
|
'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.
|
* Callback to invoke when the value changes.
|
||||||
* @param {number} event - New value
|
* @param {number} value - New value
|
||||||
*/
|
*/
|
||||||
change(value: number): void;
|
change(value: number): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
:tabindex="readonly || disabled ? -1 : tabindex"
|
:tabindex="readonly || disabled ? -1 : tabindex"
|
||||||
:aria-valuemin="min"
|
:aria-valuemin="min"
|
||||||
:aria-valuemax="max"
|
:aria-valuemax="max"
|
||||||
:aria-valuenow="modelValue"
|
:aria-valuenow="d_value"
|
||||||
:aria-labelledby="ariaLabelledby"
|
:aria-labelledby="ariaLabelledby"
|
||||||
:aria-label="ariaLabel"
|
:aria-label="ariaLabel"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
|
@blur="onBlur"
|
||||||
@keydown="onKeyDown"
|
@keydown="onKeyDown"
|
||||||
@mousedown="onMouseDown"
|
@mousedown="onMouseDown"
|
||||||
@mouseup="onMouseUp"
|
@mouseup="onMouseUp"
|
||||||
|
@ -36,7 +37,7 @@ export default {
|
||||||
name: 'Knob',
|
name: 'Knob',
|
||||||
extends: BaseKnob,
|
extends: BaseKnob,
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
emits: ['update:modelValue', 'change'],
|
emits: ['change'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
radius: 40,
|
radius: 40,
|
||||||
|
@ -64,13 +65,13 @@ export default {
|
||||||
|
|
||||||
let newValue = Math.round((mappedValue - this.min) / this.step) * this.step + this.min;
|
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);
|
this.$emit('change', newValue);
|
||||||
},
|
},
|
||||||
updateModelValue(newValue) {
|
updateModelValue(newValue) {
|
||||||
if (newValue > this.max) this.$emit('update:modelValue', this.max);
|
if (newValue > this.max) this.updateValue(this.max);
|
||||||
else if (newValue < this.min) this.$emit('update:modelValue', this.min);
|
else if (newValue < this.min) this.updateValue(this.min);
|
||||||
else this.$emit('update:modelValue', newValue);
|
else this.updateValue(newValue);
|
||||||
},
|
},
|
||||||
mapRange(x, inMin, inMax, outMin, outMax) {
|
mapRange(x, inMin, inMax, outMin, outMax) {
|
||||||
return ((x - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
return ((x - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
||||||
|
@ -80,6 +81,9 @@ export default {
|
||||||
this.updateValue(event.offsetX, event.offsetY);
|
this.updateValue(event.offsetX, event.offsetY);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onBlur(event) {
|
||||||
|
this.formField.onBlur?.(event);
|
||||||
|
},
|
||||||
onMouseDown(event) {
|
onMouseDown(event) {
|
||||||
if (!this.disabled && !this.readonly) {
|
if (!this.disabled && !this.readonly) {
|
||||||
window.addEventListener('mousemove', this.onMouseMove);
|
window.addEventListener('mousemove', this.onMouseMove);
|
||||||
|
@ -131,7 +135,7 @@ export default {
|
||||||
|
|
||||||
case 'ArrowUp': {
|
case 'ArrowUp': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.updateModelValue(this.modelValue + this.step);
|
this.updateModelValue(this.d_value + this.step);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,31 +143,31 @@ export default {
|
||||||
|
|
||||||
case 'ArrowDown': {
|
case 'ArrowDown': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.updateModelValue(this.modelValue - this.step);
|
this.updateModelValue(this.d_value - this.step);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'Home': {
|
case 'Home': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.$emit('update:modelValue', this.min);
|
this.updateValue(this.min);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'End': {
|
case 'End': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.$emit('update:modelValue', this.max);
|
this.updateValue(this.max);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'PageUp': {
|
case 'PageUp': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.updateModelValue(this.modelValue + 10);
|
this.updateModelValue(this.d_value + 10);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'PageDown': {
|
case 'PageDown': {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.updateModelValue(this.modelValue - 10);
|
this.updateModelValue(this.d_value - 10);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +186,7 @@ export default {
|
||||||
else return this.mapRange(0, this.min, this.max, this.minRadians, this.maxRadians);
|
else return this.mapRange(0, this.min, this.max, this.minRadians, this.maxRadians);
|
||||||
},
|
},
|
||||||
valueRadians() {
|
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() {
|
minX() {
|
||||||
return this.midX + Math.cos(this.minRadians) * this.radius;
|
return this.midX + Math.cos(this.minRadians) * this.radius;
|
||||||
|
@ -216,9 +220,9 @@ export default {
|
||||||
},
|
},
|
||||||
valueToDisplay() {
|
valueToDisplay() {
|
||||||
if (typeof this.valueTemplate === 'string') {
|
if (typeof this.valueTemplate === 'string') {
|
||||||
return this.valueTemplate.replace(/{value}/g, this.modelValue);
|
return this.valueTemplate.replace(/{value}/g, this.d_value);
|
||||||
} else {
|
} else {
|
||||||
return this.valueTemplate(this.modelValue);
|
return this.valueTemplate(this.d_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,13 @@ const theme = ({ dt }) => `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const classes = {
|
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',
|
range: 'p-knob-range',
|
||||||
value: 'p-knob-value',
|
value: 'p-knob-value',
|
||||||
text: 'p-knob-text'
|
text: 'p-knob-text'
|
||||||
|
|
Loading…
Reference in New Issue