/** @jsxImportSource @fluentui-react-native/framework-base */ import React from 'react'; import { Platform, ScrollView, View } from 'react-native'; import type { IViewProps } from '@fluentui-react-native/adapters'; import { FocusZone } from '@fluentui-react-native/focus-zone'; import type { UseSlots } from '@fluentui-react-native/framework'; import { compose } from '@fluentui-react-native/framework'; import { extractProps } from '@fluentui-react-native/framework-base'; import { stylingSettings } from './MenuList.styling'; import type { MenuListProps, MenuListState, MenuListType } from './MenuList.types'; import { menuListName } from './MenuList.types'; import { useMenuList } from './useMenuList'; import { useMenuListContextValue } from './useMenuListContextValue'; import { MenuListProvider } from '../context/menuListContext'; import { directComponent } from '@fluentui-react-native/framework-base'; const shouldHaveFocusZone = ['macos', 'win32'].includes(Platform.OS as string); const focusLandsOnContainer = Platform.OS === 'macos'; const hasCircularNavigation = Platform.OS === ('win32' as any); export const menuListLookup = (layer: string, state: MenuListState, userProps: MenuListProps): boolean => { return state[layer] || userProps[layer] || layer === 'hasMaxHeight'; }; export const MenuList = compose({ displayName: menuListName, ...stylingSettings, slots: { root: View, scrollView: ScrollView, focusZone: shouldHaveFocusZone ? FocusZone : View, }, useRender: (userProps: MenuListProps, useSlots: UseSlots) => { const menuList = useMenuList(userProps); const menuListContextValue = useMenuListContextValue(menuList); const Slots = useSlots(menuList.props, (layer) => menuListLookup(layer, menuList, userProps)); return directComponent(({ children }: MenuListProps) => { const itemCount = React.Children.toArray(children).filter( (child) => React.isValidElement(child) && (child as any).type.displayName !== 'MenuDivider', ).length; let itemPosition = 0; const childrenWithSet = React.Children.toArray(children).map((child) => { if (React.isValidElement(child)) { if ((child as any).type.displayName !== 'MenuDivider') { itemPosition++; } const childProps = extractProps(child); return React.cloneElement( child as React.ReactElement>, { accessibilityPosInSet: childProps?.accessibilityPosInSet ?? itemPosition, // win32 accessibilitySetSize: childProps?.accessibilitySetSize ?? itemCount, //win32 ...(childProps?.tooltip && { alwaysShowToolTip: true }), } as any, ); } return child; }); const shouldHaveScrollView = Platform.OS === 'macos' || menuList.hasMaxHeight || menuList.hasMaxWidth; const ScrollViewWrapper = shouldHaveScrollView ? Slots.scrollView : React.Fragment; const hasMenuGroupChild = React.Children.toArray(children).some( (child) => child && (child as any).type && (child as any).type.displayName === 'MenuGroup', ); // On win32, tab navigation should only be enabled when we have menu groups. const hasTabNavigation = Platform.OS === ('win32' as any) && hasMenuGroupChild; const content = ( {childrenWithSet} ); return {content}; }); }, });