1 | "use strict";
|
2 |
|
3 | exports.__esModule = true;
|
4 | exports.useListOption = useListOption;
|
5 | exports.useFocusList = exports.FocusListContext = void 0;
|
6 |
|
7 | var _querySelectorAll = _interopRequireDefault(require("dom-helpers/querySelectorAll"));
|
8 |
|
9 | var _react = _interopRequireWildcard(require("react"));
|
10 |
|
11 | function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
12 |
|
13 | function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
14 |
|
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
16 |
|
17 |
|
18 | const FocusListContext = _react.default.createContext(null);
|
19 |
|
20 | exports.FocusListContext = FocusListContext;
|
21 | const defaultOpts = {
|
22 | behavior: 'stop'
|
23 | };
|
24 |
|
25 | function useListOption(dataItem) {
|
26 | const ctx = (0, _react.useContext)(FocusListContext);
|
27 | const prevElement = (0, _react.useRef)(null);
|
28 |
|
29 |
|
30 |
|
31 | const ref = (0, _react.useRef)(null);
|
32 | (0, _react.useLayoutEffect)(() => () => {
|
33 | ctx == null ? void 0 : ctx.map.delete(ref.current);
|
34 | }, []);
|
35 | (0, _react.useLayoutEffect)(() => {
|
36 | if (prevElement.current !== ref.current) {
|
37 | ctx == null ? void 0 : ctx.map.delete(prevElement.current);
|
38 | }
|
39 |
|
40 | prevElement.current = ref.current;
|
41 |
|
42 | if (ref.current && (ctx == null ? void 0 : ctx.map.get(ref.current)) !== dataItem) {
|
43 | ctx == null ? void 0 : ctx.map.set(ref.current, dataItem);
|
44 | }
|
45 | });
|
46 | const focused = dataItem === (ctx == null ? void 0 : ctx.focusedItem);
|
47 | return [ref, focused, focused ? ctx == null ? void 0 : ctx.activeId : undefined];
|
48 | }
|
49 |
|
50 | const useFocusList = ({
|
51 | scope: listRef,
|
52 | anchorItem,
|
53 | focusFirstItem: _focusFirstItem = false,
|
54 | scopeSelector: _scopeSelector = '',
|
55 | activeId
|
56 | }) => {
|
57 | const map = (0, _react.useMemo)(() => new WeakMap(), []);
|
58 | const [focusedItem, setFocusedItem] = (0, _react.useState)();
|
59 | const itemSelector = `${_scopeSelector} [data-rw-focusable]`.trim();
|
60 |
|
61 | const get = () => {
|
62 | const items = (0, _querySelectorAll.default)(listRef.current, itemSelector);
|
63 | return [items, items.find(e => e.dataset.rwFocused === '')];
|
64 | };
|
65 |
|
66 | const list = (0, _react.useMemo)(() => {
|
67 | return {
|
68 | size() {
|
69 | const [items] = get();
|
70 | return items.length;
|
71 | },
|
72 |
|
73 | get,
|
74 | toDataItem: el => map.get(el),
|
75 |
|
76 | first() {
|
77 | const [[first]] = get();
|
78 | return first;
|
79 | },
|
80 |
|
81 | focus(el) {
|
82 | if (!el || map.has(el)) setFocusedItem(el ? map.get(el) : undefined);
|
83 | },
|
84 |
|
85 | last() {
|
86 | const [items] = get();
|
87 | return items[items.length - 1];
|
88 | },
|
89 |
|
90 | next({
|
91 | behavior
|
92 | } = defaultOpts) {
|
93 | const [items, focusedItem] = get();
|
94 | let nextIdx = items.indexOf(focusedItem) + 1;
|
95 |
|
96 | if (nextIdx >= items.length) {
|
97 | if (behavior === 'loop') return items[0];
|
98 | if (behavior === 'clear') return undefined;
|
99 | return focusedItem;
|
100 | }
|
101 |
|
102 | return items[nextIdx];
|
103 | },
|
104 |
|
105 | prev({
|
106 | behavior
|
107 | } = defaultOpts) {
|
108 | const [items, focusedItem] = get();
|
109 | let nextIdx = Math.max(0, items.indexOf(focusedItem)) - 1;
|
110 |
|
111 | if (nextIdx < 0) {
|
112 | if (behavior === 'loop') return items[items.length - 1];
|
113 | if (behavior === 'clear') return undefined;
|
114 | return focusedItem;
|
115 | }
|
116 |
|
117 | return items[nextIdx];
|
118 | }
|
119 |
|
120 | };
|
121 | }, []);
|
122 | (0, _react.useLayoutEffect)(() => {
|
123 | if (!anchorItem) {
|
124 | list.focus(null);
|
125 | return;
|
126 | }
|
127 |
|
128 | const element = get()[0].find(el => list.toDataItem(el) === anchorItem);
|
129 | list.focus(element);
|
130 | }, [anchorItem]);
|
131 | (0, _react.useLayoutEffect)(() => {
|
132 | if (!listRef.current) return;
|
133 | const [, focusedElement] = get();
|
134 | const hasItem = focusedElement != null;
|
135 |
|
136 | if (!hasItem && _focusFirstItem || hasItem && !listRef.current.contains(focusedElement)) {
|
137 | if (_focusFirstItem) list.focus(list.first());else list.focus(null);
|
138 | }
|
139 | });
|
140 | const context = (0, _react.useMemo)(() => ({
|
141 | map,
|
142 | focusedItem,
|
143 | activeId
|
144 | }), [focusedItem, activeId]);
|
145 | list.context = context;
|
146 | list.getFocused = (0, _react.useCallback)(() => focusedItem, [focusedItem]);
|
147 |
|
148 | list.hasFocused = () => focusedItem !== undefined;
|
149 |
|
150 | return list;
|
151 | };
|
152 |
|
153 | exports.useFocusList = useFocusList; |
\ | No newline at end of file |