@react-native-reusables/cli 0.0.16 → 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/__generated/components/ui/progress.tsx +57 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type GestureResponderEvent,
|
|
9
|
-
type LayoutChangeEvent,
|
|
10
|
-
type LayoutRectangle,
|
|
11
|
-
} from 'react-native';
|
|
12
|
-
import { useRelativePosition, type LayoutPosition } from '@rnr/hooks';
|
|
2
|
+
useAugmentedRef,
|
|
3
|
+
useControllableState,
|
|
4
|
+
useRelativePosition,
|
|
5
|
+
type LayoutPosition,
|
|
6
|
+
} from '@rnr/hooks';
|
|
13
7
|
import { Portal as RNPPortal } from '@rnr/portal';
|
|
14
8
|
import * as Slot from '@rnr/slot';
|
|
15
9
|
import type {
|
|
@@ -22,6 +16,17 @@ import type {
|
|
|
22
16
|
TextRef,
|
|
23
17
|
ViewRef,
|
|
24
18
|
} from '@rnr/types';
|
|
19
|
+
import * as React from 'react';
|
|
20
|
+
import {
|
|
21
|
+
BackHandler,
|
|
22
|
+
Pressable,
|
|
23
|
+
Text,
|
|
24
|
+
View,
|
|
25
|
+
type AccessibilityActionEvent,
|
|
26
|
+
type GestureResponderEvent,
|
|
27
|
+
type LayoutChangeEvent,
|
|
28
|
+
type LayoutRectangle,
|
|
29
|
+
} from 'react-native';
|
|
25
30
|
import type {
|
|
26
31
|
ContextMenuCheckboxItemProps,
|
|
27
32
|
ContextMenuItemProps,
|
|
@@ -33,9 +38,12 @@ import type {
|
|
|
33
38
|
ContextMenuSeparatorProps,
|
|
34
39
|
ContextMenuSubProps,
|
|
35
40
|
ContextMenuSubTriggerProps,
|
|
41
|
+
ContextMenuTriggerRef,
|
|
36
42
|
} from './types';
|
|
37
43
|
|
|
38
44
|
interface IRootContext extends ContextMenuRootProps {
|
|
45
|
+
open: boolean;
|
|
46
|
+
onOpenChange: (open: boolean) => void;
|
|
39
47
|
pressPosition: LayoutPosition | null;
|
|
40
48
|
setPressPosition: (pressPosition: LayoutPosition | null) => void;
|
|
41
49
|
contentLayout: LayoutRectangle | null;
|
|
@@ -46,10 +54,16 @@ interface IRootContext extends ContextMenuRootProps {
|
|
|
46
54
|
const RootContext = React.createContext<IRootContext | null>(null);
|
|
47
55
|
|
|
48
56
|
const Root = React.forwardRef<ViewRef, SlottableViewProps & ContextMenuRootProps>(
|
|
49
|
-
({ asChild,
|
|
57
|
+
({ asChild, relativeTo = 'longPress', onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
50
58
|
const nativeID = React.useId();
|
|
51
59
|
const [pressPosition, setPressPosition] = React.useState<LayoutPosition | null>(null);
|
|
52
60
|
const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
|
|
61
|
+
const [open, setOpen] = React.useState(false);
|
|
62
|
+
|
|
63
|
+
function onOpenChange(value: boolean) {
|
|
64
|
+
setOpen(value);
|
|
65
|
+
onOpenChangeProp?.(value);
|
|
66
|
+
}
|
|
53
67
|
|
|
54
68
|
const Component = asChild ? Slot.View : View;
|
|
55
69
|
return (
|
|
@@ -85,7 +99,7 @@ function useRootContext() {
|
|
|
85
99
|
|
|
86
100
|
const accessibilityActions = [{ name: 'longpress' }];
|
|
87
101
|
|
|
88
|
-
const Trigger = React.forwardRef<
|
|
102
|
+
const Trigger = React.forwardRef<ContextMenuTriggerRef, SlottablePressableProps>(
|
|
89
103
|
(
|
|
90
104
|
{
|
|
91
105
|
asChild,
|
|
@@ -96,19 +110,22 @@ const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
|
96
110
|
},
|
|
97
111
|
ref
|
|
98
112
|
) => {
|
|
99
|
-
const triggerRef = React.useRef<View>(null);
|
|
100
113
|
const { open, onOpenChange, relativeTo, setPressPosition } = useRootContext();
|
|
101
|
-
|
|
102
|
-
React.useImperativeHandle(
|
|
114
|
+
const augmentedRef = useAugmentedRef({
|
|
103
115
|
ref,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
methods: {
|
|
117
|
+
open: () => {
|
|
118
|
+
onOpenChange(true);
|
|
119
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
120
|
+
setPressPosition({ width, pageX, pageY: pageY, height });
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
close: () => {
|
|
124
|
+
setPressPosition(null);
|
|
125
|
+
onOpenChange(false);
|
|
126
|
+
},
|
|
109
127
|
},
|
|
110
|
-
|
|
111
|
-
);
|
|
128
|
+
});
|
|
112
129
|
|
|
113
130
|
function onLongPress(ev: GestureResponderEvent) {
|
|
114
131
|
if (disabled) return;
|
|
@@ -121,7 +138,7 @@ const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
|
121
138
|
});
|
|
122
139
|
}
|
|
123
140
|
if (relativeTo === 'trigger') {
|
|
124
|
-
|
|
141
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
125
142
|
setPressPosition({ width, pageX, pageY: pageY, height });
|
|
126
143
|
});
|
|
127
144
|
}
|
|
@@ -147,7 +164,7 @@ const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
|
147
164
|
const Component = asChild ? Slot.Pressable : Pressable;
|
|
148
165
|
return (
|
|
149
166
|
<Component
|
|
150
|
-
ref={
|
|
167
|
+
ref={augmentedRef}
|
|
151
168
|
aria-disabled={disabled ?? undefined}
|
|
152
169
|
role='button'
|
|
153
170
|
onLongPress={onLongPress}
|
|
@@ -386,7 +403,6 @@ const CheckboxItem = React.forwardRef<
|
|
|
386
403
|
<FormItemContext.Provider value={{ checked }}>
|
|
387
404
|
<Component
|
|
388
405
|
ref={ref}
|
|
389
|
-
key={`checkbox-${nativeID}-${checked}`}
|
|
390
406
|
role='checkbox'
|
|
391
407
|
aria-checked={checked}
|
|
392
408
|
onPress={onPress}
|
|
@@ -524,8 +540,13 @@ const SubContext = React.createContext<{
|
|
|
524
540
|
} | null>(null);
|
|
525
541
|
|
|
526
542
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & ContextMenuSubProps>(
|
|
527
|
-
({ asChild, open, onOpenChange, ...props }, ref) => {
|
|
543
|
+
({ asChild, defaultOpen, open: openProp, onOpenChange: onOpenChangeProp, ...props }, ref) => {
|
|
528
544
|
const nativeID = React.useId();
|
|
545
|
+
const [open = false, onOpenChange] = useControllableState({
|
|
546
|
+
prop: openProp,
|
|
547
|
+
defaultProp: defaultOpen,
|
|
548
|
+
onChange: onOpenChangeProp,
|
|
549
|
+
});
|
|
529
550
|
|
|
530
551
|
const Component = asChild ? Slot.View : View;
|
|
531
552
|
return (
|
|
@@ -567,7 +588,6 @@ const SubTrigger = React.forwardRef<
|
|
|
567
588
|
return (
|
|
568
589
|
<Component
|
|
569
590
|
ref={ref}
|
|
570
|
-
key={`sub-trigger-${nativeID}-${open}`}
|
|
571
591
|
aria-valuetext={textValue}
|
|
572
592
|
role='menuitem'
|
|
573
593
|
aria-expanded={open}
|
|
@@ -621,6 +641,8 @@ export {
|
|
|
621
641
|
useSubContext,
|
|
622
642
|
};
|
|
623
643
|
|
|
644
|
+
export type { ContextMenuTriggerRef };
|
|
645
|
+
|
|
624
646
|
function onStartShouldSetResponder() {
|
|
625
647
|
return true;
|
|
626
648
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import * as ContextMenu from '@radix-ui/react-context-menu';
|
|
2
|
-
import
|
|
3
|
-
import { GestureResponderEvent, Pressable, Text, View } from 'react-native';
|
|
2
|
+
import { useAugmentedRef, useControllableState } from '@rnr/hooks';
|
|
4
3
|
import * as Slot from '@rnr/slot';
|
|
5
|
-
import { useAugmentedRef } from '@rnr/hooks';
|
|
6
4
|
import type {
|
|
7
5
|
ForceMountable,
|
|
8
6
|
PositionedContentProps,
|
|
@@ -13,6 +11,9 @@ import type {
|
|
|
13
11
|
TextRef,
|
|
14
12
|
ViewRef,
|
|
15
13
|
} from '@rnr/types';
|
|
14
|
+
import { EmptyGestureResponderEvent } from '@rnr/utils';
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import { GestureResponderEvent, Pressable, Text, View } from 'react-native';
|
|
16
17
|
import type {
|
|
17
18
|
ContextMenuCheckboxItemProps,
|
|
18
19
|
ContextMenuItemProps,
|
|
@@ -24,13 +25,23 @@ import type {
|
|
|
24
25
|
ContextMenuSeparatorProps,
|
|
25
26
|
ContextMenuSubProps,
|
|
26
27
|
ContextMenuSubTriggerProps,
|
|
28
|
+
ContextMenuTriggerRef,
|
|
27
29
|
} from './types';
|
|
28
|
-
import { EmptyGestureResponderEvent } from '@rnr/utils';
|
|
29
30
|
|
|
30
|
-
const ContextMenuContext = React.createContext<
|
|
31
|
+
const ContextMenuContext = React.createContext<{
|
|
32
|
+
open: boolean;
|
|
33
|
+
onOpenChange: (open: boolean) => void;
|
|
34
|
+
} | null>(null);
|
|
31
35
|
|
|
32
36
|
const Root = React.forwardRef<ViewRef, SlottableViewProps & ContextMenuRootProps>(
|
|
33
|
-
({ asChild,
|
|
37
|
+
({ asChild, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
38
|
+
const [open, setOpen] = React.useState(false);
|
|
39
|
+
|
|
40
|
+
function onOpenChange(value: boolean) {
|
|
41
|
+
setOpen(value);
|
|
42
|
+
onOpenChangeProp?.(value);
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
const Component = asChild ? Slot.View : View;
|
|
35
46
|
return (
|
|
36
47
|
<ContextMenuContext.Provider value={{ open, onOpenChange }}>
|
|
@@ -54,10 +65,20 @@ function useRootContext() {
|
|
|
54
65
|
return context;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
const Trigger = React.forwardRef<
|
|
68
|
+
const Trigger = React.forwardRef<ContextMenuTriggerRef, SlottablePressableProps>(
|
|
58
69
|
({ asChild, disabled = false, ...props }, ref) => {
|
|
59
|
-
const augmentedRef = useAugmentedRef({ ref });
|
|
60
70
|
const { open } = useRootContext();
|
|
71
|
+
const augmentedRef = useAugmentedRef({
|
|
72
|
+
ref,
|
|
73
|
+
methods: {
|
|
74
|
+
open() {
|
|
75
|
+
console.warn('Warning: `open()` is only for Native platforms');
|
|
76
|
+
},
|
|
77
|
+
close() {
|
|
78
|
+
console.warn('Warning: `close()` is only for Native platforms');
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
61
82
|
|
|
62
83
|
React.useLayoutEffect(() => {
|
|
63
84
|
if (augmentedRef.current) {
|
|
@@ -425,7 +446,13 @@ const ContextMenuSubContext = React.createContext<{
|
|
|
425
446
|
} | null>(null);
|
|
426
447
|
|
|
427
448
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & ContextMenuSubProps>(
|
|
428
|
-
({ asChild, open, onOpenChange, ...props }, ref) => {
|
|
449
|
+
({ asChild, defaultOpen, open: openProp, onOpenChange: onOpenChangeProp, ...props }, ref) => {
|
|
450
|
+
const [open = false, onOpenChange] = useControllableState({
|
|
451
|
+
prop: openProp,
|
|
452
|
+
defaultProp: defaultOpen,
|
|
453
|
+
onChange: onOpenChangeProp,
|
|
454
|
+
});
|
|
455
|
+
|
|
429
456
|
const Component = asChild ? Slot.View : View;
|
|
430
457
|
return (
|
|
431
458
|
<ContextMenuSubContext.Provider value={{ open, onOpenChange }}>
|
|
@@ -495,10 +522,12 @@ export {
|
|
|
495
522
|
SubContent,
|
|
496
523
|
SubTrigger,
|
|
497
524
|
Trigger,
|
|
498
|
-
useSubContext,
|
|
499
525
|
useRootContext,
|
|
526
|
+
useSubContext,
|
|
500
527
|
};
|
|
501
528
|
|
|
529
|
+
export type { ContextMenuTriggerRef };
|
|
530
|
+
|
|
502
531
|
function onSelected(ev: Event) {
|
|
503
532
|
ev.preventDefault();
|
|
504
533
|
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import { ForceMountable } from '@rnr/types';
|
|
1
|
+
import { ForceMountable, PressableRef } from '@rnr/types';
|
|
2
2
|
|
|
3
3
|
interface ContextMenuRootProps {
|
|
4
|
-
|
|
5
|
-
* Platform: NATIVE ONLY
|
|
6
|
-
*/
|
|
7
|
-
open: boolean;
|
|
8
|
-
onOpenChange: (value: boolean) => void;
|
|
9
|
-
|
|
4
|
+
onOpenChange?: (open: boolean) => void;
|
|
10
5
|
/**
|
|
11
6
|
* Platform: NATIVE ONLY
|
|
12
7
|
*/
|
|
@@ -60,14 +55,26 @@ interface ContextMenuSeparatorProps {
|
|
|
60
55
|
}
|
|
61
56
|
|
|
62
57
|
interface ContextMenuSubProps {
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
defaultOpen?: boolean;
|
|
59
|
+
open?: boolean;
|
|
60
|
+
onOpenChange?: (value: boolean) => void;
|
|
65
61
|
}
|
|
66
62
|
|
|
67
63
|
interface ContextMenuSubTriggerProps {
|
|
68
64
|
textValue?: string;
|
|
69
65
|
}
|
|
70
66
|
|
|
67
|
+
interface ContextMenuTriggerRef extends PressableRef {
|
|
68
|
+
/**
|
|
69
|
+
* Platform: NATIVE ONLY
|
|
70
|
+
*/
|
|
71
|
+
open: () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Platform: NATIVE ONLY
|
|
74
|
+
*/
|
|
75
|
+
close: () => void;
|
|
76
|
+
}
|
|
77
|
+
|
|
71
78
|
export type {
|
|
72
79
|
ContextMenuCheckboxItemProps,
|
|
73
80
|
ContextMenuItemProps,
|
|
@@ -79,4 +86,5 @@ export type {
|
|
|
79
86
|
ContextMenuSeparatorProps,
|
|
80
87
|
ContextMenuSubProps,
|
|
81
88
|
ContextMenuSubTriggerProps,
|
|
89
|
+
ContextMenuTriggerRef,
|
|
82
90
|
};
|
|
@@ -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
|
DropdownMenuCheckboxItemProps,
|
|
26
31
|
DropdownMenuItemProps,
|
|
@@ -28,13 +33,15 @@ import type {
|
|
|
28
33
|
DropdownMenuPortalProps,
|
|
29
34
|
DropdownMenuRadioGroupProps,
|
|
30
35
|
DropdownMenuRadioItemProps,
|
|
31
|
-
DropdownMenuRootProps,
|
|
32
36
|
DropdownMenuSeparatorProps,
|
|
33
37
|
DropdownMenuSubProps,
|
|
34
38
|
DropdownMenuSubTriggerProps,
|
|
39
|
+
DropdownMenuTriggerRef,
|
|
35
40
|
} from './types';
|
|
36
41
|
|
|
37
|
-
interface IRootContext
|
|
42
|
+
interface IRootContext {
|
|
43
|
+
open: boolean;
|
|
44
|
+
onOpenChange: (open: boolean) => void;
|
|
38
45
|
triggerPosition: LayoutPosition | null;
|
|
39
46
|
setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;
|
|
40
47
|
contentLayout: LayoutRectangle | null;
|
|
@@ -44,30 +51,37 @@ interface IRootContext extends DropdownMenuRootProps {
|
|
|
44
51
|
|
|
45
52
|
const RootContext = React.createContext<IRootContext | null>(null);
|
|
46
53
|
|
|
47
|
-
const Root = React.forwardRef<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
contentLayout,
|
|
60
|
-
setContentLayout,
|
|
61
|
-
nativeID,
|
|
62
|
-
setTriggerPosition,
|
|
63
|
-
triggerPosition,
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
<Component ref={ref} {...viewProps} />
|
|
67
|
-
</RootContext.Provider>
|
|
68
|
-
);
|
|
54
|
+
const Root = React.forwardRef<
|
|
55
|
+
ViewRef,
|
|
56
|
+
SlottableViewProps & { onOpenChange?: (open: boolean) => void }
|
|
57
|
+
>(({ asChild, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
58
|
+
const nativeID = React.useId();
|
|
59
|
+
const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);
|
|
60
|
+
const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
|
|
61
|
+
const [open, setOpen] = React.useState(false);
|
|
62
|
+
|
|
63
|
+
function onOpenChange(open: boolean) {
|
|
64
|
+
setOpen(open);
|
|
65
|
+
onOpenChangeProp?.(open);
|
|
69
66
|
}
|
|
70
|
-
|
|
67
|
+
|
|
68
|
+
const Component = asChild ? Slot.View : View;
|
|
69
|
+
return (
|
|
70
|
+
<RootContext.Provider
|
|
71
|
+
value={{
|
|
72
|
+
open,
|
|
73
|
+
onOpenChange,
|
|
74
|
+
contentLayout,
|
|
75
|
+
setContentLayout,
|
|
76
|
+
nativeID,
|
|
77
|
+
setTriggerPosition,
|
|
78
|
+
triggerPosition,
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<Component ref={ref} {...viewProps} />
|
|
82
|
+
</RootContext.Provider>
|
|
83
|
+
);
|
|
84
|
+
});
|
|
71
85
|
|
|
72
86
|
Root.displayName = 'RootNativeDropdownMenu';
|
|
73
87
|
|
|
@@ -81,25 +95,29 @@ function useRootContext() {
|
|
|
81
95
|
return context;
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
const Trigger = React.forwardRef<
|
|
98
|
+
const Trigger = React.forwardRef<DropdownMenuTriggerRef, SlottablePressableProps>(
|
|
85
99
|
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
|
|
86
|
-
const triggerRef = React.useRef<View>(null);
|
|
87
100
|
const { open, onOpenChange, setTriggerPosition } = useRootContext();
|
|
88
101
|
|
|
89
|
-
|
|
102
|
+
const augmentedRef = useAugmentedRef({
|
|
90
103
|
ref,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
methods: {
|
|
105
|
+
open: () => {
|
|
106
|
+
onOpenChange(true);
|
|
107
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
108
|
+
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
close: () => {
|
|
112
|
+
setTriggerPosition(null);
|
|
113
|
+
onOpenChange(false);
|
|
114
|
+
},
|
|
96
115
|
},
|
|
97
|
-
|
|
98
|
-
);
|
|
116
|
+
});
|
|
99
117
|
|
|
100
118
|
function onPress(ev: GestureResponderEvent) {
|
|
101
119
|
if (disabled) return;
|
|
102
|
-
|
|
120
|
+
augmentedRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
|
|
103
121
|
setTriggerPosition({ width, pageX, pageY: pageY, height });
|
|
104
122
|
});
|
|
105
123
|
const newValue = !open;
|
|
@@ -110,7 +128,7 @@ const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
|
110
128
|
const Component = asChild ? Slot.Pressable : Pressable;
|
|
111
129
|
return (
|
|
112
130
|
<Component
|
|
113
|
-
ref={
|
|
131
|
+
ref={augmentedRef}
|
|
114
132
|
aria-disabled={disabled ?? undefined}
|
|
115
133
|
role='button'
|
|
116
134
|
onPress={onPress}
|
|
@@ -349,7 +367,6 @@ const CheckboxItem = React.forwardRef<
|
|
|
349
367
|
<FormItemContext.Provider value={{ checked }}>
|
|
350
368
|
<Component
|
|
351
369
|
ref={ref}
|
|
352
|
-
key={`checkbox-${nativeID}-${checked}`}
|
|
353
370
|
role='checkbox'
|
|
354
371
|
aria-checked={checked}
|
|
355
372
|
onPress={onPress}
|
|
@@ -487,8 +504,13 @@ const SubContext = React.createContext<{
|
|
|
487
504
|
} | null>(null);
|
|
488
505
|
|
|
489
506
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuSubProps>(
|
|
490
|
-
({ asChild, open, onOpenChange, ...props }, ref) => {
|
|
507
|
+
({ asChild, defaultOpen, open: openProp, onOpenChange: onOpenChangeProp, ...props }, ref) => {
|
|
491
508
|
const nativeID = React.useId();
|
|
509
|
+
const [open = false, onOpenChange] = useControllableState({
|
|
510
|
+
prop: openProp,
|
|
511
|
+
defaultProp: defaultOpen,
|
|
512
|
+
onChange: onOpenChangeProp,
|
|
513
|
+
});
|
|
492
514
|
|
|
493
515
|
const Component = asChild ? Slot.View : View;
|
|
494
516
|
return (
|
|
@@ -582,3 +604,5 @@ export {
|
|
|
582
604
|
useRootContext,
|
|
583
605
|
useSubContext,
|
|
584
606
|
};
|
|
607
|
+
|
|
608
|
+
export type { DropdownMenuTriggerRef };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
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
|
DropdownMenuCheckboxItemProps,
|
|
19
19
|
DropdownMenuItemProps,
|
|
@@ -21,26 +21,37 @@ import type {
|
|
|
21
21
|
DropdownMenuPortalProps,
|
|
22
22
|
DropdownMenuRadioGroupProps,
|
|
23
23
|
DropdownMenuRadioItemProps,
|
|
24
|
-
DropdownMenuRootProps,
|
|
25
24
|
DropdownMenuSeparatorProps,
|
|
26
25
|
DropdownMenuSubProps,
|
|
27
26
|
DropdownMenuSubTriggerProps,
|
|
27
|
+
DropdownMenuTriggerRef,
|
|
28
28
|
} from './types';
|
|
29
29
|
|
|
30
|
-
const DropdownMenuContext = React.createContext<
|
|
30
|
+
const DropdownMenuContext = React.createContext<{
|
|
31
|
+
open: boolean;
|
|
32
|
+
onOpenChange: (open: boolean) => void;
|
|
33
|
+
} | null>(null);
|
|
31
34
|
|
|
32
|
-
const Root = React.forwardRef<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
35
|
+
const Root = React.forwardRef<
|
|
36
|
+
ViewRef,
|
|
37
|
+
SlottableViewProps & { onOpenChange?: (open: boolean) => void }
|
|
38
|
+
>(({ asChild, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
|
|
39
|
+
const [open, setOpen] = React.useState(false);
|
|
40
|
+
|
|
41
|
+
function onOpenChange(open: boolean) {
|
|
42
|
+
setOpen(open);
|
|
43
|
+
onOpenChangeProp?.(open);
|
|
42
44
|
}
|
|
43
|
-
|
|
45
|
+
|
|
46
|
+
const Component = asChild ? Slot.View : View;
|
|
47
|
+
return (
|
|
48
|
+
<DropdownMenuContext.Provider value={{ open, onOpenChange }}>
|
|
49
|
+
<DropdownMenu.Root open={open} onOpenChange={onOpenChange}>
|
|
50
|
+
<Component ref={ref} {...viewProps} />
|
|
51
|
+
</DropdownMenu.Root>
|
|
52
|
+
</DropdownMenuContext.Provider>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
44
55
|
|
|
45
56
|
Root.displayName = 'RootWebDropdownMenu';
|
|
46
57
|
|
|
@@ -54,10 +65,20 @@ function useRootContext() {
|
|
|
54
65
|
return context;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
const Trigger = React.forwardRef<
|
|
68
|
+
const Trigger = React.forwardRef<DropdownMenuTriggerRef, SlottablePressableProps>(
|
|
58
69
|
({ asChild, disabled = false, ...props }, ref) => {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
70
|
+
const { open, onOpenChange } = useRootContext();
|
|
71
|
+
const augmentedRef = useAugmentedRef({
|
|
72
|
+
ref,
|
|
73
|
+
methods: {
|
|
74
|
+
open() {
|
|
75
|
+
onOpenChange(true);
|
|
76
|
+
},
|
|
77
|
+
close() {
|
|
78
|
+
onOpenChange(false);
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
61
82
|
|
|
62
83
|
React.useLayoutEffect(() => {
|
|
63
84
|
if (augmentedRef.current) {
|
|
@@ -442,7 +463,13 @@ const DropdownMenuSubContext = React.createContext<{
|
|
|
442
463
|
} | null>(null);
|
|
443
464
|
|
|
444
465
|
const Sub = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuSubProps>(
|
|
445
|
-
({ 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
|
+
});
|
|
472
|
+
|
|
446
473
|
const Component = asChild ? Slot.View : View;
|
|
447
474
|
return (
|
|
448
475
|
<DropdownMenuSubContext.Provider value={{ open, onOpenChange }}>
|
|
@@ -516,6 +543,8 @@ export {
|
|
|
516
543
|
useSubContext,
|
|
517
544
|
};
|
|
518
545
|
|
|
546
|
+
export type { DropdownMenuTriggerRef };
|
|
547
|
+
|
|
519
548
|
function onSelected(ev: Event) {
|
|
520
549
|
ev.preventDefault();
|
|
521
550
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type { ForceMountable } from '@rnr/types';
|
|
2
|
-
|
|
3
|
-
interface DropdownMenuRootProps {
|
|
4
|
-
open: boolean;
|
|
5
|
-
onOpenChange: (value: boolean) => void;
|
|
6
|
-
}
|
|
1
|
+
import type { ForceMountable, PressableRef } from '@rnr/types';
|
|
7
2
|
|
|
8
3
|
interface DropdownMenuPortalProps extends ForceMountable {
|
|
9
4
|
children: React.ReactNode;
|
|
@@ -49,14 +44,20 @@ interface DropdownMenuSeparatorProps {
|
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
interface DropdownMenuSubProps {
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
defaultOpen?: boolean;
|
|
48
|
+
open?: boolean;
|
|
49
|
+
onOpenChange?: (value: boolean) => void;
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
interface DropdownMenuSubTriggerProps {
|
|
57
53
|
textValue?: string;
|
|
58
54
|
}
|
|
59
55
|
|
|
56
|
+
interface DropdownMenuTriggerRef extends PressableRef {
|
|
57
|
+
open: () => void;
|
|
58
|
+
close: () => void;
|
|
59
|
+
}
|
|
60
|
+
|
|
60
61
|
export type {
|
|
61
62
|
DropdownMenuCheckboxItemProps,
|
|
62
63
|
DropdownMenuItemProps,
|
|
@@ -64,8 +65,8 @@ export type {
|
|
|
64
65
|
DropdownMenuPortalProps,
|
|
65
66
|
DropdownMenuRadioGroupProps,
|
|
66
67
|
DropdownMenuRadioItemProps,
|
|
67
|
-
DropdownMenuRootProps,
|
|
68
68
|
DropdownMenuSeparatorProps,
|
|
69
69
|
DropdownMenuSubProps,
|
|
70
70
|
DropdownMenuSubTriggerProps,
|
|
71
|
+
DropdownMenuTriggerRef,
|
|
71
72
|
};
|