mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 16:56:35 +00:00
Reduce sensitivity of the circular slider on touch devices (#18921)
This commit is contained in:
parent
15becf9ef6
commit
b4ab0fc10b
@ -2,6 +2,7 @@ import {
|
|||||||
DIRECTION_ALL,
|
DIRECTION_ALL,
|
||||||
Manager,
|
Manager,
|
||||||
Pan,
|
Pan,
|
||||||
|
Press,
|
||||||
Tap,
|
Tap,
|
||||||
TouchMouseInput,
|
TouchMouseInput,
|
||||||
} from "@egjs/hammerjs";
|
} from "@egjs/hammerjs";
|
||||||
@ -108,6 +109,9 @@ export class HaControlCircularSlider extends LitElement {
|
|||||||
@property({ type: Number })
|
@property({ type: Number })
|
||||||
public max = 100;
|
public max = 100;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "prevent-interaction-on-scroll" })
|
||||||
|
public preventInteractionOnScroll?: boolean;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
public _localValue?: number = this.value;
|
public _localValue?: number = this.value;
|
||||||
|
|
||||||
@ -246,16 +250,62 @@ export class HaControlCircularSlider extends LitElement {
|
|||||||
this._mc = new Manager(this._interaction, {
|
this._mc = new Manager(this._interaction, {
|
||||||
inputClass: TouchMouseInput,
|
inputClass: TouchMouseInput,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const pressToActivate =
|
||||||
|
this.preventInteractionOnScroll && "ontouchstart" in window;
|
||||||
|
|
||||||
|
// If press to activate is true, a 60ms press is required to activate the slider
|
||||||
this._mc.add(
|
this._mc.add(
|
||||||
new Pan({
|
new Press({
|
||||||
direction: DIRECTION_ALL,
|
enable: pressToActivate,
|
||||||
enable: true,
|
pointers: 1,
|
||||||
threshold: 0,
|
time: 60,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const panRecognizer = new Pan({
|
||||||
|
direction: DIRECTION_ALL,
|
||||||
|
enable: !pressToActivate,
|
||||||
|
threshold: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
this._mc.add(panRecognizer);
|
||||||
|
|
||||||
this._mc.add(new Tap({ event: "singletap" }));
|
this._mc.add(new Tap({ event: "singletap" }));
|
||||||
|
|
||||||
|
this._mc.on("press", (e) => {
|
||||||
|
e.srcEvent.stopPropagation();
|
||||||
|
e.srcEvent.preventDefault();
|
||||||
|
if (this.disabled || this.readonly) return;
|
||||||
|
const percentage = this._getPercentageFromEvent(e);
|
||||||
|
const raw = this._percentageToValue(percentage);
|
||||||
|
this._activeSlider = this._findActiveSlider(raw);
|
||||||
|
const bounded = this._boundedValue(raw);
|
||||||
|
this._setActiveValue(bounded);
|
||||||
|
const stepped = this._steppedValue(bounded);
|
||||||
|
if (this._activeSlider) {
|
||||||
|
fireEvent(this, `${this._activeSlider}-changing`, { value: stepped });
|
||||||
|
}
|
||||||
|
panRecognizer.set({ enable: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
this._mc.on("pressup", (e) => {
|
||||||
|
e.srcEvent.stopPropagation();
|
||||||
|
e.srcEvent.preventDefault();
|
||||||
|
const percentage = this._getPercentageFromEvent(e);
|
||||||
|
const raw = this._percentageToValue(percentage);
|
||||||
|
const bounded = this._boundedValue(raw);
|
||||||
|
const stepped = this._steppedValue(bounded);
|
||||||
|
this._setActiveValue(stepped);
|
||||||
|
if (this._activeSlider) {
|
||||||
|
fireEvent(this, `${this._activeSlider}-changing`, {
|
||||||
|
value: undefined,
|
||||||
|
});
|
||||||
|
fireEvent(this, `${this._activeSlider}-changed`, { value: stepped });
|
||||||
|
}
|
||||||
|
this._activeSlider = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
this._mc.on("pan", (e) => {
|
this._mc.on("pan", (e) => {
|
||||||
e.srcEvent.stopPropagation();
|
e.srcEvent.stopPropagation();
|
||||||
e.srcEvent.preventDefault();
|
e.srcEvent.preventDefault();
|
||||||
@ -271,6 +321,9 @@ export class HaControlCircularSlider extends LitElement {
|
|||||||
this._mc.on("pancancel", () => {
|
this._mc.on("pancancel", () => {
|
||||||
if (this.disabled || this.readonly) return;
|
if (this.disabled || this.readonly) return;
|
||||||
this._activeSlider = undefined;
|
this._activeSlider = undefined;
|
||||||
|
if (pressToActivate) {
|
||||||
|
panRecognizer.set({ enable: false });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this._mc.on("panmove", (e) => {
|
this._mc.on("panmove", (e) => {
|
||||||
if (this.disabled || this.readonly) return;
|
if (this.disabled || this.readonly) return;
|
||||||
@ -297,6 +350,9 @@ export class HaControlCircularSlider extends LitElement {
|
|||||||
fireEvent(this, `${this._activeSlider}-changed`, { value: stepped });
|
fireEvent(this, `${this._activeSlider}-changed`, { value: stepped });
|
||||||
}
|
}
|
||||||
this._activeSlider = undefined;
|
this._activeSlider = undefined;
|
||||||
|
if (pressToActivate) {
|
||||||
|
panRecognizer.set({ enable: false });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this._mc.on("singletap", (e) => {
|
this._mc.on("singletap", (e) => {
|
||||||
if (this.disabled || this.readonly) return;
|
if (this.disabled || this.readonly) return;
|
||||||
@ -315,6 +371,9 @@ export class HaControlCircularSlider extends LitElement {
|
|||||||
this._lastSlider = this._activeSlider;
|
this._lastSlider = this._activeSlider;
|
||||||
this.shadowRoot?.getElementById("#slider")?.focus();
|
this.shadowRoot?.getElementById("#slider")?.focus();
|
||||||
this._activeSlider = undefined;
|
this._activeSlider = undefined;
|
||||||
|
if (pressToActivate) {
|
||||||
|
panRecognizer.set({ enable: false });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {
|
|||||||
<ha-card>
|
<ha-card>
|
||||||
<p class="title">${name}</p>
|
<p class="title">${name}</p>
|
||||||
<ha-state-control-humidifier-humidity
|
<ha-state-control-humidifier-humidity
|
||||||
|
prevent-interaction-on-scroll
|
||||||
show-current
|
show-current
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
@ -183,7 +184,6 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {
|
|||||||
max-width: 344px; /* 12px + 12px + 320px */
|
max-width: 344px; /* 12px + 12px + 320px */
|
||||||
padding: 0 12px 12px 12px;
|
padding: 0 12px 12px 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
--interaction-margin: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.more-info {
|
.more-info {
|
||||||
|
@ -119,6 +119,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
<ha-card>
|
<ha-card>
|
||||||
<p class="title">${name}</p>
|
<p class="title">${name}</p>
|
||||||
<ha-state-control-climate-temperature
|
<ha-state-control-climate-temperature
|
||||||
|
prevent-interaction-on-scroll
|
||||||
show-current
|
show-current
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
@ -175,7 +176,6 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
max-width: 344px; /* 12px + 12px + 320px */
|
max-width: 344px; /* 12px + 12px + 320px */
|
||||||
padding: 0 12px 12px 12px;
|
padding: 0 12px 12px 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
--interaction-margin: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.more-info {
|
.more-info {
|
||||||
|
@ -30,6 +30,9 @@ export class HaStateControlClimateHumidity extends LitElement {
|
|||||||
@property({ attribute: "show-current", type: Boolean })
|
@property({ attribute: "show-current", type: Boolean })
|
||||||
public showCurrent?: boolean;
|
public showCurrent?: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "prevent-interaction-on-scroll" })
|
||||||
|
public preventInteractionOnScroll?: boolean;
|
||||||
|
|
||||||
@state() private _targetHumidity?: number;
|
@state() private _targetHumidity?: number;
|
||||||
|
|
||||||
private _sizeController = createStateControlCircularSliderController(this);
|
private _sizeController = createStateControlCircularSliderController(this);
|
||||||
@ -192,6 +195,7 @@ export class HaStateControlClimateHumidity extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.inactive=${!active}
|
.inactive=${!active}
|
||||||
.value=${this._targetHumidity}
|
.value=${this._targetHumidity}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
@ -216,6 +220,7 @@ export class HaStateControlClimateHumidity extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="container${classMap(containerSizeClass)}">
|
<div class="container${classMap(containerSizeClass)}">
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.current=${this.stateObj.attributes.current_humidity}
|
.current=${this.stateObj.attributes.current_humidity}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
.max=${this._max}
|
.max=${this._max}
|
||||||
|
@ -48,6 +48,9 @@ export class HaStateControlClimateTemperature extends LitElement {
|
|||||||
@property({ attribute: "show-current", type: Boolean })
|
@property({ attribute: "show-current", type: Boolean })
|
||||||
public showCurrent?: boolean;
|
public showCurrent?: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "prevent-interaction-on-scroll" })
|
||||||
|
public preventInteractionOnScroll?: boolean;
|
||||||
|
|
||||||
@state() private _targetTemperature: Partial<Record<Target, number>> = {};
|
@state() private _targetTemperature: Partial<Record<Target, number>> = {};
|
||||||
|
|
||||||
@state() private _selectTargetTemperature: Target = "low";
|
@state() private _selectTargetTemperature: Target = "low";
|
||||||
@ -318,6 +321,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.inactive=${!active}
|
.inactive=${!active}
|
||||||
.mode=${sliderMode}
|
.mode=${sliderMode}
|
||||||
.value=${this._targetTemperature.value}
|
.value=${this._targetTemperature.value}
|
||||||
@ -357,6 +361,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.inactive=${!active}
|
.inactive=${!active}
|
||||||
dual
|
dual
|
||||||
.low=${this._targetTemperature.low}
|
.low=${this._targetTemperature.low}
|
||||||
@ -412,6 +417,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
mode="full"
|
mode="full"
|
||||||
.current=${this.stateObj.attributes.current_temperature}
|
.current=${this.stateObj.attributes.current_temperature}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
|
@ -32,6 +32,9 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
|||||||
@property({ attribute: "show-current", type: Boolean })
|
@property({ attribute: "show-current", type: Boolean })
|
||||||
public showCurrent?: boolean = false;
|
public showCurrent?: boolean = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "prevent-interaction-on-scroll" })
|
||||||
|
public preventInteractionOnScroll?: boolean;
|
||||||
|
|
||||||
@state() private _targetHumidity?: number;
|
@state() private _targetHumidity?: number;
|
||||||
|
|
||||||
private _sizeController = createStateControlCircularSliderController(this);
|
private _sizeController = createStateControlCircularSliderController(this);
|
||||||
@ -202,6 +205,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.inactive=${!active}
|
.inactive=${!active}
|
||||||
.mode=${inverted ? "end" : "start"}
|
.mode=${inverted ? "end" : "start"}
|
||||||
.value=${targetHumidity}
|
.value=${targetHumidity}
|
||||||
@ -232,6 +236,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.current=${currentHumidity}
|
.current=${currentHumidity}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
.max=${this._max}
|
.max=${this._max}
|
||||||
|
@ -121,10 +121,6 @@ export const stateControlCircularSliderStyle = css`
|
|||||||
ha-control-circular-slider {
|
ha-control-circular-slider {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
--control-circular-slider-color: var(--state-color, var(--disabled-color));
|
--control-circular-slider-color: var(--state-color, var(--disabled-color));
|
||||||
--control-circular-slider-interaction-margin: var(
|
|
||||||
--interaction-margin,
|
|
||||||
12px
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
ha-control-circular-slider::after {
|
ha-control-circular-slider::after {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -33,6 +33,9 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
|
|||||||
@property({ attribute: "show-current", type: Boolean })
|
@property({ attribute: "show-current", type: Boolean })
|
||||||
public showCurrent?: boolean;
|
public showCurrent?: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "prevent-interaction-on-scroll" })
|
||||||
|
public preventInteractionOnScroll?: boolean;
|
||||||
|
|
||||||
@state() private _targetTemperature?: number;
|
@state() private _targetTemperature?: number;
|
||||||
|
|
||||||
private _sizeController = createStateControlCircularSliderController(this);
|
private _sizeController = createStateControlCircularSliderController(this);
|
||||||
@ -197,6 +200,7 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
.inactive=${!active}
|
.inactive=${!active}
|
||||||
.value=${this._targetTemperature}
|
.value=${this._targetTemperature}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
@ -227,6 +231,7 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-control-circular-slider
|
<ha-control-circular-slider
|
||||||
|
.preventInteractionOnScroll=${this.preventInteractionOnScroll}
|
||||||
mode="full"
|
mode="full"
|
||||||
.current=${this.stateObj.attributes.current_temperature}
|
.current=${this.stateObj.attributes.current_temperature}
|
||||||
.min=${this._min}
|
.min=${this._min}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user