@vaadin/component-base 23.0.0-alpha2 → 23.0.0-beta1

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": "23.0.0-alpha2",
3
+ "version": "23.0.0-beta1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "main": "index.js",
20
20
  "module": "index.js",
21
+ "type": "module",
21
22
  "files": [
22
23
  "custom_typings",
23
24
  "index.d.ts",
@@ -41,5 +42,5 @@
41
42
  "@vaadin/testing-helpers": "^0.3.2",
42
43
  "sinon": "^9.2.4"
43
44
  },
44
- "gitHead": "070f586dead02ca41b66717820c647f48bf1665f"
45
+ "gitHead": "467244b76021176c109df675799b07029b293e58"
45
46
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * Cause a text string to be announced by screen readers.
9
+ */
10
+ export function announce(text: string, options?: { mode?: 'polite' | 'assertive'; timeout?: number }): void;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ const region = document.createElement('div');
8
+
9
+ region.style.position = 'fixed';
10
+ region.style.clip = 'rect(0px, 0px, 0px, 0px)';
11
+ region.setAttribute('aria-live', 'polite');
12
+
13
+ document.body.appendChild(region);
14
+
15
+ /**
16
+ * Cause a text string to be announced by screen readers.
17
+ *
18
+ * @param {string} text The text that should be announced by the screen reader.
19
+ * @param {{mode?: string, timeout?: number}} options Additional options.
20
+ */
21
+ export function announce(text, options = {}) {
22
+ const mode = options.mode || 'polite';
23
+ const timeout = options.timeout === undefined ? 150 : options.timeout;
24
+
25
+ region.setAttribute('aria-live', mode);
26
+
27
+ region.textContent = '';
28
+
29
+ setTimeout(() => {
30
+ region.textContent = text;
31
+ }, timeout);
32
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { addListener } from '@vaadin/component-base/src/gestures.js';
package/src/async.js CHANGED
@@ -182,10 +182,13 @@ const microTask = {
182
182
  run(callback) {
183
183
  if (!microtaskScheduled) {
184
184
  microtaskScheduled = true;
185
- microtaskNode.textContent = microtaskNodeContent++;
185
+ microtaskNode.textContent = microtaskNodeContent;
186
+ microtaskNodeContent += 1;
186
187
  }
187
188
  microtaskCallbacks.push(callback);
188
- return microtaskCurrHandle++;
189
+ const result = microtaskCurrHandle;
190
+ microtaskCurrHandle += 1;
191
+ return result;
189
192
  },
190
193
 
191
194
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
package/src/dir-helper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
package/src/dir-mixin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { DirHelper } from './dir-helper.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 '../custom_typings/vaadin-usage-statistics.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { usageStatistics } from '@vaadin/vaadin-usage-statistics/vaadin-usage-statistics.js';
@@ -32,7 +32,7 @@ const registered = new Set();
32
32
  export const ElementMixin = (superClass) =>
33
33
  class VaadinElementMixin extends DirMixin(superClass) {
34
34
  static get version() {
35
- return '23.0.0-alpha2';
35
+ return '23.0.0-beta1';
36
36
  }
37
37
 
38
38
  /** @protected */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { ReactiveController } from 'lit';
@@ -8,7 +8,7 @@ import { ReactiveController } from 'lit';
8
8
  /**
9
9
  * A controller for trapping focus within a DOM node.
10
10
  */
11
- declare class FocusTrapController implements ReactiveController {
11
+ export class FocusTrapController implements ReactiveController {
12
12
  constructor(node: HTMLElement);
13
13
 
14
14
  hostConnected(): void;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { getFocusableElements, isElementFocused } from './focus-utils.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -193,7 +193,7 @@ export const ironList = {
193
193
  set _virtualStart(val) {
194
194
  val = this._clamp(val, 0, this._maxVirtualStart);
195
195
  if (this.grid) {
196
- val = val - (val % this._itemsPerRow);
196
+ val -= val % this._itemsPerRow;
197
197
  }
198
198
  this._virtualStartVal = val;
199
199
  },
@@ -206,12 +206,12 @@ export const ironList = {
206
206
  * The k-th tile that is at the top of the scrolling list.
207
207
  */
208
208
  set _physicalStart(val) {
209
- val = val % this._physicalCount;
209
+ val %= this._physicalCount;
210
210
  if (val < 0) {
211
211
  val = this._physicalCount + val;
212
212
  }
213
213
  if (this.grid) {
214
- val = val - (val % this._itemsPerRow);
214
+ val -= val % this._itemsPerRow;
215
215
  }
216
216
  this._physicalStartVal = val;
217
217
  },
@@ -260,7 +260,7 @@ export const ironList = {
260
260
  var physicalOffset = this._physicalTop + this._scrollOffset;
261
261
 
262
262
  idx =
263
- this._iterateItems(function (pidx, vidx) {
263
+ this._iterateItems((pidx, vidx) => {
264
264
  physicalOffset += this._getPhysicalSizeIncrement(pidx);
265
265
 
266
266
  if (physicalOffset > this._scrollPosition) {
@@ -288,7 +288,7 @@ export const ironList = {
288
288
  idx = Math.min(this._virtualCount, this.firstVisibleIndex + this._estRowsInView * this._itemsPerRow - 1);
289
289
  } else {
290
290
  var physicalOffset = this._physicalTop + this._scrollOffset;
291
- this._iterateItems(function (pidx, vidx) {
291
+ this._iterateItems((pidx, vidx) => {
292
292
  if (physicalOffset < this._scrollBottom) {
293
293
  idx = vidx;
294
294
  }
@@ -334,10 +334,10 @@ export const ironList = {
334
334
  this._lastVisibleIndexVal = null;
335
335
  // Random access.
336
336
  if (Math.abs(delta) > this._physicalSize && this._physicalSize > 0) {
337
- delta = delta - this._scrollOffset;
337
+ delta -= this._scrollOffset;
338
338
  var idxAdjustment = Math.round(delta / this._physicalAverage) * this._itemsPerRow;
339
- this._virtualStart = this._virtualStart + idxAdjustment;
340
- this._physicalStart = this._physicalStart + idxAdjustment;
339
+ this._virtualStart += idxAdjustment;
340
+ this._physicalStart += idxAdjustment;
341
341
  // Estimate new physical offset based on the virtual start index.
342
342
  // adjusts the physical start position to stay in sync with the clamped
343
343
  // virtual start index. It's critical not to let this value be
@@ -353,11 +353,11 @@ export const ironList = {
353
353
  var reusables = this._getReusables(isScrollingDown);
354
354
  if (isScrollingDown) {
355
355
  this._physicalTop = reusables.physicalTop;
356
- this._virtualStart = this._virtualStart + reusables.indexes.length;
357
- this._physicalStart = this._physicalStart + reusables.indexes.length;
356
+ this._virtualStart += reusables.indexes.length;
357
+ this._physicalStart += reusables.indexes.length;
358
358
  } else {
359
- this._virtualStart = this._virtualStart - reusables.indexes.length;
360
- this._physicalStart = this._physicalStart - reusables.indexes.length;
359
+ this._virtualStart -= reusables.indexes.length;
360
+ this._physicalStart -= reusables.indexes.length;
361
361
  }
362
362
  this._update(reusables.indexes, isScrollingDown ? null : reusables.indexes);
363
363
  this._debounce('_increasePoolIfNeeded', this._increasePoolIfNeeded.bind(this, 0), microTask);
@@ -396,7 +396,7 @@ export const ironList = {
396
396
  // eslint-disable-next-line no-constant-condition
397
397
  while (true) {
398
398
  physicalItemHeight = this._getPhysicalSizeIncrement(ith);
399
- offsetContent = offsetContent - physicalItemHeight;
399
+ offsetContent -= physicalItemHeight;
400
400
  if (idxs.length >= physicalCount || offsetContent <= protectedOffsetContent) {
401
401
  break;
402
402
  }
@@ -410,7 +410,7 @@ export const ironList = {
410
410
  break;
411
411
  }
412
412
  idxs.push(ith);
413
- top = top + physicalItemHeight;
413
+ top += physicalItemHeight;
414
414
  ith = (ith + 1) % physicalCount;
415
415
  } else {
416
416
  // Check that index is within the valid range.
@@ -422,7 +422,7 @@ export const ironList = {
422
422
  break;
423
423
  }
424
424
  idxs.push(ith);
425
- top = top - physicalItemHeight;
425
+ top -= physicalItemHeight;
426
426
  ith = ith === 0 ? physicalCount - 1 : ith - 1;
427
427
  }
428
428
  }
@@ -492,7 +492,7 @@ export const ironList = {
492
492
  for (var i = 0; i < delta; i++) {
493
493
  this._physicalSizes.push(0);
494
494
  }
495
- this._physicalCount = this._physicalCount + delta;
495
+ this._physicalCount += delta;
496
496
  // Update the physical start if it needs to preserve the model of the
497
497
  // focused item. In this situation, the focused item is currently rendered
498
498
  // and its model would have changed after increasing the pool if the
@@ -502,7 +502,7 @@ export const ironList = {
502
502
  this._isIndexRendered(this._focusedVirtualIndex) &&
503
503
  this._getPhysicalIndex(this._focusedVirtualIndex) < this._physicalEnd
504
504
  ) {
505
- this._physicalStart = this._physicalStart + delta;
505
+ this._physicalStart += delta;
506
506
  }
507
507
  this._update();
508
508
  this._templateCost = (window.performance.now() - ts) / delta;
@@ -535,8 +535,8 @@ export const ironList = {
535
535
  if (this._physicalCount !== 0) {
536
536
  var reusables = this._getReusables(true);
537
537
  this._physicalTop = reusables.physicalTop;
538
- this._virtualStart = this._virtualStart + reusables.indexes.length;
539
- this._physicalStart = this._physicalStart + reusables.indexes.length;
538
+ this._virtualStart += reusables.indexes.length;
539
+ this._physicalStart += reusables.indexes.length;
540
540
  this._update(reusables.indexes);
541
541
  this._update();
542
542
  this._increasePoolIfNeeded(0);
@@ -668,7 +668,7 @@ export const ironList = {
668
668
  var prevPhysicalAvg = this._physicalAverage;
669
669
 
670
670
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
671
- this._iterateItems(function (pidx, vidx) {
671
+ this._iterateItems((pidx, vidx) => {
672
672
  oldPhysicalSize += this._physicalSizes[pidx];
673
673
  this._physicalSizes[pidx] = this._physicalItems[pidx].offsetHeight;
674
674
  newPhysicalSize += this._physicalSizes[pidx];
@@ -712,11 +712,11 @@ export const ironList = {
712
712
  var totalItemWidth = this._itemsPerRow * this._itemWidth;
713
713
  var rowOffset = (this._viewportWidth - totalItemWidth) / 2;
714
714
 
715
- this._iterateItems(function (pidx, vidx) {
715
+ this._iterateItems((pidx, vidx) => {
716
716
  var modulus = vidx % this._itemsPerRow;
717
717
  var x = Math.floor(modulus * this._itemWidth + rowOffset);
718
718
  if (this._isRTL) {
719
- x = x * -1;
719
+ x *= -1;
720
720
  }
721
721
  this.translate3d(x + 'px', y + 'px', 0, this._physicalItems[pidx]);
722
722
  if (this._shouldRenderNextRow(vidx)) {
@@ -726,7 +726,7 @@ export const ironList = {
726
726
  } else {
727
727
  const order = [];
728
728
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
729
- this._iterateItems(function (pidx, vidx) {
729
+ this._iterateItems((pidx, vidx) => {
730
730
  const item = this._physicalItems[pidx];
731
731
  this.translate3d(0, y + 'px', 0, item);
732
732
  y += this._physicalSizes[pidx];
@@ -771,7 +771,7 @@ export const ironList = {
771
771
  this._virtualStart === 0 ? this._physicalTop : Math.min(this._scrollPosition + this._physicalTop, 0);
772
772
  // Note: the delta can be positive or negative.
773
773
  if (deltaHeight !== 0) {
774
- this._physicalTop = this._physicalTop - deltaHeight;
774
+ this._physicalTop -= deltaHeight;
775
775
  // This may be called outside of a scrollHandler, so use last cached position
776
776
  var scrollTop = this._scrollPosition;
777
777
  // juking scroll position during interial scrolling on iOS is no bueno
@@ -847,9 +847,9 @@ export const ironList = {
847
847
  var hiddenContentSize = this._hiddenContentSize;
848
848
  // scroll to the item as much as we can.
849
849
  while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) {
850
- targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(currentTopItem);
850
+ targetOffsetTop += this._getPhysicalSizeIncrement(currentTopItem);
851
851
  currentTopItem = (currentTopItem + 1) % this._physicalCount;
852
- currentVirtualItem++;
852
+ currentVirtualItem += 1;
853
853
  }
854
854
  this._updateScrollerSize(true);
855
855
  this._positionItems();
@@ -875,7 +875,7 @@ export const ironList = {
875
875
  _resizeHandler: function () {
876
876
  this._debounce(
877
877
  '_render',
878
- function () {
878
+ () => {
879
879
  // clear cached visible index.
880
880
  this._firstVisibleIndexVal = null;
881
881
  this._lastVisibleIndexVal = null;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+
8
+ /**
9
+ * A mixin that uses a ResizeObserver to listen to host size changes.
10
+ */
11
+ export declare function ResizeMixin<T extends Constructor<HTMLElement>>(base: T): T & Constructor<ResizeMixinClass>;
12
+
13
+ export declare class ResizeMixinClass {
14
+ /**
15
+ * A handler invoked on host resize. By default, it does nothing.
16
+ * Override the method to implement your own behavior.
17
+ */
18
+ protected _onResize(contentRect: DOMRect): void;
19
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
7
+
8
+ const observer = new ResizeObserver((entries) => {
9
+ setTimeout(() => {
10
+ entries.forEach((entry) => {
11
+ entry.target._onResize(entry.contentRect);
12
+ });
13
+ });
14
+ });
15
+
16
+ /**
17
+ * A mixin that uses a ResizeObserver to listen to host size changes.
18
+ *
19
+ * @polymerMixin
20
+ */
21
+ export const ResizeMixin = dedupingMixin(
22
+ (superclass) =>
23
+ class ResizeMixinClass extends superclass {
24
+ /** @protected */
25
+ connectedCallback() {
26
+ super.connectedCallback();
27
+ observer.observe(this);
28
+ }
29
+
30
+ /** @protected */
31
+ disconnectedCallback() {
32
+ super.disconnectedCallback();
33
+ observer.unobserve(this);
34
+ }
35
+
36
+ /**
37
+ * A handler invoked on host resize. By default, it does nothing.
38
+ * Override the method to implement your own behavior.
39
+ *
40
+ * @protected
41
+ */
42
+ _onResize(_contentRect) {
43
+ // To be implemented.
44
+ }
45
+
46
+ /**
47
+ * @deprecated Since Vaadin 23, `notifyResize()` is deprecated. The component uses a
48
+ * ResizeObserver internally and doesn't need to be explicitly notified of resizes.
49
+ */
50
+ notifyResize() {
51
+ console.warn(
52
+ `WARNING: Since Vaadin 23, notifyResize() is deprecated. The component uses a ResizeObserver internally and doesn't need to be explicitly notified of resizes.`
53
+ );
54
+ }
55
+ }
56
+ );
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { ReactiveController } from 'lit';
7
7
 
8
- export class SlotController implements ReactiveController {
8
+ export class SlotController extends EventTarget implements ReactiveController {
9
9
  constructor(
10
10
  host: HTMLElement,
11
11
  slotName: string,
@@ -34,6 +34,12 @@ export class SlotController implements ReactiveController {
34
34
 
35
35
  protected defaultNode: Node;
36
36
 
37
+ protected defaultId: string;
38
+
39
+ protected attachDefaultNode(): Node | undefined;
40
+
41
+ protected initNode(node: Node): void;
42
+
37
43
  /**
38
44
  * Override to initialize the newly added custom node.
39
45
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
@@ -8,44 +8,46 @@ import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nod
8
8
  /**
9
9
  * A controller for providing content to slot element and observing changes.
10
10
  */
11
- export class SlotController {
11
+ export class SlotController extends EventTarget {
12
12
  constructor(host, slotName, slotFactory, slotInitializer) {
13
+ super();
14
+
13
15
  this.host = host;
14
16
  this.slotName = slotName;
15
17
  this.slotFactory = slotFactory;
16
18
  this.slotInitializer = slotInitializer;
19
+ this.defaultId = SlotController.generateId(slotName, host);
20
+ }
21
+
22
+ /**
23
+ * Ensure that every instance has unique ID.
24
+ *
25
+ * @param {string} slotName
26
+ * @param {HTMLElement} host
27
+ * @return {string}
28
+ * @protected
29
+ */
30
+ static generateId(slotName, host) {
31
+ const prefix = slotName || 'default';
32
+
33
+ // Maintain the unique ID counter for a given prefix.
34
+ this[`${prefix}Id`] = 1 + this[`${prefix}Id`] || 0;
35
+
36
+ return `${prefix}-${host.localName}-${this[`${prefix}Id`]}`;
17
37
  }
18
38
 
19
39
  hostConnected() {
20
40
  if (!this.initialized) {
21
- const { host, slotName, slotFactory, slotInitializer } = this;
22
-
23
- const slotted = this.getSlotChild();
24
-
25
- if (!slotted) {
26
- // Slot factory is optional, some slots don't have default content.
27
- if (slotFactory) {
28
- const slotContent = slotFactory(host);
29
- if (slotContent instanceof Element) {
30
- if (slotName !== '') {
31
- slotContent.setAttribute('slot', slotName);
32
- }
33
- host.appendChild(slotContent);
34
- this.node = slotContent;
35
-
36
- // Store reference to not pass default node to `initCustomNode`.
37
- this.defaultNode = slotContent;
38
- }
39
- }
41
+ let node = this.getSlotChild();
42
+
43
+ if (!node) {
44
+ node = this.attachDefaultNode();
40
45
  } else {
41
- this.node = slotted;
46
+ this.node = node;
47
+ this.initCustomNode(node);
42
48
  }
43
49
 
44
- // Don't try to bind `this` to initializer (normally it's arrow function).
45
- // Instead, pass the host as a first argument to access component's state.
46
- if (slotInitializer) {
47
- slotInitializer(host, this.node);
48
- }
50
+ this.initNode(node);
49
51
 
50
52
  // TODO: Consider making this behavior opt-in to improve performance.
51
53
  this.observe();
@@ -54,6 +56,36 @@ export class SlotController {
54
56
  }
55
57
  }
56
58
 
59
+ /**
60
+ * Create and attach default node using the slot factory.
61
+ * @return {Node | undefined}
62
+ * @protected
63
+ */
64
+ attachDefaultNode() {
65
+ const { host, slotName, slotFactory } = this;
66
+
67
+ // Check if the node was created previously and if so, reuse it.
68
+ let node = this.defaultNode;
69
+
70
+ // Slot factory is optional, some slots don't have default content.
71
+ if (!node && slotFactory) {
72
+ node = slotFactory(host);
73
+ if (node instanceof Element) {
74
+ if (slotName !== '') {
75
+ node.setAttribute('slot', slotName);
76
+ }
77
+ this.node = node;
78
+ this.defaultNode = node;
79
+ }
80
+ }
81
+
82
+ if (node) {
83
+ host.appendChild(node);
84
+ }
85
+
86
+ return node;
87
+ }
88
+
57
89
  /**
58
90
  * Return a reference to the node managed by the controller.
59
91
  * @return {Node}
@@ -69,6 +101,19 @@ export class SlotController {
69
101
  });
70
102
  }
71
103
 
104
+ /**
105
+ * @param {Node} node
106
+ * @protected
107
+ */
108
+ initNode(node) {
109
+ const { slotInitializer } = this;
110
+ // Don't try to bind `this` to initializer (normally it's arrow function).
111
+ // Instead, pass the host as a first argument to access component's state.
112
+ if (slotInitializer) {
113
+ slotInitializer(this.host, node);
114
+ }
115
+ }
116
+
72
117
  /**
73
118
  * Override to initialize the newly added custom node.
74
119
  *
@@ -115,6 +160,8 @@ export class SlotController {
115
160
 
116
161
  if (newNode !== this.defaultNode) {
117
162
  this.initCustomNode(newNode);
163
+
164
+ this.initNode(newNode);
118
165
  }
119
166
  }
120
167
  });
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
package/src/slot-mixin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { DisabledMixin } from './disabled-mixin.js';
package/src/templates.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2021 - 2022 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 { animationFrame, timeOut } from './async.js';