@fluentui-react-native/menu 0.5.0 → 0.6.0

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.
Files changed (113) hide show
  1. package/CHANGELOG.json +46 -1
  2. package/CHANGELOG.md +26 -2
  3. package/lib/Menu/Menu.types.d.ts +6 -1
  4. package/lib/Menu/Menu.types.d.ts.map +1 -1
  5. package/lib/Menu/Menu.types.js.map +1 -1
  6. package/lib/Menu/useMenu.d.ts.map +1 -1
  7. package/lib/Menu/useMenu.js +19 -9
  8. package/lib/Menu/useMenu.js.map +1 -1
  9. package/lib/Menu/useMenuContextValue.js +2 -1
  10. package/lib/Menu/useMenuContextValue.js.map +1 -1
  11. package/lib/MenuItemCheckbox/MenuItemCheckbox.d.ts +3 -0
  12. package/lib/MenuItemCheckbox/MenuItemCheckbox.d.ts.map +1 -0
  13. package/lib/MenuItemCheckbox/MenuItemCheckbox.js +20 -0
  14. package/lib/MenuItemCheckbox/MenuItemCheckbox.js.map +1 -0
  15. package/lib/MenuItemCheckbox/MenuItemCheckbox.styling.d.ts +5 -0
  16. package/lib/MenuItemCheckbox/MenuItemCheckbox.styling.d.ts.map +1 -0
  17. package/lib/MenuItemCheckbox/MenuItemCheckbox.styling.js +21 -0
  18. package/lib/MenuItemCheckbox/MenuItemCheckbox.styling.js.map +1 -0
  19. package/lib/MenuItemCheckbox/MenuItemCheckbox.types.d.ts +43 -0
  20. package/lib/MenuItemCheckbox/MenuItemCheckbox.types.d.ts.map +1 -0
  21. package/lib/MenuItemCheckbox/MenuItemCheckbox.types.js +2 -0
  22. package/lib/MenuItemCheckbox/MenuItemCheckbox.types.js.map +1 -0
  23. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.d.ts +5 -0
  24. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.d.ts.map +1 -0
  25. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.js +26 -0
  26. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.js.map +1 -0
  27. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.win32.d.ts +5 -0
  28. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.win32.d.ts.map +1 -0
  29. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.win32.js +27 -0
  30. package/lib/MenuItemCheckbox/MenuItemCheckboxTokens.win32.js.map +1 -0
  31. package/lib/MenuItemCheckbox/useMenuItemCheckbox.d.ts +3 -0
  32. package/lib/MenuItemCheckbox/useMenuItemCheckbox.d.ts.map +1 -0
  33. package/lib/MenuItemCheckbox/useMenuItemCheckbox.js +25 -0
  34. package/lib/MenuItemCheckbox/useMenuItemCheckbox.js.map +1 -0
  35. package/lib/MenuPopover/MenuPopover.d.ts.map +1 -1
  36. package/lib/MenuPopover/MenuPopover.js +1 -1
  37. package/lib/MenuPopover/MenuPopover.js.map +1 -1
  38. package/lib/MenuPopover/MenuPopover.types.d.ts +3 -0
  39. package/lib/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  40. package/lib/MenuPopover/MenuPopover.types.js.map +1 -1
  41. package/lib/MenuPopover/useMenuPopover.d.ts.map +1 -1
  42. package/lib/MenuPopover/useMenuPopover.js +7 -1
  43. package/lib/MenuPopover/useMenuPopover.js.map +1 -1
  44. package/lib/MenuTrigger/useMenuTrigger.d.ts +2 -1
  45. package/lib/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  46. package/lib/MenuTrigger/useMenuTrigger.js +9 -3
  47. package/lib/MenuTrigger/useMenuTrigger.js.map +1 -1
  48. package/lib/context/menuContext.d.ts.map +1 -1
  49. package/lib/context/menuContext.js +1 -0
  50. package/lib/context/menuContext.js.map +1 -1
  51. package/lib-commonjs/Menu/Menu.types.d.ts +6 -1
  52. package/lib-commonjs/Menu/Menu.types.d.ts.map +1 -1
  53. package/lib-commonjs/Menu/Menu.types.js.map +1 -1
  54. package/lib-commonjs/Menu/useMenu.d.ts.map +1 -1
  55. package/lib-commonjs/Menu/useMenu.js +18 -9
  56. package/lib-commonjs/Menu/useMenu.js.map +1 -1
  57. package/lib-commonjs/Menu/useMenuContextValue.js +2 -1
  58. package/lib-commonjs/Menu/useMenuContextValue.js.map +1 -1
  59. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.d.ts +3 -0
  60. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.d.ts.map +1 -0
  61. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.js +23 -0
  62. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.js.map +1 -0
  63. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.styling.d.ts +5 -0
  64. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.styling.d.ts.map +1 -0
  65. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.styling.js +24 -0
  66. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.styling.js.map +1 -0
  67. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.types.d.ts +43 -0
  68. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.types.d.ts.map +1 -0
  69. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.types.js +5 -0
  70. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.types.js.map +1 -0
  71. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.d.ts +5 -0
  72. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.d.ts.map +1 -0
  73. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.js +30 -0
  74. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.js.map +1 -0
  75. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.win32.d.ts +5 -0
  76. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.win32.d.ts.map +1 -0
  77. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.win32.js +31 -0
  78. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckboxTokens.win32.js.map +1 -0
  79. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.d.ts +3 -0
  80. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.d.ts.map +1 -0
  81. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.js +29 -0
  82. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.js.map +1 -0
  83. package/lib-commonjs/MenuPopover/MenuPopover.d.ts.map +1 -1
  84. package/lib-commonjs/MenuPopover/MenuPopover.js +1 -1
  85. package/lib-commonjs/MenuPopover/MenuPopover.js.map +1 -1
  86. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts +3 -0
  87. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  88. package/lib-commonjs/MenuPopover/MenuPopover.types.js.map +1 -1
  89. package/lib-commonjs/MenuPopover/useMenuPopover.d.ts.map +1 -1
  90. package/lib-commonjs/MenuPopover/useMenuPopover.js +8 -1
  91. package/lib-commonjs/MenuPopover/useMenuPopover.js.map +1 -1
  92. package/lib-commonjs/MenuTrigger/useMenuTrigger.d.ts +2 -1
  93. package/lib-commonjs/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  94. package/lib-commonjs/MenuTrigger/useMenuTrigger.js +9 -3
  95. package/lib-commonjs/MenuTrigger/useMenuTrigger.js.map +1 -1
  96. package/lib-commonjs/context/menuContext.d.ts.map +1 -1
  97. package/lib-commonjs/context/menuContext.js +1 -0
  98. package/lib-commonjs/context/menuContext.js.map +1 -1
  99. package/package.json +2 -2
  100. package/src/Menu/Menu.types.ts +6 -1
  101. package/src/Menu/useMenu.ts +26 -3
  102. package/src/Menu/useMenuContextValue.ts +1 -1
  103. package/src/MenuItemCheckbox/MenuItemCheckbox.styling.ts +37 -0
  104. package/src/MenuItemCheckbox/MenuItemCheckbox.tsx +26 -0
  105. package/src/MenuItemCheckbox/MenuItemCheckbox.types.ts +52 -0
  106. package/src/MenuItemCheckbox/MenuItemCheckboxTokens.ts +29 -0
  107. package/src/MenuItemCheckbox/MenuItemCheckboxTokens.win32.ts +30 -0
  108. package/src/MenuItemCheckbox/useMenuItemCheckbox.ts +40 -0
  109. package/src/MenuPopover/MenuPopover.tsx +7 -1
  110. package/src/MenuPopover/MenuPopover.types.ts +3 -0
  111. package/src/MenuPopover/useMenuPopover.ts +8 -1
  112. package/src/MenuTrigger/useMenuTrigger.ts +10 -3
  113. package/src/context/menuContext.ts +1 -0
@@ -1,21 +1,44 @@
1
+ import { InteractionEvent } from '@fluentui-react-native/interactive-hooks';
1
2
  import React from 'react';
2
3
  import { useMenuContext } from '../context/menuContext';
3
4
  import { MenuProps, MenuState } from './Menu.types';
4
5
 
5
6
  export const useMenu = (props: MenuProps): MenuState => {
6
- const [open, setOpen] = useMenuOpenState(props);
7
7
  const triggerRef = React.useRef(null);
8
8
  const context = useMenuContext();
9
9
  const isSubmenu = context.triggerRef !== null;
10
+ const isControlled = typeof props.open !== 'undefined';
11
+ const [open, setOpen] = useMenuOpenState(isControlled, props);
10
12
 
11
13
  return {
14
+ ...props,
12
15
  open,
13
16
  setOpen,
14
17
  triggerRef,
15
18
  isSubmenu,
19
+ isControlled,
16
20
  };
17
21
  };
18
22
 
19
- const useMenuOpenState = (props: MenuProps) => {
20
- return React.useState<boolean>(props.open);
23
+ const useMenuOpenState = (isControlled: boolean, props: MenuProps): [boolean, (e: InteractionEvent, isOpen: boolean) => void] => {
24
+ const { defaultOpen, onOpenChange, open } = props;
25
+ const initialState = typeof defaultOpen !== 'undefined' ? defaultOpen : !!open;
26
+ const [openInternal, setOpenInternal] = React.useState<boolean>(initialState);
27
+
28
+ const state = isControlled ? open : openInternal;
29
+
30
+ const setOpen = React.useCallback(
31
+ (e: InteractionEvent, isOpen: boolean) => {
32
+ const openPrev = state;
33
+ if (!isControlled) {
34
+ setOpenInternal(isOpen);
35
+ }
36
+ if (onOpenChange && openPrev !== isOpen) {
37
+ onOpenChange(e, isOpen);
38
+ }
39
+ },
40
+ [isControlled, state, onOpenChange, setOpenInternal],
41
+ );
42
+
43
+ return [state, setOpen];
21
44
  };
@@ -2,5 +2,5 @@ import { MenuContextValue } from '../context/menuContext';
2
2
  import { MenuState } from './Menu.types';
3
3
 
4
4
  export const useMenuContextValue = (state: MenuState): MenuContextValue => {
5
- return { open: state.open, setOpen: state.setOpen, triggerRef: state.triggerRef, isSubmenu: state.isSubmenu };
5
+ return { ...state };
6
6
  };
@@ -0,0 +1,37 @@
1
+ import { Theme, UseStylingOptions, buildProps } from '@fluentui-react-native/framework';
2
+ import { fontStyles, layoutStyles } from '@fluentui-react-native/tokens';
3
+ import { defaultMenuItemCheckboxTokens } from './MenuItemCheckboxTokens';
4
+ import { menuItemCheckboxName, MenuItemCheckboxProps, MenuItemCheckboxTokens, MenuItemCheckboxSlotProps } from './MenuItemCheckbox.types';
5
+
6
+ export const menuItemCheckboxStates: (keyof MenuItemCheckboxTokens)[] = ['hovered', 'focused', 'pressed', 'disabled'];
7
+
8
+ export const stylingSettings: UseStylingOptions<MenuItemCheckboxProps, MenuItemCheckboxSlotProps, MenuItemCheckboxTokens> = {
9
+ tokens: [defaultMenuItemCheckboxTokens, menuItemCheckboxName],
10
+ states: menuItemCheckboxStates,
11
+ slotProps: {
12
+ root: buildProps(
13
+ (tokens: MenuItemCheckboxTokens, theme: Theme) => ({
14
+ style: {
15
+ alignItems: 'center',
16
+ backgroundColor: tokens.backgroundColor,
17
+ display: 'flex',
18
+ flexDirection: 'row',
19
+ ...layoutStyles.from(tokens, theme),
20
+ },
21
+ }),
22
+ ['backgroundColor', ...layoutStyles.keys],
23
+ ),
24
+ content: buildProps(
25
+ (tokens: MenuItemCheckboxTokens, theme: Theme) => {
26
+ return {
27
+ style: {
28
+ flexGrow: 1,
29
+ color: tokens.color,
30
+ ...fontStyles.from(tokens, theme),
31
+ },
32
+ };
33
+ },
34
+ ['color', ...fontStyles.keys],
35
+ ),
36
+ },
37
+ };
@@ -0,0 +1,26 @@
1
+ /** @jsx withSlots */
2
+ import { View } from 'react-native';
3
+ import { compose, mergeProps, UseSlots, withSlots } from '@fluentui-react-native/framework';
4
+ import { Text } from '@fluentui-react-native/experimental-text';
5
+ import { menuItemCheckboxName, MenuItemCheckboxProps, MenuItemCheckboxType } from './MenuItemCheckbox.types';
6
+ import { useMenuItemCheckbox } from './useMenuItemCheckbox';
7
+ import { stylingSettings } from './MenuItemCheckbox.styling';
8
+
9
+ export const MenuItemCheckbox = compose<MenuItemCheckboxType>({
10
+ displayName: menuItemCheckboxName,
11
+ ...stylingSettings,
12
+ slots: {
13
+ root: View,
14
+ content: Text,
15
+ },
16
+ useRender: (userProps: MenuItemCheckboxProps, useSlots: UseSlots<MenuItemCheckboxType>) => {
17
+ const menuItem = useMenuItemCheckbox(userProps);
18
+ const Slots = useSlots(userProps, (layer): boolean => menuItem.state[layer]);
19
+
20
+ return (final: MenuItemCheckboxProps) => {
21
+ const mergedProps = mergeProps(menuItem.props, final);
22
+
23
+ return <Slots.root {...mergedProps}>{mergedProps.content && <Slots.content>{mergedProps.content}</Slots.content>}</Slots.root>;
24
+ };
25
+ },
26
+ });
@@ -0,0 +1,52 @@
1
+ import * as React from 'react';
2
+ import { ViewProps } from 'react-native';
3
+ import type { IViewProps } from '@fluentui-react-native/adapters';
4
+ import { TextProps } from '@fluentui-react-native/experimental-text';
5
+ import { IFocusable, InteractionEvent, IPressableHooks, IWithPressableOptions } from '@fluentui-react-native/interactive-hooks';
6
+ import { FontTokens, IBorderTokens, IColorTokens, LayoutTokens } from '@fluentui-react-native/tokens';
7
+
8
+ export const menuItemCheckboxName = 'MenuItemCheckbox';
9
+
10
+ export interface MenuItemCheckboxTokens extends LayoutTokens, FontTokens, IBorderTokens, IColorTokens {
11
+ disabled?: MenuItemCheckboxTokens;
12
+ focused?: MenuItemCheckboxTokens;
13
+ hovered?: MenuItemCheckboxTokens;
14
+ pressed?: MenuItemCheckboxTokens;
15
+ }
16
+
17
+ export interface MenuItemCheckboxProps extends Omit<IWithPressableOptions<ViewProps>, 'onPress'> {
18
+ content: string;
19
+
20
+ /**
21
+ * Applies disabled styles to menu item but remains focusable
22
+ */
23
+ disabled?: boolean;
24
+
25
+ /**
26
+ * A RefObject to access the IButton interface. Use this to access the public methods and properties of the component.
27
+ */
28
+ componentRef?: React.RefObject<IFocusable>;
29
+
30
+ /**
31
+ * If the menu item is a trigger for a submenu
32
+ */
33
+ hasSubmenu?: boolean;
34
+
35
+ /**
36
+ * A callback to call on button click event
37
+ */
38
+ onClick?: (e: InteractionEvent) => void;
39
+ }
40
+
41
+ export type MenuItemCheckboxState = IPressableHooks<MenuItemCheckboxProps & React.ComponentPropsWithRef<any>>;
42
+
43
+ export interface MenuItemCheckboxSlotProps {
44
+ root: React.PropsWithRef<IViewProps>;
45
+ content?: TextProps;
46
+ }
47
+
48
+ export interface MenuItemCheckboxType {
49
+ props: MenuItemCheckboxProps;
50
+ tokens: MenuItemCheckboxTokens;
51
+ slotProps: MenuItemCheckboxSlotProps;
52
+ }
@@ -0,0 +1,29 @@
1
+ import { FontWeightValue, Theme } from '@fluentui-react-native/framework';
2
+ import { globalTokens } from '@fluentui-react-native/theme-tokens';
3
+ import { TokenSettings } from '@fluentui-react-native/use-styling';
4
+ import { MenuItemCheckboxTokens } from './MenuItemCheckbox.types';
5
+
6
+ export const defaultMenuItemCheckboxTokens: TokenSettings<MenuItemCheckboxTokens, Theme> = (t: Theme): MenuItemCheckboxTokens => ({
7
+ backgroundColor: t.colors.neutralBackground1,
8
+ borderRadius: globalTokens.corner.radius.medium,
9
+ color: t.colors.neutralForeground2,
10
+ fontFamily: t.typography.families.primary,
11
+ fontSize: globalTokens.font.size[300],
12
+ fontWeight: globalTokens.font.weight.regular as FontWeightValue,
13
+ minHeight: 32,
14
+ minWidth: 160,
15
+ maxWidth: 300,
16
+ padding: globalTokens.spacing.sNudge,
17
+ hovered: {
18
+ backgroundColor: t.colors.neutralBackground1Hover,
19
+ color: t.colors.neutralForeground2Hover,
20
+ },
21
+ pressed: {
22
+ backgroundColor: t.colors.neutralBackground1Pressed,
23
+ color: t.colors.neutralForeground2Pressed,
24
+ },
25
+ disabled: {
26
+ backgroundColor: t.colors.neutralBackground1,
27
+ color: t.colors.neutralForegroundDisabled,
28
+ },
29
+ });
@@ -0,0 +1,30 @@
1
+ import { FontWeightValue, Theme } from '@fluentui-react-native/framework';
2
+ import { globalTokens } from '@fluentui-react-native/theme-tokens';
3
+ import { TokenSettings } from '@fluentui-react-native/use-styling';
4
+ import { MenuItemCheckboxTokens } from './MenuItemCheckbox.types';
5
+
6
+ export const defaultMenuItemCheckboxTokens: TokenSettings<MenuItemCheckboxTokens, Theme> = (t: Theme): MenuItemCheckboxTokens => ({
7
+ backgroundColor: t.colors.neutralBackground1,
8
+ borderRadius: globalTokens.corner.radius.none,
9
+ color: t.colors.neutralForeground1,
10
+ fontFamily: t.typography.families.primary,
11
+ fontSize: globalTokens.font.size[200],
12
+ fontWeight: globalTokens.font.weight.regular as FontWeightValue,
13
+ minHeight: 24,
14
+ minWidth: 160,
15
+ maxWidth: 300,
16
+ padding: globalTokens.spacing.xs,
17
+ paddingHorizontal: globalTokens.spacing.s,
18
+ hovered: {
19
+ backgroundColor: t.colors.neutralBackground1Hover,
20
+ color: t.colors.neutralForeground1Hover,
21
+ },
22
+ pressed: {
23
+ backgroundColor: t.colors.neutralBackground1Pressed,
24
+ color: t.colors.neutralForeground1Pressed,
25
+ },
26
+ disabled: {
27
+ backgroundColor: t.colors.neutralBackground1,
28
+ color: t.colors.neutralForegroundDisabled,
29
+ },
30
+ });
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { AccessibilityState } from 'react-native';
3
+ import { MenuItemCheckboxProps, MenuItemCheckboxState } from './MenuItemCheckbox.types';
4
+ import { memoize } from '@fluentui-react-native/framework';
5
+ import { useAsPressable, useKeyProps } from '@fluentui-react-native/interactive-hooks';
6
+ import { useMenuContext } from '../context/menuContext';
7
+
8
+ export const useMenuItemCheckbox = (props: MenuItemCheckboxProps): MenuItemCheckboxState => {
9
+ // attach the pressable state handlers
10
+ const defaultComponentRef = React.useRef(null);
11
+ const { onClick, accessibilityState, componentRef = defaultComponentRef, disabled, ...rest } = props;
12
+ const pressable = useAsPressable({ ...rest, disabled, onPress: onClick });
13
+ const onKeyProps = useKeyProps(onClick, ' ', 'Enter');
14
+ const hasSubmenu = useMenuContext().isSubmenu;
15
+
16
+ return {
17
+ props: {
18
+ ...pressable.props,
19
+ accessible: true,
20
+ accessibilityRole: 'button',
21
+ onAccessibilityTap: props.onAccessibilityTap || props.onClick,
22
+ accessibilityLabel: props.accessibilityLabel,
23
+ accessibilityState: getAccessibilityState(disabled, accessibilityState),
24
+ enableFocusRing: true,
25
+ focusable: !disabled,
26
+ hasSubmenu,
27
+ ref: componentRef,
28
+ ...onKeyProps,
29
+ },
30
+ state: pressable.state,
31
+ };
32
+ };
33
+
34
+ const getAccessibilityState = memoize(getAccessibilityStateWorker);
35
+ function getAccessibilityStateWorker(disabled: boolean, accessibilityState?: AccessibilityState) {
36
+ if (accessibilityState) {
37
+ return { disabled, ...accessibilityState };
38
+ }
39
+ return { disabled };
40
+ }
@@ -10,7 +10,13 @@ export const MenuPopover = stagedComponent((props: MenuPopoverProps) => {
10
10
 
11
11
  return (_rest: MenuPopoverProps, children: React.ReactNode) => {
12
12
  return (
13
- <Callout target={state.triggerRef} borderWidth={1} borderColor={theme.colors.neutralStrokeAccessible}>
13
+ <Callout
14
+ borderWidth={1}
15
+ borderColor={theme.colors.neutralStrokeAccessible}
16
+ target={state.triggerRef}
17
+ onDismiss={state.onDismiss}
18
+ dismissBehaviors={state.dismissBehaviors}
19
+ >
14
20
  {children}
15
21
  </Callout>
16
22
  );
@@ -1,9 +1,12 @@
1
1
  import type { IViewProps } from '@fluentui-react-native/adapters';
2
+ import { DismissBehaviors } from '@fluentui-react-native/callout';
2
3
 
3
4
  export const menuPopoverName = 'MenuPopover';
4
5
 
5
6
  export interface MenuPopoverProps extends Omit<IViewProps, 'onPress'> {}
6
7
 
7
8
  export interface MenuPopoverState {
9
+ dismissBehaviors: DismissBehaviors[];
10
+ onDismiss: () => void;
8
11
  triggerRef: React.RefObject<React.Component>;
9
12
  }
@@ -1,10 +1,17 @@
1
+ import React from 'react';
2
+ import { DismissBehaviors } from '@fluentui-react-native/callout';
1
3
  import { useMenuContext } from '../context/menuContext';
2
4
  import { MenuPopoverProps, MenuPopoverState } from './MenuPopover.types';
3
5
 
4
6
  export const useMenuPopover = (_props: MenuPopoverProps): MenuPopoverState => {
5
7
  const context = useMenuContext();
8
+ const setOpen = context.setOpen;
6
9
 
7
10
  const triggerRef = context.triggerRef;
11
+ const onDismiss = React.useCallback(() => setOpen(undefined, false /* isOpen */), [setOpen]);
12
+ const dismissBehaviors = context.isControlled
13
+ ? (['preventDismissOnKeyDown', 'preventDismissOnClickOutside'] as DismissBehaviors[])
14
+ : undefined;
8
15
 
9
- return { triggerRef };
16
+ return { triggerRef, onDismiss, dismissBehaviors };
10
17
  };
@@ -7,11 +7,18 @@ export const useMenuTrigger = (_props: MenuTriggerProps) => {
7
7
 
8
8
  const setOpen = context.setOpen;
9
9
  const open = context.open;
10
+ const openOnHover = context.openOnHover;
10
11
  const triggerRef = context.triggerRef;
11
12
 
12
- const onClick = (_e: InteractionEvent) => {
13
- setOpen(!open);
13
+ const onHoverIn = (e: InteractionEvent) => {
14
+ if (openOnHover) {
15
+ setOpen(e, true /* isOpen */);
16
+ }
14
17
  };
15
18
 
16
- return { onClick, componentRef: triggerRef };
19
+ const onClick = (e: InteractionEvent) => {
20
+ setOpen(e, !open);
21
+ };
22
+
23
+ return { onClick, onHoverIn, componentRef: triggerRef };
17
24
  };
@@ -7,6 +7,7 @@ import type { MenuState } from '../Menu/Menu.types';
7
7
  export type MenuContextValue = MenuState;
8
8
 
9
9
  export const MenuContext = React.createContext<MenuContextValue>({
10
+ isControlled: false,
10
11
  isSubmenu: false,
11
12
  open: false,
12
13
  setOpen: () => false,