8000 feat(react): export most utils (#3297) · psy-repos-typescript/floating-ui@1bc8e26 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1bc8e26

Browse files
authored
feat(react): export most utils (floating-ui#3297)
1 parent 18add92 commit 1bc8e26

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+608
-544
lines changed

.changeset/bright-deers-end.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@floating-ui/react": patch
3+
---
4+
5+
feat: export most utils under `@floating-ui/react/utils`. This makes it a lot easier to write your own custom interaction hooks, or copy/paste the existing ones to change the way they are implemented yourself without patching or waiting for features/breaking changes.

packages/react/src/_deprecated-inner.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import {getUserAgent} from '@floating-ui/react/utils';
2-
import {evaluate, max, min, round} from '@floating-ui/utils';
3-
import {detectOverflow, offset, type Derivable} from '@floating-ui/react-dom';
41
import * as React from 'react';
52
import * as ReactDOM from 'react-dom';
3+
import {detectOverflow, offset, type Derivable} from '@floating-ui/react-dom';
4+
import {evaluate, max, min, round} from '@floating-ui/utils';
5+
import {useEffectEvent, getUserAgent} from '@floating-ui/react/utils';
66

7-
import {useEffectEvent} from './hooks/utils/useEffectEvent';
87
import type {
98
DetectOverflowOptions,
109
ElementProps,

packages/react/src/components/Composite.tsx

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
import * as React from 'react';
2+
import {
3+
useEffectEvent,
4+
createGridCellMap,
5+
isListIndexDisabled,
6+
getGridNavigatedIndex,
7+
getMinListIndex,
8+
getMaxListIndex,
9+
getGridCellIndexOfCorner,
10+
getGridCellIndices,
11+
isIndexOutOfListBounds,
12+
findNonDisabledListIndex,
13+
} from '@floating-ui/react/utils';
214

315
import {useMergeRefs} from '../hooks/useMergeRefs';
4-
import {useEffectEvent} from '../hooks/utils/useEffectEvent';
516
import type {Dimensions} from '../types';
17+
import {FloatingList, useListItem} from './FloatingList';
618
import {
719
ARROW_DOWN,
8-
ARROW_LEFT,
920
ARROW_RIGHT,
21+
ARROW_LEFT,
1022
ARROW_UP,
11-
buildCellMap,
12-
findNonDisabledIndex,
13-
getCellIndexOfCorner,
14-
getCellIndices,
15-
getGridNavigatedIndex,
16-
getMaxIndex,
17-
getMinIndex,
18-
isDisabled,
19-
isIndexOutOfBounds,
20-
} from '../utils/composite';
21-
import {FloatingList, useListItem} from './FloatingList';
23+
} from '../utils/constants';
2224

2325
function renderJsx(
2426
render: RenderProp | undefined,
@@ -150,8 +152,8 @@ export const Composite = React.forwardRef<
150152
if (!allKeys.includes(event.key)) return;
151153

152154
let nextIndex = activeIndex;
153-
const minIndex = getMinIndex(elementsRef, disabledIndices);
154-
const maxIndex = getMaxIndex(elementsRef, disabledIndices);
155+
const minIndex = getMinListIndex(elementsRef, disabledIndices);
156+
const maxIndex = getMaxListIndex(elementsRef, disabledIndices);
155157

156158
const horizontalEndKey = rtl ? ARROW_LEFT : ARROW_RIGHT;
157159
const horizontalStartKey = rtl ? ARROW_RIGHT : ARROW_LEFT;
@@ -165,17 +167,17 @@ export const Composite = React.forwardRef<
165167
}));
166168
// To calculate movements on the grid, we use hypothetical cell indices
167169
// as if every item was 1x1, then convert back to real indices.
168-
const cellMap = buildCellMap(sizes, cols, dense);
170+
const cellMap = createGridCellMap(sizes, cols, dense);
169171
const minGridIndex = cellMap.findIndex(
170172
(index) =>
171173
index != null &&
172-
!isDisabled(elementsRef.current, index, disabledIndices),
174+
!isListIndexDisabled(elementsRef, index, disabledIndices),
173175
);
174176
// last enabled index
175177
const maxGridIndex = cellMap.reduce(
176178
(foundIndex: number, index, cellIndex) =>
177179
index != null &&
178-
!isDisabled(elementsRef.current, index, disabledIndices)
180+
!isListIndexDisabled(elementsRef, index, disabledIndices)
179181
? cellIndex
180182
: foundIndex,
181183
-1,
@@ -197,11 +199,11 @@ export const Composite = React.forwardRef<
197199
cols,
198200
// treat undefined (empty grid spaces) as disabled indices so we
199201
// don't end up in them
200-
disabledIndices: getCellIndices(
202+
disabledIndices: getGridCellIndices(
201203
[
202204
...(disabledIndices ||
203205
elementsRef.current.map((_, index) =>
204-
isDisabled(elementsRef.current, index)
206+
isListIndexDisabled(elementsRef, index)
205207
? index
206208
: undefined,
207209
)),
@@ -211,7 +213,7 @@ export const Composite = React.forwardRef<
211213
),
212214
minIndex: minGridIndex,
213215
maxIndex: maxGridIndex,
214-
prevIndex: getCellIndexOfCorner(
216+
prevIndex: getGridCellIndexOfCorner(
215217
activeIndex > maxIndex ? minIndex : activeIndex,
216218
sizes,
217219
cellMap,
@@ -267,7 +269,7 @@ export const Composite = React.forwardRef<
267269
) {
268270
nextIndex = maxIndex;
269271
} else {
270-
nextIndex = findNonDisabledIndex(elementsRef, {
272+
nextIndex = findNonDisabledListIndex(elementsRef, {
271273
startingIndex: nextIndex,
272274
decrement: toStartKeys.includes(event.key),
273275
disabledIndices,
@@ -277,7 +279,7 @@ export const Composite = React.forwardRef<
277279

278280
if (
279281
nextIndex !== activeIndex &&
280-
!isIndexOutOfBounds(elementsRef, nextIndex)
282+
!isIndexOutOfListBounds(elementsRef, nextIndex)
281283
) {
282284
event.stopPropagation();
283285

packages/react/src/components/FloatingArrow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import {getComputedStyle} from '@floating-ui/utils/dom';
21
import * as React from 'react';
2+
import {getComputedStyle} from '@floating-ui/utils/dom';
3+
import {useModernLayoutEffect} from '@floating-ui/react/utils';
34

45
import {useId} from '../hooks/useId';
56
import type {Alignment, FloatingContext, Side} from '../types';
67
import {warn} from '../utils/log';
7-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
88

99
export interface FloatingArrowProps extends React.ComponentPropsWithRef<'svg'> {
1010
// Omit the original `refs` property from the context to avoid issues with

packages/react/src/components/FloatingDelayGroup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
2+
import {useModernLayoutEffect} from '@floating-ui/react/utils';
33
10000
44
import {getDelay} from '../hooks/useHover';
55
import type {FloatingRootContext} from '../types';

packages/react/src/components/FloatingFocusManager.tsx

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import * as React from 'react';
2+
import {tabbable, isTabbable, focusable, type FocusableElement} from 'tabbable';
3+
import {getNodeName, isHTMLElement} from '@floating-ui/utils/dom';
14
import {
25
activeElement,
36
contains,
@@ -7,31 +10,25 @@ import {
710
isVirtualClick,
811
isVirtualPointerEvent,
912
stopEvent,
13+
getNodeAncestors,
14+
getNodeChildren,
15+
getFloatingFocusElement,
16+
useLatestRef,
17+
useEffectEvent,
18+
useModernLayoutEffect,
19+
getTabbableOptions,
20+
isOutsideEvent,
21+
getNextTabbable,
22+
getPreviousTabbable,
1023
} from '@floating-ui/react/utils';
11-
import {getNodeName, isHTMLElement} from '@floating-ui/utils/dom';
12-
import * as React from 'react';
13-
import type {FocusableElement} from 'tabbable';
14-
import {tabbable, isTabbable, focusable} from 'tabbable';
15-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
1624

17-
import {useLatestRef} from '../hooks/utils/useLatestRef';
1825
import type {FloatingRootContext, OpenChangeReason} from '../types';
1926
import {createAttribute} from '../utils/createAttribute';
2027
import {enqueueFocus} from '../utils/enqueueFocus';
21-
import {getAncestors} from '../utils/getAncestors';
22-
import {getChildren} from '../utils/getChildren';
2328
import {markOthers, supportsInert} from '../utils/markOthers';
24-
import {
25-
getNextTabbable,
26-
getPreviousTabbable,
27-
getTabbableOptions,
28-
isOutsideEvent,
29-
} from '../utils/tabbable';
3029
import {usePortalContext} from './FloatingPortal';
3130
import {useFloatingTree} from './FloatingTree';
3231
import {FocusGuard, HIDDEN_STYLES} from './FocusGuard';
33-
import {useEffectEvent} from '../hooks/utils/useEffectEvent';
34-
import {getFloatingFocusElement} from '../utils/getFloatingFocusElement';
3532
import {useLiteMergeRefs} from '../utils/useLiteMergeRefs';
3633

3734
const LIST_LIMIT = 20;
@@ -79,11 +76,10 @@ function handleTabIndex(
7976

8077
const options = getTabbableOptions();
8178
const focusableElements = focusable(floatingFocusElement, options);
82-
const tabbableContent = focusableElements.filter(
83-
(element) =>
84-
isTabbable(element, options) ||
85-
element.getAttribute('data-tabindex') === '0',
86-
);
79+
const tabbableContent = focusableElements.filter((element) => {
80+
const dataTabIndex = element.getAttribute('data-tabindex') || '';
81+
return isTabbable(element, options) || !dataTabIndex.startsWith('-');
82+
});
8783
const tabIndex = floatingFocusElement.getAttribute('tabindex');
8884

8985
if (orderRef.current.includes('floating') || tabbableContent.length === 0) {
@@ -386,12 +382,12 @@ export function FloatingFocusManager(
386382
contains(portalContext?.portalNode, relatedTarget) ||
387383
relatedTarget?.hasAttribute(createAttribute('focus-guard')) ||
388384
(tree &&
389-
(getChildren(tree.nodesRef.current, nodeId).find(
385+
(getNodeChildren(tree.nodesRef.current, nodeId).find(
390386
(node) =>
391387
contains(node.context?.elements.floating, relatedTarget) ||
392388
contains(node.context?.elements.domReference, relatedTarget),
393389
) ||
394-
getAncestors(tree.nodesRef.current, nodeId).find(
390+
getNodeAncestors(tree.nodesRef.current, nodeId).find(
395391
(node) =>
396392
[
397393
node.context?.elements.floating,
@@ -499,7 +495,7 @@ export function FloatingFocusManager(
499495
);
500496

501497
const ancestors = tree
502-
? getAncestors(tree.nodesRef.current, getNodeId())
498+
? getNodeAncestors(tree.nodesRef.current, getNodeId())
503499
: [];
504500
const ancestorFloatingNodes =
505501
tree && !modal
@@ -667,7 +663,7 @@ export function FloatingFocusManager(
667663
const isFocusInsideFloatingTree =
668664
contains(floating, activeEl) ||
669665
(tree &&
670-
getChildren(tree.nodesRef.current, getNodeId()).some((node) =>
666+
getNodeChildren(tree.nodesRef.current, getNodeId()).some((node) =>
671667
contains(node.context?.elements.floating, activeEl),
672668
));
673669

packages/react/src/components/FloatingList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
2+
import {useModernLayoutEffect} from '@floating-ui/react/utils';
33

44
function sortByDocumentPosition(a: Node, b: Node) {
55
const position = a.compareDocumentPosition(b);

packages/react/src/components/FloatingOverlay.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import {getPlatform} from '@floating-ui/react/utils';
21
import * as React from 'react';
3-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
2+
import {useModernLayoutEffect, getPlatform} from '@floating-ui/react/utils';
43

54
let lockCount = 0;
65

packages/react/src/components/FloatingPortal.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import {isElement} from '@floating-ui/utils/dom';
21
import * as React from 'react';
32
import * as ReactDOM from 'react-dom';
4-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
5-
6-
import {useId} from '../hooks/useId';
7-
import type {OpenChangeReason} from '../types';
8-
import {createAttribute} from '../utils/createAttribute';
3+
import {isElement} from '@floating-ui/utils/dom';
94
import {
10-
disableFocusInside,
5+
useModernLayoutEffect,
116
enableFocusInside,
12-
getNextTabbable,
7+
disableFocusInside,
138
getPreviousTabbable,
9+
getNextTabbable,
1410
isOutsideEvent,
15-
} from '../utils/tabbable';
11+
} from '@floating-ui/react/utils';
12+
13+
import {useId} from '../hooks/useId';
14+
import type {OpenChangeReason} from '../types';
15+
import {createAttribute} from '../utils/createAttribute';
1616
import {FocusGuard, HIDDEN_STYLES} from './FocusGuard';
1717

1818
type FocusManagerState = {
@@ -197,7 +197,6 @@ export function FloatingPortal(props: FloatingPortalProps): React.JSX.Element {
197197
React.useEffect(() => {
198198
if (!portalNode) return;
199199
if (open) return;
200-
201200
enableFocusInside(portalNode);
202201
}, [open, portalNode]);
203202

packages/react/src/components/FloatingTree.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import useModernLayoutEffect from 'use-isomorphic-layout-effect';
2+
import {useModernLayoutEffect} from '@floating-ui/react/utils';
33

44
import {useId} from '../hooks/useId';
55
import type {FloatingNodeType, FloatingTreeType, ReferenceType} from '../types';

0 commit comments

Comments
 (0)
0