@vaadin/virtual-list 24.7.0-alpha1 → 24.7.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/virtual-list",
3
- "version": "24.7.0-alpha1",
3
+ "version": "24.7.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -39,21 +39,22 @@
39
39
  "dependencies": {
40
40
  "@open-wc/dedupe-mixin": "^1.3.0",
41
41
  "@polymer/polymer": "^3.0.0",
42
- "@vaadin/component-base": "24.7.0-alpha1",
43
- "@vaadin/lit-renderer": "24.7.0-alpha1",
44
- "@vaadin/vaadin-lumo-styles": "24.7.0-alpha1",
45
- "@vaadin/vaadin-material-styles": "24.7.0-alpha1",
46
- "@vaadin/vaadin-themable-mixin": "24.7.0-alpha1",
42
+ "@vaadin/component-base": "24.7.0-alpha10",
43
+ "@vaadin/lit-renderer": "24.7.0-alpha10",
44
+ "@vaadin/vaadin-lumo-styles": "24.7.0-alpha10",
45
+ "@vaadin/vaadin-material-styles": "24.7.0-alpha10",
46
+ "@vaadin/vaadin-themable-mixin": "24.7.0-alpha10",
47
47
  "lit": "^3.0.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@vaadin/chai-plugins": "24.7.0-alpha1",
51
- "@vaadin/testing-helpers": "^1.0.0",
50
+ "@vaadin/chai-plugins": "24.7.0-alpha10",
51
+ "@vaadin/test-runner-commands": "24.7.0-alpha10",
52
+ "@vaadin/testing-helpers": "^1.1.0",
52
53
  "sinon": "^18.0.0"
53
54
  },
54
55
  "web-types": [
55
56
  "web-types.json",
56
57
  "web-types.lit.json"
57
58
  ],
58
- "gitHead": "04be941c9a7b659871c97f31b9cc3ffd7528087b"
59
+ "gitHead": "c0f8933df2a6a40648d3fb9cfbae6bbf86a8aa90"
59
60
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { DirectiveResult } from 'lit/directive.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { directive } from 'lit/directive.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  export * from './vaadin-virtual-list.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, LitElement } from 'lit';
@@ -29,6 +29,7 @@ class VirtualList extends VirtualListMixin(ThemableMixin(ElementMixin(PolylitMix
29
29
  return [virtualListStyles];
30
30
  }
31
31
 
32
+ /** @protected */
32
33
  render() {
33
34
  return html`
34
35
  <div id="items">
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -53,6 +53,15 @@ export declare class VirtualListMixinClass<TItem = VirtualListDefaultItem> {
53
53
  */
54
54
  items: TItem[] | undefined;
55
55
 
56
+ /**
57
+ * A function that generates accessible names for virtual list items.
58
+ * The function gets the item as an argument and the
59
+ * return value should be a string representing that item. The
60
+ * result gets applied to the corresponding virtual list child element
61
+ * as an `aria-label` attribute.
62
+ */
63
+ itemAccessibleNameGenerator?: (item: TItem) => string;
64
+
56
65
  /**
57
66
  * Scroll to a specific index in the virtual list.
58
67
  */
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { isChrome, isSafari } from '@vaadin/component-base/src/browser-utils.js';
6
7
  import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
7
8
  import { OverflowController } from '@vaadin/component-base/src/overflow-controller.js';
8
9
  import { processTemplates } from '@vaadin/component-base/src/templates.js';
@@ -36,13 +37,25 @@ export const VirtualListMixin = (superClass) =>
36
37
  */
37
38
  renderer: { type: Function, sync: true },
38
39
 
40
+ /**
41
+ * A function that generates accessible names for virtual list items.
42
+ * The function gets the item as an argument and the
43
+ * return value should be a string representing that item. The
44
+ * result gets applied to the corresponding virtual list child element
45
+ * as an `aria-label` attribute.
46
+ */
47
+ itemAccessibleNameGenerator: {
48
+ type: Function,
49
+ sync: true,
50
+ },
51
+
39
52
  /** @private */
40
53
  __virtualizer: Object,
41
54
  };
42
55
  }
43
56
 
44
57
  static get observers() {
45
- return ['__itemsOrRendererChanged(items, renderer, __virtualizer)'];
58
+ return ['__itemsOrRendererChanged(items, renderer, __virtualizer, itemAccessibleNameGenerator)'];
46
59
  }
47
60
 
48
61
  /**
@@ -65,7 +78,7 @@ export const VirtualListMixin = (superClass) =>
65
78
 
66
79
  constructor() {
67
80
  super();
68
- this.__onDragStart = this.__onDragStart.bind(this);
81
+ this.__onDocumentDragStart = this.__onDocumentDragStart.bind(this);
69
82
  }
70
83
 
71
84
  /** @protected */
@@ -84,22 +97,19 @@ export const VirtualListMixin = (superClass) =>
84
97
  this.addController(this.__overflowController);
85
98
 
86
99
  processTemplates(this);
100
+ this.__updateAria();
87
101
  }
88
102
 
89
103
  /** @protected */
90
104
  connectedCallback() {
91
105
  super.connectedCallback();
92
- // Chromium based browsers cannot properly generate drag images for elements
93
- // that have children with massive heights. This workaround prevents crashes
94
- // and performance issues by excluding the items from the drag image.
95
- // https://github.com/vaadin/web-components/issues/7985
96
- document.addEventListener('dragstart', this.__onDragStart, { capture: true });
106
+ document.addEventListener('dragstart', this.__onDocumentDragStart, { capture: true });
97
107
  }
98
108
 
99
109
  /** @protected */
100
110
  disconnectedCallback() {
101
111
  super.disconnectedCallback();
102
- document.removeEventListener('dragstart', this.__onDragStart, { capture: true });
112
+ document.removeEventListener('dragstart', this.__onDocumentDragStart, { capture: true });
103
113
  }
104
114
 
105
115
  /**
@@ -116,18 +126,34 @@ export const VirtualListMixin = (superClass) =>
116
126
  return [...Array(count)].map(() => document.createElement('div'));
117
127
  }
118
128
 
129
+ /** @private */
130
+ __updateAria() {
131
+ this.role = 'list';
132
+ }
133
+
119
134
  /** @private */
120
135
  __updateElement(el, index) {
136
+ const item = this.items[index];
137
+ el.ariaSetSize = String(this.items.length);
138
+ el.ariaPosInSet = String(index + 1);
139
+ el.ariaLabel = this.itemAccessibleNameGenerator ? this.itemAccessibleNameGenerator(item) : null;
140
+ this.__updateElementRole(el);
141
+
121
142
  if (el.__renderer !== this.renderer) {
122
143
  el.__renderer = this.renderer;
123
144
  this.__clearRenderTargetContent(el);
124
145
  }
125
146
 
126
147
  if (this.renderer) {
127
- this.renderer(el, this, { item: this.items[index], index });
148
+ this.renderer(el, this, { item, index });
128
149
  }
129
150
  }
130
151
 
152
+ /** @private */
153
+ __updateElementRole(el) {
154
+ el.role = 'listitem';
155
+ }
156
+
131
157
  /**
132
158
  * Clears the content of a render target.
133
159
  * @private
@@ -153,25 +179,50 @@ export const VirtualListMixin = (superClass) =>
153
179
  }
154
180
  }
155
181
 
156
- /** @private */
157
- __onDragStart(e) {
158
- // The dragged element can be the element itself or a parent of the element
159
- if (!e.target.contains(this)) {
160
- return;
161
- }
162
- // The threshold value 20000 provides a buffer to both
163
- // - avoid the crash and the performance issues
164
- // - unnecessarily avoid excluding items from the drag image
165
- if (this.$.items.offsetHeight > 20000) {
166
- const initialItemsMaxHeight = this.$.items.style.maxHeight;
167
- const initialVirtualListOverflow = this.style.overflow;
168
- // Momentarily hides the items until the browser starts generating the
169
- // drag image.
170
- this.$.items.style.maxHeight = '0';
171
- this.style.overflow = 'hidden';
182
+ /**
183
+ * Webkit-based browsers have issues with generating drag images
184
+ * for elements that have children with massive heights. Chromium
185
+ * browsers crash, while Safari experiences significant performance
186
+ * issues. To mitigate these issues, we hide the items container
187
+ * when drag starts to remove it from the drag image.
188
+ *
189
+ * Virtual lists with fewer rows also have issues on Chromium and Safari
190
+ * where the drag image is not properly clipped and may include
191
+ * content outside the virtual list. Temporary inline styles are applied
192
+ * to mitigate this issue.
193
+ *
194
+ * Related issues:
195
+ * - https://github.com/vaadin/web-components/issues/7985
196
+ * - https://issues.chromium.org/issues/383356871
197
+ * - https://github.com/vaadin/web-components/issues/8386
198
+ *
199
+ * @private
200
+ */
201
+ __onDocumentDragStart(e) {
202
+ if (e.target.contains(this)) {
203
+ // Record the original inline styles to restore them later
204
+ const elements = [e.target, this.$.items];
205
+ const originalInlineStyles = elements.map((element) => element.style.cssText);
206
+
207
+ // With a large number of rows, hide the items
208
+ if (this.scrollHeight > 20000) {
209
+ this.$.items.style.display = 'none';
210
+ }
211
+
212
+ // Workaround content outside the virtual list ending up in the drag image on Chromium
213
+ if (isChrome) {
214
+ e.target.style.willChange = 'transform';
215
+ }
216
+
217
+ // Workaround text content outside the virtual list ending up in the drag image on Safari
218
+ if (isSafari) {
219
+ this.$.items.style.maxHeight = '100%';
220
+ }
221
+
172
222
  requestAnimationFrame(() => {
173
- this.$.items.style.maxHeight = initialItemsMaxHeight;
174
- this.style.overflow = initialVirtualListOverflow;
223
+ elements.forEach((element, index) => {
224
+ element.style.cssText = originalInlineStyles[index];
225
+ });
175
226
  });
176
227
  }
177
228
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { CSSResult } from 'lit';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { css } from 'lit';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 - 2024 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/virtual-list",
4
- "version": "24.7.0-alpha1",
4
+ "version": "24.7.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -43,6 +43,17 @@
43
43
  "undefined"
44
44
  ]
45
45
  }
46
+ },
47
+ {
48
+ "name": "itemAccessibleNameGenerator",
49
+ "description": "A function that generates accessible names for virtual list items.\nThe function gets the item as an argument and the\nreturn value should be a string representing that item. The\nresult gets applied to the corresponding virtual list child element\nas an `aria-label` attribute.",
50
+ "value": {
51
+ "type": [
52
+ "Function",
53
+ "null",
54
+ "undefined"
55
+ ]
56
+ }
46
57
  }
47
58
  ],
48
59
  "events": []
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/virtual-list",
4
- "version": "24.7.0-alpha1",
4
+ "version": "24.7.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -32,6 +32,13 @@
32
32
  "value": {
33
33
  "kind": "expression"
34
34
  }
35
+ },
36
+ {
37
+ "name": ".itemAccessibleNameGenerator",
38
+ "description": "A function that generates accessible names for virtual list items.\nThe function gets the item as an argument and the\nreturn value should be a string representing that item. The\nresult gets applied to the corresponding virtual list child element\nas an `aria-label` attribute.",
39
+ "value": {
40
+ "kind": "expression"
41
+ }
35
42
  }
36
43
  ]
37
44
  }