@popsure/dirty-swan 0.55.3 → 0.56.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/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +2688 -882
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/components/modal/fullScreenModal/index.d.ts +3 -0
- package/dist/cjs/lib/components/modal/index.d.ts +2 -1
- package/dist/cjs/lib/components/modal/index.stories.d.ts +4 -0
- package/dist/cjs/lib/hooks/useEscapeKey.d.ts +1 -0
- package/dist/cjs/lib/hooks/useFocusWithin.d.ts +1 -0
- package/dist/cjs/lib/index.d.ts +4 -2
- package/dist/esm/{Calendar-3239814b.js → Calendar-d39056f4.js} +9 -9
- package/dist/esm/{Calendar-3239814b.js.map → Calendar-d39056f4.js.map} +1 -1
- package/dist/esm/{TableSection-a1be2bd3.js → TableSection-24337bc7.js} +1 -1
- package/dist/esm/{TableSection-a1be2bd3.js.map → TableSection-24337bc7.js.map} +1 -1
- package/dist/esm/components/accordion/index.js +1 -1
- package/dist/esm/components/accordion/index.stories.js +1 -1
- package/dist/esm/components/autocompleteAddress/index.test.js +1 -1
- package/dist/esm/components/badge/index.test.js +1 -1
- package/dist/esm/components/button/index.js +4 -4
- package/dist/esm/components/button/index.js.map +1 -1
- package/dist/esm/components/button/index.test.js +1 -1
- package/dist/esm/components/comparisonTable/components/AccordionItem/AccordionItem.js +1 -1
- package/dist/esm/components/comparisonTable/components/AccordionItem/index.js +1 -1
- package/dist/esm/components/comparisonTable/components/Row/index.js +2 -2
- package/dist/esm/components/comparisonTable/components/Row/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableButton/index.test.js +2 -2
- package/dist/esm/components/comparisonTable/components/TableRowHeader/index.test.js +2 -2
- package/dist/esm/components/comparisonTable/index.js +2 -2
- package/dist/esm/components/comparisonTable/index.stories.js +2 -2
- package/dist/esm/components/dateSelector/components/Calendar.js +1 -1
- package/dist/esm/components/dateSelector/index.js +1 -1
- package/dist/esm/components/dateSelector/index.stories.js +1 -1
- package/dist/esm/components/dateSelector/index.test.js +2 -2
- package/dist/esm/components/informationBox/index.test.js +1 -1
- package/dist/esm/components/input/autoSuggestInput/index.js +8 -998
- package/dist/esm/components/input/autoSuggestInput/index.js.map +1 -1
- package/dist/esm/components/input/autoSuggestInput/index.stories.js +1 -0
- package/dist/esm/components/input/autoSuggestInput/index.stories.js.map +1 -1
- package/dist/esm/components/input/autoSuggestMultiSelect/index.js +1 -0
- package/dist/esm/components/input/autoSuggestMultiSelect/index.js.map +1 -1
- package/dist/esm/components/input/autoSuggestMultiSelect/index.stories.js +1 -0
- package/dist/esm/components/input/autoSuggestMultiSelect/index.stories.js.map +1 -1
- package/dist/esm/components/input/checkbox/index.test.js +1 -1
- package/dist/esm/components/input/currency/index.test.js +1 -1
- package/dist/esm/components/input/index.js +2 -2
- package/dist/esm/components/input/index.js.map +1 -1
- package/dist/esm/components/input/radio/index.test.js +1 -1
- package/dist/esm/components/input/toggle/index.test.js +1 -1
- package/dist/esm/components/modal/bottomModal/index.js +2 -0
- package/dist/esm/components/modal/bottomModal/index.js.map +1 -1
- package/dist/esm/components/modal/bottomOrRegularModal/index.js +2 -0
- package/dist/esm/components/modal/bottomOrRegularModal/index.js.map +1 -1
- package/dist/esm/components/modal/fullScreenModal/index.js +33 -0
- package/dist/esm/components/modal/fullScreenModal/index.js.map +1 -0
- package/dist/esm/components/modal/genericModal/index.js +1751 -13
- package/dist/esm/components/modal/genericModal/index.js.map +1 -1
- package/dist/esm/components/modal/index.stories.js +20 -7
- package/dist/esm/components/modal/index.stories.js.map +1 -1
- package/dist/esm/components/modal/regularModal/index.js +2 -0
- package/dist/esm/components/modal/regularModal/index.js.map +1 -1
- package/dist/esm/components/multiDropzone/index.js +3 -3
- package/dist/esm/components/multiDropzone/index.js.map +1 -1
- package/dist/esm/components/multiDropzone/index.stories.js +1 -1
- package/dist/esm/components/multiDropzone/index.test.js +3 -3
- package/dist/esm/components/segmentedControl/index.test.js +1 -1
- package/dist/esm/components/signaturePad/index.js +2 -2
- package/dist/esm/components/signaturePad/index.js.map +1 -1
- package/dist/esm/components/spinner/index.test.js +1 -1
- package/dist/esm/components/table/Table.js +4 -2
- package/dist/esm/components/table/Table.js.map +1 -1
- package/dist/esm/components/table/Table.stories.js +4 -2
- package/dist/esm/components/table/Table.stories.js.map +1 -1
- package/dist/esm/components/table/Table.test.js +5 -3
- package/dist/esm/components/table/Table.test.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.js +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.stories.js +1 -1
- package/dist/esm/components/table/components/TableCell/TableCell.js +3 -3
- package/dist/esm/components/table/components/TableCell/TableCell.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/TableCell.test.js +2 -2
- package/dist/esm/components/table/components/TableContents/TableContents.js +2 -2
- package/dist/esm/components/table/components/TableContents/TableContents.test.js +3 -3
- package/dist/esm/components/table/components/TableControls/TableControls.test.js +1 -1
- package/dist/esm/components/table/components/TableSection/TableSection.js +2 -2
- package/dist/esm/components/table/components/TableSection/TableSection.test.js +3 -3
- package/dist/esm/components/toast/index.js +1 -1
- package/dist/esm/components/toast/index.stories.js +1 -1
- package/dist/esm/components/toast/index.test.js +2 -2
- package/dist/esm/{customRender-d03c10b6.js → customRender-be47569b.js} +4 -4
- package/dist/esm/{customRender-d03c10b6.js.map → customRender-be47569b.js.map} +1 -1
- package/dist/esm/index-171a0108.js +997 -0
- package/dist/esm/index-171a0108.js.map +1 -0
- package/dist/esm/{index-3aa7e697.js → index-4b19aafb.js} +4 -4
- package/dist/esm/{index-3aa7e697.js.map → index-4b19aafb.js.map} +1 -1
- package/dist/esm/{index-6f567b0b.js → index-86558de6.js} +2 -2
- package/dist/esm/{index-6f567b0b.js.map → index-86558de6.js.map} +1 -1
- package/dist/esm/{index-3d286178.js → index-af1860d8.js} +3 -3
- package/dist/esm/{index-3d286178.js.map → index-af1860d8.js.map} +1 -1
- package/dist/esm/{index-a0ef2ab4.js → index-e27b50cf.js} +4 -4
- package/dist/esm/{index-a0ef2ab4.js.map → index-e27b50cf.js.map} +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +36 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/components/modal/fullScreenModal/index.d.ts +3 -0
- package/dist/esm/lib/components/modal/index.d.ts +2 -1
- package/dist/esm/lib/components/modal/index.stories.d.ts +4 -0
- package/dist/esm/lib/hooks/useEscapeKey.d.ts +1 -0
- package/dist/esm/lib/hooks/useFocusWithin.d.ts +1 -0
- package/dist/esm/lib/index.d.ts +4 -2
- package/dist/esm/util/testUtils/customRender.js +1 -1
- package/package.json +2 -1
- package/src/index.tsx +4 -1
- package/src/lib/components/modal/fullScreenModal/index.tsx +24 -0
- package/src/lib/components/modal/fullScreenModal/style.module.scss +49 -0
- package/src/lib/components/modal/genericModal/index.tsx +71 -78
- package/src/lib/components/modal/hooks/useOnClose.ts +10 -8
- package/src/lib/components/modal/index.stories.tsx +54 -6
- package/src/lib/components/modal/index.ts +2 -1
- package/src/lib/hooks/useEscapeKey.ts +18 -0
- package/src/lib/hooks/useFocusWithin.ts +22 -0
- package/src/lib/index.tsx +6 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as __assign, b as __rest } from '../../../tslib.es6-a39f91fc.js';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import React__default, { useState, useCallback, useEffect, createContext, PureComponent, useRef } from 'react';
|
|
4
5
|
import { s as styleInject } from '../../../style-inject.es-1f59c1d0.js';
|
|
5
6
|
import { c as classNames } from '../../../index-6ea95111.js';
|
|
6
7
|
import { Button } from '../../button/index.js';
|
|
7
8
|
import XIcon from '../../icon/icons/X.js';
|
|
9
|
+
import { P as PropTypes, p as propTypes$1 } from '../../../index-171a0108.js';
|
|
8
10
|
import '../../icon/IconWrapper/IconWrapper.js';
|
|
11
|
+
import '../../../index-dd80248b.js';
|
|
9
12
|
|
|
10
13
|
var useOnClose = function (onClose, isOpen, dismissable) {
|
|
11
14
|
var _a = useState(false), isVisible = _a[0], setIsVisible = _a[1];
|
|
@@ -27,12 +30,9 @@ var useOnClose = function (onClose, isOpen, dismissable) {
|
|
|
27
30
|
handleOnClose();
|
|
28
31
|
}, [dismissable, handleOnClose]);
|
|
29
32
|
var handleEscKey = useCallback(function (e) {
|
|
30
|
-
if (e.code !== 'Escape')
|
|
31
|
-
return;
|
|
32
|
-
if (!dismissable)
|
|
33
|
-
return null;
|
|
34
|
-
if (!isOpen)
|
|
33
|
+
if (e.code !== 'Escape' || !dismissable || !isOpen) {
|
|
35
34
|
return null;
|
|
35
|
+
}
|
|
36
36
|
handleOnClose();
|
|
37
37
|
}, [isOpen, dismissable, handleOnClose]);
|
|
38
38
|
useEffect(function () {
|
|
@@ -62,7 +62,7 @@ var useOnClose = function (onClose, isOpen, dismissable) {
|
|
|
62
62
|
handleContainerClick: handleContainerClick,
|
|
63
63
|
handleOnCloseAnimationEnded: handleOnCloseAnimationEnded,
|
|
64
64
|
handleOnClose: handleOnClose,
|
|
65
|
-
handleOnOverlayClick: handleOnOverlayClick
|
|
65
|
+
handleOnOverlayClick: handleOnOverlayClick,
|
|
66
66
|
};
|
|
67
67
|
};
|
|
68
68
|
|
|
@@ -70,6 +70,1744 @@ var css_248z = "@keyframes style-module_fade-in__f_VRg {\n 0% {\n background
|
|
|
70
70
|
var styles = {"overlay":"style-module_overlay__2f00R","fade-in":"style-module_fade-in__f_VRg","overlayClose":"style-module_overlayClose__1p313","fade-out":"style-module_fade-out__1tEwS","header":"style-module_header__284Rz","closeButton":"style-module_closeButton__1AbX8","body":"style-module_body__QtlTn","footer":"style-module_footer__Sh5bv"};
|
|
71
71
|
styleInject(css_248z);
|
|
72
72
|
|
|
73
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
74
|
+
if (null == r) return {};
|
|
75
|
+
var t = {};
|
|
76
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
77
|
+
if (e.includes(n)) continue;
|
|
78
|
+
t[n] = r[n];
|
|
79
|
+
}
|
|
80
|
+
return t;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function _extends() {
|
|
84
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
|
85
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
86
|
+
var t = arguments[e];
|
|
87
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
88
|
+
}
|
|
89
|
+
return n;
|
|
90
|
+
}, _extends.apply(null, arguments);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* defines a focus group
|
|
95
|
+
*/
|
|
96
|
+
var FOCUS_GROUP = 'data-focus-lock';
|
|
97
|
+
/**
|
|
98
|
+
* disables element discovery inside a group marked by key
|
|
99
|
+
*/
|
|
100
|
+
var FOCUS_DISABLED = 'data-focus-lock-disabled';
|
|
101
|
+
/**
|
|
102
|
+
* allows uncontrolled focus within the marked area, effectively disabling focus lock for it's content
|
|
103
|
+
*/
|
|
104
|
+
var FOCUS_ALLOW = 'data-no-focus-lock';
|
|
105
|
+
/**
|
|
106
|
+
* instructs autofocus engine to pick default autofocus inside a given node
|
|
107
|
+
* can be set on the element or container
|
|
108
|
+
*/
|
|
109
|
+
var FOCUS_AUTO = 'data-autofocus-inside';
|
|
110
|
+
/**
|
|
111
|
+
* instructs autofocus to ignore elements within a given node
|
|
112
|
+
* can be set on the element or container
|
|
113
|
+
*/
|
|
114
|
+
var FOCUS_NO_AUTOFOCUS = 'data-no-autofocus';
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Assigns a value for a given ref, no matter of the ref format
|
|
118
|
+
* @param {RefObject} ref - a callback function or ref object
|
|
119
|
+
* @param value - a new value
|
|
120
|
+
*
|
|
121
|
+
* @see https://github.com/theKashey/use-callback-ref#assignref
|
|
122
|
+
* @example
|
|
123
|
+
* const refObject = useRef();
|
|
124
|
+
* const refFn = (ref) => {....}
|
|
125
|
+
*
|
|
126
|
+
* assignRef(refObject, "refValue");
|
|
127
|
+
* assignRef(refFn, "refValue");
|
|
128
|
+
*/
|
|
129
|
+
function assignRef(ref, value) {
|
|
130
|
+
if (typeof ref === 'function') {
|
|
131
|
+
ref(value);
|
|
132
|
+
}
|
|
133
|
+
else if (ref) {
|
|
134
|
+
ref.current = value;
|
|
135
|
+
}
|
|
136
|
+
return ref;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* creates a MutableRef with ref change callback
|
|
141
|
+
* @param initialValue - initial ref value
|
|
142
|
+
* @param {Function} callback - a callback to run when value changes
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* const ref = useCallbackRef(0, (newValue, oldValue) => console.log(oldValue, '->', newValue);
|
|
146
|
+
* ref.current = 1;
|
|
147
|
+
* // prints 0 -> 1
|
|
148
|
+
*
|
|
149
|
+
* @see https://reactjs.org/docs/hooks-reference.html#useref
|
|
150
|
+
* @see https://github.com/theKashey/use-callback-ref#usecallbackref---to-replace-reactuseref
|
|
151
|
+
* @returns {MutableRefObject}
|
|
152
|
+
*/
|
|
153
|
+
function useCallbackRef(initialValue, callback) {
|
|
154
|
+
var ref = useState(function () { return ({
|
|
155
|
+
// value
|
|
156
|
+
value: initialValue,
|
|
157
|
+
// last callback
|
|
158
|
+
callback: callback,
|
|
159
|
+
// "memoized" public interface
|
|
160
|
+
facade: {
|
|
161
|
+
get current() {
|
|
162
|
+
return ref.value;
|
|
163
|
+
},
|
|
164
|
+
set current(value) {
|
|
165
|
+
var last = ref.value;
|
|
166
|
+
if (last !== value) {
|
|
167
|
+
ref.value = value;
|
|
168
|
+
ref.callback(value, last);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
}); })[0];
|
|
173
|
+
// update callback
|
|
174
|
+
ref.callback = callback;
|
|
175
|
+
return ref.facade;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
var useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
179
|
+
var currentValues = new WeakMap();
|
|
180
|
+
/**
|
|
181
|
+
* Merges two or more refs together providing a single interface to set their value
|
|
182
|
+
* @param {RefObject|Ref} refs
|
|
183
|
+
* @returns {MutableRefObject} - a new ref, which translates all changes to {refs}
|
|
184
|
+
*
|
|
185
|
+
* @see {@link mergeRefs} a version without buit-in memoization
|
|
186
|
+
* @see https://github.com/theKashey/use-callback-ref#usemergerefs
|
|
187
|
+
* @example
|
|
188
|
+
* const Component = React.forwardRef((props, ref) => {
|
|
189
|
+
* const ownRef = useRef();
|
|
190
|
+
* const domRef = useMergeRefs([ref, ownRef]); // 👈 merge together
|
|
191
|
+
* return <div ref={domRef}>...</div>
|
|
192
|
+
* }
|
|
193
|
+
*/
|
|
194
|
+
function useMergeRefs(refs, defaultValue) {
|
|
195
|
+
var callbackRef = useCallbackRef(defaultValue || null, function (newValue) {
|
|
196
|
+
return refs.forEach(function (ref) { return assignRef(ref, newValue); });
|
|
197
|
+
});
|
|
198
|
+
// handle refs changes - added or removed
|
|
199
|
+
useIsomorphicLayoutEffect(function () {
|
|
200
|
+
var oldValue = currentValues.get(callbackRef);
|
|
201
|
+
if (oldValue) {
|
|
202
|
+
var prevRefs_1 = new Set(oldValue);
|
|
203
|
+
var nextRefs_1 = new Set(refs);
|
|
204
|
+
var current_1 = callbackRef.current;
|
|
205
|
+
prevRefs_1.forEach(function (ref) {
|
|
206
|
+
if (!nextRefs_1.has(ref)) {
|
|
207
|
+
assignRef(ref, null);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
nextRefs_1.forEach(function (ref) {
|
|
211
|
+
if (!prevRefs_1.has(ref)) {
|
|
212
|
+
assignRef(ref, current_1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
currentValues.set(callbackRef, refs);
|
|
217
|
+
}, [refs]);
|
|
218
|
+
return callbackRef;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
var hiddenGuard = {
|
|
222
|
+
width: '1px',
|
|
223
|
+
height: '0px',
|
|
224
|
+
padding: 0,
|
|
225
|
+
overflow: 'hidden',
|
|
226
|
+
position: 'fixed',
|
|
227
|
+
top: '1px',
|
|
228
|
+
left: '1px'
|
|
229
|
+
};
|
|
230
|
+
process.env.NODE_ENV !== "production" ? {
|
|
231
|
+
children: PropTypes.node
|
|
232
|
+
} : {};
|
|
233
|
+
|
|
234
|
+
function ItoI(a) {
|
|
235
|
+
return a;
|
|
236
|
+
}
|
|
237
|
+
function innerCreateMedium(defaults, middleware) {
|
|
238
|
+
if (middleware === void 0) { middleware = ItoI; }
|
|
239
|
+
var buffer = [];
|
|
240
|
+
var assigned = false;
|
|
241
|
+
var medium = {
|
|
242
|
+
read: function () {
|
|
243
|
+
if (assigned) {
|
|
244
|
+
throw new Error('Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.');
|
|
245
|
+
}
|
|
246
|
+
if (buffer.length) {
|
|
247
|
+
return buffer[buffer.length - 1];
|
|
248
|
+
}
|
|
249
|
+
return defaults;
|
|
250
|
+
},
|
|
251
|
+
useMedium: function (data) {
|
|
252
|
+
var item = middleware(data, assigned);
|
|
253
|
+
buffer.push(item);
|
|
254
|
+
return function () {
|
|
255
|
+
buffer = buffer.filter(function (x) { return x !== item; });
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
assignSyncMedium: function (cb) {
|
|
259
|
+
assigned = true;
|
|
260
|
+
while (buffer.length) {
|
|
261
|
+
var cbs = buffer;
|
|
262
|
+
buffer = [];
|
|
263
|
+
cbs.forEach(cb);
|
|
264
|
+
}
|
|
265
|
+
buffer = {
|
|
266
|
+
push: function (x) { return cb(x); },
|
|
267
|
+
filter: function () { return buffer; },
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
assignMedium: function (cb) {
|
|
271
|
+
assigned = true;
|
|
272
|
+
var pendingQueue = [];
|
|
273
|
+
if (buffer.length) {
|
|
274
|
+
var cbs = buffer;
|
|
275
|
+
buffer = [];
|
|
276
|
+
cbs.forEach(cb);
|
|
277
|
+
pendingQueue = buffer;
|
|
278
|
+
}
|
|
279
|
+
var executeQueue = function () {
|
|
280
|
+
var cbs = pendingQueue;
|
|
281
|
+
pendingQueue = [];
|
|
282
|
+
cbs.forEach(cb);
|
|
283
|
+
};
|
|
284
|
+
var cycle = function () { return Promise.resolve().then(executeQueue); };
|
|
285
|
+
cycle();
|
|
286
|
+
buffer = {
|
|
287
|
+
push: function (x) {
|
|
288
|
+
pendingQueue.push(x);
|
|
289
|
+
cycle();
|
|
290
|
+
},
|
|
291
|
+
filter: function (filter) {
|
|
292
|
+
pendingQueue = pendingQueue.filter(filter);
|
|
293
|
+
return buffer;
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
return medium;
|
|
299
|
+
}
|
|
300
|
+
function createMedium(defaults, middleware) {
|
|
301
|
+
if (middleware === void 0) { middleware = ItoI; }
|
|
302
|
+
return innerCreateMedium(defaults, middleware);
|
|
303
|
+
}
|
|
304
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
305
|
+
function createSidecarMedium(options) {
|
|
306
|
+
if (options === void 0) { options = {}; }
|
|
307
|
+
var medium = innerCreateMedium(null);
|
|
308
|
+
medium.options = __assign({ async: true, ssr: false }, options);
|
|
309
|
+
return medium;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
var mediumFocus = createMedium({}, function (_ref) {
|
|
313
|
+
var target = _ref.target,
|
|
314
|
+
currentTarget = _ref.currentTarget;
|
|
315
|
+
return {
|
|
316
|
+
target: target,
|
|
317
|
+
currentTarget: currentTarget
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
var mediumBlur = createMedium();
|
|
321
|
+
var mediumEffect = createMedium();
|
|
322
|
+
var mediumSidecar = createSidecarMedium({
|
|
323
|
+
async: true,
|
|
324
|
+
ssr: typeof document !== 'undefined'
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
var focusScope = /*#__PURE__*/createContext(undefined);
|
|
328
|
+
|
|
329
|
+
var emptyArray = [];
|
|
330
|
+
var FocusLock = /*#__PURE__*/React.forwardRef(function FocusLockUI(props, parentRef) {
|
|
331
|
+
var _extends2;
|
|
332
|
+
var _React$useState = React.useState(),
|
|
333
|
+
realObserved = _React$useState[0],
|
|
334
|
+
setObserved = _React$useState[1];
|
|
335
|
+
var observed = React.useRef();
|
|
336
|
+
var isActive = React.useRef(false);
|
|
337
|
+
var originalFocusedElement = React.useRef(null);
|
|
338
|
+
var _React$useState2 = React.useState({}),
|
|
339
|
+
update = _React$useState2[1];
|
|
340
|
+
var children = props.children,
|
|
341
|
+
_props$disabled = props.disabled,
|
|
342
|
+
disabled = _props$disabled === void 0 ? false : _props$disabled,
|
|
343
|
+
_props$noFocusGuards = props.noFocusGuards,
|
|
344
|
+
noFocusGuards = _props$noFocusGuards === void 0 ? false : _props$noFocusGuards,
|
|
345
|
+
_props$persistentFocu = props.persistentFocus,
|
|
346
|
+
persistentFocus = _props$persistentFocu === void 0 ? false : _props$persistentFocu,
|
|
347
|
+
_props$crossFrame = props.crossFrame,
|
|
348
|
+
crossFrame = _props$crossFrame === void 0 ? true : _props$crossFrame,
|
|
349
|
+
_props$autoFocus = props.autoFocus,
|
|
350
|
+
autoFocus = _props$autoFocus === void 0 ? true : _props$autoFocus,
|
|
351
|
+
allowTextSelection = props.allowTextSelection,
|
|
352
|
+
group = props.group,
|
|
353
|
+
className = props.className,
|
|
354
|
+
whiteList = props.whiteList,
|
|
355
|
+
hasPositiveIndices = props.hasPositiveIndices,
|
|
356
|
+
_props$shards = props.shards,
|
|
357
|
+
shards = _props$shards === void 0 ? emptyArray : _props$shards,
|
|
358
|
+
_props$as = props.as,
|
|
359
|
+
Container = _props$as === void 0 ? 'div' : _props$as,
|
|
360
|
+
_props$lockProps = props.lockProps,
|
|
361
|
+
containerProps = _props$lockProps === void 0 ? {} : _props$lockProps,
|
|
362
|
+
SideCar = props.sideCar,
|
|
363
|
+
_props$returnFocus = props.returnFocus,
|
|
364
|
+
shouldReturnFocus = _props$returnFocus === void 0 ? false : _props$returnFocus,
|
|
365
|
+
focusOptions = props.focusOptions,
|
|
366
|
+
onActivationCallback = props.onActivation,
|
|
367
|
+
onDeactivationCallback = props.onDeactivation;
|
|
368
|
+
var _React$useState3 = React.useState({}),
|
|
369
|
+
id = _React$useState3[0];
|
|
370
|
+
var onActivation = React.useCallback(function (_ref) {
|
|
371
|
+
var captureFocusRestore = _ref.captureFocusRestore;
|
|
372
|
+
if (!originalFocusedElement.current) {
|
|
373
|
+
var _document;
|
|
374
|
+
var activeElement = (_document = document) == null ? void 0 : _document.activeElement;
|
|
375
|
+
originalFocusedElement.current = activeElement;
|
|
376
|
+
if (activeElement !== document.body) {
|
|
377
|
+
originalFocusedElement.current = captureFocusRestore(activeElement);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (observed.current && onActivationCallback) {
|
|
381
|
+
onActivationCallback(observed.current);
|
|
382
|
+
}
|
|
383
|
+
isActive.current = true;
|
|
384
|
+
update();
|
|
385
|
+
}, [onActivationCallback]);
|
|
386
|
+
var onDeactivation = React.useCallback(function () {
|
|
387
|
+
isActive.current = false;
|
|
388
|
+
if (onDeactivationCallback) {
|
|
389
|
+
onDeactivationCallback(observed.current);
|
|
390
|
+
}
|
|
391
|
+
update();
|
|
392
|
+
}, [onDeactivationCallback]);
|
|
393
|
+
var returnFocus = React.useCallback(function (allowDefer) {
|
|
394
|
+
var focusRestore = originalFocusedElement.current;
|
|
395
|
+
if (focusRestore) {
|
|
396
|
+
var returnFocusTo = (typeof focusRestore === 'function' ? focusRestore() : focusRestore) || document.body;
|
|
397
|
+
var howToReturnFocus = typeof shouldReturnFocus === 'function' ? shouldReturnFocus(returnFocusTo) : shouldReturnFocus;
|
|
398
|
+
if (howToReturnFocus) {
|
|
399
|
+
var returnFocusOptions = typeof howToReturnFocus === 'object' ? howToReturnFocus : undefined;
|
|
400
|
+
originalFocusedElement.current = null;
|
|
401
|
+
if (allowDefer) {
|
|
402
|
+
Promise.resolve().then(function () {
|
|
403
|
+
return returnFocusTo.focus(returnFocusOptions);
|
|
404
|
+
});
|
|
405
|
+
} else {
|
|
406
|
+
returnFocusTo.focus(returnFocusOptions);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}, [shouldReturnFocus]);
|
|
411
|
+
var onFocus = React.useCallback(function (event) {
|
|
412
|
+
if (isActive.current) {
|
|
413
|
+
mediumFocus.useMedium(event);
|
|
414
|
+
}
|
|
415
|
+
}, []);
|
|
416
|
+
var onBlur = mediumBlur.useMedium;
|
|
417
|
+
var setObserveNode = React.useCallback(function (newObserved) {
|
|
418
|
+
if (observed.current !== newObserved) {
|
|
419
|
+
observed.current = newObserved;
|
|
420
|
+
setObserved(newObserved);
|
|
421
|
+
}
|
|
422
|
+
}, []);
|
|
423
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
424
|
+
if (typeof allowTextSelection !== 'undefined') {
|
|
425
|
+
console.warn('React-Focus-Lock: allowTextSelection is deprecated and enabled by default');
|
|
426
|
+
}
|
|
427
|
+
React.useEffect(function () {
|
|
428
|
+
if (!observed.current && typeof Container !== 'string') {
|
|
429
|
+
console.error('FocusLock: could not obtain ref to internal node');
|
|
430
|
+
}
|
|
431
|
+
}, []);
|
|
432
|
+
}
|
|
433
|
+
var lockProps = _extends((_extends2 = {}, _extends2[FOCUS_DISABLED] = disabled && 'disabled', _extends2[FOCUS_GROUP] = group, _extends2), containerProps);
|
|
434
|
+
var hasLeadingGuards = noFocusGuards !== true;
|
|
435
|
+
var hasTailingGuards = hasLeadingGuards && noFocusGuards !== 'tail';
|
|
436
|
+
var mergedRef = useMergeRefs([parentRef, setObserveNode]);
|
|
437
|
+
var focusScopeValue = React.useMemo(function () {
|
|
438
|
+
return {
|
|
439
|
+
observed: observed,
|
|
440
|
+
shards: shards,
|
|
441
|
+
enabled: !disabled,
|
|
442
|
+
active: isActive.current
|
|
443
|
+
};
|
|
444
|
+
}, [disabled, isActive.current, shards, realObserved]);
|
|
445
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, hasLeadingGuards && [
|
|
446
|
+
/*#__PURE__*/
|
|
447
|
+
React.createElement("div", {
|
|
448
|
+
key: "guard-first",
|
|
449
|
+
"data-focus-guard": true,
|
|
450
|
+
tabIndex: disabled ? -1 : 0,
|
|
451
|
+
style: hiddenGuard
|
|
452
|
+
}), hasPositiveIndices ? /*#__PURE__*/React.createElement("div", {
|
|
453
|
+
key: "guard-nearest",
|
|
454
|
+
"data-focus-guard": true,
|
|
455
|
+
tabIndex: disabled ? -1 : 1,
|
|
456
|
+
style: hiddenGuard
|
|
457
|
+
}) : null], !disabled && /*#__PURE__*/React.createElement(SideCar, {
|
|
458
|
+
id: id,
|
|
459
|
+
sideCar: mediumSidecar,
|
|
460
|
+
observed: realObserved,
|
|
461
|
+
disabled: disabled,
|
|
462
|
+
persistentFocus: persistentFocus,
|
|
463
|
+
crossFrame: crossFrame,
|
|
464
|
+
autoFocus: autoFocus,
|
|
465
|
+
whiteList: whiteList,
|
|
466
|
+
shards: shards,
|
|
467
|
+
onActivation: onActivation,
|
|
468
|
+
onDeactivation: onDeactivation,
|
|
469
|
+
returnFocus: returnFocus,
|
|
470
|
+
focusOptions: focusOptions,
|
|
471
|
+
noFocusGuards: noFocusGuards
|
|
472
|
+
}), /*#__PURE__*/React.createElement(Container, _extends({
|
|
473
|
+
ref: mergedRef
|
|
474
|
+
}, lockProps, {
|
|
475
|
+
className: className,
|
|
476
|
+
onBlur: onBlur,
|
|
477
|
+
onFocus: onFocus
|
|
478
|
+
}), /*#__PURE__*/React.createElement(focusScope.Provider, {
|
|
479
|
+
value: focusScopeValue
|
|
480
|
+
}, children)), hasTailingGuards && /*#__PURE__*/React.createElement("div", {
|
|
481
|
+
"data-focus-guard": true,
|
|
482
|
+
tabIndex: disabled ? -1 : 0,
|
|
483
|
+
style: hiddenGuard
|
|
484
|
+
}));
|
|
485
|
+
});
|
|
486
|
+
FocusLock.propTypes = process.env.NODE_ENV !== "production" ? {
|
|
487
|
+
children: propTypes$1.exports.node,
|
|
488
|
+
disabled: propTypes$1.exports.bool,
|
|
489
|
+
returnFocus: propTypes$1.exports.oneOfType([propTypes$1.exports.bool, propTypes$1.exports.object, propTypes$1.exports.func]),
|
|
490
|
+
focusOptions: propTypes$1.exports.object,
|
|
491
|
+
noFocusGuards: propTypes$1.exports.bool,
|
|
492
|
+
hasPositiveIndices: propTypes$1.exports.bool,
|
|
493
|
+
allowTextSelection: propTypes$1.exports.bool,
|
|
494
|
+
autoFocus: propTypes$1.exports.bool,
|
|
495
|
+
persistentFocus: propTypes$1.exports.bool,
|
|
496
|
+
crossFrame: propTypes$1.exports.bool,
|
|
497
|
+
group: propTypes$1.exports.string,
|
|
498
|
+
className: propTypes$1.exports.string,
|
|
499
|
+
whiteList: propTypes$1.exports.func,
|
|
500
|
+
shards: propTypes$1.exports.arrayOf(propTypes$1.exports.any),
|
|
501
|
+
as: propTypes$1.exports.oneOfType([propTypes$1.exports.string, propTypes$1.exports.func, propTypes$1.exports.object]),
|
|
502
|
+
lockProps: propTypes$1.exports.object,
|
|
503
|
+
onActivation: propTypes$1.exports.func,
|
|
504
|
+
onDeactivation: propTypes$1.exports.func,
|
|
505
|
+
sideCar: propTypes$1.exports.any.isRequired
|
|
506
|
+
} : {};
|
|
507
|
+
|
|
508
|
+
function _setPrototypeOf(t, e) {
|
|
509
|
+
return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
|
|
510
|
+
return t.__proto__ = e, t;
|
|
511
|
+
}, _setPrototypeOf(t, e);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function _inheritsLoose(t, o) {
|
|
515
|
+
t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function _typeof(o) {
|
|
519
|
+
"@babel/helpers - typeof";
|
|
520
|
+
|
|
521
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
|
|
522
|
+
return typeof o;
|
|
523
|
+
} : function (o) {
|
|
524
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
525
|
+
}, _typeof(o);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function toPrimitive(t, r) {
|
|
529
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
530
|
+
var e = t[Symbol.toPrimitive];
|
|
531
|
+
if (void 0 !== e) {
|
|
532
|
+
var i = e.call(t, r || "default");
|
|
533
|
+
if ("object" != _typeof(i)) return i;
|
|
534
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
535
|
+
}
|
|
536
|
+
return ("string" === r ? String : Number)(t);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function toPropertyKey(t) {
|
|
540
|
+
var i = toPrimitive(t, "string");
|
|
541
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function _defineProperty(e, r, t) {
|
|
545
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
546
|
+
value: t,
|
|
547
|
+
enumerable: !0,
|
|
548
|
+
configurable: !0,
|
|
549
|
+
writable: !0
|
|
550
|
+
}) : e[r] = t, e;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function withSideEffect(reducePropsToState, handleStateChangeOnClient) {
|
|
554
|
+
if (process.env.NODE_ENV !== "production") {
|
|
555
|
+
if (typeof reducePropsToState !== 'function') {
|
|
556
|
+
throw new Error('Expected reducePropsToState to be a function.');
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (typeof handleStateChangeOnClient !== 'function') {
|
|
560
|
+
throw new Error('Expected handleStateChangeOnClient to be a function.');
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
function getDisplayName(WrappedComponent) {
|
|
565
|
+
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return function wrap(WrappedComponent) {
|
|
569
|
+
if (process.env.NODE_ENV !== "production") {
|
|
570
|
+
if (typeof WrappedComponent !== 'function') {
|
|
571
|
+
throw new Error('Expected WrappedComponent to be a React component.');
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
var mountedInstances = [];
|
|
576
|
+
var state;
|
|
577
|
+
|
|
578
|
+
function emitChange() {
|
|
579
|
+
state = reducePropsToState(mountedInstances.map(function (instance) {
|
|
580
|
+
return instance.props;
|
|
581
|
+
}));
|
|
582
|
+
handleStateChangeOnClient(state);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
var SideEffect = /*#__PURE__*/function (_PureComponent) {
|
|
586
|
+
_inheritsLoose(SideEffect, _PureComponent);
|
|
587
|
+
|
|
588
|
+
function SideEffect() {
|
|
589
|
+
return _PureComponent.apply(this, arguments) || this;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Try to use displayName of wrapped component
|
|
593
|
+
SideEffect.peek = function peek() {
|
|
594
|
+
return state;
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
var _proto = SideEffect.prototype;
|
|
598
|
+
|
|
599
|
+
_proto.componentDidMount = function componentDidMount() {
|
|
600
|
+
mountedInstances.push(this);
|
|
601
|
+
emitChange();
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
_proto.componentDidUpdate = function componentDidUpdate() {
|
|
605
|
+
emitChange();
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
609
|
+
var index = mountedInstances.indexOf(this);
|
|
610
|
+
mountedInstances.splice(index, 1);
|
|
611
|
+
emitChange();
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
_proto.render = function render() {
|
|
615
|
+
return /*#__PURE__*/React__default.createElement(WrappedComponent, this.props);
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
return SideEffect;
|
|
619
|
+
}(PureComponent);
|
|
620
|
+
|
|
621
|
+
_defineProperty(SideEffect, "displayName", "SideEffect(" + getDisplayName(WrappedComponent) + ")");
|
|
622
|
+
|
|
623
|
+
return SideEffect;
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/*
|
|
628
|
+
IE11 support
|
|
629
|
+
*/
|
|
630
|
+
var toArray = function (a) {
|
|
631
|
+
var ret = Array(a.length);
|
|
632
|
+
for (var i = 0; i < a.length; ++i) {
|
|
633
|
+
ret[i] = a[i];
|
|
634
|
+
}
|
|
635
|
+
return ret;
|
|
636
|
+
};
|
|
637
|
+
var asArray = function (a) { return (Array.isArray(a) ? a : [a]); };
|
|
638
|
+
var getFirst = function (a) { return (Array.isArray(a) ? a[0] : a); };
|
|
639
|
+
|
|
640
|
+
var isElementHidden = function (node) {
|
|
641
|
+
// we can measure only "elements"
|
|
642
|
+
// consider others as "visible"
|
|
643
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
var computedStyle = window.getComputedStyle(node, null);
|
|
647
|
+
if (!computedStyle || !computedStyle.getPropertyValue) {
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
return (computedStyle.getPropertyValue('display') === 'none' || computedStyle.getPropertyValue('visibility') === 'hidden');
|
|
651
|
+
};
|
|
652
|
+
var getParentNode = function (node) {
|
|
653
|
+
// DOCUMENT_FRAGMENT_NODE can also point on ShadowRoot. In this case .host will point on the next node
|
|
654
|
+
return node.parentNode && node.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
|
655
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
656
|
+
node.parentNode.host
|
|
657
|
+
: node.parentNode;
|
|
658
|
+
};
|
|
659
|
+
var isTopNode = function (node) {
|
|
660
|
+
// @ts-ignore
|
|
661
|
+
return node === document || (node && node.nodeType === Node.DOCUMENT_NODE);
|
|
662
|
+
};
|
|
663
|
+
var isInert = function (node) { return node.hasAttribute('inert'); };
|
|
664
|
+
/**
|
|
665
|
+
* @see https://github.com/testing-library/jest-dom/blob/main/src/to-be-visible.js
|
|
666
|
+
*/
|
|
667
|
+
var isVisibleUncached = function (node, checkParent) {
|
|
668
|
+
return !node || isTopNode(node) || (!isElementHidden(node) && !isInert(node) && checkParent(getParentNode(node)));
|
|
669
|
+
};
|
|
670
|
+
var isVisibleCached = function (visibilityCache, node) {
|
|
671
|
+
var cached = visibilityCache.get(node);
|
|
672
|
+
if (cached !== undefined) {
|
|
673
|
+
return cached;
|
|
674
|
+
}
|
|
675
|
+
var result = isVisibleUncached(node, isVisibleCached.bind(undefined, visibilityCache));
|
|
676
|
+
visibilityCache.set(node, result);
|
|
677
|
+
return result;
|
|
678
|
+
};
|
|
679
|
+
var isAutoFocusAllowedUncached = function (node, checkParent) {
|
|
680
|
+
return node && !isTopNode(node) ? (isAutoFocusAllowed(node) ? checkParent(getParentNode(node)) : false) : true;
|
|
681
|
+
};
|
|
682
|
+
var isAutoFocusAllowedCached = function (cache, node) {
|
|
683
|
+
var cached = cache.get(node);
|
|
684
|
+
if (cached !== undefined) {
|
|
685
|
+
return cached;
|
|
686
|
+
}
|
|
687
|
+
var result = isAutoFocusAllowedUncached(node, isAutoFocusAllowedCached.bind(undefined, cache));
|
|
688
|
+
cache.set(node, result);
|
|
689
|
+
return result;
|
|
690
|
+
};
|
|
691
|
+
var getDataset = function (node) {
|
|
692
|
+
// @ts-ignore
|
|
693
|
+
return node.dataset;
|
|
694
|
+
};
|
|
695
|
+
var isHTMLButtonElement = function (node) { return node.tagName === 'BUTTON'; };
|
|
696
|
+
var isHTMLInputElement = function (node) { return node.tagName === 'INPUT'; };
|
|
697
|
+
var isRadioElement = function (node) {
|
|
698
|
+
return isHTMLInputElement(node) && node.type === 'radio';
|
|
699
|
+
};
|
|
700
|
+
var notHiddenInput = function (node) {
|
|
701
|
+
return !((isHTMLInputElement(node) || isHTMLButtonElement(node)) && (node.type === 'hidden' || node.disabled));
|
|
702
|
+
};
|
|
703
|
+
var isAutoFocusAllowed = function (node) {
|
|
704
|
+
var attribute = node.getAttribute(FOCUS_NO_AUTOFOCUS);
|
|
705
|
+
return ![true, 'true', ''].includes(attribute);
|
|
706
|
+
};
|
|
707
|
+
var isGuard = function (node) { var _a; return Boolean(node && ((_a = getDataset(node)) === null || _a === void 0 ? void 0 : _a.focusGuard)); };
|
|
708
|
+
var isNotAGuard = function (node) { return !isGuard(node); };
|
|
709
|
+
var isDefined = function (x) { return Boolean(x); };
|
|
710
|
+
|
|
711
|
+
var tabSort = function (a, b) {
|
|
712
|
+
var aTab = Math.max(0, a.tabIndex);
|
|
713
|
+
var bTab = Math.max(0, b.tabIndex);
|
|
714
|
+
var tabDiff = aTab - bTab;
|
|
715
|
+
var indexDiff = a.index - b.index;
|
|
716
|
+
if (tabDiff) {
|
|
717
|
+
if (!aTab) {
|
|
718
|
+
return 1;
|
|
719
|
+
}
|
|
720
|
+
if (!bTab) {
|
|
721
|
+
return -1;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
return tabDiff || indexDiff;
|
|
725
|
+
};
|
|
726
|
+
var getTabIndex = function (node) {
|
|
727
|
+
if (node.tabIndex < 0) {
|
|
728
|
+
// all "focusable" elements are already preselected
|
|
729
|
+
// but some might have implicit negative tabIndex
|
|
730
|
+
// return 0 for <audio without tabIndex attribute - it is "tabbable"
|
|
731
|
+
if (!node.hasAttribute('tabindex')) {
|
|
732
|
+
return 0;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return node.tabIndex;
|
|
736
|
+
};
|
|
737
|
+
var orderByTabIndex = function (nodes, filterNegative, keepGuards) {
|
|
738
|
+
return toArray(nodes)
|
|
739
|
+
.map(function (node, index) {
|
|
740
|
+
var tabIndex = getTabIndex(node);
|
|
741
|
+
return {
|
|
742
|
+
node: node,
|
|
743
|
+
index: index,
|
|
744
|
+
tabIndex: keepGuards && tabIndex === -1 ? ((node.dataset || {}).focusGuard ? 0 : -1) : tabIndex,
|
|
745
|
+
};
|
|
746
|
+
})
|
|
747
|
+
.filter(function (data) { return !filterNegative || data.tabIndex >= 0; })
|
|
748
|
+
.sort(tabSort);
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* list of the object to be considered as focusable
|
|
753
|
+
*/
|
|
754
|
+
var tabbables = [
|
|
755
|
+
'button:enabled',
|
|
756
|
+
'select:enabled',
|
|
757
|
+
'textarea:enabled',
|
|
758
|
+
'input:enabled',
|
|
759
|
+
// elements with explicit roles will also use explicit tabindex
|
|
760
|
+
// '[role="button"]',
|
|
761
|
+
'a[href]',
|
|
762
|
+
'area[href]',
|
|
763
|
+
'summary',
|
|
764
|
+
'iframe',
|
|
765
|
+
'object',
|
|
766
|
+
'embed',
|
|
767
|
+
'audio[controls]',
|
|
768
|
+
'video[controls]',
|
|
769
|
+
'[tabindex]',
|
|
770
|
+
'[contenteditable]',
|
|
771
|
+
'[autofocus]',
|
|
772
|
+
];
|
|
773
|
+
|
|
774
|
+
var queryTabbables = tabbables.join(',');
|
|
775
|
+
var queryGuardTabbables = "".concat(queryTabbables, ", [data-focus-guard]");
|
|
776
|
+
var getFocusablesWithShadowDom = function (parent, withGuards) {
|
|
777
|
+
return toArray((parent.shadowRoot || parent).children).reduce(function (acc, child) {
|
|
778
|
+
return acc.concat(child.matches(withGuards ? queryGuardTabbables : queryTabbables) ? [child] : [], getFocusablesWithShadowDom(child));
|
|
779
|
+
}, []);
|
|
780
|
+
};
|
|
781
|
+
var getFocusablesWithIFrame = function (parent, withGuards) {
|
|
782
|
+
var _a;
|
|
783
|
+
// contentDocument of iframe will be null if current origin cannot access it
|
|
784
|
+
if (parent instanceof HTMLIFrameElement && ((_a = parent.contentDocument) === null || _a === void 0 ? void 0 : _a.body)) {
|
|
785
|
+
return getFocusables([parent.contentDocument.body], withGuards);
|
|
786
|
+
}
|
|
787
|
+
return [parent];
|
|
788
|
+
};
|
|
789
|
+
var getFocusables = function (parents, withGuards) {
|
|
790
|
+
return parents.reduce(function (acc, parent) {
|
|
791
|
+
var _a;
|
|
792
|
+
var focusableWithShadowDom = getFocusablesWithShadowDom(parent, withGuards);
|
|
793
|
+
var focusableWithIframes = (_a = []).concat.apply(_a, focusableWithShadowDom.map(function (node) { return getFocusablesWithIFrame(node, withGuards); }));
|
|
794
|
+
return acc.concat(
|
|
795
|
+
// add all tabbables inside and within shadow DOMs in DOM order
|
|
796
|
+
focusableWithIframes,
|
|
797
|
+
// add if node is tabbable itself
|
|
798
|
+
parent.parentNode
|
|
799
|
+
? toArray(parent.parentNode.querySelectorAll(queryTabbables)).filter(function (node) { return node === parent; })
|
|
800
|
+
: []);
|
|
801
|
+
}, []);
|
|
802
|
+
};
|
|
803
|
+
/**
|
|
804
|
+
* return a list of focusable nodes within an area marked as "auto-focusable"
|
|
805
|
+
* @param parent
|
|
806
|
+
*/
|
|
807
|
+
var getParentAutofocusables = function (parent) {
|
|
808
|
+
var parentFocus = parent.querySelectorAll("[".concat(FOCUS_AUTO, "]"));
|
|
809
|
+
return toArray(parentFocus)
|
|
810
|
+
.map(function (node) { return getFocusables([node]); })
|
|
811
|
+
.reduce(function (acc, nodes) { return acc.concat(nodes); }, []);
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* given list of focusable elements keeps the ones user can interact with
|
|
816
|
+
* @param nodes
|
|
817
|
+
* @param visibilityCache
|
|
818
|
+
*/
|
|
819
|
+
var filterFocusable = function (nodes, visibilityCache) {
|
|
820
|
+
return toArray(nodes)
|
|
821
|
+
.filter(function (node) { return isVisibleCached(visibilityCache, node); })
|
|
822
|
+
.filter(function (node) { return notHiddenInput(node); });
|
|
823
|
+
};
|
|
824
|
+
var filterAutoFocusable = function (nodes, cache) {
|
|
825
|
+
if (cache === void 0) { cache = new Map(); }
|
|
826
|
+
return toArray(nodes).filter(function (node) { return isAutoFocusAllowedCached(cache, node); });
|
|
827
|
+
};
|
|
828
|
+
/**
|
|
829
|
+
* !__WARNING__! Low level API.
|
|
830
|
+
* @returns all tabbable nodes
|
|
831
|
+
*
|
|
832
|
+
* @see {@link getFocusableNodes} to get any focusable element
|
|
833
|
+
*
|
|
834
|
+
* @param topNodes - array of top level HTMLElements to search inside
|
|
835
|
+
* @param visibilityCache - an cache to store intermediate measurements. Expected to be a fresh `new Map` on every call
|
|
836
|
+
*/
|
|
837
|
+
var getTabbableNodes = function (topNodes, visibilityCache, withGuards) {
|
|
838
|
+
return orderByTabIndex(filterFocusable(getFocusables(topNodes, withGuards), visibilityCache), true, withGuards);
|
|
839
|
+
};
|
|
840
|
+
/**
|
|
841
|
+
* !__WARNING__! Low level API.
|
|
842
|
+
*
|
|
843
|
+
* @returns anything "focusable", not only tabbable. The difference is in `tabIndex=-1`
|
|
844
|
+
* (without guards, as long as they are not expected to be ever focused)
|
|
845
|
+
*
|
|
846
|
+
* @see {@link getTabbableNodes} to get only tabble nodes element
|
|
847
|
+
*
|
|
848
|
+
* @param topNodes - array of top level HTMLElements to search inside
|
|
849
|
+
* @param visibilityCache - an cache to store intermediate measurements. Expected to be a fresh `new Map` on every call
|
|
850
|
+
*/
|
|
851
|
+
var getFocusableNodes = function (topNodes, visibilityCache) {
|
|
852
|
+
return orderByTabIndex(filterFocusable(getFocusables(topNodes), visibilityCache), false);
|
|
853
|
+
};
|
|
854
|
+
/**
|
|
855
|
+
* return list of nodes which are expected to be auto-focused
|
|
856
|
+
* @param topNode
|
|
857
|
+
* @param visibilityCache
|
|
858
|
+
*/
|
|
859
|
+
var parentAutofocusables = function (topNode, visibilityCache) {
|
|
860
|
+
return filterFocusable(getParentAutofocusables(topNode), visibilityCache);
|
|
861
|
+
};
|
|
862
|
+
/*
|
|
863
|
+
* Determines if element is contained in scope, including nested shadow DOMs
|
|
864
|
+
*/
|
|
865
|
+
var contains = function (scope, element) {
|
|
866
|
+
if (scope.shadowRoot) {
|
|
867
|
+
return contains(scope.shadowRoot, element);
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
if (Object.getPrototypeOf(scope).contains !== undefined &&
|
|
871
|
+
Object.getPrototypeOf(scope).contains.call(scope, element)) {
|
|
872
|
+
return true;
|
|
873
|
+
}
|
|
874
|
+
return toArray(scope.children).some(function (child) {
|
|
875
|
+
var _a;
|
|
876
|
+
if (child instanceof HTMLIFrameElement) {
|
|
877
|
+
var iframeBody = (_a = child.contentDocument) === null || _a === void 0 ? void 0 : _a.body;
|
|
878
|
+
if (iframeBody) {
|
|
879
|
+
return contains(iframeBody, element);
|
|
880
|
+
}
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
return contains(child, element);
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* in case of multiple nodes nested inside each other
|
|
890
|
+
* keeps only top ones
|
|
891
|
+
* this is O(nlogn)
|
|
892
|
+
* @param nodes
|
|
893
|
+
* @returns {*}
|
|
894
|
+
*/
|
|
895
|
+
var filterNested = function (nodes) {
|
|
896
|
+
var contained = new Set();
|
|
897
|
+
var l = nodes.length;
|
|
898
|
+
for (var i = 0; i < l; i += 1) {
|
|
899
|
+
for (var j = i + 1; j < l; j += 1) {
|
|
900
|
+
var position = nodes[i].compareDocumentPosition(nodes[j]);
|
|
901
|
+
/* eslint-disable no-bitwise */
|
|
902
|
+
if ((position & Node.DOCUMENT_POSITION_CONTAINED_BY) > 0) {
|
|
903
|
+
contained.add(j);
|
|
904
|
+
}
|
|
905
|
+
if ((position & Node.DOCUMENT_POSITION_CONTAINS) > 0) {
|
|
906
|
+
contained.add(i);
|
|
907
|
+
}
|
|
908
|
+
/* eslint-enable */
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return nodes.filter(function (_, index) { return !contained.has(index); });
|
|
912
|
+
};
|
|
913
|
+
/**
|
|
914
|
+
* finds top most parent for a node
|
|
915
|
+
* @param node
|
|
916
|
+
* @returns {*}
|
|
917
|
+
*/
|
|
918
|
+
var getTopParent = function (node) {
|
|
919
|
+
return node.parentNode ? getTopParent(node.parentNode) : node;
|
|
920
|
+
};
|
|
921
|
+
/**
|
|
922
|
+
* returns all "focus containers" inside a given node
|
|
923
|
+
* @param node - node or nodes to look inside
|
|
924
|
+
* @returns Element[]
|
|
925
|
+
*/
|
|
926
|
+
var getAllAffectedNodes = function (node) {
|
|
927
|
+
var nodes = asArray(node);
|
|
928
|
+
return nodes.filter(Boolean).reduce(function (acc, currentNode) {
|
|
929
|
+
var group = currentNode.getAttribute(FOCUS_GROUP);
|
|
930
|
+
acc.push.apply(acc, (group
|
|
931
|
+
? filterNested(toArray(getTopParent(currentNode).querySelectorAll("[".concat(FOCUS_GROUP, "=\"").concat(group, "\"]:not([").concat(FOCUS_DISABLED, "=\"disabled\"])"))))
|
|
932
|
+
: [currentNode]));
|
|
933
|
+
return acc;
|
|
934
|
+
}, []);
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
var safeProbe = function (cb) {
|
|
938
|
+
try {
|
|
939
|
+
return cb();
|
|
940
|
+
}
|
|
941
|
+
catch (e) {
|
|
942
|
+
return undefined;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* returns active element from document or from nested shadowdoms
|
|
948
|
+
*/
|
|
949
|
+
/**
|
|
950
|
+
* returns current active element. If the active element is a "container" itself(shadowRoot or iframe) returns active element inside it
|
|
951
|
+
* @param [inDocument]
|
|
952
|
+
*/
|
|
953
|
+
var getActiveElement = function (inDocument) {
|
|
954
|
+
if (inDocument === void 0) { inDocument = document; }
|
|
955
|
+
if (!inDocument || !inDocument.activeElement) {
|
|
956
|
+
return undefined;
|
|
957
|
+
}
|
|
958
|
+
var activeElement = inDocument.activeElement;
|
|
959
|
+
return (activeElement.shadowRoot
|
|
960
|
+
? getActiveElement(activeElement.shadowRoot)
|
|
961
|
+
: activeElement instanceof HTMLIFrameElement && safeProbe(function () { return activeElement.contentWindow.document; })
|
|
962
|
+
? getActiveElement(activeElement.contentWindow.document)
|
|
963
|
+
: activeElement);
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
var focusInFrame = function (frame, activeElement) { return frame === activeElement; };
|
|
967
|
+
var focusInsideIframe = function (topNode, activeElement) {
|
|
968
|
+
return Boolean(toArray(topNode.querySelectorAll('iframe')).some(function (node) { return focusInFrame(node, activeElement); }));
|
|
969
|
+
};
|
|
970
|
+
/**
|
|
971
|
+
* @returns {Boolean} true, if the current focus is inside given node or nodes.
|
|
972
|
+
* Supports nodes hidden inside shadowDom
|
|
973
|
+
*/
|
|
974
|
+
var focusInside = function (topNode, activeElement) {
|
|
975
|
+
// const activeElement = document && getActiveElement();
|
|
976
|
+
if (activeElement === void 0) { activeElement = getActiveElement(getFirst(topNode).ownerDocument); }
|
|
977
|
+
if (!activeElement || (activeElement.dataset && activeElement.dataset.focusGuard)) {
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
return getAllAffectedNodes(topNode).some(function (node) {
|
|
981
|
+
return contains(node, activeElement) || focusInsideIframe(node, activeElement);
|
|
982
|
+
});
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* checks if focus is hidden FROM the focus-lock
|
|
987
|
+
* ie contained inside a node focus-lock shall ignore
|
|
988
|
+
*
|
|
989
|
+
* This is a utility function coupled with {@link FOCUS_ALLOW} constant
|
|
990
|
+
*
|
|
991
|
+
* @returns {boolean} focus is currently is in "allow" area
|
|
992
|
+
*/
|
|
993
|
+
var focusIsHidden = function (inDocument) {
|
|
994
|
+
if (inDocument === void 0) { inDocument = document; }
|
|
995
|
+
var activeElement = getActiveElement(inDocument);
|
|
996
|
+
if (!activeElement) {
|
|
997
|
+
return false;
|
|
998
|
+
}
|
|
999
|
+
// this does not support setting FOCUS_ALLOW within shadow dom
|
|
1000
|
+
return toArray(inDocument.querySelectorAll("[".concat(FOCUS_ALLOW, "]"))).some(function (node) { return contains(node, activeElement); });
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
var findSelectedRadio = function (node, nodes) {
|
|
1004
|
+
return nodes
|
|
1005
|
+
.filter(isRadioElement)
|
|
1006
|
+
.filter(function (el) { return el.name === node.name; })
|
|
1007
|
+
.filter(function (el) { return el.checked; })[0] || node;
|
|
1008
|
+
};
|
|
1009
|
+
var correctNode = function (node, nodes) {
|
|
1010
|
+
if (isRadioElement(node) && node.name) {
|
|
1011
|
+
return findSelectedRadio(node, nodes);
|
|
1012
|
+
}
|
|
1013
|
+
return node;
|
|
1014
|
+
};
|
|
1015
|
+
/**
|
|
1016
|
+
* giving a set of radio inputs keeps only selected (tabbable) ones
|
|
1017
|
+
* @param nodes
|
|
1018
|
+
*/
|
|
1019
|
+
var correctNodes = function (nodes) {
|
|
1020
|
+
// IE11 has no Set(array) constructor
|
|
1021
|
+
var resultSet = new Set();
|
|
1022
|
+
nodes.forEach(function (node) { return resultSet.add(correctNode(node, nodes)); });
|
|
1023
|
+
// using filter to support IE11
|
|
1024
|
+
return nodes.filter(function (node) { return resultSet.has(node); });
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
var pickFirstFocus = function (nodes) {
|
|
1028
|
+
if (nodes[0] && nodes.length > 1) {
|
|
1029
|
+
return correctNode(nodes[0], nodes);
|
|
1030
|
+
}
|
|
1031
|
+
return nodes[0];
|
|
1032
|
+
};
|
|
1033
|
+
var pickFocusable = function (nodes, node) {
|
|
1034
|
+
return nodes.indexOf(correctNode(node, nodes));
|
|
1035
|
+
};
|
|
1036
|
+
|
|
1037
|
+
var NEW_FOCUS = 'NEW_FOCUS';
|
|
1038
|
+
/**
|
|
1039
|
+
* Main solver for the "find next focus" question
|
|
1040
|
+
* @param innerNodes - used to control "return focus"
|
|
1041
|
+
* @param innerTabbables - used to control "autofocus"
|
|
1042
|
+
* @param outerNodes
|
|
1043
|
+
* @param activeElement
|
|
1044
|
+
* @param lastNode
|
|
1045
|
+
* @returns {number|string|undefined|*}
|
|
1046
|
+
*/
|
|
1047
|
+
var newFocus = function (innerNodes, innerTabbables, outerNodes, activeElement, lastNode) {
|
|
1048
|
+
var cnt = innerNodes.length;
|
|
1049
|
+
var firstFocus = innerNodes[0];
|
|
1050
|
+
var lastFocus = innerNodes[cnt - 1];
|
|
1051
|
+
var isOnGuard = isGuard(activeElement);
|
|
1052
|
+
// focus is inside
|
|
1053
|
+
if (activeElement && innerNodes.indexOf(activeElement) >= 0) {
|
|
1054
|
+
return undefined;
|
|
1055
|
+
}
|
|
1056
|
+
var activeIndex = activeElement !== undefined ? outerNodes.indexOf(activeElement) : -1;
|
|
1057
|
+
var lastIndex = lastNode ? outerNodes.indexOf(lastNode) : activeIndex;
|
|
1058
|
+
var lastNodeInside = lastNode ? innerNodes.indexOf(lastNode) : -1;
|
|
1059
|
+
// no active focus (or focus is on the body)
|
|
1060
|
+
if (activeIndex === -1) {
|
|
1061
|
+
// known fallback
|
|
1062
|
+
if (lastNodeInside !== -1) {
|
|
1063
|
+
return lastNodeInside;
|
|
1064
|
+
}
|
|
1065
|
+
return NEW_FOCUS;
|
|
1066
|
+
}
|
|
1067
|
+
// new focus, nothing to calculate
|
|
1068
|
+
if (lastNodeInside === -1) {
|
|
1069
|
+
return NEW_FOCUS;
|
|
1070
|
+
}
|
|
1071
|
+
var indexDiff = activeIndex - lastIndex;
|
|
1072
|
+
var firstNodeIndex = outerNodes.indexOf(firstFocus);
|
|
1073
|
+
var lastNodeIndex = outerNodes.indexOf(lastFocus);
|
|
1074
|
+
var correctedNodes = correctNodes(outerNodes);
|
|
1075
|
+
var correctedIndex = activeElement !== undefined ? correctedNodes.indexOf(activeElement) : -1;
|
|
1076
|
+
var correctedIndexDiff = correctedIndex - (lastNode ? correctedNodes.indexOf(lastNode) : activeIndex);
|
|
1077
|
+
// old focus
|
|
1078
|
+
if (!indexDiff && lastNodeInside >= 0) {
|
|
1079
|
+
return lastNodeInside;
|
|
1080
|
+
}
|
|
1081
|
+
// no tabbable elements, autofocus is not possible
|
|
1082
|
+
if (innerTabbables.length === 0) {
|
|
1083
|
+
// an edge case with no tabbable elements
|
|
1084
|
+
// return the last focusable one
|
|
1085
|
+
// with some probability this will prevent focus from cycling across the lock, but there is no tabbale elements to cycle to
|
|
1086
|
+
return lastNodeInside;
|
|
1087
|
+
}
|
|
1088
|
+
var returnFirstNode = pickFocusable(innerNodes, innerTabbables[0]);
|
|
1089
|
+
var returnLastNode = pickFocusable(innerNodes, innerTabbables[innerTabbables.length - 1]);
|
|
1090
|
+
// first element
|
|
1091
|
+
if (activeIndex <= firstNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
|
|
1092
|
+
return returnLastNode;
|
|
1093
|
+
}
|
|
1094
|
+
// last element
|
|
1095
|
+
if (activeIndex >= lastNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
|
|
1096
|
+
return returnFirstNode;
|
|
1097
|
+
}
|
|
1098
|
+
// jump out, but not on the guard
|
|
1099
|
+
if (indexDiff && Math.abs(correctedIndexDiff) > 1) {
|
|
1100
|
+
return lastNodeInside;
|
|
1101
|
+
}
|
|
1102
|
+
// focus above lock
|
|
1103
|
+
if (activeIndex <= firstNodeIndex) {
|
|
1104
|
+
return returnLastNode;
|
|
1105
|
+
}
|
|
1106
|
+
// focus below lock
|
|
1107
|
+
if (activeIndex > lastNodeIndex) {
|
|
1108
|
+
return returnFirstNode;
|
|
1109
|
+
}
|
|
1110
|
+
// index is inside tab order, but outside Lock
|
|
1111
|
+
if (indexDiff) {
|
|
1112
|
+
if (Math.abs(indexDiff) > 1) {
|
|
1113
|
+
return lastNodeInside;
|
|
1114
|
+
}
|
|
1115
|
+
return (cnt + lastNodeInside + indexDiff) % cnt;
|
|
1116
|
+
}
|
|
1117
|
+
// do nothing
|
|
1118
|
+
return undefined;
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
var findAutoFocused = function (autoFocusables) {
|
|
1122
|
+
return function (node) {
|
|
1123
|
+
var _a;
|
|
1124
|
+
var autofocus = (_a = getDataset(node)) === null || _a === void 0 ? void 0 : _a.autofocus;
|
|
1125
|
+
return (
|
|
1126
|
+
// @ts-expect-error
|
|
1127
|
+
node.autofocus ||
|
|
1128
|
+
//
|
|
1129
|
+
(autofocus !== undefined && autofocus !== 'false') ||
|
|
1130
|
+
//
|
|
1131
|
+
autoFocusables.indexOf(node) >= 0);
|
|
1132
|
+
};
|
|
1133
|
+
};
|
|
1134
|
+
var pickAutofocus = function (nodesIndexes, orderedNodes, groups) {
|
|
1135
|
+
var nodes = nodesIndexes.map(function (_a) {
|
|
1136
|
+
var node = _a.node;
|
|
1137
|
+
return node;
|
|
1138
|
+
});
|
|
1139
|
+
var autoFocusable = filterAutoFocusable(nodes.filter(findAutoFocused(groups)));
|
|
1140
|
+
if (autoFocusable && autoFocusable.length) {
|
|
1141
|
+
return pickFirstFocus(autoFocusable);
|
|
1142
|
+
}
|
|
1143
|
+
return pickFirstFocus(filterAutoFocusable(orderedNodes));
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
var getParents = function (node, parents) {
|
|
1147
|
+
if (parents === void 0) { parents = []; }
|
|
1148
|
+
parents.push(node);
|
|
1149
|
+
if (node.parentNode) {
|
|
1150
|
+
getParents(node.parentNode.host || node.parentNode, parents);
|
|
1151
|
+
}
|
|
1152
|
+
return parents;
|
|
1153
|
+
};
|
|
1154
|
+
/**
|
|
1155
|
+
* finds a parent for both nodeA and nodeB
|
|
1156
|
+
* @param nodeA
|
|
1157
|
+
* @param nodeB
|
|
1158
|
+
* @returns {boolean|*}
|
|
1159
|
+
*/
|
|
1160
|
+
var getCommonParent = function (nodeA, nodeB) {
|
|
1161
|
+
var parentsA = getParents(nodeA);
|
|
1162
|
+
var parentsB = getParents(nodeB);
|
|
1163
|
+
// tslint:disable-next-line:prefer-for-of
|
|
1164
|
+
for (var i = 0; i < parentsA.length; i += 1) {
|
|
1165
|
+
var currentParent = parentsA[i];
|
|
1166
|
+
if (parentsB.indexOf(currentParent) >= 0) {
|
|
1167
|
+
return currentParent;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return false;
|
|
1171
|
+
};
|
|
1172
|
+
var getTopCommonParent = function (baseActiveElement, leftEntry, rightEntries) {
|
|
1173
|
+
var activeElements = asArray(baseActiveElement);
|
|
1174
|
+
var leftEntries = asArray(leftEntry);
|
|
1175
|
+
var activeElement = activeElements[0];
|
|
1176
|
+
var topCommon = false;
|
|
1177
|
+
leftEntries.filter(Boolean).forEach(function (entry) {
|
|
1178
|
+
topCommon = getCommonParent(topCommon || entry, entry) || topCommon;
|
|
1179
|
+
rightEntries.filter(Boolean).forEach(function (subEntry) {
|
|
1180
|
+
var common = getCommonParent(activeElement, subEntry);
|
|
1181
|
+
if (common) {
|
|
1182
|
+
if (!topCommon || contains(common, topCommon)) {
|
|
1183
|
+
topCommon = common;
|
|
1184
|
+
}
|
|
1185
|
+
else {
|
|
1186
|
+
topCommon = getCommonParent(common, topCommon);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
1191
|
+
// TODO: add assert here?
|
|
1192
|
+
return topCommon;
|
|
1193
|
+
};
|
|
1194
|
+
/**
|
|
1195
|
+
* return list of nodes which are expected to be autofocused inside a given top nodes
|
|
1196
|
+
* @param entries
|
|
1197
|
+
* @param visibilityCache
|
|
1198
|
+
*/
|
|
1199
|
+
var allParentAutofocusables = function (entries, visibilityCache) {
|
|
1200
|
+
return entries.reduce(function (acc, node) { return acc.concat(parentAutofocusables(node, visibilityCache)); }, []);
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
var reorderNodes = function (srcNodes, dstNodes) {
|
|
1204
|
+
var remap = new Map();
|
|
1205
|
+
// no Set(dstNodes) for IE11 :(
|
|
1206
|
+
dstNodes.forEach(function (entity) { return remap.set(entity.node, entity); });
|
|
1207
|
+
// remap to dstNodes
|
|
1208
|
+
return srcNodes.map(function (node) { return remap.get(node); }).filter(isDefined);
|
|
1209
|
+
};
|
|
1210
|
+
/**
|
|
1211
|
+
* contains the main logic of the `focus-lock` package.
|
|
1212
|
+
*
|
|
1213
|
+
* ! you probably dont need this function !
|
|
1214
|
+
*
|
|
1215
|
+
* given top node(s) and the last active element returns the element to be focused next
|
|
1216
|
+
* @returns element which should be focused to move focus inside
|
|
1217
|
+
* @param topNode
|
|
1218
|
+
* @param lastNode
|
|
1219
|
+
*/
|
|
1220
|
+
var focusSolver = function (topNode, lastNode) {
|
|
1221
|
+
var activeElement = getActiveElement(asArray(topNode).length > 0 ? document : getFirst(topNode).ownerDocument);
|
|
1222
|
+
var entries = getAllAffectedNodes(topNode).filter(isNotAGuard);
|
|
1223
|
+
var commonParent = getTopCommonParent(activeElement || topNode, topNode, entries);
|
|
1224
|
+
var visibilityCache = new Map();
|
|
1225
|
+
var anyFocusable = getFocusableNodes(entries, visibilityCache);
|
|
1226
|
+
var innerElements = anyFocusable.filter(function (_a) {
|
|
1227
|
+
var node = _a.node;
|
|
1228
|
+
return isNotAGuard(node);
|
|
1229
|
+
});
|
|
1230
|
+
if (!innerElements[0]) {
|
|
1231
|
+
return undefined;
|
|
1232
|
+
}
|
|
1233
|
+
var outerNodes = getFocusableNodes([commonParent], visibilityCache).map(function (_a) {
|
|
1234
|
+
var node = _a.node;
|
|
1235
|
+
return node;
|
|
1236
|
+
});
|
|
1237
|
+
var orderedInnerElements = reorderNodes(outerNodes, innerElements);
|
|
1238
|
+
// collect inner focusable and separately tabbables
|
|
1239
|
+
var innerFocusables = orderedInnerElements.map(function (_a) {
|
|
1240
|
+
var node = _a.node;
|
|
1241
|
+
return node;
|
|
1242
|
+
});
|
|
1243
|
+
var innerTabbable = orderedInnerElements.filter(function (_a) {
|
|
1244
|
+
var tabIndex = _a.tabIndex;
|
|
1245
|
+
return tabIndex >= 0;
|
|
1246
|
+
}).map(function (_a) {
|
|
1247
|
+
var node = _a.node;
|
|
1248
|
+
return node;
|
|
1249
|
+
});
|
|
1250
|
+
var newId = newFocus(innerFocusables, innerTabbable, outerNodes, activeElement, lastNode);
|
|
1251
|
+
if (newId === NEW_FOCUS) {
|
|
1252
|
+
var focusNode =
|
|
1253
|
+
// first try only tabbable, and the fallback to all focusable, as long as at least one element should be picked for focus
|
|
1254
|
+
pickAutofocus(anyFocusable, innerTabbable, allParentAutofocusables(entries, visibilityCache)) ||
|
|
1255
|
+
pickAutofocus(anyFocusable, innerFocusables, allParentAutofocusables(entries, visibilityCache));
|
|
1256
|
+
if (focusNode) {
|
|
1257
|
+
return { node: focusNode };
|
|
1258
|
+
}
|
|
1259
|
+
else {
|
|
1260
|
+
console.warn('focus-lock: cannot find any node to move focus into');
|
|
1261
|
+
return undefined;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
if (newId === undefined) {
|
|
1265
|
+
return newId;
|
|
1266
|
+
}
|
|
1267
|
+
return orderedInnerElements[newId];
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information
|
|
1272
|
+
* This is low-level API!
|
|
1273
|
+
* @returns list of focusable elements inside a given top(!) node.
|
|
1274
|
+
* @see {@link getFocusableNodes} providing a simpler API
|
|
1275
|
+
*/
|
|
1276
|
+
var expandFocusableNodes = function (topNode) {
|
|
1277
|
+
var entries = getAllAffectedNodes(topNode).filter(isNotAGuard);
|
|
1278
|
+
var commonParent = getTopCommonParent(topNode, topNode, entries);
|
|
1279
|
+
var outerNodes = orderByTabIndex(getFocusables([commonParent], true), true, true);
|
|
1280
|
+
var innerElements = getFocusables(entries, false);
|
|
1281
|
+
return outerNodes.map(function (_a) {
|
|
1282
|
+
var node = _a.node, index = _a.index;
|
|
1283
|
+
return ({
|
|
1284
|
+
node: node,
|
|
1285
|
+
index: index,
|
|
1286
|
+
lockItem: innerElements.indexOf(node) >= 0,
|
|
1287
|
+
guard: isGuard(node),
|
|
1288
|
+
});
|
|
1289
|
+
});
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1292
|
+
var focusOn = function (target, focusOptions) {
|
|
1293
|
+
if (!target) {
|
|
1294
|
+
// not clear how, but is possible https://github.com/theKashey/focus-lock/issues/53
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
if ('focus' in target) {
|
|
1298
|
+
target.focus(focusOptions);
|
|
1299
|
+
}
|
|
1300
|
+
if ('contentWindow' in target && target.contentWindow) {
|
|
1301
|
+
target.contentWindow.focus();
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
var guardCount = 0;
|
|
1306
|
+
var lockDisabled = false;
|
|
1307
|
+
/**
|
|
1308
|
+
* The main functionality of the focus-lock package
|
|
1309
|
+
*
|
|
1310
|
+
* Contains focus at a given node.
|
|
1311
|
+
* The last focused element will help to determine which element(first or last) should be focused.
|
|
1312
|
+
* The found element will be focused.
|
|
1313
|
+
*
|
|
1314
|
+
* This is one time action (move), not a persistent focus-lock
|
|
1315
|
+
*
|
|
1316
|
+
* HTML markers (see {@link import('./constants').FOCUS_AUTO} constants) can control autofocus
|
|
1317
|
+
* @see {@link focusSolver} for the same functionality without autofocus
|
|
1318
|
+
*/
|
|
1319
|
+
var moveFocusInside = function (topNode, lastNode, options) {
|
|
1320
|
+
if (options === void 0) { options = {}; }
|
|
1321
|
+
var focusable = focusSolver(topNode, lastNode);
|
|
1322
|
+
// global local side effect to countain recursive lock activation and resolve focus-fighting
|
|
1323
|
+
if (lockDisabled) {
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
if (focusable) {
|
|
1327
|
+
/** +FOCUS-FIGHTING prevention **/
|
|
1328
|
+
if (guardCount > 2) {
|
|
1329
|
+
// we have recursive entered back the lock activation
|
|
1330
|
+
console.error('FocusLock: focus-fighting detected. Only one focus management system could be active. ' +
|
|
1331
|
+
'See https://github.com/theKashey/focus-lock/#focus-fighting');
|
|
1332
|
+
lockDisabled = true;
|
|
1333
|
+
setTimeout(function () {
|
|
1334
|
+
lockDisabled = false;
|
|
1335
|
+
}, 1);
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
guardCount++;
|
|
1339
|
+
focusOn(focusable.node, options.focusOptions);
|
|
1340
|
+
guardCount--;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
function weakRef(value) {
|
|
1345
|
+
if (!value)
|
|
1346
|
+
return null;
|
|
1347
|
+
// #68 Safari 14.1 dont have it yet
|
|
1348
|
+
// FIXME: remove in 2025
|
|
1349
|
+
if (typeof WeakRef === 'undefined') {
|
|
1350
|
+
return function () { return value || null; };
|
|
1351
|
+
}
|
|
1352
|
+
var w = value ? new WeakRef(value) : null;
|
|
1353
|
+
return function () { return (w === null || w === void 0 ? void 0 : w.deref()) || null; };
|
|
1354
|
+
}
|
|
1355
|
+
var recordElementLocation = function (element) {
|
|
1356
|
+
if (!element) {
|
|
1357
|
+
return null;
|
|
1358
|
+
}
|
|
1359
|
+
var stack = [];
|
|
1360
|
+
var currentElement = element;
|
|
1361
|
+
while (currentElement && currentElement !== document.body) {
|
|
1362
|
+
stack.push({
|
|
1363
|
+
current: weakRef(currentElement),
|
|
1364
|
+
parent: weakRef(currentElement.parentElement),
|
|
1365
|
+
left: weakRef(currentElement.previousElementSibling),
|
|
1366
|
+
right: weakRef(currentElement.nextElementSibling),
|
|
1367
|
+
});
|
|
1368
|
+
currentElement = currentElement.parentElement;
|
|
1369
|
+
}
|
|
1370
|
+
return {
|
|
1371
|
+
element: weakRef(element),
|
|
1372
|
+
stack: stack,
|
|
1373
|
+
ownerDocument: element.ownerDocument,
|
|
1374
|
+
};
|
|
1375
|
+
};
|
|
1376
|
+
var restoreFocusTo = function (location) {
|
|
1377
|
+
var _a, _b, _c, _d, _e;
|
|
1378
|
+
if (!location) {
|
|
1379
|
+
return undefined;
|
|
1380
|
+
}
|
|
1381
|
+
var stack = location.stack, ownerDocument = location.ownerDocument;
|
|
1382
|
+
var visibilityCache = new Map();
|
|
1383
|
+
for (var _i = 0, stack_1 = stack; _i < stack_1.length; _i++) {
|
|
1384
|
+
var line = stack_1[_i];
|
|
1385
|
+
var parent_1 = (_a = line.parent) === null || _a === void 0 ? void 0 : _a.call(line);
|
|
1386
|
+
// is it still here?
|
|
1387
|
+
if (parent_1 && ownerDocument.contains(parent_1)) {
|
|
1388
|
+
var left = (_b = line.left) === null || _b === void 0 ? void 0 : _b.call(line);
|
|
1389
|
+
var savedCurrent = line.current();
|
|
1390
|
+
var current = parent_1.contains(savedCurrent) ? savedCurrent : undefined;
|
|
1391
|
+
var right = (_c = line.right) === null || _c === void 0 ? void 0 : _c.call(line);
|
|
1392
|
+
var focusables = getTabbableNodes([parent_1], visibilityCache);
|
|
1393
|
+
var aim =
|
|
1394
|
+
// that is element itself
|
|
1395
|
+
(_e = (_d = current !== null && current !== void 0 ? current :
|
|
1396
|
+
// or something in it's place
|
|
1397
|
+
left === null || left === void 0 ? void 0 : left.nextElementSibling) !== null && _d !== void 0 ? _d :
|
|
1398
|
+
// or somebody to the right, still close enough
|
|
1399
|
+
right) !== null && _e !== void 0 ? _e :
|
|
1400
|
+
// or somebody to the left, something?
|
|
1401
|
+
left;
|
|
1402
|
+
while (aim) {
|
|
1403
|
+
for (var _f = 0, focusables_1 = focusables; _f < focusables_1.length; _f++) {
|
|
1404
|
+
var focusable = focusables_1[_f];
|
|
1405
|
+
if (aim === null || aim === void 0 ? void 0 : aim.contains(focusable.node)) {
|
|
1406
|
+
return focusable.node;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
aim = aim.nextElementSibling;
|
|
1410
|
+
}
|
|
1411
|
+
if (focusables.length) {
|
|
1412
|
+
// if parent contains a focusable - move there
|
|
1413
|
+
return focusables[0].node;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
// nothing matched
|
|
1418
|
+
return undefined;
|
|
1419
|
+
};
|
|
1420
|
+
/**
|
|
1421
|
+
* Captures the current focused element to restore focus as close as possible in the future
|
|
1422
|
+
* Handles situations where the focused element is removed from the DOM or no longer focusable
|
|
1423
|
+
* moving focus to the closest focusable element
|
|
1424
|
+
* @param targetElement - element where focus should be restored
|
|
1425
|
+
* @returns a function returning a new element to focus
|
|
1426
|
+
*/
|
|
1427
|
+
var captureFocusRestore = function (targetElement) {
|
|
1428
|
+
var location = recordElementLocation(targetElement);
|
|
1429
|
+
return function () {
|
|
1430
|
+
return restoreFocusTo(location);
|
|
1431
|
+
};
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* for a given `element` in a given `scope` returns focusable siblings
|
|
1436
|
+
* @param element - base element
|
|
1437
|
+
* @param scope - common parent. Can be document, but better to narrow it down for performance reasons
|
|
1438
|
+
* @returns {prev,next} - references to a focusable element before and after
|
|
1439
|
+
* @returns undefined - if operation is not applicable
|
|
1440
|
+
*/
|
|
1441
|
+
var getRelativeFocusable = function (element, scope, useTabbables) {
|
|
1442
|
+
if (!element || !scope) {
|
|
1443
|
+
console.error('no element or scope given');
|
|
1444
|
+
return {};
|
|
1445
|
+
}
|
|
1446
|
+
var shards = asArray(scope);
|
|
1447
|
+
if (shards.every(function (shard) { return !contains(shard, element); })) {
|
|
1448
|
+
console.error('Active element is not contained in the scope');
|
|
1449
|
+
return {};
|
|
1450
|
+
}
|
|
1451
|
+
var focusables = useTabbables
|
|
1452
|
+
? getTabbableNodes(shards, new Map())
|
|
1453
|
+
: getFocusableNodes(shards, new Map());
|
|
1454
|
+
var current = focusables.findIndex(function (_a) {
|
|
1455
|
+
var node = _a.node;
|
|
1456
|
+
return node === element;
|
|
1457
|
+
});
|
|
1458
|
+
if (current === -1) {
|
|
1459
|
+
// an edge case, when anchor element is not found
|
|
1460
|
+
return undefined;
|
|
1461
|
+
}
|
|
1462
|
+
return {
|
|
1463
|
+
prev: focusables[current - 1],
|
|
1464
|
+
next: focusables[current + 1],
|
|
1465
|
+
first: focusables[0],
|
|
1466
|
+
last: focusables[focusables.length - 1],
|
|
1467
|
+
};
|
|
1468
|
+
};
|
|
1469
|
+
var getBoundary = function (shards, useTabbables) {
|
|
1470
|
+
var set = useTabbables
|
|
1471
|
+
? getTabbableNodes(asArray(shards), new Map())
|
|
1472
|
+
: getFocusableNodes(asArray(shards), new Map());
|
|
1473
|
+
return {
|
|
1474
|
+
first: set[0],
|
|
1475
|
+
last: set[set.length - 1],
|
|
1476
|
+
};
|
|
1477
|
+
};
|
|
1478
|
+
var defaultOptions = function (options) {
|
|
1479
|
+
return Object.assign({
|
|
1480
|
+
scope: document.body,
|
|
1481
|
+
cycle: true,
|
|
1482
|
+
onlyTabbable: true,
|
|
1483
|
+
}, options);
|
|
1484
|
+
};
|
|
1485
|
+
var moveFocus = function (fromElement, options, cb) {
|
|
1486
|
+
if (options === void 0) { options = {}; }
|
|
1487
|
+
var newOptions = defaultOptions(options);
|
|
1488
|
+
var solution = getRelativeFocusable(fromElement, newOptions.scope, newOptions.onlyTabbable);
|
|
1489
|
+
if (!solution) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
var target = cb(solution, newOptions.cycle);
|
|
1493
|
+
if (target) {
|
|
1494
|
+
focusOn(target.node, newOptions.focusOptions);
|
|
1495
|
+
}
|
|
1496
|
+
};
|
|
1497
|
+
/**
|
|
1498
|
+
* focuses next element in the tab-order
|
|
1499
|
+
* @param fromElement - common parent to scope active element search or tab cycle order
|
|
1500
|
+
* @param {FocusNextOptions} [options] - focus options
|
|
1501
|
+
*/
|
|
1502
|
+
var focusNextElement = function (fromElement, options) {
|
|
1503
|
+
if (options === void 0) { options = {}; }
|
|
1504
|
+
moveFocus(fromElement, options, function (_a, cycle) {
|
|
1505
|
+
var next = _a.next, first = _a.first;
|
|
1506
|
+
return next || (cycle && first);
|
|
1507
|
+
});
|
|
1508
|
+
};
|
|
1509
|
+
/**
|
|
1510
|
+
* focuses prev element in the tab order
|
|
1511
|
+
* @param fromElement - common parent to scope active element search or tab cycle order
|
|
1512
|
+
* @param {FocusNextOptions} [options] - focus options
|
|
1513
|
+
*/
|
|
1514
|
+
var focusPrevElement = function (fromElement, options) {
|
|
1515
|
+
if (options === void 0) { options = {}; }
|
|
1516
|
+
moveFocus(fromElement, options, function (_a, cycle) {
|
|
1517
|
+
var prev = _a.prev, last = _a.last;
|
|
1518
|
+
return prev || (cycle && last);
|
|
1519
|
+
});
|
|
1520
|
+
};
|
|
1521
|
+
var pickBoundary = function (scope, options, what) {
|
|
1522
|
+
var _a;
|
|
1523
|
+
var boundary = getBoundary(scope, (_a = options.onlyTabbable) !== null && _a !== void 0 ? _a : true);
|
|
1524
|
+
var node = boundary[what];
|
|
1525
|
+
if (node) {
|
|
1526
|
+
focusOn(node.node, options.focusOptions);
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
/**
|
|
1530
|
+
* focuses first element in the tab-order
|
|
1531
|
+
* @param {FocusNextOptions} options - focus options
|
|
1532
|
+
*/
|
|
1533
|
+
var focusFirstElement = function (scope, options) {
|
|
1534
|
+
if (options === void 0) { options = {}; }
|
|
1535
|
+
pickBoundary(scope, options, 'first');
|
|
1536
|
+
};
|
|
1537
|
+
/**
|
|
1538
|
+
* focuses last element in the tab order
|
|
1539
|
+
* @param {FocusNextOptions} options - focus options
|
|
1540
|
+
*/
|
|
1541
|
+
var focusLastElement = function (scope, options) {
|
|
1542
|
+
if (options === void 0) { options = {}; }
|
|
1543
|
+
pickBoundary(scope, options, 'last');
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1546
|
+
function deferAction(action) {
|
|
1547
|
+
setTimeout(action, 1);
|
|
1548
|
+
}
|
|
1549
|
+
var extractRef = function extractRef(ref) {
|
|
1550
|
+
return ref && 'current' in ref ? ref.current : ref;
|
|
1551
|
+
};
|
|
1552
|
+
|
|
1553
|
+
var focusOnBody = function focusOnBody() {
|
|
1554
|
+
return document && document.activeElement === document.body;
|
|
1555
|
+
};
|
|
1556
|
+
var isFreeFocus = function isFreeFocus() {
|
|
1557
|
+
return focusOnBody() || focusIsHidden();
|
|
1558
|
+
};
|
|
1559
|
+
var lastActiveTrap = null;
|
|
1560
|
+
var lastActiveFocus = null;
|
|
1561
|
+
var tryRestoreFocus = function tryRestoreFocus() {
|
|
1562
|
+
return null;
|
|
1563
|
+
};
|
|
1564
|
+
var lastPortaledElement = null;
|
|
1565
|
+
var focusWasOutsideWindow = false;
|
|
1566
|
+
var windowFocused = false;
|
|
1567
|
+
var defaultWhitelist = function defaultWhitelist() {
|
|
1568
|
+
return true;
|
|
1569
|
+
};
|
|
1570
|
+
var focusWhitelisted = function focusWhitelisted(activeElement) {
|
|
1571
|
+
return (lastActiveTrap.whiteList || defaultWhitelist)(activeElement);
|
|
1572
|
+
};
|
|
1573
|
+
var recordPortal = function recordPortal(observerNode, portaledElement) {
|
|
1574
|
+
lastPortaledElement = {
|
|
1575
|
+
observerNode: observerNode,
|
|
1576
|
+
portaledElement: portaledElement
|
|
1577
|
+
};
|
|
1578
|
+
};
|
|
1579
|
+
var focusIsPortaledPair = function focusIsPortaledPair(element) {
|
|
1580
|
+
return lastPortaledElement && lastPortaledElement.portaledElement === element;
|
|
1581
|
+
};
|
|
1582
|
+
function autoGuard(startIndex, end, step, allNodes) {
|
|
1583
|
+
var lastGuard = null;
|
|
1584
|
+
var i = startIndex;
|
|
1585
|
+
do {
|
|
1586
|
+
var item = allNodes[i];
|
|
1587
|
+
if (item.guard) {
|
|
1588
|
+
if (item.node.dataset.focusAutoGuard) {
|
|
1589
|
+
lastGuard = item;
|
|
1590
|
+
}
|
|
1591
|
+
} else if (item.lockItem) {
|
|
1592
|
+
if (i !== startIndex) {
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
lastGuard = null;
|
|
1596
|
+
} else {
|
|
1597
|
+
break;
|
|
1598
|
+
}
|
|
1599
|
+
} while ((i += step) !== end);
|
|
1600
|
+
if (lastGuard) {
|
|
1601
|
+
lastGuard.node.tabIndex = 0;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
var focusWasOutside = function focusWasOutside(crossFrameOption) {
|
|
1605
|
+
if (crossFrameOption) {
|
|
1606
|
+
return Boolean(focusWasOutsideWindow);
|
|
1607
|
+
}
|
|
1608
|
+
return focusWasOutsideWindow === 'meanwhile';
|
|
1609
|
+
};
|
|
1610
|
+
var checkInHost = function checkInHost(check, el, boundary) {
|
|
1611
|
+
return el && (el.host === check && (!el.activeElement || boundary.contains(el.activeElement)) || el.parentNode && checkInHost(check, el.parentNode, boundary));
|
|
1612
|
+
};
|
|
1613
|
+
var withinHost = function withinHost(activeElement, workingArea) {
|
|
1614
|
+
return workingArea.some(function (area) {
|
|
1615
|
+
return checkInHost(activeElement, area, area);
|
|
1616
|
+
});
|
|
1617
|
+
};
|
|
1618
|
+
var getNodeFocusables = function getNodeFocusables(nodes) {
|
|
1619
|
+
return getFocusableNodes(nodes, new Map());
|
|
1620
|
+
};
|
|
1621
|
+
var isNotFocusable = function isNotFocusable(node) {
|
|
1622
|
+
return !getNodeFocusables([node.parentNode]).some(function (el) {
|
|
1623
|
+
return el.node === node;
|
|
1624
|
+
});
|
|
1625
|
+
};
|
|
1626
|
+
var activateTrap = function activateTrap() {
|
|
1627
|
+
var result = false;
|
|
1628
|
+
if (lastActiveTrap) {
|
|
1629
|
+
var _lastActiveTrap = lastActiveTrap,
|
|
1630
|
+
observed = _lastActiveTrap.observed,
|
|
1631
|
+
persistentFocus = _lastActiveTrap.persistentFocus,
|
|
1632
|
+
autoFocus = _lastActiveTrap.autoFocus,
|
|
1633
|
+
shards = _lastActiveTrap.shards,
|
|
1634
|
+
crossFrame = _lastActiveTrap.crossFrame,
|
|
1635
|
+
focusOptions = _lastActiveTrap.focusOptions,
|
|
1636
|
+
noFocusGuards = _lastActiveTrap.noFocusGuards;
|
|
1637
|
+
var workingNode = observed || lastPortaledElement && lastPortaledElement.portaledElement;
|
|
1638
|
+
if (focusOnBody() && lastActiveFocus) {
|
|
1639
|
+
if (!document.body.contains(lastActiveFocus) || isNotFocusable(lastActiveFocus)) {
|
|
1640
|
+
lastActiveFocus = null;
|
|
1641
|
+
var newTarget = tryRestoreFocus();
|
|
1642
|
+
if (newTarget) {
|
|
1643
|
+
newTarget.focus();
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
var activeElement = document && document.activeElement;
|
|
1648
|
+
if (workingNode) {
|
|
1649
|
+
var workingArea = [workingNode].concat(shards.map(extractRef).filter(Boolean));
|
|
1650
|
+
var shouldForceRestoreFocus = function shouldForceRestoreFocus() {
|
|
1651
|
+
if (!focusWasOutside(crossFrame) || !noFocusGuards || !lastActiveFocus || windowFocused) {
|
|
1652
|
+
return false;
|
|
1653
|
+
}
|
|
1654
|
+
var nodes = getNodeFocusables(workingArea);
|
|
1655
|
+
var lastIndex = nodes.findIndex(function (_ref) {
|
|
1656
|
+
var node = _ref.node;
|
|
1657
|
+
return node === lastActiveFocus;
|
|
1658
|
+
});
|
|
1659
|
+
return lastIndex === 0 || lastIndex === nodes.length - 1;
|
|
1660
|
+
};
|
|
1661
|
+
if (!activeElement || focusWhitelisted(activeElement)) {
|
|
1662
|
+
if (persistentFocus || shouldForceRestoreFocus() || !isFreeFocus() || !lastActiveFocus && autoFocus) {
|
|
1663
|
+
if (workingNode && !(focusInside(workingArea) || activeElement && withinHost(activeElement, workingArea) || focusIsPortaledPair(activeElement))) {
|
|
1664
|
+
if (document && !lastActiveFocus && activeElement && !autoFocus) {
|
|
1665
|
+
if (activeElement.blur) {
|
|
1666
|
+
activeElement.blur();
|
|
1667
|
+
}
|
|
1668
|
+
document.body.focus();
|
|
1669
|
+
} else {
|
|
1670
|
+
result = moveFocusInside(workingArea, lastActiveFocus, {
|
|
1671
|
+
focusOptions: focusOptions
|
|
1672
|
+
});
|
|
1673
|
+
lastPortaledElement = {};
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
focusWasOutsideWindow = false;
|
|
1677
|
+
lastActiveFocus = document && document.activeElement;
|
|
1678
|
+
tryRestoreFocus = captureFocusRestore(lastActiveFocus);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
if (document && activeElement !== document.activeElement && document.querySelector('[data-focus-auto-guard]')) {
|
|
1682
|
+
var newActiveElement = document && document.activeElement;
|
|
1683
|
+
var allNodes = expandFocusableNodes(workingArea);
|
|
1684
|
+
var focusedIndex = allNodes.map(function (_ref2) {
|
|
1685
|
+
var node = _ref2.node;
|
|
1686
|
+
return node;
|
|
1687
|
+
}).indexOf(newActiveElement);
|
|
1688
|
+
if (focusedIndex > -1) {
|
|
1689
|
+
allNodes.filter(function (_ref3) {
|
|
1690
|
+
var guard = _ref3.guard,
|
|
1691
|
+
node = _ref3.node;
|
|
1692
|
+
return guard && node.dataset.focusAutoGuard;
|
|
1693
|
+
}).forEach(function (_ref4) {
|
|
1694
|
+
var node = _ref4.node;
|
|
1695
|
+
return node.removeAttribute('tabIndex');
|
|
1696
|
+
});
|
|
1697
|
+
autoGuard(focusedIndex, allNodes.length, +1, allNodes);
|
|
1698
|
+
autoGuard(focusedIndex, -1, -1, allNodes);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
return result;
|
|
1704
|
+
};
|
|
1705
|
+
var onTrap = function onTrap(event) {
|
|
1706
|
+
if (activateTrap() && event) {
|
|
1707
|
+
event.stopPropagation();
|
|
1708
|
+
event.preventDefault();
|
|
1709
|
+
}
|
|
1710
|
+
};
|
|
1711
|
+
var onBlur = function onBlur() {
|
|
1712
|
+
return deferAction(activateTrap);
|
|
1713
|
+
};
|
|
1714
|
+
var onFocus = function onFocus(event) {
|
|
1715
|
+
var source = event.target;
|
|
1716
|
+
var currentNode = event.currentTarget;
|
|
1717
|
+
if (!currentNode.contains(source)) {
|
|
1718
|
+
recordPortal(currentNode, source);
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
var FocusWatcher = function FocusWatcher() {
|
|
1722
|
+
return null;
|
|
1723
|
+
};
|
|
1724
|
+
process.env.NODE_ENV !== "production" ? {
|
|
1725
|
+
children: PropTypes.node.isRequired
|
|
1726
|
+
} : {};
|
|
1727
|
+
var onWindowFocus = function onWindowFocus() {
|
|
1728
|
+
windowFocused = true;
|
|
1729
|
+
};
|
|
1730
|
+
var onWindowBlur = function onWindowBlur() {
|
|
1731
|
+
windowFocused = false;
|
|
1732
|
+
focusWasOutsideWindow = 'just';
|
|
1733
|
+
deferAction(function () {
|
|
1734
|
+
focusWasOutsideWindow = 'meanwhile';
|
|
1735
|
+
});
|
|
1736
|
+
};
|
|
1737
|
+
var attachHandler = function attachHandler() {
|
|
1738
|
+
document.addEventListener('focusin', onTrap);
|
|
1739
|
+
document.addEventListener('focusout', onBlur);
|
|
1740
|
+
window.addEventListener('focus', onWindowFocus);
|
|
1741
|
+
window.addEventListener('blur', onWindowBlur);
|
|
1742
|
+
};
|
|
1743
|
+
var detachHandler = function detachHandler() {
|
|
1744
|
+
document.removeEventListener('focusin', onTrap);
|
|
1745
|
+
document.removeEventListener('focusout', onBlur);
|
|
1746
|
+
window.removeEventListener('focus', onWindowFocus);
|
|
1747
|
+
window.removeEventListener('blur', onWindowBlur);
|
|
1748
|
+
};
|
|
1749
|
+
function reducePropsToState(propsList) {
|
|
1750
|
+
return propsList.filter(function (_ref6) {
|
|
1751
|
+
var disabled = _ref6.disabled;
|
|
1752
|
+
return !disabled;
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
var focusLockAPI = {
|
|
1756
|
+
moveFocusInside: moveFocusInside,
|
|
1757
|
+
focusInside: focusInside,
|
|
1758
|
+
focusNextElement: focusNextElement,
|
|
1759
|
+
focusPrevElement: focusPrevElement,
|
|
1760
|
+
focusFirstElement: focusFirstElement,
|
|
1761
|
+
focusLastElement: focusLastElement,
|
|
1762
|
+
captureFocusRestore: captureFocusRestore
|
|
1763
|
+
};
|
|
1764
|
+
function handleStateChangeOnClient(traps) {
|
|
1765
|
+
var trap = traps.slice(-1)[0];
|
|
1766
|
+
if (trap && !lastActiveTrap) {
|
|
1767
|
+
attachHandler();
|
|
1768
|
+
}
|
|
1769
|
+
var lastTrap = lastActiveTrap;
|
|
1770
|
+
var sameTrap = lastTrap && trap && trap.id === lastTrap.id;
|
|
1771
|
+
lastActiveTrap = trap;
|
|
1772
|
+
if (lastTrap && !sameTrap) {
|
|
1773
|
+
lastTrap.onDeactivation();
|
|
1774
|
+
if (!traps.filter(function (_ref7) {
|
|
1775
|
+
var id = _ref7.id;
|
|
1776
|
+
return id === lastTrap.id;
|
|
1777
|
+
}).length) {
|
|
1778
|
+
lastTrap.returnFocus(!trap);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
if (trap) {
|
|
1782
|
+
lastActiveFocus = null;
|
|
1783
|
+
if (!sameTrap || lastTrap.observed !== trap.observed) {
|
|
1784
|
+
trap.onActivation(focusLockAPI);
|
|
1785
|
+
}
|
|
1786
|
+
activateTrap();
|
|
1787
|
+
deferAction(activateTrap);
|
|
1788
|
+
} else {
|
|
1789
|
+
detachHandler();
|
|
1790
|
+
lastActiveFocus = null;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
mediumFocus.assignSyncMedium(onFocus);
|
|
1794
|
+
mediumBlur.assignMedium(onBlur);
|
|
1795
|
+
mediumEffect.assignMedium(function (cb) {
|
|
1796
|
+
return cb(focusLockAPI);
|
|
1797
|
+
});
|
|
1798
|
+
var FocusTrap = withSideEffect(reducePropsToState, handleStateChangeOnClient)(FocusWatcher);
|
|
1799
|
+
|
|
1800
|
+
var FocusLockCombination = /*#__PURE__*/React.forwardRef(function FocusLockUICombination(props, ref) {
|
|
1801
|
+
return /*#__PURE__*/React.createElement(FocusLock, _extends({
|
|
1802
|
+
sideCar: FocusTrap,
|
|
1803
|
+
ref: ref
|
|
1804
|
+
}, props));
|
|
1805
|
+
});
|
|
1806
|
+
var _ref = FocusLock.propTypes || {};
|
|
1807
|
+
_ref.sideCar;
|
|
1808
|
+
var propTypes = _objectWithoutPropertiesLoose(_ref, ["sideCar"]);
|
|
1809
|
+
FocusLockCombination.propTypes = process.env.NODE_ENV !== "production" ? propTypes : {};
|
|
1810
|
+
|
|
73
1811
|
var InnerModal = function (_a) {
|
|
74
1812
|
var _b;
|
|
75
1813
|
var _c, _d;
|
|
@@ -94,12 +1832,12 @@ var InnerModal = function (_a) {
|
|
|
94
1832
|
_b[styles.overlayClose] = isClosing,
|
|
95
1833
|
_b)), onAnimationEnd: handleOnCloseAnimationEnded, onClick: handleOnOverlayClick, children: jsx("div", { className: typeof (classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.wrapper) === 'string'
|
|
96
1834
|
? classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.wrapper
|
|
97
|
-
: (_c = classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.wrapper) === null || _c === void 0 ? void 0 : _c.call(classNames$1, { isClosing: isClosing }), children:
|
|
1835
|
+
: (_c = classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.wrapper) === null || _c === void 0 ? void 0 : _c.call(classNames$1, { isClosing: isClosing }), children: jsx("div", { "aria-modal": "true", role: "dialog", className: typeof (classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.container) === 'string'
|
|
98
1836
|
? classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.container
|
|
99
|
-
: (_d = classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.container) === null || _d === void 0 ? void 0 : _d.call(classNames$1, { isClosing: isClosing }), onClick: handleContainerClick, children: [jsxs("div", { className: classNames('bg-white d-flex ai-center w100 px24 pt24 pb16', styles.header, {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1837
|
+
: (_d = classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.container) === null || _d === void 0 ? void 0 : _d.call(classNames$1, { isClosing: isClosing }), onClick: handleContainerClick, children: jsxs(FocusLockCombination, { returnFocus: true, children: [jsxs("div", { className: classNames('bg-white d-flex ai-center w100 px24 pt24 pb16', styles.header, {
|
|
1838
|
+
'jc-between': !!title,
|
|
1839
|
+
'jc-end': !title,
|
|
1840
|
+
}), children: [title && (jsx("div", { className: classNames(styles.title, titleSize === 'small' ? 'p-h4' : 'p-h2'), children: title })), dismissible && (jsx(Button, { hideLabel: true, leftIcon: jsx(XIcon, { color: "grey-700" }), onClick: handleOnClose, type: "button", variant: "textColor", className: classNames(classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.closeButton, 'p0', styles.closeButton), children: "Close modal" }))] }), jsx("div", { className: classNames('w100', classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.body, styles.body), ref: modalBodyRef, children: children }), footer && (jsx("div", { className: classNames(classNames$1 === null || classNames$1 === void 0 ? void 0 : classNames$1.footer, 'w100 bg-white', styles.footer), children: jsx("div", { className: "p24 pt16", children: footer }) }))] }) }) }) }));
|
|
103
1841
|
};
|
|
104
1842
|
var GenericModal = function (props) {
|
|
105
1843
|
var isOpen = props.isOpen, onClose = props.onClose, _a = props.dismissible, dismissible = _a === void 0 ? true : _a;
|