Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,21 @@ Optional. When set to `true`, the context menu is triggered with a single tap in
### `disabled`

Optional. Disable menu interaction.

### `borderRadius`
Optional, iOS only. Sets the border radius for all corners of the preview. Can be overridden by individual corner settings.

### `borderTopLeftRadius`
Optional, iOS only. Sets the border radius specifically for the top left corner of the preview.

### `borderTopRightRadius`
Optional, iOS only. Sets the border radius specifically for the top right corner of the preview.

### `borderBottomRightRadius`
Optional, iOS only. Sets the border radius specifically for the bottom right corner of the preview.

### `borderBottomLeftRadius`
Optional, iOS only. Sets the border radius specifically for the bottom left corner of the preview.

### `disableShadow`
Optional, iOS only. When set to `true`, removes the shadow from the preview. Default is `false`.
26 changes: 25 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@ export interface ContextMenuProps extends ViewProps {
* Children prop as per upgrade docs: https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-typescript-definitions
*/
children?: React.ReactNode;
/**
* Border radius for all corners
*/
borderRadius?: number;
/**
* Border radius for top left corner
*/
borderTopLeftRadius?: number;
/**
* Border radius for top right corner
*/
borderTopRightRadius?: number;
/**
* Border radius for bottom right corner
*/
borderBottomRightRadius?: number;
/**
* Border radius for bottom left corner
*/
borderBottomLeftRadius?: number;
/**
* Disable shadow in preview
*/
disableShadow?: boolean;
}

export default class ContextMenu extends Component<ContextMenuProps> {}
export default class ContextMenu extends Component<ContextMenuProps> { }
10 changes: 9 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ import { requireNativeComponent, View, Platform, StyleSheet, processColor } from
const NativeContextMenu = requireNativeComponent("ContextMenu", null);

const ContextMenu = (props) => {
const defaultProps = {
borderRadius: -1,
borderTopLeftRadius: -1,
borderTopRightRadius: -1,
borderBottomRightRadius: -1,
borderBottomLeftRadius: -1
};

const iconColor = props?.iconColor
? Platform.OS === 'ios'
? processColor(props.iconColor)
: props.iconColor
: undefined;

return (
<NativeContextMenu {...props} iconColor={iconColor}>
<NativeContextMenu {...defaultProps} {...props} iconColor={iconColor}>
{props.children}
{props.preview != null && Platform.OS === 'ios' ? (
<View style={styles.preview} nativeID="ContextMenuPreview">{props.preview}</View>
Expand Down
6 changes: 6 additions & 0 deletions ios/ContextMenu.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ - (UIView *) view {
RCT_CUSTOM_VIEW_PROPERTY(previewBackgroundColor, UIColor, ContextMenuView) {
view.previewBackgroundColor = json != nil ? [RCTConvert UIColor:json] : nil;
}
RCT_EXPORT_VIEW_PROPERTY(borderRadius, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(borderTopLeftRadius, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(borderTopRightRadius, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(borderBottomRightRadius, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(borderBottomLeftRadius, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(disableShadow, BOOL)
RCT_CUSTOM_VIEW_PROPERTY(dropdownMenuMode, BOOL, ContextMenuView) {
if (@available(iOS 14.0, *)) {
view.showsMenuAsPrimaryAction = json != nil ? [RCTConvert BOOL:json] : view.showsMenuAsPrimaryAction;
Expand Down
6 changes: 6 additions & 0 deletions ios/ContextMenuView.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,11 @@
@property (nullable, nonatomic, copy) NSArray<ContextMenuAction*>* actions;
@property (nullable, nonatomic, copy) UIColor* previewBackgroundColor;
@property (nonatomic, assign) BOOL disabled;
@property (nonatomic, assign) CGFloat borderRadius;
@property (nonatomic, assign) CGFloat borderTopLeftRadius;
@property (nonatomic, assign) CGFloat borderTopRightRadius;
@property (nonatomic, assign) CGFloat borderBottomRightRadius;
@property (nonatomic, assign) CGFloat borderBottomLeftRadius;
@property (nonatomic, assign) BOOL disableShadow;

@end
66 changes: 55 additions & 11 deletions ios/ContextMenuView.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,65 @@ - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction willEndFo
}
}

- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) {
UIPreviewTarget* previewTarget = [[UIPreviewTarget alloc] initWithContainer:self center:self.reactSubviews.firstObject.center];
- (UIPreviewParameters *)getPreviewParams {
UIPreviewParameters* previewParams = [[UIPreviewParameters alloc] init];

if (_previewBackgroundColor != nil) {
previewParams.backgroundColor = _previewBackgroundColor;
previewParams.backgroundColor = _previewBackgroundColor;
}

if (self.borderRadius > -1 ||
self.borderTopLeftRadius > -1 ||
self.borderTopRightRadius > -1 ||
self.borderBottomRightRadius > -1 ||
self.borderBottomLeftRadius > -1) {

CGFloat radius = self.borderRadius > -1 ? self.borderRadius : 0;
CGFloat topLeftRadius = self.borderTopLeftRadius > -1 ? self.borderTopLeftRadius : radius;
CGFloat topRightRadius = self.borderTopRightRadius > -1 ? self.borderTopRightRadius : radius;
CGFloat bottomRightRadius = self.borderBottomRightRadius > -1 ? self.borderBottomRightRadius : radius;
CGFloat bottomLeftRadius = self.borderBottomLeftRadius > -1 ? self.borderBottomLeftRadius : radius;

UIBezierPath *path = [UIBezierPath bezierPath];
CGRect bounds = self.bounds;

[path moveToPoint: CGPointMake(CGRectGetMinX(bounds) + topLeftRadius, CGRectGetMinY(bounds))];

[path addLineToPoint: CGPointMake(CGRectGetMaxX(bounds) - topRightRadius, CGRectGetMinY(bounds))];
[path addQuadCurveToPoint: CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds) + topRightRadius)
controlPoint: CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))];

[path addLineToPoint: CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds) - bottomRightRadius)];
[path addQuadCurveToPoint: CGPointMake(CGRectGetMaxX(bounds) - bottomRightRadius, CGRectGetMaxY(bounds))
controlPoint: CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))];

[path addLineToPoint: CGPointMake(CGRectGetMinX(bounds) + bottomLeftRadius, CGRectGetMaxY(bounds))];
[path addQuadCurveToPoint: CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds) - bottomLeftRadius)
controlPoint: CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))];

[path addLineToPoint: CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds) + topLeftRadius)];
[path addQuadCurveToPoint: CGPointMake(CGRectGetMinX(bounds) + topLeftRadius, CGRectGetMinY(bounds))
controlPoint: CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))];

[path closePath];

previewParams.visiblePath = path;
}


if (self.disableShadow) {
previewParams.shadowPath = [UIBezierPath bezierPath];
}

return previewParams;
}

- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) {
UIPreviewTarget* previewTarget = [[UIPreviewTarget alloc] initWithContainer:self center:self.reactSubviews.firstObject.center];


return [[UITargetedPreview alloc] initWithView:self.reactSubviews.firstObject
parameters:previewParams
parameters:[self getPreviewParams]
target:previewTarget];
}

Expand All @@ -127,14 +176,9 @@ - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)intera
}

UIPreviewTarget* previewTarget = [[UIPreviewTarget alloc] initWithContainer:self center:hostView.center];
UIPreviewParameters* previewParams = [[UIPreviewParameters alloc] init];

if (_previewBackgroundColor != nil) {
previewParams.backgroundColor = _previewBackgroundColor;
}

return [[UITargetedPreview alloc] initWithView:hostView
parameters:previewParams
parameters:[self getPreviewParams]
target:previewTarget];
}

Expand Down