@vaadin/number-field 24.3.0-alpha1 → 24.3.0-alpha10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/number-field",
3
- "version": "24.3.0-alpha1",
3
+ "version": "24.3.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -38,23 +38,23 @@
38
38
  "dependencies": {
39
39
  "@open-wc/dedupe-mixin": "^1.3.0",
40
40
  "@polymer/polymer": "^3.0.0",
41
- "@vaadin/a11y-base": "24.3.0-alpha1",
42
- "@vaadin/component-base": "24.3.0-alpha1",
43
- "@vaadin/field-base": "24.3.0-alpha1",
44
- "@vaadin/input-container": "24.3.0-alpha1",
45
- "@vaadin/vaadin-lumo-styles": "24.3.0-alpha1",
46
- "@vaadin/vaadin-material-styles": "24.3.0-alpha1",
47
- "@vaadin/vaadin-themable-mixin": "24.3.0-alpha1",
48
- "lit": "^2.0.0"
41
+ "@vaadin/a11y-base": "24.3.0-alpha10",
42
+ "@vaadin/component-base": "24.3.0-alpha10",
43
+ "@vaadin/field-base": "24.3.0-alpha10",
44
+ "@vaadin/input-container": "24.3.0-alpha10",
45
+ "@vaadin/vaadin-lumo-styles": "24.3.0-alpha10",
46
+ "@vaadin/vaadin-material-styles": "24.3.0-alpha10",
47
+ "@vaadin/vaadin-themable-mixin": "24.3.0-alpha10",
48
+ "lit": "^3.0.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@esm-bundle/chai": "^4.3.4",
52
- "@vaadin/testing-helpers": "^0.5.0",
52
+ "@vaadin/testing-helpers": "^0.6.0",
53
53
  "sinon": "^13.0.2"
54
54
  },
55
55
  "web-types": [
56
56
  "web-types.json",
57
57
  "web-types.lit.json"
58
58
  ],
59
- "gitHead": "9ca6f3ca220a777e8eea181a1f5717e39a732240"
59
+ "gitHead": "0271523d93fe5df0425ff64206886614f3c6f401"
60
60
  }
@@ -103,6 +103,15 @@ export const NumberFieldMixin = (superClass) =>
103
103
  return this.$.clearButton;
104
104
  }
105
105
 
106
+ /**
107
+ * Whether the input element's value is unparsable.
108
+ *
109
+ * @private
110
+ */
111
+ get __hasUnparsableValue() {
112
+ return this.inputElement.validity.badInput;
113
+ }
114
+
106
115
  /** @protected */
107
116
  ready() {
108
117
  super.ready();
@@ -255,17 +264,13 @@ export const NumberFieldMixin = (superClass) =>
255
264
 
256
265
  const newValue = this._getIncrement(incr, value);
257
266
  if (!this.value || incr === 0 || this._incrementIsInsideTheLimits(incr, value)) {
258
- this._setValue(newValue);
267
+ this.__keepCommittedValue = true;
268
+ this.value = this.inputElement.value = String(parseFloat(newValue));
269
+ this.__keepCommittedValue = false;
270
+ this.__commitValueChange();
259
271
  }
260
272
  }
261
273
 
262
- /** @private */
263
- _setValue(value) {
264
- this.value = this.inputElement.value = String(parseFloat(value));
265
- this.validate();
266
- this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
267
- }
268
-
269
274
  /** @private */
270
275
  _getIncrement(incr, currentValue) {
271
276
  let step = this.step || 1,
@@ -349,6 +354,11 @@ export const NumberFieldMixin = (superClass) =>
349
354
  }
350
355
 
351
356
  super._valueChanged(this.value, oldVal);
357
+
358
+ if (!this.__keepCommittedValue) {
359
+ this.__committedValue = this.value;
360
+ this.__committedUnparsableValueStatus = false;
361
+ }
352
362
  }
353
363
 
354
364
  /**
@@ -383,6 +393,113 @@ export const NumberFieldMixin = (superClass) =>
383
393
  */
384
394
  _setHasInputValue(event) {
385
395
  const target = event.composedPath()[0];
386
- this._hasInputValue = target.value.length > 0 || target.validity.badInput;
396
+ this._hasInputValue = target.value.length > 0 || this.__hasUnparsableValue;
397
+ }
398
+
399
+ /**
400
+ * Override this method from `InputMixin` to prevent
401
+ * the value change caused by user input from being treated
402
+ * as initiated programmatically by the developer and therefore
403
+ * from getting silently committed by the value observer without
404
+ * any change event. The value change will be committed later
405
+ * on blur or Enter.
406
+ *
407
+ * @param {InputEvent} event
408
+ * @override
409
+ * @protected
410
+ */
411
+ _onInput(event) {
412
+ this.__keepCommittedValue = true;
413
+ super._onInput(event);
414
+ this.__keepCommittedValue = false;
415
+ }
416
+
417
+ /**
418
+ * Override this method from `InputControlMixin`
419
+ * to stop propagation of the native change event.
420
+ *
421
+ * @param {Event}
422
+ * @override
423
+ * @protected
424
+ */
425
+ _onChange(event) {
426
+ event.stopPropagation();
427
+ }
428
+
429
+ /**
430
+ * Override this method from `ClearButtonMixin`
431
+ * to properly commit the empty value since
432
+ * the change handler doesn't do that anymore.
433
+ *
434
+ * @param {MouseEvent} event
435
+ * @override
436
+ * @protected
437
+ */
438
+ _onClearAction(event) {
439
+ super._onClearAction(event);
440
+ this.__commitValueChange();
441
+ }
442
+
443
+ /**
444
+ * Override this method from `FocusMixin`
445
+ * to commit a possible pending value change on blur.
446
+ *
447
+ * @param {boolean} focused
448
+ * @override
449
+ * @protected
450
+ */
451
+ _setFocused(focused) {
452
+ super._setFocused(focused);
453
+
454
+ if (!focused) {
455
+ this.__commitValueChange();
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Override this method from `KeyboardMixin`
461
+ * to commit a possible pending value change on Enter.
462
+ *
463
+ * @param {KeyboardEvent} event
464
+ * @override
465
+ * @protected
466
+ */
467
+ _onEnter(event) {
468
+ super._onEnter(event);
469
+ this.__commitValueChange();
470
+ }
471
+
472
+ /**
473
+ * Depending on the nature of the value change that has occurred since
474
+ * the last commit attempt, triggers validation and fires an event:
475
+ *
476
+ * Value change | Event
477
+ * :------------------------|:------------------
478
+ * empty => parsable | change
479
+ * empty => unparsable | unparsable-change
480
+ * parsable => empty | change
481
+ * parsable => parsable | change
482
+ * parsable => unparsable | change
483
+ * unparsable => empty | unparsable-change
484
+ * unparsable => parsable | change
485
+ * unparsable => unparsable | -
486
+ *
487
+ * Note, there is currently no way to detect unparsable => unparsable changes
488
+ * because the browser doesn't provide access to unparsable values of native
489
+ * [type=number] inputs.
490
+ *
491
+ * @private
492
+ */
493
+ __commitValueChange() {
494
+ if (this.__committedValue !== this.value) {
495
+ this.validate();
496
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
497
+ } else if (this.__committedUnparsableValueStatus !== this.__hasUnparsableValue) {
498
+ this.validate();
499
+ this.dispatchEvent(new CustomEvent('unparsable-change'));
500
+ }
501
+
502
+ this.__committedValue = this.value;
503
+ this.__committedUnparsableValueStatus = this.__hasUnparsableValue;
387
504
  }
388
505
  };
@@ -16,14 +16,14 @@ export type NumberFieldChangeEvent = Event & {
16
16
  };
17
17
 
18
18
  /**
19
- * Fired when the `invalid` property changes.
19
+ * Fired when the user commits an unparsable value change and there is no change event.
20
20
  */
21
- export type NumberFieldInvalidChangedEvent = CustomEvent<{ value: boolean }>;
21
+ export type NumberFieldUnparsableChangeEvent = CustomEvent;
22
22
 
23
23
  /**
24
- * Fired when the `dirty` property changes.
24
+ * Fired when the `invalid` property changes.
25
25
  */
26
- export type NumberFieldDirtyChangedEvent = CustomEvent<{ value: boolean }>;
26
+ export type NumberFieldInvalidChangedEvent = CustomEvent<{ value: boolean }>;
27
27
 
28
28
  /**
29
29
  * Fired when the `value` property changes.
@@ -36,9 +36,9 @@ export type NumberFieldValueChangedEvent = CustomEvent<{ value: string }>;
36
36
  export type NumberFieldValidatedEvent = CustomEvent<{ valid: boolean }>;
37
37
 
38
38
  export interface NumberFieldCustomEventMap {
39
- 'invalid-changed': NumberFieldInvalidChangedEvent;
39
+ 'unparsable-change': NumberFieldUnparsableChangeEvent;
40
40
 
41
- 'dirty-changed': NumberFieldDirtyChangedEvent;
41
+ 'invalid-changed': NumberFieldInvalidChangedEvent;
42
42
 
43
43
  'value-changed': NumberFieldValueChangedEvent;
44
44
 
@@ -70,10 +70,29 @@ export interface NumberFieldEventMap extends HTMLElementEventMap, NumberFieldCus
70
70
  *
71
71
  * Note, the `input-prevented` state attribute is only supported when `allowedCharPattern` is set.
72
72
  *
73
+ * ### Change events
74
+ *
75
+ * Depending on the nature of the value change that the user attempts to commit e.g. by pressing Enter,
76
+ * the component can fire either a `change` event or an `unparsable-change` event:
77
+ *
78
+ * Value change | Event
79
+ * :------------------------|:------------------
80
+ * empty => parsable | change
81
+ * empty => unparsable | unparsable-change
82
+ * parsable => empty | change
83
+ * parsable => parsable | change
84
+ * parsable => unparsable | change
85
+ * unparsable => empty | unparsable-change
86
+ * unparsable => parsable | change
87
+ * unparsable => unparsable | -
88
+ *
89
+ * Note, there is currently no way to detect unparsable => unparsable changes because the browser
90
+ * doesn't provide access to unparsable values of native [type=number] inputs.
91
+ *
73
92
  * @fires {Event} input - Fired when the value is changed by the user: on every typing keystroke, and the value is cleared using the clear button.
74
93
  * @fires {Event} change - Fired when the user commits a value change.
94
+ * @fires {Event} unparsable-change - Fired when the user commits an unparsable value change and there is no change event.
75
95
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
76
- * @fires {CustomEvent} dirty-changed - Fired when the `dirty` property changes.
77
96
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
78
97
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
79
98
  */
@@ -40,8 +40,28 @@ registerStyles('vaadin-number-field', [inputFieldShared, numberFieldStyles], {
40
40
  *
41
41
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
42
42
  *
43
+ * ### Change events
44
+ *
45
+ * Depending on the nature of the value change that the user attempts to commit e.g. by pressing Enter,
46
+ * the component can fire either a `change` event or an `unparsable-change` event:
47
+ *
48
+ * Value change | Event
49
+ * :------------------------|:------------------
50
+ * empty => parsable | change
51
+ * empty => unparsable | unparsable-change
52
+ * parsable => empty | change
53
+ * parsable => parsable | change
54
+ * parsable => unparsable | change
55
+ * unparsable => empty | unparsable-change
56
+ * unparsable => parsable | change
57
+ * unparsable => unparsable | -
58
+ *
59
+ * Note, there is currently no way to detect unparsable => unparsable changes because the browser
60
+ * doesn't provide access to unparsable values of native [type=number] inputs.
61
+ *
43
62
  * @fires {Event} input - Fired when the value is changed by the user: on every typing keystroke, and the value is cleared using the clear button.
44
63
  * @fires {Event} change - Fired when the user commits a value change.
64
+ * @fires {Event} unparsable-change - Fired when the user commits an unparsable value change and there is no change event.
45
65
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
46
66
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
47
67
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
@@ -3,6 +3,7 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import '@vaadin/input-container/theme/lumo/vaadin-input-container-styles.js';
6
7
  import '@vaadin/vaadin-lumo-styles/sizing.js';
7
8
  import { fieldButton } from '@vaadin/vaadin-lumo-styles/mixins/field-button.js';
8
9
  import { inputFieldShared } from '@vaadin/vaadin-lumo-styles/mixins/input-field-shared.js';
@@ -3,6 +3,5 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import '@vaadin/input-container/theme/lumo/vaadin-input-container.js';
7
6
  import './vaadin-number-field-styles.js';
8
7
  import '../../src/vaadin-number-field.js';
@@ -3,6 +3,7 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import '@vaadin/input-container/theme/material/vaadin-input-container-styles.js';
6
7
  import { fieldButton } from '@vaadin/vaadin-material-styles/mixins/field-button.js';
7
8
  import { inputFieldShared } from '@vaadin/vaadin-material-styles/mixins/input-field-shared.js';
8
9
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
@@ -3,6 +3,5 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import '@vaadin/input-container/theme/material/vaadin-input-container.js';
7
6
  import './vaadin-number-field-styles.js';
8
7
  import '../../src/vaadin-number-field.js';
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.3.0-alpha1",
4
+ "version": "24.3.0-alpha10",
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.3.0-alpha1/#/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/styling-components) documentation.",
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.3.0-alpha10/#/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/styling-components) documentation.\n\n### Change events\n\nDepending on the nature of the value change that the user attempts to commit e.g. by pressing Enter,\nthe component can fire either a `change` event or an `unparsable-change` event:\n\nValue change | Event\n:------------------------|:------------------\nempty => parsable | change\nempty => unparsable | unparsable-change\nparsable => empty | change\nparsable => parsable | change\nparsable => unparsable | change\nunparsable => empty | unparsable-change\nunparsable => parsable | change\nunparsable => unparsable | -\n\nNote, there is currently no way to detect unparsable => unparsable changes because the browser\ndoesn't provide access to unparsable values of native [type=number] inputs.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "disabled",
@@ -120,17 +120,6 @@
120
120
  ]
121
121
  }
122
122
  },
123
- {
124
- "name": "dirty",
125
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
126
- "value": {
127
- "type": [
128
- "boolean",
129
- "null",
130
- "undefined"
131
- ]
132
- }
133
- },
134
123
  {
135
124
  "name": "clear-button-visible",
136
125
  "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.",
@@ -407,17 +396,6 @@
407
396
  ]
408
397
  }
409
398
  },
410
- {
411
- "name": "dirty",
412
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
413
- "value": {
414
- "type": [
415
- "boolean",
416
- "null",
417
- "undefined"
418
- ]
419
- }
420
- },
421
399
  {
422
400
  "name": "clearButtonVisible",
423
401
  "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.",
@@ -591,10 +569,6 @@
591
569
  {
592
570
  "name": "value-changed",
593
571
  "description": "Fired when the `value` property changes."
594
- },
595
- {
596
- "name": "dirty-changed",
597
- "description": "Fired when the `dirty` property changes."
598
572
  }
599
573
  ]
600
574
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/number-field",
4
- "version": "24.3.0-alpha1",
4
+ "version": "24.3.0-alpha10",
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.3.0-alpha1/#/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/styling-components) documentation.",
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.3.0-alpha10/#/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/styling-components) documentation.\n\n### Change events\n\nDepending on the nature of the value change that the user attempts to commit e.g. by pressing Enter,\nthe component can fire either a `change` event or an `unparsable-change` event:\n\nValue change | Event\n:------------------------|:------------------\nempty => parsable | change\nempty => unparsable | unparsable-change\nparsable => empty | change\nparsable => parsable | change\nparsable => unparsable | change\nunparsable => empty | unparsable-change\nunparsable => parsable | change\nunparsable => unparsable | -\n\nNote, there is currently no way to detect unparsable => unparsable changes because the browser\ndoesn't provide access to unparsable values of native [type=number] inputs.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -47,13 +47,6 @@
47
47
  "kind": "expression"
48
48
  }
49
49
  },
50
- {
51
- "name": "?dirty",
52
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
53
- "value": {
54
- "kind": "expression"
55
- }
56
- },
57
50
  {
58
51
  "name": "?clearButtonVisible",
59
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.",
@@ -228,13 +221,6 @@
228
221
  "value": {
229
222
  "kind": "expression"
230
223
  }
231
- },
232
- {
233
- "name": "@dirty-changed",
234
- "description": "Fired when the `dirty` property changes.",
235
- "value": {
236
- "kind": "expression"
237
- }
238
224
  }
239
225
  ]
240
226
  }