@fluentui-react-native/menu 0.11.0 → 0.13.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 (74) hide show
  1. package/CHANGELOG.json +52 -1
  2. package/CHANGELOG.md +27 -2
  3. package/lib/MenuItem/MenuItem.js +1 -1
  4. package/lib/MenuItem/MenuItem.js.map +1 -1
  5. package/lib/MenuItem/useMenuItem.d.ts.map +1 -1
  6. package/lib/MenuItem/useMenuItem.js +34 -6
  7. package/lib/MenuItem/useMenuItem.js.map +1 -1
  8. package/lib/MenuItemCheckbox/MenuItemCheckbox.js +1 -1
  9. package/lib/MenuItemCheckbox/MenuItemCheckbox.js.map +1 -1
  10. package/lib/MenuItemCheckbox/useMenuItemCheckbox.d.ts.map +1 -1
  11. package/lib/MenuItemCheckbox/useMenuItemCheckbox.js +12 -8
  12. package/lib/MenuItemCheckbox/useMenuItemCheckbox.js.map +1 -1
  13. package/lib/MenuItemRadio/useMenuItemRadio.d.ts.map +1 -1
  14. package/lib/MenuItemRadio/useMenuItemRadio.js +5 -3
  15. package/lib/MenuItemRadio/useMenuItemRadio.js.map +1 -1
  16. package/lib/MenuPopover/MenuPopover.d.ts +1 -2
  17. package/lib/MenuPopover/MenuPopover.d.ts.map +1 -1
  18. package/lib/MenuPopover/MenuPopover.js +1 -1
  19. package/lib/MenuPopover/MenuPopover.js.map +1 -1
  20. package/lib/MenuPopover/MenuPopover.types.d.ts +4 -4
  21. package/lib/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  22. package/lib/MenuPopover/useMenuPopover.d.ts.map +1 -1
  23. package/lib/MenuPopover/useMenuPopover.js +2 -1
  24. package/lib/MenuPopover/useMenuPopover.js.map +1 -1
  25. package/lib/MenuTrigger/MenuTrigger.d.ts.map +1 -1
  26. package/lib/MenuTrigger/MenuTrigger.js +24 -2
  27. package/lib/MenuTrigger/MenuTrigger.js.map +1 -1
  28. package/lib/MenuTrigger/MenuTrigger.types.d.ts +3 -0
  29. package/lib/MenuTrigger/MenuTrigger.types.d.ts.map +1 -1
  30. package/lib/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  31. package/lib/MenuTrigger/useMenuTrigger.js +26 -1
  32. package/lib/MenuTrigger/useMenuTrigger.js.map +1 -1
  33. package/lib-commonjs/MenuItem/MenuItem.js +1 -1
  34. package/lib-commonjs/MenuItem/MenuItem.js.map +1 -1
  35. package/lib-commonjs/MenuItem/useMenuItem.d.ts.map +1 -1
  36. package/lib-commonjs/MenuItem/useMenuItem.js +32 -4
  37. package/lib-commonjs/MenuItem/useMenuItem.js.map +1 -1
  38. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.js +1 -1
  39. package/lib-commonjs/MenuItemCheckbox/MenuItemCheckbox.js.map +1 -1
  40. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.d.ts.map +1 -1
  41. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.js +12 -8
  42. package/lib-commonjs/MenuItemCheckbox/useMenuItemCheckbox.js.map +1 -1
  43. package/lib-commonjs/MenuItemRadio/useMenuItemRadio.d.ts.map +1 -1
  44. package/lib-commonjs/MenuItemRadio/useMenuItemRadio.js +5 -3
  45. package/lib-commonjs/MenuItemRadio/useMenuItemRadio.js.map +1 -1
  46. package/lib-commonjs/MenuPopover/MenuPopover.d.ts +1 -2
  47. package/lib-commonjs/MenuPopover/MenuPopover.d.ts.map +1 -1
  48. package/lib-commonjs/MenuPopover/MenuPopover.js +1 -1
  49. package/lib-commonjs/MenuPopover/MenuPopover.js.map +1 -1
  50. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts +4 -4
  51. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  52. package/lib-commonjs/MenuPopover/useMenuPopover.d.ts.map +1 -1
  53. package/lib-commonjs/MenuPopover/useMenuPopover.js +2 -1
  54. package/lib-commonjs/MenuPopover/useMenuPopover.js.map +1 -1
  55. package/lib-commonjs/MenuTrigger/MenuTrigger.d.ts.map +1 -1
  56. package/lib-commonjs/MenuTrigger/MenuTrigger.js +22 -1
  57. package/lib-commonjs/MenuTrigger/MenuTrigger.js.map +1 -1
  58. package/lib-commonjs/MenuTrigger/MenuTrigger.types.d.ts +3 -0
  59. package/lib-commonjs/MenuTrigger/MenuTrigger.types.d.ts.map +1 -1
  60. package/lib-commonjs/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  61. package/lib-commonjs/MenuTrigger/useMenuTrigger.js +27 -1
  62. package/lib-commonjs/MenuTrigger/useMenuTrigger.js.map +1 -1
  63. package/package.json +3 -3
  64. package/src/MenuItem/MenuItem.tsx +1 -1
  65. package/src/MenuItem/useMenuItem.ts +49 -9
  66. package/src/MenuItemCheckbox/MenuItemCheckbox.tsx +1 -1
  67. package/src/MenuItemCheckbox/useMenuItemCheckbox.ts +13 -9
  68. package/src/MenuItemRadio/useMenuItemRadio.ts +5 -3
  69. package/src/MenuPopover/MenuPopover.tsx +1 -0
  70. package/src/MenuPopover/MenuPopover.types.ts +4 -3
  71. package/src/MenuPopover/useMenuPopover.ts +2 -1
  72. package/src/MenuTrigger/MenuTrigger.tsx +29 -3
  73. package/src/MenuTrigger/MenuTrigger.types.ts +3 -0
  74. package/src/MenuTrigger/useMenuTrigger.ts +33 -2
@@ -1,11 +1,12 @@
1
- import type { IViewProps } from '@fluentui-react-native/adapters';
2
- import { DirectionalHint, DismissBehaviors } from '@fluentui-react-native/callout';
1
+ import { DirectionalHint, DismissBehaviors, ICalloutProps } from '@fluentui-react-native/callout';
2
+ import { AccessibilityRole } from 'react-native';
3
3
 
4
4
  export const menuPopoverName = 'MenuPopover';
5
5
 
6
- export interface MenuPopoverProps extends Omit<IViewProps, 'onPress'> {}
6
+ export type MenuPopoverProps = ICalloutProps;
7
7
 
8
8
  export interface MenuPopoverState {
9
+ accessibilityRole: AccessibilityRole;
9
10
  directionalHint?: DirectionalHint;
10
11
  dismissBehaviors: DismissBehaviors[];
11
12
  doNotTakePointerCapture: boolean;
@@ -19,8 +19,9 @@ export const useMenuPopover = (_props: MenuPopoverProps): MenuPopoverState => {
19
19
  // automatically onto first element of Callout
20
20
  const setInitialFocus = Platform.OS === ('win32' as any) || Platform.OS === 'windows';
21
21
  const doNotTakePointerCapture = context.openOnHover;
22
+ const accessibilityRole = 'menu';
22
23
 
23
- return { triggerRef, onDismiss, directionalHint, dismissBehaviors, doNotTakePointerCapture, setInitialFocus };
24
+ return { accessibilityRole, triggerRef, onDismiss, directionalHint, dismissBehaviors, doNotTakePointerCapture, setInitialFocus };
24
25
  };
25
26
 
26
27
  const getDirectionalHint = (isSubmenu: boolean, isRtl: boolean): DirectionalHint | undefined => {
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { stagedComponent } from '@fluentui-react-native/framework';
3
- import { menuTriggerName, MenuTriggerProps } from './MenuTrigger.types';
2
+ import { memoize, stagedComponent } from '@fluentui-react-native/framework';
3
+ import { menuTriggerName, MenuTriggerProps, MenuTriggerState } from './MenuTrigger.types';
4
4
  import { useMenuTrigger } from './useMenuTrigger';
5
+ import { AccessibilityActionEvent } from 'react-native';
5
6
  import { MenuTriggerProvider } from '../context/menuTriggerContext';
6
7
 
7
8
  export const MenuTrigger = stagedComponent((props: MenuTriggerProps) => {
@@ -16,12 +17,37 @@ export const MenuTrigger = stagedComponent((props: MenuTriggerProps) => {
16
17
  }
17
18
  }
18
19
 
20
+ // In order to properly support accessibility without erasing props set on the
21
+ // child component which may affect accessibility, we need to modify the
22
+ // state in the inner render so we can access the child component and its props.
19
23
  const child = childrenArray[0];
20
- const revised = React.cloneElement(child, menuTrigger.props);
24
+ const revisedState = getRevisedState(menuTrigger, child.props);
25
+ const revised = React.cloneElement(child, revisedState);
21
26
 
22
27
  return <MenuTriggerProvider value={menuTrigger.hasSubmenu}>{revised}</MenuTriggerProvider>;
23
28
  };
24
29
  });
25
30
  MenuTrigger.displayName = menuTriggerName;
26
31
 
32
+ const getRevisedState = memoize(getRevisedStateWorker);
33
+ function getRevisedStateWorker(state: MenuTriggerState, props: any): MenuTriggerState {
34
+ const revisedState = { ...state };
35
+ if (props.accessibilityState) {
36
+ revisedState.props.accessibilityState = { ...state.props.accessibilityState, ...props.accessibilityState };
37
+ }
38
+
39
+ if (props.accessibilityActions) {
40
+ revisedState.props.accessibilityActions = { ...state.props.accessibilityActions, ...props.accessibilityActions };
41
+ }
42
+
43
+ if (props.onAccessibilityAction) {
44
+ revisedState.props.onAccessibilityAction = (e: AccessibilityActionEvent) => {
45
+ state.props.onAccessibilityAction(e);
46
+ props.onAccessibilityAction(e);
47
+ };
48
+ }
49
+
50
+ return revisedState;
51
+ }
52
+
27
53
  export default MenuTrigger;
@@ -9,6 +9,9 @@ export interface MenuTriggerProps extends Omit<IWithPressableOptions<ViewProps>,
9
9
  */
10
10
  componentRef?: React.RefObject<React.Component>;
11
11
 
12
+ /**
13
+ * A callback to call on button click event
14
+ */
12
15
  onClick?: (e: InteractionEvent) => void;
13
16
  }
14
17
 
@@ -1,7 +1,11 @@
1
1
  import { useMenuContext } from '../context/menuContext';
2
2
  import { InteractionEvent } from '@fluentui-react-native/interactive-hooks';
3
3
  import { MenuTriggerProps, MenuTriggerState } from './MenuTrigger.types';
4
- import { Platform } from 'react-native';
4
+ import { AccessibilityActionEvent, AccessibilityActionName, Platform } from 'react-native';
5
+ import React from 'react';
6
+
7
+ const accessibilityActions =
8
+ Platform.OS === ('win32' as any) ? [{ name: 'Expand' as AccessibilityActionName }, { name: 'Collapse' as AccessibilityActionName }] : [];
5
9
 
6
10
  export const useMenuTrigger = (_props: MenuTriggerProps): MenuTriggerState => {
7
11
  const context = useMenuContext();
@@ -10,6 +14,23 @@ export const useMenuTrigger = (_props: MenuTriggerProps): MenuTriggerState => {
10
14
  const open = context.open;
11
15
  const openOnHover = context.openOnHover;
12
16
  const triggerRef = context.triggerRef;
17
+ const accessibilityState = context.open ? { expanded: true } : { expanded: false };
18
+ const onAccessibilityAction = React.useCallback(
19
+ (e: AccessibilityActionEvent) => {
20
+ if (Platform.OS === ('win32' as any)) {
21
+ switch (e.nativeEvent.actionName) {
22
+ case 'Expand':
23
+ setOpen(e, true /* isOpen */);
24
+ break;
25
+
26
+ case 'Collapse':
27
+ setOpen(e, false /* isOpen */);
28
+ break;
29
+ }
30
+ }
31
+ },
32
+ [setOpen],
33
+ );
13
34
 
14
35
  const delayHover = Platform.select({
15
36
  macos: 100,
@@ -33,7 +54,17 @@ export const useMenuTrigger = (_props: MenuTriggerProps): MenuTriggerState => {
33
54
  };
34
55
 
35
56
  return {
36
- props: { onClick, onHoverIn, onHoverOut, componentRef: triggerRef, delayHoverIn: delayHover, delayHoverOut: delayHover },
57
+ props: {
58
+ onClick,
59
+ onHoverIn,
60
+ onHoverOut: Platform.OS === ('win32' as any) && onHoverOut,
61
+ componentRef: triggerRef,
62
+ delayHoverIn: delayHover,
63
+ delayHoverOut: Platform.OS === ('win32' as any) && delayHover,
64
+ accessibilityState,
65
+ accessibilityActions,
66
+ onAccessibilityAction,
67
+ },
37
68
  hasSubmenu: context.isSubmenu,
38
69
  };
39
70
  };