focus-trap 6.6.1 → 6.7.3
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 +31 -0
- package/README.md +26 -9
- package/dist/focus-trap.esm.js +148 -68
- package/dist/focus-trap.esm.js.map +1 -1
- package/dist/focus-trap.esm.min.js +2 -2
- package/dist/focus-trap.esm.min.js.map +1 -1
- package/dist/focus-trap.js +147 -67
- package/dist/focus-trap.js.map +1 -1
- package/dist/focus-trap.min.js +2 -2
- package/dist/focus-trap.min.js.map +1 -1
- package/dist/focus-trap.umd.js +150 -70
- package/dist/focus-trap.umd.js.map +1 -1
- package/dist/focus-trap.umd.min.js +2 -2
- package/dist/focus-trap.umd.min.js.map +1 -1
- package/index.d.ts +25 -4
- package/index.js +150 -48
- package/package.json +27 -25
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { tabbable, isFocusable } from 'tabbable';
|
|
1
|
+
import { tabbable, focusable, isFocusable, isTabbable } from 'tabbable';
|
|
2
2
|
|
|
3
3
|
const activeFocusTraps = (function () {
|
|
4
4
|
const trapQueue = [];
|
|
@@ -82,8 +82,23 @@ const valueOrHandler = function (value, ...params) {
|
|
|
82
82
|
return typeof value === 'function' ? value(...params) : value;
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
const getActualTarget = function (event) {
|
|
86
|
+
// NOTE: If the trap is _inside_ a shadow DOM, event.target will always be the
|
|
87
|
+
// shadow host. However, event.target.composedPath() will be an array of
|
|
88
|
+
// nodes "clicked" from inner-most (the actual element inside the shadow) to
|
|
89
|
+
// outer-most (the host HTML document). If we have access to composedPath(),
|
|
90
|
+
// then use its first element; otherwise, fall back to event.target (and
|
|
91
|
+
// this only works for an _open_ shadow DOM; otherwise,
|
|
92
|
+
// composedPath()[0] === event.target always).
|
|
93
|
+
return event.target.shadowRoot && typeof event.composedPath === 'function'
|
|
94
|
+
? event.composedPath()[0]
|
|
95
|
+
: event.target;
|
|
96
|
+
};
|
|
97
|
+
|
|
85
98
|
const createFocusTrap = function (elements, userOptions) {
|
|
86
|
-
|
|
99
|
+
// SSR: a live trap shouldn't be created in this type of environment so this
|
|
100
|
+
// should be safe code to execute if the `document` option isn't specified
|
|
101
|
+
const doc = userOptions?.document || document;
|
|
87
102
|
|
|
88
103
|
const config = {
|
|
89
104
|
returnFocusOnDeactivate: true,
|
|
@@ -102,7 +117,12 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
102
117
|
// is active, but the trap should never get to a state where there isn't at least one group
|
|
103
118
|
// with at least one tabbable node in it (that would lead to an error condition that would
|
|
104
119
|
// result in an error being thrown)
|
|
105
|
-
// @type {Array<{
|
|
120
|
+
// @type {Array<{
|
|
121
|
+
// container: HTMLElement,
|
|
122
|
+
// firstTabbableNode: HTMLElement|null,
|
|
123
|
+
// lastTabbableNode: HTMLElement|null,
|
|
124
|
+
// nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
|
|
125
|
+
// }>}
|
|
106
126
|
tabbableGroups: [],
|
|
107
127
|
|
|
108
128
|
nodeFocusedBeforeActivation: null,
|
|
@@ -125,28 +145,51 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
125
145
|
};
|
|
126
146
|
|
|
127
147
|
const containersContain = function (element) {
|
|
128
|
-
return
|
|
148
|
+
return !!(
|
|
149
|
+
element &&
|
|
150
|
+
state.containers.some((container) => container.contains(element))
|
|
151
|
+
);
|
|
129
152
|
};
|
|
130
153
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Gets the node for the given option, which is expected to be an option that
|
|
156
|
+
* can be either a DOM node, a string that is a selector to get a node, `false`
|
|
157
|
+
* (if a node is explicitly NOT given), or a function that returns any of these
|
|
158
|
+
* values.
|
|
159
|
+
* @param {string} optionName
|
|
160
|
+
* @returns {undefined | false | HTMLElement | SVGElement} Returns
|
|
161
|
+
* `undefined` if the option is not specified; `false` if the option
|
|
162
|
+
* resolved to `false` (node explicitly not given); otherwise, the resolved
|
|
163
|
+
* DOM node.
|
|
164
|
+
* @throws {Error} If the option is set, not `false`, and is not, or does not
|
|
165
|
+
* resolve to a node.
|
|
166
|
+
*/
|
|
167
|
+
const getNodeForOption = function (optionName, ...params) {
|
|
168
|
+
let optionValue = config[optionName];
|
|
136
169
|
|
|
137
|
-
|
|
170
|
+
if (typeof optionValue === 'function') {
|
|
171
|
+
optionValue = optionValue(...params);
|
|
172
|
+
}
|
|
138
173
|
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
throw new Error(`\`${optionName}\` refers to no known node`);
|
|
174
|
+
if (!optionValue) {
|
|
175
|
+
if (optionValue === undefined || optionValue === false) {
|
|
176
|
+
return optionValue;
|
|
143
177
|
}
|
|
178
|
+
// else, empty string (invalid), null (invalid), 0 (invalid)
|
|
179
|
+
|
|
180
|
+
throw new Error(
|
|
181
|
+
`\`${optionName}\` was specified but was not a node, or did not return a node`
|
|
182
|
+
);
|
|
144
183
|
}
|
|
145
184
|
|
|
146
|
-
|
|
147
|
-
|
|
185
|
+
let node = optionValue; // could be HTMLElement, SVGElement, or non-empty string at this point
|
|
186
|
+
|
|
187
|
+
if (typeof optionValue === 'string') {
|
|
188
|
+
node = doc.querySelector(optionValue); // resolve to node, or null if fails
|
|
148
189
|
if (!node) {
|
|
149
|
-
throw new Error(
|
|
190
|
+
throw new Error(
|
|
191
|
+
`\`${optionName}\` as selector refers to no known node`
|
|
192
|
+
);
|
|
150
193
|
}
|
|
151
194
|
}
|
|
152
195
|
|
|
@@ -154,22 +197,25 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
154
197
|
};
|
|
155
198
|
|
|
156
199
|
const getInitialFocusNode = function () {
|
|
157
|
-
let node;
|
|
200
|
+
let node = getNodeForOption('initialFocus');
|
|
158
201
|
|
|
159
|
-
// false indicates we want no initialFocus at all
|
|
160
|
-
if (
|
|
202
|
+
// false explicitly indicates we want no initialFocus at all
|
|
203
|
+
if (node === false) {
|
|
161
204
|
return false;
|
|
162
205
|
}
|
|
163
206
|
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
207
|
+
if (node === undefined) {
|
|
208
|
+
// option not specified: use fallback options
|
|
209
|
+
if (containersContain(doc.activeElement)) {
|
|
210
|
+
node = doc.activeElement;
|
|
211
|
+
} else {
|
|
212
|
+
const firstTabbableGroup = state.tabbableGroups[0];
|
|
213
|
+
const firstTabbableNode =
|
|
214
|
+
firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
|
|
215
|
+
|
|
216
|
+
// NOTE: `fallbackFocus` option function cannot return `false` (not supported)
|
|
217
|
+
node = firstTabbableNode || getNodeForOption('fallbackFocus');
|
|
218
|
+
}
|
|
173
219
|
}
|
|
174
220
|
|
|
175
221
|
if (!node) {
|
|
@@ -186,11 +232,46 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
186
232
|
.map((container) => {
|
|
187
233
|
const tabbableNodes = tabbable(container);
|
|
188
234
|
|
|
235
|
+
// NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
|
|
236
|
+
// are a superset of tabbable nodes
|
|
237
|
+
const focusableNodes = focusable(container);
|
|
238
|
+
|
|
189
239
|
if (tabbableNodes.length > 0) {
|
|
190
240
|
return {
|
|
191
241
|
container,
|
|
192
242
|
firstTabbableNode: tabbableNodes[0],
|
|
193
243
|
lastTabbableNode: tabbableNodes[tabbableNodes.length - 1],
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Finds the __tabbable__ node that follows the given node in the specified direction,
|
|
247
|
+
* in this container, if any.
|
|
248
|
+
* @param {HTMLElement} node
|
|
249
|
+
* @param {boolean} [forward] True if going in forward tab order; false if going
|
|
250
|
+
* in reverse.
|
|
251
|
+
* @returns {HTMLElement|undefined} The next tabbable node, if any.
|
|
252
|
+
*/
|
|
253
|
+
nextTabbableNode(node, forward = true) {
|
|
254
|
+
// NOTE: If tabindex is positive (in order to manipulate the tab order separate
|
|
255
|
+
// from the DOM order), this __will not work__ because the list of focusableNodes,
|
|
256
|
+
// while it contains tabbable nodes, does not sort its nodes in any order other
|
|
257
|
+
// than DOM order, because it can't: Where would you place focusable (but not
|
|
258
|
+
// tabbable) nodes in that order? They have no order, because they aren't tabbale...
|
|
259
|
+
// Support for positive tabindex is already broken and hard to manage (possibly
|
|
260
|
+
// not supportable, TBD), so this isn't going to make things worse than they
|
|
261
|
+
// already are, and at least makes things better for the majority of cases where
|
|
262
|
+
// tabindex is either 0/unset or negative.
|
|
263
|
+
// FYI, positive tabindex issue: https://github.com/focus-trap/focus-trap/issues/375
|
|
264
|
+
const nodeIdx = focusableNodes.findIndex((n) => n === node);
|
|
265
|
+
if (forward) {
|
|
266
|
+
return focusableNodes
|
|
267
|
+
.slice(nodeIdx + 1)
|
|
268
|
+
.find((n) => isTabbable(n));
|
|
269
|
+
}
|
|
270
|
+
return focusableNodes
|
|
271
|
+
.slice(0, nodeIdx)
|
|
272
|
+
.reverse()
|
|
273
|
+
.find((n) => isTabbable(n));
|
|
274
|
+
},
|
|
194
275
|
};
|
|
195
276
|
}
|
|
196
277
|
|
|
@@ -201,7 +282,7 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
201
282
|
// throw if no groups have tabbable nodes and we don't have a fallback focus node either
|
|
202
283
|
if (
|
|
203
284
|
state.tabbableGroups.length <= 0 &&
|
|
204
|
-
!getNodeForOption('fallbackFocus')
|
|
285
|
+
!getNodeForOption('fallbackFocus') // returning false not supported for this option
|
|
205
286
|
) {
|
|
206
287
|
throw new Error(
|
|
207
288
|
'Your focus-trap must have at least one container with at least one tabbable node in it at all times'
|
|
@@ -232,15 +313,16 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
232
313
|
};
|
|
233
314
|
|
|
234
315
|
const getReturnFocusNode = function (previousActiveElement) {
|
|
235
|
-
const node = getNodeForOption('setReturnFocus');
|
|
236
|
-
|
|
237
|
-
return node ? node : previousActiveElement;
|
|
316
|
+
const node = getNodeForOption('setReturnFocus', previousActiveElement);
|
|
317
|
+
return node ? node : node === false ? false : previousActiveElement;
|
|
238
318
|
};
|
|
239
319
|
|
|
240
320
|
// This needs to be done on mousedown and touchstart instead of click
|
|
241
321
|
// so that it precedes the focus event.
|
|
242
322
|
const checkPointerDown = function (e) {
|
|
243
|
-
|
|
323
|
+
const target = getActualTarget(e);
|
|
324
|
+
|
|
325
|
+
if (containersContain(target)) {
|
|
244
326
|
// allow the click since it ocurred inside the trap
|
|
245
327
|
return;
|
|
246
328
|
}
|
|
@@ -259,7 +341,7 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
259
341
|
// that was clicked, whether it's focusable or not; by setting
|
|
260
342
|
// `returnFocus: true`, we'll attempt to re-focus the node originally-focused
|
|
261
343
|
// on activation (or the configured `setReturnFocus` node)
|
|
262
|
-
returnFocus: config.returnFocusOnDeactivate && !isFocusable(
|
|
344
|
+
returnFocus: config.returnFocusOnDeactivate && !isFocusable(target),
|
|
263
345
|
});
|
|
264
346
|
return;
|
|
265
347
|
}
|
|
@@ -278,11 +360,13 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
278
360
|
|
|
279
361
|
// In case focus escapes the trap for some strange reason, pull it back in.
|
|
280
362
|
const checkFocusIn = function (e) {
|
|
281
|
-
const
|
|
363
|
+
const target = getActualTarget(e);
|
|
364
|
+
const targetContained = containersContain(target);
|
|
365
|
+
|
|
282
366
|
// In Firefox when you Tab out of an iframe the Document is briefly focused.
|
|
283
|
-
if (targetContained ||
|
|
367
|
+
if (targetContained || target instanceof Document) {
|
|
284
368
|
if (targetContained) {
|
|
285
|
-
state.mostRecentlyFocusedNode =
|
|
369
|
+
state.mostRecentlyFocusedNode = target;
|
|
286
370
|
}
|
|
287
371
|
} else {
|
|
288
372
|
// escaped! pull it back in to where it just left
|
|
@@ -296,17 +380,20 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
296
380
|
// moment it can end up scrolling the page and causing confusion so we
|
|
297
381
|
// kind of need to capture the action at the keydown phase.
|
|
298
382
|
const checkTab = function (e) {
|
|
383
|
+
const target = getActualTarget(e);
|
|
299
384
|
updateTabbableNodes();
|
|
300
385
|
|
|
301
386
|
let destinationNode = null;
|
|
302
387
|
|
|
303
388
|
if (state.tabbableGroups.length > 0) {
|
|
304
389
|
// make sure the target is actually contained in a group
|
|
305
|
-
// NOTE: the target may also be the container itself if it's
|
|
390
|
+
// NOTE: the target may also be the container itself if it's focusable
|
|
306
391
|
// with tabIndex='-1' and was given initial focus
|
|
307
392
|
const containerIndex = findIndex(state.tabbableGroups, ({ container }) =>
|
|
308
|
-
container.contains(
|
|
393
|
+
container.contains(target)
|
|
309
394
|
);
|
|
395
|
+
const containerGroup =
|
|
396
|
+
containerIndex >= 0 ? state.tabbableGroups[containerIndex] : undefined;
|
|
310
397
|
|
|
311
398
|
if (containerIndex < 0) {
|
|
312
399
|
// target not found in any group: quite possible focus has escaped the trap,
|
|
@@ -326,14 +413,20 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
326
413
|
// is the target the first tabbable node in a group?
|
|
327
414
|
let startOfGroupIndex = findIndex(
|
|
328
415
|
state.tabbableGroups,
|
|
329
|
-
({ firstTabbableNode }) =>
|
|
416
|
+
({ firstTabbableNode }) => target === firstTabbableNode
|
|
330
417
|
);
|
|
331
418
|
|
|
332
419
|
if (
|
|
333
420
|
startOfGroupIndex < 0 &&
|
|
334
|
-
|
|
421
|
+
(containerGroup.container === target ||
|
|
422
|
+
(isFocusable(target) &&
|
|
423
|
+
!isTabbable(target) &&
|
|
424
|
+
!containerGroup.nextTabbableNode(target, false)))
|
|
335
425
|
) {
|
|
336
|
-
// an exception case where the target is the container itself,
|
|
426
|
+
// an exception case where the target is either the container itself, or
|
|
427
|
+
// a non-tabbable node that was given focus (i.e. tabindex is negative
|
|
428
|
+
// and user clicked on it or node was programmatically given focus)
|
|
429
|
+
// and is not followed by any other tabbable node, in which
|
|
337
430
|
// case, we should handle shift+tab as if focus were on the container's
|
|
338
431
|
// first tabbable node, and go to the last tabbable node of the LAST group
|
|
339
432
|
startOfGroupIndex = containerIndex;
|
|
@@ -357,14 +450,20 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
357
450
|
// is the target the last tabbable node in a group?
|
|
358
451
|
let lastOfGroupIndex = findIndex(
|
|
359
452
|
state.tabbableGroups,
|
|
360
|
-
({ lastTabbableNode }) =>
|
|
453
|
+
({ lastTabbableNode }) => target === lastTabbableNode
|
|
361
454
|
);
|
|
362
455
|
|
|
363
456
|
if (
|
|
364
457
|
lastOfGroupIndex < 0 &&
|
|
365
|
-
|
|
458
|
+
(containerGroup.container === target ||
|
|
459
|
+
(isFocusable(target) &&
|
|
460
|
+
!isTabbable(target) &&
|
|
461
|
+
!containerGroup.nextTabbableNode(target)))
|
|
366
462
|
) {
|
|
367
|
-
// an exception case where the target is the container itself,
|
|
463
|
+
// an exception case where the target is the container itself, or
|
|
464
|
+
// a non-tabbable node that was given focus (i.e. tabindex is negative
|
|
465
|
+
// and user clicked on it or node was programmatically given focus)
|
|
466
|
+
// and is not followed by any other tabbable node, in which
|
|
368
467
|
// case, we should handle tab as if focus were on the container's
|
|
369
468
|
// last tabbable node, and go to the first tabbable node of the FIRST group
|
|
370
469
|
lastOfGroupIndex = containerIndex;
|
|
@@ -384,6 +483,7 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
384
483
|
}
|
|
385
484
|
}
|
|
386
485
|
} else {
|
|
486
|
+
// NOTE: the fallbackFocus option does not support returning false to opt-out
|
|
387
487
|
destinationNode = getNodeForOption('fallbackFocus');
|
|
388
488
|
}
|
|
389
489
|
|
|
@@ -397,7 +497,7 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
397
497
|
const checkKey = function (e) {
|
|
398
498
|
if (
|
|
399
499
|
isEscapeEvent(e) &&
|
|
400
|
-
valueOrHandler(config.escapeDeactivates) !== false
|
|
500
|
+
valueOrHandler(config.escapeDeactivates, e) !== false
|
|
401
501
|
) {
|
|
402
502
|
e.preventDefault();
|
|
403
503
|
trap.deactivate();
|
|
@@ -415,7 +515,9 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
415
515
|
return;
|
|
416
516
|
}
|
|
417
517
|
|
|
418
|
-
|
|
518
|
+
const target = getActualTarget(e);
|
|
519
|
+
|
|
520
|
+
if (containersContain(target)) {
|
|
419
521
|
return;
|
|
420
522
|
}
|
|
421
523
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "focus-trap",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.3",
|
|
4
4
|
"description": "Trap focus within a DOM node.",
|
|
5
5
|
"main": "dist/focus-trap.js",
|
|
6
6
|
"module": "dist/focus-trap.esm.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"demo-bundle": "
|
|
20
|
+
"demo-bundle": "yarn compile:demo",
|
|
21
21
|
"format": "prettier --write \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
|
|
22
22
|
"format:check": "prettier --check \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
|
|
23
23
|
"format:watch": "onchange \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\" -- prettier --write {{changed}}",
|
|
@@ -26,13 +26,15 @@
|
|
|
26
26
|
"compile:esm": "cross-env BUILD_ENV=esm BABEL_ENV=esm rollup -c",
|
|
27
27
|
"compile:cjs": "cross-env BUILD_ENV=cjs BABEL_ENV=es5 rollup -c",
|
|
28
28
|
"compile:umd": "cross-env BUILD_ENV=umd BABEL_ENV=es5 rollup -c",
|
|
29
|
+
"compile:demo": "cross-env BUILD_ENV=demo BABEL_ENV=es5 rollup -c",
|
|
29
30
|
"compile": "yarn compile:esm && yarn compile:cjs && yarn compile:umd",
|
|
30
31
|
"build": "yarn clean && yarn compile",
|
|
31
|
-
"start": "yarn compile:
|
|
32
|
+
"start": "yarn compile:demo --watch --environment SERVE,RELOAD,IS_CYPRESS_ENV:''",
|
|
33
|
+
"start:cypress": "yarn compile:demo --environment SERVE,IS_CYPRESS_ENV:\"$CYPRESS_BROWSER\"",
|
|
32
34
|
"test:types": "tsc index.d.ts",
|
|
33
35
|
"test:unit": "echo \"No unit tests to run!\"",
|
|
34
|
-
"test:cypress": "start-server-and-test start 9966 'cypress open'",
|
|
35
|
-
"test:cypress:ci": "start-server-and-test start 9966 'cypress run --browser $CYPRESS_BROWSER --headless'",
|
|
36
|
+
"test:cypress": "CYPRESS_BROWSER=ANY start-server-and-test start:cypress 9966 'cypress open'",
|
|
37
|
+
"test:cypress:ci": "start-server-and-test start:cypress 9966 'cypress run --browser $CYPRESS_BROWSER --headless'",
|
|
36
38
|
"test:chrome": "CYPRESS_BROWSER=chrome yarn test:cypress:ci",
|
|
37
39
|
"test": "yarn format:check && yarn lint && yarn test:unit && yarn test:types && CYPRESS_BROWSER=chrome yarn test:cypress:ci",
|
|
38
40
|
"prepare": "yarn build",
|
|
@@ -63,33 +65,33 @@
|
|
|
63
65
|
"tabbable": "^5.2.1"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
66
|
-
"@babel/cli": "^7.
|
|
67
|
-
"@babel/core": "^7.
|
|
68
|
-
"@babel/
|
|
69
|
-
"@
|
|
68
|
+
"@babel/cli": "^7.17.0",
|
|
69
|
+
"@babel/core": "^7.17.2",
|
|
70
|
+
"@babel/eslint-parser": "^7.17.0",
|
|
71
|
+
"@babel/preset-env": "^7.16.11",
|
|
72
|
+
"@changesets/cli": "^2.20.0",
|
|
70
73
|
"@rollup/plugin-babel": "^5.3.0",
|
|
71
|
-
"@rollup/plugin-commonjs": "^
|
|
72
|
-
"@rollup/plugin-node-resolve": "^13.
|
|
73
|
-
"@testing-library/cypress": "^8.0.
|
|
74
|
-
"@types/jquery": "^3.5.
|
|
74
|
+
"@rollup/plugin-commonjs": "^21.0.1",
|
|
75
|
+
"@rollup/plugin-node-resolve": "^13.1.3",
|
|
76
|
+
"@testing-library/cypress": "^8.0.2",
|
|
77
|
+
"@types/jquery": "^3.5.13",
|
|
75
78
|
"all-contributors-cli": "^6.20.0",
|
|
76
|
-
"babel-
|
|
77
|
-
"babel-loader": "^8.2.2",
|
|
78
|
-
"babelify": "^10.0.0",
|
|
79
|
-
"browserify": "^17.0.0",
|
|
80
|
-
"budo": "^11.6.4",
|
|
79
|
+
"babel-loader": "^8.2.3",
|
|
81
80
|
"cross-env": "^7.0.3",
|
|
82
|
-
"cypress": "^
|
|
81
|
+
"cypress": "^9.4.1",
|
|
83
82
|
"cypress-plugin-tab": "^1.0.5",
|
|
84
|
-
"eslint": "^
|
|
83
|
+
"eslint": "^8.8.0",
|
|
85
84
|
"eslint-config-prettier": "^8.3.0",
|
|
86
|
-
"eslint-plugin-cypress": "^2.
|
|
85
|
+
"eslint-plugin-cypress": "^2.12.1",
|
|
87
86
|
"onchange": "^7.1.0",
|
|
88
|
-
"prettier": "^2.
|
|
89
|
-
"rollup": "^2.
|
|
87
|
+
"prettier": "^2.5.1",
|
|
88
|
+
"rollup": "^2.67.1",
|
|
89
|
+
"rollup-plugin-inject-process-env": "^1.3.1",
|
|
90
|
+
"rollup-plugin-livereload": "^2.0.5",
|
|
91
|
+
"rollup-plugin-serve": "^1.1.0",
|
|
90
92
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
91
93
|
"rollup-plugin-terser": "^7.0.1",
|
|
92
|
-
"start-server-and-test": "^1.
|
|
93
|
-
"typescript": "^4.
|
|
94
|
+
"start-server-and-test": "^1.14.0",
|
|
95
|
+
"typescript": "^4.5.5"
|
|
94
96
|
}
|
|
95
97
|
}
|