@vaadin/combo-box 24.4.0-alpha2 → 24.4.0-alpha21

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.
Files changed (32) hide show
  1. package/README.md +0 -1
  2. package/package.json +16 -14
  3. package/src/vaadin-combo-box-data-provider-mixin.js +11 -20
  4. package/src/vaadin-combo-box-item-mixin.js +1 -1
  5. package/src/vaadin-combo-box-light-mixin.d.ts +26 -0
  6. package/src/vaadin-combo-box-light-mixin.js +140 -0
  7. package/src/vaadin-combo-box-light.d.ts +2 -7
  8. package/src/vaadin-combo-box-light.js +3 -127
  9. package/src/vaadin-combo-box-mixin.js +80 -25
  10. package/src/vaadin-combo-box-scroller-mixin.js +38 -13
  11. package/src/vaadin-lit-combo-box-item.js +50 -0
  12. package/src/vaadin-lit-combo-box-light.js +58 -0
  13. package/src/vaadin-lit-combo-box-overlay.js +76 -0
  14. package/src/vaadin-lit-combo-box-scroller.js +59 -0
  15. package/src/vaadin-lit-combo-box.js +170 -0
  16. package/theme/lumo/vaadin-combo-box-item-styles.d.ts +5 -0
  17. package/theme/lumo/vaadin-combo-box-item-styles.js +2 -4
  18. package/theme/lumo/vaadin-combo-box-light.d.ts +3 -0
  19. package/theme/lumo/vaadin-combo-box-overlay-styles.d.ts +6 -0
  20. package/theme/lumo/vaadin-combo-box-styles.d.ts +2 -0
  21. package/theme/lumo/vaadin-combo-box.d.ts +4 -0
  22. package/theme/lumo/vaadin-lit-combo-box-light.d.ts +3 -0
  23. package/theme/lumo/vaadin-lit-combo-box-light.js +3 -0
  24. package/theme/lumo/vaadin-lit-combo-box.d.ts +4 -0
  25. package/theme/lumo/vaadin-lit-combo-box.js +4 -0
  26. package/theme/material/vaadin-combo-box-item-styles.d.ts +5 -0
  27. package/theme/material/vaadin-combo-box-light.d.ts +3 -0
  28. package/theme/material/vaadin-combo-box-overlay-styles.d.ts +4 -0
  29. package/theme/material/vaadin-combo-box-styles.d.ts +3 -0
  30. package/theme/material/vaadin-combo-box.d.ts +4 -0
  31. package/web-types.json +2 -2
  32. package/web-types.lit.json +2 -2
package/README.md CHANGED
@@ -5,7 +5,6 @@ A web component for choosing a value from a filterable list of options presented
5
5
  [Documentation + Live Demo ↗](https://vaadin.com/docs/latest/components/combo-box)
6
6
 
7
7
  [![npm version](https://badgen.net/npm/v/@vaadin/combo-box)](https://www.npmjs.com/package/@vaadin/combo-box)
8
- [![Discord](https://img.shields.io/discord/732335336448852018?label=discord)](https://discord.gg/PHmkCKC)
9
8
 
10
9
  ```html
11
10
  <vaadin-combo-box
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/combo-box",
3
- "version": "24.4.0-alpha2",
3
+ "version": "24.4.0-alpha21",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -26,7 +26,9 @@
26
26
  "vaadin-*.d.ts",
27
27
  "vaadin-*.js",
28
28
  "web-types.json",
29
- "web-types.lit.json"
29
+ "web-types.lit.json",
30
+ "!vaadin-lit-*.d.ts",
31
+ "!vaadin-lit-*.js"
30
32
  ],
31
33
  "keywords": [
32
34
  "Vaadin",
@@ -38,21 +40,21 @@
38
40
  "dependencies": {
39
41
  "@open-wc/dedupe-mixin": "^1.3.0",
40
42
  "@polymer/polymer": "^3.0.0",
41
- "@vaadin/a11y-base": "24.4.0-alpha2",
42
- "@vaadin/component-base": "24.4.0-alpha2",
43
- "@vaadin/field-base": "24.4.0-alpha2",
44
- "@vaadin/input-container": "24.4.0-alpha2",
45
- "@vaadin/item": "24.4.0-alpha2",
46
- "@vaadin/lit-renderer": "24.4.0-alpha2",
47
- "@vaadin/overlay": "24.4.0-alpha2",
48
- "@vaadin/vaadin-lumo-styles": "24.4.0-alpha2",
49
- "@vaadin/vaadin-material-styles": "24.4.0-alpha2",
50
- "@vaadin/vaadin-themable-mixin": "24.4.0-alpha2"
43
+ "@vaadin/a11y-base": "24.4.0-alpha21",
44
+ "@vaadin/component-base": "24.4.0-alpha21",
45
+ "@vaadin/field-base": "24.4.0-alpha21",
46
+ "@vaadin/input-container": "24.4.0-alpha21",
47
+ "@vaadin/item": "24.4.0-alpha21",
48
+ "@vaadin/lit-renderer": "24.4.0-alpha21",
49
+ "@vaadin/overlay": "24.4.0-alpha21",
50
+ "@vaadin/vaadin-lumo-styles": "24.4.0-alpha21",
51
+ "@vaadin/vaadin-material-styles": "24.4.0-alpha21",
52
+ "@vaadin/vaadin-themable-mixin": "24.4.0-alpha21"
51
53
  },
52
54
  "devDependencies": {
53
55
  "@esm-bundle/chai": "^4.3.4",
54
56
  "@vaadin/testing-helpers": "^0.6.0",
55
- "@vaadin/text-field": "24.4.0-alpha2",
57
+ "@vaadin/text-field": "24.4.0-alpha21",
56
58
  "lit": "^3.0.0",
57
59
  "sinon": "^13.0.2"
58
60
  },
@@ -60,5 +62,5 @@
60
62
  "web-types.json",
61
63
  "web-types.lit.json"
62
64
  ],
63
- "gitHead": "f303ead58d27e15d81a55db0559611fb77c0e421"
65
+ "gitHead": "2efeeebbeabddfde14c845ee4098f9e62e352ffe"
64
66
  }
@@ -21,6 +21,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
21
21
  type: Number,
22
22
  value: 50,
23
23
  observer: '_pageSizeChanged',
24
+ sync: true,
24
25
  },
25
26
 
26
27
  /**
@@ -30,6 +31,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
30
31
  size: {
31
32
  type: Number,
32
33
  observer: '_sizeChanged',
34
+ sync: true,
33
35
  },
34
36
 
35
37
  /**
@@ -49,6 +51,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
49
51
  dataProvider: {
50
52
  type: Object,
51
53
  observer: '_dataProviderChanged',
54
+ sync: true,
52
55
  },
53
56
 
54
57
  /** @private */
@@ -82,18 +85,11 @@ export const ComboBoxDataProviderMixin = (superClass) =>
82
85
  ready() {
83
86
  super.ready();
84
87
  this._scroller.addEventListener('index-requested', (e) => {
85
- const index = e.detail.index;
86
- const currentScrollerPos = e.detail.currentScrollerPos;
87
- const allowedIndexRange = Math.floor(this.pageSize * 1.5);
88
-
89
- // Ignores the indexes, which are being re-sent during scrolling reset,
90
- // if the corresponding page is around the current scroller position.
91
- // Otherwise, there might be a last pages duplicates, which cause the
92
- // loading indicator hanging and blank items
93
- if (this._shouldSkipIndex(index, allowedIndexRange, currentScrollerPos)) {
88
+ if (!this._shouldFetchData()) {
94
89
  return;
95
90
  }
96
91
 
92
+ const index = e.detail.index;
97
93
  if (index !== undefined) {
98
94
  const page = this._getPageForIndex(index);
99
95
  if (this._shouldLoadPage(page)) {
@@ -125,7 +121,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
125
121
  }
126
122
  }
127
123
 
128
- /** @private */
124
+ /** @protected */
129
125
  _shouldFetchData() {
130
126
  if (!this.dataProvider) {
131
127
  return false;
@@ -136,23 +132,18 @@ export const ComboBoxDataProviderMixin = (superClass) =>
136
132
 
137
133
  /** @private */
138
134
  _ensureFirstPage(opened) {
135
+ if (!this._shouldFetchData()) {
136
+ return;
137
+ }
138
+
139
139
  if (opened && this._shouldLoadPage(0)) {
140
140
  this._loadPage(0);
141
141
  }
142
142
  }
143
143
 
144
- /** @private */
145
- _shouldSkipIndex(index, allowedIndexRange, currentScrollerPos) {
146
- return (
147
- currentScrollerPos !== 0 &&
148
- index >= currentScrollerPos - allowedIndexRange &&
149
- index <= currentScrollerPos + allowedIndexRange
150
- );
151
- }
152
-
153
144
  /** @private */
154
145
  _shouldLoadPage(page) {
155
- if (!this.filteredItems || this._forceNextRequest) {
146
+ if (this._forceNextRequest) {
156
147
  this._forceNextRequest = false;
157
148
  return true;
158
149
  }
@@ -60,7 +60,7 @@ export const ComboBoxItemMixin = (superClass) =>
60
60
  }
61
61
 
62
62
  static get observers() {
63
- return ['__rendererOrItemChanged(renderer, index, item.*, selected, focused)', '__updateLabel(label, renderer)'];
63
+ return ['__rendererOrItemChanged(renderer, index, item, selected, focused)', '__updateLabel(label, renderer)'];
64
64
  }
65
65
 
66
66
  static get observedAttributes() {
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2015 - 2024 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 { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
8
+ import type { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
9
+ import type { ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
10
+
11
+ export declare function ComboBoxLightMixin<TItem, T extends Constructor<HTMLElement>>(
12
+ base: T,
13
+ ): Constructor<ComboBoxDataProviderMixinClass<TItem>> &
14
+ Constructor<ComboBoxLightMixinClass> &
15
+ Constructor<ComboBoxMixinClass<TItem>> &
16
+ Constructor<ValidateMixinClass> &
17
+ T;
18
+
19
+ export declare class ComboBoxLightMixinClass {
20
+ /**
21
+ * Name of the two-way data-bindable property representing the
22
+ * value of the custom input field.
23
+ * @attr {string} attr-for-value
24
+ */
25
+ attrForValue: string;
26
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2015 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { dashToCamelCase } from '@polymer/polymer/lib/utils/case-map.js';
7
+ import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
8
+ import { ValidateMixin } from '@vaadin/field-base/src/validate-mixin.js';
9
+ import { ComboBoxDataProviderMixin } from './vaadin-combo-box-data-provider-mixin.js';
10
+ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
11
+
12
+ /**
13
+ * @polymerMixin
14
+ * @mixes ComboBoxDataProviderMixin
15
+ * @mixes ComboBoxMixin
16
+ * @mixes ValidateMixin
17
+ */
18
+ export const ComboBoxLightMixin = (superClass) =>
19
+ class ComboBoxLightMixinClass extends ComboBoxDataProviderMixin(ComboBoxMixin(ValidateMixin(superClass))) {
20
+ static get properties() {
21
+ return {
22
+ /**
23
+ * Name of the two-way data-bindable property representing the
24
+ * value of the custom input field.
25
+ * @attr {string} attr-for-value
26
+ * @type {string}
27
+ */
28
+ attrForValue: {
29
+ type: String,
30
+ value: 'value',
31
+ },
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Used by `InputControlMixin` as a reference to the clear button element.
37
+ * @protected
38
+ * @return {!HTMLElement}
39
+ */
40
+ get clearElement() {
41
+ return this.querySelector('.clear-button');
42
+ }
43
+
44
+ /**
45
+ * Override this getter from `InputMixin` to allow using
46
+ * an arbitrary property name instead of `value`
47
+ * for accessing the input element's value.
48
+ *
49
+ * @protected
50
+ * @override
51
+ * @return {string}
52
+ */
53
+ get _inputElementValueProperty() {
54
+ return dashToCamelCase(this.attrForValue);
55
+ }
56
+
57
+ /**
58
+ * @protected
59
+ * @override
60
+ * @return {HTMLInputElement | undefined}
61
+ */
62
+ get _nativeInput() {
63
+ const input = this.inputElement;
64
+
65
+ if (input) {
66
+ // Support `<input class="input">`
67
+ if (input instanceof HTMLInputElement) {
68
+ return input;
69
+ }
70
+
71
+ // Support `<input>` in light DOM (e.g. `vaadin-text-field`)
72
+ const slottedInput = input.querySelector('input');
73
+ if (slottedInput) {
74
+ return slottedInput;
75
+ }
76
+
77
+ if (input.shadowRoot) {
78
+ // Support `<input>` in Shadow DOM (e.g. `mwc-textfield`)
79
+ const shadowInput = input.shadowRoot.querySelector('input');
80
+ if (shadowInput) {
81
+ return shadowInput;
82
+ }
83
+ }
84
+ }
85
+
86
+ return undefined;
87
+ }
88
+
89
+ /** @protected */
90
+ ready() {
91
+ super.ready();
92
+
93
+ this._toggleElement = this.querySelector('.toggle-button');
94
+
95
+ // Wait until the slotted input DOM is ready
96
+ afterNextRender(this, () => {
97
+ this._setInputElement(this.querySelector('vaadin-text-field,.input'));
98
+ this._revertInputValue();
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Returns true if the current input value satisfies all constraints (if any).
104
+ * @return {boolean}
105
+ */
106
+ checkValidity() {
107
+ if (this.inputElement && this.inputElement.validate) {
108
+ return this.inputElement.validate();
109
+ }
110
+ return super.checkValidity();
111
+ }
112
+
113
+ /**
114
+ * @protected
115
+ * @override
116
+ */
117
+ _isClearButton(event) {
118
+ return (
119
+ super._isClearButton(event) ||
120
+ (event.type === 'input' && !event.isTrusted) || // Fake input event dispatched by clear button
121
+ event.composedPath()[0].getAttribute('part') === 'clear-button'
122
+ );
123
+ }
124
+
125
+ /**
126
+ * @protected
127
+ * @override
128
+ */
129
+ _shouldRemoveFocus(event) {
130
+ const isBlurringControlButtons = event.target === this._toggleElement || event.target === this.clearElement;
131
+ const isFocusingInputElement = event.relatedTarget && event.relatedTarget === this._nativeInput;
132
+
133
+ // prevent closing the overlay when moving focus from clear or toggle buttons to the internal input
134
+ if (isBlurringControlButtons && isFocusingInputElement) {
135
+ return false;
136
+ }
137
+
138
+ return super._shouldRemoveFocus(event);
139
+ }
140
+ };
@@ -11,6 +11,7 @@ import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.j
11
11
  import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
12
  import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
13
13
  import type { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
14
+ import type { ComboBoxLightMixinClass } from './vaadin-combo-box-light-mixin.js';
14
15
  import type { ComboBoxDefaultItem, ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
15
16
  export {
16
17
  ComboBoxDataProvider,
@@ -126,13 +127,6 @@ export interface ComboBoxLightEventMap<TItem> extends HTMLElementEventMap {
126
127
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
127
128
  */
128
129
  declare class ComboBoxLight<TItem = ComboBoxDefaultItem> extends HTMLElement {
129
- /**
130
- * Name of the two-way data-bindable property representing the
131
- * value of the custom input field.
132
- * @attr {string} attr-for-value
133
- */
134
- attrForValue: string;
135
-
136
130
  addEventListener<K extends keyof ComboBoxLightEventMap<TItem>>(
137
131
  type: K,
138
132
  listener: (this: ComboBoxLight<TItem>, ev: ComboBoxLightEventMap<TItem>[K]) => void,
@@ -148,6 +142,7 @@ declare class ComboBoxLight<TItem = ComboBoxDefaultItem> extends HTMLElement {
148
142
 
149
143
  interface ComboBoxLight<TItem = ComboBoxDefaultItem>
150
144
  extends ComboBoxDataProviderMixinClass<TItem>,
145
+ ComboBoxLightMixinClass,
151
146
  ComboBoxMixinClass<TItem>,
152
147
  KeyboardMixinClass,
153
148
  InputMixinClass,
@@ -6,14 +6,10 @@
6
6
  import './vaadin-combo-box-item.js';
7
7
  import './vaadin-combo-box-overlay.js';
8
8
  import './vaadin-combo-box-scroller.js';
9
- import { dashToCamelCase } from '@polymer/polymer/lib/utils/case-map.js';
10
- import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
11
9
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
12
10
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
13
- import { ValidateMixin } from '@vaadin/field-base/src/validate-mixin.js';
14
11
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
15
- import { ComboBoxDataProviderMixin } from './vaadin-combo-box-data-provider-mixin.js';
16
- import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
12
+ import { ComboBoxLightMixin } from './vaadin-combo-box-light-mixin.js';
17
13
 
18
14
  /**
19
15
  * `<vaadin-combo-box-light>` is a customizable version of the `<vaadin-combo-box>` providing
@@ -63,12 +59,10 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
63
59
  *
64
60
  * @customElement
65
61
  * @extends HTMLElement
66
- * @mixes ComboBoxDataProviderMixin
67
- * @mixes ComboBoxMixin
62
+ * @mixes ComboBoxLightMixin
68
63
  * @mixes ThemableMixin
69
- * @mixes ValidateMixin
70
64
  */
71
- class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ValidateMixin(ThemableMixin(PolymerElement)))) {
65
+ class ComboBoxLight extends ComboBoxLightMixin(ThemableMixin(PolymerElement)) {
72
66
  static get is() {
73
67
  return 'vaadin-combo-box-light';
74
68
  }
@@ -94,124 +88,6 @@ class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ValidateMixi
94
88
  ></vaadin-combo-box-overlay>
95
89
  `;
96
90
  }
97
-
98
- static get properties() {
99
- return {
100
- /**
101
- * Name of the two-way data-bindable property representing the
102
- * value of the custom input field.
103
- * @attr {string} attr-for-value
104
- * @type {string}
105
- */
106
- attrForValue: {
107
- type: String,
108
- value: 'value',
109
- },
110
- };
111
- }
112
-
113
- /**
114
- * Used by `InputControlMixin` as a reference to the clear button element.
115
- * @protected
116
- * @return {!HTMLElement}
117
- */
118
- get clearElement() {
119
- return this.querySelector('.clear-button');
120
- }
121
-
122
- /**
123
- * Override this getter from `InputMixin` to allow using
124
- * an arbitrary property name instead of `value`
125
- * for accessing the input element's value.
126
- *
127
- * @protected
128
- * @override
129
- * @return {string}
130
- */
131
- get _inputElementValueProperty() {
132
- return dashToCamelCase(this.attrForValue);
133
- }
134
-
135
- /**
136
- * @protected
137
- * @override
138
- * @return {HTMLInputElement | undefined}
139
- */
140
- get _nativeInput() {
141
- const input = this.inputElement;
142
-
143
- if (input) {
144
- // Support `<input class="input">`
145
- if (input instanceof HTMLInputElement) {
146
- return input;
147
- }
148
-
149
- // Support `<input>` in light DOM (e.g. `vaadin-text-field`)
150
- const slottedInput = input.querySelector('input');
151
- if (slottedInput) {
152
- return slottedInput;
153
- }
154
-
155
- if (input.shadowRoot) {
156
- // Support `<input>` in Shadow DOM (e.g. `mwc-textfield`)
157
- const shadowInput = input.shadowRoot.querySelector('input');
158
- if (shadowInput) {
159
- return shadowInput;
160
- }
161
- }
162
- }
163
-
164
- return undefined;
165
- }
166
-
167
- /** @protected */
168
- ready() {
169
- super.ready();
170
-
171
- this._toggleElement = this.querySelector('.toggle-button');
172
-
173
- // Wait until the slotted input DOM is ready
174
- afterNextRender(this, () => {
175
- this._setInputElement(this.querySelector('vaadin-text-field,.input'));
176
- this._revertInputValue();
177
- });
178
- }
179
-
180
- /**
181
- * Returns true if the current input value satisfies all constraints (if any).
182
- * @return {boolean}
183
- */
184
- checkValidity() {
185
- if (this.inputElement && this.inputElement.validate) {
186
- return this.inputElement.validate();
187
- }
188
- return super.checkValidity();
189
- }
190
-
191
- /** @protected */
192
- _isClearButton(event) {
193
- return (
194
- super._isClearButton(event) ||
195
- (event.type === 'input' && !event.isTrusted) || // Fake input event dispatched by clear button
196
- event.composedPath()[0].getAttribute('part') === 'clear-button'
197
- );
198
- }
199
-
200
- /**
201
- * @protected
202
- * @override
203
- */
204
- _shouldRemoveFocus(event) {
205
- const isBlurringControlButtons = event.target === this._toggleElement || event.target === this.clearElement;
206
- const isFocusingInputElement = event.relatedTarget && event.relatedTarget === this._nativeInput;
207
-
208
- // prevent closing the overlay when moving focus from clear or toggle buttons to the internal input
209
- if (isBlurringControlButtons && isFocusingInputElement) {
210
- return false;
211
- }
212
-
213
- return super._shouldRemoveFocus(event);
214
- }
215
91
  }
216
92
 
217
93
  defineCustomElement(ComboBoxLight);