@vaadin/component-base 24.0.5 → 24.1.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/index.d.ts +1 -6
- package/index.js +2 -6
- package/package.json +2 -2
- package/src/async.js +1 -13
- package/src/dom-utils.d.ts +10 -0
- package/src/dom-utils.js +7 -3
- package/src/element-mixin.js +1 -1
- package/src/virtualizer-iron-list-adapter.js +77 -48
- package/src/a11y-announcer.d.ts +0 -10
- package/src/a11y-announcer.js +0 -47
- package/src/active-mixin.d.ts +0 -41
- package/src/active-mixin.js +0 -106
- package/src/delegate-focus-mixin.d.ts +0 -48
- package/src/delegate-focus-mixin.js +0 -228
- package/src/disabled-mixin.d.ts +0 -20
- package/src/disabled-mixin.js +0 -62
- package/src/focus-mixin.d.ts +0 -30
- package/src/focus-mixin.js +0 -93
- package/src/focus-trap-controller.d.ts +0 -39
- package/src/focus-trap-controller.js +0 -155
- package/src/focus-utils.d.ts +0 -51
- package/src/focus-utils.js +0 -262
- package/src/keyboard-direction-mixin.d.ts +0 -41
- package/src/keyboard-direction-mixin.js +0 -192
- package/src/keyboard-mixin.d.ts +0 -40
- package/src/keyboard-mixin.js +0 -85
- package/src/list-mixin.d.ts +0 -57
- package/src/list-mixin.js +0 -354
- package/src/tabindex-mixin.d.ts +0 -36
- package/src/tabindex-mixin.js +0 -78
package/index.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
export { ActiveMixin } from './src/active-mixin.js';
|
|
2
1
|
export { ControllerMixin } from './src/controller-mixin.js';
|
|
2
|
+
export { DelegateStateMixin } from './src/delegate-state-mixin.js';
|
|
3
3
|
export { DirMixin } from './src/dir-mixin.js';
|
|
4
|
-
export { DisabledMixin } from './src/disabled-mixin.js';
|
|
5
4
|
export { ElementMixin } from './src/element-mixin.js';
|
|
6
|
-
export { FocusMixin } from './src/focus-mixin.js';
|
|
7
|
-
export { FocusTrapController } from './src/focus-trap-controller.js';
|
|
8
|
-
export { KeyboardMixin } from './src/keyboard-mixin.js';
|
|
9
5
|
export { ResizeMixin } from './src/resize-mixin.js';
|
|
10
6
|
export { SlotController } from './src/slot-controller.js';
|
|
11
|
-
export { TabindexMixin } from './src/tabindex-mixin.js';
|
package/index.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
export { ActiveMixin } from './src/active-mixin.js';
|
|
2
1
|
export { ControllerMixin } from './src/controller-mixin.js';
|
|
2
|
+
export { DelegateStateMixin } from './src/delegate-state-mixin.js';
|
|
3
3
|
export { DirMixin } from './src/dir-mixin.js';
|
|
4
|
-
export { DisabledMixin } from './src/disabled-mixin.js';
|
|
5
4
|
export { ElementMixin } from './src/element-mixin.js';
|
|
6
|
-
export {
|
|
7
|
-
export { FocusTrapController } from './src/focus-trap-controller.js';
|
|
8
|
-
export { KeyboardMixin } from './src/keyboard-mixin.js';
|
|
5
|
+
export { ResizeMixin } from './src/resize-mixin.js';
|
|
9
6
|
export { SlotController } from './src/slot-controller.js';
|
|
10
|
-
export { TabindexMixin } from './src/tabindex-mixin.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "24.0
|
|
3
|
+
"version": "24.1.0-alpha10",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@vaadin/testing-helpers": "^0.4.0",
|
|
43
43
|
"sinon": "^13.0.2"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "12e39be7eb3b49c68708e8ca3de2fb22e91051a1"
|
|
46
46
|
}
|
package/src/async.js
CHANGED
|
@@ -20,13 +20,10 @@
|
|
|
20
20
|
* asynchronous tasks.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
// Microtask implemented using Mutation Observer
|
|
24
23
|
let microtaskCurrHandle = 0;
|
|
25
24
|
let microtaskLastHandle = 0;
|
|
26
25
|
const microtaskCallbacks = [];
|
|
27
|
-
let microtaskNodeContent = 0;
|
|
28
26
|
let microtaskScheduled = false;
|
|
29
|
-
const microtaskNode = document.createTextNode('');
|
|
30
27
|
|
|
31
28
|
function microtaskFlush() {
|
|
32
29
|
microtaskScheduled = false;
|
|
@@ -47,8 +44,6 @@ function microtaskFlush() {
|
|
|
47
44
|
microtaskLastHandle += len;
|
|
48
45
|
}
|
|
49
46
|
|
|
50
|
-
new window.MutationObserver(microtaskFlush).observe(microtaskNode, { characterData: true });
|
|
51
|
-
|
|
52
47
|
/**
|
|
53
48
|
* Async interface wrapper around `setTimeout`.
|
|
54
49
|
*
|
|
@@ -166,12 +161,6 @@ export { idlePeriod };
|
|
|
166
161
|
/**
|
|
167
162
|
* Async interface for enqueuing callbacks that run at microtask timing.
|
|
168
163
|
*
|
|
169
|
-
* Note that microtask timing is achieved via a single `MutationObserver`,
|
|
170
|
-
* and thus callbacks enqueued with this API will all run in a single
|
|
171
|
-
* batch, and not interleaved with other microtasks such as promises.
|
|
172
|
-
* Promises are avoided as an implementation choice for the time being
|
|
173
|
-
* due to Safari bugs that cause Promises to lack microtask guarantees.
|
|
174
|
-
*
|
|
175
164
|
* @namespace
|
|
176
165
|
* @summary Async interface for enqueuing callbacks that run at microtask
|
|
177
166
|
* timing.
|
|
@@ -187,8 +176,7 @@ const microTask = {
|
|
|
187
176
|
run(callback) {
|
|
188
177
|
if (!microtaskScheduled) {
|
|
189
178
|
microtaskScheduled = true;
|
|
190
|
-
|
|
191
|
-
microtaskNodeContent += 1;
|
|
179
|
+
queueMicrotask(() => microtaskFlush());
|
|
192
180
|
}
|
|
193
181
|
microtaskCallbacks.push(callback);
|
|
194
182
|
const result = microtaskCurrHandle;
|
package/src/dom-utils.d.ts
CHANGED
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export function getAncestorRootNodes(node: Node): Node[];
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Takes a string with values separated by space and returns a set the values
|
|
18
|
+
*/
|
|
19
|
+
export function deserializeAttributeValue(value: string): Set<string>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Takes a set of string values and returns a string with values separated by space
|
|
23
|
+
*/
|
|
24
|
+
export function serializeAttributeValue(values: Set<string>): string;
|
|
25
|
+
|
|
16
26
|
/**
|
|
17
27
|
* Adds a value to an attribute containing space-delimited values.
|
|
18
28
|
*/
|
package/src/dom-utils.js
CHANGED
|
@@ -41,10 +41,12 @@ export function getAncestorRootNodes(node) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
+
* Takes a string with values separated by space and returns a set the values
|
|
45
|
+
*
|
|
44
46
|
* @param {string} value
|
|
45
47
|
* @return {Set<string>}
|
|
46
48
|
*/
|
|
47
|
-
function deserializeAttributeValue(value) {
|
|
49
|
+
export function deserializeAttributeValue(value) {
|
|
48
50
|
if (!value) {
|
|
49
51
|
return new Set();
|
|
50
52
|
}
|
|
@@ -53,11 +55,13 @@ function deserializeAttributeValue(value) {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
/**
|
|
58
|
+
* Takes a set of string values and returns a string with values separated by space
|
|
59
|
+
*
|
|
56
60
|
* @param {Set<string>} values
|
|
57
61
|
* @return {string}
|
|
58
62
|
*/
|
|
59
|
-
function serializeAttributeValue(values) {
|
|
60
|
-
return [...values].join(' ');
|
|
63
|
+
export function serializeAttributeValue(values) {
|
|
64
|
+
return values ? [...values].join(' ') : '';
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
/**
|
package/src/element-mixin.js
CHANGED
|
@@ -136,11 +136,15 @@ export class IronListAdapter {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
update(startIndex = 0, endIndex = this.size - 1) {
|
|
139
|
+
const updatedElements = [];
|
|
139
140
|
this.__getVisibleElements().forEach((el) => {
|
|
140
141
|
if (el.__virtualIndex >= startIndex && el.__virtualIndex <= endIndex) {
|
|
141
142
|
this.__updateElement(el, el.__virtualIndex, true);
|
|
143
|
+
updatedElements.push(el);
|
|
142
144
|
}
|
|
143
145
|
});
|
|
146
|
+
|
|
147
|
+
this.__afterElementsUpdated(updatedElements);
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
/**
|
|
@@ -203,28 +207,40 @@ export class IronListAdapter {
|
|
|
203
207
|
this.updateElement(el, index);
|
|
204
208
|
el.__lastUpdatedIndex = index;
|
|
205
209
|
}
|
|
210
|
+
}
|
|
206
211
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
212
|
+
/**
|
|
213
|
+
* Called synchronously right after elements have been updated.
|
|
214
|
+
* This is a good place to do any post-update work.
|
|
215
|
+
*
|
|
216
|
+
* @param {!Array<!HTMLElement>} updatedElements
|
|
217
|
+
*/
|
|
218
|
+
__afterElementsUpdated(updatedElements) {
|
|
219
|
+
updatedElements.forEach((el) => {
|
|
220
|
+
const elementHeight = el.offsetHeight;
|
|
221
|
+
if (elementHeight === 0) {
|
|
222
|
+
// If the elements have 0 height after update (for example due to lazy rendering),
|
|
223
|
+
// it results in iron-list requesting to create an unlimited count of elements.
|
|
224
|
+
// Assign a temporary placeholder sizing to elements that would otherwise end up having
|
|
225
|
+
// no height.
|
|
226
|
+
el.style.paddingTop = `${this.__placeholderHeight}px`;
|
|
227
|
+
|
|
228
|
+
// Manually schedule the resize handler to make sure the placeholder padding is
|
|
229
|
+
// cleared in case the resize observer never triggers.
|
|
230
|
+
this.__placeholderClearDebouncer = Debouncer.debounce(this.__placeholderClearDebouncer, animationFrame, () =>
|
|
231
|
+
this._resizeHandler(),
|
|
232
|
+
);
|
|
233
|
+
} else {
|
|
234
|
+
// Add element height to the queue
|
|
235
|
+
this.__elementHeightQueue.push(elementHeight);
|
|
236
|
+
this.__elementHeightQueue.shift();
|
|
237
|
+
|
|
238
|
+
// Calculate new placeholder height based on the average of the defined values in the
|
|
239
|
+
// element height queue
|
|
240
|
+
const filteredHeights = this.__elementHeightQueue.filter((h) => h !== undefined);
|
|
241
|
+
this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
228
244
|
}
|
|
229
245
|
|
|
230
246
|
__getIndexScrollOffset(index) {
|
|
@@ -249,42 +265,28 @@ export class IronListAdapter {
|
|
|
249
265
|
this._debouncers._increasePoolIfNeeded.cancel();
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
// Prevent element update while the scroll position is being restored
|
|
253
|
-
this.__preventElementUpdates = true;
|
|
254
|
-
|
|
255
|
-
// Record the scroll position before changing the size
|
|
256
|
-
let fvi; // First visible index
|
|
257
|
-
let fviOffsetBefore; // Scroll offset of the first visible index
|
|
258
|
-
if (size > 0) {
|
|
259
|
-
fvi = this.adjustedFirstVisibleIndex;
|
|
260
|
-
fviOffsetBefore = this.__getIndexScrollOffset(fvi);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
268
|
// Change the size
|
|
264
269
|
this.__size = size;
|
|
265
270
|
|
|
266
|
-
this.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (fviOffsetBefore !== undefined && fviOffsetAfter !== undefined) {
|
|
278
|
-
this._scrollTop += fviOffsetBefore - fviOffsetAfter;
|
|
279
|
-
}
|
|
271
|
+
if (!this._physicalItems) {
|
|
272
|
+
// Not initialized yet
|
|
273
|
+
this._itemsChanged({
|
|
274
|
+
path: 'items',
|
|
275
|
+
});
|
|
276
|
+
this.__preventElementUpdates = true;
|
|
277
|
+
flush();
|
|
278
|
+
this.__preventElementUpdates = false;
|
|
279
|
+
} else {
|
|
280
|
+
// Already initialized, just update _virtualCount
|
|
281
|
+
this._virtualCount = this.items.length;
|
|
280
282
|
}
|
|
281
283
|
|
|
282
284
|
if (!this.elementsContainer.children.length) {
|
|
283
285
|
requestAnimationFrame(() => this._resizeHandler());
|
|
284
286
|
}
|
|
285
287
|
|
|
286
|
-
|
|
287
|
-
//
|
|
288
|
+
// Schedule and flush a resize handler. This will cause a
|
|
289
|
+
// re-render for the elements.
|
|
288
290
|
this._resizeHandler();
|
|
289
291
|
flush();
|
|
290
292
|
}
|
|
@@ -349,16 +351,20 @@ export class IronListAdapter {
|
|
|
349
351
|
|
|
350
352
|
/** @private */
|
|
351
353
|
_assignModels(itemSet) {
|
|
354
|
+
const updatedElements = [];
|
|
352
355
|
this._iterateItems((pidx, vidx) => {
|
|
353
356
|
const el = this._physicalItems[pidx];
|
|
354
357
|
el.hidden = vidx >= this.size;
|
|
355
358
|
if (!el.hidden) {
|
|
356
359
|
el.__virtualIndex = vidx + (this._vidxOffset || 0);
|
|
357
360
|
this.__updateElement(el, el.__virtualIndex);
|
|
361
|
+
updatedElements.push(el);
|
|
358
362
|
} else {
|
|
359
363
|
delete el.__lastUpdatedIndex;
|
|
360
364
|
}
|
|
361
365
|
}, itemSet);
|
|
366
|
+
|
|
367
|
+
this.__afterElementsUpdated(updatedElements);
|
|
362
368
|
}
|
|
363
369
|
|
|
364
370
|
/** @private */
|
|
@@ -557,6 +563,29 @@ export class IronListAdapter {
|
|
|
557
563
|
);
|
|
558
564
|
}
|
|
559
565
|
|
|
566
|
+
/**
|
|
567
|
+
* Increases the pool size.
|
|
568
|
+
* @override
|
|
569
|
+
*/
|
|
570
|
+
_increasePoolIfNeeded(count) {
|
|
571
|
+
if (this._physicalCount > 2 && count) {
|
|
572
|
+
// The iron-list logic has already created some physical items and
|
|
573
|
+
// has decided to create more. Since each item creation round is
|
|
574
|
+
// expensive, let's try to create the remaining items in one go.
|
|
575
|
+
|
|
576
|
+
// Calculate the total item count that would be needed to fill the viewport
|
|
577
|
+
// plus the buffer assuming rest of the items to be of the average size
|
|
578
|
+
// of the items already created.
|
|
579
|
+
const totalItemCount = Math.ceil(this._optPhysicalSize / this._physicalAverage);
|
|
580
|
+
const missingItemCount = totalItemCount - this._physicalCount;
|
|
581
|
+
// Create the remaining items in one go. Use a maximum of 100 items
|
|
582
|
+
// as a safety measure.
|
|
583
|
+
super._increasePoolIfNeeded(Math.max(count, Math.min(100, missingItemCount)));
|
|
584
|
+
} else {
|
|
585
|
+
super._increasePoolIfNeeded(count);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
560
589
|
/**
|
|
561
590
|
* @returns {Number|undefined} - The browser's default font-size in pixels
|
|
562
591
|
* @private
|
package/src/a11y-announcer.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2022 - 2023 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?: 'alert' | 'assertive' | 'polite'; timeout?: number }): void;
|
package/src/a11y-announcer.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2022 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { animationFrame } from './async.js';
|
|
7
|
-
import { Debouncer } from './debounce.js';
|
|
8
|
-
|
|
9
|
-
const region = document.createElement('div');
|
|
10
|
-
|
|
11
|
-
region.style.position = 'fixed';
|
|
12
|
-
region.style.clip = 'rect(0px, 0px, 0px, 0px)';
|
|
13
|
-
region.setAttribute('aria-live', 'polite');
|
|
14
|
-
|
|
15
|
-
document.body.appendChild(region);
|
|
16
|
-
|
|
17
|
-
let alertDebouncer;
|
|
18
|
-
/**
|
|
19
|
-
* Cause a text string to be announced by screen readers.
|
|
20
|
-
*
|
|
21
|
-
* @param {string} text The text that should be announced by the screen reader.
|
|
22
|
-
* @param {{mode?: string, timeout?: number}} options Additional options.
|
|
23
|
-
*/
|
|
24
|
-
export function announce(text, options = {}) {
|
|
25
|
-
const mode = options.mode || 'polite';
|
|
26
|
-
const timeout = options.timeout === undefined ? 150 : options.timeout;
|
|
27
|
-
|
|
28
|
-
if (mode === 'alert') {
|
|
29
|
-
region.removeAttribute('aria-live');
|
|
30
|
-
region.removeAttribute('role');
|
|
31
|
-
alertDebouncer = Debouncer.debounce(alertDebouncer, animationFrame, () => {
|
|
32
|
-
region.setAttribute('role', 'alert');
|
|
33
|
-
});
|
|
34
|
-
} else {
|
|
35
|
-
if (alertDebouncer) {
|
|
36
|
-
alertDebouncer.cancel();
|
|
37
|
-
}
|
|
38
|
-
region.removeAttribute('role');
|
|
39
|
-
region.setAttribute('aria-live', mode);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
region.textContent = '';
|
|
43
|
-
|
|
44
|
-
setTimeout(() => {
|
|
45
|
-
region.textContent = text;
|
|
46
|
-
}, timeout);
|
|
47
|
-
}
|
package/src/active-mixin.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 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 { DisabledMixinClass } from './disabled-mixin.js';
|
|
8
|
-
import type { KeyboardMixinClass } from './keyboard-mixin.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A mixin to toggle the `active` attribute.
|
|
12
|
-
*
|
|
13
|
-
* The attribute is set whenever the user activates the element by a pointer
|
|
14
|
-
* or presses an activation key on the element from the keyboard.
|
|
15
|
-
*
|
|
16
|
-
* The attribute is removed as soon as the element is deactivated
|
|
17
|
-
* by the pointer or by releasing the activation key.
|
|
18
|
-
*/
|
|
19
|
-
export declare function ActiveMixin<T extends Constructor<HTMLElement>>(
|
|
20
|
-
base: T,
|
|
21
|
-
): Constructor<ActiveMixinClass> & Constructor<DisabledMixinClass> & Constructor<KeyboardMixinClass> & T;
|
|
22
|
-
|
|
23
|
-
export declare class ActiveMixinClass {
|
|
24
|
-
/**
|
|
25
|
-
* An array of activation keys.
|
|
26
|
-
*
|
|
27
|
-
* See possible values here:
|
|
28
|
-
* https://developer.mozilla.org/ru/docs/Web/API/KeyboardEvent/key/Key_Values
|
|
29
|
-
*/
|
|
30
|
-
protected readonly _activeKeys: string[];
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Override to define if the component needs to be activated.
|
|
34
|
-
*/
|
|
35
|
-
protected _shouldSetFocus(event: KeyboardEvent | MouseEvent): boolean;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Toggles the `active` attribute on the element.
|
|
39
|
-
*/
|
|
40
|
-
protected _setActive(active: boolean): void;
|
|
41
|
-
}
|
package/src/active-mixin.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { DisabledMixin } from './disabled-mixin.js';
|
|
7
|
-
import { addListener } from './gestures.js';
|
|
8
|
-
import { KeyboardMixin } from './keyboard-mixin.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A mixin to toggle the `active` attribute.
|
|
12
|
-
*
|
|
13
|
-
* The attribute is set whenever the user activates the element by a pointer
|
|
14
|
-
* or presses an activation key on the element from the keyboard.
|
|
15
|
-
*
|
|
16
|
-
* The attribute is removed as soon as the element is deactivated
|
|
17
|
-
* by the pointer or by releasing the activation key.
|
|
18
|
-
*
|
|
19
|
-
* @polymerMixin
|
|
20
|
-
*/
|
|
21
|
-
export const ActiveMixin = (superclass) =>
|
|
22
|
-
class ActiveMixinClass extends DisabledMixin(KeyboardMixin(superclass)) {
|
|
23
|
-
/**
|
|
24
|
-
* An array of activation keys.
|
|
25
|
-
*
|
|
26
|
-
* See possible values here:
|
|
27
|
-
* https://developer.mozilla.org/ru/docs/Web/API/KeyboardEvent/key/Key_Values
|
|
28
|
-
*
|
|
29
|
-
* @protected
|
|
30
|
-
* @return {!Array<!string>}
|
|
31
|
-
*/
|
|
32
|
-
get _activeKeys() {
|
|
33
|
-
return [' '];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** @protected */
|
|
37
|
-
ready() {
|
|
38
|
-
super.ready();
|
|
39
|
-
|
|
40
|
-
addListener(this, 'down', (event) => {
|
|
41
|
-
if (this._shouldSetActive(event)) {
|
|
42
|
-
this._setActive(true);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
addListener(this, 'up', () => {
|
|
47
|
-
this._setActive(false);
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** @protected */
|
|
52
|
-
disconnectedCallback() {
|
|
53
|
-
super.disconnectedCallback();
|
|
54
|
-
|
|
55
|
-
// When the element is disconnecting from the DOM at the moment being active,
|
|
56
|
-
// the `active` attribute needs to be manually removed from the element.
|
|
57
|
-
// Otherwise, it will preserve on the element until the element is activated once again.
|
|
58
|
-
// The case reproduces for `<vaadin-date-picker>` when closing on `Cancel` or `Today` click.
|
|
59
|
-
this._setActive(false);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @param {KeyboardEvent | MouseEvent} _event
|
|
64
|
-
* @protected
|
|
65
|
-
*/
|
|
66
|
-
_shouldSetActive(_event) {
|
|
67
|
-
return !this.disabled;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Sets the `active` attribute on the element if an activation key is pressed.
|
|
72
|
-
*
|
|
73
|
-
* @param {KeyboardEvent} event
|
|
74
|
-
* @protected
|
|
75
|
-
* @override
|
|
76
|
-
*/
|
|
77
|
-
_onKeyDown(event) {
|
|
78
|
-
super._onKeyDown(event);
|
|
79
|
-
|
|
80
|
-
if (this._shouldSetActive(event) && this._activeKeys.includes(event.key)) {
|
|
81
|
-
this._setActive(true);
|
|
82
|
-
|
|
83
|
-
// Element can become hidden before the `keyup` event, e.g. on button click.
|
|
84
|
-
// Use document listener to ensure `active` attribute is removed correctly.
|
|
85
|
-
document.addEventListener(
|
|
86
|
-
'keyup',
|
|
87
|
-
(e) => {
|
|
88
|
-
if (this._activeKeys.includes(e.key)) {
|
|
89
|
-
this._setActive(false);
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
{ once: true },
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Toggles the `active` attribute on the element.
|
|
99
|
-
*
|
|
100
|
-
* @param {boolean} active
|
|
101
|
-
* @protected
|
|
102
|
-
*/
|
|
103
|
-
_setActive(active) {
|
|
104
|
-
this.toggleAttribute('active', active);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 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 { DisabledMixinClass } from './disabled-mixin.js';
|
|
8
|
-
import type { FocusMixinClass } from './focus-mixin.js';
|
|
9
|
-
import type { TabindexMixinClass } from './tabindex-mixin.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* A mixin to forward focus to an element in the light DOM.
|
|
13
|
-
*/
|
|
14
|
-
export declare function DelegateFocusMixin<T extends Constructor<HTMLElement>>(
|
|
15
|
-
base: T,
|
|
16
|
-
): Constructor<DelegateFocusMixinClass> &
|
|
17
|
-
Constructor<DisabledMixinClass> &
|
|
18
|
-
Constructor<FocusMixinClass> &
|
|
19
|
-
Constructor<TabindexMixinClass> &
|
|
20
|
-
T;
|
|
21
|
-
|
|
22
|
-
export declare class DelegateFocusMixinClass {
|
|
23
|
-
/**
|
|
24
|
-
* Specify that this control should have input focus when the page loads.
|
|
25
|
-
*/
|
|
26
|
-
autofocus: boolean;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A reference to the focusable element controlled by the mixin.
|
|
30
|
-
* It can be an input, textarea, button or any element with tabindex > -1.
|
|
31
|
-
*
|
|
32
|
-
* Any component implementing this mixin is expected to provide it
|
|
33
|
-
* by using `this._setFocusElement(input)` Polymer API.
|
|
34
|
-
*/
|
|
35
|
-
readonly focusElement: HTMLElement | null | undefined;
|
|
36
|
-
|
|
37
|
-
protected _addFocusListeners(element: HTMLElement): void;
|
|
38
|
-
|
|
39
|
-
protected _removeFocusListeners(element: HTMLElement): void;
|
|
40
|
-
|
|
41
|
-
protected _focusElementChanged(element: HTMLElement, oldElement: HTMLElement): void;
|
|
42
|
-
|
|
43
|
-
protected _onBlur(event: FocusEvent): void;
|
|
44
|
-
|
|
45
|
-
protected _onFocus(event: FocusEvent): void;
|
|
46
|
-
|
|
47
|
-
protected _setFocusElement(element: HTMLElement): void;
|
|
48
|
-
}
|