@primer/behaviors 1.3.1-rc.8de3bf8 → 1.3.2-rc.b275ab5
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 +9 -0
- package/dist/cjs/focus-zone.js +22 -2
- package/dist/esm/focus-zone.js +22 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @primer/behaviors
|
|
2
2
|
|
|
3
|
+
## 1.3.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#176](https://github.com/primer/behaviors/pull/176) [`5e74867`](https://github.com/primer/behaviors/commit/5e7486702074bbb89e6a7a96a4b0db71d763c74c) Thanks [@jbrown1618](https://github.com/jbrown1618)! - Use a binary search to find the insertion index for new elements managed by the focus zone.
|
|
8
|
+
For a use case with 1000 elements managed by the focus zone, added one at a time (by react),
|
|
9
|
+
this takes us from 500,000 calls to `compareDocumentPosition` over 1000ms to 8,000 calls
|
|
10
|
+
over 16ms.
|
|
11
|
+
|
|
3
12
|
## 1.3.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/cjs/focus-zone.js
CHANGED
|
@@ -190,8 +190,7 @@ function focusZone(container, settings) {
|
|
|
190
190
|
if (filteredElements.length === 0) {
|
|
191
191
|
return;
|
|
192
192
|
}
|
|
193
|
-
|
|
194
|
-
focusableElements.splice(insertIndex === -1 ? focusableElements.length : insertIndex, 0, ...filteredElements);
|
|
193
|
+
focusableElements.splice(findInsertionIndex(filteredElements), 0, ...filteredElements);
|
|
195
194
|
for (const element of filteredElements) {
|
|
196
195
|
if (!savedTabIndex.has(element)) {
|
|
197
196
|
savedTabIndex.set(element, element.getAttribute('tabindex'));
|
|
@@ -202,6 +201,27 @@ function focusZone(container, settings) {
|
|
|
202
201
|
updateFocusedElement(getFirstFocusableElement());
|
|
203
202
|
}
|
|
204
203
|
}
|
|
204
|
+
function findInsertionIndex(elementsToInsert) {
|
|
205
|
+
const firstElementToInsert = elementsToInsert[0];
|
|
206
|
+
if (focusableElements.length === 0)
|
|
207
|
+
return 0;
|
|
208
|
+
let iMin = 0;
|
|
209
|
+
let iMax = focusableElements.length - 1;
|
|
210
|
+
while (iMin <= iMax) {
|
|
211
|
+
const i = Math.floor((iMin + iMax) / 2);
|
|
212
|
+
const element = focusableElements[i];
|
|
213
|
+
if (followsInDocument(firstElementToInsert, element)) {
|
|
214
|
+
iMax = i - 1;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
iMin = i + 1;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return iMin;
|
|
221
|
+
}
|
|
222
|
+
function followsInDocument(first, second) {
|
|
223
|
+
return (second.compareDocumentPosition(first) & Node.DOCUMENT_POSITION_PRECEDING) > 0;
|
|
224
|
+
}
|
|
205
225
|
function endFocusManagement(...elements) {
|
|
206
226
|
for (const element of elements) {
|
|
207
227
|
const focusableElementIndex = focusableElements.indexOf(element);
|
package/dist/esm/focus-zone.js
CHANGED
|
@@ -187,8 +187,7 @@ export function focusZone(container, settings) {
|
|
|
187
187
|
if (filteredElements.length === 0) {
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
focusableElements.splice(insertIndex === -1 ? focusableElements.length : insertIndex, 0, ...filteredElements);
|
|
190
|
+
focusableElements.splice(findInsertionIndex(filteredElements), 0, ...filteredElements);
|
|
192
191
|
for (const element of filteredElements) {
|
|
193
192
|
if (!savedTabIndex.has(element)) {
|
|
194
193
|
savedTabIndex.set(element, element.getAttribute('tabindex'));
|
|
@@ -199,6 +198,27 @@ export function focusZone(container, settings) {
|
|
|
199
198
|
updateFocusedElement(getFirstFocusableElement());
|
|
200
199
|
}
|
|
201
200
|
}
|
|
201
|
+
function findInsertionIndex(elementsToInsert) {
|
|
202
|
+
const firstElementToInsert = elementsToInsert[0];
|
|
203
|
+
if (focusableElements.length === 0)
|
|
204
|
+
return 0;
|
|
205
|
+
let iMin = 0;
|
|
206
|
+
let iMax = focusableElements.length - 1;
|
|
207
|
+
while (iMin <= iMax) {
|
|
208
|
+
const i = Math.floor((iMin + iMax) / 2);
|
|
209
|
+
const element = focusableElements[i];
|
|
210
|
+
if (followsInDocument(firstElementToInsert, element)) {
|
|
211
|
+
iMax = i - 1;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
iMin = i + 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return iMin;
|
|
218
|
+
}
|
|
219
|
+
function followsInDocument(first, second) {
|
|
220
|
+
return (second.compareDocumentPosition(first) & Node.DOCUMENT_POSITION_PRECEDING) > 0;
|
|
221
|
+
}
|
|
202
222
|
function endFocusManagement(...elements) {
|
|
203
223
|
for (const element of elements) {
|
|
204
224
|
const focusableElementIndex = focusableElements.indexOf(element);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/behaviors",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2-rc.b275ab5",
|
|
4
4
|
"description": "Shared behaviors for JavaScript components",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@testing-library/user-event": "^13.5.0",
|
|
75
75
|
"@types/jest": "^27.0.3",
|
|
76
76
|
"@types/react": "^17.0.37",
|
|
77
|
-
"esbuild": "^0.
|
|
77
|
+
"esbuild": "^0.15.16",
|
|
78
78
|
"esbuild-jest": "^0.5.0",
|
|
79
79
|
"eslint": "^8.3.0",
|
|
80
80
|
"eslint-plugin-github": "^4.3.5",
|