@primer/behaviors 0.0.0-20220188453 → 0.0.0-2022019163715

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.
Files changed (78) hide show
  1. package/dist/cjs/anchored-position.d.ts +15 -0
  2. package/dist/cjs/anchored-position.js +210 -0
  3. package/dist/cjs/focus-trap.d.ts +2 -0
  4. package/dist/cjs/focus-trap.js +111 -0
  5. package/dist/cjs/focus-zone.d.ts +32 -0
  6. package/dist/cjs/focus-zone.js +410 -0
  7. package/{lib-esm → dist/cjs}/index.d.ts +0 -0
  8. package/dist/cjs/index.js +16 -0
  9. package/{lib-esm → dist/cjs}/polyfills/event-listener-signal.d.ts +0 -0
  10. package/dist/cjs/polyfills/event-listener-signal.js +44 -0
  11. package/{lib-esm → dist/cjs}/scroll-into-view.d.ts +0 -0
  12. package/dist/cjs/scroll-into-view.js +21 -0
  13. package/{lib-esm → dist/cjs}/utils/index.d.ts +0 -0
  14. package/dist/cjs/utils/index.js +15 -0
  15. package/dist/cjs/utils/iterate-focusable-elements.d.ts +8 -0
  16. package/dist/cjs/utils/iterate-focusable-elements.js +63 -0
  17. package/{lib-esm → dist/cjs}/utils/unique-id.d.ts +0 -0
  18. package/dist/cjs/utils/unique-id.js +8 -0
  19. package/{lib-esm → dist/cjs}/utils/user-agent.d.ts +0 -0
  20. package/dist/cjs/utils/user-agent.js +11 -0
  21. package/dist/esm/anchored-position.d.ts +15 -0
  22. package/dist/esm/anchored-position.js +206 -0
  23. package/dist/esm/focus-trap.d.ts +2 -0
  24. package/dist/esm/focus-trap.js +107 -0
  25. package/dist/esm/focus-zone.d.ts +32 -0
  26. package/dist/esm/focus-zone.js +406 -0
  27. package/{lib → dist/esm}/index.d.ts +0 -0
  28. package/{lib-esm → dist/esm}/index.js +1 -1
  29. package/{lib → dist/esm}/polyfills/event-listener-signal.d.ts +0 -0
  30. package/dist/esm/polyfills/event-listener-signal.js +40 -0
  31. package/{lib → dist/esm}/scroll-into-view.d.ts +0 -0
  32. package/dist/esm/scroll-into-view.js +17 -0
  33. package/{lib → dist/esm}/utils/index.d.ts +0 -0
  34. package/{lib-esm → dist/esm}/utils/index.js +1 -1
  35. package/dist/esm/utils/iterate-focusable-elements.d.ts +8 -0
  36. package/dist/esm/utils/iterate-focusable-elements.js +57 -0
  37. package/{lib → dist/esm}/utils/unique-id.d.ts +0 -0
  38. package/dist/esm/utils/unique-id.js +4 -0
  39. package/{lib → dist/esm}/utils/user-agent.d.ts +0 -0
  40. package/dist/esm/utils/user-agent.js +7 -0
  41. package/package.json +18 -35
  42. package/utils/package.json +7 -0
  43. package/lib/__tests__/anchored-position.test.js +0 -388
  44. package/lib/__tests__/focus-trap.test.js +0 -234
  45. package/lib/__tests__/focus-zone.test.js +0 -570
  46. package/lib/__tests__/iterate-focusable-elements.test.js +0 -55
  47. package/lib/__tests__/scroll-into-view.test.js +0 -245
  48. package/lib/anchored-position.d.ts +0 -89
  49. package/lib/anchored-position.js +0 -316
  50. package/lib/focus-trap.d.ts +0 -12
  51. package/lib/focus-trap.js +0 -179
  52. package/lib/focus-zone.d.ts +0 -137
  53. package/lib/focus-zone.js +0 -578
  54. package/lib/index.js +0 -57
  55. package/lib/polyfills/event-listener-signal.js +0 -64
  56. package/lib/scroll-into-view.js +0 -42
  57. package/lib/utils/index.js +0 -44
  58. package/lib/utils/iterate-focusable-elements.d.ts +0 -42
  59. package/lib/utils/iterate-focusable-elements.js +0 -113
  60. package/lib/utils/unique-id.js +0 -12
  61. package/lib/utils/user-agent.js +0 -15
  62. package/lib-esm/__tests__/anchored-position.test.js +0 -386
  63. package/lib-esm/__tests__/focus-trap.test.js +0 -227
  64. package/lib-esm/__tests__/focus-zone.test.js +0 -487
  65. package/lib-esm/__tests__/iterate-focusable-elements.test.js +0 -48
  66. package/lib-esm/__tests__/scroll-into-view.test.js +0 -243
  67. package/lib-esm/anchored-position.d.ts +0 -89
  68. package/lib-esm/anchored-position.js +0 -309
  69. package/lib-esm/focus-trap.d.ts +0 -12
  70. package/lib-esm/focus-trap.js +0 -170
  71. package/lib-esm/focus-zone.d.ts +0 -137
  72. package/lib-esm/focus-zone.js +0 -559
  73. package/lib-esm/polyfills/event-listener-signal.js +0 -57
  74. package/lib-esm/scroll-into-view.js +0 -35
  75. package/lib-esm/utils/iterate-focusable-elements.d.ts +0 -42
  76. package/lib-esm/utils/iterate-focusable-elements.js +0 -102
  77. package/lib-esm/utils/unique-id.js +0 -5
  78. package/lib-esm/utils/user-agent.js +0 -8
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@primer/behaviors/utils",
3
+ "types": "../dist/esm/utils/index.d.ts",
4
+ "main": "../dist/esm/utils/index.js",
5
+ "type": "module",
6
+ "sideEffects": false
7
+ }
@@ -1,388 +0,0 @@
1
- "use strict";
2
-
3
- var _anchoredPosition = require("../anchored-position.js");
4
-
5
- /*
6
-
7
- Note: In each test below, we check the calculation from getAnchoredPosition against exact
8
- values. For each `expect` call, there is an accompanying comment that distills the effective
9
- calculation from the inputs, which may help debugging in the event of a test failure.
10
-
11
- */
12
- // The DOMRect constructor isn't available in JSDOM, so we improvise here.
13
- function makeDOMRect(x, y, width, height) {
14
- return {
15
- x,
16
- y,
17
- width,
18
- height,
19
- top: y,
20
- left: x,
21
- right: x + width,
22
- bottom: y + height,
23
-
24
- toJSON() {
25
- return this;
26
- }
27
-
28
- };
29
- } // Since Jest/JSDOM doesn't support layout, we can stub out getBoundingClientRect if we know the
30
- // correct dimensions. JSDOM will handle the rest of the DOM API used by getAnchoredPosition.
31
-
32
-
33
- function createVirtualDOM(parentRect, anchorRect, floatingRect, parentBorders = {
34
- top: 0,
35
- right: 0,
36
- bottom: 0,
37
- left: 0
38
- }) {
39
- const parent = document.createElement('div');
40
- parent.style.overflow = 'hidden';
41
- parent.style.position = 'relative';
42
- parent.style.borderTopWidth = `${parentBorders.top}px`;
43
- parent.style.borderRightWidth = `${parentBorders.right}px`;
44
- parent.style.borderBottomWidth = `${parentBorders.bottom}px`;
45
- parent.style.borderLeftWidth = `${parentBorders.left}px`;
46
- parent.id = 'parent';
47
- parent.innerHTML = '<div id="float"></div><div id="anchor"></div>';
48
- const float = parent.querySelector('#float');
49
- const anchor = parent.querySelector('#anchor');
50
-
51
- anchor.getBoundingClientRect = () => anchorRect;
52
-
53
- parent.getBoundingClientRect = () => parentRect;
54
-
55
- float.getBoundingClientRect = () => floatingRect;
56
-
57
- return {
58
- float,
59
- parent,
60
- anchor
61
- };
62
- }
63
-
64
- describe('getAnchoredPosition', () => {
65
- it('returns the correct position in the default case with no overflow', () => {
66
- const anchorRect = makeDOMRect(300, 200, 50, 50);
67
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
68
- document.body.innerHTML = '<div id="float"></div><div id="anchor"></div>';
69
- const float = document.querySelector('#float');
70
- const anchor = document.querySelector('#anchor');
71
-
72
- float.getBoundingClientRect = () => floatingRect;
73
-
74
- anchor.getBoundingClientRect = () => anchorRect;
75
-
76
- document.body.getBoundingClientRect = () => makeDOMRect(0, 0, 1920, 0);
77
-
78
- Object.defineProperty(window, 'innerHeight', {
79
- get: () => 1080
80
- });
81
- const settings = {
82
- anchorOffset: 4
83
- };
84
- const {
85
- top,
86
- left
87
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
88
- expect(top).toEqual(254);
89
- expect(left).toEqual(300);
90
- });
91
- it('returns the correct position in the default case with no overflow, inside a clipping parent', () => {
92
- const parentRect = makeDOMRect(20, 20, 500, 500);
93
- const anchorRect = makeDOMRect(300, 200, 50, 50);
94
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
95
- const {
96
- float,
97
- anchor
98
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
99
- const settings = {
100
- anchorOffset: 4
101
- };
102
- const {
103
- top,
104
- left
105
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
106
- expect(top).toEqual(234);
107
- expect(left).toEqual(280);
108
- });
109
- it('returns the correct position for different outside side settings with no overflow', () => {
110
- const parentRect = makeDOMRect(20, 20, 500, 500);
111
- const anchorRect = makeDOMRect(300, 200, 50, 50);
112
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
113
- const {
114
- float,
115
- anchor
116
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
117
- const settings = {};
118
- let top = 0;
119
- let left = 0; // should be the same calculation as the default settings test above
120
-
121
- settings.side = 'outside-bottom';
122
- ({
123
- top,
124
- left
125
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
126
- expect(top).toEqual(234); // anchorRect.top + anchorRect.height + (settings.anchorOffset ?? 4) - parentRect.top
127
-
128
- expect(left).toEqual(280); // anchorRect.left - parentRect.left
129
-
130
- settings.side = 'outside-left';
131
- ({
132
- top,
133
- left
134
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
135
- expect(top).toEqual(180); // anchorRect.top - parentRect.top
136
-
137
- expect(left).toEqual(176); // anchorRect.left - floatingRect.width - (settings.anchorOffset ?? 4) - parentRect.left
138
-
139
- settings.side = 'outside-right';
140
- ({
141
- top,
142
- left
143
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
144
- expect(top).toEqual(180); // anchorRect.top - parentRect.top
145
-
146
- expect(left).toEqual(334); // anchorRect.left + anchorRect.width + (settings.anchorOffset ?? 4) - parentRect.left
147
-
148
- settings.side = 'outside-top';
149
- ({
150
- top,
151
- left
152
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
153
- expect(top).toEqual(76); // anchorRect.top - floatingRect.height - (settings.anchorOffset ?? 4) - parentRect.top
154
-
155
- expect(left).toEqual(280); // anchorRect.left - parentRect.left
156
- });
157
- it('returns the correct position for different inside side settings', () => {
158
- const parentRect = makeDOMRect(20, 20, 500, 500);
159
- const anchorRect = makeDOMRect(300, 200, 50, 50);
160
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
161
- const {
162
- float,
163
- anchor
164
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
165
- const settings = {};
166
- let top = 0;
167
- let left = 0;
168
- settings.side = 'inside-bottom';
169
- ({
170
- top,
171
- left
172
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings)); // anchorRect.top + anchorRect.height - (settings.anchorOffset ?? 4) - floatingRect.height - parentRect.top
173
-
174
- expect(top).toEqual(126); // anchorRect.left + (settings.alignmentOffset ?? 4) - parentRect.left
175
-
176
- expect(left).toEqual(284);
177
- settings.side = 'inside-left';
178
- ({
179
- top,
180
- left
181
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
182
- expect(top).toEqual(184); // anchorRect.top + (settings.alignmentOffset ?? 4) - parentRect.top
183
-
184
- expect(left).toEqual(284); // anchorRect.left + (settings.anchorOffset ?? 4) - parentRect.left
185
-
186
- settings.side = 'inside-right';
187
- ({
188
- top,
189
- left
190
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings)); // anchorRect.top + (settings.alignmentOffset ?? 4) - parentRect.top
191
-
192
- expect(top).toEqual(184); // anchorRect.left + anchorRect.width - (settings.anchorOffset ?? 4) - floatingRect.width - parentRect.left
193
-
194
- expect(left).toEqual(226); // almost the same as inside-left, with the exception of offsets
195
-
196
- settings.side = 'inside-top';
197
- ({
198
- top,
199
- left
200
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
201
- expect(top).toEqual(184); // anchorRect.top + (settings.anchorOffset ?? 4) - parentRect.top
202
-
203
- expect(left).toEqual(284); // anchorRect.left + (settings.alignmentOffset ?? 4) - parentRect.left
204
-
205
- settings.side = 'inside-center';
206
- ({
207
- top,
208
- left
209
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
210
- expect(top).toEqual(184); // anchorRect.top + (settings.alignmentOffset ?? 4) - parentRect.top
211
-
212
- expect(left).toEqual(255); // anchorRect.left + anchorRect.width / 2 - floatingRect.width / 2 - parentRect.left
213
- });
214
- it('returns the correct position inside centering along both axes', () => {
215
- const parentRect = makeDOMRect(20, 20, 500, 500);
216
- const anchorRect = makeDOMRect(300, 200, 50, 50);
217
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
218
- const {
219
- float,
220
- anchor
221
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
222
- const settings = {
223
- side: 'inside-center',
224
- align: 'center'
225
- };
226
- const {
227
- top,
228
- left
229
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
230
- expect(top).toEqual(155); // anchorRect.top + anchorRect.height / 2 - floatingRect.height / 2 - parentRect.top
231
-
232
- expect(left).toEqual(255); // anchorRect.left + anchorRect.width / 2 - floatingRect.width / 2 - parentRect.left
233
- });
234
- it('returns the correct position for different alignment settings with no overflow', () => {
235
- const parentRect = makeDOMRect(20, 20, 500, 500);
236
- const anchorRect = makeDOMRect(300, 200, 50, 50);
237
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
238
- const {
239
- float,
240
- anchor
241
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
242
- const settings = {};
243
- let top = 0;
244
- let left = 0;
245
- settings.align = 'start';
246
- ({
247
- top,
248
- left
249
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings));
250
- expect(top).toEqual(234); // anchorRect.top + anchorRect.height + (settings.anchorOffset ?? 4) - parentRect.top
251
-
252
- expect(left).toEqual(280); // anchorRect.left + (settings.alignmentOffset ?? 0) - parentRect.left
253
-
254
- settings.align = 'center';
255
- ({
256
- top,
257
- left
258
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings)); // anchorRect.top + anchorRect.height + (settings.anchorOffset ?? 4) - parentRect.top
259
-
260
- expect(top).toEqual(234); // anchorRect.left + anchorRect.width / 2 - floatingRect.width / 2 + (settings.anchorOffset ?? 0) - parentRect.left
261
-
262
- expect(left).toEqual(255);
263
- settings.align = 'end';
264
- ({
265
- top,
266
- left
267
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings)); // anchorRect.top + anchorRect.height + (settings.anchorOffset ?? 4) - parentRect.top
268
-
269
- expect(top).toEqual(234); // anchorRect.left + anchorRect.width - floatingRect.width - (settings.alignmentOffset ?? 0) - parentRect.left
270
-
271
- expect(left).toEqual(230);
272
- });
273
- it('properly flips to the opposite side if the calculated position overflows along the same axis', () => {
274
- const parentRect = makeDOMRect(20, 20, 500, 500);
275
- const anchorRect = makeDOMRect(300, 400, 50, 50);
276
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
277
- const {
278
- float,
279
- anchor
280
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
281
- const settings = {};
282
- const {
283
- top,
284
- left
285
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
286
- expect(top).toEqual(276); // anchorRect.top - floatingRect.height - (settings.anchorOffset ?? 4) - parentRect.top
287
-
288
- expect(left).toEqual(280); // anchorRect.left - parentRect.left
289
- });
290
- it('properly moves to an adjacent side if overflow happens along side edge and flipped edge', () => {
291
- const parentRect = makeDOMRect(20, 20, 500, 200);
292
- const anchorRect = makeDOMRect(300, 100, 50, 50);
293
- const floatingRect = makeDOMRect(NaN, NaN, 100, 100);
294
- const {
295
- float,
296
- anchor
297
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
298
- const settings = {};
299
- const {
300
- top,
301
- left
302
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
303
- expect(top).toEqual(80); // anchorRect.top - parentRect.top
304
-
305
- expect(left).toEqual(334); // anchorRect.left + anchorRect.width + (settings.anchorOffset ?? 4) - parentRect.left
306
- });
307
- it('properly adjusts the position using an alignment offset if overflow happens along the alignment edge', () => {
308
- const parentRect = makeDOMRect(20, 20, 500, 500);
309
- const anchorRect = makeDOMRect(300, 200, 50, 50);
310
- const floatingRect = makeDOMRect(NaN, NaN, 400, 100);
311
- const {
312
- float,
313
- anchor
314
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
315
- const settings = {};
316
- const {
317
- top,
318
- left
319
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
320
- expect(top).toEqual(234); // anchorRect.top + anchorRect.height + (settings.anchorOffset ?? 4) - parentRect.top
321
-
322
- expect(left).toEqual(100); // parentRect.width - floatingRect.width
323
- });
324
- it('properly calculates the position that needs to be flipped and offset-adjusted', () => {
325
- const parentRect = makeDOMRect(20, 20, 500, 500);
326
- const anchorRect = makeDOMRect(300, 400, 50, 50);
327
- const floatingRect = makeDOMRect(NaN, NaN, 400, 100);
328
- const {
329
- float,
330
- anchor
331
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
332
- const settings = {};
333
- const {
334
- top,
335
- left
336
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings);
337
- expect(top).toEqual(276); // anchorRect.top - floatingRect.height - (settings.anchorOffset ?? 4) - parentRect.top
338
-
339
- expect(left).toEqual(100); // parentRect.width - floatingRect.width
340
- });
341
- it('properly calculates the outside position with many simultaneous settings interactions (stress test)', () => {
342
- const parentRect = makeDOMRect(20, 20, 200, 500);
343
- const anchorRect = makeDOMRect(95, 295, 100, 200);
344
- const floatingRect = makeDOMRect(NaN, NaN, 175, 200);
345
- const {
346
- float,
347
- anchor
348
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
349
- const settings = {
350
- side: 'outside-right',
351
- align: 'center',
352
- alignmentOffset: 10,
353
- anchorOffset: -10
354
- };
355
- const {
356
- top,
357
- left
358
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings); // expect to try right, left, and bottom before ending on top
359
-
360
- expect(top).toEqual(85); // anchorRect.top - floatingRect.height - (settings.anchorOffset ?? 4) - parentRect.top
361
- // expect center alignment to run against edge, so ignored. Also causes alignment offset to be ignored.
362
-
363
- expect(left).toEqual(25); // parentRect.width - floatingRect.width
364
- });
365
- it('properly calculates the inside position with many simultaneous settings interactions (stress test)', () => {
366
- const parentRect = makeDOMRect(20, 20, 500, 500);
367
- const anchorRect = makeDOMRect(100, 100, 300, 300);
368
- const floatingRect = makeDOMRect(NaN, NaN, 100, 200);
369
- const {
370
- float,
371
- anchor
372
- } = createVirtualDOM(parentRect, anchorRect, floatingRect);
373
- const settings = {
374
- side: 'inside-right',
375
- align: 'center',
376
- alignmentOffset: 10,
377
- anchorOffset: -10
378
- };
379
- const {
380
- top,
381
- left
382
- } = (0, _anchoredPosition.getAnchoredPosition)(float, anchor, settings); // anchorRect.top + anchorRect.height / 2 - floatingRect.height / 2 + (settings.alignmentOffset ?? 4) - parentRect.top
383
-
384
- expect(top).toEqual(140); // anchorRect.left + anchorRect.width - floatingRect.width - (settings.anchorOffset ?? 4) - parentRect.left
385
-
386
- expect(left).toEqual(290);
387
- });
388
- });
@@ -1,234 +0,0 @@
1
- "use strict";
2
-
3
- var _react = require("@testing-library/react");
4
-
5
- var _react2 = _interopRequireDefault(require("react"));
6
-
7
- var _focusTrap = require("../focus-trap.js");
8
-
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
-
11
- // Since we use strict `isTabbable` checks within focus trap, we need to mock these
12
- // properties that Jest does not populate.
13
- beforeAll(() => {
14
- try {
15
- Object.defineProperties(HTMLElement.prototype, {
16
- offsetHeight: {
17
- get: () => 42
18
- },
19
- offsetWidth: {
20
- get: () => 42
21
- },
22
- getClientRects: {
23
- get: () => () => [42]
24
- }
25
- });
26
- } catch {// ignore
27
- }
28
- });
29
- it('Should initially focus the container when activated', () => {
30
- const {
31
- container
32
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("button", {
33
- tabIndex: 0
34
- }, "Bad Apple"), /*#__PURE__*/_react2.default.createElement("div", {
35
- id: "trapContainer"
36
- }, /*#__PURE__*/_react2.default.createElement("button", {
37
- tabIndex: 0
38
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
39
- tabIndex: 0
40
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
41
- tabIndex: 0
42
- }, "Cantaloupe"))));
43
- const trapContainer = container.querySelector('#trapContainer');
44
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
45
- expect(document.activeElement).toEqual(trapContainer);
46
- controller.abort();
47
- });
48
- it('Should initially focus the initialFocus element when specified', () => {
49
- const {
50
- container
51
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", {
52
- id: "trapContainer"
53
- }, /*#__PURE__*/_react2.default.createElement("button", {
54
- tabIndex: 0
55
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
56
- tabIndex: 0
57
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
58
- tabIndex: 0
59
- }, "Cantaloupe")));
60
- const trapContainer = container.querySelector('#trapContainer');
61
- const secondButton = trapContainer.querySelectorAll('button')[1];
62
- const controller = (0, _focusTrap.focusTrap)(trapContainer, secondButton);
63
- expect(document.activeElement).toEqual(secondButton);
64
- controller.abort();
65
- });
66
- it('Should prevent focus from exiting the trap, returns focus to previously-focused element', async () => {
67
- const {
68
- container
69
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
70
- id: "trapContainer"
71
- }, /*#__PURE__*/_react2.default.createElement("button", {
72
- tabIndex: 0
73
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
74
- tabIndex: 0
75
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
76
- tabIndex: 0
77
- }, "Cantaloupe")), /*#__PURE__*/_react2.default.createElement("button", {
78
- id: "durian",
79
- tabIndex: 0
80
- }, "Durian")));
81
- const trapContainer = container.querySelector('#trapContainer');
82
- const secondButton = trapContainer.querySelectorAll('button')[1];
83
- const durianButton = container.querySelector('#durian');
84
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
85
- focus(durianButton);
86
- expect(document.activeElement).toEqual(trapContainer);
87
- focus(secondButton);
88
- expect(document.activeElement).toEqual(secondButton);
89
- focus(durianButton);
90
- expect(document.activeElement).toEqual(secondButton);
91
- controller.abort();
92
- });
93
- it('Should prevent focus from exiting the trap if there are no focusable children', async () => {
94
- const {
95
- container
96
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
97
- id: "trapContainer"
98
- }), /*#__PURE__*/_react2.default.createElement("button", {
99
- id: "durian",
100
- tabIndex: 0
101
- }, "Durian")));
102
- const trapContainer = container.querySelector('#trapContainer');
103
- const durianButton = container.querySelector('#durian');
104
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
105
- focus(durianButton);
106
- expect(document.activeElement === durianButton).toEqual(false);
107
- controller.abort();
108
- });
109
- it('Should cycle focus from last element to first element and vice-versa', async () => {
110
- const {
111
- container
112
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
113
- id: "trapContainer"
114
- }, /*#__PURE__*/_react2.default.createElement("button", {
115
- tabIndex: 0
116
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
117
- tabIndex: 0
118
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
119
- tabIndex: 0
120
- }, "Cantaloupe")), /*#__PURE__*/_react2.default.createElement("button", {
121
- id: "durian",
122
- tabIndex: 0
123
- }, "Durian")));
124
- const trapContainer = container.querySelector('#trapContainer');
125
- const firstButton = trapContainer.querySelector('button');
126
- const lastButton = trapContainer.querySelectorAll('button')[2];
127
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
128
- lastButton.focus();
129
- (0, _react.fireEvent)(lastButton, new KeyboardEvent('keydown', {
130
- bubbles: true,
131
- key: 'Tab'
132
- }));
133
- expect(document.activeElement).toEqual(firstButton);
134
- (0, _react.fireEvent)(firstButton, new KeyboardEvent('keydown', {
135
- bubbles: true,
136
- key: 'Tab',
137
- shiftKey: true
138
- }));
139
- expect(document.activeElement).toEqual(lastButton);
140
- controller.abort();
141
- });
142
- it('Should should release the trap when the signal is aborted', async () => {
143
- const {
144
- container
145
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
146
- id: "trapContainer"
147
- }, /*#__PURE__*/_react2.default.createElement("button", {
148
- tabIndex: 0
149
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
150
- tabIndex: 0
151
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
152
- tabIndex: 0
153
- }, "Cantaloupe")), /*#__PURE__*/_react2.default.createElement("button", {
154
- id: "durian",
155
- tabIndex: 0
156
- }, "Durian")));
157
- const trapContainer = container.querySelector('#trapContainer');
158
- const durianButton = container.querySelector('#durian');
159
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
160
- focus(durianButton);
161
- expect(document.activeElement).toEqual(trapContainer);
162
- controller.abort();
163
- focus(durianButton);
164
- expect(document.activeElement).toEqual(durianButton);
165
- });
166
- it('Should should release the trap when the container is removed from the DOM', async () => {
167
- var _trapContainer$parent;
168
-
169
- const {
170
- container
171
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
172
- id: "trapContainer"
173
- }, /*#__PURE__*/_react2.default.createElement("button", {
174
- tabIndex: 0
175
- }, "Apple")), /*#__PURE__*/_react2.default.createElement("button", {
176
- id: "durian",
177
- tabIndex: 0
178
- }, "Durian")));
179
- const trapContainer = container.querySelector('#trapContainer');
180
- const durianButton = container.querySelector('#durian');
181
- const firstButton = trapContainer.querySelector('button');
182
- (0, _focusTrap.focusTrap)(trapContainer);
183
- focus(durianButton);
184
- expect(document.activeElement).toEqual(trapContainer); // empty trap and remove it from the DOM
185
-
186
- trapContainer.removeChild(firstButton);
187
- (_trapContainer$parent = trapContainer.parentElement) === null || _trapContainer$parent === void 0 ? void 0 : _trapContainer$parent.removeChild(trapContainer);
188
- focus(durianButton);
189
- expect(document.activeElement).toEqual(durianButton);
190
- });
191
- it('Should handle dynamic content', async () => {
192
- const {
193
- container
194
- } = (0, _react.render)( /*#__PURE__*/_react2.default.createElement("div", null, /*#__PURE__*/_react2.default.createElement("div", {
195
- id: "trapContainer"
196
- }, /*#__PURE__*/_react2.default.createElement("button", {
197
- tabIndex: 0
198
- }, "Apple"), /*#__PURE__*/_react2.default.createElement("button", {
199
- tabIndex: 0
200
- }, "Banana"), /*#__PURE__*/_react2.default.createElement("button", {
201
- tabIndex: 0
202
- }, "Cantaloupe")), /*#__PURE__*/_react2.default.createElement("button", {
203
- id: "durian",
204
- tabIndex: 0
205
- }, "Durian")));
206
- const trapContainer = container.querySelector('#trapContainer');
207
- const [firstButton, secondButton, thirdButton] = trapContainer.querySelectorAll('button');
208
- const controller = (0, _focusTrap.focusTrap)(trapContainer);
209
- secondButton.focus();
210
- trapContainer.removeChild(thirdButton);
211
- (0, _react.fireEvent)(secondButton, new KeyboardEvent('keydown', {
212
- bubbles: true,
213
- key: 'Tab'
214
- }));
215
- expect(document.activeElement).toEqual(firstButton);
216
- (0, _react.fireEvent)(firstButton, new KeyboardEvent('keydown', {
217
- bubbles: true,
218
- key: 'Tab',
219
- shiftKey: true
220
- }));
221
- expect(document.activeElement).toEqual(secondButton);
222
- controller.abort();
223
- });
224
- /**
225
- * Helper to handle firing the focusin event, which jest/JSDOM does not do for us.
226
- * @param element
227
- */
228
-
229
- function focus(element) {
230
- element.focus();
231
- (0, _react.fireEvent)(element, new FocusEvent('focusin', {
232
- bubbles: true
233
- }));
234
- }