@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 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
@@ -190,8 +190,7 @@ function focusZone(container, settings) {
190
190
  if (filteredElements.length === 0) {
191
191
  return;
192
192
  }
193
- const insertIndex = focusableElements.findIndex(e => (e.compareDocumentPosition(filteredElements[0]) & Node.DOCUMENT_POSITION_PRECEDING) > 0);
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);
@@ -187,8 +187,7 @@ export function focusZone(container, settings) {
187
187
  if (filteredElements.length === 0) {
188
188
  return;
189
189
  }
190
- const insertIndex = focusableElements.findIndex(e => (e.compareDocumentPosition(filteredElements[0]) & Node.DOCUMENT_POSITION_PRECEDING) > 0);
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.1-rc.8de3bf8",
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.14.1",
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",