@react-native-reusables/cli 0.0.17 → 0.0.18
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/__generated/components/primitives/context-menu/context-menu.tsx +50 -28
- package/__generated/components/primitives/context-menu/context-menu.web.tsx +39 -10
- package/__generated/components/primitives/context-menu/types.ts +17 -9
- package/__generated/components/primitives/dropdown-menu/dropdown-menu.tsx +73 -49
- package/__generated/components/primitives/dropdown-menu/dropdown-menu.web.tsx +49 -20
- package/__generated/components/primitives/dropdown-menu/types.ts +10 -9
- package/__generated/components/primitives/hover-card/hover-card.tsx +40 -32
- package/__generated/components/primitives/hover-card/hover-card.web.tsx +28 -23
- package/__generated/components/primitives/hover-card/types.ts +14 -5
- package/__generated/components/primitives/menubar/menubar.tsx +22 -24
- package/__generated/components/primitives/menubar/menubar.web.tsx +10 -5
- package/__generated/components/primitives/menubar/types.ts +3 -2
- package/__generated/components/primitives/popover/popover.tsx +61 -57
- package/__generated/components/primitives/popover/popover.web.tsx +44 -32
- package/__generated/components/primitives/popover/types.ts +7 -13
- package/__generated/components/primitives/select/select.tsx +32 -21
- package/__generated/components/primitives/select/select.web.tsx +26 -13
- package/__generated/components/primitives/select/types.ts +8 -6
- package/__generated/components/primitives/tooltip/tooltip.tsx +38 -32
- package/__generated/components/primitives/tooltip/tooltip.web.tsx +29 -15
- package/__generated/components/primitives/tooltip/types.ts +8 -10
- package/package.json +14 -14
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
BackHandler,
|
|
4
|
-
Pressable,
|
|
5
|
-
View,
|
|
6
|
-
type GestureResponderEvent,
|
|
7
|
-
type LayoutChangeEvent,
|
|
8
|
-
type LayoutRectangle,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
import { useRelativePosition, type LayoutPosition, useControllableState } from '@rnr/hooks';
|
|
1
|
+
import { useAugmentedRef, useRelativePosition, type LayoutPosition } from '@rnr/hooks';
|
|
11
2
|
import { Portal as RNPPortal } from '@rnr/portal';
|
|
12
3
|
import * as Slot from '@rnr/slot';
|
|
13
4
|
import type {
|
|
@@ -17,14 +8,26 @@ import type {
|
|
|
17
8
|
SlottableViewProps,
|
|
18
9
|
ViewRef,
|
|
19
10
|
} from '@rnr/types';
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
import {
|
|
13
|
+
BackHandler,
|
|
14
|
+
Pressable,
|
|
15
|
+
View,
|
|
16
|
+
type GestureResponderEvent,
|
|
17
|
+
type LayoutChangeEvent,
|
|
18
|
+
type LayoutRectangle,
|
|
19
|
+
} from 'react-native';
|
|
20
20
|
import type {
|
|
21
21
|
HoverCardOverlayProps,
|
|
22
22
|
HoverCardPortalProps,
|
|
23
23
|
HoverCardRootProps,
|
|
24
|
+
HoverCardTriggerRef,
|
|
24
25
|
RootContext,
|
|
25
26
|
} from './types';
|
|
26
27
|
|
|
27
28
|
interface IRootContext extends RootContext {
|
|
29
|
+
open: boolean;
|
|
30
|
+
onOpenChange: (open: boolean) => void;
|
|
28
31
|
triggerPosition: LayoutPosition | null;
|
|
29
32
|
setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;
|
|
30
33
|
contentLayout: LayoutRectangle | null;
|
|
@@ -38,23 +41,22 @@ const Root = React.forwardRef<ViewRef, SlottableViewProps & HoverCardRootProps>(
|
|
|
38
41
|
(
|
|
39
42
|
{
|
|
40
43
|
asChild,
|
|
41
|
-
open: openProp,
|
|
42
|
-
defaultOpen,
|
|
43
|
-
onOpenChange: onOpenChangeProp,
|
|
44
44
|
openDelay: _openDelay,
|
|
45
45
|
closeDelay: _closeDelay,
|
|
46
|
+
onOpenChange: onOpenChangeProp,
|
|
46
47
|
...viewProps
|
|
47
48
|
},
|
|
48
49
|
ref
|
|
49
50
|
) => {
|
|
50
51
|
const nativeID = React.useId();
|
|
51
|
-
const [open = false, onOpenChange] = useControllableState({
|
|
52
|
-
prop: openProp,
|
|
53
|
-
defaultProp: defaultOpen,
|
|
54
|
-
onChange: onOpenChangeProp,
|
|
55
|
-
});
|
|
56
52
|
const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);
|
|
57
53
|
const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
|
|
54
|
+
const [open, setOpen] = React.useState(false);
|
|
55
|
+
|
|
56
|
+
function onOpenChange(value: boolean) {
|
|
57
|
+
setOpen(value);
|
|
58
|
+
onOpenChangeProp?.(value);
|
|
59
|
+
}
|
|
58
60
|
|
|
59
61
|
const Component = asChild ? Slot.View : View;
|
|
60
62
|
return (
|
|
@@ -87,36 +89,40 @@ function useRootContext() {
|
|
|
87
89
|
return context;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
const Trigger = React.forwardRef<
|
|
92
|
+
const Trigger = React.forwardRef<HoverCardTriggerRef, SlottablePressableProps>(
|
|
91
93
|
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
|
|
92
|
-
const triggerRef = React.useRef<View>(null);
|
|
93
94
|
const { open, onOpenChange, setTriggerPosition } = useRootContext();
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
const augmentedRef = useAugmentedRef({
|
|
96
97
|
ref,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
methods: {
|
|
99
|
+
open: () => {
|
|
100
|
+
onOpenChange(true);
|
|
101
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
102
|
+
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
close: () => {
|
|
106
|
+
setTriggerPosition(null);
|
|
107
|
+
onOpenChange(false);
|
|
108
|
+
},
|
|
102
109
|
},
|
|
103
|
-
|
|
104
|
-
);
|
|
110
|
+
});
|
|
105
111
|
|
|
106
112
|
function onPress(ev: GestureResponderEvent) {
|
|
107
113
|
if (disabled) return;
|
|
108
|
-
|
|
114
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
109
115
|
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
110
116
|
});
|
|
111
|
-
|
|
112
|
-
onOpenChange(
|
|
117
|
+
|
|
118
|
+
onOpenChange(!open);
|
|
113
119
|
onPressProp?.(ev);
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
const Component = asChild ? Slot.Pressable : Pressable;
|
|
117
123
|
return (
|
|
118
124
|
<Component
|
|
119
|
-
ref={
|
|
125
|
+
ref={augmentedRef}
|
|
120
126
|
aria-disabled={disabled ?? undefined}
|
|
121
127
|
role='button'
|
|
122
128
|
onPress={onPress}
|
|
@@ -266,6 +272,8 @@ Content.displayName = 'ContentNativeHoverCard';
|
|
|
266
272
|
|
|
267
273
|
export { Content, Overlay, Portal, Root, Trigger, useRootContext };
|
|
268
274
|
|
|
275
|
+
export type { HoverCardTriggerRef };
|
|
276
|
+
|
|
269
277
|
function onStartShouldSetResponder() {
|
|
270
278
|
return true;
|
|
271
279
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as HoverCard from '@radix-ui/react-hover-card';
|
|
2
|
-
import
|
|
3
|
-
import { Pressable, View } from 'react-native';
|
|
2
|
+
import { useAugmentedRef } from '@rnr/hooks';
|
|
4
3
|
import * as Slot from '@rnr/slot';
|
|
5
4
|
import type {
|
|
6
5
|
PositionedContentProps,
|
|
@@ -9,40 +8,31 @@ import type {
|
|
|
9
8
|
SlottableViewProps,
|
|
10
9
|
ViewRef,
|
|
11
10
|
} from '@rnr/types';
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
import { Pressable, View } from 'react-native';
|
|
12
13
|
import type {
|
|
13
14
|
HoverCardOverlayProps,
|
|
14
15
|
HoverCardPortalProps,
|
|
15
16
|
HoverCardRootProps,
|
|
17
|
+
HoverCardTriggerRef,
|
|
16
18
|
RootContext,
|
|
17
19
|
} from './types';
|
|
18
|
-
import { useControllableState } from '@rnr/hooks';
|
|
19
20
|
|
|
20
21
|
const HoverCardContext = React.createContext<RootContext | null>(null);
|
|
21
22
|
|
|
22
23
|
const Root = React.forwardRef<ViewRef, SlottableViewProps & HoverCardRootProps>(
|
|
23
|
-
(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
closeDelay,
|
|
31
|
-
...viewProps
|
|
32
|
-
},
|
|
33
|
-
ref
|
|
34
|
-
) => {
|
|
35
|
-
const [open = false, onOpenChange] = useControllableState({
|
|
36
|
-
prop: openProp,
|
|
37
|
-
defaultProp: defaultOpen,
|
|
38
|
-
onChange: onOpenChangeProp,
|
|
39
|
-
});
|
|
24
|
+
({ asChild, openDelay, closeDelay, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
25
|
+
const [open, setOpen] = React.useState(false);
|
|
26
|
+
|
|
27
|
+
function onOpenChange(value: boolean) {
|
|
28
|
+
setOpen(value);
|
|
29
|
+
onOpenChangeProp?.(value);
|
|
30
|
+
}
|
|
40
31
|
const Component = asChild ? Slot.View : View;
|
|
41
32
|
return (
|
|
42
33
|
<HoverCardContext.Provider value={{ open, onOpenChange }}>
|
|
43
34
|
<HoverCard.Root
|
|
44
35
|
open={open}
|
|
45
|
-
defaultOpen={defaultOpen}
|
|
46
36
|
onOpenChange={onOpenChange}
|
|
47
37
|
openDelay={openDelay}
|
|
48
38
|
closeDelay={closeDelay}
|
|
@@ -66,12 +56,25 @@ function useRootContext() {
|
|
|
66
56
|
return context;
|
|
67
57
|
}
|
|
68
58
|
|
|
69
|
-
const Trigger = React.forwardRef<
|
|
59
|
+
const Trigger = React.forwardRef<HoverCardTriggerRef, SlottablePressableProps>(
|
|
70
60
|
({ asChild, ...props }, ref) => {
|
|
61
|
+
const { onOpenChange } = useRootContext();
|
|
62
|
+
const augmentedRef = useAugmentedRef({
|
|
63
|
+
ref,
|
|
64
|
+
methods: {
|
|
65
|
+
open() {
|
|
66
|
+
onOpenChange(true);
|
|
67
|
+
},
|
|
68
|
+
close() {
|
|
69
|
+
onOpenChange(false);
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
71
74
|
const Component = asChild ? Slot.Pressable : Pressable;
|
|
72
75
|
return (
|
|
73
76
|
<HoverCard.Trigger asChild>
|
|
74
|
-
<Component ref={
|
|
77
|
+
<Component ref={augmentedRef} {...props} />
|
|
75
78
|
</HoverCard.Trigger>
|
|
76
79
|
);
|
|
77
80
|
}
|
|
@@ -143,3 +146,5 @@ const Content = React.forwardRef<PressableRef, SlottablePressableProps & Positio
|
|
|
143
146
|
Content.displayName = 'ContentWebHoverCard';
|
|
144
147
|
|
|
145
148
|
export { Content, Overlay, Portal, Root, Trigger, useRootContext };
|
|
149
|
+
|
|
150
|
+
export type { HoverCardTriggerRef };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ForceMountable } from '@rnr/types';
|
|
1
|
+
import type { ForceMountable, PressableRef } from '@rnr/types';
|
|
2
2
|
|
|
3
3
|
interface RootContext {
|
|
4
4
|
open: boolean;
|
|
@@ -8,9 +8,7 @@ interface RootContext {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
interface HoverCardRootProps {
|
|
11
|
-
|
|
12
|
-
defaultOpen?: boolean;
|
|
13
|
-
onOpenChange?: (value: boolean) => void;
|
|
11
|
+
onOpenChange?: (open: boolean) => void;
|
|
14
12
|
/**
|
|
15
13
|
* Platform: WEB ONLY
|
|
16
14
|
* @default 700
|
|
@@ -39,4 +37,15 @@ interface HoverCardOverlayProps extends ForceMountable {
|
|
|
39
37
|
closeOnPress?: boolean;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
interface HoverCardTriggerRef extends PressableRef {
|
|
41
|
+
open: () => void;
|
|
42
|
+
close: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type {
|
|
46
|
+
HoverCardOverlayProps,
|
|
47
|
+
HoverCardPortalProps,
|
|
48
|
+
HoverCardRootProps,
|
|
49
|
+
HoverCardTriggerRef,
|
|
50
|
+
RootContext,
|
|
51
|
+
};
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type LayoutChangeEvent,
|
|
9
|
-
type LayoutRectangle,
|
|
10
|
-
} from 'react-native';
|
|
11
|
-
import { useRelativePosition, type LayoutPosition } from '@rnr/hooks';
|
|
2
|
+
useAugmentedRef,
|
|
3
|
+
useControllableState,
|
|
4
|
+
useRelativePosition,
|
|
5
|
+
type LayoutPosition,
|
|
6
|
+
} from '@rnr/hooks';
|
|
12
7
|
import { Portal as RNPPortal } from '@rnr/portal';
|
|
13
8
|
import * as Slot from '@rnr/slot';
|
|
14
9
|
import type {
|
|
@@ -21,6 +16,16 @@ import type {
|
|
|
21
16
|
TextRef,
|
|
22
17
|
ViewRef,
|
|
23
18
|
} from '@rnr/types';
|
|
19
|
+
import * as React from 'react';
|
|
20
|
+
import {
|
|
21
|
+
BackHandler,
|
|
22
|
+
Pressable,
|
|
23
|
+
Text,
|
|
24
|
+
View,
|
|
25
|
+
type GestureResponderEvent,
|
|
26
|
+
type LayoutChangeEvent,
|
|
27
|
+
type LayoutRectangle,
|
|
28
|
+
} from 'react-native';
|
|
24
29
|
import type {
|
|
25
30
|
MenubarCheckboxItemProps,
|
|
26
31
|
MenubarItemProps,
|
|
@@ -109,21 +114,10 @@ function useMenuContext() {
|
|
|
109
114
|
|
|
110
115
|
const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
111
116
|
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
|
|
112
|
-
const triggerRef =
|
|
117
|
+
const triggerRef = useAugmentedRef({ ref });
|
|
113
118
|
const { value, onValueChange, setTriggerPosition } = useRootContext();
|
|
114
119
|
const { value: menuValue } = useMenuContext();
|
|
115
120
|
|
|
116
|
-
React.useImperativeHandle(
|
|
117
|
-
ref,
|
|
118
|
-
() => {
|
|
119
|
-
if (!triggerRef.current) {
|
|
120
|
-
return new View({});
|
|
121
|
-
}
|
|
122
|
-
return triggerRef.current;
|
|
123
|
-
},
|
|
124
|
-
[triggerRef.current]
|
|
125
|
-
);
|
|
126
|
-
|
|
127
121
|
function onPress(ev: GestureResponderEvent) {
|
|
128
122
|
if (disabled) return;
|
|
129
123
|
triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
@@ -383,7 +377,6 @@ const CheckboxItem = React.forwardRef<
|
|
|
383
377
|
<FormItemContext.Provider value={{ checked }}>
|
|
384
378
|
<Component
|
|
385
379
|
ref={ref}
|
|
386
|
-
key={`checkbox-${nativeID}-${checked}`}
|
|
387
380
|
role='checkbox'
|
|
388
381
|
aria-checked={checked}
|
|
389
382
|
onPress={onPress}
|
|
@@ -522,8 +515,13 @@ const SubContext = React.createContext<{
|
|
|
522
515
|
} | null>(null);
|
|
523
516
|
|
|
524
517
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & MenubarSubProps>(
|
|
525
|
-
({ asChild, open, onOpenChange, ...props }, ref) => {
|
|
518
|
+
({ asChild, defaultOpen, open: openProp, onOpenChange: onOpenChangeProp, ...props }, ref) => {
|
|
526
519
|
const nativeID = React.useId();
|
|
520
|
+
const [open = false, onOpenChange] = useControllableState({
|
|
521
|
+
prop: openProp,
|
|
522
|
+
defaultProp: defaultOpen,
|
|
523
|
+
onChange: onOpenChangeProp,
|
|
524
|
+
});
|
|
527
525
|
|
|
528
526
|
const Component = asChild ? Slot.View : View;
|
|
529
527
|
return (
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as Menubar from '@radix-ui/react-menubar';
|
|
2
|
-
import
|
|
3
|
-
import { GestureResponderEvent, Pressable, Text, View } from 'react-native';
|
|
4
|
-
import { useAugmentedRef } from '@rnr/hooks';
|
|
2
|
+
import { useAugmentedRef, useControllableState } from '@rnr/hooks';
|
|
5
3
|
import * as Slot from '@rnr/slot';
|
|
6
4
|
import type {
|
|
7
5
|
ForceMountable,
|
|
@@ -14,6 +12,8 @@ import type {
|
|
|
14
12
|
ViewRef,
|
|
15
13
|
} from '@rnr/types';
|
|
16
14
|
import { EmptyGestureResponderEvent } from '@rnr/utils';
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import { GestureResponderEvent, Pressable, Text, View } from 'react-native';
|
|
17
17
|
import type {
|
|
18
18
|
MenubarCheckboxItemProps,
|
|
19
19
|
MenubarItemProps,
|
|
@@ -463,7 +463,12 @@ const MenubarSubContext = React.createContext<{
|
|
|
463
463
|
} | null>(null);
|
|
464
464
|
|
|
465
465
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & MenubarSubProps>(
|
|
466
|
-
({ asChild, open, onOpenChange, ...props }, ref) => {
|
|
466
|
+
({ asChild, defaultOpen, open: openProp, onOpenChange: onOpenChangeProp, ...props }, ref) => {
|
|
467
|
+
const [open = false, onOpenChange] = useControllableState({
|
|
468
|
+
prop: openProp,
|
|
469
|
+
defaultProp: defaultOpen,
|
|
470
|
+
onChange: onOpenChangeProp,
|
|
471
|
+
});
|
|
467
472
|
const Component = asChild ? Slot.View : View;
|
|
468
473
|
return (
|
|
469
474
|
<MenubarSubContext.Provider value={{ open, onOpenChange }}>
|
|
@@ -533,8 +538,8 @@ export {
|
|
|
533
538
|
SubContent,
|
|
534
539
|
SubTrigger,
|
|
535
540
|
Trigger,
|
|
536
|
-
useRootContext,
|
|
537
541
|
useMenuContext,
|
|
542
|
+
useRootContext,
|
|
538
543
|
useSubContext,
|
|
539
544
|
};
|
|
540
545
|
|
|
@@ -53,8 +53,9 @@ interface MenubarSeparatorProps {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
interface MenubarSubProps {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
defaultOpen?: boolean;
|
|
57
|
+
open?: boolean;
|
|
58
|
+
onOpenChange?: (value: boolean) => void;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
interface MenubarSubTriggerProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useAugmentedRef, useRelativePosition, type LayoutPosition } from '@rnr/hooks';
|
|
2
2
|
import { Portal as RNPPortal } from '@rnr/portal';
|
|
3
3
|
import * as Slot from '@rnr/slot';
|
|
4
4
|
import type {
|
|
@@ -17,14 +17,11 @@ import {
|
|
|
17
17
|
type LayoutChangeEvent,
|
|
18
18
|
type LayoutRectangle,
|
|
19
19
|
} from 'react-native';
|
|
20
|
-
import type {
|
|
21
|
-
PopoverOverlayProps,
|
|
22
|
-
PopoverPortalProps,
|
|
23
|
-
PopoverRootProps,
|
|
24
|
-
RootContext,
|
|
25
|
-
} from './types';
|
|
20
|
+
import type { PopoverOverlayProps, PopoverPortalProps, PopoverTriggerRef } from './types';
|
|
26
21
|
|
|
27
|
-
interface IRootContext
|
|
22
|
+
interface IRootContext {
|
|
23
|
+
open: boolean;
|
|
24
|
+
onOpenChange: (open: boolean) => void;
|
|
28
25
|
triggerPosition: LayoutPosition | null;
|
|
29
26
|
setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;
|
|
30
27
|
contentLayout: LayoutRectangle | null;
|
|
@@ -34,39 +31,41 @@ interface IRootContext extends RootContext {
|
|
|
34
31
|
|
|
35
32
|
const RootContext = React.createContext<IRootContext | null>(null);
|
|
36
33
|
|
|
37
|
-
const Root = React.forwardRef<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<RootContext.Provider
|
|
51
|
-
value={{
|
|
52
|
-
open,
|
|
53
|
-
onOpenChange,
|
|
54
|
-
contentLayout,
|
|
55
|
-
nativeID,
|
|
56
|
-
setContentLayout,
|
|
57
|
-
setTriggerPosition,
|
|
58
|
-
triggerPosition,
|
|
59
|
-
}}
|
|
60
|
-
>
|
|
61
|
-
<Component ref={ref} {...viewProps} />
|
|
62
|
-
</RootContext.Provider>
|
|
63
|
-
);
|
|
34
|
+
const Root = React.forwardRef<
|
|
35
|
+
ViewRef,
|
|
36
|
+
SlottableViewProps & { onOpenChange?: (open: boolean) => void }
|
|
37
|
+
>(({ asChild, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
38
|
+
const nativeID = React.useId();
|
|
39
|
+
const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);
|
|
40
|
+
const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
|
|
41
|
+
const [open, setOpen] = React.useState(false);
|
|
42
|
+
|
|
43
|
+
function onOpenChange(value: boolean) {
|
|
44
|
+
setOpen(value);
|
|
45
|
+
onOpenChangeProp?.(value);
|
|
64
46
|
}
|
|
65
|
-
|
|
47
|
+
|
|
48
|
+
const Component = asChild ? Slot.View : View;
|
|
49
|
+
return (
|
|
50
|
+
<RootContext.Provider
|
|
51
|
+
value={{
|
|
52
|
+
open,
|
|
53
|
+
onOpenChange,
|
|
54
|
+
contentLayout,
|
|
55
|
+
nativeID,
|
|
56
|
+
setContentLayout,
|
|
57
|
+
setTriggerPosition,
|
|
58
|
+
triggerPosition,
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<Component ref={ref} {...viewProps} />
|
|
62
|
+
</RootContext.Provider>
|
|
63
|
+
);
|
|
64
|
+
});
|
|
66
65
|
|
|
67
66
|
Root.displayName = 'RootNativePopover';
|
|
68
67
|
|
|
69
|
-
function
|
|
68
|
+
function useRootContext() {
|
|
70
69
|
const context = React.useContext(RootContext);
|
|
71
70
|
if (!context) {
|
|
72
71
|
throw new Error('Popover compound components cannot be rendered outside the Popover component');
|
|
@@ -74,36 +73,39 @@ function usePopoverContext() {
|
|
|
74
73
|
return context;
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
const Trigger = React.forwardRef<
|
|
76
|
+
const Trigger = React.forwardRef<PopoverTriggerRef, SlottablePressableProps>(
|
|
78
77
|
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
|
|
79
|
-
const
|
|
80
|
-
const { open, onOpenChange, setTriggerPosition } = usePopoverContext();
|
|
78
|
+
const { onOpenChange, setTriggerPosition } = useRootContext();
|
|
81
79
|
|
|
82
|
-
|
|
80
|
+
const augmentedRef = useAugmentedRef({
|
|
83
81
|
ref,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
methods: {
|
|
83
|
+
open: () => {
|
|
84
|
+
onOpenChange(true);
|
|
85
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
86
|
+
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
close: () => {
|
|
90
|
+
setTriggerPosition(null);
|
|
91
|
+
onOpenChange(false);
|
|
92
|
+
},
|
|
89
93
|
},
|
|
90
|
-
|
|
91
|
-
);
|
|
94
|
+
});
|
|
92
95
|
|
|
93
96
|
function onPress(ev: GestureResponderEvent) {
|
|
94
97
|
if (disabled) return;
|
|
95
|
-
|
|
98
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
96
99
|
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
97
100
|
});
|
|
98
|
-
|
|
99
|
-
onOpenChange(newValue);
|
|
101
|
+
onOpenChange(!open);
|
|
100
102
|
onPressProp?.(ev);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
const Component = asChild ? Slot.Pressable : Pressable;
|
|
104
106
|
return (
|
|
105
107
|
<Component
|
|
106
|
-
ref={
|
|
108
|
+
ref={augmentedRef}
|
|
107
109
|
aria-disabled={disabled ?? undefined}
|
|
108
110
|
role='button'
|
|
109
111
|
onPress={onPress}
|
|
@@ -120,7 +122,7 @@ Trigger.displayName = 'TriggerNativePopover';
|
|
|
120
122
|
* @warning when using a custom `<PortalHost />`, you might have to adjust the Content's sideOffset to account for nav elements like headers.
|
|
121
123
|
*/
|
|
122
124
|
function Portal({ forceMount, hostName, children }: PopoverPortalProps) {
|
|
123
|
-
const value =
|
|
125
|
+
const value = useRootContext();
|
|
124
126
|
|
|
125
127
|
if (!value.triggerPosition) {
|
|
126
128
|
return null;
|
|
@@ -141,7 +143,7 @@ function Portal({ forceMount, hostName, children }: PopoverPortalProps) {
|
|
|
141
143
|
|
|
142
144
|
const Overlay = React.forwardRef<PressableRef, SlottablePressableProps & PopoverOverlayProps>(
|
|
143
145
|
({ asChild, forceMount, onPress: OnPressProp, closeOnPress = true, ...props }, ref) => {
|
|
144
|
-
const { open, onOpenChange, setTriggerPosition, setContentLayout } =
|
|
146
|
+
const { open, onOpenChange, setTriggerPosition, setContentLayout } = useRootContext();
|
|
145
147
|
|
|
146
148
|
function onPress(ev: GestureResponderEvent) {
|
|
147
149
|
if (closeOnPress) {
|
|
@@ -194,7 +196,7 @@ const Content = React.forwardRef<ViewRef, SlottableViewProps & PositionedContent
|
|
|
194
196
|
setContentLayout,
|
|
195
197
|
setTriggerPosition,
|
|
196
198
|
triggerPosition,
|
|
197
|
-
} =
|
|
199
|
+
} = useRootContext();
|
|
198
200
|
|
|
199
201
|
React.useEffect(() => {
|
|
200
202
|
const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
|
|
@@ -253,7 +255,7 @@ Content.displayName = 'ContentNativePopover';
|
|
|
253
255
|
|
|
254
256
|
const Close = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
255
257
|
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
|
|
256
|
-
const { onOpenChange, setContentLayout, setTriggerPosition } =
|
|
258
|
+
const { onOpenChange, setContentLayout, setTriggerPosition } = useRootContext();
|
|
257
259
|
|
|
258
260
|
function onPress(ev: GestureResponderEvent) {
|
|
259
261
|
if (disabled) return;
|
|
@@ -279,7 +281,9 @@ const Close = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
|
279
281
|
|
|
280
282
|
Close.displayName = 'CloseNativePopover';
|
|
281
283
|
|
|
282
|
-
export { Close, Content, Overlay, Portal, Root, Trigger,
|
|
284
|
+
export { Close, Content, Overlay, Portal, Root, Trigger, useRootContext };
|
|
285
|
+
|
|
286
|
+
export type { PopoverTriggerRef };
|
|
283
287
|
|
|
284
288
|
function onStartShouldSetResponder() {
|
|
285
289
|
return true;
|