diff --git a/ios/src_library/React Native/RCTContextMenu/RCTContextMenuManager.m b/ios/src_library/React Native/RCTContextMenu/RCTContextMenuManager.m index 3ef89db..efbb0ad 100644 --- a/ios/src_library/React Native/RCTContextMenu/RCTContextMenuManager.m +++ b/ios/src_library/React Native/RCTContextMenu/RCTContextMenuManager.m @@ -11,11 +11,18 @@ @interface RCT_EXTERN_MODULE(RCTContextMenuManager, RCTViewManager) -// -------------------------------- -// MARK: Props - RN Component Props -// -------------------------------- +// ----------------------------------- +// MARK: Props - RN Comp Props: Events +// ----------------------------------- -RCT_EXPORT_VIEW_PROPERTY(onPressMenuItem, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onMenuShow , RCTBubblingEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onMenuHide , RCTBubblingEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPressMenuItem , RCTBubblingEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPressMenuPreview, RCTBubblingEventBlock); + +// ----------------------------------- +// MARK: Props - RN Comp Props: Values +// ----------------------------------- RCT_EXPORT_VIEW_PROPERTY(menuConfig, NSDictionary); diff --git a/ios/src_library/React Native/RCTContextMenu/RCTContextMenuView.swift b/ios/src_library/React Native/RCTContextMenu/RCTContextMenuView.swift index a14d27e..3d84b8f 100644 --- a/ios/src_library/React Native/RCTContextMenu/RCTContextMenuView.swift +++ b/ios/src_library/React Native/RCTContextMenu/RCTContextMenuView.swift @@ -12,7 +12,18 @@ import UIKit @available(iOS 13, *) class RCTContextMenuView: UIView { - @objc var onPressMenuItem: RCTDirectEventBlock?; + // --------------------------------------------- + // MARK: RCTContextMenuView - RN Event Callbacks + // --------------------------------------------- + + @objc var onMenuShow : RCTBubblingEventBlock?; + @objc var onMenuHide : RCTBubblingEventBlock?; + @objc var onPressMenuItem : RCTBubblingEventBlock?; + @objc var onPressMenuPreview: RCTBubblingEventBlock?; + + // ----------------------------------- + // MARK: RCTContextMenuView - RN Props + // ----------------------------------- private var _menuConfig: RCTMenuItem?; @objc var menuConfig: NSDictionary? { @@ -32,6 +43,10 @@ class RCTContextMenuView: UIView { } }; + // ------------------------------- + // MARK: RCTContextMenuView - Init + // ------------------------------- + init(bridge: RCTBridge) { super.init(frame: CGRect()); @@ -53,7 +68,10 @@ extension RCTContextMenuView: UIContextMenuInteractionDelegate { func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { guard let menuConfig = self._menuConfig else { #if DEBUG - print("guard check failed - contextMenuInteraction, menuConfig: is nil"); + print("RCTContextMenuView, UIContextMenuInteractionDelegate" + + " - contextMenuInteraction: config" + + " - guard check failed, menuConfig: nil" + ); #endif return nil; }; @@ -64,4 +82,37 @@ extension RCTContextMenuView: UIContextMenuInteractionDelegate { }); }); }; + + // context menu display begins + func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willDisplayMenuFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) { + #if DEBUG + print("RCTContextMenuView, UIContextMenuInteractionDelegate" + + " - contextMenuInteraction: will show" + ); + #endif + + self.onMenuShow?([:]); + }; + + // context menu display ends + func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) { + #if DEBUG + print("RCTContextMenuView, UIContextMenuInteractionDelegate" + + " - contextMenuInteraction: will hide" + ); + #endif + + self.onMenuHide?([:]); + }; + + // context menu preview tapped + func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { + #if DEBUG + print("RCTContextMenuView, UIContextMenuInteractionDelegate" + + " - contextMenuInteraction: preview tapped" + ); + #endif + + self.onPressMenuPreview?([:]); + }; }; diff --git a/src/ContextMenuView.js b/src/ContextMenuView.js index 6b3b250..ebfd0f1 100644 --- a/src/ContextMenuView.js +++ b/src/ContextMenuView.js @@ -8,33 +8,82 @@ const NativeCommands = UIManager[componentName]?.Commands; const NativeComponent = requireNativeComponent(componentName); const NATIVE_PROP_KEYS = { - menuConfig : 'menuConfig' , - onPressMenuItem: 'onPressMenuItem', + // props: values -------- + menuConfig: 'menuConfig', + // props: events ------------------------ + onMenuShow : 'onMenuShow' , + onMenuHide : 'onMenuHide' , + onPressMenuItem : 'onPressMenuItem' , + onPressMenuPreview: 'onPressMenuPreview', }; export class ContextMenuView extends React.PureComponent { static proptypes = { menuConfig: Proptypes.object, - onPressMenuItem: Proptypes.func, + // events ------------------------- + onMenuShow : Proptypes.func, + onMenuHide : Proptypes.func, + onPressMenuItem : Proptypes.func, + onPressMenuPreview: Proptypes.func, + }; + + constructor(props){ + super(props); + + this.state = { + menuVisible: false, + }; + }; + + //#region - Event Handlers + _handleOnMenuShow = (event) => { + const { onMenuShow } = this.props; + onMenuShow?.(event); + + this.setState({menuVisible: true}); + + }; + + _handleOnMenuHide = (event) => { + const { onMenuHide } = this.props; + onMenuHide?.(event); + + this.setState({menuVisible: false}); }; _handleOnPressMenuItem = ({nativeEvent}) => { this.props.onPressMenuItem?.({key: nativeEvent.key}); }; + _handleOnPressMenuPreview = (event) => { + const { onPressMenuPreview } = this.props; + onPressMenuPreview?.(event); + }; + //#endregion + render(){ - const { style, ...props } = this.props; + const { style, children, ...props } = this.props; + const { menuVisible } = this.state; + const nativeProps = { ...props, - style: [styles.menuView, style], - [NATIVE_PROP_KEYS.onPressMenuItem]: this._handleOnPressMenuItem, + // Native Props ------------------------------------------------------ + [NATIVE_PROP_KEYS.onMenuShow ]: this._handleOnMenuShow , + [NATIVE_PROP_KEYS.onMenuHide ]: this._handleOnMenuHide , + [NATIVE_PROP_KEYS.onPressMenuItem ]: this._handleOnPressMenuItem , + [NATIVE_PROP_KEYS.onPressMenuPreview]: this._handleOnPressMenuPreview, }; return( + > + {React.Children.map(children, child => + React.cloneElement(child, {menuVisible}) + )} + ); }; };