@cdx-ui/primitives 0.0.1-beta.159 → 0.0.1-beta.160
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/lib/commonjs/dialog/DialogContent.js +17 -3
- package/lib/commonjs/dialog/DialogContent.js.map +1 -1
- package/lib/commonjs/dialog/DialogPopup.js +5 -1
- package/lib/commonjs/dialog/DialogPopup.js.map +1 -1
- package/lib/commonjs/index.js +54 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/menu/MenuCheckboxItem.js +42 -0
- package/lib/commonjs/menu/MenuCheckboxItem.js.map +1 -0
- package/lib/commonjs/menu/MenuItem.js +142 -0
- package/lib/commonjs/menu/MenuItem.js.map +1 -0
- package/lib/commonjs/menu/MenuOverlayRoot.js +80 -0
- package/lib/commonjs/menu/MenuOverlayRoot.js.map +1 -0
- package/lib/commonjs/menu/MenuPopup.js +78 -0
- package/lib/commonjs/menu/MenuPopup.js.map +1 -0
- package/lib/commonjs/menu/MenuRadioGroup.js +48 -0
- package/lib/commonjs/menu/MenuRadioGroup.js.map +1 -0
- package/lib/commonjs/menu/MenuRadioItem.js +32 -0
- package/lib/commonjs/menu/MenuRadioItem.js.map +1 -0
- package/lib/commonjs/menu/MenuRoot.js +139 -0
- package/lib/commonjs/menu/MenuRoot.js.map +1 -0
- package/lib/commonjs/menu/MenuTrigger.js +59 -0
- package/lib/commonjs/menu/MenuTrigger.js.map +1 -0
- package/lib/commonjs/menu/context.js +36 -0
- package/lib/commonjs/menu/context.js.map +1 -0
- package/lib/commonjs/menu/index.js +118 -0
- package/lib/commonjs/menu/index.js.map +1 -0
- package/lib/commonjs/menu/overlayContext.js +30 -0
- package/lib/commonjs/menu/overlayContext.js.map +1 -0
- package/lib/commonjs/menu/types.js +6 -0
- package/lib/commonjs/menu/types.js.map +1 -0
- package/lib/commonjs/menu/useMenuNavigation.js +87 -0
- package/lib/commonjs/menu/useMenuNavigation.js.map +1 -0
- package/lib/commonjs/menu/useMenuOverlayLifecycle.js +68 -0
- package/lib/commonjs/menu/useMenuOverlayLifecycle.js.map +1 -0
- package/lib/commonjs/menu/useMenuTrigger.js +115 -0
- package/lib/commonjs/menu/useMenuTrigger.js.map +1 -0
- package/lib/commonjs/overlay/OverlayContainer.js +2 -3
- package/lib/commonjs/overlay/OverlayContainer.js.map +1 -1
- package/lib/commonjs/overlay/OverlayStack.js +125 -0
- package/lib/commonjs/overlay/OverlayStack.js.map +1 -0
- package/lib/commonjs/overlay/constants.js +7 -1
- package/lib/commonjs/overlay/constants.js.map +1 -1
- package/lib/commonjs/overlay/getAnchoredOverlayPosition.js +188 -0
- package/lib/commonjs/overlay/getAnchoredOverlayPosition.js.map +1 -0
- package/lib/commonjs/overlay/index.js +39 -0
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/commonjs/overlay/useAnchoredOverlay.js +127 -0
- package/lib/commonjs/overlay/useAnchoredOverlay.js.map +1 -0
- package/lib/commonjs/overlay/useDismissOverlay.js +8 -1
- package/lib/commonjs/overlay/useDismissOverlay.js.map +1 -1
- package/lib/commonjs/overlay/useDismissOverlay.web.js +11 -3
- package/lib/commonjs/overlay/useDismissOverlay.web.js.map +1 -1
- package/lib/commonjs/overlay/useEscapeKey.js +8 -1
- package/lib/commonjs/overlay/useEscapeKey.js.map +1 -1
- package/lib/commonjs/overlay/useEscapeKey.web.js +11 -3
- package/lib/commonjs/overlay/useEscapeKey.web.js.map +1 -1
- package/lib/commonjs/overlay/useOverlayPosition.js +16 -7
- package/lib/commonjs/overlay/useOverlayPosition.js.map +1 -1
- package/lib/commonjs/portal/portal.js +86 -63
- package/lib/commonjs/portal/portal.js.map +1 -1
- package/lib/commonjs/select/SelectContent.js +23 -11
- package/lib/commonjs/select/SelectContent.js.map +1 -1
- package/lib/commonjs/select/useListboxNavigation.js +10 -11
- package/lib/commonjs/select/useListboxNavigation.js.map +1 -1
- package/lib/commonjs/tooltip/TooltipContent.js +25 -24
- package/lib/commonjs/tooltip/TooltipContent.js.map +1 -1
- package/lib/commonjs/tooltip/getTooltipPosition.js +37 -84
- package/lib/commonjs/tooltip/getTooltipPosition.js.map +1 -1
- package/lib/module/dialog/DialogContent.js +18 -4
- package/lib/module/dialog/DialogContent.js.map +1 -1
- package/lib/module/dialog/DialogPopup.js +5 -1
- package/lib/module/dialog/DialogPopup.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/menu/MenuCheckboxItem.js +38 -0
- package/lib/module/menu/MenuCheckboxItem.js.map +1 -0
- package/lib/module/menu/MenuItem.js +138 -0
- package/lib/module/menu/MenuItem.js.map +1 -0
- package/lib/module/menu/MenuOverlayRoot.js +76 -0
- package/lib/module/menu/MenuOverlayRoot.js.map +1 -0
- package/lib/module/menu/MenuPopup.js +74 -0
- package/lib/module/menu/MenuPopup.js.map +1 -0
- package/lib/module/menu/MenuRadioGroup.js +44 -0
- package/lib/module/menu/MenuRadioGroup.js.map +1 -0
- package/lib/module/menu/MenuRadioItem.js +28 -0
- package/lib/module/menu/MenuRadioItem.js.map +1 -0
- package/lib/module/menu/MenuRoot.js +135 -0
- package/lib/module/menu/MenuRoot.js.map +1 -0
- package/lib/module/menu/MenuTrigger.js +55 -0
- package/lib/module/menu/MenuTrigger.js.map +1 -0
- package/lib/module/menu/context.js +27 -0
- package/lib/module/menu/context.js.map +1 -0
- package/lib/module/menu/index.js +13 -0
- package/lib/module/menu/index.js.map +1 -0
- package/lib/module/menu/overlayContext.js +24 -0
- package/lib/module/menu/overlayContext.js.map +1 -0
- package/lib/module/menu/types.js +4 -0
- package/lib/module/menu/types.js.map +1 -0
- package/lib/module/menu/useMenuNavigation.js +84 -0
- package/lib/module/menu/useMenuNavigation.js.map +1 -0
- package/lib/module/menu/useMenuOverlayLifecycle.js +63 -0
- package/lib/module/menu/useMenuOverlayLifecycle.js.map +1 -0
- package/lib/module/menu/useMenuTrigger.js +111 -0
- package/lib/module/menu/useMenuTrigger.js.map +1 -0
- package/lib/module/overlay/OverlayContainer.js +2 -3
- package/lib/module/overlay/OverlayContainer.js.map +1 -1
- package/lib/module/overlay/OverlayStack.js +119 -0
- package/lib/module/overlay/OverlayStack.js.map +1 -0
- package/lib/module/overlay/constants.js +6 -0
- package/lib/module/overlay/constants.js.map +1 -1
- package/lib/module/overlay/getAnchoredOverlayPosition.js +183 -0
- package/lib/module/overlay/getAnchoredOverlayPosition.js.map +1 -0
- package/lib/module/overlay/index.js +4 -1
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/module/overlay/useAnchoredOverlay.js +123 -0
- package/lib/module/overlay/useAnchoredOverlay.js.map +1 -0
- package/lib/module/overlay/useDismissOverlay.js +9 -1
- package/lib/module/overlay/useDismissOverlay.js.map +1 -1
- package/lib/module/overlay/useDismissOverlay.web.js +11 -3
- package/lib/module/overlay/useDismissOverlay.web.js.map +1 -1
- package/lib/module/overlay/useEscapeKey.js +9 -1
- package/lib/module/overlay/useEscapeKey.js.map +1 -1
- package/lib/module/overlay/useEscapeKey.web.js +11 -3
- package/lib/module/overlay/useEscapeKey.web.js.map +1 -1
- package/lib/module/overlay/useOverlayPosition.js +16 -7
- package/lib/module/overlay/useOverlayPosition.js.map +1 -1
- package/lib/module/portal/portal.js +86 -64
- package/lib/module/portal/portal.js.map +1 -1
- package/lib/module/select/SelectContent.js +25 -13
- package/lib/module/select/SelectContent.js.map +1 -1
- package/lib/module/select/useListboxNavigation.js +10 -11
- package/lib/module/select/useListboxNavigation.js.map +1 -1
- package/lib/module/tooltip/TooltipContent.js +30 -29
- package/lib/module/tooltip/TooltipContent.js.map +1 -1
- package/lib/module/tooltip/getTooltipPosition.js +37 -84
- package/lib/module/tooltip/getTooltipPosition.js.map +1 -1
- package/lib/typescript/dialog/DialogContent.d.ts.map +1 -1
- package/lib/typescript/dialog/DialogPopup.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/menu/MenuCheckboxItem.d.ts +6 -0
- package/lib/typescript/menu/MenuCheckboxItem.d.ts.map +1 -0
- package/lib/typescript/menu/MenuItem.d.ts +8 -0
- package/lib/typescript/menu/MenuItem.d.ts.map +1 -0
- package/lib/typescript/menu/MenuOverlayRoot.d.ts +8 -0
- package/lib/typescript/menu/MenuOverlayRoot.d.ts.map +1 -0
- package/lib/typescript/menu/MenuPopup.d.ts +8 -0
- package/lib/typescript/menu/MenuPopup.d.ts.map +1 -0
- package/lib/typescript/menu/MenuRadioGroup.d.ts +8 -0
- package/lib/typescript/menu/MenuRadioGroup.d.ts.map +1 -0
- package/lib/typescript/menu/MenuRadioItem.d.ts +6 -0
- package/lib/typescript/menu/MenuRadioItem.d.ts.map +1 -0
- package/lib/typescript/menu/MenuRoot.d.ts +8 -0
- package/lib/typescript/menu/MenuRoot.d.ts.map +1 -0
- package/lib/typescript/menu/MenuTrigger.d.ts +7 -0
- package/lib/typescript/menu/MenuTrigger.d.ts.map +1 -0
- package/lib/typescript/menu/context.d.ts +15 -0
- package/lib/typescript/menu/context.d.ts.map +1 -0
- package/lib/typescript/menu/index.d.ts +12 -0
- package/lib/typescript/menu/index.d.ts.map +1 -0
- package/lib/typescript/menu/overlayContext.d.ts +35 -0
- package/lib/typescript/menu/overlayContext.d.ts.map +1 -0
- package/lib/typescript/menu/types.d.ts +104 -0
- package/lib/typescript/menu/types.d.ts.map +1 -0
- package/lib/typescript/menu/useMenuNavigation.d.ts +16 -0
- package/lib/typescript/menu/useMenuNavigation.d.ts.map +1 -0
- package/lib/typescript/menu/useMenuOverlayLifecycle.d.ts +15 -0
- package/lib/typescript/menu/useMenuOverlayLifecycle.d.ts.map +1 -0
- package/lib/typescript/menu/useMenuTrigger.d.ts +35 -0
- package/lib/typescript/menu/useMenuTrigger.d.ts.map +1 -0
- package/lib/typescript/overlay/OverlayContainer.d.ts.map +1 -1
- package/lib/typescript/overlay/OverlayStack.d.ts +46 -0
- package/lib/typescript/overlay/OverlayStack.d.ts.map +1 -0
- package/lib/typescript/overlay/constants.d.ts +5 -0
- package/lib/typescript/overlay/constants.d.ts.map +1 -1
- package/lib/typescript/overlay/getAnchoredOverlayPosition.d.ts +45 -0
- package/lib/typescript/overlay/getAnchoredOverlayPosition.d.ts.map +1 -0
- package/lib/typescript/overlay/index.d.ts +5 -2
- package/lib/typescript/overlay/index.d.ts.map +1 -1
- package/lib/typescript/overlay/useAnchoredOverlay.d.ts +15 -0
- package/lib/typescript/overlay/useAnchoredOverlay.d.ts.map +1 -0
- package/lib/typescript/overlay/useDismissOverlay.d.ts +2 -1
- package/lib/typescript/overlay/useDismissOverlay.d.ts.map +1 -1
- package/lib/typescript/overlay/useDismissOverlay.web.d.ts +2 -1
- package/lib/typescript/overlay/useDismissOverlay.web.d.ts.map +1 -1
- package/lib/typescript/overlay/useEscapeKey.d.ts +2 -1
- package/lib/typescript/overlay/useEscapeKey.d.ts.map +1 -1
- package/lib/typescript/overlay/useEscapeKey.web.d.ts +2 -1
- package/lib/typescript/overlay/useEscapeKey.web.d.ts.map +1 -1
- package/lib/typescript/overlay/useOverlayPosition.d.ts +5 -1
- package/lib/typescript/overlay/useOverlayPosition.d.ts.map +1 -1
- package/lib/typescript/portal/portal.d.ts +3 -0
- package/lib/typescript/portal/portal.d.ts.map +1 -1
- package/lib/typescript/select/SelectContent.d.ts.map +1 -1
- package/lib/typescript/select/useListboxNavigation.d.ts.map +1 -1
- package/lib/typescript/tooltip/TooltipContent.d.ts.map +1 -1
- package/lib/typescript/tooltip/getTooltipPosition.d.ts +6 -8
- package/lib/typescript/tooltip/getTooltipPosition.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/dialog/DialogContent.tsx +16 -4
- package/src/dialog/DialogPopup.tsx +5 -1
- package/src/index.ts +23 -0
- package/src/menu/MenuCheckboxItem.tsx +51 -0
- package/src/menu/MenuItem.tsx +197 -0
- package/src/menu/MenuOverlayRoot.tsx +100 -0
- package/src/menu/MenuPopup.tsx +81 -0
- package/src/menu/MenuRadioGroup.tsx +48 -0
- package/src/menu/MenuRadioItem.tsx +32 -0
- package/src/menu/MenuRoot.tsx +190 -0
- package/src/menu/MenuTrigger.tsx +57 -0
- package/src/menu/context.tsx +38 -0
- package/src/menu/index.ts +36 -0
- package/src/menu/overlayContext.tsx +61 -0
- package/src/menu/types.ts +119 -0
- package/src/menu/useMenuNavigation.ts +102 -0
- package/src/menu/useMenuOverlayLifecycle.ts +77 -0
- package/src/menu/useMenuTrigger.ts +161 -0
- package/src/overlay/OverlayContainer.tsx +3 -1
- package/src/overlay/OverlayStack.tsx +202 -0
- package/src/overlay/constants.ts +6 -0
- package/src/overlay/getAnchoredOverlayPosition.ts +326 -0
- package/src/overlay/index.ts +29 -1
- package/src/overlay/useAnchoredOverlay.ts +153 -0
- package/src/overlay/useDismissOverlay.ts +10 -2
- package/src/overlay/useDismissOverlay.web.ts +9 -2
- package/src/overlay/useEscapeKey.ts +13 -1
- package/src/overlay/useEscapeKey.web.ts +13 -3
- package/src/overlay/useOverlayPosition.ts +35 -8
- package/src/portal/portal.tsx +109 -69
- package/src/select/SelectContent.tsx +29 -17
- package/src/select/useListboxNavigation.ts +12 -9
- package/src/tooltip/TooltipContent.tsx +32 -34
- package/src/tooltip/getTooltipPosition.ts +58 -125
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import React, { forwardRef, useCallback, useRef, type ComponentRef } from 'react';
|
|
2
|
-
import { Platform,
|
|
2
|
+
import { Platform, View } from 'react-native';
|
|
3
3
|
import { FadeIn, FadeOut } from 'react-native-reanimated';
|
|
4
4
|
import { composeEventHandlers, mergeRefs } from '@cdx-ui/utils';
|
|
5
|
-
import {
|
|
6
|
-
OverlayContainer,
|
|
7
|
-
useAnchorPosition,
|
|
8
|
-
useDismissOverlay,
|
|
9
|
-
useOverlayPosition,
|
|
10
|
-
} from '../overlay';
|
|
5
|
+
import { OverlayContainer, useAnchoredOverlay, useDismissOverlay } from '../overlay';
|
|
11
6
|
import { Slot } from '../slot';
|
|
12
7
|
import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
|
|
13
8
|
import { useSelectContext } from './context';
|
|
@@ -21,7 +16,7 @@ export interface SelectContentProps extends ISelectContentProps {
|
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
export const SelectContent = forwardRef<ComponentRef<typeof View>, SelectContentProps>(
|
|
24
|
-
({ asChild, children, enteringAnimation, exitingAnimation, ...props }, ref) => {
|
|
19
|
+
({ asChild, children, enteringAnimation, exitingAnimation, onLayout, style, ...props }, ref) => {
|
|
25
20
|
const {
|
|
26
21
|
open,
|
|
27
22
|
setOpen,
|
|
@@ -49,14 +44,23 @@ export const SelectContent = forwardRef<ComponentRef<typeof View>, SelectContent
|
|
|
49
44
|
}
|
|
50
45
|
}, []);
|
|
51
46
|
|
|
52
|
-
const mergedRef = mergeRefs(ref, focusOnMount as unknown as React.Ref<View>);
|
|
53
|
-
|
|
54
47
|
const dismiss = useCallback(() => setOpen(false), [setOpen]);
|
|
55
48
|
|
|
56
|
-
const
|
|
57
|
-
const
|
|
49
|
+
const overlayOpen = open && !native;
|
|
50
|
+
const {
|
|
51
|
+
floatingRef,
|
|
52
|
+
onFloatingLayout,
|
|
53
|
+
style: overlayStyle,
|
|
54
|
+
position,
|
|
55
|
+
} = useAnchoredOverlay(triggerRef, overlayOpen, {
|
|
56
|
+
placement: 'bottom-start',
|
|
57
|
+
offset: 4,
|
|
58
|
+
collisionBehavior: 'flip-shift',
|
|
59
|
+
width: 'anchor',
|
|
60
|
+
});
|
|
61
|
+
const mergedRef = mergeRefs(ref, focusOnMount as unknown as React.Ref<View>, floatingRef);
|
|
58
62
|
|
|
59
|
-
useDismissOverlay(
|
|
63
|
+
useDismissOverlay(overlayOpen, contentRef, [triggerRef], dismiss);
|
|
60
64
|
|
|
61
65
|
const { handleKeyDown } = useListboxNavigation({
|
|
62
66
|
items,
|
|
@@ -77,7 +81,7 @@ export const SelectContent = forwardRef<ComponentRef<typeof View>, SelectContent
|
|
|
77
81
|
setActiveValue,
|
|
78
82
|
});
|
|
79
83
|
|
|
80
|
-
if (
|
|
84
|
+
if (!overlayOpen) {
|
|
81
85
|
return null;
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -99,18 +103,26 @@ export const SelectContent = forwardRef<ComponentRef<typeof View>, SelectContent
|
|
|
99
103
|
onDismiss={dismiss}
|
|
100
104
|
entering={enteringAnimation ?? FadeIn.duration(150)}
|
|
101
105
|
exiting={exitingAnimation ?? FadeOut.duration(100)}
|
|
102
|
-
style={position.style}
|
|
103
106
|
>
|
|
104
107
|
<Comp
|
|
105
108
|
ref={mergedRef}
|
|
109
|
+
onLayout={composeEventHandlers(onLayout, onFloatingLayout)}
|
|
110
|
+
style={[style, overlayStyle]}
|
|
106
111
|
role="listbox"
|
|
107
112
|
id={contentId}
|
|
108
113
|
aria-labelledby={triggerId}
|
|
109
114
|
{...props}
|
|
110
|
-
{...mergeDataAttributes(
|
|
115
|
+
{...mergeDataAttributes(
|
|
116
|
+
props,
|
|
117
|
+
dataAttributes({
|
|
118
|
+
state: 'open',
|
|
119
|
+
side: position?.resolvedPlacement.side,
|
|
120
|
+
align: position?.resolvedPlacement.align,
|
|
121
|
+
}),
|
|
122
|
+
)}
|
|
111
123
|
{...webProps}
|
|
112
124
|
>
|
|
113
|
-
|
|
125
|
+
{children}
|
|
114
126
|
</Comp>
|
|
115
127
|
</OverlayContainer>
|
|
116
128
|
);
|
|
@@ -28,6 +28,18 @@ export function useListboxNavigation({
|
|
|
28
28
|
|
|
29
29
|
const handleKeyDown = useCallback(
|
|
30
30
|
(e: any) => {
|
|
31
|
+
if (e.key === 'Escape') {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
e.stopPropagation?.();
|
|
34
|
+
onDismissRef.current();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (e.key === 'Tab') {
|
|
39
|
+
onDismissRef.current();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
const enabledItems = getEnabledItems();
|
|
32
44
|
if (enabledItems.length === 0) {
|
|
33
45
|
return;
|
|
@@ -67,15 +79,6 @@ export function useListboxNavigation({
|
|
|
67
79
|
}
|
|
68
80
|
break;
|
|
69
81
|
}
|
|
70
|
-
case 'Escape': {
|
|
71
|
-
e.preventDefault();
|
|
72
|
-
onDismissRef.current();
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case 'Tab': {
|
|
76
|
-
onDismissRef.current();
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
[activeValue, getEnabledItems, setActiveValue],
|
|
@@ -1,26 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
useLayoutEffect,
|
|
5
|
-
useMemo,
|
|
6
|
-
useRef,
|
|
7
|
-
type ComponentRef,
|
|
8
|
-
} from 'react';
|
|
9
|
-
import { Platform, StyleSheet, View, useWindowDimensions } from 'react-native';
|
|
10
|
-
import { mergeRefs } from '@cdx-ui/utils';
|
|
1
|
+
import { forwardRef, useCallback, useLayoutEffect, type ComponentRef } from 'react';
|
|
2
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
3
|
+
import { composeEventHandlers, mergeRefs } from '@cdx-ui/utils';
|
|
11
4
|
import { Portal } from '../portal';
|
|
12
|
-
import {
|
|
5
|
+
import { useAnchoredOverlay, useDismissOverlay, useEscapeKey } from '../overlay';
|
|
13
6
|
import { createPortalFn } from '../utils/createPortal';
|
|
14
7
|
import { Slot } from '../slot';
|
|
15
8
|
import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
|
|
16
9
|
import { TooltipProvider, useTooltipContext } from './context';
|
|
17
|
-
import {
|
|
10
|
+
import { TOOLTIP_Z_INDEX } from './getTooltipPosition';
|
|
18
11
|
import type { ITooltipContentProps } from './types';
|
|
19
12
|
|
|
20
13
|
export interface TooltipContentProps extends ITooltipContentProps {}
|
|
21
14
|
|
|
22
15
|
export const TooltipContent = forwardRef<ComponentRef<typeof View>, TooltipContentProps>(
|
|
23
|
-
({ asChild, children, ...props }, ref) => {
|
|
16
|
+
({ asChild, children, onLayout, ...props }, ref) => {
|
|
24
17
|
const contextValue = useTooltipContext();
|
|
25
18
|
const {
|
|
26
19
|
open,
|
|
@@ -31,11 +24,22 @@ export const TooltipContent = forwardRef<ComponentRef<typeof View>, TooltipConte
|
|
|
31
24
|
trigger,
|
|
32
25
|
triggerRef,
|
|
33
26
|
contentId,
|
|
27
|
+
resolvedPlacement,
|
|
34
28
|
setResolvedPlacement,
|
|
35
29
|
} = contextValue;
|
|
36
30
|
|
|
37
|
-
const
|
|
38
|
-
|
|
31
|
+
const {
|
|
32
|
+
floatingRef,
|
|
33
|
+
onFloatingLayout,
|
|
34
|
+
style: overlayStyle,
|
|
35
|
+
position,
|
|
36
|
+
} = useAnchoredOverlay(triggerRef, open && !isDisabled, {
|
|
37
|
+
placement,
|
|
38
|
+
offset,
|
|
39
|
+
collisionBehavior: 'none',
|
|
40
|
+
width: 'content',
|
|
41
|
+
});
|
|
42
|
+
const mergedRef = mergeRefs(ref, floatingRef);
|
|
39
43
|
|
|
40
44
|
const handleDismiss = useCallback(() => {
|
|
41
45
|
setOpen(false);
|
|
@@ -44,27 +48,20 @@ export const TooltipContent = forwardRef<ComponentRef<typeof View>, TooltipConte
|
|
|
44
48
|
const shouldDismissOnInteraction =
|
|
45
49
|
trigger === 'click' && Platform.OS === 'web' && open && !isDisabled;
|
|
46
50
|
|
|
47
|
-
useDismissOverlay(shouldDismissOnInteraction,
|
|
51
|
+
useDismissOverlay(shouldDismissOnInteraction, floatingRef, [triggerRef], handleDismiss);
|
|
48
52
|
useEscapeKey(shouldDismissOnInteraction, handleDismiss);
|
|
49
53
|
|
|
50
|
-
const { width, height } = useWindowDimensions();
|
|
51
|
-
const anchorLayout = useAnchorPosition(triggerRef, open && !isDisabled);
|
|
52
|
-
|
|
53
|
-
const position = useMemo(() => {
|
|
54
|
-
if (!anchorLayout) {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return getTooltipAnchorStyle(anchorLayout, placement, offset, { width, height });
|
|
59
|
-
}, [anchorLayout, height, offset, placement, width]);
|
|
60
|
-
|
|
61
54
|
useLayoutEffect(() => {
|
|
62
|
-
if (
|
|
63
|
-
|
|
55
|
+
if (
|
|
56
|
+
position &&
|
|
57
|
+
(resolvedPlacement?.side !== position.resolvedPlacement.side ||
|
|
58
|
+
resolvedPlacement.align !== position.resolvedPlacement.align)
|
|
59
|
+
) {
|
|
60
|
+
setResolvedPlacement(position.resolvedPlacement);
|
|
64
61
|
}
|
|
65
|
-
}, [position, setResolvedPlacement]);
|
|
62
|
+
}, [position, resolvedPlacement, setResolvedPlacement]);
|
|
66
63
|
|
|
67
|
-
if (!open || isDisabled
|
|
64
|
+
if (!open || isDisabled) {
|
|
68
65
|
return null;
|
|
69
66
|
}
|
|
70
67
|
|
|
@@ -82,16 +79,17 @@ export const TooltipContent = forwardRef<ComponentRef<typeof View>, TooltipConte
|
|
|
82
79
|
|
|
83
80
|
const popup = (
|
|
84
81
|
<TooltipProvider value={contextValue}>
|
|
85
|
-
<View pointerEvents="none" style={
|
|
82
|
+
<View pointerEvents="none" style={[overlayStyle, { zIndex: TOOLTIP_Z_INDEX }]}>
|
|
86
83
|
<Comp
|
|
87
84
|
ref={mergedRef}
|
|
85
|
+
onLayout={composeEventHandlers(onLayout, onFloatingLayout)}
|
|
88
86
|
{...props}
|
|
89
87
|
{...webProps}
|
|
90
88
|
{...mergeDataAttributes(
|
|
91
89
|
props,
|
|
92
90
|
dataAttributes({
|
|
93
|
-
side: position.
|
|
94
|
-
align: position.
|
|
91
|
+
side: position?.resolvedPlacement.side,
|
|
92
|
+
align: position?.resolvedPlacement.align,
|
|
95
93
|
state: 'open',
|
|
96
94
|
}),
|
|
97
95
|
)}
|
|
@@ -1,88 +1,57 @@
|
|
|
1
1
|
import { Platform, type ViewStyle } from 'react-native';
|
|
2
2
|
import type { AnchorLayout } from '../overlay/useAnchorPosition';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'left-start',
|
|
16
|
-
'left-end',
|
|
17
|
-
'right',
|
|
18
|
-
'right-start',
|
|
19
|
-
'right-end',
|
|
20
|
-
] as const;
|
|
21
|
-
|
|
22
|
-
export type TooltipPlacement = (typeof TOOLTIP_PLACEMENTS)[number];
|
|
3
|
+
import {
|
|
4
|
+
getAnchoredOverlayPosition,
|
|
5
|
+
OVERLAY_PLACEMENTS,
|
|
6
|
+
type OverlayAlign,
|
|
7
|
+
type OverlayPlacement,
|
|
8
|
+
type OverlaySide,
|
|
9
|
+
type ResolvedOverlayPlacement,
|
|
10
|
+
} from '../overlay/getAnchoredOverlayPosition';
|
|
11
|
+
|
|
12
|
+
export const TOOLTIP_PLACEMENTS = OVERLAY_PLACEMENTS;
|
|
13
|
+
|
|
14
|
+
export type TooltipPlacement = OverlayPlacement;
|
|
23
15
|
export type TooltipTriggerMode = 'hover' | 'focus' | 'click';
|
|
24
|
-
export type TooltipSide =
|
|
25
|
-
export type TooltipAlign =
|
|
26
|
-
|
|
27
|
-
export interface ResolvedTooltipPlacement {
|
|
28
|
-
readonly side: TooltipSide;
|
|
29
|
-
readonly align: TooltipAlign;
|
|
30
|
-
}
|
|
16
|
+
export type TooltipSide = OverlaySide;
|
|
17
|
+
export type TooltipAlign = OverlayAlign;
|
|
18
|
+
export type ResolvedTooltipPlacement = Readonly<ResolvedOverlayPlacement>;
|
|
31
19
|
|
|
32
20
|
export const TOOLTIP_Z_INDEX = 9999;
|
|
33
|
-
const SCREEN_PADDING = 8;
|
|
34
21
|
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
function getCompatibilityTransform({
|
|
23
|
+
side,
|
|
24
|
+
align,
|
|
25
|
+
}: ResolvedTooltipPlacement): ViewStyle['transform'] {
|
|
26
|
+
if (side === 'top') {
|
|
27
|
+
return align === 'center'
|
|
28
|
+
? ([{ translateX: '-50%' }, { translateY: '-100%' }] as ViewStyle['transform'])
|
|
29
|
+
: align === 'end'
|
|
30
|
+
? ([{ translateX: '-100%' }, { translateY: '-100%' }] as ViewStyle['transform'])
|
|
31
|
+
: ([{ translateY: '-100%' }] as ViewStyle['transform']);
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
if (side === 'bottom') {
|
|
35
|
+
return align === 'center'
|
|
36
|
+
? ([{ translateX: '-50%' }] as ViewStyle['transform'])
|
|
37
|
+
: align === 'end'
|
|
38
|
+
? ([{ translateX: '-100%' }] as ViewStyle['transform'])
|
|
39
|
+
: undefined;
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
alignPreference: TooltipAlign,
|
|
54
|
-
): ResolvedTooltipPlacement {
|
|
55
|
-
const spaceTop = anchor.y - SCREEN_PADDING;
|
|
56
|
-
const spaceBottom = viewport.height - anchor.y - anchor.height - SCREEN_PADDING;
|
|
57
|
-
const spaceLeft = anchor.x - SCREEN_PADDING;
|
|
58
|
-
const spaceRight = viewport.width - anchor.x - anchor.width - SCREEN_PADDING;
|
|
59
|
-
|
|
60
|
-
const spaces: { side: TooltipSide; value: number }[] = [
|
|
61
|
-
{ side: 'top', value: spaceTop },
|
|
62
|
-
{ side: 'bottom', value: spaceBottom },
|
|
63
|
-
{ side: 'left', value: spaceLeft },
|
|
64
|
-
{ side: 'right', value: spaceRight },
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
const best = spaces.reduce((current, next) => (next.value > current.value ? next : current));
|
|
68
|
-
|
|
69
|
-
return { side: best.side, align: alignPreference };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function getAlignOffset(
|
|
73
|
-
anchor: AnchorLayout,
|
|
74
|
-
align: TooltipAlign,
|
|
75
|
-
axis: 'horizontal' | 'vertical',
|
|
76
|
-
): number {
|
|
77
|
-
if (align === 'start') {
|
|
78
|
-
return axis === 'horizontal' ? anchor.x : anchor.y;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (align === 'end') {
|
|
82
|
-
return axis === 'horizontal' ? anchor.x + anchor.width : anchor.y + anchor.height;
|
|
42
|
+
if (side === 'left') {
|
|
43
|
+
return align === 'center'
|
|
44
|
+
? ([{ translateX: '-100%' }, { translateY: '-50%' }] as ViewStyle['transform'])
|
|
45
|
+
: align === 'end'
|
|
46
|
+
? ([{ translateX: '-100%' }, { translateY: '-100%' }] as ViewStyle['transform'])
|
|
47
|
+
: ([{ translateX: '-100%' }] as ViewStyle['transform']);
|
|
83
48
|
}
|
|
84
49
|
|
|
85
|
-
return
|
|
50
|
+
return align === 'center'
|
|
51
|
+
? ([{ translateY: '-50%' }] as ViewStyle['transform'])
|
|
52
|
+
: align === 'end'
|
|
53
|
+
? ([{ translateY: '-100%' }] as ViewStyle['transform'])
|
|
54
|
+
: undefined;
|
|
86
55
|
}
|
|
87
56
|
|
|
88
57
|
export function getTooltipAnchorStyle(
|
|
@@ -91,57 +60,21 @@ export function getTooltipAnchorStyle(
|
|
|
91
60
|
offset: number,
|
|
92
61
|
viewport: { width: number; height: number },
|
|
93
62
|
): { style: ViewStyle; resolved: ResolvedTooltipPlacement } {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
placement === 'auto-start' ? 'start' : placement === 'auto-end' ? 'end' : 'center',
|
|
101
|
-
)
|
|
102
|
-
: parsed;
|
|
103
|
-
|
|
63
|
+
const result = getAnchoredOverlayPosition(anchor, { width: 0, height: 0 }, viewport, {
|
|
64
|
+
placement,
|
|
65
|
+
offset,
|
|
66
|
+
collisionBehavior: 'none',
|
|
67
|
+
});
|
|
68
|
+
const resolved = result.resolvedPlacement;
|
|
104
69
|
const position = (Platform.OS === 'web' ? 'fixed' : 'absolute') as ViewStyle['position'];
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
? ([{ translateX: '-100%' }, { translateY: '-100%' }] as ViewStyle['transform'])
|
|
116
|
-
: ([{ translateY: '-100%' }] as ViewStyle['transform']);
|
|
117
|
-
} else if (side === 'bottom') {
|
|
118
|
-
style.top = anchor.y + anchor.height + offset;
|
|
119
|
-
style.left = getAlignOffset(anchor, align, 'horizontal');
|
|
120
|
-
style.transform =
|
|
121
|
-
align === 'center'
|
|
122
|
-
? ([{ translateX: '-50%' }] as ViewStyle['transform'])
|
|
123
|
-
: align === 'end'
|
|
124
|
-
? ([{ translateX: '-100%' }] as ViewStyle['transform'])
|
|
125
|
-
: undefined;
|
|
126
|
-
} else if (side === 'left') {
|
|
127
|
-
style.left = anchor.x - offset;
|
|
128
|
-
style.top = getAlignOffset(anchor, align, 'vertical');
|
|
129
|
-
style.transform =
|
|
130
|
-
align === 'center'
|
|
131
|
-
? ([{ translateX: '-100%' }, { translateY: '-50%' }] as ViewStyle['transform'])
|
|
132
|
-
: align === 'end'
|
|
133
|
-
? ([{ translateX: '-100%' }, { translateY: '-100%' }] as ViewStyle['transform'])
|
|
134
|
-
: ([{ translateX: '-100%' }] as ViewStyle['transform']);
|
|
135
|
-
} else {
|
|
136
|
-
style.left = anchor.x + anchor.width + offset;
|
|
137
|
-
style.top = getAlignOffset(anchor, align, 'vertical');
|
|
138
|
-
style.transform =
|
|
139
|
-
align === 'center'
|
|
140
|
-
? ([{ translateY: '-50%' }] as ViewStyle['transform'])
|
|
141
|
-
: align === 'end'
|
|
142
|
-
? ([{ translateY: '-100%' }] as ViewStyle['transform'])
|
|
143
|
-
: undefined;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return { style, resolved };
|
|
70
|
+
return {
|
|
71
|
+
style: {
|
|
72
|
+
position,
|
|
73
|
+
left: result.style.left,
|
|
74
|
+
top: result.style.top,
|
|
75
|
+
zIndex: TOOLTIP_Z_INDEX,
|
|
76
|
+
transform: getCompatibilityTransform(resolved),
|
|
77
|
+
},
|
|
78
|
+
resolved,
|
|
79
|
+
};
|
|
147
80
|
}
|