@vaadin/component-base 25.0.0-alpha9 → 25.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/component-base",
3
- "version": "25.0.0-alpha9",
3
+ "version": "25.0.0-beta2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,8 +23,7 @@
23
23
  "custom_typings",
24
24
  "index.d.ts",
25
25
  "index.js",
26
- "src",
27
- "!src/style-props.js"
26
+ "src"
28
27
  ],
29
28
  "keywords": [
30
29
  "Vaadin",
@@ -34,14 +33,15 @@
34
33
  "dependencies": {
35
34
  "@open-wc/dedupe-mixin": "^1.3.0",
36
35
  "@vaadin/vaadin-development-mode-detector": "^2.0.0",
36
+ "@vaadin/vaadin-themable-mixin": "25.0.0-beta2",
37
37
  "@vaadin/vaadin-usage-statistics": "^2.1.0",
38
38
  "lit": "^3.0.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@vaadin/chai-plugins": "25.0.0-alpha9",
42
- "@vaadin/test-runner-commands": "25.0.0-alpha9",
41
+ "@vaadin/chai-plugins": "25.0.0-beta2",
42
+ "@vaadin/test-runner-commands": "25.0.0-beta2",
43
43
  "@vaadin/testing-helpers": "^2.0.0",
44
- "sinon": "^18.0.0"
44
+ "sinon": "^21.0.0"
45
45
  },
46
- "gitHead": "bbe4720721e0955ffc87a79b412bee38b1f0eb1e"
46
+ "gitHead": "e078f8371ae266f05c7ca1ec25686cc489c83f24"
47
47
  }
@@ -48,7 +48,7 @@ export class Cache {
48
48
  * @type {Record<number, Cache>}
49
49
  * @private
50
50
  */
51
- __subCacheByIndex = {};
51
+ #subCacheByIndex = {};
52
52
 
53
53
  /**
54
54
  * The number of items.
@@ -56,7 +56,7 @@ export class Cache {
56
56
  * @type {number}
57
57
  * @private
58
58
  */
59
- __size = 0;
59
+ #size = 0;
60
60
 
61
61
  /**
62
62
  * The total number of items, including items from expanded sub-caches.
@@ -64,7 +64,7 @@ export class Cache {
64
64
  * @type {number}
65
65
  * @private
66
66
  */
67
- __flatSize = 0;
67
+ #flatSize = 0;
68
68
 
69
69
  /**
70
70
  * @param {Cache['context']} context
@@ -79,7 +79,7 @@ export class Cache {
79
79
  this.size = size;
80
80
  this.parentCache = parentCache;
81
81
  this.parentCacheIndex = parentCacheIndex;
82
- this.__flatSize = size || 0;
82
+ this.#flatSize = size || 0;
83
83
  }
84
84
 
85
85
  /**
@@ -98,7 +98,7 @@ export class Cache {
98
98
  * @return {Cache[]}
99
99
  */
100
100
  get subCaches() {
101
- return Object.values(this.__subCacheByIndex);
101
+ return Object.values(this.#subCacheByIndex);
102
102
  }
103
103
 
104
104
  /**
@@ -120,7 +120,7 @@ export class Cache {
120
120
  * @return {number}
121
121
  */
122
122
  get flatSize() {
123
- return this.__flatSize;
123
+ return this.#flatSize;
124
124
  }
125
125
 
126
126
  /**
@@ -129,7 +129,7 @@ export class Cache {
129
129
  * @return {number}
130
130
  */
131
131
  get size() {
132
- return this.__size;
132
+ return this.#size;
133
133
  }
134
134
 
135
135
  /**
@@ -138,12 +138,12 @@ export class Cache {
138
138
  * @param {number} size
139
139
  */
140
140
  set size(size) {
141
- const oldSize = this.__size;
141
+ const oldSize = this.#size;
142
142
  if (oldSize === size) {
143
143
  return;
144
144
  }
145
145
 
146
- this.__size = size;
146
+ this.#size = size;
147
147
 
148
148
  if (this.context.placeholder !== undefined) {
149
149
  this.items.length = size || 0;
@@ -152,6 +152,10 @@ export class Cache {
152
152
  }
153
153
  }
154
154
 
155
+ if (this.items.length > size) {
156
+ this.items.length = size || 0;
157
+ }
158
+
155
159
  Object.keys(this.pendingRequests).forEach((page) => {
156
160
  const startIndex = parseInt(page) * this.pageSize;
157
161
  if (startIndex >= this.size || 0) {
@@ -164,7 +168,7 @@ export class Cache {
164
168
  * Recalculates the flattened size for the cache and its descendant caches recursively.
165
169
  */
166
170
  recalculateFlatSize() {
167
- this.__flatSize =
171
+ this.#flatSize =
168
172
  !this.parentItem || this.context.isExpanded(this.parentItem)
169
173
  ? this.size +
170
174
  this.subCaches.reduce((total, subCache) => {
@@ -199,7 +203,7 @@ export class Cache {
199
203
  * @return {Cache | undefined}
200
204
  */
201
205
  getSubCache(index) {
202
- return this.__subCacheByIndex[index];
206
+ return this.#subCacheByIndex[index];
203
207
  }
204
208
 
205
209
  /**
@@ -209,14 +213,14 @@ export class Cache {
209
213
  * @param {number} index
210
214
  */
211
215
  removeSubCache(index) {
212
- delete this.__subCacheByIndex[index];
216
+ delete this.#subCacheByIndex[index];
213
217
  }
214
218
 
215
219
  /**
216
220
  * Removes all sub-caches.
217
221
  */
218
222
  removeSubCaches() {
219
- this.__subCacheByIndex = {};
223
+ this.#subCacheByIndex = {};
220
224
  }
221
225
 
222
226
  /**
@@ -228,7 +232,7 @@ export class Cache {
228
232
  */
229
233
  createSubCache(index) {
230
234
  const subCache = new Cache(this.context, this.pageSize, 0, this, index);
231
- this.__subCacheByIndex[index] = subCache;
235
+ this.#subCacheByIndex[index] = subCache;
232
236
  return subCache;
233
237
  }
234
238
 
@@ -85,7 +85,7 @@ export class DataProviderController extends EventTarget {
85
85
  this.isPlaceholder = isPlaceholder;
86
86
  this.dataProvider = dataProvider;
87
87
  this.dataProviderParams = dataProviderParams;
88
- this.rootCache = this.__createRootCache(size);
88
+ this.rootCache = this.#createRootCache(size);
89
89
  }
90
90
 
91
91
  /**
@@ -96,7 +96,7 @@ export class DataProviderController extends EventTarget {
96
96
  }
97
97
 
98
98
  /** @private */
99
- get __cacheContext() {
99
+ get #cacheContext() {
100
100
  return {
101
101
  isExpanded: this.isExpanded,
102
102
  placeholder: this.placeholder,
@@ -143,7 +143,7 @@ export class DataProviderController extends EventTarget {
143
143
  * Clears the cache.
144
144
  */
145
145
  clearCache() {
146
- this.rootCache = this.__createRootCache(this.rootCache.size);
146
+ this.rootCache = this.#createRootCache(this.rootCache.size);
147
147
  }
148
148
 
149
149
  /**
@@ -198,8 +198,8 @@ export class DataProviderController extends EventTarget {
198
198
  ensureFlatIndexLoaded(flatIndex) {
199
199
  const { cache, page, item } = this.getFlatIndexContext(flatIndex);
200
200
 
201
- if (!this.__isItemLoaded(item)) {
202
- this.__loadCachePage(cache, page);
201
+ if (!this.#isItemLoaded(item)) {
202
+ this.#loadCachePage(cache, page);
203
203
  }
204
204
  }
205
205
 
@@ -213,9 +213,9 @@ export class DataProviderController extends EventTarget {
213
213
  ensureFlatIndexHierarchy(flatIndex) {
214
214
  const { cache, item, index } = this.getFlatIndexContext(flatIndex);
215
215
 
216
- if (this.__isItemLoaded(item) && this.isExpanded(item) && !cache.getSubCache(index)) {
216
+ if (this.#isItemLoaded(item) && this.isExpanded(item) && !cache.getSubCache(index)) {
217
217
  const subCache = cache.createSubCache(index);
218
- this.__loadCachePage(subCache, 0);
218
+ this.#loadCachePage(subCache, 0);
219
219
  }
220
220
  }
221
221
 
@@ -223,17 +223,28 @@ export class DataProviderController extends EventTarget {
223
223
  * Loads the first page into the root cache.
224
224
  */
225
225
  loadFirstPage() {
226
- this.__loadCachePage(this.rootCache, 0);
226
+ this.#loadCachePage(this.rootCache, 0);
227
+ }
228
+
229
+ /**
230
+ * Override to prevent loading of the cache page under certain conditions.
231
+ *
232
+ * @param {Cache} cache
233
+ * @param {number} page
234
+ * @protected
235
+ */
236
+ _shouldLoadCachePage(_cache, _page) {
237
+ return true;
227
238
  }
228
239
 
229
240
  /** @private */
230
- __createRootCache(size) {
231
- return new Cache(this.__cacheContext, this.pageSize, size);
241
+ #createRootCache(size) {
242
+ return new Cache(this.#cacheContext, this.pageSize, size);
232
243
  }
233
244
 
234
245
  /** @private */
235
- __loadCachePage(cache, page) {
236
- if (!this.dataProvider || cache.pendingRequests[page]) {
246
+ #loadCachePage(cache, page) {
247
+ if (!this.dataProvider || cache.pendingRequests[page] || !this._shouldLoadCachePage(cache, page)) {
237
248
  return;
238
249
  }
239
250
 
@@ -277,7 +288,7 @@ export class DataProviderController extends EventTarget {
277
288
  }
278
289
 
279
290
  /** @private */
280
- __isItemLoaded(item) {
291
+ #isItemLoaded(item) {
281
292
  if (this.isPlaceholder) {
282
293
  return !this.isPlaceholder(item);
283
294
  } else if (this.placeholder) {
@@ -18,6 +18,7 @@
18
18
  *
19
19
  * @param {Cache} cache
20
20
  * @param {number} flatIndex
21
+ * @param {number} level
21
22
  */
22
23
  export function getFlatIndexContext(cache, flatIndex, level = 0) {
23
24
  let levelIndex = flatIndex;
@@ -53,7 +54,6 @@ export function getFlatIndexContext(cache, flatIndex, level = 0) {
53
54
  *
54
55
  * If the item isn't found, the method returns undefined.
55
56
  *
56
- * @param {Cache} cache
57
57
  * @param {{ getItemId: (item: unknown) => unknown}} context
58
58
  * @param {Cache} cache
59
59
  * @param {unknown} targetItem
package/src/define.js CHANGED
@@ -13,7 +13,7 @@ function dashToCamelCase(dash) {
13
13
 
14
14
  const experimentalMap = {};
15
15
 
16
- export function defineCustomElement(CustomElement, version = '25.0.0-alpha9') {
16
+ export function defineCustomElement(CustomElement, version = '25.0.0-beta2') {
17
17
  Object.defineProperty(CustomElement, 'version', {
18
18
  get() {
19
19
  return version;
@@ -48,9 +48,10 @@ export const ElementMixin = (superClass) =>
48
48
  window.Vaadin.registrations.push(this);
49
49
  registered.add(is);
50
50
 
51
- if (window.Vaadin.developmentModeCallback) {
51
+ const callback = window.Vaadin.developmentModeCallback;
52
+ if (callback) {
52
53
  statsJob = Debouncer.debounce(statsJob, idlePeriod, () => {
53
- window.Vaadin.developmentModeCallback['vaadin-usage-statistics']();
54
+ callback['vaadin-usage-statistics']();
54
55
  });
55
56
  enqueueDebouncer(statsJob);
56
57
  }
@@ -215,26 +215,10 @@ const PolylitMixinImplementation = (superclass) => {
215
215
  };
216
216
  }
217
217
 
218
- constructor() {
219
- super();
220
- this.__hasPolylitMixin = true;
221
- }
222
-
223
218
  /** @protected */
224
219
  connectedCallback() {
225
220
  super.connectedCallback();
226
221
 
227
- // Components like `vaadin-overlay` are teleported to the body element when opened.
228
- // If their opened state is set as an attribute, the teleportation happens immediately
229
- // after they are connected to the DOM. This means they will be outside the scope of
230
- // querySelectorAll in the parent component's `firstUpdated()`. To ensure their reference
231
- // is still registered in the $ map, we propagate the reference here.
232
- const parentHost = this.getRootNode().host;
233
- if (parentHost && parentHost.__hasPolylitMixin && this.id) {
234
- parentHost.$ ||= {};
235
- parentHost.$[this.id] = this;
236
- }
237
-
238
222
  const { polylitConfig } = this.constructor;
239
223
  if (!this.hasUpdated && !polylitConfig.asyncFirstRender) {
240
224
  this.performUpdate();
@@ -249,10 +233,8 @@ const PolylitMixinImplementation = (superclass) => {
249
233
  this.$ = {};
250
234
  }
251
235
 
252
- [...Object.values(this.$), this.renderRoot].forEach((node) => {
253
- node.querySelectorAll('[id]').forEach((node) => {
254
- this.$[node.id] = node;
255
- });
236
+ this.renderRoot.querySelectorAll('[id]').forEach((node) => {
237
+ this.$[node.id] = node;
256
238
  });
257
239
  }
258
240
 
@@ -15,7 +15,7 @@ export class SlotController extends EventTarget {
15
15
  * Ensure that every instance has unique ID.
16
16
  *
17
17
  * @param {HTMLElement} host
18
- * @param {string} slotName
18
+ * @param {string} prefix
19
19
  * @return {string}
20
20
  * @protected
21
21
  */
@@ -24,7 +24,7 @@ export const loaderStyles = css`
24
24
  spin var(--vaadin-spinner-animation-duration, 1s) linear infinite,
25
25
  fade-in 0.3s 0.3s both;
26
26
  border: var(--vaadin-spinner-width, 2px) solid;
27
- --_spinner-color: var(--vaadin-spinner-color, var(--vaadin-color));
27
+ --_spinner-color: var(--vaadin-spinner-color, var(--vaadin-text-color));
28
28
  --_spinner-color2: color-mix(in srgb, var(--_spinner-color) 20%, transparent);
29
29
  border-color: var(--_spinner-color) var(--_spinner-color) var(--_spinner-color2) var(--_spinner-color2);
30
30
  border-radius: 50%;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 2025 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
+ import { addGlobalThemeStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
8
+
9
+ addGlobalThemeStyles(
10
+ 'vaadin-base',
11
+ css`
12
+ @layer vaadin.base {
13
+ :where(html) {
14
+ /* Background color */
15
+ --vaadin-background-color: light-dark(#fff, #222);
16
+
17
+ /* Container colors */
18
+ --vaadin-background-container: color-mix(in oklab, var(--vaadin-text-color) 5%, var(--vaadin-background-color));
19
+ --vaadin-background-container-strong: color-mix(
20
+ in oklab,
21
+ var(--vaadin-text-color) 10%,
22
+ var(--vaadin-background-color)
23
+ );
24
+
25
+ /* Border colors */
26
+ --vaadin-border-color-secondary: color-mix(in oklab, var(--vaadin-text-color) 24%, transparent);
27
+ --vaadin-border-color: color-mix(in oklab, var(--vaadin-text-color) 48%, transparent); /* Above 3:1 contrast */
28
+
29
+ /* Text colors */
30
+ /* Above 3:1 contrast */
31
+ --vaadin-text-color-disabled: color-mix(in oklab, var(--vaadin-text-color) 48%, transparent);
32
+ /* Above 4.5:1 contrast */
33
+ --vaadin-text-color-secondary: color-mix(in oklab, var(--vaadin-text-color) 68%, transparent);
34
+ /* Above 7:1 contrast */
35
+ --vaadin-text-color: light-dark(#1f1f1f, white);
36
+
37
+ /* Padding */
38
+ --vaadin-padding-xs: 6px;
39
+ --vaadin-padding-s: 8px;
40
+ --vaadin-padding-m: 12px;
41
+ --vaadin-padding-l: 16px;
42
+ --vaadin-padding-xl: 24px;
43
+ --vaadin-padding-container: var(--vaadin-padding-xs) var(--vaadin-padding-s);
44
+
45
+ /* Gap/spacing */
46
+ --vaadin-gap-xs: 6px;
47
+ --vaadin-gap-s: 8px;
48
+ --vaadin-gap-m: 12px;
49
+ --vaadin-gap-l: 16px;
50
+ --vaadin-gap-xl: 24px;
51
+
52
+ /* Border radius */
53
+ --vaadin-radius-s: 3px;
54
+ --vaadin-radius-m: 6px;
55
+ --vaadin-radius-l: 12px;
56
+
57
+ /* Focus outline */
58
+ --vaadin-focus-ring-width: 2px;
59
+ --vaadin-focus-ring-color: var(--vaadin-text-color);
60
+
61
+ /* Icons, used as mask-image */
62
+ --_vaadin-icon-arrow-up: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" /></svg>');
63
+ --_vaadin-icon-calendar: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" /></svg>');
64
+ --_vaadin-icon-checkmark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /></svg>');
65
+ --_vaadin-icon-chevron-down: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /></svg>');
66
+ --_vaadin-icon-clock: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" /></svg>');
67
+ --_vaadin-icon-cross: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>');
68
+ --_vaadin-icon-drag: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M11 7c0 .82843-.6716 1.5-1.5 1.5C8.67157 8.5 8 7.82843 8 7s.67157-1.5 1.5-1.5c.8284 0 1.5.67157 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5-.82843 0-1.5-.6716-1.5-1.5s.67157-1.5 1.5-1.5c.8284 0 1.5.6716 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5-.82843 0-1.5-.6716-1.5-1.5s.67157-1.5 1.5-1.5c.8284 0 1.5.6716 1.5 1.5Zm5-10c0 .82843-.6716 1.5-1.5 1.5S13 7.82843 13 7s.6716-1.5 1.5-1.5S16 6.17157 16 7Zm0 5c0 .8284-.6716 1.5-1.5 1.5S13 12.8284 13 12s.6716-1.5 1.5-1.5 1.5.6716 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5S13 17.8284 13 17s.6716-1.5 1.5-1.5 1.5.6716 1.5 1.5Z" fill="currentColor"/></svg>');
69
+ --_vaadin-icon-eye: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg>');
70
+ --_vaadin-icon-eye-slash: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" /></svg>');
71
+ --_vaadin-icon-fullscreen: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /></svg>');
72
+ --_vaadin-icon-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>');
73
+ --_vaadin-icon-link: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>');
74
+ --_vaadin-icon-menu: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /></svg>');
75
+ --_vaadin-icon-minus: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14" /></svg>');
76
+ --_vaadin-icon-paper-airplane: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" /></svg>');
77
+ --_vaadin-icon-pen: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/></svg>');
78
+ --_vaadin-icon-play: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" /></svg>');
79
+ --_vaadin-icon-plus: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>');
80
+ --_vaadin-icon-redo: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"/></svg>');
81
+ --_vaadin-icon-refresh: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M22 10C22 10 19.995 7.26822 18.3662 5.63824C16.7373 4.00827 14.4864 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.1031 21 19.5649 18.2543 20.6482 14.5M22 10V4M22 10H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>');
82
+ --_vaadin-icon-resize: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill-rule="evenodd" clip-rule="evenodd" d="M18.5303 7.46967c.2929.29289.2929.76777 0 1.06066L8.53033 18.5304c-.29289.2929-.76777.2929-1.06066 0s-.29289-.7678 0-1.0607L17.4697 7.46967c.2929-.29289.7677-.29289 1.0606 0Zm0 4.50003c.2929.2929.2929.7678 0 1.0607l-5.5 5.5c-.2929.2928-.7677.2928-1.0606 0-.2929-.2929-.2929-.7678 0-1.0607l5.4999-5.5c.2929-.2929.7678-.2929 1.0607 0Zm0 4.5c.2929.2928.2929.7677 0 1.0606l-1 1.0001c-.2929.2928-.7677.2929-1.0606 0-.2929-.2929-.2929-.7678 0-1.0607l1-1c.2929-.2929.7677-.2929 1.0606 0Z" fill="currentColor"/></svg>');
83
+ --_vaadin-icon-sort: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12" fill="none"><path d="M7.49854 6.99951C7.92795 6.99951 8.15791 7.50528 7.87549 7.82861L4.37646 11.8296C4.17728 12.0571 3.82272 12.0571 3.62354 11.8296L0.125488 7.82861C-0.157248 7.50531 0.0719873 6.99956 0.501465 6.99951H7.49854ZM3.62354 0.17041C3.82275 -0.0573875 4.17725 -0.0573848 4.37646 0.17041L7.87549 4.17041C8.15825 4.49373 7.92806 5.00049 7.49854 5.00049L0.501465 4.99951C0.0719873 4.99946 -0.157248 4.49371 0.125488 4.17041L3.62354 0.17041Z" fill="black"/></svg>');
84
+ --_vaadin-icon-undo: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/></svg>');
85
+ --_vaadin-icon-upload: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5" /></svg>');
86
+ --_vaadin-icon-user: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M3 20C5.33579 17.5226 8.50702 16 12 16C15.493 16 18.6642 17.5226 21 20M16.5 7.5C16.5 9.98528 14.4853 12 12 12C9.51472 12 7.5 9.98528 7.5 7.5C7.5 5.01472 9.51472 3 12 3C14.4853 3 16.5 5.01472 16.5 7.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>');
87
+ --_vaadin-icon-warn: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /></svg>');
88
+
89
+ /* Cursors for interactive elements */
90
+ --vaadin-clickable-cursor: pointer;
91
+ --vaadin-disabled-cursor: not-allowed;
92
+ }
93
+
94
+ @media (forced-colors: active) {
95
+ html {
96
+ --vaadin-background-color: Canvas;
97
+ --vaadin-border-color: CanvasText;
98
+ --vaadin-border-color-secondary: CanvasText;
99
+ --vaadin-text-color-disabled: CanvasText;
100
+ --vaadin-text-color-secondary: CanvasText;
101
+ --vaadin-text-color: CanvasText;
102
+ --vaadin-icon-color: CanvasText;
103
+ --vaadin-focus-ring-color: Highlight;
104
+ }
105
+ }
106
+ }
107
+ `,
108
+ );
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 2025 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
+ import { addGlobalThemeStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
8
+
9
+ addGlobalThemeStyles(
10
+ 'vaadin-base-user-colors',
11
+ css`
12
+ @layer vaadin.base {
13
+ :where(html) {
14
+ --_color-count: 10;
15
+ --_hue-step: round(360 / var(--_color-count), 1);
16
+ --vaadin-user-color-0: var(--vaadin-user-color, oklch(0.52 0.2 240));
17
+ --vaadin-user-color-1: oklch(
18
+ from var(--vaadin-user-color-0) calc(0.62 + clamp(-0.15, (0.6201 - l) * 10000, 0.15)) c
19
+ calc(h - var(--_hue-step) * 2 * var(---_vaadin-safari-17-deg, 1))
20
+ );
21
+ --vaadin-user-color-2: oklch(
22
+ from var(--vaadin-user-color-0) l c calc(h - var(--_hue-step) * -2 * var(---_vaadin-safari-17-deg, 1))
23
+ );
24
+ --vaadin-user-color-3: oklch(
25
+ from var(--vaadin-user-color-0) calc(0.62 + clamp(-0.15, (0.6201 - l) * 10000, 0.15)) c
26
+ calc(h - var(--_hue-step) * 0 * var(---_vaadin-safari-17-deg, 1))
27
+ );
28
+ --vaadin-user-color-4: oklch(
29
+ from var(--vaadin-user-color-0) l c calc(h - var(--_hue-step) * 2 * var(---_vaadin-safari-17-deg, 1))
30
+ );
31
+ --vaadin-user-color-5: oklch(
32
+ from var(--vaadin-user-color-0) calc(0.62 + clamp(-0.15, (0.6201 - l) * 10000, 0.15)) c
33
+ calc(h - var(--_hue-step) * -2 * var(---_vaadin-safari-17-deg, 1))
34
+ );
35
+ --vaadin-user-color-6: oklch(
36
+ from var(--vaadin-user-color-0) l c calc(h - var(--_hue-step) * -4 * var(---_vaadin-safari-17-deg, 1))
37
+ );
38
+ --vaadin-user-color-7: oklch(
39
+ from var(--vaadin-user-color-0) calc(0.62 + clamp(-0.15, (0.6201 - l) * 10000, 0.15)) c
40
+ calc(h - var(--_hue-step) * 4 * var(---_vaadin-safari-17-deg, 1))
41
+ );
42
+ --vaadin-user-color-8: oklch(
43
+ from var(--vaadin-user-color-0) l c calc(h - var(--_hue-step) * 4 * var(---_vaadin-safari-17-deg, 1))
44
+ );
45
+ --vaadin-user-color-9: oklch(
46
+ from var(--vaadin-user-color-0) calc(0.62 + clamp(-0.15, (0.6201 - l) * 10000, 0.15)) c
47
+ calc(h - var(--_hue-step) * 6 * var(---_vaadin-safari-17-deg, 1))
48
+ );
49
+ }
50
+
51
+ @supports not (color: hsl(0 0 0)) {
52
+ :where(:root),
53
+ :where(:host) {
54
+ ---_vaadin-safari-17-deg: 1deg;
55
+ }
56
+ }
57
+ }
58
+ `,
59
+ );
@@ -14,6 +14,7 @@ export class TooltipController extends SlotController {
14
14
  super(host, 'tooltip');
15
15
 
16
16
  this.setTarget(host);
17
+ this.__onContentChange = this.__onContentChange.bind(this);
17
18
  }
18
19
 
19
20
  /**
@@ -50,7 +51,11 @@ export class TooltipController extends SlotController {
50
51
  tooltipNode.shouldShow = this.shouldShow;
51
52
  }
52
53
 
53
- this.__notifyChange();
54
+ if (!this.manual) {
55
+ this.host.setAttribute('has-tooltip', '');
56
+ }
57
+ this.__notifyChange(tooltipNode);
58
+ tooltipNode.addEventListener('content-changed', this.__onContentChange);
54
59
  }
55
60
 
56
61
  /**
@@ -60,8 +65,12 @@ export class TooltipController extends SlotController {
60
65
  * @protected
61
66
  * @override
62
67
  */
63
- teardownNode() {
64
- this.__notifyChange();
68
+ teardownNode(tooltipNode) {
69
+ if (!this.manual) {
70
+ this.host.removeAttribute('has-tooltip');
71
+ }
72
+ tooltipNode.removeEventListener('content-changed', this.__onContentChange);
73
+ this.__notifyChange(null);
65
74
  }
66
75
 
67
76
  /**
@@ -160,7 +169,12 @@ export class TooltipController extends SlotController {
160
169
  }
161
170
 
162
171
  /** @private */
163
- __notifyChange() {
164
- this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node: this.node } }));
172
+ __onContentChange(event) {
173
+ this.__notifyChange(event.target);
174
+ }
175
+
176
+ /** @private */
177
+ __notifyChange(node) {
178
+ this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node } }));
165
179
  }
166
180
  }
@@ -14,15 +14,29 @@ const MAX_VIRTUAL_COUNT = 100000;
14
14
  const OFFSET_ADJUST_MIN_THRESHOLD = 1000;
15
15
 
16
16
  export class IronListAdapter {
17
- constructor({ createElements, updateElement, scrollTarget, scrollContainer, elementsContainer, reorderElements }) {
17
+ constructor({
18
+ createElements,
19
+ updateElement,
20
+ scrollTarget,
21
+ scrollContainer,
22
+ reorderElements,
23
+ elementsContainer,
24
+ __disableHeightPlaceholder,
25
+ }) {
18
26
  this.isAttached = true;
19
27
  this._vidxOffset = 0;
20
28
  this.createElements = createElements;
21
29
  this.updateElement = updateElement;
22
30
  this.scrollTarget = scrollTarget;
23
31
  this.scrollContainer = scrollContainer;
24
- this.elementsContainer = elementsContainer || scrollContainer;
25
32
  this.reorderElements = reorderElements;
33
+ this.elementsContainer = elementsContainer || scrollContainer;
34
+
35
+ // Internal option that disables the heavy height placeholder calculation
36
+ // (see __afterElementsUpdated) for components that always render virtual
37
+ // elements with a non-zero height. Not for public use.
38
+ this.__disableHeightPlaceholder = __disableHeightPlaceholder ?? false;
39
+
26
40
  // Iron-list uses this value to determine how many pages of elements to render
27
41
  this._maxPages = 1.3;
28
42
 
@@ -33,7 +47,7 @@ export class IronListAdapter {
33
47
 
34
48
  this.timeouts = {
35
49
  SCROLL_REORDER: 500,
36
- IGNORE_WHEEL: 500,
50
+ PREVENT_OVERSCROLL: 500,
37
51
  FIX_INVALID_ITEM_POSITIONING: 100,
38
52
  };
39
53
 
@@ -65,7 +79,6 @@ export class IronListAdapter {
65
79
  attachObserver.observe(this.scrollTarget);
66
80
 
67
81
  this._scrollLineHeight = this._getScrollLineHeight();
68
- this.scrollTarget.addEventListener('wheel', (e) => this.__onWheel(e));
69
82
 
70
83
  this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
71
84
  this.elementsContainer.addEventListener('focusin', () => {
@@ -218,7 +231,16 @@ export class IronListAdapter {
218
231
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
219
232
  this._iterateItems((pidx, vidx) => {
220
233
  oldPhysicalSize += this._physicalSizes[pidx];
234
+ const elementOldPhysicalSize = this._physicalSizes[pidx];
221
235
  this._physicalSizes[pidx] = Math.ceil(this.__getBorderBoxHeight(this._physicalItems[pidx]));
236
+
237
+ if (this._physicalSizes[pidx] !== elementOldPhysicalSize) {
238
+ // Physical size changed, but resize observer may not catch it if the original size is restored quickly.
239
+ // See https://github.com/vaadin/web-components/issues/9077
240
+ this.__resizeObserver.unobserve(this._physicalItems[pidx]);
241
+ this.__resizeObserver.observe(this._physicalItems[pidx], { box: 'border-box' });
242
+ }
243
+
222
244
  newPhysicalSize += this._physicalSizes[pidx];
223
245
  this._physicalAverageCount += this._physicalSizes[pidx] ? 1 : 0;
224
246
  }, itemSet);
@@ -271,33 +293,35 @@ export class IronListAdapter {
271
293
  * @param {!Array<!HTMLElement>} updatedElements
272
294
  */
273
295
  __afterElementsUpdated(updatedElements) {
274
- updatedElements.forEach((el) => {
275
- const elementHeight = el.offsetHeight;
276
- if (elementHeight === 0) {
277
- // If the elements have 0 height after update (for example due to lazy rendering),
278
- // it results in iron-list requesting to create an unlimited count of elements.
279
- // Assign a temporary placeholder sizing to elements that would otherwise end up having
280
- // no height.
281
- el.style.paddingTop = `${this.__placeholderHeight}px`;
282
- el.style.opacity = '0';
283
- el.__virtualizerPlaceholder = true;
284
-
285
- // Manually schedule the resize handler to make sure the placeholder padding is
286
- // cleared in case the resize observer never triggers.
287
- this.__placeholderClearDebouncer = Debouncer.debounce(this.__placeholderClearDebouncer, animationFrame, () =>
288
- this._resizeHandler(),
289
- );
290
- } else {
291
- // Add element height to the queue
292
- this.__elementHeightQueue.push(elementHeight);
293
- this.__elementHeightQueue.shift();
294
-
295
- // Calculate new placeholder height based on the average of the defined values in the
296
- // element height queue
297
- const filteredHeights = this.__elementHeightQueue.filter((h) => h !== undefined);
298
- this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
299
- }
300
- });
296
+ if (!this.__disableHeightPlaceholder) {
297
+ updatedElements.forEach((el) => {
298
+ const elementHeight = el.offsetHeight;
299
+ if (elementHeight === 0) {
300
+ // If the elements have 0 height after update (for example due to lazy rendering),
301
+ // it results in iron-list requesting to create an unlimited count of elements.
302
+ // Assign a temporary placeholder sizing to elements that would otherwise end up having
303
+ // no height.
304
+ el.style.paddingTop = `${this.__placeholderHeight}px`;
305
+ el.style.opacity = '0';
306
+ el.__virtualizerPlaceholder = true;
307
+
308
+ // Manually schedule the resize handler to make sure the placeholder padding is
309
+ // cleared in case the resize observer never triggers.
310
+ this.__placeholderClearDebouncer = Debouncer.debounce(this.__placeholderClearDebouncer, animationFrame, () =>
311
+ this._resizeHandler(),
312
+ );
313
+ } else {
314
+ // Add element height to the queue
315
+ this.__elementHeightQueue.push(elementHeight);
316
+ this.__elementHeightQueue.shift();
317
+
318
+ // Calculate new placeholder height based on the average of the defined values in the
319
+ // element height queue
320
+ const filteredHeights = this.__elementHeightQueue.filter((h) => h !== undefined);
321
+ this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
322
+ }
323
+ });
324
+ }
301
325
 
302
326
  if (this.__pendingScrollToIndex !== undefined && !this.__hasPlaceholders()) {
303
327
  this.scrollToIndex(this.__pendingScrollToIndex);
@@ -432,7 +456,7 @@ export class IronListAdapter {
432
456
  physicalItems.forEach((el) => {
433
457
  el.style.position = 'absolute';
434
458
  fragment.appendChild(el);
435
- this.__resizeObserver.observe(el);
459
+ this.__resizeObserver.observe(el, { box: 'border-box' });
436
460
  });
437
461
  this.elementsContainer.appendChild(fragment);
438
462
  return physicalItems;
@@ -548,8 +572,8 @@ export class IronListAdapter {
548
572
  return;
549
573
  }
550
574
 
551
- this._adjustVirtualIndexOffset(this._scrollTop - (this.__previousScrollTop || 0));
552
- const delta = this.scrollTarget.scrollTop - this._scrollPosition;
575
+ this._adjustVirtualIndexOffset(this._scrollTop - this._scrollPosition);
576
+ const delta = this._scrollTop - this._scrollPosition;
553
577
 
554
578
  super._scrollHandler();
555
579
 
@@ -580,6 +604,18 @@ export class IronListAdapter {
580
604
  timeOut.after(this.timeouts.FIX_INVALID_ITEM_POSITIONING),
581
605
  () => this.__fixInvalidItemPositioning(),
582
606
  );
607
+
608
+ if (!this.__overscrollDebouncer?.isActive()) {
609
+ this.scrollTarget.style.overscrollBehavior = 'none';
610
+ }
611
+
612
+ this.__overscrollDebouncer = Debouncer.debounce(
613
+ this.__overscrollDebouncer,
614
+ timeOut.after(this.timeouts.PREVENT_OVERSCROLL),
615
+ () => {
616
+ this.scrollTarget.style.overscrollBehavior = null;
617
+ },
618
+ );
583
619
  }
584
620
 
585
621
  if (this.reorderElements) {
@@ -590,11 +626,9 @@ export class IronListAdapter {
590
626
  );
591
627
  }
592
628
 
593
- this.__previousScrollTop = this._scrollTop;
594
-
595
629
  // If the first visible index is not 0 when scrolled to the top,
596
630
  // scroll to index 0 to fix the issue.
597
- if (this._scrollTop === 0 && this.firstVisibleIndex !== 0 && Math.abs(delta) > 0) {
631
+ if (this._scrollPosition === 0 && this.firstVisibleIndex !== 0 && Math.abs(delta) > 0) {
598
632
  this.scrollToIndex(0);
599
633
  }
600
634
  }
@@ -654,96 +688,6 @@ export class IronListAdapter {
654
688
  }
655
689
  }
656
690
 
657
- /** @private */
658
- __onWheel(e) {
659
- if (e.ctrlKey || this._hasScrolledAncestor(e.target, e.deltaX, e.deltaY)) {
660
- return;
661
- }
662
-
663
- let deltaY = e.deltaY;
664
- if (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {
665
- // Scrolling by "lines of text" instead of pixels
666
- deltaY *= this._scrollLineHeight;
667
- } else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
668
- // Scrolling by "pages" instead of pixels
669
- deltaY *= this._scrollPageHeight;
670
- }
671
-
672
- if (!this._deltaYAcc) {
673
- this._deltaYAcc = 0;
674
- }
675
-
676
- if (this._wheelAnimationFrame) {
677
- // Accumulate wheel delta while a frame is being processed
678
- this._deltaYAcc += deltaY;
679
- e.preventDefault();
680
- return;
681
- }
682
-
683
- deltaY += this._deltaYAcc;
684
- this._deltaYAcc = 0;
685
-
686
- this._wheelAnimationFrame = true;
687
- this.__debouncerWheelAnimationFrame = Debouncer.debounce(
688
- this.__debouncerWheelAnimationFrame,
689
- animationFrame,
690
- () => {
691
- this._wheelAnimationFrame = false;
692
- },
693
- );
694
-
695
- const momentum = Math.abs(e.deltaX) + Math.abs(deltaY);
696
-
697
- if (this._canScroll(this.scrollTarget, e.deltaX, deltaY)) {
698
- e.preventDefault();
699
- this.scrollTarget.scrollTop += deltaY;
700
- this.scrollTarget.scrollLeft += e.deltaX;
701
-
702
- this._hasResidualMomentum = true;
703
-
704
- this._ignoreNewWheel = true;
705
- this._debouncerIgnoreNewWheel = Debouncer.debounce(
706
- this._debouncerIgnoreNewWheel,
707
- timeOut.after(this.timeouts.IGNORE_WHEEL),
708
- () => {
709
- this._ignoreNewWheel = false;
710
- },
711
- );
712
- } else if ((this._hasResidualMomentum && momentum <= this._previousMomentum) || this._ignoreNewWheel) {
713
- e.preventDefault();
714
- } else if (momentum > this._previousMomentum) {
715
- this._hasResidualMomentum = false;
716
- }
717
- this._previousMomentum = momentum;
718
- }
719
-
720
- /**
721
- * Determines if the element has an ancestor that handles the scroll delta prior to this
722
- *
723
- * @private
724
- */
725
- _hasScrolledAncestor(el, deltaX, deltaY) {
726
- if (el === this.scrollTarget || el === this.scrollTarget.getRootNode().host) {
727
- return false;
728
- } else if (
729
- this._canScroll(el, deltaX, deltaY) &&
730
- ['auto', 'scroll'].indexOf(getComputedStyle(el).overflow) !== -1
731
- ) {
732
- return true;
733
- } else if (el !== this && el.parentElement) {
734
- return this._hasScrolledAncestor(el.parentElement, deltaX, deltaY);
735
- }
736
- }
737
-
738
- _canScroll(el, deltaX, deltaY) {
739
- return (
740
- (deltaY > 0 && el.scrollTop < el.scrollHeight - el.offsetHeight) ||
741
- (deltaY < 0 && el.scrollTop > 0) ||
742
- (deltaX > 0 && el.scrollLeft < el.scrollWidth - el.offsetWidth) ||
743
- (deltaX < 0 && el.scrollLeft > 0)
744
- );
745
- }
746
-
747
691
  /**
748
692
  * Increases the pool size.
749
693
  * @override
@@ -78,9 +78,7 @@ export class Virtualizer {
78
78
  /**
79
79
  * Flushes active asynchronous tasks so that the component and the DOM end up in a stable state
80
80
  *
81
- * @method update
82
- * @param {number | undefined} startIndex The start index of the range
83
- * @param {number | undefined} endIndex The end index of the range
81
+ * @method flush
84
82
  */
85
83
  flush() {
86
84
  this.__adapter.flush();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * Issues a warning in the browser console if it has not been issued before.
9
+ */
10
+ export declare function issueWarning(warning: string): void;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ const issuedWarnings = new Set();
8
+
9
+ /**
10
+ * Issues a warning in the browser console if it has not been issued before.
11
+ * @param {string} warning
12
+ */
13
+ export function issueWarning(warning) {
14
+ if (issuedWarnings.has(warning)) {
15
+ return;
16
+ }
17
+
18
+ issuedWarnings.add(warning);
19
+ console.warn(warning);
20
+ }
21
+
22
+ /**
23
+ * Clears all issued warnings. Only intended for testing purposes.
24
+ */
25
+ export function clearWarnings() {
26
+ issuedWarnings.clear();
27
+ }