@tamagui/create-menu 2.7.7 → 3.0.0-beta.643.1
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/dist/cjs/createBaseMenu.cjs +1033 -1247
- package/dist/cjs/createBaseMenu.native.cjs +1217 -0
- package/dist/cjs/createBaseMenu.native.js +1155 -1387
- package/dist/cjs/createBaseMenu.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/createNativeMenu.cjs +346 -377
- package/dist/cjs/createNativeMenu/createNativeMenu.native.cjs +439 -0
- package/dist/cjs/createNativeMenu/createNativeMenu.native.js +405 -439
- package/dist/cjs/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.cjs +10 -11
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.cjs +19 -0
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js +10 -10
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/utils.cjs +76 -86
- package/dist/cjs/createNativeMenu/utils.native.cjs +107 -0
- package/dist/cjs/createNativeMenu/utils.native.js +82 -92
- package/dist/cjs/createNativeMenu/utils.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/withNativeMenu.cjs +27 -35
- package/dist/cjs/createNativeMenu/withNativeMenu.native.cjs +42 -0
- package/dist/cjs/createNativeMenu/withNativeMenu.native.js +27 -34
- package/dist/cjs/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/cjs/index.cjs +9 -20
- package/dist/cjs/index.native.cjs +23 -0
- package/dist/cjs/index.native.js +10 -20
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/createBaseMenu.mjs +1021 -1225
- package/dist/esm/createBaseMenu.mjs.map +1 -1
- package/dist/esm/createBaseMenu.native.js +1144 -1367
- package/dist/esm/createBaseMenu.native.js.map +1 -1
- package/dist/esm/createNativeMenu/createNativeMenu.mjs +332 -353
- package/dist/esm/createNativeMenu/createNativeMenu.mjs.map +1 -1
- package/dist/esm/createNativeMenu/createNativeMenu.native.js +392 -417
- package/dist/esm/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs +0 -2
- package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js +0 -2
- package/dist/esm/createNativeMenu/utils.mjs +55 -57
- package/dist/esm/createNativeMenu/utils.mjs.map +1 -1
- package/dist/esm/createNativeMenu/utils.native.js +62 -65
- package/dist/esm/createNativeMenu/utils.native.js.map +1 -1
- package/dist/esm/createNativeMenu/withNativeMenu.mjs +14 -17
- package/dist/esm/createNativeMenu/withNativeMenu.mjs.map +1 -1
- package/dist/esm/createNativeMenu/withNativeMenu.native.js +15 -18
- package/dist/esm/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/esm/index.js +5 -6
- package/dist/esm/index.mjs +5 -6
- package/dist/esm/index.native.js +5 -6
- package/dist/jsx/createBaseMenu.mjs +1021 -1225
- package/dist/jsx/createBaseMenu.mjs.map +1 -1
- package/dist/jsx/createBaseMenu.native.cjs +1217 -0
- package/dist/jsx/createBaseMenu.native.js +1155 -1387
- package/dist/jsx/createBaseMenu.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenu.mjs +332 -353
- package/dist/jsx/createNativeMenu/createNativeMenu.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenu.native.cjs +439 -0
- package/dist/jsx/createNativeMenu/createNativeMenu.native.js +405 -439
- package/dist/jsx/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs +0 -2
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.cjs +19 -0
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js +10 -10
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/utils.mjs +55 -57
- package/dist/jsx/createNativeMenu/utils.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/utils.native.cjs +107 -0
- package/dist/jsx/createNativeMenu/utils.native.js +82 -92
- package/dist/jsx/createNativeMenu/utils.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/withNativeMenu.mjs +14 -17
- package/dist/jsx/createNativeMenu/withNativeMenu.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/withNativeMenu.native.cjs +42 -0
- package/dist/jsx/createNativeMenu/withNativeMenu.native.js +27 -34
- package/dist/jsx/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/jsx/index.js +5 -6
- package/dist/jsx/index.mjs +5 -6
- package/dist/jsx/index.native.cjs +23 -0
- package/dist/jsx/index.native.js +10 -20
- package/dist/jsx/index.native.js.map +1 -1
- package/package.json +23 -22
- package/src/createBaseMenu.tsx +211 -231
- package/src/createNativeMenu/createNativeMenuTypes.ts +0 -6
- package/src/createNativeMenu/utils.tsx +6 -6
- package/src/createNativeMenu/withNativeMenu.tsx +1 -2
- package/src/index.tsx +0 -1
- package/types/createBaseMenu.d.ts +38 -126
- package/types/createBaseMenu.d.ts.map +1 -1
- package/types/createNativeMenu/createNativeMenu.d.ts +1 -1
- package/types/createNativeMenu/createNativeMenu.d.ts.map +1 -1
- package/types/createNativeMenu/createNativeMenuTypes.d.ts +0 -6
- package/types/createNativeMenu/createNativeMenuTypes.d.ts.map +1 -1
- package/types/createNativeMenu/utils.d.ts +5 -5
- package/types/createNativeMenu/utils.d.ts.map +1 -1
- package/types/createNativeMenu/withNativeMenu.d.ts.map +1 -1
- package/types/index.d.ts +0 -1
- package/types/index.d.ts.map +1 -1
- package/dist/cjs/MenuPredefined.cjs +0 -191
- package/dist/cjs/MenuPredefined.native.js +0 -194
- package/dist/cjs/MenuPredefined.native.js.map +0 -1
- package/dist/esm/MenuPredefined.mjs +0 -166
- package/dist/esm/MenuPredefined.mjs.map +0 -1
- package/dist/esm/MenuPredefined.native.js +0 -166
- package/dist/esm/MenuPredefined.native.js.map +0 -1
- package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs.map +0 -1
- package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/index.native.js.map +0 -1
- package/dist/jsx/MenuPredefined.mjs +0 -166
- package/dist/jsx/MenuPredefined.mjs.map +0 -1
- package/dist/jsx/MenuPredefined.native.js +0 -194
- package/dist/jsx/MenuPredefined.native.js.map +0 -1
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs.map +0 -1
- package/dist/jsx/index.js.map +0 -1
- package/dist/jsx/index.mjs.map +0 -1
- package/src/MenuPredefined.tsx +0 -204
- package/types/MenuPredefined.d.ts +0 -31
- package/types/MenuPredefined.d.ts.map +0 -1
package/src/createBaseMenu.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createStyledHOC, createRefComponent } from '@tamagui/core'
|
|
1
2
|
import { Animate } from '@tamagui/animate'
|
|
2
3
|
import { AnimatePresence as Presence } from '@tamagui/animate-presence'
|
|
3
4
|
import { createCollection } from '@tamagui/collection'
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
} from '@tamagui/dismissable'
|
|
8
9
|
import { useFocusGuards } from '@tamagui/focus-guard'
|
|
9
10
|
import { FocusScope } from '@tamagui/focus-scope'
|
|
11
|
+
import { Image as TamaguiImage, type ImageProps } from '@tamagui/image'
|
|
10
12
|
import type { PopperContentProps } from '@tamagui/popper'
|
|
11
13
|
import * as PopperPrimitive from '@tamagui/popper'
|
|
12
14
|
import { needsPortalRepropagation, Portal as PortalPrimitive } from '@tamagui/portal'
|
|
@@ -17,6 +19,7 @@ import { useCallbackRef } from '@tamagui/use-callback-ref'
|
|
|
17
19
|
import { useDirection } from '@tamagui/use-direction'
|
|
18
20
|
import type { TextProps } from '@tamagui/web'
|
|
19
21
|
import {
|
|
22
|
+
type GetRef,
|
|
20
23
|
type ViewProps,
|
|
21
24
|
composeEventHandlers,
|
|
22
25
|
composeRefs,
|
|
@@ -34,9 +37,6 @@ import {
|
|
|
34
37
|
import type { TamaguiElement } from '@tamagui/web/types'
|
|
35
38
|
import * as React from 'react'
|
|
36
39
|
import { useId } from 'react'
|
|
37
|
-
import type { Image, ImageProps } from 'react-native'
|
|
38
|
-
|
|
39
|
-
import { MenuPredefined } from './MenuPredefined'
|
|
40
40
|
|
|
41
41
|
type Direction = 'ltr' | 'rtl'
|
|
42
42
|
|
|
@@ -156,7 +156,7 @@ interface MenuRootContentTypeProps extends Omit<
|
|
|
156
156
|
|
|
157
157
|
/* ---------------------------------------------------------------------------------------------- */
|
|
158
158
|
|
|
159
|
-
type MenuContentImplElement =
|
|
159
|
+
type MenuContentImplElement = GetRef<typeof PopperPrimitive.PopperContent>
|
|
160
160
|
type FocusScopeProps = React.ComponentPropsWithoutRef<typeof FocusScope>
|
|
161
161
|
type DismissableLayerProps = React.ComponentPropsWithoutRef<typeof DismissableLayer>
|
|
162
162
|
type MenuContentImplPrivateProps = {
|
|
@@ -175,18 +175,18 @@ type MenuContentImplPrivateProps = {
|
|
|
175
175
|
* (default: false)
|
|
176
176
|
*/
|
|
177
177
|
trapFocus?: FocusScopeProps['trapped']
|
|
178
|
-
|
|
178
|
+
}
|
|
179
|
+
interface MenuContentImplProps
|
|
180
|
+
extends MenuContentImplPrivateProps, Omit<PopperContentProps, 'dir' | 'onPlaced'> {
|
|
179
181
|
/**
|
|
180
182
|
* Whether to disable dismissing the menu when the user scrolls outside of it
|
|
181
183
|
* (default: false, meaning scroll will dismiss on web)
|
|
182
184
|
*/
|
|
183
185
|
disableDismissOnScroll?: boolean
|
|
184
|
-
|
|
185
|
-
interface MenuContentImplProps
|
|
186
|
-
extends MenuContentImplPrivateProps, Omit<PopperContentProps, 'dir' | 'onPlaced'> {
|
|
186
|
+
|
|
187
187
|
/**
|
|
188
188
|
* Event handler called when auto-focusing on close.
|
|
189
|
-
* Can be
|
|
189
|
+
* Can be canceled.
|
|
190
190
|
*/
|
|
191
191
|
onCloseAutoFocus?: FocusScopeProps['onUnmountAutoFocus']
|
|
192
192
|
|
|
@@ -203,7 +203,7 @@ interface MenuContentImplProps
|
|
|
203
203
|
onInteractOutside?: DismissableLayerProps['onInteractOutside']
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
type
|
|
206
|
+
type StyledHOCMenuContentProps = MenuContentImplProps & ViewProps
|
|
207
207
|
|
|
208
208
|
interface MenuGroupProps extends ViewProps {}
|
|
209
209
|
|
|
@@ -211,12 +211,11 @@ interface MenuGroupProps extends ViewProps {}
|
|
|
211
211
|
* MenuLabel
|
|
212
212
|
* -----------------------------------------------------------------------------------------------*/
|
|
213
213
|
|
|
214
|
-
interface MenuLabelProps extends
|
|
214
|
+
interface MenuLabelProps extends TextProps {}
|
|
215
215
|
|
|
216
216
|
type MenuItemElement = MenuItemImplElement
|
|
217
217
|
interface MenuItemProps extends Omit<MenuItemImplProps, 'onSelect'> {
|
|
218
218
|
onSelect?: (event: Event) => void
|
|
219
|
-
unstyled?: boolean
|
|
220
219
|
/**
|
|
221
220
|
* Prevents the menu from closing when this item is selected.
|
|
222
221
|
* Useful for toggle items or multi-select scenarios.
|
|
@@ -229,7 +228,6 @@ type MenuItemImplElement = TamaguiElement
|
|
|
229
228
|
interface MenuItemImplProps extends ViewProps {
|
|
230
229
|
disabled?: boolean
|
|
231
230
|
textValue?: string
|
|
232
|
-
unstyled?: boolean
|
|
233
231
|
}
|
|
234
232
|
|
|
235
233
|
/* -------------------------------------------------------------------------------------------------
|
|
@@ -299,7 +297,6 @@ interface MenuItemIndicatorProps extends PrimitiveSpanProps {
|
|
|
299
297
|
* MenuSeparator
|
|
300
298
|
* -----------------------------------------------------------------------------------------------*/
|
|
301
299
|
|
|
302
|
-
// type MenuSeparatorElement = React.ElementRef<typeof Stack>
|
|
303
300
|
interface MenuSeparatorProps extends ViewProps {}
|
|
304
301
|
|
|
305
302
|
/* -------------------------------------------------------------------------------------------------
|
|
@@ -308,9 +305,7 @@ interface MenuSeparatorProps extends ViewProps {}
|
|
|
308
305
|
|
|
309
306
|
// type MenuArrowElement = React.ElementRef<typeof PopperPrimitive.PopperArrow>
|
|
310
307
|
type PopperArrowProps = React.ComponentPropsWithoutRef<typeof PopperPrimitive.PopperArrow>
|
|
311
|
-
|
|
312
|
-
unstyled?: boolean
|
|
313
|
-
}
|
|
308
|
+
type MenuArrowProps = PopperArrowProps
|
|
314
309
|
|
|
315
310
|
/* -------------------------------------------------------------------------------------------------
|
|
316
311
|
* MenuSub
|
|
@@ -375,29 +370,11 @@ const { Provider: MenuRootProvider, useStyledContext: useMenuRootContext } =
|
|
|
375
370
|
|
|
376
371
|
const MENU_CONTEXT = 'MenuContext'
|
|
377
372
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
Title?: typeof MenuPredefined.Title
|
|
382
|
-
SubTitle?: typeof MenuPredefined.SubTitle
|
|
383
|
-
Image?: React.ElementType
|
|
384
|
-
Icon?: typeof MenuPredefined.MenuIcon
|
|
385
|
-
Indicator?: typeof MenuPredefined.MenuIndicator
|
|
386
|
-
Separator?: typeof MenuPredefined.MenuSeparator
|
|
387
|
-
Label?: typeof MenuPredefined.MenuLabel
|
|
388
|
-
}
|
|
373
|
+
const MenuImageFrame = styled(TamaguiImage, {
|
|
374
|
+
displayName: 'MenuItemImage',
|
|
375
|
+
})
|
|
389
376
|
|
|
390
|
-
export function createBaseMenu({
|
|
391
|
-
Item: _Item = MenuPredefined.MenuItem,
|
|
392
|
-
Title: _Title = MenuPredefined.Title,
|
|
393
|
-
SubTitle: _SubTitle = MenuPredefined.SubTitle,
|
|
394
|
-
Image: _Image = MenuPredefined.MenuImage,
|
|
395
|
-
Icon: _Icon = MenuPredefined.MenuIcon,
|
|
396
|
-
Indicator: _Indicator = MenuPredefined.MenuIndicator,
|
|
397
|
-
Separator: _Separator = MenuPredefined.MenuSeparator,
|
|
398
|
-
MenuGroup: _MenuGroup = MenuPredefined.MenuGroup,
|
|
399
|
-
Label: _Label = MenuPredefined.MenuLabel,
|
|
400
|
-
}: CreateBaseMenuProps) {
|
|
377
|
+
export function createBaseMenu() {
|
|
401
378
|
const MenuComp = (props: ScopedProps<MenuBaseProps>) => {
|
|
402
379
|
const direction = useDirection(props.dir)
|
|
403
380
|
// default placement: bottom-start for LTR, bottom-end for RTL
|
|
@@ -604,11 +581,12 @@ export function createBaseMenu({
|
|
|
604
581
|
createStyledContext<MenuContentContextValue>()
|
|
605
582
|
|
|
606
583
|
const MenuContentFrame = styled(PopperPrimitive.PopperContentFrame, {
|
|
607
|
-
|
|
584
|
+
displayName: CONTENT_NAME,
|
|
608
585
|
})
|
|
609
586
|
|
|
610
|
-
const MenuContent =
|
|
611
|
-
|
|
587
|
+
const MenuContent = createStyledHOC(
|
|
588
|
+
MenuContentFrame,
|
|
589
|
+
(props: ScopedProps<MenuContentProps>, forwardedRef) => {
|
|
612
590
|
const scope = props.scope || MENU_CONTEXT
|
|
613
591
|
const portalContext = usePortalContext(scope)
|
|
614
592
|
const { forceMount = portalContext.forceMount, ...contentProps } = props
|
|
@@ -630,7 +608,7 @@ export function createBaseMenu({
|
|
|
630
608
|
|
|
631
609
|
/* ---------------------------------------------------------------------------------------------- */
|
|
632
610
|
|
|
633
|
-
const MenuRootContentModal =
|
|
611
|
+
const MenuRootContentModal = createRefComponent<
|
|
634
612
|
MenuRootContentTypeElement,
|
|
635
613
|
ScopedProps<MenuRootContentTypeProps>
|
|
636
614
|
>((props, forwardedRef) => {
|
|
@@ -662,7 +640,7 @@ export function createBaseMenu({
|
|
|
662
640
|
// We make sure we don't trigger our `onDismiss` in such case.
|
|
663
641
|
onFocusOutside={composeEventHandlers(
|
|
664
642
|
props.onFocusOutside,
|
|
665
|
-
(event
|
|
643
|
+
(event) => event.cancel(),
|
|
666
644
|
{ checkDefaultPrevented: false }
|
|
667
645
|
)}
|
|
668
646
|
onDismiss={() => context.onOpenChange(false)}
|
|
@@ -670,7 +648,7 @@ export function createBaseMenu({
|
|
|
670
648
|
)
|
|
671
649
|
})
|
|
672
650
|
|
|
673
|
-
const MenuRootContentNonModal =
|
|
651
|
+
const MenuRootContentNonModal = createRefComponent<
|
|
674
652
|
MenuRootContentTypeElement,
|
|
675
653
|
ScopedProps<MenuRootContentTypeProps>
|
|
676
654
|
>((props, forwardedRef) => {
|
|
@@ -689,9 +667,9 @@ export function createBaseMenu({
|
|
|
689
667
|
)
|
|
690
668
|
})
|
|
691
669
|
|
|
692
|
-
const MenuContentImpl =
|
|
670
|
+
const MenuContentImpl = createRefComponent<
|
|
693
671
|
MenuContentImplElement,
|
|
694
|
-
ScopedProps<
|
|
672
|
+
ScopedProps<StyledHOCMenuContentProps>
|
|
695
673
|
>((props, forwardedRef) => {
|
|
696
674
|
const {
|
|
697
675
|
scope = MENU_CONTEXT,
|
|
@@ -708,7 +686,6 @@ export function createBaseMenu({
|
|
|
708
686
|
onDismiss,
|
|
709
687
|
disableOutsideScroll,
|
|
710
688
|
disableDismissOnScroll = false,
|
|
711
|
-
unstyled = process.env.TAMAGUI_HEADLESS === '1',
|
|
712
689
|
...contentProps
|
|
713
690
|
} = props
|
|
714
691
|
|
|
@@ -805,13 +782,13 @@ export function createBaseMenu({
|
|
|
805
782
|
// relative to the viewport. window/document scrolls have `document`
|
|
806
783
|
// as the target, which contains the anchor, so those still dismiss.
|
|
807
784
|
if (anchor && !scrolled.contains(anchor)) return
|
|
808
|
-
|
|
785
|
+
context.onOpenChange(false)
|
|
809
786
|
}
|
|
810
787
|
window.addEventListener('scroll', handleScroll, { capture: true, passive: true })
|
|
811
788
|
return () => {
|
|
812
789
|
window.removeEventListener('scroll', handleScroll, { capture: true })
|
|
813
790
|
}
|
|
814
|
-
}, [disableDismissOnScroll, context.open,
|
|
791
|
+
}, [disableDismissOnScroll, context.open, context.onOpenChange, popperContext.refs])
|
|
815
792
|
|
|
816
793
|
// Make sure the whole tree has focus guards as our `MenuContent` may be
|
|
817
794
|
// the last element in the DOM (beacuse of the `Portal`)
|
|
@@ -832,14 +809,6 @@ export function createBaseMenu({
|
|
|
832
809
|
// tabIndex allows the content to be focusable so that onItemLeave can
|
|
833
810
|
// focus the content frame and properly blur the previously focused item
|
|
834
811
|
tabIndex={-1}
|
|
835
|
-
unstyled={unstyled}
|
|
836
|
-
{...(!unstyled && {
|
|
837
|
-
backgroundColor: '$background',
|
|
838
|
-
borderWidth: 1,
|
|
839
|
-
borderColor: '$borderColor',
|
|
840
|
-
outlineWidth: 0,
|
|
841
|
-
minWidth: 180,
|
|
842
|
-
})}
|
|
843
812
|
aria-orientation="vertical"
|
|
844
813
|
data-state={getOpenState(context.open)}
|
|
845
814
|
data-tamagui-menu-content=""
|
|
@@ -945,7 +914,7 @@ export function createBaseMenu({
|
|
|
945
914
|
onMountAutoFocus={composeEventHandlers(onOpenAutoFocus, (event) => {
|
|
946
915
|
// when opening, explicitly focus the content area only and leave
|
|
947
916
|
// `onEntryFocus` in control of focusing first item
|
|
948
|
-
event.
|
|
917
|
+
event.cancel()
|
|
949
918
|
// contentRef.current doesn't reliably point to the focusable DOM element
|
|
950
919
|
// due to how refs propagate through Tamagui's styled component chain,
|
|
951
920
|
// so we query for the element directly using the data attribute
|
|
@@ -977,7 +946,7 @@ export function createBaseMenu({
|
|
|
977
946
|
// for keyboard users, focus first item for immediate navigation
|
|
978
947
|
// for mouse users, prevent auto-focus to avoid showing focus style
|
|
979
948
|
if (!rootContext.isUsingKeyboardRef.current) {
|
|
980
|
-
event.
|
|
949
|
+
event.cancel()
|
|
981
950
|
}
|
|
982
951
|
})}
|
|
983
952
|
>
|
|
@@ -999,119 +968,118 @@ export function createBaseMenu({
|
|
|
999
968
|
const ITEM_NAME = 'MenuItem'
|
|
1000
969
|
const ITEM_SELECT = 'menu.itemSelect'
|
|
1001
970
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
971
|
+
const MenuItem = createStyledHOC(
|
|
972
|
+
View,
|
|
973
|
+
(props: ScopedProps<MenuItemProps>, forwardedRef) => {
|
|
974
|
+
const {
|
|
975
|
+
disabled = false,
|
|
976
|
+
onSelect,
|
|
977
|
+
preventCloseOnSelect,
|
|
978
|
+
children,
|
|
979
|
+
scope = MENU_CONTEXT,
|
|
980
|
+
// filter out native-only props that shouldn't reach the DOM
|
|
981
|
+
// @ts-ignore
|
|
982
|
+
destructive,
|
|
983
|
+
// @ts-ignore
|
|
984
|
+
hidden,
|
|
985
|
+
// @ts-ignore
|
|
986
|
+
androidIconName,
|
|
987
|
+
...itemProps
|
|
988
|
+
} = props
|
|
989
|
+
const ref = React.useRef<TamaguiElement>(null)
|
|
990
|
+
const rootContext = useMenuRootContext(scope)
|
|
991
|
+
const contentContext = useMenuContentContext(scope)
|
|
992
|
+
const composedRefs = useComposedRefs(forwardedRef, ref)
|
|
993
|
+
const isPointerDownRef = React.useRef(false)
|
|
994
|
+
|
|
995
|
+
const handleSelect = () => {
|
|
996
|
+
const menuItem = ref.current
|
|
997
|
+
if (!disabled && menuItem) {
|
|
998
|
+
if (isWeb) {
|
|
999
|
+
const menuItemEl = menuItem as HTMLElement
|
|
1000
|
+
const itemSelectEvent = new CustomEvent(ITEM_SELECT, {
|
|
1001
|
+
bubbles: true,
|
|
1002
|
+
cancelable: true,
|
|
1003
|
+
})
|
|
1004
|
+
menuItemEl.addEventListener(ITEM_SELECT, (event) => onSelect?.(event), {
|
|
1005
|
+
once: true,
|
|
1006
|
+
})
|
|
1007
|
+
dispatchDiscreteCustomEvent(menuItemEl, itemSelectEvent)
|
|
1008
|
+
// close the menu unless preventCloseOnSelect is set or event.preventDefault() was called
|
|
1009
|
+
if (itemSelectEvent.defaultPrevented || preventCloseOnSelect) {
|
|
1010
|
+
isPointerDownRef.current = false
|
|
1011
|
+
} else {
|
|
1012
|
+
rootContext.onClose()
|
|
1013
|
+
}
|
|
1043
1014
|
} else {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
if (!preventCloseOnSelect) {
|
|
1051
|
-
rootContext.onClose()
|
|
1015
|
+
// TODO: find a better way to handle this on native
|
|
1016
|
+
onSelect?.({ target: menuItem } as unknown as Event)
|
|
1017
|
+
isPointerDownRef.current = false
|
|
1018
|
+
if (!preventCloseOnSelect) {
|
|
1019
|
+
rootContext.onClose()
|
|
1020
|
+
}
|
|
1052
1021
|
}
|
|
1053
1022
|
}
|
|
1054
1023
|
}
|
|
1055
|
-
}
|
|
1056
1024
|
|
|
1057
|
-
|
|
1025
|
+
const content = typeof children === 'string' ? <Text>{children}</Text> : children
|
|
1058
1026
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
if (!isPointerDownRef.current) event.currentTarget?.click()
|
|
1079
|
-
}
|
|
1080
|
-
})}
|
|
1081
|
-
{...(isWeb
|
|
1082
|
-
? {
|
|
1083
|
-
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
1084
|
-
const isTypingAhead = contentContext.searchRef.current !== ''
|
|
1085
|
-
if (disabled || (isTypingAhead && event.key === ' ')) return
|
|
1086
|
-
if (SELECTION_KEYS.includes(event.key)) {
|
|
1087
|
-
// @ts-ignore
|
|
1088
|
-
event.currentTarget?.click()
|
|
1089
|
-
/**
|
|
1090
|
-
* We prevent default browser behaviour for selection keys as they should trigger
|
|
1091
|
-
* a selection only:
|
|
1092
|
-
* - prevents space from scrolling the page.
|
|
1093
|
-
* - if keydown causes focus to move, prevents keydown from firing on the new target.
|
|
1094
|
-
*/
|
|
1095
|
-
event.preventDefault()
|
|
1096
|
-
}
|
|
1097
|
-
}),
|
|
1027
|
+
return (
|
|
1028
|
+
<MenuItemImpl
|
|
1029
|
+
{...itemProps}
|
|
1030
|
+
scope={scope}
|
|
1031
|
+
// @ts-ignore
|
|
1032
|
+
ref={composedRefs}
|
|
1033
|
+
disabled={disabled}
|
|
1034
|
+
onPress={composeEventHandlers(props.onPress, handleSelect)}
|
|
1035
|
+
onPointerDown={(event) => {
|
|
1036
|
+
props.onPointerDown?.(event)
|
|
1037
|
+
isPointerDownRef.current = true
|
|
1038
|
+
}}
|
|
1039
|
+
onPointerUp={composeEventHandlers(props.onPointerUp, (event) => {
|
|
1040
|
+
// Pointer down can move to a different menu item which should activate it on pointer up.
|
|
1041
|
+
// We dispatch a click for selection to allow composition with click based triggers and to
|
|
1042
|
+
// prevent Firefox from getting stuck in text selection mode when the menu closes.
|
|
1043
|
+
if (isWeb) {
|
|
1044
|
+
// @ts-ignore
|
|
1045
|
+
if (!isPointerDownRef.current) event.currentTarget?.click()
|
|
1098
1046
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1047
|
+
})}
|
|
1048
|
+
{...(isWeb
|
|
1049
|
+
? {
|
|
1050
|
+
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
1051
|
+
const isTypingAhead = contentContext.searchRef.current !== ''
|
|
1052
|
+
if (disabled || (isTypingAhead && event.key === ' ')) return
|
|
1053
|
+
if (SELECTION_KEYS.includes(event.key)) {
|
|
1054
|
+
// @ts-ignore
|
|
1055
|
+
event.currentTarget?.click()
|
|
1056
|
+
/**
|
|
1057
|
+
* We prevent default browser behaviour for selection keys as they should trigger
|
|
1058
|
+
* a selection only:
|
|
1059
|
+
* - prevents space from scrolling the page.
|
|
1060
|
+
* - if keydown causes focus to move, prevents keydown from firing on the new target.
|
|
1061
|
+
*/
|
|
1062
|
+
event.preventDefault()
|
|
1063
|
+
}
|
|
1064
|
+
}),
|
|
1065
|
+
}
|
|
1066
|
+
: {})}
|
|
1067
|
+
>
|
|
1068
|
+
{content}
|
|
1069
|
+
</MenuItemImpl>
|
|
1070
|
+
)
|
|
1071
|
+
}
|
|
1072
|
+
)
|
|
1105
1073
|
|
|
1106
|
-
const MenuItemImpl =
|
|
1074
|
+
const MenuItemImpl = createRefComponent<
|
|
1107
1075
|
MenuItemImplElement,
|
|
1108
1076
|
ScopedProps<MenuItemImplProps>
|
|
1109
1077
|
>((props, forwardedRef) => {
|
|
1110
1078
|
const {
|
|
1111
1079
|
scope = MENU_CONTEXT,
|
|
1080
|
+
className,
|
|
1112
1081
|
disabled = false,
|
|
1113
1082
|
textValue,
|
|
1114
|
-
unstyled = process.env.TAMAGUI_HEADLESS === '1',
|
|
1115
1083
|
...itemProps
|
|
1116
1084
|
} = props
|
|
1117
1085
|
const contentContext = useMenuContentContext(scope)
|
|
@@ -1140,11 +1108,10 @@ export function createBaseMenu({
|
|
|
1140
1108
|
<RovingFocusGroup.Item
|
|
1141
1109
|
asChild
|
|
1142
1110
|
__scopeRovingFocusGroup={scope}
|
|
1143
|
-
|
|
1111
|
+
tabIndex={disabled ? -1 : 0}
|
|
1144
1112
|
>
|
|
1145
|
-
<
|
|
1146
|
-
|
|
1147
|
-
componentName={ITEM_NAME}
|
|
1113
|
+
<View
|
|
1114
|
+
className={`is_${ITEM_NAME} ${className || ''}`.trim()}
|
|
1148
1115
|
role="menuitem"
|
|
1149
1116
|
data-highlighted={isFocused ? '' : undefined}
|
|
1150
1117
|
aria-disabled={disabled || undefined}
|
|
@@ -1195,9 +1162,12 @@ export function createBaseMenu({
|
|
|
1195
1162
|
* MenuItemTitle
|
|
1196
1163
|
* -----------------------------------------------------------------------------------------------*/
|
|
1197
1164
|
const ITEM_TITLE_NAME = 'MenuItemTitle'
|
|
1198
|
-
const MenuItemTitle =
|
|
1199
|
-
|
|
1200
|
-
|
|
1165
|
+
const MenuItemTitle = createStyledHOC(
|
|
1166
|
+
Text,
|
|
1167
|
+
(props: MenuItemTitleProps, forwardedRef) => {
|
|
1168
|
+
return <Text {...props} ref={forwardedRef} />
|
|
1169
|
+
}
|
|
1170
|
+
)
|
|
1201
1171
|
|
|
1202
1172
|
MenuItemTitle.displayName = ITEM_TITLE_NAME
|
|
1203
1173
|
/* ---------------------------------------------------------------------------------------------- */
|
|
@@ -1206,9 +1176,10 @@ export function createBaseMenu({
|
|
|
1206
1176
|
* MenuItemSubTitle
|
|
1207
1177
|
* -----------------------------------------------------------------------------------------------*/
|
|
1208
1178
|
const ITEM_SUB_TITLE_NAME = 'MenuItemSubTitle'
|
|
1209
|
-
const MenuItemSubTitle =
|
|
1210
|
-
|
|
1211
|
-
|
|
1179
|
+
const MenuItemSubTitle = createStyledHOC(
|
|
1180
|
+
Text,
|
|
1181
|
+
(props: MenuItemSubTitleProps, forwardedRef) => {
|
|
1182
|
+
return <Text {...props} ref={forwardedRef} />
|
|
1212
1183
|
}
|
|
1213
1184
|
)
|
|
1214
1185
|
|
|
@@ -1220,19 +1191,19 @@ export function createBaseMenu({
|
|
|
1220
1191
|
* MenuItemImage
|
|
1221
1192
|
* -----------------------------------------------------------------------------------------------*/
|
|
1222
1193
|
const ITEM_IMAGE = 'MenuItemImage'
|
|
1223
|
-
const MenuItemImage =
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1194
|
+
const MenuItemImage = createRefComponent<TamaguiElement, ImageProps>(
|
|
1195
|
+
(props, forwardedRef) => {
|
|
1196
|
+
// filter out native-only props that shouldn't reach the DOM
|
|
1197
|
+
const {
|
|
1198
|
+
// @ts-ignore - native menu ios config
|
|
1199
|
+
ios,
|
|
1200
|
+
// @ts-ignore
|
|
1201
|
+
androidIconName,
|
|
1202
|
+
...rest
|
|
1203
|
+
} = props
|
|
1204
|
+
return <MenuImageFrame {...rest} ref={forwardedRef} />
|
|
1205
|
+
}
|
|
1206
|
+
)
|
|
1236
1207
|
|
|
1237
1208
|
MenuItemImage.displayName = ITEM_IMAGE
|
|
1238
1209
|
|
|
@@ -1243,7 +1214,7 @@ export function createBaseMenu({
|
|
|
1243
1214
|
* -----------------------------------------------------------------------------------------------*/
|
|
1244
1215
|
|
|
1245
1216
|
const ITEM_ICON = 'MenuItemIcon'
|
|
1246
|
-
const MenuItemIcon =
|
|
1217
|
+
const MenuItemIcon = createStyledHOC(View, (props: MenuItemIconProps, forwardedRef) => {
|
|
1247
1218
|
// filter out native-only props that shouldn't reach the DOM
|
|
1248
1219
|
const {
|
|
1249
1220
|
// @ts-ignore
|
|
@@ -1252,11 +1223,9 @@ export function createBaseMenu({
|
|
|
1252
1223
|
android,
|
|
1253
1224
|
// @ts-ignore
|
|
1254
1225
|
androidIconName,
|
|
1255
|
-
// @ts-ignore
|
|
1256
|
-
iosIconName,
|
|
1257
1226
|
...rest
|
|
1258
1227
|
} = props
|
|
1259
|
-
return <
|
|
1228
|
+
return <View {...rest} ref={forwardedRef} />
|
|
1260
1229
|
})
|
|
1261
1230
|
|
|
1262
1231
|
MenuItemIcon.displayName = ITEM_ICON
|
|
@@ -1269,8 +1238,9 @@ export function createBaseMenu({
|
|
|
1269
1238
|
|
|
1270
1239
|
const CHECKBOX_ITEM_NAME = 'MenuCheckboxItem'
|
|
1271
1240
|
|
|
1272
|
-
const MenuCheckboxItem =
|
|
1273
|
-
|
|
1241
|
+
const MenuCheckboxItem = createStyledHOC(
|
|
1242
|
+
View,
|
|
1243
|
+
(props: ScopedProps<MenuCheckboxItemProps>, forwardedRef) => {
|
|
1274
1244
|
const {
|
|
1275
1245
|
checked = false,
|
|
1276
1246
|
onCheckedChange,
|
|
@@ -1280,12 +1250,13 @@ export function createBaseMenu({
|
|
|
1280
1250
|
value,
|
|
1281
1251
|
// @ts-ignore - native menu value change handler
|
|
1282
1252
|
onValueChange,
|
|
1253
|
+
className,
|
|
1283
1254
|
...checkboxItemProps
|
|
1284
1255
|
} = props
|
|
1285
1256
|
return (
|
|
1286
1257
|
<ItemIndicatorProvider scope={scope} checked={checked}>
|
|
1287
1258
|
<MenuItem
|
|
1288
|
-
|
|
1259
|
+
className={`is_${CHECKBOX_ITEM_NAME} ${className || ''}`.trim()}
|
|
1289
1260
|
role={(isWeb ? 'menuitemcheckbox' : 'menuitem') as 'menuitem'}
|
|
1290
1261
|
aria-checked={isIndeterminate(checked) ? 'mixed' : checked}
|
|
1291
1262
|
{...checkboxItemProps}
|
|
@@ -1313,14 +1284,21 @@ export function createBaseMenu({
|
|
|
1313
1284
|
const { Provider: RadioGroupProvider, useStyledContext: useRadioGroupContext } =
|
|
1314
1285
|
createStyledContext<MenuRadioGroupProps>()
|
|
1315
1286
|
|
|
1316
|
-
const MenuRadioGroup =
|
|
1317
|
-
|
|
1318
|
-
|
|
1287
|
+
const MenuRadioGroup = createStyledHOC(
|
|
1288
|
+
View,
|
|
1289
|
+
(props: ScopedProps<MenuRadioGroupProps>, forwardedRef) => {
|
|
1290
|
+
const {
|
|
1291
|
+
value,
|
|
1292
|
+
onValueChange,
|
|
1293
|
+
scope = MENU_CONTEXT,
|
|
1294
|
+
className,
|
|
1295
|
+
...groupProps
|
|
1296
|
+
} = props
|
|
1319
1297
|
const handleValueChange = useCallbackRef(onValueChange)
|
|
1320
1298
|
return (
|
|
1321
1299
|
<RadioGroupProvider scope={scope} value={value} onValueChange={handleValueChange}>
|
|
1322
|
-
<
|
|
1323
|
-
|
|
1300
|
+
<View
|
|
1301
|
+
className={`is_${RADIO_GROUP_NAME} ${className || ''}`.trim()}
|
|
1324
1302
|
{...groupProps}
|
|
1325
1303
|
ref={forwardedRef}
|
|
1326
1304
|
/>
|
|
@@ -1336,15 +1314,16 @@ export function createBaseMenu({
|
|
|
1336
1314
|
|
|
1337
1315
|
const RADIO_ITEM_NAME = 'MenuRadioItem'
|
|
1338
1316
|
|
|
1339
|
-
const MenuRadioItem =
|
|
1340
|
-
|
|
1341
|
-
|
|
1317
|
+
const MenuRadioItem = createStyledHOC(
|
|
1318
|
+
View,
|
|
1319
|
+
(props: ScopedProps<MenuRadioItemProps>, forwardedRef) => {
|
|
1320
|
+
const { value, scope = MENU_CONTEXT, className, ...radioItemProps } = props
|
|
1342
1321
|
const context = useRadioGroupContext(scope)
|
|
1343
1322
|
const checked = value === context.value
|
|
1344
1323
|
return (
|
|
1345
1324
|
<ItemIndicatorProvider scope={scope} checked={checked}>
|
|
1346
1325
|
<MenuItem
|
|
1347
|
-
|
|
1326
|
+
className={`is_${RADIO_ITEM_NAME} ${className || ''}`.trim()}
|
|
1348
1327
|
{...radioItemProps}
|
|
1349
1328
|
scope={scope}
|
|
1350
1329
|
aria-checked={checked}
|
|
@@ -1373,17 +1352,18 @@ export function createBaseMenu({
|
|
|
1373
1352
|
const { Provider: ItemIndicatorProvider, useStyledContext: useItemIndicatorContext } =
|
|
1374
1353
|
createStyledContext<CheckboxContextValue>()
|
|
1375
1354
|
|
|
1376
|
-
const MenuItemIndicator =
|
|
1377
|
-
|
|
1378
|
-
|
|
1355
|
+
const MenuItemIndicator = createStyledHOC(
|
|
1356
|
+
View,
|
|
1357
|
+
(props: ScopedProps<MenuItemIndicatorProps>, forwardedRef) => {
|
|
1358
|
+
const { scope = MENU_CONTEXT, className, forceMount, ...itemIndicatorProps } = props
|
|
1379
1359
|
const indicatorContext = useItemIndicatorContext(scope)
|
|
1380
1360
|
return (
|
|
1381
1361
|
<Presence>
|
|
1382
1362
|
{forceMount ||
|
|
1383
1363
|
isIndeterminate(indicatorContext.checked) ||
|
|
1384
1364
|
indicatorContext.checked === true ? (
|
|
1385
|
-
<
|
|
1386
|
-
|
|
1365
|
+
<View
|
|
1366
|
+
className={`is_${ITEM_INDICATOR_NAME} ${className || ''}`.trim()}
|
|
1387
1367
|
render="span"
|
|
1388
1368
|
{...itemIndicatorProps}
|
|
1389
1369
|
ref={forwardedRef}
|
|
@@ -1401,22 +1381,14 @@ export function createBaseMenu({
|
|
|
1401
1381
|
* MenuArrow
|
|
1402
1382
|
* -----------------------------------------------------------------------------------------------*/
|
|
1403
1383
|
|
|
1404
|
-
// TODO this
|
|
1405
|
-
const MenuArrow =
|
|
1384
|
+
// TODO this wrapped a styled component but it cant flatten anyways so likely fine just need to check
|
|
1385
|
+
const MenuArrow = createRefComponent<TamaguiElement, MenuArrowProps>(
|
|
1406
1386
|
function MenuArrow(props, forwardedRef) {
|
|
1407
|
-
const {
|
|
1408
|
-
scope = MENU_CONTEXT,
|
|
1409
|
-
unstyled = process.env.TAMAGUI_HEADLESS === '1',
|
|
1410
|
-
...rest
|
|
1411
|
-
} = props
|
|
1387
|
+
const { scope = MENU_CONTEXT, className, ...rest } = props
|
|
1412
1388
|
return (
|
|
1413
1389
|
<PopperPrimitive.PopperArrow
|
|
1414
1390
|
scope={scope}
|
|
1415
|
-
|
|
1416
|
-
unstyled={unstyled}
|
|
1417
|
-
{...(!unstyled && {
|
|
1418
|
-
backgroundColor: '$background',
|
|
1419
|
-
})}
|
|
1391
|
+
className={`is_PopperArrow ${className || ''}`.trim()}
|
|
1420
1392
|
{...rest}
|
|
1421
1393
|
ref={forwardedRef}
|
|
1422
1394
|
/>
|
|
@@ -1534,7 +1506,7 @@ export function createBaseMenu({
|
|
|
1534
1506
|
|
|
1535
1507
|
const SUB_TRIGGER_NAME = 'MenuSubTrigger'
|
|
1536
1508
|
|
|
1537
|
-
const MenuSubTrigger =
|
|
1509
|
+
const MenuSubTrigger = createRefComponent<
|
|
1538
1510
|
TamaguiElement,
|
|
1539
1511
|
ScopedProps<MenuSubTriggerProps>
|
|
1540
1512
|
>((props, forwardedRef) => {
|
|
@@ -1567,14 +1539,17 @@ export function createBaseMenu({
|
|
|
1567
1539
|
}, [pointerGraceTimerRef, onPointerGraceIntentChange])
|
|
1568
1540
|
|
|
1569
1541
|
return (
|
|
1570
|
-
<MenuAnchor
|
|
1542
|
+
<MenuAnchor
|
|
1543
|
+
className={`is_${SUB_TRIGGER_NAME}`}
|
|
1544
|
+
asChild="except-style"
|
|
1545
|
+
scope={scope}
|
|
1546
|
+
>
|
|
1571
1547
|
<MenuItemImpl
|
|
1572
1548
|
id={subContext.triggerId}
|
|
1573
1549
|
aria-haspopup="menu"
|
|
1574
1550
|
aria-expanded={context.open}
|
|
1575
1551
|
aria-controls={subContext.contentId}
|
|
1576
1552
|
data-state={getOpenState(context.open)}
|
|
1577
|
-
outlineStyle="none"
|
|
1578
1553
|
{...props}
|
|
1579
1554
|
ref={composeRefs(forwardedRef, subContext.onTriggerChange)}
|
|
1580
1555
|
// This is redundant for mouse users but we cannot determine pointer type from
|
|
@@ -1776,11 +1751,12 @@ export function createBaseMenu({
|
|
|
1776
1751
|
const SUB_CONTENT_NAME = 'MenuSubContent'
|
|
1777
1752
|
|
|
1778
1753
|
const MenuSubContentFrame = styled(PopperPrimitive.PopperContentFrame, {
|
|
1779
|
-
|
|
1754
|
+
displayName: SUB_CONTENT_NAME,
|
|
1780
1755
|
})
|
|
1781
1756
|
|
|
1782
|
-
const MenuSubContent =
|
|
1783
|
-
|
|
1757
|
+
const MenuSubContent = createStyledHOC(
|
|
1758
|
+
MenuSubContentFrame,
|
|
1759
|
+
(props: ScopedProps<MenuSubContentProps>, forwardedRef) => {
|
|
1784
1760
|
const scope = props.scope || MENU_CONTEXT
|
|
1785
1761
|
const portalContext = usePortalContext(scope)
|
|
1786
1762
|
const { forceMount = portalContext.forceMount, ...subContentProps } = props
|
|
@@ -1834,15 +1810,16 @@ export function createBaseMenu({
|
|
|
1834
1810
|
) as HTMLElement | null
|
|
1835
1811
|
;(content || root)?.focus({ preventScroll: true })
|
|
1836
1812
|
}
|
|
1837
|
-
event.
|
|
1813
|
+
event.cancel()
|
|
1838
1814
|
}}
|
|
1839
1815
|
// The menu might close because of focusing another menu item in the parent menu. We
|
|
1840
1816
|
// don't want it to refocus the trigger in that case so we handle trigger focus ourselves.
|
|
1841
|
-
onCloseAutoFocus={(event) => event.
|
|
1817
|
+
onCloseAutoFocus={(event) => event.cancel()}
|
|
1842
1818
|
onFocusOutside={composeEventHandlers(props.onFocusOutside, (event) => {
|
|
1843
1819
|
// We prevent closing when the trigger is focused to avoid triggering a re-open animation
|
|
1844
1820
|
// on pointer interaction.
|
|
1845
|
-
if (event.target !== subContext.trigger)
|
|
1821
|
+
if (event.event?.target !== subContext.trigger)
|
|
1822
|
+
context.onOpenChange(false)
|
|
1846
1823
|
})}
|
|
1847
1824
|
onEscapeKeyDown={composeEventHandlers(props.onEscapeKeyDown, (event) => {
|
|
1848
1825
|
// close only this submenu, not the root menu
|
|
@@ -1850,8 +1827,11 @@ export function createBaseMenu({
|
|
|
1850
1827
|
// return focus to the submenu trigger with focusVisible since this is keyboard navigation
|
|
1851
1828
|
// @ts-ignore focusVisible is a newer API
|
|
1852
1829
|
subContext.trigger?.focus({ focusVisible: true })
|
|
1853
|
-
//
|
|
1854
|
-
event.
|
|
1830
|
+
// we close the submenu ourselves, so veto the layer's dismiss
|
|
1831
|
+
event.cancel()
|
|
1832
|
+
// and still ensure escape doesn't exit fullscreen (cancel no
|
|
1833
|
+
// longer touches the native event)
|
|
1834
|
+
event.event?.preventDefault?.()
|
|
1855
1835
|
})}
|
|
1856
1836
|
{...(isWeb
|
|
1857
1837
|
? {
|
|
@@ -1888,12 +1868,12 @@ export function createBaseMenu({
|
|
|
1888
1868
|
const Anchor = MenuAnchor
|
|
1889
1869
|
const Portal = MenuPortal
|
|
1890
1870
|
const Content = MenuContent
|
|
1891
|
-
const Group =
|
|
1892
|
-
return <
|
|
1871
|
+
const Group = createStyledHOC(View, (props: MenuGroupProps, ref) => {
|
|
1872
|
+
return <View role="group" {...props} ref={ref} />
|
|
1893
1873
|
})
|
|
1894
1874
|
Group.displayName = 'MenuGroup'
|
|
1895
|
-
const Label =
|
|
1896
|
-
return <
|
|
1875
|
+
const Label = createStyledHOC(Text, (props: MenuLabelProps, ref) => {
|
|
1876
|
+
return <Text {...props} ref={ref} />
|
|
1897
1877
|
})
|
|
1898
1878
|
Label.displayName = 'MenuLabel'
|
|
1899
1879
|
const Item = MenuItem
|
|
@@ -1901,8 +1881,8 @@ export function createBaseMenu({
|
|
|
1901
1881
|
const RadioGroup = MenuRadioGroup
|
|
1902
1882
|
const RadioItem = MenuRadioItem
|
|
1903
1883
|
const ItemIndicator = MenuItemIndicator
|
|
1904
|
-
const Separator =
|
|
1905
|
-
return <
|
|
1884
|
+
const Separator = createStyledHOC(View, (props: MenuSeparatorProps, ref) => {
|
|
1885
|
+
return <View role="separator" aria-orientation="horizontal" {...props} ref={ref} />
|
|
1906
1886
|
})
|
|
1907
1887
|
Separator.displayName = 'MenuSeparator'
|
|
1908
1888
|
const Arrow = MenuArrow
|