@wordpress/dom 4.55.0 → 4.55.2-next.v.202609171837.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/CHANGELOG.md +7 -0
- package/README.md +73 -73
- package/build/dom/get-rectangle-from-range.cjs +47 -22
- package/build/dom/get-rectangle-from-range.cjs.map +2 -2
- package/build/focusable.cjs +5 -8
- package/build/focusable.cjs.map +2 -2
- package/build-module/dom/get-rectangle-from-range.mjs +47 -22
- package/build-module/dom/get-rectangle-from-range.mjs.map +2 -2
- package/build-module/focusable.mjs +5 -8
- package/build-module/focusable.mjs.map +2 -2
- package/build-types/dom/get-rectangle-from-range.d.ts.map +1 -1
- package/build-types/focusable.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/dom/get-rectangle-from-range.js +64 -31
- package/src/dom/test/get-rectangle-from-range.browser.test.js +128 -0
- package/src/focusable.js +8 -11
- package/src/test/focusable-area.jsdom.test.js +43 -0
- package/src/test/focusable.browser.test.js +243 -2
- package/src/test/{tabbable.jsdom.test.js → tabbable.browser.test.js} +11 -5
- package/src/test/focusable.jsdom.test.js +0 -193
- package/src/test/utils/create-element.js +0 -54
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 4.55.1-next.0 (2026-09-17)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- `getRectangleFromRange`: Measure a collapsed range on an element at the text position next to it instead of inserting a temporary text node under the caret ([#82977](https://github.com/WordPress/gutenberg/pull/82977)).
|
|
10
|
+
- `focusable.find`: Return linked image-map areas when their mapped image is visible and outside an inert subtree ([#82736](https://github.com/WordPress/gutenberg/pull/82736)).
|
|
11
|
+
|
|
5
12
|
## 4.55.0 (2026-09-10)
|
|
6
13
|
|
|
7
14
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -20,11 +20,11 @@ Get the rectangle for the selection in a container.
|
|
|
20
20
|
|
|
21
21
|
_Parameters_
|
|
22
22
|
|
|
23
|
-
-
|
|
23
|
+
- _win_ `Window`: The window of the selection.
|
|
24
24
|
|
|
25
25
|
_Returns_
|
|
26
26
|
|
|
27
|
-
-
|
|
27
|
+
- `DOMRect | null`: The rectangle.
|
|
28
28
|
|
|
29
29
|
### documentHasSelection
|
|
30
30
|
|
|
@@ -32,11 +32,11 @@ Check whether the current document has a selection. This includes focus in input
|
|
|
32
32
|
|
|
33
33
|
_Parameters_
|
|
34
34
|
|
|
35
|
-
-
|
|
35
|
+
- _doc_ `Document`: The document to check.
|
|
36
36
|
|
|
37
37
|
_Returns_
|
|
38
38
|
|
|
39
|
-
-
|
|
39
|
+
- `boolean`: True if there is selection, false if not.
|
|
40
40
|
|
|
41
41
|
### documentHasTextSelection
|
|
42
42
|
|
|
@@ -46,11 +46,11 @@ See: <https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Relat
|
|
|
46
46
|
|
|
47
47
|
_Parameters_
|
|
48
48
|
|
|
49
|
-
-
|
|
49
|
+
- _doc_ `Document`: The document to check.
|
|
50
50
|
|
|
51
51
|
_Returns_
|
|
52
52
|
|
|
53
|
-
-
|
|
53
|
+
- `boolean`: True if there is selection, false if not.
|
|
54
54
|
|
|
55
55
|
### documentHasUncollapsedSelection
|
|
56
56
|
|
|
@@ -58,11 +58,11 @@ Check whether the current document has any sort of (uncollapsed) selection. This
|
|
|
58
58
|
|
|
59
59
|
_Parameters_
|
|
60
60
|
|
|
61
|
-
-
|
|
61
|
+
- _doc_ `Document`: The document to check.
|
|
62
62
|
|
|
63
63
|
_Returns_
|
|
64
64
|
|
|
65
|
-
-
|
|
65
|
+
- `boolean`: Whether there is any recognizable text selection in the document.
|
|
66
66
|
|
|
67
67
|
### focus
|
|
68
68
|
|
|
@@ -74,11 +74,11 @@ Gets all files from a DataTransfer object.
|
|
|
74
74
|
|
|
75
75
|
_Parameters_
|
|
76
76
|
|
|
77
|
-
-
|
|
77
|
+
- _dataTransfer_ `DataTransfer`: DataTransfer object to inspect.
|
|
78
78
|
|
|
79
79
|
_Returns_
|
|
80
80
|
|
|
81
|
-
-
|
|
81
|
+
- `File[]`: An array containing all files.
|
|
82
82
|
|
|
83
83
|
### getOffsetParent
|
|
84
84
|
|
|
@@ -86,15 +86,15 @@ Returns the closest positioned element, or null under any of the conditions of t
|
|
|
86
86
|
|
|
87
87
|
_Related_
|
|
88
88
|
|
|
89
|
-
-
|
|
89
|
+
- <https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent>
|
|
90
90
|
|
|
91
91
|
_Parameters_
|
|
92
92
|
|
|
93
|
-
-
|
|
93
|
+
- _node_ `Node`: Node from which to find offset parent.
|
|
94
94
|
|
|
95
95
|
_Returns_
|
|
96
96
|
|
|
97
|
-
-
|
|
97
|
+
- `Node | null`: Offset parent.
|
|
98
98
|
|
|
99
99
|
### getPhrasingContentSchema
|
|
100
100
|
|
|
@@ -102,15 +102,15 @@ Get schema of possible paths for phrasing content.
|
|
|
102
102
|
|
|
103
103
|
_Related_
|
|
104
104
|
|
|
105
|
-
-
|
|
105
|
+
- <https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content>
|
|
106
106
|
|
|
107
107
|
_Parameters_
|
|
108
108
|
|
|
109
|
-
-
|
|
109
|
+
- _context_ `[string]`: Set to "paste" to exclude invisible elements and sensitive data.
|
|
110
110
|
|
|
111
111
|
_Returns_
|
|
112
112
|
|
|
113
|
-
-
|
|
113
|
+
- `Partial<ContentSchema>`: Schema.
|
|
114
114
|
|
|
115
115
|
### getRectangleFromRange
|
|
116
116
|
|
|
@@ -118,11 +118,11 @@ Get the rectangle of a given Range. Returns `null` if no suitable rectangle can
|
|
|
118
118
|
|
|
119
119
|
_Parameters_
|
|
120
120
|
|
|
121
|
-
-
|
|
121
|
+
- _range_ `Range`: The range.
|
|
122
122
|
|
|
123
123
|
_Returns_
|
|
124
124
|
|
|
125
|
-
-
|
|
125
|
+
- `DOMRect?`: The rectangle.
|
|
126
126
|
|
|
127
127
|
### getScrollContainer
|
|
128
128
|
|
|
@@ -130,12 +130,12 @@ Given a DOM node, finds the closest scrollable container node or the node itself
|
|
|
130
130
|
|
|
131
131
|
_Parameters_
|
|
132
132
|
|
|
133
|
-
-
|
|
134
|
-
-
|
|
133
|
+
- _node_ `Element | null`: Node from which to start.
|
|
134
|
+
- _direction_ `?string`: Direction of scrollable container to search for ('vertical', 'horizontal', 'all'). Defaults to 'vertical'.
|
|
135
135
|
|
|
136
136
|
_Returns_
|
|
137
137
|
|
|
138
|
-
-
|
|
138
|
+
- `Element | undefined`: Scrollable container node, if found.
|
|
139
139
|
|
|
140
140
|
### insertAfter
|
|
141
141
|
|
|
@@ -143,12 +143,12 @@ Given two DOM nodes, inserts the former in the DOM as the next sibling of the la
|
|
|
143
143
|
|
|
144
144
|
_Parameters_
|
|
145
145
|
|
|
146
|
-
-
|
|
147
|
-
-
|
|
146
|
+
- _newNode_ `Node`: Node to be inserted.
|
|
147
|
+
- _referenceNode_ `Node`: Node after which to perform the insertion.
|
|
148
148
|
|
|
149
149
|
_Returns_
|
|
150
150
|
|
|
151
|
-
-
|
|
151
|
+
- `void`:
|
|
152
152
|
|
|
153
153
|
### isEmpty
|
|
154
154
|
|
|
@@ -156,11 +156,11 @@ Recursively checks if an element is empty. An element is not empty if it contain
|
|
|
156
156
|
|
|
157
157
|
_Parameters_
|
|
158
158
|
|
|
159
|
-
-
|
|
159
|
+
- _element_ `Element`: The element to check.
|
|
160
160
|
|
|
161
161
|
_Returns_
|
|
162
162
|
|
|
163
|
-
-
|
|
163
|
+
- `boolean`: Whether or not the element is empty.
|
|
164
164
|
|
|
165
165
|
### isEntirelySelected
|
|
166
166
|
|
|
@@ -168,11 +168,11 @@ Check whether the contents of the element have been entirely selected. Returns t
|
|
|
168
168
|
|
|
169
169
|
_Parameters_
|
|
170
170
|
|
|
171
|
-
-
|
|
171
|
+
- _element_ `HTMLElement`: The element to check.
|
|
172
172
|
|
|
173
173
|
_Returns_
|
|
174
174
|
|
|
175
|
-
-
|
|
175
|
+
- `boolean`: True if entirely selected, false if not.
|
|
176
176
|
|
|
177
177
|
### isFormElement
|
|
178
178
|
|
|
@@ -180,11 +180,11 @@ Detects if element is a form element.
|
|
|
180
180
|
|
|
181
181
|
_Parameters_
|
|
182
182
|
|
|
183
|
-
-
|
|
183
|
+
- _element_ `Element`: The element to check.
|
|
184
184
|
|
|
185
185
|
_Returns_
|
|
186
186
|
|
|
187
|
-
-
|
|
187
|
+
- `boolean`: True if form element and false otherwise.
|
|
188
188
|
|
|
189
189
|
### isHorizontalEdge
|
|
190
190
|
|
|
@@ -192,12 +192,12 @@ Check whether the selection is horizontally at the edge of the container.
|
|
|
192
192
|
|
|
193
193
|
_Parameters_
|
|
194
194
|
|
|
195
|
-
-
|
|
196
|
-
-
|
|
195
|
+
- _container_ `HTMLElement`: Focusable element.
|
|
196
|
+
- _isReverse_ `boolean`: Set to true to check left, false for right.
|
|
197
197
|
|
|
198
198
|
_Returns_
|
|
199
199
|
|
|
200
|
-
-
|
|
200
|
+
- `boolean`: True if at the horizontal edge, false if not.
|
|
201
201
|
|
|
202
202
|
### isNumberInput
|
|
203
203
|
|
|
@@ -205,11 +205,11 @@ Check whether the given element is an input field of type number.
|
|
|
205
205
|
|
|
206
206
|
_Parameters_
|
|
207
207
|
|
|
208
|
-
-
|
|
208
|
+
- _node_ `Node`: The HTML node.
|
|
209
209
|
|
|
210
210
|
_Returns_
|
|
211
211
|
|
|
212
|
-
-
|
|
212
|
+
- `node is HTMLInputElement`: True if the node is number input.
|
|
213
213
|
|
|
214
214
|
### isPhrasingContent
|
|
215
215
|
|
|
@@ -217,15 +217,15 @@ Find out whether or not the given node is phrasing content.
|
|
|
217
217
|
|
|
218
218
|
_Related_
|
|
219
219
|
|
|
220
|
-
-
|
|
220
|
+
- <https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content>
|
|
221
221
|
|
|
222
222
|
_Parameters_
|
|
223
223
|
|
|
224
|
-
-
|
|
224
|
+
- _node_ `Node`: The node to test.
|
|
225
225
|
|
|
226
226
|
_Returns_
|
|
227
227
|
|
|
228
|
-
-
|
|
228
|
+
- `boolean`: True if phrasing content, false if not.
|
|
229
229
|
|
|
230
230
|
### isRTL
|
|
231
231
|
|
|
@@ -233,11 +233,11 @@ Whether the element's text direction is right-to-left.
|
|
|
233
233
|
|
|
234
234
|
_Parameters_
|
|
235
235
|
|
|
236
|
-
-
|
|
236
|
+
- _element_ `Element`: The element to check.
|
|
237
237
|
|
|
238
238
|
_Returns_
|
|
239
239
|
|
|
240
|
-
-
|
|
240
|
+
- `boolean`: True if rtl, false if ltr.
|
|
241
241
|
|
|
242
242
|
### isSelectionForward
|
|
243
243
|
|
|
@@ -245,25 +245,25 @@ Returns true if the given selection object is in the forward direction, or false
|
|
|
245
245
|
|
|
246
246
|
_Related_
|
|
247
247
|
|
|
248
|
-
-
|
|
248
|
+
- <https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition>
|
|
249
249
|
|
|
250
250
|
_Parameters_
|
|
251
251
|
|
|
252
|
-
-
|
|
252
|
+
- _selection_ `Selection`: Selection object to check.
|
|
253
253
|
|
|
254
254
|
_Returns_
|
|
255
255
|
|
|
256
|
-
-
|
|
256
|
+
- `boolean`: Whether the selection is forward.
|
|
257
257
|
|
|
258
258
|
### isTextContent
|
|
259
259
|
|
|
260
260
|
_Parameters_
|
|
261
261
|
|
|
262
|
-
-
|
|
262
|
+
- _node_ `Node`:
|
|
263
263
|
|
|
264
264
|
_Returns_
|
|
265
265
|
|
|
266
|
-
-
|
|
266
|
+
- `boolean`: Node is text content
|
|
267
267
|
|
|
268
268
|
### isTextField
|
|
269
269
|
|
|
@@ -273,11 +273,11 @@ See: <https://html.spec.whatwg.org/#textFieldSelection>
|
|
|
273
273
|
|
|
274
274
|
_Parameters_
|
|
275
275
|
|
|
276
|
-
-
|
|
276
|
+
- _node_ `Node`: The HTML element.
|
|
277
277
|
|
|
278
278
|
_Returns_
|
|
279
279
|
|
|
280
|
-
-
|
|
280
|
+
- `node is HTMLElement`: True if the element is an text field, false if not.
|
|
281
281
|
|
|
282
282
|
### isVerticalEdge
|
|
283
283
|
|
|
@@ -285,12 +285,12 @@ Check whether the selection is vertically at the edge of the container.
|
|
|
285
285
|
|
|
286
286
|
_Parameters_
|
|
287
287
|
|
|
288
|
-
-
|
|
289
|
-
-
|
|
288
|
+
- _container_ `HTMLElement`: Focusable element.
|
|
289
|
+
- _isReverse_ `boolean`: Set to true to check top, false for bottom.
|
|
290
290
|
|
|
291
291
|
_Returns_
|
|
292
292
|
|
|
293
|
-
-
|
|
293
|
+
- `boolean`: True if at the vertical edge, false if not.
|
|
294
294
|
|
|
295
295
|
### placeCaretAtHorizontalEdge
|
|
296
296
|
|
|
@@ -298,8 +298,8 @@ Places the caret at start or end of a given element.
|
|
|
298
298
|
|
|
299
299
|
_Parameters_
|
|
300
300
|
|
|
301
|
-
-
|
|
302
|
-
-
|
|
301
|
+
- _container_ `HTMLElement`: Focusable element.
|
|
302
|
+
- _isReverse_ `boolean`: True for end, false for start.
|
|
303
303
|
|
|
304
304
|
### placeCaretAtVerticalEdge
|
|
305
305
|
|
|
@@ -307,9 +307,9 @@ Places the caret at the top or bottom of a given element.
|
|
|
307
307
|
|
|
308
308
|
_Parameters_
|
|
309
309
|
|
|
310
|
-
-
|
|
311
|
-
-
|
|
312
|
-
-
|
|
310
|
+
- _container_ `HTMLElement`: Focusable element.
|
|
311
|
+
- _isReverse_ `boolean`: True for bottom, false for top.
|
|
312
|
+
- _rect_ `[DOMRect]`: The rectangle to position the caret with.
|
|
313
313
|
|
|
314
314
|
### remove
|
|
315
315
|
|
|
@@ -317,11 +317,11 @@ Given a DOM node, removes it from the DOM.
|
|
|
317
317
|
|
|
318
318
|
_Parameters_
|
|
319
319
|
|
|
320
|
-
-
|
|
320
|
+
- _node_ `Node`: Node to be removed.
|
|
321
321
|
|
|
322
322
|
_Returns_
|
|
323
323
|
|
|
324
|
-
-
|
|
324
|
+
- `void`:
|
|
325
325
|
|
|
326
326
|
### removeInvalidHTML
|
|
327
327
|
|
|
@@ -329,13 +329,13 @@ Given a schema, unwraps or removes nodes, attributes and classes on HTML.
|
|
|
329
329
|
|
|
330
330
|
_Parameters_
|
|
331
331
|
|
|
332
|
-
-
|
|
333
|
-
-
|
|
334
|
-
-
|
|
332
|
+
- _HTML_ `string`: The HTML to clean up.
|
|
333
|
+
- _schema_ `import('./clean-node-list').Schema`: Schema for the HTML.
|
|
334
|
+
- _inline_ `boolean`: Whether to clean for inline mode.
|
|
335
335
|
|
|
336
336
|
_Returns_
|
|
337
337
|
|
|
338
|
-
-
|
|
338
|
+
- `string`: The cleaned up HTML.
|
|
339
339
|
|
|
340
340
|
### replace
|
|
341
341
|
|
|
@@ -343,12 +343,12 @@ Given two DOM nodes, replaces the former with the latter in the DOM.
|
|
|
343
343
|
|
|
344
344
|
_Parameters_
|
|
345
345
|
|
|
346
|
-
-
|
|
347
|
-
-
|
|
346
|
+
- _processedNode_ `Element`: Node to be removed.
|
|
347
|
+
- _newNode_ `Element`: Node to be inserted in its place.
|
|
348
348
|
|
|
349
349
|
_Returns_
|
|
350
350
|
|
|
351
|
-
-
|
|
351
|
+
- `void`:
|
|
352
352
|
|
|
353
353
|
### replaceTag
|
|
354
354
|
|
|
@@ -356,12 +356,12 @@ Replaces the given node with a new node with the given tag name.
|
|
|
356
356
|
|
|
357
357
|
_Parameters_
|
|
358
358
|
|
|
359
|
-
-
|
|
360
|
-
-
|
|
359
|
+
- _node_ `Element`: The node to replace
|
|
360
|
+
- _tagName_ `string`: The new tag name.
|
|
361
361
|
|
|
362
362
|
_Returns_
|
|
363
363
|
|
|
364
|
-
-
|
|
364
|
+
- `Element`: The new node.
|
|
365
365
|
|
|
366
366
|
### safeHTML
|
|
367
367
|
|
|
@@ -369,11 +369,11 @@ Strips scripts and on\* attributes from HTML.
|
|
|
369
369
|
|
|
370
370
|
_Parameters_
|
|
371
371
|
|
|
372
|
-
-
|
|
372
|
+
- _html_ `string`: HTML to sanitize.
|
|
373
373
|
|
|
374
374
|
_Returns_
|
|
375
375
|
|
|
376
|
-
-
|
|
376
|
+
- `string`: The sanitized HTML.
|
|
377
377
|
|
|
378
378
|
### unwrap
|
|
379
379
|
|
|
@@ -381,11 +381,11 @@ Unwrap the given node. This means any child nodes are moved to the parent.
|
|
|
381
381
|
|
|
382
382
|
_Parameters_
|
|
383
383
|
|
|
384
|
-
-
|
|
384
|
+
- _node_ `Node`: The node to unwrap.
|
|
385
385
|
|
|
386
386
|
_Returns_
|
|
387
387
|
|
|
388
|
-
-
|
|
388
|
+
- `void`:
|
|
389
389
|
|
|
390
390
|
### wrap
|
|
391
391
|
|
|
@@ -393,8 +393,8 @@ Wraps the given node with a new node with the given tag name.
|
|
|
393
393
|
|
|
394
394
|
_Parameters_
|
|
395
395
|
|
|
396
|
-
-
|
|
397
|
-
-
|
|
396
|
+
- _newNode_ `Element`: The node to insert.
|
|
397
|
+
- _referenceNode_ `Element`: The node to wrap.
|
|
398
398
|
|
|
399
399
|
<!-- END TOKEN(Autogenerated API docs) -->
|
|
400
400
|
|
|
@@ -64,19 +64,54 @@ function getRectangleFromRange(range) {
|
|
|
64
64
|
furthestBottom - furthestTop
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
|
-
const { startContainer } = range;
|
|
67
|
+
const { startContainer, startOffset } = range;
|
|
68
68
|
const { ownerDocument } = startContainer;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
(0, import_assert_is_defined.assertIsDefined)(parentNode, "parentNode");
|
|
72
|
-
const index = (
|
|
73
|
-
/** @type {Node[]} */
|
|
74
|
-
Array.from(parentNode.childNodes).indexOf(startContainer)
|
|
75
|
-
);
|
|
76
|
-
(0, import_assert_is_defined.assertIsDefined)(ownerDocument, "ownerDocument");
|
|
69
|
+
(0, import_assert_is_defined.assertIsDefined)(ownerDocument, "ownerDocument");
|
|
70
|
+
if (startContainer.nodeType !== startContainer.TEXT_NODE && !startContainer.childNodes.length && startContainer.parentNode) {
|
|
77
71
|
range = ownerDocument.createRange();
|
|
78
|
-
range.
|
|
79
|
-
range.
|
|
72
|
+
range.setStartBefore(startContainer);
|
|
73
|
+
range.collapse(true);
|
|
74
|
+
return getRectangleFromRange(range);
|
|
75
|
+
}
|
|
76
|
+
if (startContainer.nodeType !== startContainer.TEXT_NODE) {
|
|
77
|
+
let before = startContainer.childNodes[startOffset - 1];
|
|
78
|
+
while (before?.lastChild) {
|
|
79
|
+
before = before.lastChild;
|
|
80
|
+
}
|
|
81
|
+
let after = startContainer.childNodes[startOffset];
|
|
82
|
+
while (after?.firstChild) {
|
|
83
|
+
after = after.firstChild;
|
|
84
|
+
}
|
|
85
|
+
let beforeRange;
|
|
86
|
+
if (before && before.nodeType === before.TEXT_NODE) {
|
|
87
|
+
beforeRange = ownerDocument.createRange();
|
|
88
|
+
beforeRange.setStart(
|
|
89
|
+
before,
|
|
90
|
+
/** @type {Text} */
|
|
91
|
+
before.length
|
|
92
|
+
);
|
|
93
|
+
beforeRange.collapse(true);
|
|
94
|
+
}
|
|
95
|
+
let afterRange;
|
|
96
|
+
if (after && after.nodeType === after.TEXT_NODE) {
|
|
97
|
+
afterRange = ownerDocument.createRange();
|
|
98
|
+
afterRange.setStart(after, 0);
|
|
99
|
+
afterRange.collapse(true);
|
|
100
|
+
}
|
|
101
|
+
if (beforeRange && afterRange) {
|
|
102
|
+
const beforeRect = beforeRange.getClientRects()[0];
|
|
103
|
+
const afterRect = afterRange.getClientRects()[0];
|
|
104
|
+
if (beforeRect && afterRect && beforeRect.bottom <= afterRect.top) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (afterRange) {
|
|
109
|
+
range = afterRange;
|
|
110
|
+
} else if (beforeRange) {
|
|
111
|
+
range = beforeRange;
|
|
112
|
+
} else {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
80
115
|
}
|
|
81
116
|
const rects = range.getClientRects();
|
|
82
117
|
if (rects.length > 1) {
|
|
@@ -97,16 +132,6 @@ function getRectangleFromRange(range) {
|
|
|
97
132
|
return null;
|
|
98
133
|
}
|
|
99
134
|
}
|
|
100
|
-
|
|
101
|
-
if (!rect || rect.height === 0) {
|
|
102
|
-
(0, import_assert_is_defined.assertIsDefined)(ownerDocument, "ownerDocument");
|
|
103
|
-
const padNode = ownerDocument.createTextNode("");
|
|
104
|
-
range = range.cloneRange();
|
|
105
|
-
range.insertNode(padNode);
|
|
106
|
-
rect = range.getClientRects()[0];
|
|
107
|
-
(0, import_assert_is_defined.assertIsDefined)(padNode.parentNode, "padNode.parentNode");
|
|
108
|
-
padNode.parentNode.removeChild(padNode);
|
|
109
|
-
}
|
|
110
|
-
return rect;
|
|
135
|
+
return rects[0] ?? null;
|
|
111
136
|
}
|
|
112
137
|
//# sourceMappingURL=get-rectangle-from-range.cjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/dom/get-rectangle-from-range.js"],
|
|
4
|
-
"sourcesContent": ["import { assertIsDefined } from '../utils/assert-is-defined';\n\n/**\n * Get the rectangle of a given Range. Returns `null` if no suitable rectangle\n * can be found. Use instead of `Range.getBoundingClientRect()`, which is often\n * broken, especially for collapsed ranges.\n *\n * @param {Range} range The range.\n *\n * @return {DOMRect?} The rectangle.\n */\nexport default function getRectangleFromRange( range ) {\n\t// For uncollapsed ranges, get the rectangle that bounds the contents of the\n\t// range; this a rectangle enclosing the union of the bounding rectangles\n\t// for all the elements in the range.\n\tif ( ! range.collapsed ) {\n\t\tconst rects = Array.from( range.getClientRects() );\n\n\t\t// If there's just a single rect, return it.\n\t\tif ( rects.length === 1 ) {\n\t\t\treturn rects[ 0 ];\n\t\t}\n\n\t\t// Ignore tiny selection at the edge of a range.\n\t\tconst filteredRects = rects.filter( ( { width } ) => width > 1 );\n\n\t\t// If it's full of tiny selections, return browser default.\n\t\tif ( filteredRects.length === 0 ) {\n\t\t\treturn range.getBoundingClientRect();\n\t\t}\n\n\t\tif ( filteredRects.length === 1 ) {\n\t\t\treturn filteredRects[ 0 ];\n\t\t}\n\n\t\tlet {\n\t\t\ttop: furthestTop,\n\t\t\tbottom: furthestBottom,\n\t\t\tleft: furthestLeft,\n\t\t\tright: furthestRight,\n\t\t} = filteredRects[ 0 ];\n\n\t\tfor ( const { top, bottom, left, right } of filteredRects ) {\n\t\t\tif ( top < furthestTop ) {\n\t\t\t\tfurthestTop = top;\n\t\t\t}\n\t\t\tif ( bottom > furthestBottom ) {\n\t\t\t\tfurthestBottom = bottom;\n\t\t\t}\n\t\t\tif ( left < furthestLeft ) {\n\t\t\t\tfurthestLeft = left;\n\t\t\t}\n\t\t\tif ( right > furthestRight ) {\n\t\t\t\tfurthestRight = right;\n\t\t\t}\n\t\t}\n\n\t\treturn new window.DOMRect(\n\t\t\tfurthestLeft,\n\t\t\tfurthestTop,\n\t\t\tfurthestRight - furthestLeft,\n\t\t\tfurthestBottom - furthestTop\n\t\t);\n\t}\n\n\tconst { startContainer } = range;\n\tconst { ownerDocument } = startContainer;\n\n\t//
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAgC;AAWjB,SAAR,sBAAwC,OAAQ;AAItD,MAAK,CAAE,MAAM,WAAY;AACxB,UAAMA,SAAQ,MAAM,KAAM,MAAM,eAAe,CAAE;AAGjD,QAAKA,OAAM,WAAW,GAAI;AACzB,aAAOA,OAAO,CAAE;AAAA,IACjB;AAGA,UAAM,gBAAgBA,OAAM,OAAQ,CAAE,EAAE,MAAM,MAAO,QAAQ,CAAE;AAG/D,QAAK,cAAc,WAAW,GAAI;AACjC,aAAO,MAAM,sBAAsB;AAAA,IACpC;AAEA,QAAK,cAAc,WAAW,GAAI;AACjC,aAAO,cAAe,CAAE;AAAA,IACzB;AAEA,QAAI;AAAA,MACH,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,IACR,IAAI,cAAe,CAAE;AAErB,eAAY,EAAE,KAAK,QAAQ,MAAM,MAAM,KAAK,eAAgB;AAC3D,UAAK,MAAM,aAAc;AACxB,sBAAc;AAAA,MACf;AACA,UAAK,SAAS,gBAAiB;AAC9B,yBAAiB;AAAA,MAClB;AACA,UAAK,OAAO,cAAe;AAC1B,uBAAe;AAAA,MAChB;AACA,UAAK,QAAQ,eAAgB;AAC5B,wBAAgB;AAAA,MACjB;AAAA,IACD;AAEA,WAAO,IAAI,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IAClB;AAAA,EACD;AAEA,QAAM,EAAE,
|
|
4
|
+
"sourcesContent": ["import { assertIsDefined } from '../utils/assert-is-defined';\n\n/**\n * Get the rectangle of a given Range. Returns `null` if no suitable rectangle\n * can be found. Use instead of `Range.getBoundingClientRect()`, which is often\n * broken, especially for collapsed ranges.\n *\n * @param {Range} range The range.\n *\n * @return {DOMRect?} The rectangle.\n */\nexport default function getRectangleFromRange( range ) {\n\t// For uncollapsed ranges, get the rectangle that bounds the contents of the\n\t// range; this a rectangle enclosing the union of the bounding rectangles\n\t// for all the elements in the range.\n\tif ( ! range.collapsed ) {\n\t\tconst rects = Array.from( range.getClientRects() );\n\n\t\t// If there's just a single rect, return it.\n\t\tif ( rects.length === 1 ) {\n\t\t\treturn rects[ 0 ];\n\t\t}\n\n\t\t// Ignore tiny selection at the edge of a range.\n\t\tconst filteredRects = rects.filter( ( { width } ) => width > 1 );\n\n\t\t// If it's full of tiny selections, return browser default.\n\t\tif ( filteredRects.length === 0 ) {\n\t\t\treturn range.getBoundingClientRect();\n\t\t}\n\n\t\tif ( filteredRects.length === 1 ) {\n\t\t\treturn filteredRects[ 0 ];\n\t\t}\n\n\t\tlet {\n\t\t\ttop: furthestTop,\n\t\t\tbottom: furthestBottom,\n\t\t\tleft: furthestLeft,\n\t\t\tright: furthestRight,\n\t\t} = filteredRects[ 0 ];\n\n\t\tfor ( const { top, bottom, left, right } of filteredRects ) {\n\t\t\tif ( top < furthestTop ) {\n\t\t\t\tfurthestTop = top;\n\t\t\t}\n\t\t\tif ( bottom > furthestBottom ) {\n\t\t\t\tfurthestBottom = bottom;\n\t\t\t}\n\t\t\tif ( left < furthestLeft ) {\n\t\t\t\tfurthestLeft = left;\n\t\t\t}\n\t\t\tif ( right > furthestRight ) {\n\t\t\t\tfurthestRight = right;\n\t\t\t}\n\t\t}\n\n\t\treturn new window.DOMRect(\n\t\t\tfurthestLeft,\n\t\t\tfurthestTop,\n\t\t\tfurthestRight - furthestLeft,\n\t\t\tfurthestBottom - furthestTop\n\t\t);\n\t}\n\n\tconst { startContainer, startOffset } = range;\n\tconst { ownerDocument } = startContainer;\n\tassertIsDefined( ownerDocument, 'ownerDocument' );\n\n\t// A range inside an element with no children, like a line break or the\n\t// placeholder, is the same spot as the position before that element.\n\tif (\n\t\tstartContainer.nodeType !== startContainer.TEXT_NODE &&\n\t\t! startContainer.childNodes.length &&\n\t\tstartContainer.parentNode\n\t) {\n\t\trange = ownerDocument.createRange();\n\t\trange.setStartBefore( startContainer );\n\t\trange.collapse( true );\n\t\treturn getRectangleFromRange( range );\n\t}\n\n\t// A collapsed range at an element offset has no rectangle. Translate it\n\t// to the text offset next to it: the end of the text before or the start\n\t// of the text after. When those sit on different lines the caret could\n\t// be on either, so return null.\n\tif ( startContainer.nodeType !== startContainer.TEXT_NODE ) {\n\t\tlet before = startContainer.childNodes[ startOffset - 1 ];\n\t\twhile ( before?.lastChild ) {\n\t\t\tbefore = before.lastChild;\n\t\t}\n\t\tlet after = startContainer.childNodes[ startOffset ];\n\t\twhile ( after?.firstChild ) {\n\t\t\tafter = after.firstChild;\n\t\t}\n\n\t\tlet beforeRange;\n\t\tif ( before && before.nodeType === before.TEXT_NODE ) {\n\t\t\tbeforeRange = ownerDocument.createRange();\n\t\t\tbeforeRange.setStart(\n\t\t\t\tbefore,\n\t\t\t\t/** @type {Text} */ ( before ).length\n\t\t\t);\n\t\t\tbeforeRange.collapse( true );\n\t\t}\n\t\tlet afterRange;\n\t\tif ( after && after.nodeType === after.TEXT_NODE ) {\n\t\t\tafterRange = ownerDocument.createRange();\n\t\t\tafterRange.setStart( after, 0 );\n\t\t\tafterRange.collapse( true );\n\t\t}\n\n\t\tif ( beforeRange && afterRange ) {\n\t\t\tconst beforeRect = beforeRange.getClientRects()[ 0 ];\n\t\t\tconst afterRect = afterRange.getClientRects()[ 0 ];\n\t\t\tif (\n\t\t\t\tbeforeRect &&\n\t\t\t\tafterRect &&\n\t\t\t\tbeforeRect.bottom <= afterRect.top\n\t\t\t) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif ( afterRange ) {\n\t\t\trange = afterRange;\n\t\t} else if ( beforeRange ) {\n\t\t\trange = beforeRange;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tconst rects = range.getClientRects();\n\n\t// If we have multiple rectangles for a collapsed range, there's no way to\n\t// know which it is, so don't return anything.\n\tif ( rects.length > 1 ) {\n\t\treturn null;\n\t}\n\n\t// A collapsed range at a soft line wrap is equally ambiguous: the same\n\t// position ends one line and starts the next. Some browsers (Gecko)\n\t// return a single rectangle for it, on the upper line, regardless of\n\t// where the caret is. Detect the boundary by measuring the characters\n\t// around the position: when they sit on different lines, there is no\n\t// way to know which line the caret is on, so don't return anything.\n\tif (\n\t\trects.length === 1 &&\n\t\tstartContainer.nodeType === startContainer.TEXT_NODE &&\n\t\trange.startOffset > 0 &&\n\t\trange.startOffset < /** @type {Text} */ ( startContainer ).length\n\t) {\n\t\tassertIsDefined( ownerDocument, 'ownerDocument' );\n\t\tconst measure = (\n\t\t\t/** @type {number} */ start,\n\t\t\t/** @type {number} */ end\n\t\t) => {\n\t\t\tconst charRange = ownerDocument.createRange();\n\t\t\tcharRange.setStart( startContainer, start );\n\t\t\tcharRange.setEnd( startContainer, end );\n\t\t\treturn charRange.getBoundingClientRect();\n\t\t};\n\t\tconst before = measure( range.startOffset - 1, range.startOffset );\n\t\tconst after = measure( range.startOffset, range.startOffset + 1 );\n\n\t\tif ( before.bottom <= after.top ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn rects[ 0 ] ?? null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["rects"]
|
|
7
7
|
}
|
package/build/focusable.cjs
CHANGED
|
@@ -62,17 +62,11 @@ function isValidFocusableArea(element) {
|
|
|
62
62
|
const img = element.ownerDocument.querySelector(
|
|
63
63
|
'img[usemap="#' + map.name + '"]'
|
|
64
64
|
);
|
|
65
|
-
return !!img && isVisible(img);
|
|
65
|
+
return !!img && !img.closest("[inert]") && isVisible(img);
|
|
66
66
|
}
|
|
67
67
|
function find(context, { sequential = false } = {}) {
|
|
68
68
|
const elements = context.querySelectorAll(buildSelector(sequential));
|
|
69
69
|
return Array.from(elements).filter((element) => {
|
|
70
|
-
if (!isVisible(element)) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
if (element.closest("[inert]")) {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
70
|
const { nodeName } = element;
|
|
77
71
|
if ("AREA" === nodeName) {
|
|
78
72
|
return isValidFocusableArea(
|
|
@@ -80,7 +74,10 @@ function find(context, { sequential = false } = {}) {
|
|
|
80
74
|
element
|
|
81
75
|
);
|
|
82
76
|
}
|
|
83
|
-
|
|
77
|
+
if (element.closest("[inert]")) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return isVisible(element);
|
|
84
81
|
});
|
|
85
82
|
}
|
|
86
83
|
// Annotate the CommonJS export names for ESM import in node:
|
package/build/focusable.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/focusable.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * References:\n *\n * Focusable:\n * - https://www.w3.org/TR/html5/editing.html#focus-management\n *\n * Sequential focus navigation:\n * - https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute\n *\n * Disabled elements:\n * - https://www.w3.org/TR/html5/disabled-elements.html#disabled-elements\n *\n * getClientRects algorithm (requiring layout box):\n * - https://www.w3.org/TR/cssom-view-1/#extension-to-the-element-interface\n *\n * AREA elements associated with an IMG:\n * - https://w3c.github.io/html/editing.html#data-model\n */\n\n/**\n * Returns a CSS selector used to query for focusable elements.\n *\n * @param {boolean} sequential If set, only query elements that are sequentially\n * focusable. Non-interactive elements with a\n * negative `tabindex` are focusable but not\n * sequentially focusable.\n * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute\n *\n * @return {string} CSS selector.\n */\nfunction buildSelector( sequential ) {\n\treturn [\n\t\tsequential ? '[tabindex]:not([tabindex^=\"-\"])' : '[tabindex]',\n\t\t'a[href]',\n\t\t'button:not([disabled])',\n\t\t'input:not([type=\"hidden\"]):not([disabled])',\n\t\t'select:not([disabled])',\n\t\t'textarea:not([disabled])',\n\t\t'iframe:not([tabindex^=\"-\"])',\n\t\t'object',\n\t\t'embed',\n\t\t'summary',\n\t\t'area[href]',\n\t\t'[contenteditable]:not([contenteditable=false])',\n\t].join( ',' );\n}\n\n/**\n * Returns true if the specified element has a layout box and is not hidden by\n * CSS visibility or content visibility.\n *\n * @param {HTMLElement} element DOM element to test.\n *\n * @return {boolean} Whether element is visible.\n */\nfunction isVisible( element ) {\n\tif ( typeof element.checkVisibility === 'function' ) {\n\t\tif ( ! element.checkVisibility( { visibilityProperty: true } ) ) {\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\tconst visibility =\n\t\t\telement.ownerDocument.defaultView?.getComputedStyle(\n\t\t\t\telement\n\t\t\t).visibility;\n\t\tif ( visibility === 'hidden' || visibility === 'collapse' ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn (\n\t\telement.offsetWidth > 0 ||\n\t\telement.offsetHeight > 0 ||\n\t\telement.getClientRects().length > 0\n\t);\n}\n\n/**\n * Returns true if the specified area element is a valid focusable element, or\n * false otherwise. Area is only focusable if within a map where a named map\n * referenced by an image somewhere in the document.\n *\n * @param {HTMLAreaElement} element DOM area element to test.\n *\n * @return {boolean} Whether area element is valid for focus.\n */\nfunction isValidFocusableArea( element ) {\n\t/** @type {HTMLMapElement | null} */\n\tconst map = element.closest( 'map[name]' );\n\tif ( ! map ) {\n\t\treturn false;\n\t}\n\n\t/** @type {HTMLImageElement | null} */\n\tconst img = element.ownerDocument.querySelector(\n\t\t'img[usemap=\"#' + map.name + '\"]'\n\t);\n\treturn !! img && isVisible( img );\n}\n\n/**\n * Returns all focusable elements within a given context.\n *\n * @param {Element} context Element in which to search.\n * @param {Object} options\n * @param {boolean} [options.sequential] If set, only return elements that are\n * sequentially focusable.\n * Non-interactive elements with a\n * negative `tabindex` are focusable but\n * not sequentially focusable.\n * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute\n *\n * @return {HTMLElement[]} Focusable elements.\n */\nexport function find( context, { sequential = false } = {} ) {\n\t/** @type {NodeListOf<HTMLElement>} */\n\tconst elements = context.querySelectorAll( buildSelector( sequential ) );\n\n\treturn Array.from( elements ).filter( ( element ) => {\n\t\tif (
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BA,SAAS,cAAe,YAAa;AACpC,SAAO;AAAA,IACN,aAAa,oCAAoC;AAAA,IACjD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,EAAE,KAAM,GAAI;AACb;AAUA,SAAS,UAAW,SAAU;AAC7B,MAAK,OAAO,QAAQ,oBAAoB,YAAa;AACpD,QAAK,CAAE,QAAQ,gBAAiB,EAAE,oBAAoB,KAAK,CAAE,GAAI;AAChE,aAAO;AAAA,IACR;AAAA,EACD,OAAO;AACN,UAAM,aACL,QAAQ,cAAc,aAAa;AAAA,MAClC;AAAA,IACD,EAAE;AACH,QAAK,eAAe,YAAY,eAAe,YAAa;AAC3D,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SACC,QAAQ,cAAc,KACtB,QAAQ,eAAe,KACvB,QAAQ,eAAe,EAAE,SAAS;AAEpC;AAWA,SAAS,qBAAsB,SAAU;AAExC,QAAM,MAAM,QAAQ,QAAS,WAAY;AACzC,MAAK,CAAE,KAAM;AACZ,WAAO;AAAA,EACR;AAGA,QAAM,MAAM,QAAQ,cAAc;AAAA,IACjC,kBAAkB,IAAI,OAAO;AAAA,EAC9B;AACA,SAAO,CAAC,CAAE,OAAO,UAAW,GAAI;
|
|
4
|
+
"sourcesContent": ["/**\n * References:\n *\n * Focusable:\n * - https://www.w3.org/TR/html5/editing.html#focus-management\n *\n * Sequential focus navigation:\n * - https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute\n *\n * Disabled elements:\n * - https://www.w3.org/TR/html5/disabled-elements.html#disabled-elements\n *\n * getClientRects algorithm (requiring layout box):\n * - https://www.w3.org/TR/cssom-view-1/#extension-to-the-element-interface\n *\n * AREA elements associated with an IMG:\n * - https://w3c.github.io/html/editing.html#data-model\n */\n\n/**\n * Returns a CSS selector used to query for focusable elements.\n *\n * @param {boolean} sequential If set, only query elements that are sequentially\n * focusable. Non-interactive elements with a\n * negative `tabindex` are focusable but not\n * sequentially focusable.\n * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute\n *\n * @return {string} CSS selector.\n */\nfunction buildSelector( sequential ) {\n\treturn [\n\t\tsequential ? '[tabindex]:not([tabindex^=\"-\"])' : '[tabindex]',\n\t\t'a[href]',\n\t\t'button:not([disabled])',\n\t\t'input:not([type=\"hidden\"]):not([disabled])',\n\t\t'select:not([disabled])',\n\t\t'textarea:not([disabled])',\n\t\t'iframe:not([tabindex^=\"-\"])',\n\t\t'object',\n\t\t'embed',\n\t\t'summary',\n\t\t'area[href]',\n\t\t'[contenteditable]:not([contenteditable=false])',\n\t].join( ',' );\n}\n\n/**\n * Returns true if the specified element has a layout box and is not hidden by\n * CSS visibility or content visibility.\n *\n * @param {HTMLElement} element DOM element to test.\n *\n * @return {boolean} Whether element is visible.\n */\nfunction isVisible( element ) {\n\tif ( typeof element.checkVisibility === 'function' ) {\n\t\tif ( ! element.checkVisibility( { visibilityProperty: true } ) ) {\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\tconst visibility =\n\t\t\telement.ownerDocument.defaultView?.getComputedStyle(\n\t\t\t\telement\n\t\t\t).visibility;\n\t\tif ( visibility === 'hidden' || visibility === 'collapse' ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn (\n\t\telement.offsetWidth > 0 ||\n\t\telement.offsetHeight > 0 ||\n\t\telement.getClientRects().length > 0\n\t);\n}\n\n/**\n * Returns true if the specified area element is a valid focusable element, or\n * false otherwise. Area is only focusable if within a map where a named map\n * referenced by an image somewhere in the document.\n *\n * @param {HTMLAreaElement} element DOM area element to test.\n *\n * @return {boolean} Whether area element is valid for focus.\n */\nfunction isValidFocusableArea( element ) {\n\t/** @type {HTMLMapElement | null} */\n\tconst map = element.closest( 'map[name]' );\n\tif ( ! map ) {\n\t\treturn false;\n\t}\n\n\t/** @type {HTMLImageElement | null} */\n\tconst img = element.ownerDocument.querySelector(\n\t\t'img[usemap=\"#' + map.name + '\"]'\n\t);\n\treturn !! img && ! img.closest( '[inert]' ) && isVisible( img );\n}\n\n/**\n * Returns all focusable elements within a given context.\n *\n * @param {Element} context Element in which to search.\n * @param {Object} options\n * @param {boolean} [options.sequential] If set, only return elements that are\n * sequentially focusable.\n * Non-interactive elements with a\n * negative `tabindex` are focusable but\n * not sequentially focusable.\n * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute\n *\n * @return {HTMLElement[]} Focusable elements.\n */\nexport function find( context, { sequential = false } = {} ) {\n\t/** @type {NodeListOf<HTMLElement>} */\n\tconst elements = context.querySelectorAll( buildSelector( sequential ) );\n\n\treturn Array.from( elements ).filter( ( element ) => {\n\t\tconst { nodeName } = element;\n\t\tif ( 'AREA' === nodeName ) {\n\t\t\t// The mapped image determines whether this region is visible or inert.\n\t\t\treturn isValidFocusableArea(\n\t\t\t\t/** @type {HTMLAreaElement} */ ( element )\n\t\t\t);\n\t\t}\n\n\t\t// Elements inside an inert subtree are not focusable.\n\t\tif ( element.closest( '[inert]' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn isVisible( element );\n\t} );\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BA,SAAS,cAAe,YAAa;AACpC,SAAO;AAAA,IACN,aAAa,oCAAoC;AAAA,IACjD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,EAAE,KAAM,GAAI;AACb;AAUA,SAAS,UAAW,SAAU;AAC7B,MAAK,OAAO,QAAQ,oBAAoB,YAAa;AACpD,QAAK,CAAE,QAAQ,gBAAiB,EAAE,oBAAoB,KAAK,CAAE,GAAI;AAChE,aAAO;AAAA,IACR;AAAA,EACD,OAAO;AACN,UAAM,aACL,QAAQ,cAAc,aAAa;AAAA,MAClC;AAAA,IACD,EAAE;AACH,QAAK,eAAe,YAAY,eAAe,YAAa;AAC3D,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SACC,QAAQ,cAAc,KACtB,QAAQ,eAAe,KACvB,QAAQ,eAAe,EAAE,SAAS;AAEpC;AAWA,SAAS,qBAAsB,SAAU;AAExC,QAAM,MAAM,QAAQ,QAAS,WAAY;AACzC,MAAK,CAAE,KAAM;AACZ,WAAO;AAAA,EACR;AAGA,QAAM,MAAM,QAAQ,cAAc;AAAA,IACjC,kBAAkB,IAAI,OAAO;AAAA,EAC9B;AACA,SAAO,CAAC,CAAE,OAAO,CAAE,IAAI,QAAS,SAAU,KAAK,UAAW,GAAI;AAC/D;AAgBO,SAAS,KAAM,SAAS,EAAE,aAAa,MAAM,IAAI,CAAC,GAAI;AAE5D,QAAM,WAAW,QAAQ,iBAAkB,cAAe,UAAW,CAAE;AAEvE,SAAO,MAAM,KAAM,QAAS,EAAE,OAAQ,CAAE,YAAa;AACpD,UAAM,EAAE,SAAS,IAAI;AACrB,QAAK,WAAW,UAAW;AAE1B,aAAO;AAAA;AAAA,QAC2B;AAAA,MAClC;AAAA,IACD;AAGA,QAAK,QAAQ,QAAS,SAAU,GAAI;AACnC,aAAO;AAAA,IACR;AAEA,WAAO,UAAW,OAAQ;AAAA,EAC3B,CAAE;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|