tinky-mouse 0.1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/contexts/MouseContext.d.ts +13 -8
- package/lib/contexts/MouseContext.js +36 -85
- package/lib/hooks/use-mouse-context.d.ts +1 -1
- package/lib/hooks/use-mouse-context.js +4 -7
- package/lib/hooks/use-mouse.js +6 -10
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -11
- package/lib/utils/mouse.js +54 -61
- package/lib/utils/sequences.js +16 -22
- package/package.json +1 -1
- package/lib/hooks/useMouse.d.ts +0 -4
- package/lib/hooks/useMouse.js +0 -16
- package/lib/hooks/useMouseContext.d.ts +0 -1
- package/lib/hooks/useMouseContext.js +0 -12
- package/lib/utils/events.d.ts +0 -17
- package/lib/utils/events.js +0 -14
- package/lib/utils/input.d.ts +0 -12
- package/lib/utils/input.js +0 -51
|
@@ -24,10 +24,22 @@ export interface MouseContextValue {
|
|
|
24
24
|
*/
|
|
25
25
|
unsubscribe: (handler: MouseHandler) => void;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Context for managing mouse events.
|
|
29
|
+
*/
|
|
27
30
|
/**
|
|
28
31
|
* Context for managing mouse events.
|
|
29
32
|
*/
|
|
30
33
|
export declare const MouseContext: React.Context<MouseContextValue | undefined>;
|
|
34
|
+
/**
|
|
35
|
+
* Props for the MouseProvider component.
|
|
36
|
+
*/
|
|
37
|
+
export interface MouseProviderProps {
|
|
38
|
+
/** The child components that will have access to the mouse context. */
|
|
39
|
+
children: React.ReactNode;
|
|
40
|
+
/** Whether to enable mouse event reporting. */
|
|
41
|
+
mouseEventsEnabled?: boolean;
|
|
42
|
+
}
|
|
31
43
|
/**
|
|
32
44
|
* Provider component that sets up mouse event listening and distribution.
|
|
33
45
|
*
|
|
@@ -42,12 +54,5 @@ export declare const MouseContext: React.Context<MouseContextValue | undefined>;
|
|
|
42
54
|
* ```
|
|
43
55
|
*
|
|
44
56
|
* @param props - The component props.
|
|
45
|
-
* @param props.children - The child components.
|
|
46
|
-
* @param props.mouseEventsEnabled - Whether to enable mouse event reporting. Defaults to `false` (implicit).
|
|
47
57
|
*/
|
|
48
|
-
export declare function MouseProvider(
|
|
49
|
-
/** The child components that will have access to the mouse context. */
|
|
50
|
-
children: React.ReactNode;
|
|
51
|
-
/** Whether to enable mouse event reporting. */
|
|
52
|
-
mouseEventsEnabled?: boolean;
|
|
53
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
58
|
+
export declare function MouseProvider(props: MouseProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,34 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (o && i >= o.length) o = void 0;
|
|
8
|
-
return { value: o && o[i++], done: !o };
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
-
};
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.MouseContext = void 0;
|
|
15
|
-
exports.enableMouseEvents = enableMouseEvents;
|
|
16
|
-
exports.disableMouseEvents = disableMouseEvents;
|
|
17
|
-
exports.MouseProvider = MouseProvider;
|
|
18
|
-
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
-
var tinky_1 = require("tinky");
|
|
20
|
-
var react_1 = require("react");
|
|
21
|
-
var sequences_js_1 = require("../utils/sequences.js");
|
|
22
|
-
var mouse_js_1 = require("../utils/mouse.js");
|
|
23
|
-
var MAX_MOUSE_BUFFER_SIZE = 4096;
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useStdin } from "tinky";
|
|
3
|
+
import { createContext, useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import { ESC } from "../utils/sequences.js";
|
|
5
|
+
import { isIncompleteMouseSequence, parseMouseEvent, } from "../utils/mouse.js";
|
|
6
|
+
const MAX_MOUSE_BUFFER_SIZE = 4096;
|
|
24
7
|
// ANSI escape sequences for mouse event control
|
|
25
|
-
|
|
8
|
+
const ENABLE_MOUSE_SEQUENCES = [
|
|
26
9
|
"\x1b[?1000h", // Enable basic mouse mode (button press/release)
|
|
27
10
|
"\x1b[?1002h", // Enable button event tracking (motion while button down)
|
|
28
11
|
"\x1b[?1003h", // Enable any event tracking (all motion) - optional
|
|
29
12
|
"\x1b[?1006h", // Enable SGR extended mode (better coordinate reporting)
|
|
30
13
|
];
|
|
31
|
-
|
|
14
|
+
const DISABLE_MOUSE_SEQUENCES = [
|
|
32
15
|
"\x1b[?1006l", // Disable SGR extended mode
|
|
33
16
|
"\x1b[?1003l", // Disable any event tracking
|
|
34
17
|
"\x1b[?1002l", // Disable button event tracking
|
|
@@ -37,45 +20,26 @@ var DISABLE_MOUSE_SEQUENCES = [
|
|
|
37
20
|
/**
|
|
38
21
|
* Enable mouse event reporting in the terminal.
|
|
39
22
|
*/
|
|
40
|
-
function enableMouseEvents() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
for (var ENABLE_MOUSE_SEQUENCES_1 = __values(ENABLE_MOUSE_SEQUENCES), ENABLE_MOUSE_SEQUENCES_1_1 = ENABLE_MOUSE_SEQUENCES_1.next(); !ENABLE_MOUSE_SEQUENCES_1_1.done; ENABLE_MOUSE_SEQUENCES_1_1 = ENABLE_MOUSE_SEQUENCES_1.next()) {
|
|
44
|
-
var seq = ENABLE_MOUSE_SEQUENCES_1_1.value;
|
|
45
|
-
process.stdout.write(seq);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
49
|
-
finally {
|
|
50
|
-
try {
|
|
51
|
-
if (ENABLE_MOUSE_SEQUENCES_1_1 && !ENABLE_MOUSE_SEQUENCES_1_1.done && (_a = ENABLE_MOUSE_SEQUENCES_1.return)) _a.call(ENABLE_MOUSE_SEQUENCES_1);
|
|
52
|
-
}
|
|
53
|
-
finally { if (e_1) throw e_1.error; }
|
|
23
|
+
export function enableMouseEvents() {
|
|
24
|
+
for (const seq of ENABLE_MOUSE_SEQUENCES) {
|
|
25
|
+
process.stdout.write(seq);
|
|
54
26
|
}
|
|
55
27
|
}
|
|
56
28
|
/**
|
|
57
29
|
* Disable mouse event reporting in the terminal.
|
|
58
30
|
*/
|
|
59
|
-
function disableMouseEvents() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (var DISABLE_MOUSE_SEQUENCES_1 = __values(DISABLE_MOUSE_SEQUENCES), DISABLE_MOUSE_SEQUENCES_1_1 = DISABLE_MOUSE_SEQUENCES_1.next(); !DISABLE_MOUSE_SEQUENCES_1_1.done; DISABLE_MOUSE_SEQUENCES_1_1 = DISABLE_MOUSE_SEQUENCES_1.next()) {
|
|
63
|
-
var seq = DISABLE_MOUSE_SEQUENCES_1_1.value;
|
|
64
|
-
process.stdout.write(seq);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
68
|
-
finally {
|
|
69
|
-
try {
|
|
70
|
-
if (DISABLE_MOUSE_SEQUENCES_1_1 && !DISABLE_MOUSE_SEQUENCES_1_1.done && (_a = DISABLE_MOUSE_SEQUENCES_1.return)) _a.call(DISABLE_MOUSE_SEQUENCES_1);
|
|
71
|
-
}
|
|
72
|
-
finally { if (e_2) throw e_2.error; }
|
|
31
|
+
export function disableMouseEvents() {
|
|
32
|
+
for (const seq of DISABLE_MOUSE_SEQUENCES) {
|
|
33
|
+
process.stdout.write(seq);
|
|
73
34
|
}
|
|
74
35
|
}
|
|
75
36
|
/**
|
|
76
37
|
* Context for managing mouse events.
|
|
77
38
|
*/
|
|
78
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Context for managing mouse events.
|
|
41
|
+
*/
|
|
42
|
+
export const MouseContext = createContext(undefined);
|
|
79
43
|
/**
|
|
80
44
|
* Provider component that sets up mouse event listening and distribution.
|
|
81
45
|
*
|
|
@@ -90,61 +54,48 @@ exports.MouseContext = (0, react_1.createContext)(undefined);
|
|
|
90
54
|
* ```
|
|
91
55
|
*
|
|
92
56
|
* @param props - The component props.
|
|
93
|
-
* @param props.children - The child components.
|
|
94
|
-
* @param props.mouseEventsEnabled - Whether to enable mouse event reporting. Defaults to `false` (implicit).
|
|
95
57
|
*/
|
|
96
|
-
function MouseProvider(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
58
|
+
export function MouseProvider(props) {
|
|
59
|
+
const { children, mouseEventsEnabled } = props;
|
|
60
|
+
const { stdin } = useStdin();
|
|
61
|
+
const subscribers = useRef(new Set()).current;
|
|
62
|
+
const subscribe = useCallback((handler) => {
|
|
101
63
|
subscribers.add(handler);
|
|
102
64
|
}, [subscribers]);
|
|
103
|
-
|
|
65
|
+
const unsubscribe = useCallback((handler) => {
|
|
104
66
|
subscribers.delete(handler);
|
|
105
67
|
}, [subscribers]);
|
|
106
|
-
|
|
68
|
+
useEffect(() => {
|
|
107
69
|
if (!mouseEventsEnabled) {
|
|
108
70
|
return;
|
|
109
71
|
}
|
|
110
72
|
// Enable mouse event reporting in terminal
|
|
111
73
|
enableMouseEvents();
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
for (var subscribers_1 = __values(subscribers), subscribers_1_1 = subscribers_1.next(); !subscribers_1_1.done; subscribers_1_1 = subscribers_1.next()) {
|
|
117
|
-
var handler = subscribers_1_1.value;
|
|
118
|
-
handler(event);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
122
|
-
finally {
|
|
123
|
-
try {
|
|
124
|
-
if (subscribers_1_1 && !subscribers_1_1.done && (_a = subscribers_1.return)) _a.call(subscribers_1);
|
|
125
|
-
}
|
|
126
|
-
finally { if (e_3) throw e_3.error; }
|
|
74
|
+
let mouseBuffer = "";
|
|
75
|
+
const broadcast = (event) => {
|
|
76
|
+
for (const handler of subscribers) {
|
|
77
|
+
handler(event);
|
|
127
78
|
}
|
|
128
79
|
};
|
|
129
|
-
|
|
80
|
+
const handleData = (data) => {
|
|
130
81
|
mouseBuffer += typeof data === "string" ? data : data.toString("utf-8");
|
|
131
82
|
// Safety cap to prevent infinite buffer growth on garbage
|
|
132
83
|
if (mouseBuffer.length > MAX_MOUSE_BUFFER_SIZE) {
|
|
133
84
|
mouseBuffer = mouseBuffer.slice(-MAX_MOUSE_BUFFER_SIZE);
|
|
134
85
|
}
|
|
135
86
|
while (mouseBuffer.length > 0) {
|
|
136
|
-
|
|
87
|
+
const parsed = parseMouseEvent(mouseBuffer);
|
|
137
88
|
if (parsed) {
|
|
138
89
|
broadcast(parsed.event);
|
|
139
90
|
mouseBuffer = mouseBuffer.slice(parsed.length);
|
|
140
91
|
continue;
|
|
141
92
|
}
|
|
142
|
-
if (
|
|
93
|
+
if (isIncompleteMouseSequence(mouseBuffer)) {
|
|
143
94
|
break; // Wait for more data
|
|
144
95
|
}
|
|
145
96
|
// Not a valid sequence at start, and not waiting for more data.
|
|
146
97
|
// Discard garbage until next possible sequence start.
|
|
147
|
-
|
|
98
|
+
const nextEsc = mouseBuffer.indexOf(ESC, 1);
|
|
148
99
|
if (nextEsc !== -1) {
|
|
149
100
|
mouseBuffer = mouseBuffer.slice(nextEsc);
|
|
150
101
|
// Loop continues to try parsing at new location
|
|
@@ -157,13 +108,13 @@ function MouseProvider(_a) {
|
|
|
157
108
|
};
|
|
158
109
|
if (!stdin)
|
|
159
110
|
return;
|
|
160
|
-
|
|
111
|
+
const stdinStream = stdin;
|
|
161
112
|
stdinStream.on("data", handleData);
|
|
162
|
-
return
|
|
113
|
+
return () => {
|
|
163
114
|
stdinStream.removeListener("data", handleData);
|
|
164
115
|
// Disable mouse event reporting when unmounting
|
|
165
116
|
disableMouseEvents();
|
|
166
117
|
};
|
|
167
118
|
}, [stdin, mouseEventsEnabled, subscribers]);
|
|
168
|
-
return ((
|
|
119
|
+
return (_jsx(MouseContext.Provider, { value: { subscribe, unsubscribe }, children: children }));
|
|
169
120
|
}
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
* @returns The mouse context value containing `subscribe` and `unsubscribe` methods.
|
|
7
7
|
* @throws Error if used outside of a `MouseProvider`.
|
|
8
8
|
*/
|
|
9
|
-
export declare function useMouseContext(): import("../
|
|
9
|
+
export declare function useMouseContext(): import("../index.js").MouseContextValue;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.useMouseContext = useMouseContext;
|
|
4
|
-
var react_1 = require("react");
|
|
5
|
-
var MouseContext_js_1 = require("../contexts/MouseContext.js");
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { MouseContext } from "../contexts/MouseContext.js";
|
|
6
3
|
/**
|
|
7
4
|
* Hook to access the MouseContext.
|
|
8
5
|
*
|
|
@@ -11,8 +8,8 @@ var MouseContext_js_1 = require("../contexts/MouseContext.js");
|
|
|
11
8
|
* @returns The mouse context value containing `subscribe` and `unsubscribe` methods.
|
|
12
9
|
* @throws Error if used outside of a `MouseProvider`.
|
|
13
10
|
*/
|
|
14
|
-
function useMouseContext() {
|
|
15
|
-
|
|
11
|
+
export function useMouseContext() {
|
|
12
|
+
const context = useContext(MouseContext);
|
|
16
13
|
if (!context) {
|
|
17
14
|
throw new Error("useMouseContext must be used within a MouseProvider");
|
|
18
15
|
}
|
package/lib/hooks/use-mouse.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.useMouse = useMouse;
|
|
4
|
-
var react_1 = require("react");
|
|
5
|
-
var use_mouse_context_js_1 = require("./use-mouse-context.js");
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useMouseContext } from "./use-mouse-context.js";
|
|
6
3
|
/**
|
|
7
4
|
* Hook to subscribe to mouse events.
|
|
8
5
|
*
|
|
@@ -19,14 +16,13 @@ var use_mouse_context_js_1 = require("./use-mouse-context.js");
|
|
|
19
16
|
* });
|
|
20
17
|
* ```
|
|
21
18
|
*/
|
|
22
|
-
function useMouse(handler,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(0, react_1.useEffect)(function () {
|
|
19
|
+
export function useMouse(handler, { isActive = true } = {}) {
|
|
20
|
+
const { subscribe, unsubscribe } = useMouseContext();
|
|
21
|
+
useEffect(() => {
|
|
26
22
|
if (!isActive) {
|
|
27
23
|
return;
|
|
28
24
|
}
|
|
29
25
|
subscribe(handler);
|
|
30
|
-
return
|
|
26
|
+
return () => unsubscribe(handler);
|
|
31
27
|
}, [isActive, handler, subscribe, unsubscribe]);
|
|
32
28
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { MouseProvider, enableMouseEvents, disableMouseEvents, type MouseEvent, type MouseEventName, type MouseHandler, type MouseContextValue, } from "./contexts/MouseContext.js";
|
|
1
|
+
export { MouseProvider, enableMouseEvents, disableMouseEvents, type MouseEvent, type MouseEventName, type MouseHandler, type MouseContextValue, type MouseProviderProps, } from "./contexts/MouseContext.js";
|
|
2
2
|
export { useMouseContext } from "./hooks/use-mouse-context.js";
|
|
3
3
|
export { useMouse } from "./hooks/use-mouse.js";
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var MouseContext_js_1 = require("./contexts/MouseContext.js");
|
|
5
|
-
Object.defineProperty(exports, "MouseProvider", { enumerable: true, get: function () { return MouseContext_js_1.MouseProvider; } });
|
|
6
|
-
Object.defineProperty(exports, "enableMouseEvents", { enumerable: true, get: function () { return MouseContext_js_1.enableMouseEvents; } });
|
|
7
|
-
Object.defineProperty(exports, "disableMouseEvents", { enumerable: true, get: function () { return MouseContext_js_1.disableMouseEvents; } });
|
|
8
|
-
var use_mouse_context_js_1 = require("./hooks/use-mouse-context.js");
|
|
9
|
-
Object.defineProperty(exports, "useMouseContext", { enumerable: true, get: function () { return use_mouse_context_js_1.useMouseContext; } });
|
|
10
|
-
var use_mouse_js_1 = require("./hooks/use-mouse.js");
|
|
11
|
-
Object.defineProperty(exports, "useMouse", { enumerable: true, get: function () { return use_mouse_js_1.useMouse; } });
|
|
1
|
+
export { MouseProvider, enableMouseEvents, disableMouseEvents, } from "./contexts/MouseContext.js";
|
|
2
|
+
export { useMouseContext } from "./hooks/use-mouse-context.js";
|
|
3
|
+
export { useMouse } from "./hooks/use-mouse.js";
|
package/lib/utils/mouse.js
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getMouseEventName = getMouseEventName;
|
|
4
|
-
exports.parseSGRMouseEvent = parseSGRMouseEvent;
|
|
5
|
-
exports.parseX11MouseEvent = parseX11MouseEvent;
|
|
6
|
-
exports.parseMouseEvent = parseMouseEvent;
|
|
7
|
-
exports.isIncompleteMouseSequence = isIncompleteMouseSequence;
|
|
8
|
-
var sequences_js_1 = require("./sequences.js");
|
|
1
|
+
import { SGR_MOUSE_REGEX, X11_MOUSE_REGEX, SGR_EVENT_PREFIX, X11_EVENT_PREFIX, couldBeMouseSequence, } from "./sequences.js";
|
|
9
2
|
/**
|
|
10
3
|
* Derives the `MouseEventName` from the SGR button code and release state.
|
|
11
4
|
*
|
|
@@ -13,8 +6,8 @@ var sequences_js_1 = require("./sequences.js");
|
|
|
13
6
|
* @param isRelease - Whether the event is a release event (last char is 'm').
|
|
14
7
|
* @returns The `MouseEventName` or `null` if unknown.
|
|
15
8
|
*/
|
|
16
|
-
function getMouseEventName(buttonCode, isRelease) {
|
|
17
|
-
|
|
9
|
+
export function getMouseEventName(buttonCode, isRelease) {
|
|
10
|
+
const isMove = (buttonCode & 32) !== 0;
|
|
18
11
|
if (buttonCode === 66) {
|
|
19
12
|
return "scroll-left";
|
|
20
13
|
}
|
|
@@ -33,22 +26,22 @@ function getMouseEventName(buttonCode, isRelease) {
|
|
|
33
26
|
return "move";
|
|
34
27
|
}
|
|
35
28
|
else {
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
const button = buttonCode & 3;
|
|
30
|
+
const type = isRelease ? "release" : "press";
|
|
38
31
|
switch (button) {
|
|
39
32
|
case 0:
|
|
40
|
-
return
|
|
33
|
+
return `left-${type}`;
|
|
41
34
|
case 1:
|
|
42
|
-
return
|
|
35
|
+
return `middle-${type}`;
|
|
43
36
|
case 2:
|
|
44
|
-
return
|
|
37
|
+
return `right-${type}`;
|
|
45
38
|
default:
|
|
46
39
|
return null;
|
|
47
40
|
}
|
|
48
41
|
}
|
|
49
42
|
}
|
|
50
43
|
function getButtonFromCode(code) {
|
|
51
|
-
|
|
44
|
+
const button = code & 3;
|
|
52
45
|
switch (button) {
|
|
53
46
|
case 0:
|
|
54
47
|
return "left";
|
|
@@ -71,27 +64,27 @@ function getButtonFromCode(code) {
|
|
|
71
64
|
* parseSGRMouseEvent("\x1b[<0;10;10M"); // Left press at 10,10
|
|
72
65
|
* ```
|
|
73
66
|
*/
|
|
74
|
-
function parseSGRMouseEvent(buffer) {
|
|
75
|
-
|
|
67
|
+
export function parseSGRMouseEvent(buffer) {
|
|
68
|
+
const match = buffer.match(SGR_MOUSE_REGEX);
|
|
76
69
|
if (match) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (
|
|
70
|
+
const buttonCode = parseInt(match[1], 10);
|
|
71
|
+
const col = parseInt(match[2], 10);
|
|
72
|
+
const row = parseInt(match[3], 10);
|
|
73
|
+
const action = match[4];
|
|
74
|
+
const isRelease = action === "m";
|
|
75
|
+
const shift = (buttonCode & 4) !== 0;
|
|
76
|
+
const meta = (buttonCode & 8) !== 0;
|
|
77
|
+
const ctrl = (buttonCode & 16) !== 0;
|
|
78
|
+
const name = getMouseEventName(buttonCode, isRelease);
|
|
79
|
+
if (name) {
|
|
87
80
|
return {
|
|
88
81
|
event: {
|
|
89
|
-
name
|
|
90
|
-
ctrl
|
|
91
|
-
meta
|
|
92
|
-
shift
|
|
93
|
-
col
|
|
94
|
-
row
|
|
82
|
+
name,
|
|
83
|
+
ctrl,
|
|
84
|
+
meta,
|
|
85
|
+
shift,
|
|
86
|
+
col,
|
|
87
|
+
row,
|
|
95
88
|
button: getButtonFromCode(buttonCode),
|
|
96
89
|
},
|
|
97
90
|
length: match[0].length,
|
|
@@ -112,22 +105,22 @@ function parseSGRMouseEvent(buffer) {
|
|
|
112
105
|
* parseX11MouseEvent("\x1b[M..."); // Parsed X11 event
|
|
113
106
|
* ```
|
|
114
107
|
*/
|
|
115
|
-
function parseX11MouseEvent(buffer) {
|
|
116
|
-
|
|
108
|
+
export function parseX11MouseEvent(buffer) {
|
|
109
|
+
const match = buffer.match(X11_MOUSE_REGEX);
|
|
117
110
|
if (!match)
|
|
118
111
|
return null;
|
|
119
112
|
// The 3 bytes are in match[1]
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
const b = match[1].charCodeAt(0) - 32;
|
|
114
|
+
const col = match[1].charCodeAt(1) - 32;
|
|
115
|
+
const row = match[1].charCodeAt(2) - 32;
|
|
116
|
+
const shift = (b & 4) !== 0;
|
|
117
|
+
const meta = (b & 8) !== 0;
|
|
118
|
+
const ctrl = (b & 16) !== 0;
|
|
119
|
+
const isMove = (b & 32) !== 0;
|
|
120
|
+
const isWheel = (b & 64) !== 0;
|
|
121
|
+
let name = null;
|
|
129
122
|
if (isWheel) {
|
|
130
|
-
|
|
123
|
+
const button = b & 3;
|
|
131
124
|
switch (button) {
|
|
132
125
|
case 0:
|
|
133
126
|
name = "scroll-up";
|
|
@@ -143,7 +136,7 @@ function parseX11MouseEvent(buffer) {
|
|
|
143
136
|
name = "move";
|
|
144
137
|
}
|
|
145
138
|
else {
|
|
146
|
-
|
|
139
|
+
const button = b & 3;
|
|
147
140
|
if (button === 3) {
|
|
148
141
|
// X11 reports 'release' (3) for all button releases without specifying which one.
|
|
149
142
|
// We'll default to 'left-release' as a best-effort guess if we don't track state.
|
|
@@ -166,19 +159,19 @@ function parseX11MouseEvent(buffer) {
|
|
|
166
159
|
}
|
|
167
160
|
}
|
|
168
161
|
if (name) {
|
|
169
|
-
|
|
162
|
+
let button = getButtonFromCode(b);
|
|
170
163
|
if (name === "left-release" && button === "none") {
|
|
171
164
|
button = "left";
|
|
172
165
|
}
|
|
173
166
|
return {
|
|
174
167
|
event: {
|
|
175
|
-
name
|
|
176
|
-
ctrl
|
|
177
|
-
meta
|
|
178
|
-
shift
|
|
179
|
-
col
|
|
180
|
-
row
|
|
181
|
-
button
|
|
168
|
+
name,
|
|
169
|
+
ctrl,
|
|
170
|
+
meta,
|
|
171
|
+
shift,
|
|
172
|
+
col,
|
|
173
|
+
row,
|
|
174
|
+
button,
|
|
182
175
|
},
|
|
183
176
|
length: match[0].length,
|
|
184
177
|
};
|
|
@@ -191,7 +184,7 @@ function parseX11MouseEvent(buffer) {
|
|
|
191
184
|
* @param buffer - The input string.
|
|
192
185
|
* @returns The parsed event and length, or `null`.
|
|
193
186
|
*/
|
|
194
|
-
function parseMouseEvent(buffer) {
|
|
187
|
+
export function parseMouseEvent(buffer) {
|
|
195
188
|
return parseSGRMouseEvent(buffer) || parseX11MouseEvent(buffer);
|
|
196
189
|
}
|
|
197
190
|
/**
|
|
@@ -201,17 +194,17 @@ function parseMouseEvent(buffer) {
|
|
|
201
194
|
* @param buffer - The input string.
|
|
202
195
|
* @returns `true` if the buffer looks like the start of a mouse sequence but is incomplete.
|
|
203
196
|
*/
|
|
204
|
-
function isIncompleteMouseSequence(buffer) {
|
|
205
|
-
if (!
|
|
197
|
+
export function isIncompleteMouseSequence(buffer) {
|
|
198
|
+
if (!couldBeMouseSequence(buffer))
|
|
206
199
|
return false;
|
|
207
200
|
// If it matches a complete sequence, it's not incomplete.
|
|
208
201
|
if (parseMouseEvent(buffer))
|
|
209
202
|
return false;
|
|
210
|
-
if (buffer.startsWith(
|
|
203
|
+
if (buffer.startsWith(X11_EVENT_PREFIX)) {
|
|
211
204
|
// X11 needs exactly 3 bytes after prefix.
|
|
212
|
-
return buffer.length <
|
|
205
|
+
return buffer.length < X11_EVENT_PREFIX.length + 3;
|
|
213
206
|
}
|
|
214
|
-
if (buffer.startsWith(
|
|
207
|
+
if (buffer.startsWith(SGR_EVENT_PREFIX)) {
|
|
215
208
|
// SGR sequences end with 'm' or 'M'.
|
|
216
209
|
// If it doesn't have it yet, it's incomplete.
|
|
217
210
|
// Add a reasonable max length check to fail early on garbage.
|
package/lib/utils/sequences.js
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.X11_MOUSE_REGEX = exports.SGR_MOUSE_REGEX = exports.X11_EVENT_PREFIX = exports.SGR_EVENT_PREFIX = exports.ESC = void 0;
|
|
4
|
-
exports.couldBeSGRMouseSequence = couldBeSGRMouseSequence;
|
|
5
|
-
exports.couldBeMouseSequence = couldBeMouseSequence;
|
|
6
|
-
exports.getMouseSequenceLength = getMouseSequenceLength;
|
|
7
1
|
/* eslint-disable no-control-regex */
|
|
8
2
|
/** ESC character (ASCII 27). */
|
|
9
|
-
|
|
3
|
+
export const ESC = "\u001B";
|
|
10
4
|
/** Prefix for SGR (1006) mouse sequences. */
|
|
11
|
-
|
|
5
|
+
export const SGR_EVENT_PREFIX = `${ESC}[<`;
|
|
12
6
|
/** Prefix for X11 mouse sequences. */
|
|
13
|
-
|
|
7
|
+
export const X11_EVENT_PREFIX = `${ESC}[M`;
|
|
14
8
|
/** Regex to match a complete SGR mouse event sequence. */
|
|
15
|
-
|
|
9
|
+
export const SGR_MOUSE_REGEX = /^\x1b\[<(\d+);(\d+);(\d+)([mM])/; // SGR mouse events
|
|
16
10
|
// X11 is ESC [ M followed by 3 bytes.
|
|
17
11
|
/** Regex to match a complete X11 mouse event sequence. */
|
|
18
|
-
|
|
12
|
+
export const X11_MOUSE_REGEX = /^\x1b\[M([\s\S]{3})/;
|
|
19
13
|
/**
|
|
20
14
|
* Checks if the buffer starts with or is a prefix of an SGR mouse sequence.
|
|
21
15
|
*
|
|
@@ -29,14 +23,14 @@ exports.X11_MOUSE_REGEX = /^\x1b\[M([\s\S]{3})/;
|
|
|
29
23
|
* couldBeSGRMouseSequence("hello"); // false
|
|
30
24
|
* ```
|
|
31
25
|
*/
|
|
32
|
-
function couldBeSGRMouseSequence(buffer) {
|
|
26
|
+
export function couldBeSGRMouseSequence(buffer) {
|
|
33
27
|
if (buffer.length === 0)
|
|
34
28
|
return true;
|
|
35
29
|
// Check if buffer is a prefix of a mouse sequence starter
|
|
36
|
-
if (
|
|
30
|
+
if (SGR_EVENT_PREFIX.startsWith(buffer))
|
|
37
31
|
return true;
|
|
38
32
|
// Check if buffer is a mouse sequence prefix
|
|
39
|
-
if (buffer.startsWith(
|
|
33
|
+
if (buffer.startsWith(SGR_EVENT_PREFIX))
|
|
40
34
|
return true;
|
|
41
35
|
return false;
|
|
42
36
|
}
|
|
@@ -52,16 +46,16 @@ function couldBeSGRMouseSequence(buffer) {
|
|
|
52
46
|
* couldBeMouseSequence("\x1b[<"); // true
|
|
53
47
|
* ```
|
|
54
48
|
*/
|
|
55
|
-
function couldBeMouseSequence(buffer) {
|
|
49
|
+
export function couldBeMouseSequence(buffer) {
|
|
56
50
|
if (buffer.length === 0)
|
|
57
51
|
return true;
|
|
58
52
|
// Check SGR prefix
|
|
59
|
-
if (
|
|
60
|
-
buffer.startsWith(
|
|
53
|
+
if (SGR_EVENT_PREFIX.startsWith(buffer) ||
|
|
54
|
+
buffer.startsWith(SGR_EVENT_PREFIX))
|
|
61
55
|
return true;
|
|
62
56
|
// Check X11 prefix
|
|
63
|
-
if (
|
|
64
|
-
buffer.startsWith(
|
|
57
|
+
if (X11_EVENT_PREFIX.startsWith(buffer) ||
|
|
58
|
+
buffer.startsWith(X11_EVENT_PREFIX))
|
|
65
59
|
return true;
|
|
66
60
|
return false;
|
|
67
61
|
}
|
|
@@ -79,11 +73,11 @@ function couldBeMouseSequence(buffer) {
|
|
|
79
73
|
* getMouseSequenceLength("not mouse"); // 0
|
|
80
74
|
* ```
|
|
81
75
|
*/
|
|
82
|
-
function getMouseSequenceLength(buffer) {
|
|
83
|
-
|
|
76
|
+
export function getMouseSequenceLength(buffer) {
|
|
77
|
+
const sgrMatch = buffer.match(SGR_MOUSE_REGEX);
|
|
84
78
|
if (sgrMatch)
|
|
85
79
|
return sgrMatch[0].length;
|
|
86
|
-
|
|
80
|
+
const x11Match = buffer.match(X11_MOUSE_REGEX);
|
|
87
81
|
if (x11Match)
|
|
88
82
|
return x11Match[0].length;
|
|
89
83
|
return 0;
|
package/package.json
CHANGED
package/lib/hooks/useMouse.d.ts
DELETED
package/lib/hooks/useMouse.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useMouse = useMouse;
|
|
4
|
-
var react_1 = require("react");
|
|
5
|
-
var useMouseContext_js_1 = require("./useMouseContext.js");
|
|
6
|
-
function useMouse(handler, _a) {
|
|
7
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.isActive, isActive = _c === void 0 ? true : _c;
|
|
8
|
-
var _d = (0, useMouseContext_js_1.useMouseContext)(), subscribe = _d.subscribe, unsubscribe = _d.unsubscribe;
|
|
9
|
-
(0, react_1.useEffect)(function () {
|
|
10
|
-
if (!isActive) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
subscribe(handler);
|
|
14
|
-
return function () { return unsubscribe(handler); };
|
|
15
|
-
}, [isActive, handler, subscribe, unsubscribe]);
|
|
16
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function useMouseContext(): import("../contexts/MouseContext.js").MouseContextValue;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useMouseContext = useMouseContext;
|
|
4
|
-
var react_1 = require("react");
|
|
5
|
-
var MouseContext_js_1 = require("../contexts/MouseContext.js");
|
|
6
|
-
function useMouseContext() {
|
|
7
|
-
var context = (0, react_1.useContext)(MouseContext_js_1.MouseContext);
|
|
8
|
-
if (!context) {
|
|
9
|
-
throw new Error("useMouseContext must be used within a MouseProvider");
|
|
10
|
-
}
|
|
11
|
-
return context;
|
|
12
|
-
}
|
package/lib/utils/events.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from "node:events";
|
|
2
|
-
export declare enum AppEvent {
|
|
3
|
-
OpenDebugConsole = "open-debug-console",
|
|
4
|
-
OauthDisplayMessage = "oauth-display-message",
|
|
5
|
-
Flicker = "flicker",
|
|
6
|
-
McpClientUpdate = "mcp-client-update",
|
|
7
|
-
SelectionWarning = "selection-warning",
|
|
8
|
-
PasteTimeout = "paste-timeout"
|
|
9
|
-
}
|
|
10
|
-
export interface AppEvents {
|
|
11
|
-
[AppEvent.OpenDebugConsole]: never[];
|
|
12
|
-
[AppEvent.OauthDisplayMessage]: string[];
|
|
13
|
-
[AppEvent.Flicker]: never[];
|
|
14
|
-
[AppEvent.SelectionWarning]: never[];
|
|
15
|
-
[AppEvent.PasteTimeout]: never[];
|
|
16
|
-
}
|
|
17
|
-
export declare const appEvents: EventEmitter<AppEvents>;
|
package/lib/utils/events.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.appEvents = exports.AppEvent = void 0;
|
|
4
|
-
var node_events_1 = require("node:events");
|
|
5
|
-
var AppEvent;
|
|
6
|
-
(function (AppEvent) {
|
|
7
|
-
AppEvent["OpenDebugConsole"] = "open-debug-console";
|
|
8
|
-
AppEvent["OauthDisplayMessage"] = "oauth-display-message";
|
|
9
|
-
AppEvent["Flicker"] = "flicker";
|
|
10
|
-
AppEvent["McpClientUpdate"] = "mcp-client-update";
|
|
11
|
-
AppEvent["SelectionWarning"] = "selection-warning";
|
|
12
|
-
AppEvent["PasteTimeout"] = "paste-timeout";
|
|
13
|
-
})(AppEvent || (exports.AppEvent = AppEvent = {}));
|
|
14
|
-
exports.appEvents = new node_events_1.EventEmitter();
|
package/lib/utils/input.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare const ESC = "\u001B";
|
|
2
|
-
export declare const SGR_EVENT_PREFIX = "\u001B[<";
|
|
3
|
-
export declare const X11_EVENT_PREFIX = "\u001B[M";
|
|
4
|
-
export declare const SGR_MOUSE_REGEX: RegExp;
|
|
5
|
-
export declare const X11_MOUSE_REGEX: RegExp;
|
|
6
|
-
export declare function couldBeSGRMouseSequence(buffer: string): boolean;
|
|
7
|
-
export declare function couldBeMouseSequence(buffer: string): boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Checks if the buffer *starts* with a complete mouse sequence.
|
|
10
|
-
* Returns the length of the sequence if matched, or 0 if not.
|
|
11
|
-
*/
|
|
12
|
-
export declare function getMouseSequenceLength(buffer: string): number;
|
package/lib/utils/input.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.X11_MOUSE_REGEX = exports.SGR_MOUSE_REGEX = exports.X11_EVENT_PREFIX = exports.SGR_EVENT_PREFIX = exports.ESC = void 0;
|
|
4
|
-
exports.couldBeSGRMouseSequence = couldBeSGRMouseSequence;
|
|
5
|
-
exports.couldBeMouseSequence = couldBeMouseSequence;
|
|
6
|
-
exports.getMouseSequenceLength = getMouseSequenceLength;
|
|
7
|
-
exports.ESC = "\u001B";
|
|
8
|
-
exports.SGR_EVENT_PREFIX = "".concat(exports.ESC, "[<");
|
|
9
|
-
exports.X11_EVENT_PREFIX = "".concat(exports.ESC, "[M");
|
|
10
|
-
// eslint-disable-next-line no-control-regex
|
|
11
|
-
exports.SGR_MOUSE_REGEX = /^\x1b\[<(\d+);(\d+);(\d+)([mM])/; // SGR mouse events
|
|
12
|
-
// X11 is ESC [ M followed by 3 bytes.
|
|
13
|
-
// eslint-disable-next-line no-control-regex
|
|
14
|
-
exports.X11_MOUSE_REGEX = /^\x1b\[M([\s\S]{3})/;
|
|
15
|
-
function couldBeSGRMouseSequence(buffer) {
|
|
16
|
-
if (buffer.length === 0)
|
|
17
|
-
return true;
|
|
18
|
-
// Check if buffer is a prefix of a mouse sequence starter
|
|
19
|
-
if (exports.SGR_EVENT_PREFIX.startsWith(buffer))
|
|
20
|
-
return true;
|
|
21
|
-
// Check if buffer is a mouse sequence prefix
|
|
22
|
-
if (buffer.startsWith(exports.SGR_EVENT_PREFIX))
|
|
23
|
-
return true;
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
function couldBeMouseSequence(buffer) {
|
|
27
|
-
if (buffer.length === 0)
|
|
28
|
-
return true;
|
|
29
|
-
// Check SGR prefix
|
|
30
|
-
if (exports.SGR_EVENT_PREFIX.startsWith(buffer) ||
|
|
31
|
-
buffer.startsWith(exports.SGR_EVENT_PREFIX))
|
|
32
|
-
return true;
|
|
33
|
-
// Check X11 prefix
|
|
34
|
-
if (exports.X11_EVENT_PREFIX.startsWith(buffer) ||
|
|
35
|
-
buffer.startsWith(exports.X11_EVENT_PREFIX))
|
|
36
|
-
return true;
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Checks if the buffer *starts* with a complete mouse sequence.
|
|
41
|
-
* Returns the length of the sequence if matched, or 0 if not.
|
|
42
|
-
*/
|
|
43
|
-
function getMouseSequenceLength(buffer) {
|
|
44
|
-
var sgrMatch = buffer.match(exports.SGR_MOUSE_REGEX);
|
|
45
|
-
if (sgrMatch)
|
|
46
|
-
return sgrMatch[0].length;
|
|
47
|
-
var x11Match = buffer.match(exports.X11_MOUSE_REGEX);
|
|
48
|
-
if (x11Match)
|
|
49
|
-
return x11Match[0].length;
|
|
50
|
-
return 0;
|
|
51
|
-
}
|