@vaadin/slider 25.1.0-alpha2 → 25.1.0-alpha4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -8
- package/src/styles/vaadin-slider-base-styles.js +45 -25
- package/src/vaadin-range-slider.d.ts +2 -1
- package/src/vaadin-range-slider.js +115 -79
- package/src/vaadin-slider-mixin.d.ts +2 -1
- package/src/vaadin-slider-mixin.js +41 -128
- package/src/vaadin-slider.d.ts +2 -1
- package/src/vaadin-slider.js +63 -16
- package/web-types.json +369 -1
- package/web-types.lit.json +141 -1
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
|
|
7
|
+
import { SlotStylesMixin } from '@vaadin/component-base/src/slot-styles-mixin.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @polymerMixin
|
|
10
11
|
* @mixes DisabledMixin
|
|
12
|
+
* @mixes SlotStylesMixin
|
|
11
13
|
*/
|
|
12
14
|
export const SliderMixin = (superClass) =>
|
|
13
|
-
class SliderMixinClass extends DisabledMixin(superClass) {
|
|
15
|
+
class SliderMixinClass extends SlotStylesMixin(DisabledMixin(superClass)) {
|
|
14
16
|
static get properties() {
|
|
15
17
|
return {
|
|
16
18
|
/**
|
|
@@ -56,17 +58,39 @@ export const SliderMixin = (superClass) =>
|
|
|
56
58
|
};
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
/** @protected */
|
|
62
|
+
get slotStyles() {
|
|
63
|
+
const tag = this.localName;
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
`
|
|
67
|
+
${tag} > input::-webkit-slider-runnable-track {
|
|
68
|
+
height: 100%;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
${tag} > input::-webkit-slider-thumb {
|
|
72
|
+
appearance: none;
|
|
73
|
+
width: var(--_thumb-width);
|
|
74
|
+
height: 100%;
|
|
75
|
+
/* iOS needs these */
|
|
76
|
+
background: transparent;
|
|
77
|
+
box-shadow: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
${tag} > input::-moz-range-thumb {
|
|
81
|
+
border: 0;
|
|
82
|
+
background: transparent;
|
|
83
|
+
width: var(--_thumb-width);
|
|
84
|
+
height: 100%;
|
|
85
|
+
}
|
|
86
|
+
`,
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
59
90
|
constructor() {
|
|
60
91
|
super();
|
|
61
92
|
|
|
62
|
-
this.__onPointerMove = this.__onPointerMove.bind(this);
|
|
63
|
-
this.__onPointerUp = this.__onPointerUp.bind(this);
|
|
64
|
-
|
|
65
|
-
// Use separate mousedown listener for focusing the input, as
|
|
66
|
-
// pointerdown fires too early and the global `keyboardActive`
|
|
67
|
-
// flag isn't updated yet, which incorrectly shows focus-ring
|
|
68
93
|
this.addEventListener('mousedown', (e) => this.__onMouseDown(e));
|
|
69
|
-
this.addEventListener('pointerdown', (e) => this.__onPointerDown(e));
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
/** @protected */
|
|
@@ -76,14 +100,6 @@ export const SliderMixin = (superClass) =>
|
|
|
76
100
|
this.__lastCommittedValue = this.value;
|
|
77
101
|
}
|
|
78
102
|
|
|
79
|
-
/**
|
|
80
|
-
* @param {Event} event
|
|
81
|
-
* @return {number}
|
|
82
|
-
*/
|
|
83
|
-
__getThumbIndex(_event) {
|
|
84
|
-
return 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
103
|
/**
|
|
88
104
|
* @param {number} value
|
|
89
105
|
* @param {number} index
|
|
@@ -102,7 +118,9 @@ export const SliderMixin = (superClass) =>
|
|
|
102
118
|
const nearestOffset = Math.round(offset / step) * step;
|
|
103
119
|
const nearestValue = minValue + nearestOffset;
|
|
104
120
|
|
|
105
|
-
|
|
121
|
+
// Ensure the last value matching step is used below the max limit.
|
|
122
|
+
// Example: max = 100, step = 1.5 - force maximum allowed value to 99.
|
|
123
|
+
const newValue = nearestValue <= maxValue ? nearestValue : nearestValue - step;
|
|
106
124
|
|
|
107
125
|
this.__value = fullValue.with(index, newValue);
|
|
108
126
|
}
|
|
@@ -126,39 +144,8 @@ export const SliderMixin = (superClass) =>
|
|
|
126
144
|
*/
|
|
127
145
|
__getPercentFromValue(value) {
|
|
128
146
|
const { min, max } = this.__getConstraints();
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* @param {number} percent
|
|
134
|
-
* @return {number}
|
|
135
|
-
* @private
|
|
136
|
-
*/
|
|
137
|
-
__getValueFromPercent(percent) {
|
|
138
|
-
const { min, max } = this.__getConstraints();
|
|
139
|
-
return min + percent * (max - min);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @param {PointerEvent} event
|
|
144
|
-
* @return {number}
|
|
145
|
-
* @private
|
|
146
|
-
*/
|
|
147
|
-
__getEventPercent(event) {
|
|
148
|
-
const offset = event.offsetX;
|
|
149
|
-
const size = this.offsetWidth;
|
|
150
|
-
const safeOffset = Math.min(Math.max(offset, 0), size);
|
|
151
|
-
return safeOffset / size;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @param {PointerEvent} event
|
|
156
|
-
* @return {number}
|
|
157
|
-
* @private
|
|
158
|
-
*/
|
|
159
|
-
__getEventValue(event) {
|
|
160
|
-
const percent = this.__getEventPercent(event);
|
|
161
|
-
return this.__getValueFromPercent(percent);
|
|
147
|
+
const safeValue = Math.min(Math.max(value, min), max);
|
|
148
|
+
return (safeValue - min) / (max - min);
|
|
162
149
|
}
|
|
163
150
|
|
|
164
151
|
/**
|
|
@@ -166,80 +153,16 @@ export const SliderMixin = (superClass) =>
|
|
|
166
153
|
* @private
|
|
167
154
|
*/
|
|
168
155
|
__onMouseDown(event) {
|
|
169
|
-
|
|
170
|
-
if (!part || (!part.startsWith('track') && !part.startsWith('thumb'))) {
|
|
156
|
+
if (!event.composedPath().includes(this.$.controls)) {
|
|
171
157
|
return;
|
|
172
158
|
}
|
|
173
159
|
|
|
174
|
-
// Prevent
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
this.__focusInput(event);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* @param {PointerEvent} event
|
|
182
|
-
* @private
|
|
183
|
-
*/
|
|
184
|
-
__onPointerDown(event) {
|
|
185
|
-
if (this.disabled || this.readonly || event.button !== 0) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Only handle pointerdown on the thumb, track or track-fill
|
|
190
|
-
const part = event.composedPath()[0].getAttribute('part');
|
|
191
|
-
if (!part || (!part.startsWith('track') && !part.startsWith('thumb'))) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
this.setPointerCapture(event.pointerId);
|
|
196
|
-
this.addEventListener('pointermove', this.__onPointerMove);
|
|
197
|
-
this.addEventListener('pointerup', this.__onPointerUp);
|
|
198
|
-
this.addEventListener('pointercancel', this.__onPointerUp);
|
|
199
|
-
|
|
200
|
-
this.__thumbIndex = this.__getThumbIndex(event);
|
|
201
|
-
|
|
202
|
-
// Update value on track click
|
|
203
|
-
if (part.startsWith('track')) {
|
|
204
|
-
const newValue = this.__getEventValue(event);
|
|
205
|
-
this.__updateValue(newValue, this.__thumbIndex);
|
|
206
|
-
this.__commitValue();
|
|
160
|
+
// Prevent modifying value when readonly
|
|
161
|
+
if (this.readonly) {
|
|
162
|
+
event.preventDefault();
|
|
207
163
|
}
|
|
208
164
|
}
|
|
209
165
|
|
|
210
|
-
/**
|
|
211
|
-
* @param {PointerEvent} event
|
|
212
|
-
* @private
|
|
213
|
-
*/
|
|
214
|
-
__onPointerMove(event) {
|
|
215
|
-
const newValue = this.__getEventValue(event);
|
|
216
|
-
this.__updateValue(newValue, this.__thumbIndex);
|
|
217
|
-
this.__commitValue();
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* @param {PointerEvent} event
|
|
222
|
-
* @private
|
|
223
|
-
*/
|
|
224
|
-
__onPointerUp(event) {
|
|
225
|
-
this.__thumbIndex = null;
|
|
226
|
-
|
|
227
|
-
this.releasePointerCapture(event.pointerId);
|
|
228
|
-
this.removeEventListener('pointermove', this.__onPointerMove);
|
|
229
|
-
this.removeEventListener('pointerup', this.__onPointerUp);
|
|
230
|
-
this.removeEventListener('pointercancel', this.__onPointerUp);
|
|
231
|
-
|
|
232
|
-
this.__detectAndDispatchChange();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* @param {Event} event
|
|
237
|
-
* @private
|
|
238
|
-
*/
|
|
239
|
-
__focusInput(_event) {
|
|
240
|
-
this.focus({ focusVisible: false });
|
|
241
|
-
}
|
|
242
|
-
|
|
243
166
|
/** @private */
|
|
244
167
|
__detectAndDispatchChange() {
|
|
245
168
|
if (JSON.stringify(this.__lastCommittedValue) !== JSON.stringify(this.value)) {
|
|
@@ -248,16 +171,6 @@ export const SliderMixin = (superClass) =>
|
|
|
248
171
|
}
|
|
249
172
|
}
|
|
250
173
|
|
|
251
|
-
/**
|
|
252
|
-
* @param {Event} event
|
|
253
|
-
* @private
|
|
254
|
-
*/
|
|
255
|
-
__onInput(event) {
|
|
256
|
-
const index = this.__getThumbIndex(event);
|
|
257
|
-
this.__updateValue(event.target.value, index);
|
|
258
|
-
this.__commitValue();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
174
|
/**
|
|
262
175
|
* @param {Event} event
|
|
263
176
|
* @private
|
package/src/vaadin-slider.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
7
7
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
8
|
+
import { FieldMixin } from '@vaadin/field-base/src/field-mixin.js';
|
|
8
9
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
9
10
|
import { SliderMixin } from './vaadin-slider-mixin.js';
|
|
10
11
|
|
|
@@ -39,7 +40,7 @@ export interface SliderEventMap extends HTMLElementEventMap, SliderCustomEventMa
|
|
|
39
40
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
40
41
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
41
42
|
*/
|
|
42
|
-
declare class Slider extends SliderMixin(FocusMixin(ThemableMixin(ElementMixin(HTMLElement)))) {
|
|
43
|
+
declare class Slider extends FieldMixin(SliderMixin(FocusMixin(ThemableMixin(ElementMixin(HTMLElement))))) {
|
|
43
44
|
/**
|
|
44
45
|
* The value of the slider.
|
|
45
46
|
*/
|
package/src/vaadin-slider.js
CHANGED
|
@@ -10,6 +10,8 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
|
10
10
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
11
11
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
12
12
|
import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
|
|
13
|
+
import { FieldMixin } from '@vaadin/field-base/src/field-mixin.js';
|
|
14
|
+
import { field } from '@vaadin/field-base/src/styles/field-base-styles.js';
|
|
13
15
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
14
16
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
15
17
|
import { sliderStyles } from './styles/vaadin-slider-base-styles.js';
|
|
@@ -29,12 +31,13 @@ import { SliderMixin } from './vaadin-slider-mixin.js';
|
|
|
29
31
|
* @customElement
|
|
30
32
|
* @extends HTMLElement
|
|
31
33
|
* @mixes ElementMixin
|
|
34
|
+
* @mixes FieldMixin
|
|
32
35
|
* @mixes FocusMixin
|
|
33
36
|
* @mixes SliderMixin
|
|
34
37
|
* @mixes ThemableMixin
|
|
35
38
|
*/
|
|
36
|
-
class Slider extends
|
|
37
|
-
FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))),
|
|
39
|
+
class Slider extends FieldMixin(
|
|
40
|
+
SliderMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))))),
|
|
38
41
|
) {
|
|
39
42
|
static get is() {
|
|
40
43
|
return 'vaadin-slider';
|
|
@@ -42,15 +45,27 @@ class Slider extends SliderMixin(
|
|
|
42
45
|
|
|
43
46
|
static get styles() {
|
|
44
47
|
return [
|
|
48
|
+
field,
|
|
45
49
|
sliderStyles,
|
|
46
50
|
css`
|
|
47
51
|
:host([focus-ring]) [part='thumb'] {
|
|
48
|
-
outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
|
|
52
|
+
outline: var(--vaadin-focus-ring-width) var(--_outline-style, solid) var(--vaadin-focus-ring-color);
|
|
49
53
|
outline-offset: 1px;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
#controls {
|
|
57
|
+
grid-template-columns:
|
|
58
|
+
[track-start fill-start]
|
|
59
|
+
calc(var(--value) * var(--_track-width))
|
|
60
|
+
[fill-end thumb1]
|
|
61
|
+
var(--_thumb-width)
|
|
62
|
+
calc((1 - var(--value)) * var(--_track-width))
|
|
63
|
+
[track-end];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[part='track-fill'] {
|
|
67
|
+
border-start-start-radius: inherit;
|
|
68
|
+
border-end-start-radius: inherit;
|
|
54
69
|
}
|
|
55
70
|
`,
|
|
56
71
|
];
|
|
@@ -60,6 +75,10 @@ class Slider extends SliderMixin(
|
|
|
60
75
|
return 'sliderComponent';
|
|
61
76
|
}
|
|
62
77
|
|
|
78
|
+
static get lumoInjector() {
|
|
79
|
+
return { ...super.lumoInjector, includeBaseStyles: true };
|
|
80
|
+
}
|
|
81
|
+
|
|
63
82
|
static get properties() {
|
|
64
83
|
return {
|
|
65
84
|
/**
|
|
@@ -80,17 +99,28 @@ class Slider extends SliderMixin(
|
|
|
80
99
|
const percent = this.__getPercentFromValue(value);
|
|
81
100
|
|
|
82
101
|
return html`
|
|
83
|
-
<div
|
|
84
|
-
<div
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
<div class="vaadin-slider-container">
|
|
103
|
+
<div part="label" @click="${this.focus}">
|
|
104
|
+
<slot name="label"></slot>
|
|
105
|
+
<span part="required-indicator" aria-hidden="true"></span>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div id="controls" style="${styleMap({ '--value': percent })}">
|
|
109
|
+
<div part="track">
|
|
110
|
+
<div part="track-fill"></div>
|
|
111
|
+
</div>
|
|
112
|
+
<div part="thumb"></div>
|
|
113
|
+
<slot name="input"></slot>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div part="helper-text">
|
|
117
|
+
<slot name="helper"></slot>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div part="error-message">
|
|
121
|
+
<slot name="error-message"></slot>
|
|
122
|
+
</div>
|
|
91
123
|
</div>
|
|
92
|
-
<div part="thumb" style="${styleMap({ insetInlineStart: `${percent}%` })}"></div>
|
|
93
|
-
<slot name="input"></slot>
|
|
94
124
|
`;
|
|
95
125
|
}
|
|
96
126
|
|
|
@@ -107,6 +137,7 @@ class Slider extends SliderMixin(
|
|
|
107
137
|
|
|
108
138
|
const input = this.querySelector('[slot="input"]');
|
|
109
139
|
this._inputElement = input;
|
|
140
|
+
this.ariaTarget = input;
|
|
110
141
|
}
|
|
111
142
|
|
|
112
143
|
/**
|
|
@@ -146,7 +177,7 @@ class Slider extends SliderMixin(
|
|
|
146
177
|
updated(props) {
|
|
147
178
|
super.updated(props);
|
|
148
179
|
|
|
149
|
-
if (props.has('value') || props.has('min') || props.has('max')) {
|
|
180
|
+
if (props.has('value') || props.has('min') || props.has('max') || props.has('step')) {
|
|
150
181
|
this.__updateValue(this.value);
|
|
151
182
|
}
|
|
152
183
|
}
|
|
@@ -168,6 +199,16 @@ class Slider extends SliderMixin(
|
|
|
168
199
|
super.focus(options);
|
|
169
200
|
}
|
|
170
201
|
|
|
202
|
+
/**
|
|
203
|
+
* @protected
|
|
204
|
+
* @override
|
|
205
|
+
*/
|
|
206
|
+
blur() {
|
|
207
|
+
if (this._inputElement) {
|
|
208
|
+
this._inputElement.blur();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
171
212
|
/**
|
|
172
213
|
* @private
|
|
173
214
|
* @override
|
|
@@ -176,6 +217,12 @@ class Slider extends SliderMixin(
|
|
|
176
217
|
this.value = this.__value[0];
|
|
177
218
|
}
|
|
178
219
|
|
|
220
|
+
/** @private */
|
|
221
|
+
__onInput(event) {
|
|
222
|
+
this.__updateValue(event.target.value, 0);
|
|
223
|
+
this.__commitValue();
|
|
224
|
+
}
|
|
225
|
+
|
|
179
226
|
/** @private */
|
|
180
227
|
__onKeyDown(event) {
|
|
181
228
|
const arrowKeys = ['ArrowLeft', 'ArrowDown', 'ArrowRight', 'ArrowUp'];
|