@fluentui/react-menu 9.6.8 → 9.6.9

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.json CHANGED
@@ -2,7 +2,36 @@
2
2
  "name": "@fluentui/react-menu",
3
3
  "entries": [
4
4
  {
5
- "date": "Fri, 10 Feb 2023 08:46:47 GMT",
5
+ "date": "Mon, 13 Feb 2023 09:34:34 GMT",
6
+ "tag": "@fluentui/react-menu_v9.6.9",
7
+ "version": "9.6.9",
8
+ "comments": {
9
+ "none": [
10
+ {
11
+ "author": "martinhochel@microsoft.com",
12
+ "package": "@fluentui/react-menu",
13
+ "commit": "cbba19f7ed8a619b5fa856575fde872e79be99b9",
14
+ "comment": "style: fix formatting in files that were silently passed previously"
15
+ }
16
+ ],
17
+ "patch": [
18
+ {
19
+ "author": "lingfangao@hotmail.com",
20
+ "package": "@fluentui/react-menu",
21
+ "commit": "01013be09ee21b976963582f112365ae81a33ae0",
22
+ "comment": "fix: MenuList is a single tabstop"
23
+ },
24
+ {
25
+ "author": "beachball",
26
+ "package": "@fluentui/react-menu",
27
+ "comment": "Bump @fluentui/react-positioning to v9.4.1",
28
+ "commit": "b24aed22677cb12a74f185feee89edefd1601b9a"
29
+ }
30
+ ]
31
+ }
32
+ },
33
+ {
34
+ "date": "Fri, 10 Feb 2023 08:50:02 GMT",
6
35
  "tag": "@fluentui/react-menu_v9.6.8",
7
36
  "version": "9.6.8",
8
37
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # Change Log - @fluentui/react-menu
2
2
 
3
- This log was last generated on Fri, 10 Feb 2023 08:46:47 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 13 Feb 2023 09:34:34 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## [9.6.9](https://github.com/microsoft/fluentui/tree/@fluentui/react-menu_v9.6.9)
8
+
9
+ Mon, 13 Feb 2023 09:34:34 GMT
10
+ [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-menu_v9.6.8..@fluentui/react-menu_v9.6.9)
11
+
12
+ ### Patches
13
+
14
+ - fix: MenuList is a single tabstop ([PR #26803](https://github.com/microsoft/fluentui/pull/26803) by lingfangao@hotmail.com)
15
+ - Bump @fluentui/react-positioning to v9.4.1 ([PR #26800](https://github.com/microsoft/fluentui/pull/26800) by beachball)
16
+
7
17
  ## [9.6.8](https://github.com/microsoft/fluentui/tree/@fluentui/react-menu_v9.6.8)
8
18
 
9
- Fri, 10 Feb 2023 08:46:47 GMT
19
+ Fri, 10 Feb 2023 08:50:02 GMT
10
20
  [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-menu_v9.6.7..@fluentui/react-menu_v9.6.8)
11
21
 
12
22
  ### Patches
@@ -9,17 +9,17 @@ import { MenuContext } from '../../contexts/menuContext';
9
9
  */
10
10
  export const useMenuList_unstable = (props, ref) => {
11
11
  var _a, _b;
12
- const focusAttributes = useArrowNavigationGroup({
13
- circular: true,
14
- ignoreDefaultKeydown: {
15
- Tab: true
16
- }
17
- });
18
12
  const {
19
13
  findAllFocusable
20
14
  } = useFocusFinders();
21
15
  const menuContext = useMenuContextSelectors();
22
16
  const hasMenuContext = useHasParentContext(MenuContext);
17
+ const focusAttributes = useArrowNavigationGroup({
18
+ circular: true,
19
+ ignoreDefaultKeydown: {
20
+ Tab: hasMenuContext
21
+ }
22
+ });
23
23
  if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {
24
24
  // TODO throw warnings in development safely
25
25
  // eslint-disable-next-line no-console
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["React","useMergedRefs","useEventCallback","useControllableState","getNativeElementProps","useArrowNavigationGroup","useFocusFinders","useHasParentContext","useMenuContext_unstable","MenuContext","useMenuList_unstable","props","ref","focusAttributes","circular","ignoreDefaultKeydown","Tab","findAllFocusable","menuContext","useMenuContextSelectors","hasMenuContext","usingPropsAndMenuContext","console","warn","innerRef","useRef","setFocusByFirstCharacter","useCallback","e","itemEl","acceptedRoles","current","menuItems","el","hasAttribute","indexOf","getAttribute","startIndex","length","firstChars","map","menuItem","textContent","charAt","toLowerCase","char","key","getIndexFirstChars","start","firstChar","i","index","focus","checkedValues","setCheckedValues","state","undefined","defaultState","defaultCheckedValues","initialState","handleCheckedValueChange","onCheckedValueChange","toggleCheckbox","name","value","checked","checkedItems","newCheckedItems","splice","push","s","selectRadio","components","root","role","triggerId","hasIcons","hasCheckmarks","context","contextValue","isUsingPropsAndContext","val"],"sourceRoot":"../src/","sources":["packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: true } });\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
1
+ {"version":3,"mappings":"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","names":["React","useMergedRefs","useEventCallback","useControllableState","getNativeElementProps","useArrowNavigationGroup","useFocusFinders","useHasParentContext","useMenuContext_unstable","MenuContext","useMenuList_unstable","props","ref","findAllFocusable","menuContext","useMenuContextSelectors","hasMenuContext","focusAttributes","circular","ignoreDefaultKeydown","Tab","usingPropsAndMenuContext","console","warn","innerRef","useRef","setFocusByFirstCharacter","useCallback","e","itemEl","acceptedRoles","current","menuItems","el","hasAttribute","indexOf","getAttribute","startIndex","length","firstChars","map","menuItem","textContent","charAt","toLowerCase","char","key","getIndexFirstChars","start","firstChar","i","index","focus","checkedValues","setCheckedValues","state","undefined","defaultState","defaultCheckedValues","initialState","handleCheckedValueChange","onCheckedValueChange","toggleCheckbox","name","value","checked","checkedItems","newCheckedItems","splice","push","s","selectRadio","components","root","role","triggerId","hasIcons","hasCheckmarks","context","contextValue","isUsingPropsAndContext","val"],"sourceRoot":"../src/","sources":["packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: hasMenuContext } });\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
@@ -7,10 +7,10 @@ define(["require", "exports", "tslib", "react", "@fluentui/react-utilities", "@f
7
7
  */
8
8
  var useMenuList_unstable = function (props, ref) {
9
9
  var _a, _b;
10
- var focusAttributes = react_tabster_1.useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: true } });
11
10
  var findAllFocusable = react_tabster_1.useFocusFinders().findAllFocusable;
12
11
  var menuContext = useMenuContextSelectors();
13
12
  var hasMenuContext = react_context_selector_1.useHasParentContext(menuContext_2.MenuContext);
13
+ var focusAttributes = react_tabster_1.useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: hasMenuContext } });
14
14
  if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {
15
15
  // TODO throw warnings in development safely
16
16
  // eslint-disable-next-line no-console
@@ -1 +1 @@
1
- {"version":3,"file":"useMenuList.js","sourceRoot":"","sources":["../../../../../../../../../packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: true } });\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
1
+ {"version":3,"file":"useMenuList.js","sourceRoot":"","sources":["../../../../../../../../../packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"names":[],"mappings":";;;;IAaA;;OAEG;IACI,IAAM,oBAAoB,GAAG,UAAC,KAAoB,EAAE,GAA2B;;QAC5E,IAAA,gBAAgB,GAAK,+BAAe,EAAE,iBAAtB,CAAuB;QAC/C,IAAM,WAAW,GAAG,uBAAuB,EAAE,CAAC;QAC9C,IAAM,cAAc,GAAG,4CAAmB,CAAC,yBAAW,CAAC,CAAC;QACxD,IAAM,eAAe,GAAG,uCAAuB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;QAEnH,IAAI,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE;YAChE,4CAA4C;YAC5C,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,+FAA+F,CAAC,CAAC;SAC/G;QAED,IAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAc,IAAI,CAAC,CAAC;QAEjD,IAAM,wBAAwB,GAAG,KAAK,CAAC,WAAW,CAChD,UAAC,CAAmC,EAAE,MAAmB;YACvD,gFAAgF;YAChF,IAAM,aAAa,GAAG,CAAC,UAAU,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;YACxE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;gBACrB,OAAO;aACR;YAED,IAAM,SAAS,GAAG,gBAAgB,CAChC,QAAQ,CAAC,OAAO,EAChB,UAAC,EAAe,IAAK,OAAA,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAE,CAAC,KAAK,CAAC,CAAC,EAAjF,CAAiF,CACvG,CAAC;YAEF,IAAI,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/C,IAAI,UAAU,KAAK,SAAS,CAAC,MAAM,EAAE;gBACnC,UAAU,GAAG,CAAC,CAAC;aAChB;YAED,IAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,UAAA,QAAQ,YAAI,OAAA,MAAA,QAAQ,CAAC,WAAW,0CAAE,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAA,EAAA,CAAC,CAAC;YAC5F,IAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAEjC,IAAM,kBAAkB,GAAG,UAAC,KAAa,EAAE,SAAiB;gBAC1D,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBAC9C,IAAI,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE;wBAC1B,OAAO,CAAC,CAAC;qBACV;iBACF;gBACD,OAAO,CAAC,CAAC,CAAC;YACZ,CAAC,CAAC;YAEF,oCAAoC;YACpC,IAAI,KAAK,GAAG,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAEjD,wDAAwD;YACxD,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;gBAChB,KAAK,GAAG,kBAAkB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;aACrC;YAED,wBAAwB;YACxB,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;gBACd,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;aAC1B;QACH,CAAC,EACD,CAAC,gBAAgB,CAAC,CACnB,CAAC;QAEI,IAAA,KAAoC,sCAAoB,CAAC;YAC7D,KAAK,EAAE,MAAA,KAAK,CAAC,aAAa,mCAAI,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YACtF,YAAY,EAAE,KAAK,CAAC,oBAAoB;YACxC,YAAY,EAAE,EAAE;SACjB,CAAC,EAJK,aAAa,QAAA,EAAE,gBAAgB,QAIpC,CAAC;QAEH,IAAM,wBAAwB,GAC5B,MAAA,KAAK,CAAC,oBAAoB,mCAAI,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEhG,IAAM,cAAc,GAAG,kCAAgB,CACrC,UAAC,CAAyC,EAAE,IAAY,EAAE,KAAa,EAAE,OAAgB;YACvF,IAAM,YAAY,GAAG,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAG,IAAI,CAAC,KAAI,EAAE,CAAC;YACjD,IAAM,eAAe,6BAAO,YAAY,CAAC,CAAC;YAC1C,IAAI,OAAO,EAAE;gBACX,eAAe,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;aAC3D;iBAAM;gBACL,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aAC7B;YAED,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAG,CAAC,EAAE,EAAE,IAAI,MAAA,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC,CAAC;YACvE,gBAAgB,CAAC,UAAA,CAAC;;gBAAI,OAAA,uCAAM,CAAC,gBAAG,IAAI,IAAG,eAAe,OAAG;YAAnC,CAAmC,CAAC,CAAC;QAC7D,CAAC,CACF,CAAC;QAEF,IAAM,WAAW,GAAG,kCAAgB,CAAC,UAAC,CAAyC,EAAE,IAAY,EAAE,KAAa;YAC1G,IAAM,eAAe,GAAG,CAAC,KAAK,CAAC,CAAC;YAChC,gBAAgB,CAAC,UAAA,CAAC;;gBAAI,OAAA,uCAAM,CAAC,gBAAG,IAAI,IAAG,eAAe,OAAG;YAAnC,CAAmC,CAAC,CAAC;YAC3D,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAG,CAAC,EAAE,EAAE,IAAI,MAAA,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,UAAU,EAAE;gBACV,IAAI,EAAE,KAAK;aACZ;YACD,IAAI,EAAE,uCAAqB,CAAC,KAAK,sCAC/B,GAAG,EAAE,+BAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,EACjC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,WAAW,CAAC,SAAS,IACrC,eAAe,GACf,KAAK,EACR;YACF,QAAQ,EAAE,WAAW,CAAC,QAAQ,IAAI,KAAK;YACvC,aAAa,EAAE,WAAW,CAAC,aAAa,IAAI,KAAK;YACjD,aAAa,eAAA;YACb,wBAAwB,0BAAA;YACxB,WAAW,aAAA;YACX,cAAc,gBAAA;SACf,CAAC;IACJ,CAAC,CAAC;IA5GW,QAAA,oBAAoB,wBA4G/B;IAEF;;OAEG;IACH,IAAM,uBAAuB,GAAG;QAC9B,IAAM,aAAa,GAAG,qCAAuB,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,aAAa,EAArB,CAAqB,CAAC,CAAC;QAChF,IAAM,oBAAoB,GAAG,qCAAuB,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,oBAAoB,EAA5B,CAA4B,CAAC,CAAC;QAC9F,IAAM,SAAS,GAAG,qCAAuB,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,SAAS,EAAjB,CAAiB,CAAC,CAAC;QACxE,IAAM,QAAQ,GAAG,qCAAuB,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,QAAQ,EAAhB,CAAgB,CAAC,CAAC;QACtE,IAAM,aAAa,GAAG,qCAAuB,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,aAAa,EAArB,CAAqB,CAAC,CAAC;QAEhF,OAAO;YACL,aAAa,eAAA;YACb,oBAAoB,sBAAA;YACpB,SAAS,WAAA;YACT,QAAQ,UAAA;YACR,aAAa,eAAA;SACd,CAAC;IACJ,CAAC,CAAC;IAEF;;OAEG;IACH,IAAM,wBAAwB,GAAG,UAC/B,KAAoB,EACpB,YAAwD,EACxD,cAAuB;QAEvB,IAAI,sBAAsB,GAAG,KAAK,CAAC;QACnC,KAAK,IAAM,GAAG,IAAI,YAAY,EAAE;YAC9B,IAAI,KAAK,CAAC,GAA+F,CAAC,EAAE;gBAC1G,sBAAsB,GAAG,IAAI,CAAC;aAC/B;SACF;QAED,OAAO,cAAc,IAAI,sBAAsB,CAAC;IAClD,CAAC,CAAC","sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: hasMenuContext } });\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
@@ -15,17 +15,17 @@ const menuContext_2 = /*#__PURE__*/require("../../contexts/menuContext");
15
15
  */
16
16
  const useMenuList_unstable = (props, ref) => {
17
17
  var _a, _b;
18
- const focusAttributes = react_tabster_1.useArrowNavigationGroup({
19
- circular: true,
20
- ignoreDefaultKeydown: {
21
- Tab: true
22
- }
23
- });
24
18
  const {
25
19
  findAllFocusable
26
20
  } = react_tabster_1.useFocusFinders();
27
21
  const menuContext = useMenuContextSelectors();
28
22
  const hasMenuContext = react_context_selector_1.useHasParentContext(menuContext_2.MenuContext);
23
+ const focusAttributes = react_tabster_1.useArrowNavigationGroup({
24
+ circular: true,
25
+ ignoreDefaultKeydown: {
26
+ Tab: hasMenuContext
27
+ }
28
+ });
29
29
  if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {
30
30
  // TODO throw warnings in development safely
31
31
  // eslint-disable-next-line no-console
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["useMenuList_unstable","props","ref","focusAttributes","react_tabster_1","circular","ignoreDefaultKeydown","Tab","findAllFocusable","menuContext","useMenuContextSelectors","hasMenuContext","react_context_selector_1","menuContext_2","usingPropsAndMenuContext","console","warn","innerRef","React","useRef","setFocusByFirstCharacter","useCallback","e","itemEl","acceptedRoles","current","menuItems","el","hasAttribute","indexOf","getAttribute","startIndex","length","firstChars","map","menuItem","textContent","charAt","toLowerCase","char","key","getIndexFirstChars","start","firstChar","i","index","focus","checkedValues","setCheckedValues","react_utilities_1","state","undefined","defaultState","defaultCheckedValues","initialState","handleCheckedValueChange","onCheckedValueChange","toggleCheckbox","name","value","checked","checkedItems","newCheckedItems","splice","push","s","selectRadio","components","root","role","triggerId","hasIcons","hasCheckmarks","exports","menuContext_1","context","contextValue","isUsingPropsAndContext","val"],"sourceRoot":"../src/","sources":["packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: true } });\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
1
+ {"version":3,"mappings":"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","names":["useMenuList_unstable","props","ref","findAllFocusable","react_tabster_1","menuContext","useMenuContextSelectors","hasMenuContext","react_context_selector_1","menuContext_2","focusAttributes","circular","ignoreDefaultKeydown","Tab","usingPropsAndMenuContext","console","warn","innerRef","React","useRef","setFocusByFirstCharacter","useCallback","e","itemEl","acceptedRoles","current","menuItems","el","hasAttribute","indexOf","getAttribute","startIndex","length","firstChars","map","menuItem","textContent","charAt","toLowerCase","char","key","getIndexFirstChars","start","firstChar","i","index","focus","checkedValues","setCheckedValues","react_utilities_1","state","undefined","defaultState","defaultCheckedValues","initialState","handleCheckedValueChange","onCheckedValueChange","toggleCheckbox","name","value","checked","checkedItems","newCheckedItems","splice","push","s","selectRadio","components","root","role","triggerId","hasIcons","hasCheckmarks","exports","menuContext_1","context","contextValue","isUsingPropsAndContext","val"],"sourceRoot":"../src/","sources":["packages/react-components/react-menu/src/components/MenuList/useMenuList.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n useMergedRefs,\n useEventCallback,\n useControllableState,\n getNativeElementProps,\n} from '@fluentui/react-utilities';\nimport { useArrowNavigationGroup, useFocusFinders } from '@fluentui/react-tabster';\nimport { useHasParentContext } from '@fluentui/react-context-selector';\nimport { useMenuContext_unstable } from '../../contexts/menuContext';\nimport { MenuContext } from '../../contexts/menuContext';\nimport type { MenuListProps, MenuListState } from './MenuList.types';\n\n/**\n * Returns the props and state required to render the component\n */\nexport const useMenuList_unstable = (props: MenuListProps, ref: React.Ref<HTMLElement>): MenuListState => {\n const { findAllFocusable } = useFocusFinders();\n const menuContext = useMenuContextSelectors();\n const hasMenuContext = useHasParentContext(MenuContext);\n const focusAttributes = useArrowNavigationGroup({ circular: true, ignoreDefaultKeydown: { Tab: hasMenuContext } });\n\n if (usingPropsAndMenuContext(props, menuContext, hasMenuContext)) {\n // TODO throw warnings in development safely\n // eslint-disable-next-line no-console\n console.warn('You are using both MenuList and Menu props, we recommend you to use Menu props when available');\n }\n\n const innerRef = React.useRef<HTMLElement>(null);\n\n const setFocusByFirstCharacter = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>, itemEl: HTMLElement) => {\n // TODO use some kind of children registration to reduce dependency on DOM roles\n const acceptedRoles = ['menuitem', 'menuitemcheckbox', 'menuitemradio'];\n if (!innerRef.current) {\n return;\n }\n\n const menuItems = findAllFocusable(\n innerRef.current,\n (el: HTMLElement) => el.hasAttribute('role') && acceptedRoles.indexOf(el.getAttribute('role')!) !== -1,\n );\n\n let startIndex = menuItems.indexOf(itemEl) + 1;\n if (startIndex === menuItems.length) {\n startIndex = 0;\n }\n\n const firstChars = menuItems.map(menuItem => menuItem.textContent?.charAt(0).toLowerCase());\n const char = e.key.toLowerCase();\n\n const getIndexFirstChars = (start: number, firstChar: string) => {\n for (let i = start; i < firstChars.length; i++) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n };\n\n // Check remaining slots in the menu\n let index = getIndexFirstChars(startIndex, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n menuItems[index].focus();\n }\n },\n [findAllFocusable],\n );\n\n const [checkedValues, setCheckedValues] = useControllableState({\n state: props.checkedValues ?? (hasMenuContext ? menuContext.checkedValues : undefined),\n defaultState: props.defaultCheckedValues,\n initialState: {},\n });\n\n const handleCheckedValueChange =\n props.onCheckedValueChange ?? (hasMenuContext ? menuContext.onCheckedValueChange : undefined);\n\n const toggleCheckbox = useEventCallback(\n (e: React.MouseEvent | React.KeyboardEvent, name: string, value: string, checked: boolean) => {\n const checkedItems = checkedValues?.[name] || [];\n const newCheckedItems = [...checkedItems];\n if (checked) {\n newCheckedItems.splice(newCheckedItems.indexOf(value), 1);\n } else {\n newCheckedItems.push(value);\n }\n\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n },\n );\n\n const selectRadio = useEventCallback((e: React.MouseEvent | React.KeyboardEvent, name: string, value: string) => {\n const newCheckedItems = [value];\n setCheckedValues(s => ({ ...s, [name]: newCheckedItems }));\n handleCheckedValueChange?.(e, { name, checkedItems: newCheckedItems });\n });\n\n return {\n components: {\n root: 'div',\n },\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, innerRef),\n role: 'menu',\n 'aria-labelledby': menuContext.triggerId,\n ...focusAttributes,\n ...props,\n }),\n hasIcons: menuContext.hasIcons || false,\n hasCheckmarks: menuContext.hasCheckmarks || false,\n checkedValues,\n setFocusByFirstCharacter,\n selectRadio,\n toggleCheckbox,\n };\n};\n\n/**\n * Adds some sugar to fetching multiple context selector values\n */\nconst useMenuContextSelectors = () => {\n const checkedValues = useMenuContext_unstable(context => context.checkedValues);\n const onCheckedValueChange = useMenuContext_unstable(context => context.onCheckedValueChange);\n const triggerId = useMenuContext_unstable(context => context.triggerId);\n const hasIcons = useMenuContext_unstable(context => context.hasIcons);\n const hasCheckmarks = useMenuContext_unstable(context => context.hasCheckmarks);\n\n return {\n checkedValues,\n onCheckedValueChange,\n triggerId,\n hasIcons,\n hasCheckmarks,\n };\n};\n\n/**\n * Helper function to detect if props and MenuContext values are both used\n */\nconst usingPropsAndMenuContext = (\n props: MenuListProps,\n contextValue: ReturnType<typeof useMenuContextSelectors>,\n hasMenuContext: boolean,\n) => {\n let isUsingPropsAndContext = false;\n for (const val in contextValue) {\n if (props[val as keyof Omit<typeof contextValue, 'hasMenuContext' | 'onCheckedValueChange' | 'triggerId'>]) {\n isUsingPropsAndContext = true;\n }\n }\n\n return hasMenuContext && isUsingPropsAndContext;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui/react-menu",
3
- "version": "9.6.8",
3
+ "version": "9.6.9",
4
4
  "description": "Fluent UI menu component",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -40,7 +40,7 @@
40
40
  "@fluentui/react-context-selector": "^9.1.8",
41
41
  "@fluentui/react-icons": "^2.0.175",
42
42
  "@fluentui/react-portal": "^9.1.7",
43
- "@fluentui/react-positioning": "^9.4.0",
43
+ "@fluentui/react-positioning": "^9.4.1",
44
44
  "@fluentui/react-shared-contexts": "^9.2.0",
45
45
  "@fluentui/react-tabster": "^9.5.1",
46
46
  "@fluentui/react-theme": "^9.1.5",