@vaadin/component-base 23.2.15 → 23.2.16
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/custom_typings/vaadin-usage-statistics.d.ts +2 -2
- package/index.d.ts +0 -1
- package/index.js +0 -1
- package/package.json +3 -3
- package/src/a11y-announcer.d.ts +1 -1
- package/src/a11y-announcer.js +1 -1
- package/src/active-mixin.d.ts +1 -1
- package/src/active-mixin.js +1 -1
- package/src/async.d.ts +3 -0
- package/src/async.js +2 -1
- package/src/browser-utils.js +7 -7
- package/src/controller-mixin.d.ts +1 -1
- package/src/controller-mixin.js +1 -1
- package/src/debounce.js +2 -2
- package/src/delegate-focus-mixin.d.ts +48 -0
- package/src/delegate-focus-mixin.js +228 -0
- package/src/delegate-state-mixin.d.ts +20 -0
- package/src/delegate-state-mixin.js +125 -0
- package/src/dir-mixin.d.ts +2 -4
- package/src/dir-mixin.js +17 -39
- package/src/dir-utils.d.ts +19 -0
- package/src/dir-utils.js +36 -0
- package/src/disabled-mixin.d.ts +1 -1
- package/src/disabled-mixin.js +1 -1
- package/src/dom-utils.d.ts +6 -1
- package/src/dom-utils.js +11 -1
- package/src/element-mixin.d.ts +1 -1
- package/src/element-mixin.js +11 -5
- package/src/focus-mixin.d.ts +1 -1
- package/src/focus-mixin.js +2 -2
- package/src/focus-trap-controller.d.ts +1 -1
- package/src/focus-trap-controller.js +22 -22
- package/src/focus-utils.d.ts +1 -1
- package/src/focus-utils.js +57 -57
- package/src/gestures.d.ts +6 -12
- package/src/gestures.js +6 -4
- package/src/iron-list-core.js +22 -44
- package/src/keyboard-direction-mixin.d.ts +41 -0
- package/src/keyboard-direction-mixin.js +192 -0
- package/src/keyboard-mixin.d.ts +1 -1
- package/src/keyboard-mixin.js +1 -1
- package/src/list-mixin.d.ts +57 -0
- package/src/list-mixin.js +354 -0
- package/src/media-query-controller.d.ts +1 -1
- package/src/media-query-controller.js +1 -1
- package/src/overflow-controller.d.ts +1 -1
- package/src/overflow-controller.js +3 -3
- package/src/overlay-class-mixin.d.ts +33 -0
- package/src/overlay-class-mixin.js +79 -0
- package/src/polylit-mixin.d.ts +3 -3
- package/src/polylit-mixin.js +9 -4
- package/src/resize-mixin.d.ts +1 -1
- package/src/resize-mixin.js +11 -21
- package/src/slot-child-observe-controller.d.ts +28 -0
- package/src/slot-child-observe-controller.js +176 -0
- package/src/slot-controller.d.ts +33 -5
- package/src/slot-controller.js +103 -40
- package/src/tabindex-mixin.d.ts +1 -1
- package/src/tabindex-mixin.js +1 -1
- package/src/templates.js +1 -1
- package/src/tooltip-controller.d.ts +86 -0
- package/src/tooltip-controller.js +130 -0
- package/src/unique-id-utils.d.ts +1 -1
- package/src/unique-id-utils.js +1 -1
- package/src/virtualizer-iron-list-adapter.js +56 -2
- package/src/virtualizer.js +18 -18
- package/src/dir-helper.d.ts +0 -42
- package/src/dir-helper.js +0 -93
- package/src/slot-mixin.d.ts +0 -18
- package/src/slot-mixin.js +0 -60
package/src/dir-mixin.js
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import { DirHelper } from './dir-helper.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Array of Vaadin custom element classes that have been subscribed to the dir changes.
|
|
10
9
|
*/
|
|
11
10
|
const directionSubscribers = [];
|
|
12
11
|
|
|
13
|
-
function directionUpdater() {
|
|
14
|
-
const documentDir = getDocumentDir();
|
|
15
|
-
directionSubscribers.forEach((element) => {
|
|
16
|
-
alignDirs(element, documentDir);
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let scrollType;
|
|
21
|
-
|
|
22
|
-
const directionObserver = new MutationObserver(directionUpdater);
|
|
23
|
-
directionObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
|
|
24
|
-
|
|
25
12
|
function alignDirs(element, documentDir, elementDir = element.getAttribute('dir')) {
|
|
26
13
|
if (documentDir) {
|
|
27
14
|
element.setAttribute('dir', documentDir);
|
|
@@ -34,6 +21,16 @@ function getDocumentDir() {
|
|
|
34
21
|
return document.documentElement.getAttribute('dir');
|
|
35
22
|
}
|
|
36
23
|
|
|
24
|
+
function directionUpdater() {
|
|
25
|
+
const documentDir = getDocumentDir();
|
|
26
|
+
directionSubscribers.forEach((element) => {
|
|
27
|
+
alignDirs(element, documentDir);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const directionObserver = new MutationObserver(directionUpdater);
|
|
32
|
+
directionObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });
|
|
33
|
+
|
|
37
34
|
/**
|
|
38
35
|
* A mixin to handle `dir` attribute based on the one set on the `<html>` element.
|
|
39
36
|
*
|
|
@@ -62,13 +59,12 @@ export const DirMixin = (superClass) =>
|
|
|
62
59
|
};
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
62
|
+
/**
|
|
63
|
+
* @return {boolean}
|
|
64
|
+
* @protected
|
|
65
|
+
*/
|
|
66
|
+
get __isRTL() {
|
|
67
|
+
return this.getAttribute('dir') === 'rtl';
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
/** @protected */
|
|
@@ -146,22 +142,4 @@ export const DirMixin = (superClass) =>
|
|
|
146
142
|
directionSubscribers.splice(directionSubscribers.indexOf(this), 1);
|
|
147
143
|
}
|
|
148
144
|
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* @param {Element} element
|
|
152
|
-
* @return {number}
|
|
153
|
-
* @protected
|
|
154
|
-
*/
|
|
155
|
-
__getNormalizedScrollLeft(element) {
|
|
156
|
-
return DirHelper.getNormalizedScrollLeft(scrollType, this.getAttribute('dir') || 'ltr', element);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @param {Element} element
|
|
161
|
-
* @param {number} scrollLeft
|
|
162
|
-
* @protected
|
|
163
|
-
*/
|
|
164
|
-
__setNormalizedScrollLeft(element, scrollLeft) {
|
|
165
|
-
return DirHelper.setNormalizedScrollLeft(scrollType, this.getAttribute('dir') || 'ltr', element, scrollLeft);
|
|
166
|
-
}
|
|
167
145
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the scrollLeft value of the element relative to the direction
|
|
9
|
+
*/
|
|
10
|
+
export declare function getNormalizedScrollLeft(element: HTMLElement, direction: string | null): number;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Set the scrollLeft value of the element relative to the direction
|
|
14
|
+
*/
|
|
15
|
+
export declare function setNormalizedScrollLeft(
|
|
16
|
+
element: HTMLElement,
|
|
17
|
+
direction: string | null,
|
|
18
|
+
scrollLeft: number,
|
|
19
|
+
): void;
|
package/src/dir-utils.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the scrollLeft value of the element relative to the direction
|
|
9
|
+
*
|
|
10
|
+
* @param {HTMLElement} element
|
|
11
|
+
* @param {string} direction current direction of the element
|
|
12
|
+
* @return {number} the scrollLeft value.
|
|
13
|
+
*/
|
|
14
|
+
export function getNormalizedScrollLeft(element, direction) {
|
|
15
|
+
const { scrollLeft } = element;
|
|
16
|
+
if (direction !== 'rtl') {
|
|
17
|
+
return scrollLeft;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return element.scrollWidth - element.clientWidth + scrollLeft;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set the scrollLeft value of the element relative to the direction
|
|
25
|
+
*
|
|
26
|
+
* @param {HTMLElement} element
|
|
27
|
+
* @param {string} direction current direction of the element
|
|
28
|
+
* @param {number} scrollLeft the scrollLeft value to be set
|
|
29
|
+
*/
|
|
30
|
+
export function setNormalizedScrollLeft(element, direction, scrollLeft) {
|
|
31
|
+
if (direction !== 'rtl') {
|
|
32
|
+
element.scrollLeft = scrollLeft;
|
|
33
|
+
} else {
|
|
34
|
+
element.scrollLeft = element.clientWidth - element.scrollWidth + scrollLeft;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/disabled-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
package/src/disabled-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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';
|
package/src/dom-utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -23,3 +23,8 @@ export function addValueToAttribute(element: HTMLElement, attr: string, value: s
|
|
|
23
23
|
* If the value is the last one, the whole attribute is removed.
|
|
24
24
|
*/
|
|
25
25
|
export function removeValueFromAttribute(element: HTMLElement, attr: string, value: string): void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns true if the given node is an empty text node, false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function isEmptyTextNode(node: Node): boolean;
|
package/src/dom-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -90,3 +90,13 @@ export function removeValueFromAttribute(element, attr, value) {
|
|
|
90
90
|
}
|
|
91
91
|
element.setAttribute(attr, serializeAttributeValue(values));
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns true if the given node is an empty text node, false otherwise.
|
|
96
|
+
*
|
|
97
|
+
* @param {Node} node
|
|
98
|
+
* @return {boolean}
|
|
99
|
+
*/
|
|
100
|
+
export function isEmptyTextNode(node) {
|
|
101
|
+
return node.nodeType === Node.TEXT_NODE && node.textContent.trim() === '';
|
|
102
|
+
}
|
package/src/element-mixin.d.ts
CHANGED
package/src/element-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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 { setCancelSyntheticClickEvents } from '@polymer/polymer/lib/utils/settings.js';
|
|
@@ -15,14 +15,20 @@ import { DirMixin } from './dir-mixin.js';
|
|
|
15
15
|
// for buttons that are based on `[role=button]` e.g vaadin-button.
|
|
16
16
|
setCancelSyntheticClickEvents(false);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
if (!window.Vaadin) {
|
|
19
|
+
window.Vaadin = {};
|
|
20
|
+
}
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Array of Vaadin custom element classes that have been finalized.
|
|
22
24
|
*/
|
|
23
|
-
|
|
25
|
+
if (!window.Vaadin.registrations) {
|
|
26
|
+
window.Vaadin.registrations = [];
|
|
27
|
+
}
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
if (!window.Vaadin.developmentModeCallback) {
|
|
30
|
+
window.Vaadin.developmentModeCallback = {};
|
|
31
|
+
}
|
|
26
32
|
|
|
27
33
|
window.Vaadin.developmentModeCallback['vaadin-usage-statistics'] = function () {
|
|
28
34
|
usageStatistics();
|
|
@@ -39,7 +45,7 @@ const registered = new Set();
|
|
|
39
45
|
export const ElementMixin = (superClass) =>
|
|
40
46
|
class VaadinElementMixin extends DirMixin(superClass) {
|
|
41
47
|
static get version() {
|
|
42
|
-
return '23.2.
|
|
48
|
+
return '23.2.16';
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
/** @protected */
|
package/src/focus-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
package/src/focus-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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';
|
|
@@ -39,7 +39,7 @@ export const FocusMixin = dedupingMixin(
|
|
|
39
39
|
// In super.ready() other 'focusin' and 'focusout' listeners might be
|
|
40
40
|
// added, so we call it after our own ones to ensure they execute first.
|
|
41
41
|
// Issue to watch out: when incorrect, <vaadin-combo-box> refocuses the
|
|
42
|
-
// input field on iOS after
|
|
42
|
+
// input field on iOS after "Done" is pressed.
|
|
43
43
|
super.ready();
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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';
|
|
@@ -33,6 +33,27 @@ export class FocusTrapController {
|
|
|
33
33
|
this.__onKeyDown = this.__onKeyDown.bind(this);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* An array of tab-ordered focusable elements inside the trap node.
|
|
38
|
+
*
|
|
39
|
+
* @return {HTMLElement[]}
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
get __focusableElements() {
|
|
43
|
+
return getFocusableElements(this.__trapNode);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The index of the element inside the trap node that currently has focus.
|
|
48
|
+
*
|
|
49
|
+
* @return {HTMLElement | undefined}
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
get __focusedElementIndex() {
|
|
53
|
+
const focusableElements = this.__focusableElements;
|
|
54
|
+
return focusableElements.indexOf(focusableElements.filter(isElementFocused).pop());
|
|
55
|
+
}
|
|
56
|
+
|
|
36
57
|
hostConnected() {
|
|
37
58
|
document.addEventListener('keydown', this.__onKeyDown);
|
|
38
59
|
}
|
|
@@ -131,25 +152,4 @@ export class FocusTrapController {
|
|
|
131
152
|
element.select();
|
|
132
153
|
}
|
|
133
154
|
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* An array of tab-ordered focusable elements inside the trap node.
|
|
137
|
-
*
|
|
138
|
-
* @return {HTMLElement[]}
|
|
139
|
-
* @private
|
|
140
|
-
*/
|
|
141
|
-
get __focusableElements() {
|
|
142
|
-
return getFocusableElements(this.__trapNode);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* The index of the element inside the trap node that currently has focus.
|
|
147
|
-
*
|
|
148
|
-
* @return {HTMLElement | undefined}
|
|
149
|
-
* @private
|
|
150
|
-
*/
|
|
151
|
-
get __focusedElementIndex() {
|
|
152
|
-
const focusableElements = this.__focusableElements;
|
|
153
|
-
return focusableElements.indexOf(focusableElements.filter(isElementFocused).pop());
|
|
154
|
-
}
|
|
155
155
|
}
|
package/src/focus-utils.d.ts
CHANGED
package/src/focus-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -61,24 +61,6 @@ function isElementHiddenDirectly(element) {
|
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/**
|
|
65
|
-
* Returns the normalized element tabindex. If not focusable, returns -1.
|
|
66
|
-
* It checks for the attribute "tabindex" instead of the element property
|
|
67
|
-
* `tabIndex` since browsers assign different values to it.
|
|
68
|
-
* e.g. in Firefox `<div contenteditable>` has `tabIndex = -1`
|
|
69
|
-
*
|
|
70
|
-
* @param {HTMLElement} element
|
|
71
|
-
* @return {number}
|
|
72
|
-
*/
|
|
73
|
-
function normalizeTabIndex(element) {
|
|
74
|
-
if (!isElementFocusable(element)) {
|
|
75
|
-
return -1;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const tabIndex = element.getAttribute('tabindex') || 0;
|
|
79
|
-
return Number(tabIndex);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
64
|
/**
|
|
83
65
|
* Returns if element `a` has lower tab order compared to element `b`
|
|
84
66
|
* (both elements are assumed to be focusable and tabbable).
|
|
@@ -138,42 +120,6 @@ function sortElementsByTabIndex(elements) {
|
|
|
138
120
|
return mergeSortByTabIndex(left, right);
|
|
139
121
|
}
|
|
140
122
|
|
|
141
|
-
/**
|
|
142
|
-
* Searches for nodes that are tabbable and adds them to the `result` array.
|
|
143
|
-
* Returns if the `result` array needs to be sorted by tabindex.
|
|
144
|
-
*
|
|
145
|
-
* @param {Node} node The starting point for the search; added to `result` if tabbable.
|
|
146
|
-
* @param {HTMLElement[]} result
|
|
147
|
-
* @return {boolean}
|
|
148
|
-
* @private
|
|
149
|
-
*/
|
|
150
|
-
function collectFocusableNodes(node, result) {
|
|
151
|
-
if (node.nodeType !== Node.ELEMENT_NODE || isElementHiddenDirectly(node)) {
|
|
152
|
-
// Don't traverse children if the node is not an HTML element or not visible.
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const element = /** @type {HTMLElement} */ (node);
|
|
157
|
-
const tabIndex = normalizeTabIndex(element);
|
|
158
|
-
let needsSort = tabIndex > 0;
|
|
159
|
-
if (tabIndex >= 0) {
|
|
160
|
-
result.push(element);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
let children = [];
|
|
164
|
-
if (element.localName === 'slot') {
|
|
165
|
-
children = element.assignedNodes({ flatten: true });
|
|
166
|
-
} else {
|
|
167
|
-
// Use shadow root if possible, will check for distributed nodes.
|
|
168
|
-
children = (element.shadowRoot || element).children;
|
|
169
|
-
}
|
|
170
|
-
[...children].forEach((child) => {
|
|
171
|
-
// Ensure method is always invoked to collect focusable children.
|
|
172
|
-
needsSort = collectFocusableNodes(child, result) || needsSort;
|
|
173
|
-
});
|
|
174
|
-
return needsSort;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
123
|
/**
|
|
178
124
|
* Returns true if the element is hidden, false otherwise.
|
|
179
125
|
*
|
|
@@ -239,6 +185,60 @@ export function isElementFocused(element) {
|
|
|
239
185
|
return element.getRootNode().activeElement === element;
|
|
240
186
|
}
|
|
241
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Returns the normalized element tabindex. If not focusable, returns -1.
|
|
190
|
+
* It checks for the attribute "tabindex" instead of the element property
|
|
191
|
+
* `tabIndex` since browsers assign different values to it.
|
|
192
|
+
* e.g. in Firefox `<div contenteditable>` has `tabIndex = -1`
|
|
193
|
+
*
|
|
194
|
+
* @param {HTMLElement} element
|
|
195
|
+
* @return {number}
|
|
196
|
+
*/
|
|
197
|
+
function normalizeTabIndex(element) {
|
|
198
|
+
if (!isElementFocusable(element)) {
|
|
199
|
+
return -1;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const tabIndex = element.getAttribute('tabindex') || 0;
|
|
203
|
+
return Number(tabIndex);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Searches for nodes that are tabbable and adds them to the `result` array.
|
|
208
|
+
* Returns if the `result` array needs to be sorted by tabindex.
|
|
209
|
+
*
|
|
210
|
+
* @param {Node} node The starting point for the search; added to `result` if tabbable.
|
|
211
|
+
* @param {HTMLElement[]} result
|
|
212
|
+
* @return {boolean}
|
|
213
|
+
* @private
|
|
214
|
+
*/
|
|
215
|
+
function collectFocusableNodes(node, result) {
|
|
216
|
+
if (node.nodeType !== Node.ELEMENT_NODE || isElementHiddenDirectly(node)) {
|
|
217
|
+
// Don't traverse children if the node is not an HTML element or not visible.
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const element = /** @type {HTMLElement} */ (node);
|
|
222
|
+
const tabIndex = normalizeTabIndex(element);
|
|
223
|
+
let needsSort = tabIndex > 0;
|
|
224
|
+
if (tabIndex >= 0) {
|
|
225
|
+
result.push(element);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let children = [];
|
|
229
|
+
if (element.localName === 'slot') {
|
|
230
|
+
children = element.assignedNodes({ flatten: true });
|
|
231
|
+
} else {
|
|
232
|
+
// Use shadow root if possible, will check for distributed nodes.
|
|
233
|
+
children = (element.shadowRoot || element).children;
|
|
234
|
+
}
|
|
235
|
+
[...children].forEach((child) => {
|
|
236
|
+
// Ensure method is always invoked to collect focusable children.
|
|
237
|
+
needsSort = collectFocusableNodes(child, result) || needsSort;
|
|
238
|
+
});
|
|
239
|
+
return needsSort;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
242
|
/**
|
|
243
243
|
* Returns a tab-ordered array of focusable elements for a root element.
|
|
244
244
|
* The resulting array will include the root element if it is focusable.
|
|
@@ -251,8 +251,8 @@ export function isElementFocused(element) {
|
|
|
251
251
|
export function getFocusableElements(element) {
|
|
252
252
|
const focusableElements = [];
|
|
253
253
|
const needsSortByTabIndex = collectFocusableNodes(element, focusableElements);
|
|
254
|
-
// If there is at least one element with tabindex > 0,
|
|
255
|
-
// the final array by tabindex
|
|
254
|
+
// If there is at least one element with tabindex > 0,
|
|
255
|
+
// we need to sort the final array by tabindex.
|
|
256
256
|
if (needsSortByTabIndex) {
|
|
257
257
|
return sortElementsByTabIndex(focusableElements);
|
|
258
258
|
}
|
package/src/gestures.d.ts
CHANGED
|
@@ -8,8 +8,6 @@ Code distributed by Google as part of the polymer project is also
|
|
|
8
8
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
export { deepTargetFind };
|
|
12
|
-
|
|
13
11
|
/**
|
|
14
12
|
* Finds the element rendered on the screen at the provided coordinates.
|
|
15
13
|
*
|
|
@@ -20,8 +18,7 @@ export { deepTargetFind };
|
|
|
20
18
|
* found at the screen position given.
|
|
21
19
|
*/
|
|
22
20
|
declare function deepTargetFind(x: number, y: number): Element | null;
|
|
23
|
-
|
|
24
|
-
export { addListener };
|
|
21
|
+
export { deepTargetFind };
|
|
25
22
|
|
|
26
23
|
/**
|
|
27
24
|
* Adds an event listener to a node for the given gesture type.
|
|
@@ -29,8 +26,7 @@ export { addListener };
|
|
|
29
26
|
* @returns Returns true if a gesture event listener was added.
|
|
30
27
|
*/
|
|
31
28
|
declare function addListener(node: EventTarget, evType: string, handler: (p0: Event) => void): boolean;
|
|
32
|
-
|
|
33
|
-
export { removeListener };
|
|
29
|
+
export { addListener };
|
|
34
30
|
|
|
35
31
|
/**
|
|
36
32
|
* Removes an event listener from a node for the given gesture type.
|
|
@@ -38,16 +34,14 @@ export { removeListener };
|
|
|
38
34
|
* @returns Returns true if a gesture event listener was removed.
|
|
39
35
|
*/
|
|
40
36
|
declare function removeListener(node: EventTarget, evType: string, handler: (p0: Event) => void): boolean;
|
|
41
|
-
|
|
42
|
-
export { register };
|
|
37
|
+
export { removeListener };
|
|
43
38
|
|
|
44
39
|
/**
|
|
45
40
|
* Registers a new gesture event recognizer for adding new custom
|
|
46
41
|
* gesture event types.
|
|
47
42
|
*/
|
|
48
43
|
declare function register(recog: GestureRecognizer): void;
|
|
49
|
-
|
|
50
|
-
export { setTouchAction };
|
|
44
|
+
export { register };
|
|
51
45
|
|
|
52
46
|
/**
|
|
53
47
|
* Sets scrolling direction on node.
|
|
@@ -56,13 +50,13 @@ export { setTouchAction };
|
|
|
56
50
|
* adding event listeners.
|
|
57
51
|
*/
|
|
58
52
|
declare function setTouchAction(node: EventTarget, value: string): void;
|
|
59
|
-
|
|
60
|
-
export { prevent };
|
|
53
|
+
export { setTouchAction };
|
|
61
54
|
|
|
62
55
|
/**
|
|
63
56
|
* Prevents the dispatch and default action of the given event name.
|
|
64
57
|
*/
|
|
65
58
|
declare function prevent(evName: string): void;
|
|
59
|
+
export { prevent };
|
|
66
60
|
|
|
67
61
|
export interface GestureRecognizer {
|
|
68
62
|
reset(): void;
|
package/src/gestures.js
CHANGED
|
@@ -8,6 +8,8 @@ Code distributed by Google as part of the polymer project is also
|
|
|
8
8
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* @fileoverview
|
|
13
15
|
*
|
|
@@ -90,7 +92,7 @@ function PASSIVE_TOUCH(eventName) {
|
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
// Check for touch-only devices
|
|
93
|
-
const IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
|
|
95
|
+
const IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/u);
|
|
94
96
|
|
|
95
97
|
// Defined at https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#enabling-and-disabling-form-controls:-the-disabled-attribute
|
|
96
98
|
/** @type {!Object<boolean>} */
|
|
@@ -468,9 +470,9 @@ function _remove(node, evType, handler) {
|
|
|
468
470
|
*/
|
|
469
471
|
export function register(recog) {
|
|
470
472
|
recognizers.push(recog);
|
|
471
|
-
|
|
472
|
-
gestures[
|
|
473
|
-
}
|
|
473
|
+
recog.emits.forEach((emit) => {
|
|
474
|
+
gestures[emit] = recog;
|
|
475
|
+
});
|
|
474
476
|
}
|
|
475
477
|
|
|
476
478
|
/**
|