import * as Helpers from './Helpers' ; import type { MenuActionConfig , MenuConfig } from '../types/MenuConfig' ; class ActionSheetFallbackHelpers { /** is the object a `MenuAction` item */ static isObjectMenuAction ( object ) { return ( ( 'actionKey' in object ) || ( 'actionTitle' in object ) || ( 'menuState' in object ) || ( 'menuAttributes' in object ) ) ; } ; /** is the object a `MenuObject` item */ static isObjectMenuConfig ( object ) { return ( ( 'menuTitle' in object ) || ( 'menuOptions' in object ) || ( 'menuItems' in object ) ) ; } ; /** based on the `indexPath`, return the corresponding `MenuConfig` item */ static getItemFromMenuConfig ( menuConfig , indexPath ) { if ( indexPath == null ) return null ; if ( menuConfig == null ) return null ; let currentObject = menuConfig ; for ( const index of indexPath ) { if ( currentObject == null ) { return null ; } else if ( ActionSheetFallbackHelpers . isObjectMenuAction ( currentObject ) ) { return currentObject ; } else if ( ! ActionSheetFallbackHelpers . isObjectMenuConfig ( currentObject ) ) { return null ; } ; currentObject = currentObject ?. menuItems ?. [ index ] ; } ; return currentObject ; } ; /** handle inline submenu's by hoisting submenu action to the parent menu */ static flattenMenuConfig ( menuConfig ) { if ( menuConfig == null ) return null ; let indexPath = [ 0 ] ; let currentParent = menuConfig ; const incrementCurrentIndexPath = ( ) => { const indexPathCount = indexPath . length ; indexPath [ indexPathCount - 1 ] ++ ; } ; const getCurrentIndexPath = ( ) => ( indexPath [ indexPath . length - 1 ] ) ; const getCurrentParentItemsCount = ( ) => ( currentParent ?. menuItems ?. length ?? 0 ) ; const didReachEnd = ( ) => ( getCurrentIndexPath ( ) >= ( getCurrentParentItemsCount ( ) - 1 ) ) ; while ( true ) { let currentItem = ActionSheetFallbackHelpers . getItemFromMenuConfig ( menuConfig , indexPath ) ; const isCurrentItemEmpty = ( currentItem == null ) ; if ( ! isCurrentItemEmpty && ActionSheetFallbackHelpers . isObjectMenuConfig ( currentItem ! ) ) { const isInlineSubmenu = currentItem ! . menuOptions ?. includes ( 'displayInline' ) ?? false ; const inlineSubmenuItemsCount = currentItem ! . menuItems ?. length ?? 0 ; if ( isInlineSubmenu && inlineSubmenuItemsCount > 0 ) { const inlineMenu = currentParent ?. menuItems ! . splice ( getCurrentIndexPath ( ) , 1 ) ; const inlineMenuItems = inlineMenu ?. [ 0 ] ?. menuItems ?? [ ] ; currentParent ?. menuItems ! . splice ( getCurrentIndexPath ( ) , 0 , ... inlineMenuItems ) ; } else { currentParent = ActionSheetFallbackHelpers . getItemFromMenuConfig ( menuConfig , indexPath ) ; indexPath . push ( 0 ) ; } ; } else if ( didReachEnd ( ) ) { indexPath . pop ( ) ; incrementCurrentIndexPath ( ) ; const indexPathCount = indexPath . length ; const nextIndexPath = indexPath . slice ( 0 , indexPathCount - 1 ) ; currentParent = ( ( indexPathCount <= 0 ) ? menuConfig : ActionSheetFallbackHelpers . getItemFromMenuConfig ( menuConfig , nextIndexPath ) ) ; if ( didReachEnd ( ) || indexPath . length < 1 ) break ; } else if ( ActionSheetFallbackHelpers . isObjectMenuAction ( currentItem ! ) ) { incrementCurrentIndexPath ( ) ; } else { incrementCurrentIndexPath ( ) ; } ; } ; return menuConfig ; } ; /** returns the index of the first destructive action */ static getdestructiveButtonIndex ( menuItems ) { if ( menuItems == null ) return null ; for ( let index = 0 ; index < menuItems . length ; index ++ ) { const menuItem = menuItems [ index ] ; const isDestructiveAction = menuItem ?. menuAttributes ?. includes ( 'destructive' ) ?? false ; const isDestructiveMenu = menuItem ?. menuOptions ?. includes ( 'destructive' ) ?? false ; if ( isDestructiveAction || isDestructiveMenu ) { return index ; } ; } ; return null ; } ; /** remove disabled/hidden menu actions */ static filterMenuItems ( menuItems = [ ] ) { if ( menuItems == null ) return [ ] ; return menuItems . filter ( menuItem => { const isDisabledAction = menuItem ?. menuAttributes ?. includes ( 'disabled' ) ?? false ; const isHiddenAction = menuItem ?. menuAttributes ?. includes ( 'hidden' ) ?? false ; return ( ! isDisabledAction && ! isHiddenAction ) ; } ) ; } ; } ; export class ActionSheetFallback { /** based on a `MenuConfig` object, show an `ActionSheetIOS` menu  */ static async show ( menuConfig ) { let indexPath = [ ] ; let actionSheetOptions = [ ] ; let cancelButtonIndex = 0 ; let destructiveButtonIndex = null ; const menuConfigCopy = JSON . parse ( JSON . stringify ( menuConfig ) ) ; ActionSheetFallbackHelpers . flattenMenuConfig ( menuConfigCopy ) ; while ( true ) { const menuItem = ActionSheetFallbackHelpers . getItemFromMenuConfig ( menuConfigCopy , indexPath ) ; if ( ActionSheetFallbackHelpers . isObjectMenuAction ( menuItem ! ) ) { return menuItem ; } ; const menuItems = ActionSheetFallbackHelpers . filterMenuItems ( menuItem ?. menuItems ?? [ ] ) ; actionSheetOptions = menuItems . map ( item => ( item ?. actionTitle ?? item ?. menuTitle ?? null ) ) ; destructiveButtonIndex = ActionSheetFallbackHelpers . getdestructiveButtonIndex ( menuItems ) ; if ( destructiveButtonIndex != null ) destructiveButtonIndex ++ ; const selectedIndex = await Helpers . asyncActionSheet ( { ... ( ( cancelButtonIndex != null ) && { cancelButtonIndex } ) , ... ( ( destructiveButtonIndex != null ) && { destructiveButtonIndex } ) , options : [ 'cancel' , ... actionSheetOptions ] , } ) ; if ( selectedIndex === cancelButtonIndex ) return null ; indexPath . push ( selectedIndex - 1 ) ; } ; } ; } ;