Skip to content

Commit

Permalink
Add hitSlop support (#627) (#888)
Browse files Browse the repository at this point in the history
  • Loading branch information
elliottkember authored Sep 13, 2024
1 parent a149bbf commit 285248d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ios/MenuViewManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,9 @@ - (UIView *)view
*/
RCT_EXPORT_VIEW_PROPERTY(themeVariant, NSString)

/**
* hitSlop: The same as hitSlop in React Native
*/
RCT_EXPORT_VIEW_PROPERTY(hitSlop, UIEdgeInsets)

@end
19 changes: 19 additions & 0 deletions ios/Shared/MenuViewImplementation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class MenuViewImplementation: UIButton {
}
}

@objc var hitSlop: UIEdgeInsets = .zero

override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
Expand Down Expand Up @@ -77,6 +79,23 @@ public class MenuViewImplementation: UIButton {
super.reactSetFrame(frame);
};

public override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if hitSlop == .zero || !self.isEnabled || self.isHidden {
return super.point(inside: point, with: event)
}

// Create a larger hit frame that extends beyond the view's bounds
let largerFrame = CGRect(
x: self.bounds.origin.x - hitSlop.left,
y: self.bounds.origin.y - hitSlop.top,
width: self.bounds.size.width + hitSlop.left + hitSlop.right,
height: self.bounds.size.height + hitSlop.top + hitSlop.bottom
)

// Check if the point is within the larger frame
return largerFrame.contains(point)
}


required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
Expand Down
6 changes: 4 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ function processAction(action: MenuAction): ProcessedMenuAction {
};
}

const MenuView: React.FC<MenuComponentProps> = ({ actions, ...props }) => {
const defaultHitslop = { top: 0, left: 0, bottom: 0, right: 0 };

const MenuView: React.FC<MenuComponentProps> = ({ actions, hitSlop = defaultHitslop, ...props }) => {

Check failure on line 24 in src/index.tsx

View workflow job for this annotation

GitHub Actions / lint (20)

Replace `·actions,·hitSlop·=·defaultHitslop,·...props·` with `⏎··actions,⏎··hitSlop·=·defaultHitslop,⏎··...props⏎`
const processedActions = actions.map<ProcessedMenuAction>((action) =>
processAction(action)
);
const hash = useMemo(() => {
return objectHash(processedActions);
}, [processedActions]);
return (
<UIMenuView {...props} actions={processedActions} actionsHash={hash} />
<UIMenuView {...props} hitSlop={hitSlop} actions={processedActions} actionsHash={hash} />

Check failure on line 32 in src/index.tsx

View workflow job for this annotation

GitHub Actions / lint (20)

Replace `·{...props}·hitSlop={hitSlop}·actions={processedActions}·actionsHash={hash}` with `⏎······{...props}⏎······hitSlop={hitSlop}⏎······actions={processedActions}⏎······actionsHash={hash}⏎···`
);
};

Expand Down
11 changes: 11 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ type MenuComponentPropsBase = {
* @platform iOS
*/
themeVariant?: string;
/**
* Custom OpenSpace hitSlop prop. Works like touchable hitslop.
* @platform iOS
*/
hitSlop?: {
top: number;
bottom: number;
left: number;
right: number;
};
};

export type MenuComponentProps =
Expand All @@ -164,4 +174,5 @@ export type NativeMenuComponentProps = {
actions: ProcessedMenuAction[];
actionsHash: string;
title?: string;
hitSlop?: MenuComponentProps['hitSlop'];
};

0 comments on commit 285248d

Please sign in to comment.