@oscarpalmer/atoms 0.15.0 → 0.17.0
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/dist/js/array.js +101 -67
- package/dist/js/array.mjs +106 -44
- package/dist/js/element/focusable.js +24 -32
- package/dist/js/element/focusable.mjs +24 -32
- package/dist/js/element/index.js +28 -11
- package/dist/js/element/index.mjs +28 -11
- package/dist/js/index.js +275 -153
- package/dist/js/index.mjs +1 -0
- package/dist/js/number.js +11 -7
- package/dist/js/number.mjs +11 -7
- package/dist/js/object.js +40 -0
- package/dist/js/object.mjs +36 -0
- package/dist/js/string.js +5 -1
- package/dist/js/string.mjs +5 -1
- package/dist/js/value.js +5 -1
- package/package.json +9 -9
- package/src/js/array.ts +293 -64
- package/src/js/element/focusable.ts +44 -55
- package/src/js/element/index.ts +71 -32
- package/src/js/index.ts +1 -0
- package/src/js/number.ts +19 -10
- package/src/js/object.ts +48 -0
- package/src/js/string.ts +7 -5
- package/src/js/value.ts +2 -2
- package/types/array.d.ts +59 -11
- package/types/element/focusable.d.ts +2 -5
- package/types/element/index.d.ts +3 -2
- package/types/index.d.ts +1 -0
- package/types/number.d.ts +5 -0
- package/types/object.d.ts +9 -0
package/dist/js/array.js
CHANGED
|
@@ -1,47 +1,87 @@
|
|
|
1
|
-
// src/js/
|
|
2
|
-
function
|
|
3
|
-
if (typeof
|
|
4
|
-
return
|
|
1
|
+
// src/js/array.ts
|
|
2
|
+
var _getCallbacks = function(bool, key) {
|
|
3
|
+
if (typeof bool === "function") {
|
|
4
|
+
return { bool };
|
|
5
5
|
}
|
|
6
|
-
if (typeof
|
|
7
|
-
return
|
|
6
|
+
if (typeof key === "function") {
|
|
7
|
+
return { key };
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
if (typeof
|
|
11
|
-
|
|
9
|
+
const isString = typeof key === "string";
|
|
10
|
+
if (!isString && typeof key !== "number" || isString && key.includes(".")) {
|
|
11
|
+
return;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return {
|
|
14
|
+
key: (item) => item?.[key]
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
var _findValue = function(type, array, value, key) {
|
|
18
|
+
const callbacks = _getCallbacks(value, key);
|
|
19
|
+
if (callbacks?.bool === undefined && callbacks?.key === undefined) {
|
|
20
|
+
return type === "index" ? array.indexOf(value) : array.find((item) => item === value);
|
|
15
21
|
}
|
|
16
|
-
if (
|
|
17
|
-
|
|
22
|
+
if (callbacks.bool !== undefined) {
|
|
23
|
+
const index2 = array.findIndex(callbacks.bool);
|
|
24
|
+
return type === "index" ? index2 : index2 > -1 ? array[index2] : undefined;
|
|
18
25
|
}
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
const { length } = array;
|
|
27
|
+
let index = 0;
|
|
28
|
+
for (;index < length; index += 1) {
|
|
29
|
+
const item = array[index];
|
|
30
|
+
if (callbacks.key?.(item) === value) {
|
|
31
|
+
return type === "index" ? index : item;
|
|
32
|
+
}
|
|
22
33
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
return type === "index" ? -1 : undefined;
|
|
35
|
+
};
|
|
36
|
+
var _findValues = function(type, array, value, key) {
|
|
37
|
+
const callbacks = _getCallbacks(value, key);
|
|
38
|
+
const { length } = array;
|
|
39
|
+
if (type === "unique" && callbacks?.key === undefined && length >= 100) {
|
|
40
|
+
return Array.from(new Set(array));
|
|
26
41
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// src/js/array.ts
|
|
31
|
-
var _getCallback = function(value) {
|
|
32
|
-
if (typeof value === "function") {
|
|
33
|
-
return value;
|
|
42
|
+
if (typeof callbacks?.bool === "function") {
|
|
43
|
+
return array.filter(callbacks.bool);
|
|
34
44
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
if (type === "all" && key === undefined) {
|
|
46
|
+
return array.filter((item) => item === value);
|
|
47
|
+
}
|
|
48
|
+
const hasCallback = typeof callbacks?.key === "function";
|
|
49
|
+
const result = [];
|
|
50
|
+
const values = hasCallback ? [] : result;
|
|
51
|
+
let index = 0;
|
|
52
|
+
for (;index < length; index += 1) {
|
|
53
|
+
const item = array[index];
|
|
54
|
+
const itemValue = hasCallback ? callbacks.key?.(item) : item;
|
|
55
|
+
if (type === "all" && itemValue === value || type === "unique" && values.indexOf(itemValue) === -1) {
|
|
56
|
+
if (values !== result) {
|
|
57
|
+
values.push(itemValue);
|
|
58
|
+
}
|
|
59
|
+
result.push(item);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
var _insertValues = function(type, array, values, start, deleteCount) {
|
|
65
|
+
const chunked = chunk(values).reverse();
|
|
66
|
+
const { length } = chunked;
|
|
67
|
+
let index = 0;
|
|
68
|
+
let returned;
|
|
69
|
+
for (;index < length; index += 1) {
|
|
70
|
+
const result = array.splice(start, index === 0 ? deleteCount : 0, ...chunked[index]);
|
|
71
|
+
if (returned === undefined) {
|
|
72
|
+
returned = result;
|
|
73
|
+
}
|
|
38
74
|
}
|
|
39
|
-
return
|
|
75
|
+
return type === "splice" ? returned : array.length;
|
|
40
76
|
};
|
|
41
77
|
function chunk(array, size) {
|
|
78
|
+
const { length } = array;
|
|
79
|
+
const chunkSize = typeof size === "number" && size > 0 ? size : 32000;
|
|
80
|
+
if (length <= chunkSize) {
|
|
81
|
+
return [array];
|
|
82
|
+
}
|
|
42
83
|
const chunks = [];
|
|
43
|
-
|
|
44
|
-
let remaining = Number(array.length);
|
|
84
|
+
let remaining = Number(length);
|
|
45
85
|
while (remaining > 0) {
|
|
46
86
|
chunks.push(array.splice(0, chunkSize));
|
|
47
87
|
remaining -= chunkSize;
|
|
@@ -49,23 +89,17 @@ function chunk(array, size) {
|
|
|
49
89
|
return chunks;
|
|
50
90
|
}
|
|
51
91
|
function exists(array, value, key) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (;index < length; index += 1) {
|
|
60
|
-
if (callback(array[index]) === needle) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return false;
|
|
92
|
+
return _findValue("index", array, value, key) > -1;
|
|
93
|
+
}
|
|
94
|
+
function filter(array, value, key) {
|
|
95
|
+
return _findValues("all", array, value, key);
|
|
96
|
+
}
|
|
97
|
+
function find(array, value, key) {
|
|
98
|
+
return _findValue("value", array, value, key);
|
|
65
99
|
}
|
|
66
100
|
function groupBy(array, key) {
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
101
|
+
const callbacks = _getCallbacks(undefined, key);
|
|
102
|
+
if (callbacks?.key === undefined) {
|
|
69
103
|
return {};
|
|
70
104
|
}
|
|
71
105
|
const grouped = {};
|
|
@@ -73,7 +107,7 @@ function groupBy(array, key) {
|
|
|
73
107
|
let index = 0;
|
|
74
108
|
for (;index < length; index += 1) {
|
|
75
109
|
const item = array[index];
|
|
76
|
-
const value =
|
|
110
|
+
const value = callbacks.key(item);
|
|
77
111
|
if (value in grouped) {
|
|
78
112
|
grouped[value].push(item);
|
|
79
113
|
} else {
|
|
@@ -82,30 +116,30 @@ function groupBy(array, key) {
|
|
|
82
116
|
}
|
|
83
117
|
return grouped;
|
|
84
118
|
}
|
|
119
|
+
function indexOf(array, value, key) {
|
|
120
|
+
return _findValue("index", array, value, key);
|
|
121
|
+
}
|
|
122
|
+
function insert(array, index, values) {
|
|
123
|
+
_insertValues("splice", array, values, index, 0);
|
|
124
|
+
}
|
|
125
|
+
function push(array, values) {
|
|
126
|
+
return _insertValues("push", array, values, array.length, 0);
|
|
127
|
+
}
|
|
128
|
+
function splice(array, start, deleteCount, values) {
|
|
129
|
+
return _insertValues("splice", array, values, start, deleteCount);
|
|
130
|
+
}
|
|
85
131
|
function unique(array, key) {
|
|
86
|
-
|
|
87
|
-
const { length } = array;
|
|
88
|
-
if (keyCallback === undefined && length >= 100) {
|
|
89
|
-
return Array.from(new Set(array));
|
|
90
|
-
}
|
|
91
|
-
const result = [];
|
|
92
|
-
const values = keyCallback === undefined ? result : [];
|
|
93
|
-
let index = 0;
|
|
94
|
-
for (;index < length; index += 1) {
|
|
95
|
-
const item = array[index];
|
|
96
|
-
const value = keyCallback?.(item) ?? item;
|
|
97
|
-
if (values.indexOf(value) === -1) {
|
|
98
|
-
if (values !== result) {
|
|
99
|
-
values.push(value);
|
|
100
|
-
}
|
|
101
|
-
result.push(item);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return result;
|
|
132
|
+
return _findValues("unique", array, undefined, key);
|
|
105
133
|
}
|
|
106
134
|
export {
|
|
107
135
|
unique,
|
|
136
|
+
splice,
|
|
137
|
+
push,
|
|
138
|
+
insert,
|
|
139
|
+
indexOf,
|
|
108
140
|
groupBy,
|
|
141
|
+
find,
|
|
142
|
+
filter,
|
|
109
143
|
exists,
|
|
110
144
|
chunk
|
|
111
145
|
};
|
package/dist/js/array.mjs
CHANGED
|
@@ -1,19 +1,87 @@
|
|
|
1
1
|
// src/js/array.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return value;
|
|
2
|
+
var _getCallbacks = function(bool, key) {
|
|
3
|
+
if (typeof bool === "function") {
|
|
4
|
+
return { bool };
|
|
6
5
|
}
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
if (typeof key === "function") {
|
|
7
|
+
return { key };
|
|
8
|
+
}
|
|
9
|
+
const isString = typeof key === "string";
|
|
10
|
+
if (!isString && typeof key !== "number" || isString && key.includes(".")) {
|
|
9
11
|
return;
|
|
10
12
|
}
|
|
11
|
-
return
|
|
13
|
+
return {
|
|
14
|
+
key: (item) => item?.[key]
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
var _findValue = function(type, array, value, key) {
|
|
18
|
+
const callbacks = _getCallbacks(value, key);
|
|
19
|
+
if (callbacks?.bool === undefined && callbacks?.key === undefined) {
|
|
20
|
+
return type === "index" ? array.indexOf(value) : array.find((item) => item === value);
|
|
21
|
+
}
|
|
22
|
+
if (callbacks.bool !== undefined) {
|
|
23
|
+
const index2 = array.findIndex(callbacks.bool);
|
|
24
|
+
return type === "index" ? index2 : index2 > -1 ? array[index2] : undefined;
|
|
25
|
+
}
|
|
26
|
+
const { length } = array;
|
|
27
|
+
let index = 0;
|
|
28
|
+
for (;index < length; index += 1) {
|
|
29
|
+
const item = array[index];
|
|
30
|
+
if (callbacks.key?.(item) === value) {
|
|
31
|
+
return type === "index" ? index : item;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return type === "index" ? -1 : undefined;
|
|
35
|
+
};
|
|
36
|
+
var _findValues = function(type, array, value, key) {
|
|
37
|
+
const callbacks = _getCallbacks(value, key);
|
|
38
|
+
const { length } = array;
|
|
39
|
+
if (type === "unique" && callbacks?.key === undefined && length >= 100) {
|
|
40
|
+
return Array.from(new Set(array));
|
|
41
|
+
}
|
|
42
|
+
if (typeof callbacks?.bool === "function") {
|
|
43
|
+
return array.filter(callbacks.bool);
|
|
44
|
+
}
|
|
45
|
+
if (type === "all" && key === undefined) {
|
|
46
|
+
return array.filter((item) => item === value);
|
|
47
|
+
}
|
|
48
|
+
const hasCallback = typeof callbacks?.key === "function";
|
|
49
|
+
const result = [];
|
|
50
|
+
const values = hasCallback ? [] : result;
|
|
51
|
+
let index = 0;
|
|
52
|
+
for (;index < length; index += 1) {
|
|
53
|
+
const item = array[index];
|
|
54
|
+
const itemValue = hasCallback ? callbacks.key?.(item) : item;
|
|
55
|
+
if (type === "all" && itemValue === value || type === "unique" && values.indexOf(itemValue) === -1) {
|
|
56
|
+
if (values !== result) {
|
|
57
|
+
values.push(itemValue);
|
|
58
|
+
}
|
|
59
|
+
result.push(item);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
var _insertValues = function(type, array, values, start, deleteCount) {
|
|
65
|
+
const chunked = chunk(values).reverse();
|
|
66
|
+
const { length } = chunked;
|
|
67
|
+
let index = 0;
|
|
68
|
+
let returned;
|
|
69
|
+
for (;index < length; index += 1) {
|
|
70
|
+
const result = array.splice(start, index === 0 ? deleteCount : 0, ...chunked[index]);
|
|
71
|
+
if (returned === undefined) {
|
|
72
|
+
returned = result;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return type === "splice" ? returned : array.length;
|
|
12
76
|
};
|
|
13
77
|
function chunk(array, size) {
|
|
78
|
+
const { length } = array;
|
|
79
|
+
const chunkSize = typeof size === "number" && size > 0 ? size : 32000;
|
|
80
|
+
if (length <= chunkSize) {
|
|
81
|
+
return [array];
|
|
82
|
+
}
|
|
14
83
|
const chunks = [];
|
|
15
|
-
|
|
16
|
-
let remaining = Number(array.length);
|
|
84
|
+
let remaining = Number(length);
|
|
17
85
|
while (remaining > 0) {
|
|
18
86
|
chunks.push(array.splice(0, chunkSize));
|
|
19
87
|
remaining -= chunkSize;
|
|
@@ -21,23 +89,17 @@ function chunk(array, size) {
|
|
|
21
89
|
return chunks;
|
|
22
90
|
}
|
|
23
91
|
function exists(array, value, key) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
for (;index < length; index += 1) {
|
|
32
|
-
if (callback(array[index]) === needle) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return false;
|
|
92
|
+
return _findValue("index", array, value, key) > -1;
|
|
93
|
+
}
|
|
94
|
+
function filter(array, value, key) {
|
|
95
|
+
return _findValues("all", array, value, key);
|
|
96
|
+
}
|
|
97
|
+
function find(array, value, key) {
|
|
98
|
+
return _findValue("value", array, value, key);
|
|
37
99
|
}
|
|
38
100
|
function groupBy(array, key) {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
101
|
+
const callbacks = _getCallbacks(undefined, key);
|
|
102
|
+
if (callbacks?.key === undefined) {
|
|
41
103
|
return {};
|
|
42
104
|
}
|
|
43
105
|
const grouped = {};
|
|
@@ -45,7 +107,7 @@ function groupBy(array, key) {
|
|
|
45
107
|
let index = 0;
|
|
46
108
|
for (;index < length; index += 1) {
|
|
47
109
|
const item = array[index];
|
|
48
|
-
const value =
|
|
110
|
+
const value = callbacks.key(item);
|
|
49
111
|
if (value in grouped) {
|
|
50
112
|
grouped[value].push(item);
|
|
51
113
|
} else {
|
|
@@ -54,30 +116,30 @@ function groupBy(array, key) {
|
|
|
54
116
|
}
|
|
55
117
|
return grouped;
|
|
56
118
|
}
|
|
119
|
+
function indexOf(array, value, key) {
|
|
120
|
+
return _findValue("index", array, value, key);
|
|
121
|
+
}
|
|
122
|
+
function insert(array, index, values) {
|
|
123
|
+
_insertValues("splice", array, values, index, 0);
|
|
124
|
+
}
|
|
125
|
+
function push(array, values) {
|
|
126
|
+
return _insertValues("push", array, values, array.length, 0);
|
|
127
|
+
}
|
|
128
|
+
function splice(array, start, deleteCount, values) {
|
|
129
|
+
return _insertValues("splice", array, values, start, deleteCount);
|
|
130
|
+
}
|
|
57
131
|
function unique(array, key) {
|
|
58
|
-
|
|
59
|
-
const { length } = array;
|
|
60
|
-
if (keyCallback === undefined && length >= 100) {
|
|
61
|
-
return Array.from(new Set(array));
|
|
62
|
-
}
|
|
63
|
-
const result = [];
|
|
64
|
-
const values = keyCallback === undefined ? result : [];
|
|
65
|
-
let index = 0;
|
|
66
|
-
for (;index < length; index += 1) {
|
|
67
|
-
const item = array[index];
|
|
68
|
-
const value = keyCallback?.(item) ?? item;
|
|
69
|
-
if (values.indexOf(value) === -1) {
|
|
70
|
-
if (values !== result) {
|
|
71
|
-
values.push(value);
|
|
72
|
-
}
|
|
73
|
-
result.push(item);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
132
|
+
return _findValues("unique", array, undefined, key);
|
|
77
133
|
}
|
|
78
134
|
export {
|
|
79
135
|
unique,
|
|
136
|
+
splice,
|
|
137
|
+
push,
|
|
138
|
+
insert,
|
|
139
|
+
indexOf,
|
|
80
140
|
groupBy,
|
|
141
|
+
find,
|
|
142
|
+
filter,
|
|
81
143
|
exists,
|
|
82
144
|
chunk
|
|
83
145
|
};
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// src/js/element/focusable.ts
|
|
2
|
-
var _getItem = function(
|
|
2
|
+
var _getItem = function(element, tabbable) {
|
|
3
3
|
return {
|
|
4
4
|
element,
|
|
5
|
-
tabIndex:
|
|
5
|
+
tabIndex: tabbable ? _getTabIndex(element) : -1
|
|
6
6
|
};
|
|
7
7
|
};
|
|
8
|
+
var _getFocusableFilters = function() {
|
|
9
|
+
return [_isDisabled, _isInert, _isHidden, _isSummarised];
|
|
10
|
+
};
|
|
11
|
+
var _getTabbableFilters = function() {
|
|
12
|
+
return [_isNotTabbable, _isNotTabbableRadio, ..._getFocusableFilters()];
|
|
13
|
+
};
|
|
8
14
|
var _getTabIndex = function(element) {
|
|
9
|
-
|
|
15
|
+
const tabIndex = element?.tabIndex ?? -1;
|
|
16
|
+
if (tabIndex < 0 && (/^(audio|details|video)$/i.test(element.tagName) || _isEditable(element)) && !_hasTabIndex(element)) {
|
|
10
17
|
return 0;
|
|
11
18
|
}
|
|
12
|
-
return
|
|
19
|
+
return tabIndex;
|
|
13
20
|
};
|
|
14
|
-
var _getValidElements = function(
|
|
15
|
-
const items = Array.from(parent.querySelectorAll(selector)).map((element) => _getItem(
|
|
16
|
-
if (
|
|
21
|
+
var _getValidElements = function(parent, filters, tabbable) {
|
|
22
|
+
const items = Array.from(parent.querySelectorAll(selector)).map((element) => _getItem(element, tabbable)).filter((item) => !filters.some((filter) => filter(item)));
|
|
23
|
+
if (!tabbable) {
|
|
17
24
|
return items.map((item) => item.element);
|
|
18
25
|
}
|
|
19
26
|
const indiced = [];
|
|
@@ -37,7 +44,7 @@ var _hasTabIndex = function(element) {
|
|
|
37
44
|
return !Number.isNaN(Number.parseInt(element.getAttribute("tabindex"), 10));
|
|
38
45
|
};
|
|
39
46
|
var _isDisabled = function(item) {
|
|
40
|
-
if (
|
|
47
|
+
if (/^(button|input|select|textarea)$/i.test(item.element.tagName) && _isDisabledFromFieldset(item.element)) {
|
|
41
48
|
return true;
|
|
42
49
|
}
|
|
43
50
|
return (item.element.disabled ?? false) || item.element.getAttribute("aria-disabled") === "true";
|
|
@@ -62,7 +69,7 @@ var _isDisabledFromFieldset = function(element) {
|
|
|
62
69
|
return false;
|
|
63
70
|
};
|
|
64
71
|
var _isEditable = function(element) {
|
|
65
|
-
return
|
|
72
|
+
return /^(|true)$/i.test(element.getAttribute("contenteditable"));
|
|
66
73
|
};
|
|
67
74
|
var _isHidden = function(item) {
|
|
68
75
|
if ((item.element.hidden ?? false) || item.element instanceof HTMLInputElement && item.element.type === "hidden") {
|
|
@@ -81,7 +88,7 @@ var _isHidden = function(item) {
|
|
|
81
88
|
return height === 0 && width === 0;
|
|
82
89
|
};
|
|
83
90
|
var _isInert = function(item) {
|
|
84
|
-
return (item.element.inert ?? false) ||
|
|
91
|
+
return (item.element.inert ?? false) || /^(|true)$/i.test(item.element.getAttribute("inert")) || item.element.parentElement !== null && _isInert({
|
|
85
92
|
element: item.element.parentElement,
|
|
86
93
|
tabIndex: -1
|
|
87
94
|
});
|
|
@@ -100,33 +107,24 @@ var _isNotTabbableRadio = function(item) {
|
|
|
100
107
|
return checked !== undefined && checked !== item.element;
|
|
101
108
|
};
|
|
102
109
|
var _isSummarised = function(item) {
|
|
103
|
-
return item.element instanceof HTMLDetailsElement && Array.from(item.element.children).some((child) =>
|
|
110
|
+
return item.element instanceof HTMLDetailsElement && Array.from(item.element.children).some((child) => /^summary$/i.test(child.tagName));
|
|
104
111
|
};
|
|
105
|
-
var _isValidElement = function(element, filters) {
|
|
106
|
-
const item = _getItem(
|
|
112
|
+
var _isValidElement = function(element, filters, tabbable) {
|
|
113
|
+
const item = _getItem(element, tabbable);
|
|
107
114
|
return !filters.some((filter) => filter(item));
|
|
108
115
|
};
|
|
109
116
|
function getFocusableElements(parent) {
|
|
110
|
-
return _getValidElements(
|
|
117
|
+
return _getValidElements(parent, _getFocusableFilters(), false);
|
|
111
118
|
}
|
|
112
119
|
function getTabbableElements(parent) {
|
|
113
|
-
return _getValidElements(
|
|
120
|
+
return _getValidElements(parent, _getTabbableFilters(), true);
|
|
114
121
|
}
|
|
115
122
|
function isFocusableElement(element) {
|
|
116
|
-
return _isValidElement(element,
|
|
123
|
+
return _isValidElement(element, _getFocusableFilters(), false);
|
|
117
124
|
}
|
|
118
125
|
function isTabbableElement(element) {
|
|
119
|
-
return _isValidElement(element,
|
|
126
|
+
return _isValidElement(element, _getTabbableFilters(), true);
|
|
120
127
|
}
|
|
121
|
-
var audioDetailsVideoPattern = /^(audio|details|video)$/i;
|
|
122
|
-
var booleanPattern = /^(|true)$/i;
|
|
123
|
-
var focusableFilters = [
|
|
124
|
-
_isDisabled,
|
|
125
|
-
_isInert,
|
|
126
|
-
_isHidden,
|
|
127
|
-
_isSummarised
|
|
128
|
-
];
|
|
129
|
-
var inputPattern = /^(button|input|select|textarea)$/i;
|
|
130
128
|
var selector = [
|
|
131
129
|
'[contenteditable]:not([contenteditable="false"])',
|
|
132
130
|
"[tabindex]:not(slot)",
|
|
@@ -140,12 +138,6 @@ var selector = [
|
|
|
140
138
|
"textarea",
|
|
141
139
|
"video[controls]"
|
|
142
140
|
].map((selector2) => `${selector2}:not([inert])`).join(",");
|
|
143
|
-
var summaryPattern = /^summary$/i;
|
|
144
|
-
var tabbableFilters = [
|
|
145
|
-
_isNotTabbable,
|
|
146
|
-
_isNotTabbableRadio,
|
|
147
|
-
...focusableFilters
|
|
148
|
-
];
|
|
149
141
|
export {
|
|
150
142
|
isTabbableElement,
|
|
151
143
|
isFocusableElement,
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// src/js/element/focusable.ts
|
|
2
|
-
var _getItem = function(
|
|
2
|
+
var _getItem = function(element, tabbable) {
|
|
3
3
|
return {
|
|
4
4
|
element,
|
|
5
|
-
tabIndex:
|
|
5
|
+
tabIndex: tabbable ? _getTabIndex(element) : -1
|
|
6
6
|
};
|
|
7
7
|
};
|
|
8
|
+
var _getFocusableFilters = function() {
|
|
9
|
+
return [_isDisabled, _isInert, _isHidden, _isSummarised];
|
|
10
|
+
};
|
|
11
|
+
var _getTabbableFilters = function() {
|
|
12
|
+
return [_isNotTabbable, _isNotTabbableRadio, ..._getFocusableFilters()];
|
|
13
|
+
};
|
|
8
14
|
var _getTabIndex = function(element) {
|
|
9
|
-
|
|
15
|
+
const tabIndex = element?.tabIndex ?? -1;
|
|
16
|
+
if (tabIndex < 0 && (/^(audio|details|video)$/i.test(element.tagName) || _isEditable(element)) && !_hasTabIndex(element)) {
|
|
10
17
|
return 0;
|
|
11
18
|
}
|
|
12
|
-
return
|
|
19
|
+
return tabIndex;
|
|
13
20
|
};
|
|
14
|
-
var _getValidElements = function(
|
|
15
|
-
const items = Array.from(parent.querySelectorAll(selector)).map((element) => _getItem(
|
|
16
|
-
if (
|
|
21
|
+
var _getValidElements = function(parent, filters, tabbable) {
|
|
22
|
+
const items = Array.from(parent.querySelectorAll(selector)).map((element) => _getItem(element, tabbable)).filter((item) => !filters.some((filter) => filter(item)));
|
|
23
|
+
if (!tabbable) {
|
|
17
24
|
return items.map((item) => item.element);
|
|
18
25
|
}
|
|
19
26
|
const indiced = [];
|
|
@@ -37,7 +44,7 @@ var _hasTabIndex = function(element) {
|
|
|
37
44
|
return !Number.isNaN(Number.parseInt(element.getAttribute("tabindex"), 10));
|
|
38
45
|
};
|
|
39
46
|
var _isDisabled = function(item) {
|
|
40
|
-
if (
|
|
47
|
+
if (/^(button|input|select|textarea)$/i.test(item.element.tagName) && _isDisabledFromFieldset(item.element)) {
|
|
41
48
|
return true;
|
|
42
49
|
}
|
|
43
50
|
return (item.element.disabled ?? false) || item.element.getAttribute("aria-disabled") === "true";
|
|
@@ -62,7 +69,7 @@ var _isDisabledFromFieldset = function(element) {
|
|
|
62
69
|
return false;
|
|
63
70
|
};
|
|
64
71
|
var _isEditable = function(element) {
|
|
65
|
-
return
|
|
72
|
+
return /^(|true)$/i.test(element.getAttribute("contenteditable"));
|
|
66
73
|
};
|
|
67
74
|
var _isHidden = function(item) {
|
|
68
75
|
if ((item.element.hidden ?? false) || item.element instanceof HTMLInputElement && item.element.type === "hidden") {
|
|
@@ -81,7 +88,7 @@ var _isHidden = function(item) {
|
|
|
81
88
|
return height === 0 && width === 0;
|
|
82
89
|
};
|
|
83
90
|
var _isInert = function(item) {
|
|
84
|
-
return (item.element.inert ?? false) ||
|
|
91
|
+
return (item.element.inert ?? false) || /^(|true)$/i.test(item.element.getAttribute("inert")) || item.element.parentElement !== null && _isInert({
|
|
85
92
|
element: item.element.parentElement,
|
|
86
93
|
tabIndex: -1
|
|
87
94
|
});
|
|
@@ -100,33 +107,24 @@ var _isNotTabbableRadio = function(item) {
|
|
|
100
107
|
return checked !== undefined && checked !== item.element;
|
|
101
108
|
};
|
|
102
109
|
var _isSummarised = function(item) {
|
|
103
|
-
return item.element instanceof HTMLDetailsElement && Array.from(item.element.children).some((child) =>
|
|
110
|
+
return item.element instanceof HTMLDetailsElement && Array.from(item.element.children).some((child) => /^summary$/i.test(child.tagName));
|
|
104
111
|
};
|
|
105
|
-
var _isValidElement = function(element, filters) {
|
|
106
|
-
const item = _getItem(
|
|
112
|
+
var _isValidElement = function(element, filters, tabbable) {
|
|
113
|
+
const item = _getItem(element, tabbable);
|
|
107
114
|
return !filters.some((filter) => filter(item));
|
|
108
115
|
};
|
|
109
116
|
function getFocusableElements(parent) {
|
|
110
|
-
return _getValidElements(
|
|
117
|
+
return _getValidElements(parent, _getFocusableFilters(), false);
|
|
111
118
|
}
|
|
112
119
|
function getTabbableElements(parent) {
|
|
113
|
-
return _getValidElements(
|
|
120
|
+
return _getValidElements(parent, _getTabbableFilters(), true);
|
|
114
121
|
}
|
|
115
122
|
function isFocusableElement(element) {
|
|
116
|
-
return _isValidElement(element,
|
|
123
|
+
return _isValidElement(element, _getFocusableFilters(), false);
|
|
117
124
|
}
|
|
118
125
|
function isTabbableElement(element) {
|
|
119
|
-
return _isValidElement(element,
|
|
126
|
+
return _isValidElement(element, _getTabbableFilters(), true);
|
|
120
127
|
}
|
|
121
|
-
var audioDetailsVideoPattern = /^(audio|details|video)$/i;
|
|
122
|
-
var booleanPattern = /^(|true)$/i;
|
|
123
|
-
var focusableFilters = [
|
|
124
|
-
_isDisabled,
|
|
125
|
-
_isInert,
|
|
126
|
-
_isHidden,
|
|
127
|
-
_isSummarised
|
|
128
|
-
];
|
|
129
|
-
var inputPattern = /^(button|input|select|textarea)$/i;
|
|
130
128
|
var selector = [
|
|
131
129
|
'[contenteditable]:not([contenteditable="false"])',
|
|
132
130
|
"[tabindex]:not(slot)",
|
|
@@ -140,12 +138,6 @@ var selector = [
|
|
|
140
138
|
"textarea",
|
|
141
139
|
"video[controls]"
|
|
142
140
|
].map((selector2) => `${selector2}:not([inert])`).join(",");
|
|
143
|
-
var summaryPattern = /^summary$/i;
|
|
144
|
-
var tabbableFilters = [
|
|
145
|
-
_isNotTabbable,
|
|
146
|
-
_isNotTabbableRadio,
|
|
147
|
-
...focusableFilters
|
|
148
|
-
];
|
|
149
141
|
export {
|
|
150
142
|
isTabbableElement,
|
|
151
143
|
isFocusableElement,
|