Skip to content

Commit ecb9448

Browse files
committed
feat: restrict trigger fall-through issue to iOS
1 parent 5cf3e15 commit ecb9448

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

Diff for: README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -77,26 +77,26 @@ If you want to avoid wrapping your component in a span that listens for the brow
7777

7878
```jsx
7979
import { h } from "preact";
80-
import { ContextMenu, attachContextMenu } from "preact-context-menu";
80+
import { ContextMenu, useTriggerEvents } from "preact-context-menu";
8181

8282
function Component() {
8383
return (
8484
<div>
8585
<ContextMenu id="unique_id">
8686
My Context Menu
8787
</ContextMenu>
88-
<div onContextMenu={attachContextMenu("unique_id")}>
88+
<div {...useTriggerEvents("unique_id")}>
8989
Right-click me to open context menu!
9090
</div>
91-
<div onContextMenu={attachContextMenu("unique_id", { hello: "Hello, world!" })}>
91+
<div {...useTriggerEvents("unique_id", { hello: "Hello, world!" })}>
9292
Right-click me to open context menu with data!
9393
</div>
9494
</div>
9595
);
9696
}
9797
```
9898

99-
#### Opening a menu programatically
99+
#### Opening a menu programmatically
100100

101101
A context menu can also be opened by calling the openContextMenu function with the context menu ID and optionally any data and/or the coordinates where the context menu should appear
102102

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "preact-context-menu",
3-
"version": "0.4.0-patch.0",
3+
"version": "0.4.1",
44
"description": "A context menu in Preact",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

Diff for: src/util.ts

+34-27
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export const openContextMenu = (id: string, data?: any, coords?: Coords) => {
2121

2222
var timeout = 0;
2323

24+
const iOS = () => /(iPad|iPhone|iPod)/g.test(navigator.userAgent) || (navigator.userAgent.includes("Mac") && "ontouchend" in document);
25+
2426
/**
2527
* Bind context menu events to a Ref.
2628
* @param ref Ref object
@@ -30,35 +32,40 @@ var timeout = 0;
3032
* @param touchTimeout Long press duration to show context menu
3133
*/
3234
export const useTriggerEvents = (id: string, data?: any, disabled?: boolean, touchTimeout = 610) => {
33-
// For most browsers, we can use onContextMenu.
34-
const onContextMenu = (event: JSX.TargetedMouseEvent<HTMLSpanElement>) => {
35-
if (disabled === true) return;
36-
openContextMenu(id, data, { x: event.clientX, y: event.clientY });
37-
event.stopPropagation();
38-
event.preventDefault();
39-
};
35+
if (iOS()) {
36+
// On iOS devices, we need to manually handle the touch events.
37+
const onTouchStart = (event: JSX.TargetedTouchEvent<HTMLSpanElement>) => {
38+
if (disabled === true) return;
39+
const touch = event.touches[0];
40+
41+
clearTimeout(timeout);
42+
timeout = setTimeout(() => {
43+
openContextMenu(id, data, { x: touch.clientX, y: touch.clientY });
44+
}, touchTimeout) as unknown as number;
45+
};
4046

41-
// On iOS devices, we need to manually handle the touch events.
42-
const onTouchStart = (event: JSX.TargetedTouchEvent<HTMLSpanElement>) => {
43-
if (disabled === true) return;
44-
const touch = event.touches[0];
45-
46-
clearTimeout(timeout);
47-
timeout = setTimeout(() => {
48-
openContextMenu(id, data, { x: touch.clientX, y: touch.clientY });
49-
}, touchTimeout) as unknown as number;
50-
};
47+
// Cancel context menu if we move, end or cancel the touch.
48+
const onTouchCancel = () => {
49+
clearTimeout(timeout);
50+
};
5151

52-
// Cancel context menu if we move, end or cancel the touch.
53-
const onTouchCancel = () => {
54-
clearTimeout(timeout);
55-
};
52+
return {
53+
onTouchStart,
54+
onTouchCancel,
55+
onTouchMove: onTouchCancel,
56+
onTouchEnd: onTouchCancel
57+
}
58+
} else {
59+
// For most browsers, we can use onContextMenu.
60+
const onContextMenu = (event: JSX.TargetedMouseEvent<HTMLSpanElement>) => {
61+
if (disabled === true) return;
62+
openContextMenu(id, data, { x: event.clientX, y: event.clientY });
63+
event.stopPropagation();
64+
event.preventDefault();
65+
};
5666

57-
return {
58-
onContextMenu,
59-
onTouchStart,
60-
onTouchCancel,
61-
onTouchMove: onTouchCancel,
62-
onTouchEnd: onTouchCancel
67+
return {
68+
onContextMenu
69+
}
6370
}
6471
}

0 commit comments

Comments
 (0)