@fluentui-react-native/menu 0.13.0 → 0.14.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.
Files changed (80) hide show
  1. package/CHANGELOG.json +58 -1
  2. package/CHANGELOG.md +28 -2
  3. package/jest.config.js +2 -0
  4. package/lib/Menu/Menu.types.d.ts +2 -0
  5. package/lib/Menu/Menu.types.d.ts.map +1 -1
  6. package/lib/Menu/useMenu.d.ts.map +1 -1
  7. package/lib/Menu/useMenu.js +8 -3
  8. package/lib/Menu/useMenu.js.map +1 -1
  9. package/lib/Menu/useMenuContextValue.d.ts.map +1 -1
  10. package/lib/Menu/useMenuContextValue.js +4 -1
  11. package/lib/Menu/useMenuContextValue.js.map +1 -1
  12. package/lib/MenuPopover/MenuPopover.d.ts.map +1 -1
  13. package/lib/MenuPopover/MenuPopover.js +7 -3
  14. package/lib/MenuPopover/MenuPopover.js.map +1 -1
  15. package/lib/MenuPopover/MenuPopover.types.d.ts +4 -10
  16. package/lib/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  17. package/lib/MenuPopover/useMenuPopover.d.ts.map +1 -1
  18. package/lib/MenuPopover/useMenuPopover.js +35 -8
  19. package/lib/MenuPopover/useMenuPopover.js.map +1 -1
  20. package/lib/MenuTrigger/MenuTrigger.js +8 -8
  21. package/lib/MenuTrigger/MenuTrigger.js.map +1 -1
  22. package/lib/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  23. package/lib/MenuTrigger/useMenuTrigger.js +21 -20
  24. package/lib/MenuTrigger/useMenuTrigger.js.map +1 -1
  25. package/lib/__tests__/Menu.test.d.ts +2 -0
  26. package/lib/__tests__/Menu.test.d.ts.map +1 -0
  27. package/lib/__tests__/Menu.test.js +145 -0
  28. package/lib/__tests__/Menu.test.js.map +1 -0
  29. package/lib/consts.d.ts +3 -0
  30. package/lib/consts.d.ts.map +1 -0
  31. package/lib/consts.js +7 -0
  32. package/lib/consts.js.map +1 -0
  33. package/lib/context/menuContext.d.ts +10 -4
  34. package/lib/context/menuContext.d.ts.map +1 -1
  35. package/lib/context/menuContext.js.map +1 -1
  36. package/lib-commonjs/Menu/Menu.types.d.ts +2 -0
  37. package/lib-commonjs/Menu/Menu.types.d.ts.map +1 -1
  38. package/lib-commonjs/Menu/useMenu.d.ts.map +1 -1
  39. package/lib-commonjs/Menu/useMenu.js +8 -3
  40. package/lib-commonjs/Menu/useMenu.js.map +1 -1
  41. package/lib-commonjs/Menu/useMenuContextValue.d.ts.map +1 -1
  42. package/lib-commonjs/Menu/useMenuContextValue.js +4 -1
  43. package/lib-commonjs/Menu/useMenuContextValue.js.map +1 -1
  44. package/lib-commonjs/MenuPopover/MenuPopover.d.ts.map +1 -1
  45. package/lib-commonjs/MenuPopover/MenuPopover.js +5 -2
  46. package/lib-commonjs/MenuPopover/MenuPopover.js.map +1 -1
  47. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts +4 -10
  48. package/lib-commonjs/MenuPopover/MenuPopover.types.d.ts.map +1 -1
  49. package/lib-commonjs/MenuPopover/useMenuPopover.d.ts.map +1 -1
  50. package/lib-commonjs/MenuPopover/useMenuPopover.js +35 -8
  51. package/lib-commonjs/MenuPopover/useMenuPopover.js.map +1 -1
  52. package/lib-commonjs/MenuTrigger/MenuTrigger.js +8 -8
  53. package/lib-commonjs/MenuTrigger/MenuTrigger.js.map +1 -1
  54. package/lib-commonjs/MenuTrigger/useMenuTrigger.d.ts.map +1 -1
  55. package/lib-commonjs/MenuTrigger/useMenuTrigger.js +21 -20
  56. package/lib-commonjs/MenuTrigger/useMenuTrigger.js.map +1 -1
  57. package/lib-commonjs/__tests__/Menu.test.d.ts +2 -0
  58. package/lib-commonjs/__tests__/Menu.test.d.ts.map +1 -0
  59. package/lib-commonjs/__tests__/Menu.test.js +148 -0
  60. package/lib-commonjs/__tests__/Menu.test.js.map +1 -0
  61. package/lib-commonjs/consts.d.ts +3 -0
  62. package/lib-commonjs/consts.d.ts.map +1 -0
  63. package/lib-commonjs/consts.js +10 -0
  64. package/lib-commonjs/consts.js.map +1 -0
  65. package/lib-commonjs/context/menuContext.d.ts +10 -4
  66. package/lib-commonjs/context/menuContext.d.ts.map +1 -1
  67. package/lib-commonjs/context/menuContext.js.map +1 -1
  68. package/package.json +5 -3
  69. package/src/Menu/Menu.types.ts +1 -0
  70. package/src/Menu/useMenu.ts +9 -2
  71. package/src/Menu/useMenuContextValue.ts +4 -1
  72. package/src/MenuPopover/MenuPopover.tsx +7 -14
  73. package/src/MenuPopover/MenuPopover.types.ts +4 -9
  74. package/src/MenuPopover/useMenuPopover.ts +48 -8
  75. package/src/MenuTrigger/MenuTrigger.tsx +9 -9
  76. package/src/MenuTrigger/useMenuTrigger.ts +36 -26
  77. package/src/__tests__/Menu.test.tsx +235 -0
  78. package/src/__tests__/__snapshots__/Menu.test.tsx.snap +2098 -0
  79. package/src/consts.ts +8 -0
  80. package/src/context/menuContext.ts +6 -1
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ var React = (0, tslib_1.__importStar)(require("react"));
5
+ var renderer = (0, tslib_1.__importStar)(require("react-test-renderer"));
6
+ var Menu_1 = require("../Menu/Menu");
7
+ var test_tools_1 = require("@fluentui-react-native/test-tools");
8
+ var MenuTrigger_1 = (0, tslib_1.__importDefault)(require("../MenuTrigger/MenuTrigger"));
9
+ var button_1 = require("@fluentui-react-native/button");
10
+ var MenuPopover_1 = (0, tslib_1.__importDefault)(require("../MenuPopover/MenuPopover"));
11
+ var MenuList_1 = require("../MenuList/MenuList");
12
+ var MenuItem_1 = require("../MenuItem/MenuItem");
13
+ var MenuItemCheckbox_1 = require("../MenuItemCheckbox/MenuItemCheckbox");
14
+ var MenuDivider_1 = require("../MenuDivider/MenuDivider");
15
+ var MenuItemRadio_1 = require("../MenuItemRadio/MenuItemRadio");
16
+ describe('Checkbox component tests', function () {
17
+ it('Menu default', function () {
18
+ var tree = renderer
19
+ .create(React.createElement(Menu_1.Menu, null,
20
+ React.createElement(MenuTrigger_1.default, null,
21
+ React.createElement(button_1.ButtonV1, null, "Default")),
22
+ React.createElement(MenuPopover_1.default, null,
23
+ React.createElement(MenuList_1.MenuList, null,
24
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" })))))
25
+ .toJSON();
26
+ expect(tree).toMatchSnapshot();
27
+ });
28
+ it('Menu open', function () {
29
+ var tree = renderer
30
+ .create(React.createElement(Menu_1.Menu, { open: true },
31
+ React.createElement(MenuTrigger_1.default, null,
32
+ React.createElement(button_1.ButtonV1, null, "Open")),
33
+ React.createElement(MenuPopover_1.default, null,
34
+ React.createElement(MenuList_1.MenuList, null,
35
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" })))))
36
+ .toJSON();
37
+ expect(tree).toMatchSnapshot();
38
+ });
39
+ it('Menu defaultOpen', function () {
40
+ var tree = renderer
41
+ .create(React.createElement(Menu_1.Menu, { defaultOpen: true },
42
+ React.createElement(MenuTrigger_1.default, null,
43
+ React.createElement(button_1.ButtonV1, null, "Open")),
44
+ React.createElement(MenuPopover_1.default, null,
45
+ React.createElement(MenuList_1.MenuList, null,
46
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" }),
47
+ React.createElement(MenuItem_1.MenuItem, { disabled: true, content: "Option 2" })))))
48
+ .toJSON();
49
+ expect(tree).toMatchSnapshot();
50
+ });
51
+ it('Menu open checkbox and divider', function () {
52
+ var tree = renderer
53
+ .create(React.createElement(Menu_1.Menu, { open: true },
54
+ React.createElement(MenuTrigger_1.default, null,
55
+ React.createElement(button_1.ButtonV1, null, "Open")),
56
+ React.createElement(MenuPopover_1.default, null,
57
+ React.createElement(MenuList_1.MenuList, null,
58
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { content: "Option 1", name: "Option 1" }),
59
+ React.createElement(MenuDivider_1.MenuDivider, null),
60
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { disabled: true, content: "Option 2", name: "Option 2" })))))
61
+ .toJSON();
62
+ expect(tree).toMatchSnapshot();
63
+ });
64
+ it('Menu open radio', function () {
65
+ var tree = renderer
66
+ .create(React.createElement(Menu_1.Menu, { open: true },
67
+ React.createElement(MenuTrigger_1.default, null,
68
+ React.createElement(button_1.ButtonV1, null, "Open")),
69
+ React.createElement(MenuPopover_1.default, null,
70
+ React.createElement(MenuList_1.MenuList, null,
71
+ React.createElement(MenuItemRadio_1.MenuItemRadio, { content: "Option 1", name: "Option 1" }),
72
+ React.createElement(MenuItemRadio_1.MenuItemRadio, { content: "Option 2", name: "Option 2" })))))
73
+ .toJSON();
74
+ expect(tree).toMatchSnapshot();
75
+ });
76
+ it('Menu open checkbox defaultChecked', function () {
77
+ var tree = renderer
78
+ .create(React.createElement(Menu_1.Menu, { open: true, defaultChecked: { 'Option 1': true } },
79
+ React.createElement(MenuTrigger_1.default, null,
80
+ React.createElement(button_1.ButtonV1, null, "Open")),
81
+ React.createElement(MenuPopover_1.default, null,
82
+ React.createElement(MenuList_1.MenuList, null,
83
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { content: "Option 1", name: "Option 1" }),
84
+ React.createElement(MenuDivider_1.MenuDivider, null),
85
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { content: "Option 2", name: "Option 2" })))))
86
+ .toJSON();
87
+ expect(tree).toMatchSnapshot();
88
+ });
89
+ it('Menu open checkbox checked', function () {
90
+ var tree = renderer
91
+ .create(React.createElement(Menu_1.Menu, { open: true, checked: { 'Option 1': true } },
92
+ React.createElement(MenuTrigger_1.default, null,
93
+ React.createElement(button_1.ButtonV1, null, "Open")),
94
+ React.createElement(MenuPopover_1.default, null,
95
+ React.createElement(MenuList_1.MenuList, null,
96
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { content: "Option 1", name: "Option 1" }),
97
+ React.createElement(MenuDivider_1.MenuDivider, null),
98
+ React.createElement(MenuItemCheckbox_1.MenuItemCheckbox, { content: "Option 2", name: "Option 2" })))))
99
+ .toJSON();
100
+ expect(tree).toMatchSnapshot();
101
+ });
102
+ it('Menu submenu', function () {
103
+ var tree = renderer
104
+ .create(React.createElement(Menu_1.Menu, { open: true },
105
+ React.createElement(MenuTrigger_1.default, null,
106
+ React.createElement(button_1.ButtonV1, null, "Default")),
107
+ React.createElement(MenuPopover_1.default, null,
108
+ React.createElement(MenuList_1.MenuList, null,
109
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" }),
110
+ React.createElement(Menu_1.Menu, null,
111
+ React.createElement(MenuTrigger_1.default, null,
112
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 2" })),
113
+ React.createElement(MenuPopover_1.default, null,
114
+ React.createElement(MenuList_1.MenuList, null,
115
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" }))))))))
116
+ .toJSON();
117
+ expect(tree).toMatchSnapshot();
118
+ });
119
+ });
120
+ describe('Menu rerender tests', function () {
121
+ it('Menu re-renders correctly', function () {
122
+ (0, test_tools_1.checkReRender)(function () { return (React.createElement(Menu_1.Menu, { open: true },
123
+ React.createElement(MenuTrigger_1.default, null,
124
+ React.createElement(button_1.ButtonV1, null, "Rerender twice")),
125
+ React.createElement(MenuPopover_1.default, null,
126
+ React.createElement(MenuList_1.MenuList, null,
127
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" }))))); }, 3);
128
+ });
129
+ it('Menu re-renders correctly with style', function () {
130
+ var style = { backgroundColor: 'black' };
131
+ (0, test_tools_1.checkReRender)(function () { return (React.createElement(Menu_1.Menu, null,
132
+ React.createElement(MenuTrigger_1.default, null,
133
+ React.createElement(button_1.ButtonV1, { style: style }, "Rerender twice")),
134
+ React.createElement(MenuPopover_1.default, null,
135
+ React.createElement(MenuList_1.MenuList, null,
136
+ React.createElement(MenuItem_1.MenuItem, { content: "Option 1" }))))); }, 3);
137
+ });
138
+ it('Menu re-renders correctly with accessibilityAction', function () {
139
+ var action = [{ name: 'Expand' }];
140
+ (0, test_tools_1.checkReRender)(function () { return (React.createElement(Menu_1.Menu, null,
141
+ React.createElement(MenuTrigger_1.default, null,
142
+ React.createElement(button_1.ButtonV1, null, "Rerender twice")),
143
+ React.createElement(MenuPopover_1.default, null,
144
+ React.createElement(MenuList_1.MenuList, null,
145
+ React.createElement(MenuItem_1.MenuItem, { accessibilityActions: action, content: "Option 1" }))))); }, 3);
146
+ });
147
+ });
148
+ //# sourceMappingURL=Menu.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Menu.test.js","sourceRoot":"","sources":["../../src/__tests__/Menu.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const delayHover: number;
2
+ export declare const isCloseOnHoverOutEnabled: boolean;
3
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,QAGrB,CAAC;AAEH,eAAO,MAAM,wBAAwB,SAAmC,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isCloseOnHoverOutEnabled = exports.delayHover = void 0;
4
+ var react_native_1 = require("react-native");
5
+ exports.delayHover = react_native_1.Platform.select({
6
+ macos: 100,
7
+ default: 500, // win32
8
+ });
9
+ exports.isCloseOnHoverOutEnabled = react_native_1.Platform.OS === 'win32';
10
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AAE3B,QAAA,UAAU,GAAG,uBAAQ,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,GAAG,EAAE,QAAQ;CACvB,CAAC,CAAC;AAEU,QAAA,wBAAwB,GAAG,uBAAQ,CAAC,EAAE,KAAM,OAAe,CAAC"}
@@ -1,10 +1,16 @@
1
+ /// <reference types="node" />
1
2
  import * as React from 'react';
2
3
  import type { MenuState } from '../Menu/Menu.types';
3
4
  /**
4
5
  * Context shared between Menu and its child components
5
6
  */
6
- export declare type MenuContextValue = MenuState;
7
- export declare const MenuContext: React.Context<MenuState>;
8
- export declare const MenuProvider: React.Provider<MenuState>;
9
- export declare const useMenuContext: () => MenuState;
7
+ export interface MenuContextValue extends MenuState {
8
+ popoverHoverOutTimer?: NodeJS.Timeout;
9
+ triggerHoverOutTimer?: NodeJS.Timeout;
10
+ setPopoverHoverOutTimer?: (timer: NodeJS.Timeout) => void;
11
+ setTriggerHoverOutTimer?: (timer: NodeJS.Timeout) => void;
12
+ }
13
+ export declare const MenuContext: React.Context<MenuContextValue>;
14
+ export declare const MenuProvider: React.Provider<MenuContextValue>;
15
+ export declare const useMenuContext: () => MenuContextValue;
10
16
  //# sourceMappingURL=menuContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"menuContext.d.ts","sourceRoot":"","sources":["../../src/context/menuContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;GAEG;AACH,oBAAY,gBAAgB,GAAG,SAAS,CAAC;AAEzC,eAAO,MAAM,WAAW,0BAUtB,CAAC;AAEH,eAAO,MAAM,YAAY,2BAAuB,CAAC;AACjD,eAAO,MAAM,cAAc,iBAAsC,CAAC"}
1
+ {"version":3,"file":"menuContext.d.ts","sourceRoot":"","sources":["../../src/context/menuContext.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,oBAAoB,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IACtC,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IAC1D,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;CAC3D;AAED,eAAO,MAAM,WAAW,iCAUtB,CAAC;AAEH,eAAO,MAAM,YAAY,kCAAuB,CAAC;AACjD,eAAO,MAAM,cAAc,wBAAsC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"menuContext.js","sourceRoot":"","sources":["../../src/context/menuContext.ts"],"names":[],"mappings":";;;;AAAA,wDAA+B;AAQlB,QAAA,WAAW,GAAG,KAAK,CAAC,aAAa,CAAmB;IAC/D,YAAY,EAAE,KAAK;IACnB,OAAO,EAAE,EAAE;IACX,cAAc,EAAE,EAAE;IAClB,aAAa,EAAE,KAAK;IACpB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,KAAK;IACX,eAAe,EAAE,cAAM,OAAA,KAAK,EAAL,CAAK;IAC5B,OAAO,EAAE,cAAM,OAAA,KAAK,EAAL,CAAK;IACpB,UAAU,EAAE,IAAI;CACjB,CAAC,CAAC;AAEU,QAAA,YAAY,GAAG,mBAAW,CAAC,QAAQ,CAAC;AAC1C,IAAM,cAAc,GAAG,cAAM,OAAA,KAAK,CAAC,UAAU,CAAC,mBAAW,CAAC,EAA7B,CAA6B,CAAC;AAArD,QAAA,cAAc,kBAAuC"}
1
+ {"version":3,"file":"menuContext.js","sourceRoot":"","sources":["../../src/context/menuContext.ts"],"names":[],"mappings":";;;;AAAA,wDAA+B;AAalB,QAAA,WAAW,GAAG,KAAK,CAAC,aAAa,CAAmB;IAC/D,YAAY,EAAE,KAAK;IACnB,OAAO,EAAE,EAAE;IACX,cAAc,EAAE,EAAE;IAClB,aAAa,EAAE,KAAK;IACpB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,KAAK;IACX,eAAe,EAAE,cAAM,OAAA,KAAK,EAAL,CAAK;IAC5B,OAAO,EAAE,cAAM,OAAA,KAAK,EAAL,CAAK;IACpB,UAAU,EAAE,IAAI;CACjB,CAAC,CAAC;AAEU,QAAA,YAAY,GAAG,mBAAW,CAAC,QAAQ,CAAC;AAC1C,IAAM,cAAc,GAAG,cAAM,OAAA,KAAK,CAAC,UAAU,CAAC,mBAAW,CAAC,EAA7B,CAA6B,CAAC;AAArD,QAAA,cAAc,kBAAuC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui-react-native/menu",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "A cross-platform Menu component using the Fluent Design System",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -23,10 +23,10 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@fluentui-react-native/adapters": ">=0.8.5 <1.0.0",
26
- "@fluentui-react-native/callout": ">=0.20.5 <1.0.0",
26
+ "@fluentui-react-native/callout": ">=0.20.6 <1.0.0",
27
27
  "@fluentui-react-native/experimental-text": ">=0.9.0 <1.0.0",
28
28
  "@fluentui-react-native/framework": "0.7.30",
29
- "@fluentui-react-native/interactive-hooks": ">=0.16.1 <1.0.0",
29
+ "@fluentui-react-native/interactive-hooks": ">=0.16.2 <1.0.0",
30
30
  "@fluentui-react-native/theme-tokens": ">=0.18.0 <1.0.0",
31
31
  "@fluentui-react-native/tokens": ">=0.14.0 <1.0.0",
32
32
  "@fluentui-react-native/use-styling": ">=0.8.3 <1.0.0",
@@ -34,8 +34,10 @@
34
34
  "tslib": "^2.3.1"
35
35
  },
36
36
  "devDependencies": {
37
+ "@fluentui-react-native/button": ">=0.22.27 <1.0.0",
37
38
  "@fluentui-react-native/eslint-config-rules": "^0.1.1",
38
39
  "@fluentui-react-native/scripts": "^0.1.1",
40
+ "@fluentui-react-native/test-tools": ">=0.1.1 <1.0.0",
39
41
  "@types/react-native": "^0.64.0",
40
42
  "react-native": "^0.64.3"
41
43
  },
@@ -14,6 +14,7 @@ export interface MenuProps extends MenuListProps {
14
14
  export interface MenuState extends MenuProps {
15
15
  isControlled: boolean;
16
16
  isSubmenu: boolean;
17
+ parentPopoverHoverOutTimer?: NodeJS.Timeout;
17
18
  setOpen: (e: InteractionEvent, isOpen: boolean) => void;
18
19
  triggerRef: React.RefObject<React.Component>;
19
20
  }
@@ -4,17 +4,23 @@ import { useMenuContext } from '../context/menuContext';
4
4
  import { MenuProps, MenuState } from './Menu.types';
5
5
 
6
6
  export const useMenu = (props: MenuProps): MenuState => {
7
- const triggerRef = React.useRef(null);
7
+ const triggerRef = React.useRef();
8
8
  const context = useMenuContext();
9
9
  const isSubmenu = context.triggerRef !== null;
10
10
  const isControlled = typeof props.open !== 'undefined';
11
11
  const [open, setOpen] = useMenuOpenState(isControlled, props);
12
12
 
13
- // Default behaviot for submenu is to open on hover
13
+ // Default behavior for submenu is to open on hover
14
14
  // the ...props line below will override this behavior for a submenu
15
15
  // or apply openOnHover if passed into a root Menu.
16
16
  const openOnHover = isSubmenu;
17
17
 
18
+ // We need to be able to cancel the timer that gets set on
19
+ // hover out of the parent popover if the parent popover
20
+ // is also set to open/close on hover out. Otherwise
21
+ // the parent menu will close when the timeout passes.
22
+ const parentPopoverHoverOutTimer = isSubmenu ? context.popoverHoverOutTimer : undefined;
23
+
18
24
  return {
19
25
  openOnHover,
20
26
  ...props,
@@ -23,6 +29,7 @@ export const useMenu = (props: MenuProps): MenuState => {
23
29
  triggerRef,
24
30
  isSubmenu,
25
31
  isControlled,
32
+ parentPopoverHoverOutTimer,
26
33
  };
27
34
  };
28
35
 
@@ -1,6 +1,9 @@
1
+ import React from 'react';
1
2
  import { MenuContextValue } from '../context/menuContext';
2
3
  import { MenuState } from './Menu.types';
3
4
 
4
5
  export const useMenuContextValue = (state: MenuState): MenuContextValue => {
5
- return { ...state };
6
+ const [triggerHoverOutTimer, setTriggerHoverOutTimer] = React.useState<NodeJS.Timeout | undefined>();
7
+ const [popoverHoverOutTimer, setPopoverHoverOutTimer] = React.useState<NodeJS.Timeout>();
8
+ return { ...state, popoverHoverOutTimer, triggerHoverOutTimer, setPopoverHoverOutTimer, setTriggerHoverOutTimer };
6
9
  };
@@ -1,27 +1,20 @@
1
1
  import React from 'react';
2
- import { stagedComponent, useFluentTheme } from '@fluentui-react-native/framework';
2
+ import { mergeProps, stagedComponent, useFluentTheme } from '@fluentui-react-native/framework';
3
3
  import { Callout } from '@fluentui-react-native/callout';
4
4
  import { menuPopoverName, MenuPopoverProps } from './MenuPopover.types';
5
5
  import { useMenuPopover } from './useMenuPopover';
6
+ import { View } from 'react-native';
6
7
 
7
8
  export const MenuPopover = stagedComponent((props: MenuPopoverProps) => {
8
9
  const state = useMenuPopover(props);
9
10
  const theme = useFluentTheme();
10
11
 
11
- return (_rest: MenuPopoverProps, children: React.ReactNode) => {
12
+ return (final: MenuPopoverProps, children: React.ReactNode) => {
13
+ const mergedProps = mergeProps(state.props, final);
14
+ const content = React.createElement(View, state.innerView, children);
12
15
  return (
13
- <Callout
14
- accessibilityRole={state.accessibilityRole}
15
- borderWidth={1}
16
- borderColor={theme.colors.neutralStrokeAccessible}
17
- target={state.triggerRef}
18
- onDismiss={state.onDismiss}
19
- dismissBehaviors={state.dismissBehaviors}
20
- setInitialFocus={state.setInitialFocus}
21
- directionalHint={state.directionalHint}
22
- doNotTakePointerCapture={state.doNotTakePointerCapture}
23
- >
24
- {children}
16
+ <Callout borderWidth={1} borderColor={theme.colors.neutralStrokeAccessible} {...mergedProps}>
17
+ {content}
25
18
  </Callout>
26
19
  );
27
20
  };
@@ -1,16 +1,11 @@
1
- import { DirectionalHint, DismissBehaviors, ICalloutProps } from '@fluentui-react-native/callout';
2
- import { AccessibilityRole } from 'react-native';
1
+ import { IViewProps } from '@fluentui-react-native/adapters';
2
+ import { ICalloutProps } from '@fluentui-react-native/callout';
3
3
 
4
4
  export const menuPopoverName = 'MenuPopover';
5
5
 
6
6
  export type MenuPopoverProps = ICalloutProps;
7
7
 
8
8
  export interface MenuPopoverState {
9
- accessibilityRole: AccessibilityRole;
10
- directionalHint?: DirectionalHint;
11
- dismissBehaviors: DismissBehaviors[];
12
- doNotTakePointerCapture: boolean;
13
- onDismiss: () => void;
14
- setInitialFocus: boolean;
15
- triggerRef: React.RefObject<React.Component>;
9
+ props: ICalloutProps;
10
+ innerView: IViewProps;
16
11
  }
@@ -3,25 +3,65 @@ import { I18nManager, Platform } from 'react-native';
3
3
  import { DirectionalHint, DismissBehaviors } from '@fluentui-react-native/callout';
4
4
  import { useMenuContext } from '../context/menuContext';
5
5
  import { MenuPopoverProps, MenuPopoverState } from './MenuPopover.types';
6
+ import { isCloseOnHoverOutEnabled } from '../consts';
7
+
8
+ const controlledDismissBehaviors = ['preventDismissOnKeyDown', 'preventDismissOnClickOutside'] as DismissBehaviors[];
6
9
 
7
10
  export const useMenuPopover = (_props: MenuPopoverProps): MenuPopoverState => {
8
11
  const context = useMenuContext();
9
- const setOpen = context.setOpen;
12
+ const {
13
+ setOpen,
14
+ triggerRef,
15
+ isControlled,
16
+ isSubmenu,
17
+ openOnHover,
18
+ parentPopoverHoverOutTimer,
19
+ popoverHoverOutTimer,
20
+ setPopoverHoverOutTimer,
21
+ triggerHoverOutTimer,
22
+ } = context;
10
23
 
11
- const triggerRef = context.triggerRef;
12
24
  const onDismiss = React.useCallback(() => setOpen(undefined, false /* isOpen */), [setOpen]);
13
- const dismissBehaviors = context.isControlled
14
- ? (['preventDismissOnKeyDown', 'preventDismissOnClickOutside'] as DismissBehaviors[])
15
- : undefined;
16
- const directionalHint = getDirectionalHint(context.isSubmenu, I18nManager.isRTL);
25
+ const dismissBehaviors = isControlled ? controlledDismissBehaviors : undefined;
26
+ const directionalHint = getDirectionalHint(isSubmenu, I18nManager.isRTL);
17
27
 
18
28
  // Initial focus behavior differs per platform, Windows platforms move focus
19
29
  // automatically onto first element of Callout
20
30
  const setInitialFocus = Platform.OS === ('win32' as any) || Platform.OS === 'windows';
21
- const doNotTakePointerCapture = context.openOnHover;
31
+ const doNotTakePointerCapture = openOnHover;
22
32
  const accessibilityRole = 'menu';
23
33
 
24
- return { accessibilityRole, triggerRef, onDismiss, directionalHint, dismissBehaviors, doNotTakePointerCapture, setInitialFocus };
34
+ const onMouseEnter = React.useCallback(() => {
35
+ clearTimeout(triggerHoverOutTimer);
36
+ clearTimeout(popoverHoverOutTimer);
37
+ clearTimeout(parentPopoverHoverOutTimer);
38
+ }, [parentPopoverHoverOutTimer, popoverHoverOutTimer, triggerHoverOutTimer]);
39
+ const onMouseLeave = React.useCallback(() => {
40
+ if (!openOnHover) {
41
+ return;
42
+ }
43
+
44
+ const timer = setTimeout(() => {
45
+ setOpen(undefined, false /* isOpen */);
46
+ }, 500);
47
+ setPopoverHoverOutTimer(timer);
48
+ }, [openOnHover, setOpen, setPopoverHoverOutTimer]);
49
+
50
+ return {
51
+ props: {
52
+ accessibilityRole,
53
+ target: triggerRef,
54
+ onDismiss,
55
+ directionalHint,
56
+ dismissBehaviors,
57
+ doNotTakePointerCapture,
58
+ setInitialFocus,
59
+ },
60
+ innerView: {
61
+ onMouseEnter,
62
+ onMouseLeave: isCloseOnHoverOutEnabled && onMouseLeave,
63
+ },
64
+ };
25
65
  };
26
66
 
27
67
  const getDirectionalHint = (isSubmenu: boolean, isRtl: boolean): DirectionalHint | undefined => {
@@ -21,8 +21,8 @@ export const MenuTrigger = stagedComponent((props: MenuTriggerProps) => {
21
21
  // child component which may affect accessibility, we need to modify the
22
22
  // state in the inner render so we can access the child component and its props.
23
23
  const child = childrenArray[0];
24
- const revisedState = getRevisedState(menuTrigger, child.props);
25
- const revised = React.cloneElement(child, revisedState);
24
+ const revisedProps = getRevisedState(menuTrigger, child.props);
25
+ const revised = React.cloneElement(child, revisedProps);
26
26
 
27
27
  return <MenuTriggerProvider value={menuTrigger.hasSubmenu}>{revised}</MenuTriggerProvider>;
28
28
  };
@@ -30,24 +30,24 @@ export const MenuTrigger = stagedComponent((props: MenuTriggerProps) => {
30
30
  MenuTrigger.displayName = menuTriggerName;
31
31
 
32
32
  const getRevisedState = memoize(getRevisedStateWorker);
33
- function getRevisedStateWorker(state: MenuTriggerState, props: any): MenuTriggerState {
34
- const revisedState = { ...state };
33
+ function getRevisedStateWorker(state: MenuTriggerState, props: any): MenuTriggerProps {
34
+ const revisedProps = state.props;
35
35
  if (props.accessibilityState) {
36
- revisedState.props.accessibilityState = { ...state.props.accessibilityState, ...props.accessibilityState };
36
+ revisedProps.accessibilityState = { ...revisedProps.accessibilityState, ...props.accessibilityState };
37
37
  }
38
38
 
39
39
  if (props.accessibilityActions) {
40
- revisedState.props.accessibilityActions = { ...state.props.accessibilityActions, ...props.accessibilityActions };
40
+ revisedProps.accessibilityActions = { ...revisedProps.accessibilityActions, ...props.accessibilityActions };
41
41
  }
42
42
 
43
43
  if (props.onAccessibilityAction) {
44
- revisedState.props.onAccessibilityAction = (e: AccessibilityActionEvent) => {
45
- state.props.onAccessibilityAction(e);
44
+ revisedProps.onAccessibilityAction = (e: AccessibilityActionEvent) => {
45
+ revisedProps.onAccessibilityAction(e);
46
46
  props.onAccessibilityAction(e);
47
47
  };
48
48
  }
49
49
 
50
- return revisedState;
50
+ return revisedProps;
51
51
  }
52
52
 
53
53
  export default MenuTrigger;
@@ -3,18 +3,19 @@ import { InteractionEvent } from '@fluentui-react-native/interactive-hooks';
3
3
  import { MenuTriggerProps, MenuTriggerState } from './MenuTrigger.types';
4
4
  import { AccessibilityActionEvent, AccessibilityActionName, Platform } from 'react-native';
5
5
  import React from 'react';
6
+ import { delayHover, isCloseOnHoverOutEnabled } from '../consts';
6
7
 
7
8
  const accessibilityActions =
8
9
  Platform.OS === ('win32' as any) ? [{ name: 'Expand' as AccessibilityActionName }, { name: 'Collapse' as AccessibilityActionName }] : [];
10
+ const expandedState = { expanded: true };
11
+ const collapsedState = { expanded: false };
9
12
 
10
13
  export const useMenuTrigger = (_props: MenuTriggerProps): MenuTriggerState => {
11
14
  const context = useMenuContext();
15
+ const { open, openOnHover, popoverHoverOutTimer, setOpen, setTriggerHoverOutTimer, triggerHoverOutTimer, triggerRef } = context;
16
+
17
+ const accessibilityState = open ? expandedState : collapsedState;
12
18
 
13
- const setOpen = context.setOpen;
14
- const open = context.open;
15
- const openOnHover = context.openOnHover;
16
- const triggerRef = context.triggerRef;
17
- const accessibilityState = context.open ? { expanded: true } : { expanded: false };
18
19
  const onAccessibilityAction = React.useCallback(
19
20
  (e: AccessibilityActionEvent) => {
20
21
  if (Platform.OS === ('win32' as any)) {
@@ -32,35 +33,44 @@ export const useMenuTrigger = (_props: MenuTriggerProps): MenuTriggerState => {
32
33
  [setOpen],
33
34
  );
34
35
 
35
- const delayHover = Platform.select({
36
- macos: 100,
37
- default: 500, // win32
38
- });
39
-
40
- const onHoverIn = (e: InteractionEvent) => {
41
- if (openOnHover) {
42
- setOpen(e, true /* isOpen */);
43
- }
44
- };
36
+ const onHoverIn = React.useCallback(
37
+ (e: InteractionEvent) => {
38
+ if (openOnHover) {
39
+ clearTimeout(popoverHoverOutTimer);
40
+ clearTimeout(triggerHoverOutTimer);
41
+ setTimeout(() => {
42
+ setOpen(e, true /* isOpen */);
43
+ }, delayHover);
44
+ }
45
+ },
46
+ [openOnHover, setOpen, triggerHoverOutTimer, popoverHoverOutTimer],
47
+ );
45
48
 
46
- const onHoverOut = (e: InteractionEvent) => {
47
- if (openOnHover) {
48
- setOpen(e, false /* isOpen */);
49
- }
50
- };
49
+ const onHoverOut = React.useCallback(
50
+ (e: InteractionEvent) => {
51
+ if (openOnHover) {
52
+ const timer = setTimeout(() => {
53
+ setOpen(e, false /* isOpen */);
54
+ }, delayHover);
55
+ setTriggerHoverOutTimer(timer);
56
+ }
57
+ },
58
+ [openOnHover, setOpen, setTriggerHoverOutTimer],
59
+ );
51
60
 
52
- const onClick = (e: InteractionEvent) => {
53
- setOpen(e, !open);
54
- };
61
+ const onClick = React.useCallback(
62
+ (e: InteractionEvent) => {
63
+ setOpen(e, !open);
64
+ },
65
+ [open, setOpen],
66
+ );
55
67
 
56
68
  return {
57
69
  props: {
58
70
  onClick,
59
71
  onHoverIn,
60
- onHoverOut: Platform.OS === ('win32' as any) && onHoverOut,
72
+ onHoverOut: isCloseOnHoverOutEnabled && onHoverOut,
61
73
  componentRef: triggerRef,
62
- delayHoverIn: delayHover,
63
- delayHoverOut: Platform.OS === ('win32' as any) && delayHover,
64
74
  accessibilityState,
65
75
  accessibilityActions,
66
76
  onAccessibilityAction,