@vaadin/number-field 24.0.0-alpha9 → 24.0.0-beta2
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 +13 -9
- package/src/vaadin-number-field-mixin.d.ts +65 -0
- package/src/vaadin-number-field-mixin.js +342 -0
- package/src/vaadin-number-field-styles.d.ts +8 -0
- package/src/vaadin-number-field-styles.js +31 -0
- package/src/vaadin-number-field.d.ts +2 -22
- package/src/vaadin-number-field.js +13 -345
- package/theme/lumo/vaadin-number-field-styles.js +0 -4
- package/theme/material/vaadin-number-field-styles.js +0 -4
- package/web-types.json +40 -40
- package/web-types.lit.json +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/number-field",
|
|
3
|
-
"version": "24.0.0-
|
|
3
|
+
"version": "24.0.0-beta2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
"type": "module",
|
|
22
22
|
"files": [
|
|
23
23
|
"src",
|
|
24
|
+
"!src/vaadin-lit-number-field.d.ts",
|
|
25
|
+
"!src/vaadin-lit-number-field.js",
|
|
24
26
|
"theme",
|
|
25
27
|
"vaadin-*.d.ts",
|
|
26
28
|
"vaadin-*.js",
|
|
@@ -34,22 +36,24 @@
|
|
|
34
36
|
"web-component"
|
|
35
37
|
],
|
|
36
38
|
"dependencies": {
|
|
39
|
+
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
40
|
"@polymer/polymer": "^3.0.0",
|
|
38
|
-
"@vaadin/component-base": "24.0.0-
|
|
39
|
-
"@vaadin/field-base": "24.0.0-
|
|
40
|
-
"@vaadin/input-container": "24.0.0-
|
|
41
|
-
"@vaadin/vaadin-lumo-styles": "24.0.0-
|
|
42
|
-
"@vaadin/vaadin-material-styles": "24.0.0-
|
|
43
|
-
"@vaadin/vaadin-themable-mixin": "24.0.0-
|
|
41
|
+
"@vaadin/component-base": "24.0.0-beta2",
|
|
42
|
+
"@vaadin/field-base": "24.0.0-beta2",
|
|
43
|
+
"@vaadin/input-container": "24.0.0-beta2",
|
|
44
|
+
"@vaadin/vaadin-lumo-styles": "24.0.0-beta2",
|
|
45
|
+
"@vaadin/vaadin-material-styles": "24.0.0-beta2",
|
|
46
|
+
"@vaadin/vaadin-themable-mixin": "24.0.0-beta2",
|
|
47
|
+
"lit": "^2.0.0"
|
|
44
48
|
},
|
|
45
49
|
"devDependencies": {
|
|
46
50
|
"@esm-bundle/chai": "^4.3.4",
|
|
47
|
-
"@vaadin/testing-helpers": "^0.
|
|
51
|
+
"@vaadin/testing-helpers": "^0.4.0",
|
|
48
52
|
"sinon": "^13.0.2"
|
|
49
53
|
},
|
|
50
54
|
"web-types": [
|
|
51
55
|
"web-types.json",
|
|
52
56
|
"web-types.lit.json"
|
|
53
57
|
],
|
|
54
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "00086f1f6d487f042f189c9b9ecd7ba736960888"
|
|
55
59
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
+
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
8
|
+
import type { DelegateFocusMixinClass } from '@vaadin/component-base/src/delegate-focus-mixin.js';
|
|
9
|
+
import type { DelegateStateMixinClass } from '@vaadin/component-base/src/delegate-state-mixin.js';
|
|
10
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
11
|
+
import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
12
|
+
import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
13
|
+
import type { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
|
|
14
|
+
import type { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
15
|
+
import type { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
16
|
+
import type { InputFieldMixinClass } from '@vaadin/field-base/src/input-field-mixin.js';
|
|
17
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
18
|
+
import type { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
19
|
+
import type { SlotStylesMixinClass } from '@vaadin/field-base/src/slot-styles-mixin.js';
|
|
20
|
+
import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A mixin providing common number field functionality.
|
|
24
|
+
*/
|
|
25
|
+
export declare function NumberFieldMixin<T extends Constructor<HTMLElement>>(
|
|
26
|
+
base: T,
|
|
27
|
+
): Constructor<ControllerMixinClass> &
|
|
28
|
+
Constructor<DelegateFocusMixinClass> &
|
|
29
|
+
Constructor<DelegateStateMixinClass> &
|
|
30
|
+
Constructor<DisabledMixinClass> &
|
|
31
|
+
Constructor<FieldMixinClass> &
|
|
32
|
+
Constructor<FocusMixinClass> &
|
|
33
|
+
Constructor<InputConstraintsMixinClass> &
|
|
34
|
+
Constructor<InputControlMixinClass> &
|
|
35
|
+
Constructor<InputFieldMixinClass> &
|
|
36
|
+
Constructor<InputMixinClass> &
|
|
37
|
+
Constructor<KeyboardMixinClass> &
|
|
38
|
+
Constructor<LabelMixinClass> &
|
|
39
|
+
Constructor<NumberFieldMixinClass> &
|
|
40
|
+
Constructor<SlotStylesMixinClass> &
|
|
41
|
+
Constructor<ValidateMixinClass> &
|
|
42
|
+
T;
|
|
43
|
+
|
|
44
|
+
export declare class NumberFieldMixinClass {
|
|
45
|
+
/**
|
|
46
|
+
* The minimum value of the field.
|
|
47
|
+
*/
|
|
48
|
+
min: number | null | undefined;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The maximum value of the field.
|
|
52
|
+
*/
|
|
53
|
+
max: number | null | undefined;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Specifies the allowed number intervals of the field.
|
|
57
|
+
*/
|
|
58
|
+
step: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Set to true to show increase/decrease buttons.
|
|
62
|
+
* @attr {boolean} step-buttons-visible
|
|
63
|
+
*/
|
|
64
|
+
stepButtonsVisible: boolean;
|
|
65
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { InputController } from '@vaadin/field-base/src/input-controller.js';
|
|
7
|
+
import { InputFieldMixin } from '@vaadin/field-base/src/input-field-mixin.js';
|
|
8
|
+
import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-controller.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A mixin providing common number field functionality.
|
|
12
|
+
*
|
|
13
|
+
* @polymerMixin
|
|
14
|
+
* @mixes InputFieldMixin
|
|
15
|
+
*/
|
|
16
|
+
export const NumberFieldMixin = (superClass) =>
|
|
17
|
+
class NumberFieldMixinClass extends InputFieldMixin(superClass) {
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* The minimum value of the field.
|
|
22
|
+
*/
|
|
23
|
+
min: {
|
|
24
|
+
type: Number,
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The maximum value of the field.
|
|
29
|
+
*/
|
|
30
|
+
max: {
|
|
31
|
+
type: Number,
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Specifies the allowed number intervals of the field.
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
step: {
|
|
39
|
+
type: Number,
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Set to true to show increase/decrease buttons.
|
|
44
|
+
* @attr {boolean} step-buttons-visible
|
|
45
|
+
*/
|
|
46
|
+
stepButtonsVisible: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
value: false,
|
|
49
|
+
reflectToAttribute: true,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static get observers() {
|
|
55
|
+
return ['_stepChanged(step, inputElement)'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static get delegateProps() {
|
|
59
|
+
return [...super.delegateProps, 'min', 'max'];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static get constraints() {
|
|
63
|
+
return [...super.constraints, 'min', 'max', 'step'];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
constructor() {
|
|
67
|
+
super();
|
|
68
|
+
this._setType('number');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** @protected */
|
|
72
|
+
get slotStyles() {
|
|
73
|
+
const tag = this.localName;
|
|
74
|
+
return [
|
|
75
|
+
`
|
|
76
|
+
${tag} input[type="number"]::-webkit-outer-spin-button,
|
|
77
|
+
${tag} input[type="number"]::-webkit-inner-spin-button {
|
|
78
|
+
-webkit-appearance: none;
|
|
79
|
+
margin: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
${tag} input[type="number"] {
|
|
83
|
+
-moz-appearance: textfield;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
${tag}[dir='rtl'] input[type="number"]::placeholder {
|
|
87
|
+
direction: rtl;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
${tag}[dir='rtl']:not([step-buttons-visible]) input[type="number"]::placeholder {
|
|
91
|
+
text-align: left;
|
|
92
|
+
}
|
|
93
|
+
`,
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Used by `InputControlMixin` as a reference to the clear button element.
|
|
99
|
+
* @protected
|
|
100
|
+
*/
|
|
101
|
+
get clearElement() {
|
|
102
|
+
return this.$.clearButton;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** @protected */
|
|
106
|
+
ready() {
|
|
107
|
+
super.ready();
|
|
108
|
+
|
|
109
|
+
this.addController(
|
|
110
|
+
new InputController(this, (input) => {
|
|
111
|
+
this._setInputElement(input);
|
|
112
|
+
this._setFocusElement(input);
|
|
113
|
+
this.stateTarget = input;
|
|
114
|
+
this.ariaTarget = input;
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
this.addController(new LabelledInputController(this.inputElement, this._labelController));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Override the method from `InputConstraintsMixin`
|
|
123
|
+
* to enforce HTML constraint validation even if
|
|
124
|
+
* the user didn't add any constraints explicitly:
|
|
125
|
+
* the field has to be regardless checked for bad input.
|
|
126
|
+
*
|
|
127
|
+
* @override
|
|
128
|
+
*/
|
|
129
|
+
checkValidity() {
|
|
130
|
+
if (this.inputElement) {
|
|
131
|
+
return this.inputElement.checkValidity();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return !this.invalid;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** @protected */
|
|
138
|
+
_onDecreaseButtonTouchend(e) {
|
|
139
|
+
// Cancel the following click and focus events
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
this._decreaseValue();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** @protected */
|
|
145
|
+
_onIncreaseButtonTouchend(e) {
|
|
146
|
+
// Cancel the following click and focus events
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
this._increaseValue();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** @protected */
|
|
152
|
+
_onDecreaseButtonClick() {
|
|
153
|
+
this._decreaseValue();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** @protected */
|
|
157
|
+
_onIncreaseButtonClick() {
|
|
158
|
+
this._increaseValue();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** @private */
|
|
162
|
+
_decreaseValue() {
|
|
163
|
+
this._incrementValue(-1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** @private */
|
|
167
|
+
_increaseValue() {
|
|
168
|
+
this._incrementValue(1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** @private */
|
|
172
|
+
_incrementValue(incr) {
|
|
173
|
+
if (this.disabled || this.readonly) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const step = this.step || 1;
|
|
178
|
+
let value = parseFloat(this.value);
|
|
179
|
+
|
|
180
|
+
if (!this.value) {
|
|
181
|
+
if ((this.min === 0 && incr < 0) || (this.max === 0 && incr > 0) || (this.max === 0 && this.min === 0)) {
|
|
182
|
+
incr = 0;
|
|
183
|
+
value = 0;
|
|
184
|
+
} else if ((this.max == null || this.max >= 0) && (this.min == null || this.min <= 0)) {
|
|
185
|
+
value = 0;
|
|
186
|
+
} else if (this.min > 0) {
|
|
187
|
+
value = this.min;
|
|
188
|
+
if (this.max < 0 && incr < 0) {
|
|
189
|
+
value = this.max;
|
|
190
|
+
}
|
|
191
|
+
incr = 0;
|
|
192
|
+
} else if (this.max < 0) {
|
|
193
|
+
value = this.max;
|
|
194
|
+
if (incr < 0) {
|
|
195
|
+
incr = 0;
|
|
196
|
+
} else if (this._getIncrement(1, value - step) > this.max) {
|
|
197
|
+
value -= 2 * step;
|
|
198
|
+
// FIXME(yuriy): find a proper solution to make correct step back
|
|
199
|
+
} else {
|
|
200
|
+
value -= step;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} else if (value < this.min) {
|
|
204
|
+
incr = 0;
|
|
205
|
+
value = this.min;
|
|
206
|
+
} else if (value > this.max) {
|
|
207
|
+
incr = 0;
|
|
208
|
+
value = this.max;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const newValue = this._getIncrement(incr, value);
|
|
212
|
+
if (!this.value || incr === 0 || this._incrementIsInsideTheLimits(incr, value)) {
|
|
213
|
+
this._setValue(newValue);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** @private */
|
|
218
|
+
_setValue(value) {
|
|
219
|
+
this.value = this.inputElement.value = String(parseFloat(value));
|
|
220
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** @private */
|
|
224
|
+
_getIncrement(incr, currentValue) {
|
|
225
|
+
let step = this.step || 1,
|
|
226
|
+
min = this.min || 0;
|
|
227
|
+
|
|
228
|
+
// To avoid problems with decimal math, multiplying to operate with integers.
|
|
229
|
+
const multiplier = Math.max(
|
|
230
|
+
this._getMultiplier(currentValue),
|
|
231
|
+
this._getMultiplier(step),
|
|
232
|
+
this._getMultiplier(min),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
step *= multiplier;
|
|
236
|
+
currentValue = Math.round(currentValue * multiplier);
|
|
237
|
+
min *= multiplier;
|
|
238
|
+
|
|
239
|
+
const margin = (currentValue - min) % step;
|
|
240
|
+
|
|
241
|
+
if (incr > 0) {
|
|
242
|
+
return (currentValue - margin + step) / multiplier;
|
|
243
|
+
} else if (incr < 0) {
|
|
244
|
+
return (currentValue - (margin || step)) / multiplier;
|
|
245
|
+
}
|
|
246
|
+
return currentValue / multiplier;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** @private */
|
|
250
|
+
_getDecimalCount(number) {
|
|
251
|
+
const s = String(number);
|
|
252
|
+
const i = s.indexOf('.');
|
|
253
|
+
return i === -1 ? 1 : s.length - i - 1;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** @private */
|
|
257
|
+
_getMultiplier(number) {
|
|
258
|
+
if (!isNaN(number)) {
|
|
259
|
+
return 10 ** this._getDecimalCount(number);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** @private */
|
|
264
|
+
_incrementIsInsideTheLimits(incr, value) {
|
|
265
|
+
if (incr < 0) {
|
|
266
|
+
return this.min == null || this._getIncrement(incr, value) >= this.min;
|
|
267
|
+
} else if (incr > 0) {
|
|
268
|
+
return this.max == null || this._getIncrement(incr, value) <= this.max;
|
|
269
|
+
}
|
|
270
|
+
return this._getIncrement(incr, value) <= this.max && this._getIncrement(incr, value) >= this.min;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** @protected */
|
|
274
|
+
_isButtonEnabled(sign) {
|
|
275
|
+
const incr = sign * (this.step || 1);
|
|
276
|
+
const value = parseFloat(this.value);
|
|
277
|
+
return !this.value || (!this.disabled && this._incrementIsInsideTheLimits(incr, value));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @param {number} step
|
|
282
|
+
* @param {HTMLElement | undefined} inputElement
|
|
283
|
+
* @protected
|
|
284
|
+
*/
|
|
285
|
+
_stepChanged(step, inputElement) {
|
|
286
|
+
if (inputElement) {
|
|
287
|
+
inputElement.step = step || 'any';
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @param {unknown} newVal
|
|
293
|
+
* @param {unknown} oldVal
|
|
294
|
+
* @protected
|
|
295
|
+
* @override
|
|
296
|
+
*/
|
|
297
|
+
_valueChanged(newVal, oldVal) {
|
|
298
|
+
// Validate value to be numeric
|
|
299
|
+
if (newVal && isNaN(parseFloat(newVal))) {
|
|
300
|
+
this.value = '';
|
|
301
|
+
} else if (typeof this.value !== 'string') {
|
|
302
|
+
this.value = String(this.value);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
super._valueChanged(this.value, oldVal);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Override an event listener from `InputControlMixin`
|
|
310
|
+
* to avoid adding a separate listener.
|
|
311
|
+
* @param {!KeyboardEvent} event
|
|
312
|
+
* @protected
|
|
313
|
+
* @override
|
|
314
|
+
*/
|
|
315
|
+
_onKeyDown(event) {
|
|
316
|
+
if (event.key === 'ArrowUp') {
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
this._increaseValue();
|
|
319
|
+
} else if (event.key === 'ArrowDown') {
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
this._decreaseValue();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
super._onKeyDown(event);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Native [type=number] inputs don't update their value
|
|
329
|
+
* when you are entering input that the browser is unable to parse
|
|
330
|
+
* e.g. "--5", hence we have to override this method from `InputMixin`
|
|
331
|
+
* so that, when value is empty, it would additionally check
|
|
332
|
+
* for bad input based on the native `validity.badInput` property.
|
|
333
|
+
*
|
|
334
|
+
* @param {InputEvent} event
|
|
335
|
+
* @protected
|
|
336
|
+
* @override
|
|
337
|
+
*/
|
|
338
|
+
_setHasInputValue(event) {
|
|
339
|
+
const target = event.composedPath()[0];
|
|
340
|
+
this._hasInputValue = target.value.length > 0 || target.validity.badInput;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
|
|
8
|
+
export const numberFieldStyles = css`
|
|
9
|
+
:host([readonly]) [part$='button'] {
|
|
10
|
+
pointer-events: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
[part='decrease-button']::before {
|
|
14
|
+
content: '\\2212';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[part='increase-button']::before {
|
|
18
|
+
content: '+';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
[part='decrease-button'],
|
|
22
|
+
[part='increase-button'] {
|
|
23
|
+
-webkit-user-select: none;
|
|
24
|
+
-moz-user-select: none;
|
|
25
|
+
user-select: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:host([dir='rtl']) [part='input-field'] {
|
|
29
|
+
direction: ltr;
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
7
7
|
import { InputFieldMixin } from '@vaadin/field-base/src/input-field-mixin.js';
|
|
8
8
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
9
|
+
import { NumberFieldMixin } from './vaadin-number-field-mixin.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Fired when the user commits a value change.
|
|
@@ -68,28 +69,7 @@ export interface NumberFieldEventMap extends HTMLElementEventMap, NumberFieldCus
|
|
|
68
69
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
69
70
|
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
70
71
|
*/
|
|
71
|
-
declare class NumberField extends
|
|
72
|
-
/**
|
|
73
|
-
* Set to true to show increase/decrease buttons.
|
|
74
|
-
* @attr {boolean} step-buttons-visible
|
|
75
|
-
*/
|
|
76
|
-
stepButtonsVisible: boolean;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* The minimum value of the field.
|
|
80
|
-
*/
|
|
81
|
-
min: number | null | undefined;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* The maximum value of the field.
|
|
85
|
-
*/
|
|
86
|
-
max: number | null | undefined;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Specifies the allowed number intervals of the field.
|
|
90
|
-
*/
|
|
91
|
-
step: number | null | undefined;
|
|
92
|
-
|
|
72
|
+
declare class NumberField extends NumberFieldMixin(ThemableMixin(ElementMixin(HTMLElement))) {
|
|
93
73
|
addEventListener<K extends keyof NumberFieldEventMap>(
|
|
94
74
|
type: K,
|
|
95
75
|
listener: (this: NumberField, ev: NumberFieldEventMap[K]) => void,
|
|
@@ -7,13 +7,14 @@ import '@vaadin/input-container/src/vaadin-input-container.js';
|
|
|
7
7
|
import { html, PolymerElement } from '@polymer/polymer';
|
|
8
8
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
9
9
|
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
|
|
10
|
-
import { InputController } from '@vaadin/field-base/src/input-controller.js';
|
|
11
|
-
import { InputFieldMixin } from '@vaadin/field-base/src/input-field-mixin.js';
|
|
12
|
-
import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-controller.js';
|
|
13
10
|
import { inputFieldShared } from '@vaadin/field-base/src/styles/input-field-shared-styles.js';
|
|
14
11
|
import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
12
|
+
import { NumberFieldMixin } from './vaadin-number-field-mixin.js';
|
|
13
|
+
import { numberFieldStyles } from './vaadin-number-field-styles.js';
|
|
15
14
|
|
|
16
|
-
registerStyles('vaadin-number-field', inputFieldShared, {
|
|
15
|
+
registerStyles('vaadin-number-field', [inputFieldShared, numberFieldStyles], {
|
|
16
|
+
moduleId: 'vaadin-number-field-styles',
|
|
17
|
+
});
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* `<vaadin-number-field>` is an input field web component that only accepts numeric input.
|
|
@@ -45,43 +46,17 @@ registerStyles('vaadin-number-field', inputFieldShared, { moduleId: 'vaadin-numb
|
|
|
45
46
|
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
46
47
|
*
|
|
47
48
|
* @extends HTMLElement
|
|
48
|
-
* @mixes
|
|
49
|
-
* @mixes SlotStylesMixin
|
|
49
|
+
* @mixes NumberFieldMixin
|
|
50
50
|
* @mixes ElementMixin
|
|
51
51
|
* @mixes ThemableMixin
|
|
52
52
|
*/
|
|
53
|
-
export class NumberField extends
|
|
53
|
+
export class NumberField extends NumberFieldMixin(ThemableMixin(ElementMixin(PolymerElement))) {
|
|
54
54
|
static get is() {
|
|
55
55
|
return 'vaadin-number-field';
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
static get template() {
|
|
59
59
|
return html`
|
|
60
|
-
<style>
|
|
61
|
-
:host([readonly]) [part$='button'] {
|
|
62
|
-
pointer-events: none;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
[part='decrease-button']::before {
|
|
66
|
-
content: '−';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
[part='increase-button']::before {
|
|
70
|
-
content: '+';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
[part='decrease-button'],
|
|
74
|
-
[part='increase-button'] {
|
|
75
|
-
-webkit-user-select: none;
|
|
76
|
-
-moz-user-select: none;
|
|
77
|
-
user-select: none;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
:host([dir='rtl']) [part='input-field'] {
|
|
81
|
-
direction: ltr;
|
|
82
|
-
}
|
|
83
|
-
</style>
|
|
84
|
-
|
|
85
60
|
<div class="vaadin-field-container">
|
|
86
61
|
<div part="label">
|
|
87
62
|
<slot name="label"></slot>
|
|
@@ -96,10 +71,10 @@ export class NumberField extends InputFieldMixin(ThemableMixin(ElementMixin(Poly
|
|
|
96
71
|
theme$="[[_theme]]"
|
|
97
72
|
>
|
|
98
73
|
<div
|
|
99
|
-
disabled$="[[!
|
|
74
|
+
disabled$="[[!_isButtonEnabled(-1, value, min, max, step)]]"
|
|
100
75
|
part="decrease-button"
|
|
101
|
-
on-click="
|
|
102
|
-
on-touchend="
|
|
76
|
+
on-click="_onDecreaseButtonClick"
|
|
77
|
+
on-touchend="_onDecreaseButtonTouchend"
|
|
103
78
|
hidden$="[[!stepButtonsVisible]]"
|
|
104
79
|
aria-hidden="true"
|
|
105
80
|
slot="prefix"
|
|
@@ -109,10 +84,10 @@ export class NumberField extends InputFieldMixin(ThemableMixin(ElementMixin(Poly
|
|
|
109
84
|
<slot name="suffix" slot="suffix"></slot>
|
|
110
85
|
<div id="clearButton" part="clear-button" slot="suffix" aria-hidden="true"></div>
|
|
111
86
|
<div
|
|
112
|
-
disabled$="[[!
|
|
87
|
+
disabled$="[[!_isButtonEnabled(1, value, min, max, step)]]"
|
|
113
88
|
part="increase-button"
|
|
114
|
-
on-click="
|
|
115
|
-
on-touchend="
|
|
89
|
+
on-click="_onIncreaseButtonClick"
|
|
90
|
+
on-touchend="_onIncreaseButtonTouchend"
|
|
116
91
|
hidden$="[[!stepButtonsVisible]]"
|
|
117
92
|
aria-hidden="true"
|
|
118
93
|
slot="suffix"
|
|
@@ -132,321 +107,14 @@ export class NumberField extends InputFieldMixin(ThemableMixin(ElementMixin(Poly
|
|
|
132
107
|
`;
|
|
133
108
|
}
|
|
134
109
|
|
|
135
|
-
static get properties() {
|
|
136
|
-
return {
|
|
137
|
-
/**
|
|
138
|
-
* Set to true to show increase/decrease buttons.
|
|
139
|
-
* @attr {boolean} step-buttons-visible
|
|
140
|
-
*/
|
|
141
|
-
stepButtonsVisible: {
|
|
142
|
-
type: Boolean,
|
|
143
|
-
value: false,
|
|
144
|
-
reflectToAttribute: true,
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* The minimum value of the field.
|
|
149
|
-
*/
|
|
150
|
-
min: {
|
|
151
|
-
type: Number,
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* The maximum value of the field.
|
|
156
|
-
*/
|
|
157
|
-
max: {
|
|
158
|
-
type: Number,
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Specifies the allowed number intervals of the field.
|
|
163
|
-
* @type {number}
|
|
164
|
-
*/
|
|
165
|
-
step: {
|
|
166
|
-
type: Number,
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
static get observers() {
|
|
172
|
-
return ['_stepChanged(step, inputElement)'];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
static get delegateProps() {
|
|
176
|
-
return [...super.delegateProps, 'min', 'max'];
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
static get constraints() {
|
|
180
|
-
return [...super.constraints, 'min', 'max', 'step'];
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
constructor() {
|
|
184
|
-
super();
|
|
185
|
-
this._setType('number');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/** @protected */
|
|
189
|
-
get slotStyles() {
|
|
190
|
-
const tag = this.localName;
|
|
191
|
-
return [
|
|
192
|
-
...super.slotStyles,
|
|
193
|
-
`
|
|
194
|
-
${tag} input[type="number"]::-webkit-outer-spin-button,
|
|
195
|
-
${tag} input[type="number"]::-webkit-inner-spin-button {
|
|
196
|
-
-webkit-appearance: none;
|
|
197
|
-
margin: 0;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
${tag} input[type="number"] {
|
|
201
|
-
-moz-appearance: textfield;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
${tag}[dir='rtl'] input[type="number"]::placeholder {
|
|
205
|
-
direction: rtl;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
${tag}[dir='rtl']:not([step-buttons-visible]) input[type="number"]::placeholder {
|
|
209
|
-
text-align: left;
|
|
210
|
-
}
|
|
211
|
-
`,
|
|
212
|
-
];
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Used by `InputControlMixin` as a reference to the clear button element.
|
|
217
|
-
* @protected
|
|
218
|
-
*/
|
|
219
|
-
get clearElement() {
|
|
220
|
-
return this.$.clearButton;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
110
|
/** @protected */
|
|
224
111
|
ready() {
|
|
225
112
|
super.ready();
|
|
226
113
|
|
|
227
|
-
this.addController(
|
|
228
|
-
new InputController(this, (input) => {
|
|
229
|
-
this._setInputElement(input);
|
|
230
|
-
this._setFocusElement(input);
|
|
231
|
-
this.stateTarget = input;
|
|
232
|
-
this.ariaTarget = input;
|
|
233
|
-
}),
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
this.addController(new LabelledInputController(this.inputElement, this._labelController));
|
|
237
|
-
|
|
238
114
|
this._tooltipController = new TooltipController(this);
|
|
239
115
|
this.addController(this._tooltipController);
|
|
240
116
|
this._tooltipController.setPosition('top');
|
|
241
117
|
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Override the method from `InputConstraintsMixin`
|
|
245
|
-
* to enforce HTML constraint validation even if
|
|
246
|
-
* the user didn't add any constraints explicitly:
|
|
247
|
-
* the field has to be regardless checked for bad input.
|
|
248
|
-
*
|
|
249
|
-
* @override
|
|
250
|
-
*/
|
|
251
|
-
checkValidity() {
|
|
252
|
-
if (this.inputElement) {
|
|
253
|
-
return this.inputElement.checkValidity();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return !this.invalid;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/** @private */
|
|
260
|
-
_decreaseButtonTouchend(e) {
|
|
261
|
-
// Cancel the following click and focus events
|
|
262
|
-
e.preventDefault();
|
|
263
|
-
this._decreaseValue();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/** @private */
|
|
267
|
-
_increaseButtonTouchend(e) {
|
|
268
|
-
// Cancel the following click and focus events
|
|
269
|
-
e.preventDefault();
|
|
270
|
-
this._increaseValue();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** @private */
|
|
274
|
-
_decreaseValue() {
|
|
275
|
-
this._incrementValue(-1);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/** @private */
|
|
279
|
-
_increaseValue() {
|
|
280
|
-
this._incrementValue(1);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/** @private */
|
|
284
|
-
_incrementValue(incr) {
|
|
285
|
-
if (this.disabled || this.readonly) {
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const step = this.step || 1;
|
|
290
|
-
let value = parseFloat(this.value);
|
|
291
|
-
|
|
292
|
-
if (!this.value) {
|
|
293
|
-
if ((this.min === 0 && incr < 0) || (this.max === 0 && incr > 0) || (this.max === 0 && this.min === 0)) {
|
|
294
|
-
incr = 0;
|
|
295
|
-
value = 0;
|
|
296
|
-
} else if ((this.max == null || this.max >= 0) && (this.min == null || this.min <= 0)) {
|
|
297
|
-
value = 0;
|
|
298
|
-
} else if (this.min > 0) {
|
|
299
|
-
value = this.min;
|
|
300
|
-
if (this.max < 0 && incr < 0) {
|
|
301
|
-
value = this.max;
|
|
302
|
-
}
|
|
303
|
-
incr = 0;
|
|
304
|
-
} else if (this.max < 0) {
|
|
305
|
-
value = this.max;
|
|
306
|
-
if (incr < 0) {
|
|
307
|
-
incr = 0;
|
|
308
|
-
} else if (this._getIncrement(1, value - step) > this.max) {
|
|
309
|
-
value -= 2 * step;
|
|
310
|
-
// FIXME(yuriy): find a proper solution to make correct step back
|
|
311
|
-
} else {
|
|
312
|
-
value -= step;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
} else if (value < this.min) {
|
|
316
|
-
incr = 0;
|
|
317
|
-
value = this.min;
|
|
318
|
-
} else if (value > this.max) {
|
|
319
|
-
incr = 0;
|
|
320
|
-
value = this.max;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const newValue = this._getIncrement(incr, value);
|
|
324
|
-
if (!this.value || incr === 0 || this._incrementIsInsideTheLimits(incr, value)) {
|
|
325
|
-
this._setValue(newValue);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/** @private */
|
|
330
|
-
_setValue(value) {
|
|
331
|
-
this.value = this.inputElement.value = String(parseFloat(value));
|
|
332
|
-
this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** @private */
|
|
336
|
-
_getIncrement(incr, currentValue) {
|
|
337
|
-
let step = this.step || 1,
|
|
338
|
-
min = this.min || 0;
|
|
339
|
-
|
|
340
|
-
// To avoid problems with decimal math, multiplying to operate with integers.
|
|
341
|
-
const multiplier = Math.max(this._getMultiplier(currentValue), this._getMultiplier(step), this._getMultiplier(min));
|
|
342
|
-
|
|
343
|
-
step *= multiplier;
|
|
344
|
-
currentValue = Math.round(currentValue * multiplier);
|
|
345
|
-
min *= multiplier;
|
|
346
|
-
|
|
347
|
-
const margin = (currentValue - min) % step;
|
|
348
|
-
|
|
349
|
-
if (incr > 0) {
|
|
350
|
-
return (currentValue - margin + step) / multiplier;
|
|
351
|
-
} else if (incr < 0) {
|
|
352
|
-
return (currentValue - (margin || step)) / multiplier;
|
|
353
|
-
}
|
|
354
|
-
return currentValue / multiplier;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/** @private */
|
|
358
|
-
_getDecimalCount(number) {
|
|
359
|
-
const s = String(number);
|
|
360
|
-
const i = s.indexOf('.');
|
|
361
|
-
return i === -1 ? 1 : s.length - i - 1;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/** @private */
|
|
365
|
-
_getMultiplier(number) {
|
|
366
|
-
if (!isNaN(number)) {
|
|
367
|
-
return 10 ** this._getDecimalCount(number);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/** @private */
|
|
372
|
-
_incrementIsInsideTheLimits(incr, value) {
|
|
373
|
-
if (incr < 0) {
|
|
374
|
-
return this.min == null || this._getIncrement(incr, value) >= this.min;
|
|
375
|
-
} else if (incr > 0) {
|
|
376
|
-
return this.max == null || this._getIncrement(incr, value) <= this.max;
|
|
377
|
-
}
|
|
378
|
-
return this._getIncrement(incr, value) <= this.max && this._getIncrement(incr, value) >= this.min;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/** @private */
|
|
382
|
-
_allowed(sign) {
|
|
383
|
-
const incr = sign * (this.step || 1);
|
|
384
|
-
const value = parseFloat(this.value);
|
|
385
|
-
return !this.value || (!this.disabled && this._incrementIsInsideTheLimits(incr, value));
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* @param {number} step
|
|
390
|
-
* @param {HTMLElement | undefined} inputElement
|
|
391
|
-
* @protected
|
|
392
|
-
*/
|
|
393
|
-
_stepChanged(step, inputElement) {
|
|
394
|
-
if (inputElement) {
|
|
395
|
-
inputElement.step = step || 'any';
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* @param {unknown} newVal
|
|
401
|
-
* @param {unknown} oldVal
|
|
402
|
-
* @protected
|
|
403
|
-
* @override
|
|
404
|
-
*/
|
|
405
|
-
_valueChanged(newVal, oldVal) {
|
|
406
|
-
// Validate value to be numeric
|
|
407
|
-
if (newVal && isNaN(parseFloat(newVal))) {
|
|
408
|
-
this.value = '';
|
|
409
|
-
} else if (typeof this.value !== 'string') {
|
|
410
|
-
this.value = String(this.value);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
super._valueChanged(this.value, oldVal);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Override an event listener from `InputControlMixin`
|
|
418
|
-
* to avoid adding a separate listener.
|
|
419
|
-
* @param {!KeyboardEvent} event
|
|
420
|
-
* @protected
|
|
421
|
-
* @override
|
|
422
|
-
*/
|
|
423
|
-
_onKeyDown(event) {
|
|
424
|
-
if (event.key === 'ArrowUp') {
|
|
425
|
-
event.preventDefault();
|
|
426
|
-
this._increaseValue();
|
|
427
|
-
} else if (event.key === 'ArrowDown') {
|
|
428
|
-
event.preventDefault();
|
|
429
|
-
this._decreaseValue();
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
super._onKeyDown(event);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Native [type=number] inputs don't update their value
|
|
437
|
-
* when you are entering input that the browser is unable to parse
|
|
438
|
-
* e.g. "--5", hence we have to override this method from `InputMixin`
|
|
439
|
-
* so that, when value is empty, it would additionally check
|
|
440
|
-
* for bad input based on the native `validity.badInput` property.
|
|
441
|
-
*
|
|
442
|
-
* @param {InputEvent} event
|
|
443
|
-
* @protected
|
|
444
|
-
* @override
|
|
445
|
-
*/
|
|
446
|
-
_setHasInputValue(event) {
|
|
447
|
-
const target = event.composedPath()[0];
|
|
448
|
-
this._hasInputValue = target.value.length > 0 || target.validity.badInput;
|
|
449
|
-
}
|
|
450
118
|
}
|
|
451
119
|
|
|
452
120
|
customElements.define(NumberField.is, NumberField);
|
|
@@ -9,10 +9,6 @@ import { inputFieldShared } from '@vaadin/vaadin-lumo-styles/mixins/input-field-
|
|
|
9
9
|
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
10
10
|
|
|
11
11
|
const numberField = css`
|
|
12
|
-
:host {
|
|
13
|
-
width: 8em;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
:host([step-buttons-visible]:not([theme~='align-right'])) ::slotted(input) {
|
|
17
13
|
text-align: center;
|
|
18
14
|
}
|
|
@@ -8,10 +8,6 @@ import { inputFieldShared } from '@vaadin/vaadin-material-styles/mixins/input-fi
|
|
|
8
8
|
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
9
9
|
|
|
10
10
|
const numberField = css`
|
|
11
|
-
:host {
|
|
12
|
-
width: 8em;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
:host([step-buttons-visible]) ::slotted(input) {
|
|
16
12
|
text-align: center;
|
|
17
13
|
}
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/number-field",
|
|
4
|
-
"version": "24.0.0-
|
|
4
|
+
"version": "24.0.0-beta2",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-number-field",
|
|
11
|
-
"description": "`<vaadin-number-field>` is an input field web component that only accepts numeric input.\n\n```html\n<vaadin-number-field label=\"Balance\"></vaadin-number-field>\n```\n\n### Styling\n\n`<vaadin-number-field>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-
|
|
11
|
+
"description": "`<vaadin-number-field>` is an input field web component that only accepts numeric input.\n\n```html\n<vaadin-number-field label=\"Balance\"></vaadin-number-field>\n```\n\n### Styling\n\n`<vaadin-number-field>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-text-field) for the styling documentation.\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n------------------|-------------------------\n`increase-button` | Increase (\"plus\") button\n`decrease-button` | Decrease (\"minus\") button\n\nNote, the `input-prevented` state attribute is only supported when `allowedCharPattern` is set.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "disabled",
|
|
@@ -99,30 +99,30 @@
|
|
|
99
99
|
}
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
|
-
"name": "
|
|
103
|
-
"description": "
|
|
102
|
+
"name": "clear-button-visible",
|
|
103
|
+
"description": "Set to true to display the clear icon which clears the input.\n\nIt is up to the component to choose where to place the clear icon:\nin the Shadow DOM or in the light DOM. In any way, a reference to\nthe clear icon element should be provided via the `clearElement` getter.",
|
|
104
104
|
"value": {
|
|
105
105
|
"type": [
|
|
106
|
-
"
|
|
106
|
+
"boolean",
|
|
107
107
|
"null",
|
|
108
108
|
"undefined"
|
|
109
109
|
]
|
|
110
110
|
}
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
|
-
"name": "
|
|
114
|
-
"description": "
|
|
113
|
+
"name": "allowed-char-pattern",
|
|
114
|
+
"description": "A pattern matched against individual characters the user inputs.\n\nWhen set, the field will prevent:\n- `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`\n- `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`\n- `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`\n\nFor example, to allow entering only numbers and minus signs, use:\n`allowedCharPattern = \"[\\\\d-]\"`",
|
|
115
115
|
"value": {
|
|
116
116
|
"type": [
|
|
117
|
-
"
|
|
117
|
+
"string",
|
|
118
118
|
"null",
|
|
119
119
|
"undefined"
|
|
120
120
|
]
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
{
|
|
124
|
-
"name": "
|
|
125
|
-
"description": "
|
|
124
|
+
"name": "autoselect",
|
|
125
|
+
"description": "If true, the input text gets fully selected when the field is focused using click or touch / tap.",
|
|
126
126
|
"value": {
|
|
127
127
|
"type": [
|
|
128
128
|
"boolean",
|
|
@@ -208,17 +208,6 @@
|
|
|
208
208
|
]
|
|
209
209
|
}
|
|
210
210
|
},
|
|
211
|
-
{
|
|
212
|
-
"name": "step-buttons-visible",
|
|
213
|
-
"description": "Set to true to show increase/decrease buttons.",
|
|
214
|
-
"value": {
|
|
215
|
-
"type": [
|
|
216
|
-
"boolean",
|
|
217
|
-
"null",
|
|
218
|
-
"undefined"
|
|
219
|
-
]
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
211
|
{
|
|
223
212
|
"name": "min",
|
|
224
213
|
"description": "The minimum value of the field.",
|
|
@@ -250,6 +239,17 @@
|
|
|
250
239
|
]
|
|
251
240
|
}
|
|
252
241
|
},
|
|
242
|
+
{
|
|
243
|
+
"name": "step-buttons-visible",
|
|
244
|
+
"description": "Set to true to show increase/decrease buttons.",
|
|
245
|
+
"value": {
|
|
246
|
+
"type": [
|
|
247
|
+
"boolean",
|
|
248
|
+
"null",
|
|
249
|
+
"undefined"
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
253
|
{
|
|
254
254
|
"name": "theme",
|
|
255
255
|
"description": "The theme variants to apply to the component.",
|
|
@@ -353,30 +353,30 @@
|
|
|
353
353
|
}
|
|
354
354
|
},
|
|
355
355
|
{
|
|
356
|
-
"name": "
|
|
357
|
-
"description": "
|
|
356
|
+
"name": "clearButtonVisible",
|
|
357
|
+
"description": "Set to true to display the clear icon which clears the input.\n\nIt is up to the component to choose where to place the clear icon:\nin the Shadow DOM or in the light DOM. In any way, a reference to\nthe clear icon element should be provided via the `clearElement` getter.",
|
|
358
358
|
"value": {
|
|
359
359
|
"type": [
|
|
360
|
-
"
|
|
360
|
+
"boolean",
|
|
361
361
|
"null",
|
|
362
362
|
"undefined"
|
|
363
363
|
]
|
|
364
364
|
}
|
|
365
365
|
},
|
|
366
366
|
{
|
|
367
|
-
"name": "
|
|
368
|
-
"description": "
|
|
367
|
+
"name": "allowedCharPattern",
|
|
368
|
+
"description": "A pattern matched against individual characters the user inputs.\n\nWhen set, the field will prevent:\n- `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`\n- `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`\n- `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`\n\nFor example, to allow entering only numbers and minus signs, use:\n`allowedCharPattern = \"[\\\\d-]\"`",
|
|
369
369
|
"value": {
|
|
370
370
|
"type": [
|
|
371
|
-
"
|
|
371
|
+
"string",
|
|
372
372
|
"null",
|
|
373
373
|
"undefined"
|
|
374
374
|
]
|
|
375
375
|
}
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
|
-
"name": "
|
|
379
|
-
"description": "
|
|
378
|
+
"name": "autoselect",
|
|
379
|
+
"description": "If true, the input text gets fully selected when the field is focused using click or touch / tap.",
|
|
380
380
|
"value": {
|
|
381
381
|
"type": [
|
|
382
382
|
"boolean",
|
|
@@ -462,17 +462,6 @@
|
|
|
462
462
|
]
|
|
463
463
|
}
|
|
464
464
|
},
|
|
465
|
-
{
|
|
466
|
-
"name": "stepButtonsVisible",
|
|
467
|
-
"description": "Set to true to show increase/decrease buttons.",
|
|
468
|
-
"value": {
|
|
469
|
-
"type": [
|
|
470
|
-
"boolean",
|
|
471
|
-
"null",
|
|
472
|
-
"undefined"
|
|
473
|
-
]
|
|
474
|
-
}
|
|
475
|
-
},
|
|
476
465
|
{
|
|
477
466
|
"name": "min",
|
|
478
467
|
"description": "The minimum value of the field.",
|
|
@@ -503,6 +492,17 @@
|
|
|
503
492
|
"number"
|
|
504
493
|
]
|
|
505
494
|
}
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"name": "stepButtonsVisible",
|
|
498
|
+
"description": "Set to true to show increase/decrease buttons.",
|
|
499
|
+
"value": {
|
|
500
|
+
"type": [
|
|
501
|
+
"boolean",
|
|
502
|
+
"null",
|
|
503
|
+
"undefined"
|
|
504
|
+
]
|
|
505
|
+
}
|
|
506
506
|
}
|
|
507
507
|
],
|
|
508
508
|
"events": [
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/number-field",
|
|
4
|
-
"version": "24.0.0-
|
|
4
|
+
"version": "24.0.0-beta2",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"elements": [
|
|
17
17
|
{
|
|
18
18
|
"name": "vaadin-number-field",
|
|
19
|
-
"description": "`<vaadin-number-field>` is an input field web component that only accepts numeric input.\n\n```html\n<vaadin-number-field label=\"Balance\"></vaadin-number-field>\n```\n\n### Styling\n\n`<vaadin-number-field>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-
|
|
19
|
+
"description": "`<vaadin-number-field>` is an input field web component that only accepts numeric input.\n\n```html\n<vaadin-number-field label=\"Balance\"></vaadin-number-field>\n```\n\n### Styling\n\n`<vaadin-number-field>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-text-field) for the styling documentation.\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n------------------|-------------------------\n`increase-button` | Increase (\"plus\") button\n`decrease-button` | Decrease (\"minus\") button\n\nNote, the `input-prevented` state attribute is only supported when `allowedCharPattern` is set.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
|
-
"name": "?
|
|
52
|
-
"description": "
|
|
51
|
+
"name": "?clearButtonVisible",
|
|
52
|
+
"description": "Set to true to display the clear icon which clears the input.\n\nIt is up to the component to choose where to place the clear icon:\nin the Shadow DOM or in the light DOM. In any way, a reference to\nthe clear icon element should be provided via the `clearElement` getter.",
|
|
53
53
|
"value": {
|
|
54
54
|
"kind": "expression"
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
|
-
"name": "?
|
|
59
|
-
"description": "
|
|
58
|
+
"name": "?autoselect",
|
|
59
|
+
"description": "If true, the input text gets fully selected when the field is focused using click or touch / tap.",
|
|
60
60
|
"value": {
|
|
61
61
|
"kind": "expression"
|
|
62
62
|
}
|