@actview/floating-ui 0.1.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/LICENSE +21 -0
- package/dist/_deprecated-inner.d.ts +82 -0
- package/dist/components/Composite.d.ts +109 -0
- package/dist/components/FloatingArrow.d.ts +66 -0
- package/dist/components/FloatingDelayGroup.d.ts +70 -0
- package/dist/components/FloatingFocusManager.d.ts +92 -0
- package/dist/components/FloatingList.d.ts +43 -0
- package/dist/components/FloatingOverlay.d.ts +18 -0
- package/dist/components/FloatingPortal.d.ts +63 -0
- package/dist/components/FloatingTree.d.ts +45 -0
- package/dist/components/FocusGuard.d.ts +19 -0
- package/dist/components/NextFloatingDelayGroup.d.ts +57 -0
- package/dist/floating-ui.actview.d.mts +37 -0
- package/dist/floating-ui.actview.d.ts +37 -0
- package/dist/floating-ui.actview.esm.js +6688 -0
- package/dist/floating-ui.actview.mjs +6688 -0
- package/dist/floating-ui.actview.umd.js +6772 -0
- package/dist/floating-ui.actview.umd.min.js +1 -0
- package/dist/floating-ui.actview.utils.d.mts +7 -0
- package/dist/floating-ui.actview.utils.d.ts +7 -0
- package/dist/floating-ui.actview.utils.esm.js +587 -0
- package/dist/floating-ui.actview.utils.mjs +587 -0
- package/dist/floating-ui.actview.utils.umd.js +634 -0
- package/dist/floating-ui.actview.utils.umd.min.js +1 -0
- package/dist/hooks/gridNavigation.d.ts +39 -0
- package/dist/hooks/useClick.d.ts +45 -0
- package/dist/hooks/useClientPoint.d.ts +32 -0
- package/dist/hooks/useDismiss.d.ts +80 -0
- package/dist/hooks/useFloating.d.ts +18 -0
- package/dist/hooks/useFloatingRootContext.d.ts +22 -0
- package/dist/hooks/useFocus.d.ts +21 -0
- package/dist/hooks/useHover.d.ts +57 -0
- package/dist/hooks/useId.d.ts +11 -0
- package/dist/hooks/useInteractions.d.ts +13 -0
- package/dist/hooks/useListNavigation.d.ts +176 -0
- package/dist/hooks/useMergeRefs.d.ts +20 -0
- package/dist/hooks/useRole.d.ts +33 -0
- package/dist/hooks/useTransition.d.ts +68 -0
- package/dist/hooks/useTypeahead.d.ts +66 -0
- package/dist/index.d.ts +37 -0
- package/dist/safePolygon.d.ts +12 -0
- package/dist/types.d.ts +140 -0
- package/dist/useFloating.d.ts +57 -0
- package/dist/utils/clearTimeoutIfSet.d.ts +2 -0
- package/dist/utils/composite.d.ts +41 -0
- package/dist/utils/constants.d.ts +8 -0
- package/dist/utils/createAttribute.d.ts +1 -0
- package/dist/utils/createEventEmitter.d.ts +5 -0
- package/dist/utils/deepEqual.d.ts +1 -0
- package/dist/utils/element.d.ts +10 -0
- package/dist/utils/enqueueFocus.d.ts +8 -0
- package/dist/utils/event.d.ts +10 -0
- package/dist/utils/getDPR.d.ts +1 -0
- package/dist/utils/hooks.d.ts +16 -0
- package/dist/utils/log.d.ts +2 -0
- package/dist/utils/markOthers.d.ts +4 -0
- package/dist/utils/nodes.d.ts +4 -0
- package/dist/utils/platform.d.ts +6 -0
- package/dist/utils/roundByDPR.d.ts +1 -0
- package/dist/utils/safeReact.d.ts +8 -0
- package/dist/utils/tabbable.d.ts +13 -0
- package/dist/utils/useLiteMergeRefs.d.ts +14 -0
- package/dist/utils.d.ts +7 -0
- package/package.json +83 -0
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@actview/core'), require('@floating-ui/utils'), require('tabbable')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@actview/core', '@floating-ui/utils', 'tabbable'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FloatingUIActviewUtils = {}, global.ActviewCore, global.FloatingUIUtils, global.tabbable));
|
|
5
|
+
})(this, (function (exports, core, utils, tabbable) { 'use strict';
|
|
6
|
+
|
|
7
|
+
function hasWindow() {
|
|
8
|
+
return typeof window !== 'undefined';
|
|
9
|
+
}
|
|
10
|
+
function getWindow(node) {
|
|
11
|
+
var _node$ownerDocument;
|
|
12
|
+
return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
|
|
13
|
+
}
|
|
14
|
+
function isHTMLElement(value) {
|
|
15
|
+
if (!hasWindow()) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
|
|
19
|
+
}
|
|
20
|
+
function isShadowRoot(value) {
|
|
21
|
+
if (!hasWindow() || typeof ShadowRoot === 'undefined') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Avoid Chrome DevTools blue warning.
|
|
28
|
+
function getPlatform() {
|
|
29
|
+
const uaData = navigator.userAgentData;
|
|
30
|
+
if (uaData != null && uaData.platform) {
|
|
31
|
+
return uaData.platform;
|
|
32
|
+
}
|
|
33
|
+
return navigator.platform;
|
|
34
|
+
}
|
|
35
|
+
function getUserAgent() {
|
|
36
|
+
const uaData = navigator.userAgentData;
|
|
37
|
+
if (uaData && Array.isArray(uaData.brands)) {
|
|
38
|
+
return uaData.brands.map(_ref => {
|
|
39
|
+
let {
|
|
40
|
+
brand,
|
|
41
|
+
version
|
|
42
|
+
} = _ref;
|
|
43
|
+
return brand + "/" + version;
|
|
44
|
+
}).join(' ');
|
|
45
|
+
}
|
|
46
|
+
return navigator.userAgent;
|
|
47
|
+
}
|
|
48
|
+
function isSafari() {
|
|
49
|
+
// Chrome DevTools does not complain about navigator.vendor
|
|
50
|
+
return /apple/i.test(navigator.vendor);
|
|
51
|
+
}
|
|
52
|
+
function isAndroid() {
|
|
53
|
+
const re = /android/i;
|
|
54
|
+
return re.test(getPlatform()) || re.test(getUserAgent());
|
|
55
|
+
}
|
|
56
|
+
function isMac() {
|
|
57
|
+
return getPlatform().toLowerCase().startsWith('mac') && !navigator.maxTouchPoints;
|
|
58
|
+
}
|
|
59
|
+
function isJSDOM() {
|
|
60
|
+
return getUserAgent().includes('jsdom/');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const FOCUSABLE_ATTRIBUTE = 'data-floating-ui-focusable';
|
|
64
|
+
const TYPEABLE_SELECTOR = "input:not([type='hidden']):not([disabled])," + "[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";
|
|
65
|
+
const ARROW_LEFT = 'ArrowLeft';
|
|
66
|
+
const ARROW_RIGHT = 'ArrowRight';
|
|
67
|
+
const ARROW_UP = 'ArrowUp';
|
|
68
|
+
const ARROW_DOWN = 'ArrowDown';
|
|
69
|
+
|
|
70
|
+
function activeElement(doc) {
|
|
71
|
+
let activeElement = doc.activeElement;
|
|
72
|
+
while (((_activeElement = activeElement) == null || (_activeElement = _activeElement.shadowRoot) == null ? void 0 : _activeElement.activeElement) != null) {
|
|
73
|
+
var _activeElement;
|
|
74
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
75
|
+
}
|
|
76
|
+
return activeElement;
|
|
77
|
+
}
|
|
78
|
+
function contains(parent, child) {
|
|
79
|
+
if (!parent || !child) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const rootNode = child.getRootNode == null ? void 0 : child.getRootNode();
|
|
83
|
+
|
|
84
|
+
// First, attempt with faster native method
|
|
85
|
+
// `parent.contains(window)` 在真实浏览器抛 TypeError(window 不是 Node),
|
|
86
|
+
// jsdom 则宽容返回 false;加 Node 防护对齐两环境行为(window mousemove 等
|
|
87
|
+
// 事件经 getTarget 取到 window 时)。
|
|
88
|
+
if (child instanceof Node && parent.contains(child)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// then fallback to custom implementation with Shadow DOM support
|
|
93
|
+
if (rootNode && isShadowRoot(rootNode)) {
|
|
94
|
+
let next = child;
|
|
95
|
+
while (next) {
|
|
96
|
+
if (parent === next) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
// @ts-ignore
|
|
100
|
+
next = next.parentNode || next.host;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Give up, the result is false
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
function getTarget(event) {
|
|
108
|
+
if ('composedPath' in event) {
|
|
109
|
+
return event.composedPath()[0];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// TS thinks `event` is of type never as it assumes all browsers support
|
|
113
|
+
// `composedPath()`, but browsers without shadow DOM don't.
|
|
114
|
+
return event.target;
|
|
115
|
+
}
|
|
116
|
+
function isEventTargetWithin(event, node) {
|
|
117
|
+
if (node == null) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if ('composedPath' in event) {
|
|
121
|
+
return event.composedPath().includes(node);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// TS thinks `event` is of type never as it assumes all browsers support composedPath, but browsers without shadow dom don't
|
|
125
|
+
const e = event;
|
|
126
|
+
return e.target != null && node.contains(e.target);
|
|
127
|
+
}
|
|
128
|
+
function isRootElement(element) {
|
|
129
|
+
return element.matches('html,body');
|
|
130
|
+
}
|
|
131
|
+
function getDocument(node) {
|
|
132
|
+
return (node == null ? void 0 : node.ownerDocument) || document;
|
|
133
|
+
}
|
|
134
|
+
function isTypeableElement(element) {
|
|
135
|
+
return isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
|
|
136
|
+
}
|
|
137
|
+
function isTypeableCombobox(element) {
|
|
138
|
+
if (!element) return false;
|
|
139
|
+
return element.getAttribute('role') === 'combobox' && isTypeableElement(element);
|
|
140
|
+
}
|
|
141
|
+
function matchesFocusVisible(element) {
|
|
142
|
+
// We don't want to block focus from working with `visibleOnly`
|
|
143
|
+
// (JSDOM doesn't match `:focus-visible` when the element has `:focus`)
|
|
144
|
+
if (!element || isJSDOM()) return true;
|
|
145
|
+
try {
|
|
146
|
+
return element.matches(':focus-visible');
|
|
147
|
+
} catch (_e) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function getFloatingFocusElement(floatingElement) {
|
|
152
|
+
if (!floatingElement) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
// Try to find the element that has `{...getFloatingProps()}` spread on it.
|
|
156
|
+
// This indicates the floating element is acting as a positioning wrapper, and
|
|
157
|
+
// so focus should be managed on the child element with the event handlers and
|
|
158
|
+
// aria props.
|
|
159
|
+
return floatingElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? floatingElement : floatingElement.querySelector("[" + FOCUSABLE_ATTRIBUTE + "]") || floatingElement;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function getNodeChildren(nodes, id, onlyOpenChildren) {
|
|
163
|
+
if (onlyOpenChildren === void 0) {
|
|
164
|
+
onlyOpenChildren = true;
|
|
165
|
+
}
|
|
166
|
+
const directChildren = nodes.filter(node => {
|
|
167
|
+
var _node$context;
|
|
168
|
+
return node.parentId === id && (!onlyOpenChildren || ((_node$context = node.context) == null ? void 0 : _node$context.open.value));
|
|
169
|
+
});
|
|
170
|
+
return directChildren.flatMap(child => [child, ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);
|
|
171
|
+
}
|
|
172
|
+
function getDeepestNode(nodes, id) {
|
|
173
|
+
let deepestNodeId;
|
|
174
|
+
let maxDepth = -1;
|
|
175
|
+
function findDeepest(nodeId, depth) {
|
|
176
|
+
if (depth > maxDepth) {
|
|
177
|
+
deepestNodeId = nodeId;
|
|
178
|
+
maxDepth = depth;
|
|
179
|
+
}
|
|
180
|
+
const children = getNodeChildren(nodes, nodeId);
|
|
181
|
+
children.forEach(child => {
|
|
182
|
+
findDeepest(child.id, depth + 1);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
findDeepest(id, 0);
|
|
186
|
+
return nodes.find(node => node.id === deepestNodeId);
|
|
187
|
+
}
|
|
188
|
+
function getNodeAncestors(nodes, id) {
|
|
189
|
+
var _nodes$find;
|
|
190
|
+
let allAncestors = [];
|
|
191
|
+
let currentParentId = (_nodes$find = nodes.find(node => node.id === id)) == null ? void 0 : _nodes$find.parentId;
|
|
192
|
+
while (currentParentId) {
|
|
193
|
+
const currentNode = nodes.find(node => node.id === currentParentId);
|
|
194
|
+
currentParentId = currentNode == null ? void 0 : currentNode.parentId;
|
|
195
|
+
if (currentNode) {
|
|
196
|
+
allAncestors = allAncestors.concat(currentNode);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return allAncestors;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// actview: `React.SyntheticEvent` → 结构类型(actview 事件是原生 Event)
|
|
203
|
+
|
|
204
|
+
function stopEvent(event) {
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
event.stopPropagation();
|
|
207
|
+
}
|
|
208
|
+
function isReactEvent(event) {
|
|
209
|
+
return 'nativeEvent' in event;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// License: https://github.com/adobe/react-spectrum/blob/b35d5c02fe900badccd0cf1a8f23bb593419f238/packages/@react-aria/utils/src/isVirtualEvent.ts
|
|
213
|
+
function isVirtualClick(event) {
|
|
214
|
+
// FIXME: Firefox is now emitting a deprecation warning for `mozInputSource`.
|
|
215
|
+
// Try to find a workaround for this. `react-aria` source still has the check.
|
|
216
|
+
if (event.mozInputSource === 0 && event.isTrusted) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
if (isAndroid() && event.pointerType) {
|
|
220
|
+
return event.type === 'click' && event.buttons === 1;
|
|
221
|
+
}
|
|
222
|
+
return event.detail === 0 && !event.pointerType;
|
|
223
|
+
}
|
|
224
|
+
function isVirtualPointerEvent(event) {
|
|
225
|
+
if (isJSDOM()) return false;
|
|
226
|
+
return !isAndroid() && event.width === 0 && event.height === 0 || isAndroid() && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
|
|
227
|
+
// iOS VoiceOver returns 0.333• for width/height.
|
|
228
|
+
event.width < 1 && event.height < 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'touch';
|
|
229
|
+
}
|
|
230
|
+
function isMouseLikePointerType(pointerType, strict) {
|
|
231
|
+
// On some Linux machines with Chromium, mouse inputs return a `pointerType`
|
|
232
|
+
// of "pen": https://github.com/floating-ui/floating-ui/issues/2015
|
|
233
|
+
const values = ['mouse', 'pen'];
|
|
234
|
+
if (!strict) {
|
|
235
|
+
values.push('', undefined);
|
|
236
|
+
}
|
|
237
|
+
return values.includes(pointerType);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* actview 版(upstream 为 React hooks:useLatestRef / useEffectEvent)。
|
|
242
|
+
*
|
|
243
|
+
* 与 upstream 的差异:
|
|
244
|
+
* - ref 为 actview 框架类型 `Ref<T>`(.value,非 React 的 .current),创建用 `ref()`
|
|
245
|
+
* - actview 无渲染循环与 effect 概念(setup 只执行一次、render 闭包每次渲染执行)——
|
|
246
|
+
* `useLatestRef` 每次调用返回新的 `ref()`(引用稳定性由调用方负责)
|
|
247
|
+
* - `useEffectEvent` 无 useInsertionEffect 概念:回调在调用时同步写入 ref,
|
|
248
|
+
* 返回的稳定闭包始终调用最新回调。
|
|
249
|
+
* - `useModernLayoutEffect` 不再导出(React 专属,actview 无 layout effect)。
|
|
250
|
+
*/
|
|
251
|
+
function useLatestRef(value) {
|
|
252
|
+
const r = core.ref(value);
|
|
253
|
+
return r;
|
|
254
|
+
}
|
|
255
|
+
function useEffectEvent(callback) {
|
|
256
|
+
const r = core.ref(callback);
|
|
257
|
+
return function () {
|
|
258
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
259
|
+
args[_key] = arguments[_key];
|
|
260
|
+
}
|
|
261
|
+
return r.value == null ? void 0 : r.value(...args);
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// actview: `React.MutableRefObject<T>` → actview 框架类型 `Ref<T>`(.value)、
|
|
266
|
+
// `React.KeyboardEvent` → `KeyboardEventLike`(结构类型,无 React 依赖)
|
|
267
|
+
|
|
268
|
+
function isDifferentGridRow(index, cols, prevRow) {
|
|
269
|
+
return Math.floor(index / cols) !== prevRow;
|
|
270
|
+
}
|
|
271
|
+
function isIndexOutOfListBounds(listRef, index) {
|
|
272
|
+
return index < 0 || index >= listRef.value.length;
|
|
273
|
+
}
|
|
274
|
+
function getMinListIndex(listRef, disabledIndices) {
|
|
275
|
+
return findNonDisabledListIndex(listRef, {
|
|
276
|
+
disabledIndices
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
function getMaxListIndex(listRef, disabledIndices) {
|
|
280
|
+
return findNonDisabledListIndex(listRef, {
|
|
281
|
+
decrement: true,
|
|
282
|
+
startingIndex: listRef.value.length,
|
|
283
|
+
disabledIndices
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function findNonDisabledListIndex(listRef, _temp) {
|
|
287
|
+
let {
|
|
288
|
+
startingIndex = -1,
|
|
289
|
+
decrement = false,
|
|
290
|
+
disabledIndices,
|
|
291
|
+
amount = 1
|
|
292
|
+
} = _temp === void 0 ? {} : _temp;
|
|
293
|
+
let index = startingIndex;
|
|
294
|
+
do {
|
|
295
|
+
index += decrement ? -amount : amount;
|
|
296
|
+
} while (index >= 0 && index <= listRef.value.length - 1 && isListIndexDisabled(listRef, index, disabledIndices));
|
|
297
|
+
return index;
|
|
298
|
+
}
|
|
299
|
+
function getGridNavigatedIndex(listRef, _ref) {
|
|
300
|
+
let {
|
|
301
|
+
event,
|
|
302
|
+
orientation,
|
|
303
|
+
loop,
|
|
304
|
+
rtl,
|
|
305
|
+
cols,
|
|
306
|
+
disabledIndices,
|
|
307
|
+
minIndex,
|
|
308
|
+
maxIndex,
|
|
309
|
+
prevIndex,
|
|
310
|
+
stopEvent: stop = false
|
|
311
|
+
} = _ref;
|
|
312
|
+
let nextIndex = prevIndex;
|
|
313
|
+
if (event.key === ARROW_UP) {
|
|
314
|
+
stop && stopEvent(event);
|
|
315
|
+
if (prevIndex === -1) {
|
|
316
|
+
nextIndex = maxIndex;
|
|
317
|
+
} else {
|
|
318
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
319
|
+
startingIndex: nextIndex,
|
|
320
|
+
amount: cols,
|
|
321
|
+
decrement: true,
|
|
322
|
+
disabledIndices
|
|
323
|
+
});
|
|
324
|
+
if (loop && (prevIndex - cols < minIndex || nextIndex < 0)) {
|
|
325
|
+
const col = prevIndex % cols;
|
|
326
|
+
const maxCol = maxIndex % cols;
|
|
327
|
+
const offset = maxIndex - (maxCol - col);
|
|
328
|
+
if (maxCol === col) {
|
|
329
|
+
nextIndex = maxIndex;
|
|
330
|
+
} else {
|
|
331
|
+
nextIndex = maxCol > col ? offset : offset - cols;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (isIndexOutOfListBounds(listRef, nextIndex)) {
|
|
336
|
+
nextIndex = prevIndex;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (event.key === ARROW_DOWN) {
|
|
340
|
+
stop && stopEvent(event);
|
|
341
|
+
if (prevIndex === -1) {
|
|
342
|
+
nextIndex = minIndex;
|
|
343
|
+
} else {
|
|
344
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
345
|
+
startingIndex: prevIndex,
|
|
346
|
+
amount: cols,
|
|
347
|
+
disabledIndices
|
|
348
|
+
});
|
|
349
|
+
if (loop && prevIndex + cols > maxIndex) {
|
|
350
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
351
|
+
startingIndex: prevIndex % cols - cols,
|
|
352
|
+
amount: cols,
|
|
353
|
+
disabledIndices
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (isIndexOutOfListBounds(listRef, nextIndex)) {
|
|
358
|
+
nextIndex = prevIndex;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Remains on the same row/column.
|
|
363
|
+
if (orientation === 'both') {
|
|
364
|
+
const prevRow = utils.floor(prevIndex / cols);
|
|
365
|
+
if (event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT)) {
|
|
366
|
+
stop && stopEvent(event);
|
|
367
|
+
if (prevIndex % cols !== cols - 1) {
|
|
368
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
369
|
+
startingIndex: prevIndex,
|
|
370
|
+
disabledIndices
|
|
371
|
+
});
|
|
372
|
+
if (loop && isDifferentGridRow(nextIndex, cols, prevRow)) {
|
|
373
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
374
|
+
startingIndex: prevIndex - prevIndex % cols - 1,
|
|
375
|
+
disabledIndices
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
} else if (loop) {
|
|
379
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
380
|
+
startingIndex: prevIndex - prevIndex % cols - 1,
|
|
381
|
+
disabledIndices
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
if (isDifferentGridRow(nextIndex, cols, prevRow)) {
|
|
385
|
+
nextIndex = prevIndex;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT)) {
|
|
389
|
+
stop && stopEvent(event);
|
|
390
|
+
if (prevIndex % cols !== 0) {
|
|
391
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
392
|
+
startingIndex: prevIndex,
|
|
393
|
+
decrement: true,
|
|
394
|
+
disabledIndices
|
|
395
|
+
});
|
|
396
|
+
if (loop && isDifferentGridRow(nextIndex, cols, prevRow)) {
|
|
397
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
398
|
+
startingIndex: prevIndex + (cols - prevIndex % cols),
|
|
399
|
+
decrement: true,
|
|
400
|
+
disabledIndices
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
} else if (loop) {
|
|
404
|
+
nextIndex = findNonDisabledListIndex(listRef, {
|
|
405
|
+
startingIndex: prevIndex + (cols - prevIndex % cols),
|
|
406
|
+
decrement: true,
|
|
407
|
+
disabledIndices
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
if (isDifferentGridRow(nextIndex, cols, prevRow)) {
|
|
411
|
+
nextIndex = prevIndex;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const lastRow = utils.floor(maxIndex / cols) === prevRow;
|
|
415
|
+
if (isIndexOutOfListBounds(listRef, nextIndex)) {
|
|
416
|
+
if (loop && lastRow) {
|
|
417
|
+
nextIndex = event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT) ? maxIndex : findNonDisabledListIndex(listRef, {
|
|
418
|
+
startingIndex: prevIndex - prevIndex % cols - 1,
|
|
419
|
+
disabledIndices
|
|
420
|
+
});
|
|
421
|
+
} else {
|
|
422
|
+
nextIndex = prevIndex;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return nextIndex;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** For each cell index, gets the item index that occupies that cell */
|
|
430
|
+
function createGridCellMap(sizes, cols, dense) {
|
|
431
|
+
const cellMap = [];
|
|
432
|
+
let startIndex = 0;
|
|
433
|
+
sizes.forEach((_ref2, index) => {
|
|
434
|
+
let {
|
|
435
|
+
width,
|
|
436
|
+
height
|
|
437
|
+
} = _ref2;
|
|
438
|
+
if (width > cols) {
|
|
439
|
+
{
|
|
440
|
+
throw new Error("[Floating UI]: Invalid grid - item width at index " + index + " is greater than grid columns");
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
let itemPlaced = false;
|
|
444
|
+
if (dense) {
|
|
445
|
+
startIndex = 0;
|
|
446
|
+
}
|
|
447
|
+
while (!itemPlaced) {
|
|
448
|
+
const targetCells = [];
|
|
449
|
+
for (let i = 0; i < width; i++) {
|
|
450
|
+
for (let j = 0; j < height; j++) {
|
|
451
|
+
targetCells.push(startIndex + i + j * cols);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (startIndex % cols + width <= cols && targetCells.every(cell => cellMap[cell] == null)) {
|
|
455
|
+
targetCells.forEach(cell => {
|
|
456
|
+
cellMap[cell] = index;
|
|
457
|
+
});
|
|
458
|
+
itemPlaced = true;
|
|
459
|
+
} else {
|
|
460
|
+
startIndex++;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// convert into a non-sparse array
|
|
466
|
+
return [...cellMap];
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/** Gets cell index of an item's corner or -1 when index is -1. */
|
|
470
|
+
function getGridCellIndexOfCorner(index, sizes, cellMap, cols, corner) {
|
|
471
|
+
if (index === -1) return -1;
|
|
472
|
+
const firstCellIndex = cellMap.indexOf(index);
|
|
473
|
+
const sizeItem = sizes[index];
|
|
474
|
+
switch (corner) {
|
|
475
|
+
case 'tl':
|
|
476
|
+
return firstCellIndex;
|
|
477
|
+
case 'tr':
|
|
478
|
+
if (!sizeItem) {
|
|
479
|
+
return firstCellIndex;
|
|
480
|
+
}
|
|
481
|
+
return firstCellIndex + sizeItem.width - 1;
|
|
482
|
+
case 'bl':
|
|
483
|
+
if (!sizeItem) {
|
|
484
|
+
return firstCellIndex;
|
|
485
|
+
}
|
|
486
|
+
return firstCellIndex + (sizeItem.height - 1) * cols;
|
|
487
|
+
case 'br':
|
|
488
|
+
return cellMap.lastIndexOf(index);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Gets all cell indices that correspond to the specified indices */
|
|
493
|
+
function getGridCellIndices(indices, cellMap) {
|
|
494
|
+
return cellMap.flatMap((index, cellIndex) => indices.includes(index) ? [cellIndex] : []);
|
|
495
|
+
}
|
|
496
|
+
function isListIndexDisabled(listRef, index, disabledIndices) {
|
|
497
|
+
var _disabledIndices$incl;
|
|
498
|
+
const isExplicitlyDisabled = typeof disabledIndices === 'function' ? disabledIndices(index) : (_disabledIndices$incl = disabledIndices == null ? void 0 : disabledIndices.includes(index)) != null ? _disabledIndices$incl : false;
|
|
499
|
+
if (isExplicitlyDisabled) {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
const element = listRef.value[index];
|
|
503
|
+
if (!element) {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
if (!isElementVisible(element)) {
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// A natively disabled element can never receive focus, so it must always be
|
|
511
|
+
// skipped, even when `disabledIndices` marks it as enabled. Only
|
|
512
|
+
// `aria-disabled` items can be focusable-while-disabled.
|
|
513
|
+
if (element.matches(':disabled')) {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// base-ui 语义:只有未显式传入 disabledIndices 时才检查属性
|
|
518
|
+
// (disabled/aria-disabled)。initial sync 故意不传 disabledIndices
|
|
519
|
+
// (mui/base-ui#2604),使属性禁用的项在打开时也被跳过;导航时传入
|
|
520
|
+
// disabledIndices 数组,由数组控制(aria-disabled 项可聚焦)。
|
|
521
|
+
return !disabledIndices && (element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true');
|
|
522
|
+
}
|
|
523
|
+
function isHiddenByStyles(styles) {
|
|
524
|
+
return styles.visibility === 'hidden' || styles.visibility === 'collapse';
|
|
525
|
+
}
|
|
526
|
+
function isElementVisible(element, styles) {
|
|
527
|
+
if (styles === void 0) {
|
|
528
|
+
styles = element ? getComputedStyle(element) : null;
|
|
529
|
+
}
|
|
530
|
+
if (!element || !element.isConnected || !styles || isHiddenByStyles(styles)) {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
if (typeof element.checkVisibility === 'function') {
|
|
534
|
+
return element.checkVisibility();
|
|
535
|
+
}
|
|
536
|
+
return styles.display !== 'none' && styles.display !== 'contents';
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const getTabbableOptions = () => ({
|
|
540
|
+
getShadowRoot: true,
|
|
541
|
+
displayCheck:
|
|
542
|
+
// JSDOM does not support the `tabbable` library. To solve this we can
|
|
543
|
+
// check if `ResizeObserver` is a real function (not polyfilled), which
|
|
544
|
+
// determines if the current environment is JSDOM-like.
|
|
545
|
+
typeof ResizeObserver === 'function' && ResizeObserver.toString().includes('[native code]') ? 'full' : 'none'
|
|
546
|
+
});
|
|
547
|
+
function getTabbableIn(container, dir) {
|
|
548
|
+
const list = tabbable.tabbable(container, getTabbableOptions());
|
|
549
|
+
const len = list.length;
|
|
550
|
+
if (len === 0) return;
|
|
551
|
+
const active = activeElement(getDocument(container));
|
|
552
|
+
const index = list.indexOf(active);
|
|
553
|
+
const nextIndex = index === -1 ? dir === 1 ? 0 : len - 1 : index + dir;
|
|
554
|
+
return list[nextIndex];
|
|
555
|
+
}
|
|
556
|
+
function getNextTabbable(referenceElement) {
|
|
557
|
+
return getTabbableIn(getDocument(referenceElement).body, 1) || referenceElement;
|
|
558
|
+
}
|
|
559
|
+
function getPreviousTabbable(referenceElement) {
|
|
560
|
+
return getTabbableIn(getDocument(referenceElement).body, -1) || referenceElement;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// actview: `React.FocusEvent` → 结构类型(actview 事件是原生 FocusEvent)
|
|
564
|
+
function isOutsideEvent(event, container) {
|
|
565
|
+
const containerElement = container || event.currentTarget;
|
|
566
|
+
const relatedTarget = event.relatedTarget;
|
|
567
|
+
return !relatedTarget || !contains(containerElement, relatedTarget);
|
|
568
|
+
}
|
|
569
|
+
function disableFocusInside(container) {
|
|
570
|
+
const tabbableElements = tabbable.tabbable(container, getTabbableOptions());
|
|
571
|
+
tabbableElements.forEach(element => {
|
|
572
|
+
element.dataset.tabindex = element.getAttribute('tabindex') || '';
|
|
573
|
+
element.setAttribute('tabindex', '-1');
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
function enableFocusInside(container) {
|
|
577
|
+
const elements = container.querySelectorAll('[data-tabindex]');
|
|
578
|
+
elements.forEach(element => {
|
|
579
|
+
const tabindex = element.dataset.tabindex;
|
|
580
|
+
delete element.dataset.tabindex;
|
|
581
|
+
if (tabindex) {
|
|
582
|
+
element.setAttribute('tabindex', tabindex);
|
|
583
|
+
} else {
|
|
584
|
+
element.removeAttribute('tabindex');
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
exports.activeElement = activeElement;
|
|
590
|
+
exports.contains = contains;
|
|
591
|
+
exports.createGridCellMap = createGridCellMap;
|
|
592
|
+
exports.disableFocusInside = disableFocusInside;
|
|
593
|
+
exports.enableFocusInside = enableFocusInside;
|
|
594
|
+
exports.findNonDisabledListIndex = findNonDisabledListIndex;
|
|
595
|
+
exports.getDeepestNode = getDeepestNode;
|
|
596
|
+
exports.getDocument = getDocument;
|
|
597
|
+
exports.getFloatingFocusElement = getFloatingFocusElement;
|
|
598
|
+
exports.getGridCellIndexOfCorner = getGridCellIndexOfCorner;
|
|
599
|
+
exports.getGridCellIndices = getGridCellIndices;
|
|
600
|
+
exports.getGridNavigatedIndex = getGridNavigatedIndex;
|
|
601
|
+
exports.getMaxListIndex = getMaxListIndex;
|
|
602
|
+
exports.getMinListIndex = getMinListIndex;
|
|
603
|
+
exports.getNextTabbable = getNextTabbable;
|
|
604
|
+
exports.getNodeAncestors = getNodeAncestors;
|
|
605
|
+
exports.getNodeChildren = getNodeChildren;
|
|
606
|
+
exports.getPlatform = getPlatform;
|
|
607
|
+
exports.getPreviousTabbable = getPreviousTabbable;
|
|
608
|
+
exports.getTabbableOptions = getTabbableOptions;
|
|
609
|
+
exports.getTarget = getTarget;
|
|
610
|
+
exports.getUserAgent = getUserAgent;
|
|
611
|
+
exports.isAndroid = isAndroid;
|
|
612
|
+
exports.isDifferentGridRow = isDifferentGridRow;
|
|
613
|
+
exports.isElementVisible = isElementVisible;
|
|
614
|
+
exports.isEventTargetWithin = isEventTargetWithin;
|
|
615
|
+
exports.isHiddenByStyles = isHiddenByStyles;
|
|
616
|
+
exports.isIndexOutOfListBounds = isIndexOutOfListBounds;
|
|
617
|
+
exports.isJSDOM = isJSDOM;
|
|
618
|
+
exports.isListIndexDisabled = isListIndexDisabled;
|
|
619
|
+
exports.isMac = isMac;
|
|
620
|
+
exports.isMouseLikePointerType = isMouseLikePointerType;
|
|
621
|
+
exports.isOutsideEvent = isOutsideEvent;
|
|
622
|
+
exports.isReactEvent = isReactEvent;
|
|
623
|
+
exports.isRootElement = isRootElement;
|
|
624
|
+
exports.isSafari = isSafari;
|
|
625
|
+
exports.isTypeableCombobox = isTypeableCombobox;
|
|
626
|
+
exports.isTypeableElement = isTypeableElement;
|
|
627
|
+
exports.isVirtualClick = isVirtualClick;
|
|
628
|
+
exports.isVirtualPointerEvent = isVirtualPointerEvent;
|
|
629
|
+
exports.matchesFocusVisible = matchesFocusVisible;
|
|
630
|
+
exports.stopEvent = stopEvent;
|
|
631
|
+
exports.useEffectEvent = useEffectEvent;
|
|
632
|
+
exports.useLatestRef = useLatestRef;
|
|
633
|
+
|
|
634
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@actview/core"),require("@floating-ui/utils"),require("tabbable")):"function"==typeof define&&define.amd?define(["exports","@actview/core","@floating-ui/utils","tabbable"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).FloatingUIActviewUtils={},e.ActviewCore,e.FloatingUIUtils,e.tabbable)}(this,(function(e,t,n,i){"use strict";function r(){return"undefined"!=typeof window}function o(e){var t;return(null==e||null==(t=e.ownerDocument)?void 0:t.defaultView)||window}function a(){const e=navigator.userAgentData;return null!=e&&e.platform?e.platform:navigator.platform}function s(){const e=navigator.userAgentData;return e&&Array.isArray(e.brands)?e.brands.map((e=>{let{brand:t,version:n}=e;return t+"/"+n})).join(" "):navigator.userAgent}function d(){const e=/android/i;return e.test(a())||e.test(s())}function u(){return s().includes("jsdom/")}const l="data-floating-ui-focusable",c="ArrowLeft",f="ArrowRight";function b(e){let t=e.activeElement;for(;null!=(null==(n=t)||null==(n=n.shadowRoot)?void 0:n.activeElement);){var n;t=t.shadowRoot.activeElement}return t}function g(e,t){if(!e||!t)return!1;const n=null==t.getRootNode?void 0:t.getRootNode();if(t instanceof Node&&e.contains(t))return!0;if(n&&(i=n,r()&&"undefined"!=typeof ShadowRoot&&(i instanceof ShadowRoot||i instanceof o(i).ShadowRoot))){let n=t;for(;n;){if(e===n)return!0;n=n.parentNode||n.host}}var i;return!1}function v(e){return(null==e?void 0:e.ownerDocument)||document}function h(e){return t=e,!!r()&&(t instanceof HTMLElement||t instanceof o(t).HTMLElement)&&e.matches("input:not([type='hidden']):not([disabled]),[contenteditable]:not([contenteditable='false']),textarea:not([disabled])");var t}function p(e,t,n){void 0===n&&(n=!0);return e.filter((e=>{var i;return e.parentId===t&&(!n||(null==(i=e.context)?void 0:i.open.value))})).flatMap((t=>[t,...p(e,t.id,n)]))}function m(e){e.preventDefault(),e.stopPropagation()}function I(e,t,n){return Math.floor(e/t)!==n}function x(e,t){return t<0||t>=e.value.length}function y(e,t){let{startingIndex:n=-1,decrement:i=!1,disabledIndices:r,amount:o=1}=void 0===t?{}:t,a=n;do{a+=i?-o:o}while(a>=0&&a<=e.value.length-1&&w(e,a,r));return a}function w(e,t,n){var i;if("function"==typeof n?n(t):null!=(i=null==n?void 0:n.includes(t))&&i)return!0;const r=e.value[t];return!!r&&(!E(r)||(!!r.matches(":disabled")||!n&&(r.hasAttribute("disabled")||"true"===r.getAttribute("aria-disabled"))))}function A(e){return"hidden"===e.visibility||"collapse"===e.visibility}function E(e,t){return void 0===t&&(t=e?getComputedStyle(e):null),!(!(e&&e.isConnected&&t)||A(t))&&("function"==typeof e.checkVisibility?e.checkVisibility():"none"!==t.display&&"contents"!==t.display)}const T=()=>({getShadowRoot:!0,displayCheck:"function"==typeof ResizeObserver&&ResizeObserver.toString().includes("[native code]")?"full":"none"});function R(e,t){const n=i.tabbable(e,T()),r=n.length;if(0===r)return;const o=b(v(e)),a=n.indexOf(o);return n[-1===a?1===t?0:r-1:a+t]}e.activeElement=b,e.contains=g,e.createGridCellMap=function(e,t,n){const i=[];let r=0;return e.forEach(((e,o)=>{let{width:a,height:s}=e,d=!1;for(n&&(r=0);!d;){const e=[];for(let n=0;n<a;n++)for(let i=0;i<s;i++)e.push(r+n+i*t);r%t+a<=t&&e.every((e=>null==i[e]))?(e.forEach((e=>{i[e]=o})),d=!0):r++}})),[...i]},e.disableFocusInside=function(e){i.tabbable(e,T()).forEach((e=>{e.dataset.tabindex=e.getAttribute("tabindex")||"",e.setAttribute("tabindex","-1")}))},e.enableFocusInside=function(e){e.querySelectorAll("[data-tabindex]").forEach((e=>{const t=e.dataset.tabindex;delete e.dataset.tabindex,t?e.setAttribute("tabindex",t):e.removeAttribute("tabindex")}))},e.findNonDisabledListIndex=y,e.getDeepestNode=function(e,t){let n,i=-1;return function t(r,o){o>i&&(n=r,i=o),p(e,r).forEach((e=>{t(e.id,o+1)}))}(t,0),e.find((e=>e.id===n))},e.getDocument=v,e.getFloatingFocusElement=function(e){return e?e.hasAttribute(l)?e:e.querySelector("["+l+"]")||e:null},e.getGridCellIndexOfCorner=function(e,t,n,i,r){if(-1===e)return-1;const o=n.indexOf(e),a=t[e];switch(r){case"tl":return o;case"tr":return a?o+a.width-1:o;case"bl":return a?o+(a.height-1)*i:o;case"br":return n.lastIndexOf(e)}},e.getGridCellIndices=function(e,t){return t.flatMap(((t,n)=>e.includes(t)?[n]:[]))},e.getGridNavigatedIndex=function(e,t){let{event:i,orientation:r,loop:o,rtl:a,cols:s,disabledIndices:d,minIndex:u,maxIndex:l,prevIndex:b,stopEvent:g=!1}=t,v=b;if("ArrowUp"===i.key){if(g&&m(i),-1===b)v=l;else if(v=y(e,{startingIndex:v,amount:s,decrement:!0,disabledIndices:d}),o&&(b-s<u||v<0)){const e=b%s,t=l%s,n=l-(t-e);v=t===e?l:t>e?n:n-s}x(e,v)&&(v=b)}if("ArrowDown"===i.key&&(g&&m(i),-1===b?v=u:(v=y(e,{startingIndex:b,amount:s,disabledIndices:d}),o&&b+s>l&&(v=y(e,{startingIndex:b%s-s,amount:s,disabledIndices:d}))),x(e,v)&&(v=b)),"both"===r){const t=n.floor(b/s);i.key===(a?c:f)&&(g&&m(i),b%s!=s-1?(v=y(e,{startingIndex:b,disabledIndices:d}),o&&I(v,s,t)&&(v=y(e,{startingIndex:b-b%s-1,disabledIndices:d}))):o&&(v=y(e,{startingIndex:b-b%s-1,disabledIndices:d})),I(v,s,t)&&(v=b)),i.key===(a?f:c)&&(g&&m(i),b%s!=0?(v=y(e,{startingIndex:b,decrement:!0,disabledIndices:d}),o&&I(v,s,t)&&(v=y(e,{startingIndex:b+(s-b%s),decrement:!0,disabledIndices:d}))):o&&(v=y(e,{startingIndex:b+(s-b%s),decrement:!0,disabledIndices:d})),I(v,s,t)&&(v=b));const r=n.floor(l/s)===t;x(e,v)&&(v=o&&r?i.key===(a?f:c)?l:y(e,{startingIndex:b-b%s-1,disabledIndices:d}):b)}return v},e.getMaxListIndex=function(e,t){return y(e,{decrement:!0,startingIndex:e.value.length,disabledIndices:t})},e.getMinListIndex=function(e,t){return y(e,{disabledIndices:t})},e.getNextTabbable=function(e){return R(v(e).body,1)||e},e.getNodeAncestors=function(e,t){var n;let i=[],r=null==(n=e.find((e=>e.id===t)))?void 0:n.parentId;for(;r;){const t=e.find((e=>e.id===r));r=null==t?void 0:t.parentId,t&&(i=i.concat(t))}return i},e.getNodeChildren=p,e.getPlatform=a,e.getPreviousTabbable=function(e){return R(v(e).body,-1)||e},e.getTabbableOptions=T,e.getTarget=function(e){return"composedPath"in e?e.composedPath()[0]:e.target},e.getUserAgent=s,e.isAndroid=d,e.isDifferentGridRow=I,e.isElementVisible=E,e.isEventTargetWithin=function(e,t){if(null==t)return!1;if("composedPath"in e)return e.composedPath().includes(t);const n=e;return null!=n.target&&t.contains(n.target)},e.isHiddenByStyles=A,e.isIndexOutOfListBounds=x,e.isJSDOM=u,e.isListIndexDisabled=w,e.isMac=function(){return a().toLowerCase().startsWith("mac")&&!navigator.maxTouchPoints},e.isMouseLikePointerType=function(e,t){const n=["mouse","pen"];return t||n.push("",void 0),n.includes(e)},e.isOutsideEvent=function(e,t){const n=t||e.currentTarget,i=e.relatedTarget;return!i||!g(n,i)},e.isReactEvent=function(e){return"nativeEvent"in e},e.isRootElement=function(e){return e.matches("html,body")},e.isSafari=function(){return/apple/i.test(navigator.vendor)},e.isTypeableCombobox=function(e){return!!e&&("combobox"===e.getAttribute("role")&&h(e))},e.isTypeableElement=h,e.isVirtualClick=function(e){return!(0!==e.mozInputSource||!e.isTrusted)||(d()&&e.pointerType?"click"===e.type&&1===e.buttons:0===e.detail&&!e.pointerType)},e.isVirtualPointerEvent=function(e){return!u()&&(!d()&&0===e.width&&0===e.height||d()&&1===e.width&&1===e.height&&0===e.pressure&&0===e.detail&&"mouse"===e.pointerType||e.width<1&&e.height<1&&0===e.pressure&&0===e.detail&&"touch"===e.pointerType)},e.matchesFocusVisible=function(e){if(!e||u())return!0;try{return e.matches(":focus-visible")}catch(e){return!0}},e.stopEvent=m,e.useEffectEvent=function(e){const n=t.ref(e);return function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];return null==n.value?void 0:n.value(...t)}},e.useLatestRef=function(e){return t.ref(e)}}));
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Ref } from '@actview/core';
|
|
2
|
+
import { type DisabledIndices } from '../utils/composite';
|
|
3
|
+
interface KeyboardEventLike {
|
|
4
|
+
key: string;
|
|
5
|
+
which: number;
|
|
6
|
+
altKey: boolean;
|
|
7
|
+
ctrlKey: boolean;
|
|
8
|
+
metaKey: boolean;
|
|
9
|
+
shiftKey: boolean;
|
|
10
|
+
defaultPrevented: boolean;
|
|
11
|
+
}
|
|
12
|
+
type List = Array<HTMLElement | null>;
|
|
13
|
+
type ListRef = Ref<List>;
|
|
14
|
+
export declare function getGridNavigatedIndex(list: List, { event, orientation, loop, onLoop, rtl, cols, disabledIndices, minIndex, maxIndex, prevIndex, stopEvent: stop, }: {
|
|
15
|
+
event: KeyboardEventLike;
|
|
16
|
+
orientation: 'horizontal' | 'vertical' | 'both';
|
|
17
|
+
loop: boolean;
|
|
18
|
+
onLoop?: ((event: KeyboardEventLike, prevIndex: number, nextIndex: number) => number) | undefined;
|
|
19
|
+
rtl: boolean;
|
|
20
|
+
cols: number;
|
|
21
|
+
disabledIndices: DisabledIndices | undefined;
|
|
22
|
+
minIndex: number;
|
|
23
|
+
maxIndex: number;
|
|
24
|
+
prevIndex: number;
|
|
25
|
+
stopEvent?: boolean | undefined;
|
|
26
|
+
}): number;
|
|
27
|
+
/**
|
|
28
|
+
* Positional arguments are deliberate: property names of an options object
|
|
29
|
+
* don't minify, and the signature is locked to the caller via `typeof` on the
|
|
30
|
+
* `grid` option of `useListNavigation`.
|
|
31
|
+
*
|
|
32
|
+
* The injected grid navigator only ever operates on a uniform 1x1 grid (sizes are
|
|
33
|
+
* always `1x1` and packing is never dense), so the cell-map machinery that supports
|
|
34
|
+
* multi-cell items collapses to an identity transform over the item list. Calling
|
|
35
|
+
* `getGridNavigatedIndex` directly keeps the cell-map helpers out of
|
|
36
|
+
* grid-combobox bundles.
|
|
37
|
+
*/
|
|
38
|
+
export declare function gridNavigation(event: KeyboardEventLike, prevIndex: number, listRef: ListRef, orientation: 'horizontal' | 'vertical' | 'both', loop: boolean, rtl: boolean, disabledIndices: DisabledIndices | undefined, minIndex: number, maxIndex: number, cols?: number): number | undefined;
|
|
39
|
+
export {};
|