/** @jsxImportSource @fluentui-react-native/framework-base */ import React from 'react'; import { Platform, View } from 'react-native'; import type { IViewProps } from '@fluentui-react-native/adapters'; import { FocusZone } from '@fluentui-react-native/focus-zone'; import { compose } from '@fluentui-react-native/framework'; import { extractChildren, extractProps, mergeProps } from '@fluentui-react-native/framework-base'; import type { UseSlots } from '@fluentui-react-native/framework'; import type { MenuGroupProps, MenuGroupType } from './MenuGroup.types'; import { menuGroupName } from './MenuGroup.types'; import { directComponent } from '@fluentui-react-native/framework-base'; // Intentionally not enabled on macOS to match system context menus const hasFocusZone = ['win32'].includes(Platform.OS as string); export const MenuGroup = compose({ displayName: menuGroupName, slots: { root: View, contentWrapper: hasFocusZone ? FocusZone : React.Fragment, }, useRender: (userProps: MenuGroupProps, useSlots: UseSlots) => { const Slots = useSlots(userProps); return directComponent(({ children, ...final }: MenuGroupProps) => { const { ...mergedProps } = mergeProps(userProps, final); let itemPosition = 0; const childrenWithSet = React.Children.toArray(children).map((child) => { if (React.isValidElement(child)) { const itemCount = React.Children.toArray(children).filter( (child) => React.isValidElement(child) && (child as any).type.displayName !== 'MenuGroupHeader' && (child as any).type.displayName !== 'MenuDivider', ).length; if ((child as any).type.displayName !== 'MenuGroupHeader' && (child as any).type.displayName !== 'MenuDivider') { itemPosition++; } return React.cloneElement( child as React.ReactElement>, { accessibilityPosInSet: extractProps(child)?.accessibilityPosInSet ?? itemPosition, // win32 accessibilitySetSize: extractProps(child)?.accessibilitySetSize ?? itemCount, //win32 } as any, ); } return child; }); // Check if this MenuGroup has a MenuGroupHeader. If so, use the MenuGroupHeader // as the accessibilityLabel for the MenuGroup. const menuGroupHeader = React.Children.toArray(children).find( (child) => React.isValidElement(child) && (child as any).type.displayName === 'MenuGroupHeader', ); // On win32, in order for assistive technology to read a group, it must have a name which is why // we use a string with a space as the default accessibilityLabel for MenuGroup. // If an empty string was used, the group context would not be read. let menuGroupA11yLabel = ' '; const menuGroupHeaderChild = extractChildren(menuGroupHeader as React.ReactElement); if (menuGroupHeader && typeof menuGroupHeaderChild === 'string') { menuGroupA11yLabel = menuGroupHeaderChild; } return ( {childrenWithSet} ); }); }, });