/** @jsxImportSource @fluentui-react-native/framework-base */ import * as React from 'react'; import { View } from 'react-native'; import { FocusZone } from '@fluentui-react-native/focus-zone'; import { useSelectedKey } from '@fluentui-react-native/interactive-hooks'; import { Text } from '@fluentui-react-native/text'; import { foregroundColorTokens, textTokens } from '@fluentui-react-native/tokens'; import type { ISlots } from '@uifabricshared/foundation-composable'; import type { IUseComposeStyling } from '@uifabricshared/foundation-compose'; import { compose } from '@uifabricshared/foundation-compose'; import { mergeSettings } from '@uifabricshared/foundation-settings'; import { settings } from './RadioGroup.settings'; import type { IRadioGroupType, IRadioGroupProps, IRadioGroupState, IRadioGroupSlotProps, IRadioGroupRenderData, IRadioGroupContext, } from './RadioGroup.types'; import { radioGroupName } from './RadioGroup.types'; export const RadioGroupContext = React.createContext({ selectedKey: null, onChange: (/* key: string */) => { return; }, updateSelectedButtonRef: (/* ref: React.RefObject*/) => { return; }, buttonKeys: [], }); export const RadioGroup = compose({ displayName: radioGroupName, usePrepareProps: (userProps: IRadioGroupProps, useStyling: IUseComposeStyling) => { const { label, ariaLabel, accessibilityLabel, selectedKey, defaultSelectedKey, ...rest } = userProps; // This hook updates the Selected Button and calls the customer's onClick function. This gets called after a button is pressed. const data = useSelectedKey(selectedKey || defaultSelectedKey || null, userProps.onChange); const [selectedButtonRef, setSelectedButtonRef] = React.useState(React.useRef(null)); const onSelectButtonRef = React.useCallback( (ref: React.RefObject) => { setSelectedButtonRef(ref); }, [setSelectedButtonRef], ); const [invoked, setInvoked] = React.useState(false); const onInvoked = React.useCallback( (check: boolean) => { setInvoked(check); }, [setInvoked], ); const [buttonKeys, setButtonKeys] = React.useState([]); const onAddRadioButtonKey = React.useCallback( (buttonKey: string) => { setButtonKeys((prevButtonKeys) => [...prevButtonKeys, buttonKey]); }, [setButtonKeys], ); const onRemoveRadioButtonKey = React.useCallback( (buttonKey: string) => { setButtonKeys((prevButtonKeys) => prevButtonKeys.filter((item) => item !== buttonKey)); }, [setButtonKeys], ); const [enabledButtonKeys, setEnabledButtonKeys] = React.useState([]); const onAddRadioButtonEnabledKey = React.useCallback( (buttonKey: string) => { setEnabledButtonKeys((prevEnabledButtonKeys) => [...prevEnabledButtonKeys, buttonKey]); }, [setEnabledButtonKeys], ); const onRemoveRadioButtonEnabledKey = React.useCallback( (buttonKey: string) => { setEnabledButtonKeys((prevEnabledButtonKeys) => prevEnabledButtonKeys.filter((item) => item !== buttonKey)); }, [setEnabledButtonKeys], ); const state: IRadioGroupState = { context: { selectedKey: selectedKey ?? data.selectedKey, onChange: data.onKeySelect, updateSelectedButtonRef: onSelectButtonRef, invoked: invoked, updateInvoked: onInvoked, buttonKeys: buttonKeys, enabledButtonKeys: enabledButtonKeys, addRadioButtonKey: onAddRadioButtonKey, removeRadioButtonKey: onRemoveRadioButtonKey, addRadioButtonEnabledKey: onAddRadioButtonEnabledKey, removeRadioButtonEnabledKey: onRemoveRadioButtonEnabledKey, }, }; const styleProps = useStyling(userProps, (override: string) => state[override] || userProps[override]); const slotProps = mergeSettings(styleProps, { root: { accessibilityLabel: accessibilityLabel ?? ariaLabel ?? label, accessibilityRole: 'radiogroup', ...rest }, label: { children: label }, container: { isCircularNavigation: true, defaultTabbableElement: selectedButtonRef }, }); return { slotProps, state }; }, render: (Slots: ISlots, renderData: IRadioGroupRenderData, ...children: React.ReactNode[]) => { if (renderData.state == undefined) { return null; } return ( {children} ); }, settings, slots: { root: View, label: Text, container: FocusZone, }, styles: { root: [], label: [foregroundColorTokens, textTokens], container: [], }, }); export default RadioGroup;