@gd-kirie/ipc 0.1.1 → 0.2.0
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/README.md +59 -10
- package/dist/index.d.ts +49 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +164 -19
- package/dist/index.js.map +1 -1
- package/dist/pointer-input/auto.d.ts +1 -0
- package/dist/pointer-input/auto.js +11 -0
- package/dist/pointer-input/auto.js.map +1 -0
- package/dist/pointer-input/index.d.ts +14 -0
- package/dist/pointer-input/index.d.ts.map +1 -0
- package/dist/pointer-input/index.js +105 -0
- package/dist/pointer-input/index.js.map +1 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -8,24 +8,73 @@ level bridge on `globalThis`, and this package only wraps that bridge with a sma
|
|
|
8
8
|
## API
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
import {
|
|
11
|
+
import { onTextReceived, sendText } from "@gd-kirie/ipc";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
sendText(JSON.stringify({
|
|
14
14
|
type: "web_ready",
|
|
15
|
-
});
|
|
15
|
+
}));
|
|
16
16
|
|
|
17
|
-
const unsubscribe =
|
|
17
|
+
const unsubscribe = onTextReceived((message) => {
|
|
18
18
|
console.log(message);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
unsubscribe();
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
The package selects the native transport from `window.kirie.platform`, which is
|
|
25
|
+
injected by Kirie before page scripts run.
|
|
26
|
+
|
|
27
|
+
Android exposes three channels backed by CBOR packets and AndroidX WebKit
|
|
28
|
+
ArrayBuffer messages. iOS exposes the same lane API over WKWebView script
|
|
29
|
+
messages, carrying each CBOR packet as base64 inside the platform string
|
|
30
|
+
message:
|
|
31
|
+
|
|
32
|
+
- `sendText()` / `onTextReceived()` for CBOR text strings
|
|
33
|
+
- `sendBinary()` / `onBinaryReceived()` for CBOR byte strings
|
|
34
|
+
- `sendData()` / `onDataReceived()` for CBOR-encoded structured data through `cborg`
|
|
35
|
+
|
|
36
|
+
The structured data subset is limited to `null`, booleans, numbers, strings,
|
|
37
|
+
arrays, and objects with string keys. JSON message shapes are a caller or
|
|
38
|
+
adapter convention and should be sent with `sendText()` when needed.
|
|
39
|
+
|
|
40
|
+
## Pointer input forwarding
|
|
41
|
+
|
|
42
|
+
> [!IMPORTANT]
|
|
43
|
+
> Kirie WebViews normally fill their native host above Godot. CSS transparency
|
|
44
|
+
> does not pass native hit tests through to Godot, so visible Godot controls
|
|
45
|
+
> behind the WebView cannot be clicked without pointer forwarding. Most Kirie
|
|
46
|
+
> pages should import `@gd-kirie/ipc/pointer-input/auto`.
|
|
47
|
+
|
|
48
|
+
Enable both sides; the browser entry registers on import:
|
|
49
|
+
|
|
50
|
+
```gdscript
|
|
51
|
+
$KirieNode.pointer_input_forwarding_enabled = true
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import "@gd-kirie/ipc/pointer-input/auto";
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Custom event orchestration
|
|
59
|
+
|
|
60
|
+
For custom targets or lifetimes, use the explicit entry instead:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import {
|
|
64
|
+
createPointerEventsHandler,
|
|
65
|
+
phaseFromPointerEvent,
|
|
66
|
+
sendPointerEvent,
|
|
67
|
+
} from "@gd-kirie/ipc/pointer-input";
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`createPointerEventsHandler()` returns `capture`, `bubble`, and `cancel` handlers;
|
|
71
|
+
the caller owns their registration and removal.
|
|
26
72
|
|
|
27
|
-
|
|
28
|
-
|
|
73
|
+
`pointerdown` bubbling decides ownership: `event.stopPropagation()` keeps the
|
|
74
|
+
sequence in the WebView; otherwise its move, up, and cancel events are forwarded
|
|
75
|
+
to Godot.
|
|
29
76
|
|
|
30
|
-
|
|
31
|
-
|
|
77
|
+
Forwarding uses Godot's
|
|
78
|
+
[`Input.parse_input_event()`](https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-parse-input-event)
|
|
79
|
+
API; forwarded mouse and touch events retain their destination
|
|
80
|
+
[`window_id`](https://docs.godotengine.org/en/stable/classes/class_inputeventfromwindow.html#class-inputeventfromwindow-property-window-id).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,54 @@
|
|
|
1
1
|
//#region src/index.d.ts
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
2
|
+
type KiriePlatformOs = "android" | "ios" | "macos" | "windows" | "linux";
|
|
3
|
+
type KiriePlatformBackend = "webview" | "wkwebview" | "godot-cef";
|
|
4
|
+
interface KiriePlatform {
|
|
5
|
+
os: KiriePlatformOs;
|
|
6
|
+
backend: KiriePlatformBackend;
|
|
7
|
+
}
|
|
8
|
+
interface KirieRuntime {
|
|
9
|
+
platform: KiriePlatform;
|
|
10
|
+
}
|
|
11
|
+
interface KirieAndroidChannel {
|
|
12
|
+
postMessage(message: ArrayBuffer): void;
|
|
13
|
+
onmessage: ((event: MessageEvent) => void) | null;
|
|
14
|
+
}
|
|
15
|
+
interface KirieIosMessageHandler {
|
|
16
|
+
postMessage(message: string): void;
|
|
17
|
+
}
|
|
18
|
+
interface KirieIosWebkit {
|
|
19
|
+
messageHandlers?: {
|
|
20
|
+
kirie?: KirieIosMessageHandler;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
8
23
|
declare global {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
interface Window {
|
|
25
|
+
kirie?: KirieRuntime;
|
|
26
|
+
KirieTextChannel?: KirieAndroidChannel;
|
|
27
|
+
KirieBinaryChannel?: KirieAndroidChannel;
|
|
28
|
+
KirieDataChannel?: KirieAndroidChannel;
|
|
29
|
+
webkit?: KirieIosWebkit;
|
|
30
|
+
sendIpcMessage(message: string): void;
|
|
31
|
+
sendIpcBinaryMessage(message: ArrayBuffer): void;
|
|
32
|
+
sendIpcData(message: KirieData): void;
|
|
33
|
+
onIpcMessage?: KirieMessageHandler<string>;
|
|
34
|
+
onIpcBinaryMessage?: KirieMessageHandler<ArrayBuffer>;
|
|
35
|
+
onIpcDataMessage?: KirieMessageHandler<KirieData>;
|
|
36
|
+
}
|
|
15
37
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Structured data lane subset shared with Godot Variant data.
|
|
40
|
+
* It intentionally excludes engine-local and JavaScript-local object types.
|
|
41
|
+
*/
|
|
42
|
+
type KirieData = null | boolean | number | string | KirieData[] | {
|
|
43
|
+
[key: string]: KirieData;
|
|
44
|
+
};
|
|
45
|
+
type KirieMessageHandler<TMessage> = (message: TMessage) => void;
|
|
46
|
+
declare function sendText(message: string): void;
|
|
47
|
+
declare function sendBinary(bytes: Uint8Array): void;
|
|
48
|
+
declare function sendData(value: KirieData): void;
|
|
49
|
+
declare function onTextReceived(handler: KirieMessageHandler<string>): () => void;
|
|
50
|
+
declare function onBinaryReceived(handler: KirieMessageHandler<Uint8Array>): () => void;
|
|
51
|
+
declare function onDataReceived(handler: KirieMessageHandler<KirieData>): () => void;
|
|
19
52
|
//#endregion
|
|
20
|
-
export {
|
|
53
|
+
export { KirieData, KirieMessageHandler, KiriePlatform, KiriePlatformBackend, KiriePlatformOs, KirieRuntime, onBinaryReceived, onDataReceived, onTextReceived, sendBinary, sendData, sendText };
|
|
21
54
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";KAKY,eAAA;AAAA,KACA,oBAAA;AAAA,UAEK,aAAA;EACf,EAAA,EAAI,eAAA;EACJ,OAAA,EAAS,oBAAA;AAAA;AAAA,UAGM,YAAA;EACf,QAAA,EAAU,aAAA;AAAA;AAAA,UAGF,mBAAA;EACR,WAAA,CAAY,OAAA,EAAS,WAAA;EACrB,SAAA,IAAa,KAAA,EAAO,YAAA;AAAA;AAAA,UAGZ,sBAAA;EACR,WAAA,CAAY,OAAA;AAAA;AAAA,UAUJ,cAAA;EACR,eAAA;IACE,KAAA,GAAQ,sBAAA;EAAA;AAAA;AAAA;YAKA,MAAA;IACR,KAAA,GAAQ,YAAA;IACR,gBAAA,GAAmB,mBAAA;IACnB,kBAAA,GAAqB,mBAAA;IACrB,gBAAA,GAAmB,mBAAA;IACnB,MAAA,GAAS,cAAA;IACT,cAAA,CAAe,OAAA;IACf,oBAAA,CAAqB,OAAA,EAAS,WAAA;IAC9B,WAAA,CAAY,OAAA,EAAS,SAAA;IACrB,YAAA,GAAe,mBAAA;IACf,kBAAA,GAAqB,mBAAA,CAAoB,WAAA;IACzC,gBAAA,GAAmB,mBAAA,CAAoB,SAAA;EAAA;AAAA;;AAhCrB;AAAA;;KAwCV,SAAA,sCAKR,SAAA;EAAA,eACiB,SAAA;AAAA;AAAA,KAET,mBAAA,cAAiC,OAAA,EAAS,QAAA;AAAA,iBAqRtC,QAAA,CAAS,OAAA;AAAA,iBAIT,UAAA,CAAW,KAAO,EAAA,UAAA;AAAA,iBAIlB,QAAA,CAAS,KAAO,EAAA,SAAA;AAAA,iBAIhB,cAAA,CAAe,OAAS,EAAA,mBAAA;AAAA,iBAIxB,gBAAA,CAAiB,OAAA,EAAS,mBAAA,CAAoB,UAAA;AAAA,iBAI9C,cAAA,CAAe,OAAA,EAAS,mBAAA,CAAoB,SAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,175 @@
|
|
|
1
|
+
import { decode, encode } from "cborg";
|
|
1
2
|
//#region src/index.ts
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
const READY_MESSAGE = /* @__PURE__ */ new ArrayBuffer(0);
|
|
4
|
+
const ENCODE_OPTIONS = { float64: true };
|
|
5
|
+
function asArrayBuffer(bytes) {
|
|
6
|
+
if (bytes.buffer instanceof ArrayBuffer && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength) return bytes.buffer;
|
|
7
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
8
|
+
copy.set(bytes);
|
|
9
|
+
return copy.buffer;
|
|
10
|
+
}
|
|
11
|
+
function asUint8Array(value) {
|
|
12
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
13
|
+
throw new TypeError("Kirie message must be an ArrayBuffer.");
|
|
14
|
+
}
|
|
15
|
+
function decodeText(value) {
|
|
16
|
+
const decoded = decode(asUint8Array(value));
|
|
17
|
+
if (typeof decoded !== "string") throw new TypeError("Kirie text message must decode to a string.");
|
|
18
|
+
return decoded;
|
|
19
|
+
}
|
|
20
|
+
function decodeBinary(value) {
|
|
21
|
+
const decoded = decode(asUint8Array(value));
|
|
22
|
+
if (decoded instanceof Uint8Array) return decoded;
|
|
23
|
+
throw new TypeError("Kirie binary message must decode to bytes.");
|
|
24
|
+
}
|
|
25
|
+
function currentTransport() {
|
|
26
|
+
const platform = window.kirie?.platform;
|
|
27
|
+
return transports[`${platform?.os}/${platform?.backend}`];
|
|
28
|
+
}
|
|
29
|
+
function listenAndroid(channel, read, handler) {
|
|
30
|
+
const listener = (event) => {
|
|
31
|
+
handler(read(event.data));
|
|
32
|
+
};
|
|
33
|
+
channel.onmessage = listener;
|
|
34
|
+
channel.postMessage(READY_MESSAGE);
|
|
35
|
+
return () => {
|
|
36
|
+
if (channel.onmessage === listener) channel.onmessage = null;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function requireAndroidChannel(name) {
|
|
40
|
+
const channel = window[name];
|
|
41
|
+
if (!channel) throw new Error(`Kirie Android channel is not available: ${name}`);
|
|
42
|
+
return channel;
|
|
43
|
+
}
|
|
44
|
+
const androidTransport = {
|
|
45
|
+
sendText(message) {
|
|
46
|
+
requireAndroidChannel("KirieTextChannel").postMessage(asArrayBuffer(encode(message, ENCODE_OPTIONS)));
|
|
47
|
+
},
|
|
48
|
+
sendBinary(bytes) {
|
|
49
|
+
requireAndroidChannel("KirieBinaryChannel").postMessage(asArrayBuffer(encode(bytes, ENCODE_OPTIONS)));
|
|
50
|
+
},
|
|
51
|
+
sendData(value) {
|
|
52
|
+
requireAndroidChannel("KirieDataChannel").postMessage(asArrayBuffer(encode(value, ENCODE_OPTIONS)));
|
|
53
|
+
},
|
|
54
|
+
onTextReceived(handler) {
|
|
55
|
+
return listenAndroid(requireAndroidChannel("KirieTextChannel"), decodeText, handler);
|
|
56
|
+
},
|
|
57
|
+
onBinaryReceived(handler) {
|
|
58
|
+
return listenAndroid(requireAndroidChannel("KirieBinaryChannel"), decodeBinary, handler);
|
|
59
|
+
},
|
|
60
|
+
onDataReceived(handler) {
|
|
61
|
+
return listenAndroid(requireAndroidChannel("KirieDataChannel"), (value) => decode(asUint8Array(value)), handler);
|
|
15
62
|
}
|
|
16
|
-
|
|
63
|
+
};
|
|
64
|
+
function requireIosMessageHandler() {
|
|
65
|
+
const handler = window.webkit?.messageHandlers?.kirie;
|
|
66
|
+
if (!handler) throw new Error("Kirie iOS message handler is not available: window.webkit.messageHandlers.kirie");
|
|
67
|
+
return handler;
|
|
68
|
+
}
|
|
69
|
+
function bytesToBase64(bytes) {
|
|
70
|
+
let binary = "";
|
|
71
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
72
|
+
return btoa(binary);
|
|
17
73
|
}
|
|
18
|
-
function
|
|
74
|
+
function base64ToArrayBuffer(encoded) {
|
|
75
|
+
const binary = atob(encoded);
|
|
76
|
+
const bytes = new Uint8Array(binary.length);
|
|
77
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
78
|
+
return bytes.buffer;
|
|
79
|
+
}
|
|
80
|
+
function postIosPacket(lane, packet) {
|
|
81
|
+
requireIosMessageHandler().postMessage(JSON.stringify({
|
|
82
|
+
lane,
|
|
83
|
+
packet: bytesToBase64(packet)
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
function listenIos(lane, read, handler) {
|
|
19
87
|
const listener = (event) => {
|
|
20
|
-
|
|
88
|
+
if (!(event instanceof CustomEvent) || !isIosPacketMessage(event.detail)) return;
|
|
89
|
+
if (event.detail.lane !== lane) return;
|
|
90
|
+
handler(read(base64ToArrayBuffer(event.detail.packet)));
|
|
21
91
|
};
|
|
22
|
-
|
|
92
|
+
window.addEventListener("kirie:ipc-packet", listener);
|
|
93
|
+
return () => window.removeEventListener("kirie:ipc-packet", listener);
|
|
94
|
+
}
|
|
95
|
+
function isIosPacketMessage(value) {
|
|
96
|
+
if (typeof value !== "object" || value === null) return false;
|
|
97
|
+
const message = value;
|
|
98
|
+
return (message.lane === "text" || message.lane === "binary" || message.lane === "data") && typeof message.packet === "string";
|
|
99
|
+
}
|
|
100
|
+
const iosTransport = {
|
|
101
|
+
sendText(message) {
|
|
102
|
+
postIosPacket("text", encode(message, ENCODE_OPTIONS));
|
|
103
|
+
},
|
|
104
|
+
sendBinary(bytes) {
|
|
105
|
+
postIosPacket("binary", encode(bytes, ENCODE_OPTIONS));
|
|
106
|
+
},
|
|
107
|
+
sendData(value) {
|
|
108
|
+
postIosPacket("data", encode(value, ENCODE_OPTIONS));
|
|
109
|
+
},
|
|
110
|
+
onTextReceived(handler) {
|
|
111
|
+
return listenIos("text", decodeText, handler);
|
|
112
|
+
},
|
|
113
|
+
onBinaryReceived(handler) {
|
|
114
|
+
return listenIos("binary", decodeBinary, handler);
|
|
115
|
+
},
|
|
116
|
+
onDataReceived(handler) {
|
|
117
|
+
return listenIos("data", (value) => decode(asUint8Array(value)), handler);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
function listenCefLegacy(name, handler) {
|
|
121
|
+
const callbacks = window;
|
|
122
|
+
callbacks[name] = handler;
|
|
23
123
|
return () => {
|
|
24
|
-
|
|
124
|
+
if (callbacks[name] === handler) callbacks[name] = void 0;
|
|
25
125
|
};
|
|
26
126
|
}
|
|
127
|
+
const cefTransport = {
|
|
128
|
+
sendText(message) {
|
|
129
|
+
window.sendIpcMessage(message);
|
|
130
|
+
},
|
|
131
|
+
sendBinary(bytes) {
|
|
132
|
+
window.sendIpcBinaryMessage(asArrayBuffer(bytes));
|
|
133
|
+
},
|
|
134
|
+
sendData(value) {
|
|
135
|
+
window.sendIpcData(value);
|
|
136
|
+
},
|
|
137
|
+
onTextReceived(handler) {
|
|
138
|
+
return listenCefLegacy("onIpcMessage", handler);
|
|
139
|
+
},
|
|
140
|
+
onBinaryReceived(handler) {
|
|
141
|
+
return listenCefLegacy("onIpcBinaryMessage", (value) => handler(new Uint8Array(value)));
|
|
142
|
+
},
|
|
143
|
+
onDataReceived(handler) {
|
|
144
|
+
return listenCefLegacy("onIpcDataMessage", handler);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const transports = {
|
|
148
|
+
"android/webview": androidTransport,
|
|
149
|
+
"ios/wkwebview": iosTransport,
|
|
150
|
+
"linux/godot-cef": cefTransport,
|
|
151
|
+
"macos/godot-cef": cefTransport,
|
|
152
|
+
"windows/godot-cef": cefTransport
|
|
153
|
+
};
|
|
154
|
+
function sendText(message) {
|
|
155
|
+
currentTransport().sendText(message);
|
|
156
|
+
}
|
|
157
|
+
function sendBinary(bytes) {
|
|
158
|
+
currentTransport().sendBinary(bytes);
|
|
159
|
+
}
|
|
160
|
+
function sendData(value) {
|
|
161
|
+
currentTransport().sendData(value);
|
|
162
|
+
}
|
|
163
|
+
function onTextReceived(handler) {
|
|
164
|
+
return currentTransport().onTextReceived(handler);
|
|
165
|
+
}
|
|
166
|
+
function onBinaryReceived(handler) {
|
|
167
|
+
return currentTransport().onBinaryReceived(handler);
|
|
168
|
+
}
|
|
169
|
+
function onDataReceived(handler) {
|
|
170
|
+
return currentTransport().onDataReceived(handler);
|
|
171
|
+
}
|
|
27
172
|
//#endregion
|
|
28
|
-
export {
|
|
173
|
+
export { onBinaryReceived, onDataReceived, onTextReceived, sendBinary, sendData, sendText };
|
|
29
174
|
|
|
30
175
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["const IPC_MESSAGE_EVENT = \"kirie:ipc-message\";\n\ntype AndroidBridge = {\n postMessage(messageJson: string): void;\n};\n\ntype IosBridge = {\n postMessage(messageJson: string): void;\n};\n\ndeclare global {\n var KirieAndroidBridge: AndroidBridge | undefined;\n\n var webkit:\n | {\n messageHandlers?: {\n kirie?: IosBridge;\n };\n }\n | undefined;\n}\n\nexport type KirieIpcMessageHandler<TMessage = unknown> = (message: TMessage) => void;\n\nexport function sendIpcMessage(message: unknown): void {\n const messageJson = JSON.stringify(message);\n if (messageJson === undefined) {\n throw new TypeError(\n \"Kirie IPC message root must serialize to a JSON string. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description for details.\",\n );\n }\n\n const androidBridge = globalThis.KirieAndroidBridge;\n if (androidBridge) {\n androidBridge.postMessage(messageJson);\n return;\n }\n\n const iosBridge = globalThis.webkit?.messageHandlers?.kirie;\n if (iosBridge) {\n iosBridge.postMessage(messageJson);\n return;\n }\n\n throw new Error(\"Kirie native IPC bridge is not available.\");\n}\n\nexport function onIpcMessageReceived<TMessage = unknown>(\n handler: KirieIpcMessageHandler<TMessage>,\n): () => void {\n const listener = (event: Event) => {\n handler((event as CustomEvent<TMessage>).detail);\n };\n\n globalThis.addEventListener(IPC_MESSAGE_EVENT, listener);\n\n return () => {\n globalThis.removeEventListener(IPC_MESSAGE_EVENT, listener);\n };\n}\n"],"mappings":";AAAA,MAAM,oBAAoB;AAwB1B,SAAgB,eAAe,SAAwB;CACrD,MAAM,cAAc,KAAK,UAAU,QAAQ;AAC3C,KAAI,gBAAgB,KAAA,EAClB,OAAM,IAAI,UACR,uLACD;CAGH,MAAM,gBAAgB,WAAW;AACjC,KAAI,eAAe;AACjB,gBAAc,YAAY,YAAY;AACtC;;CAGF,MAAM,YAAY,WAAW,QAAQ,iBAAiB;AACtD,KAAI,WAAW;AACb,YAAU,YAAY,YAAY;AAClC;;AAGF,OAAM,IAAI,MAAM,4CAA4C;;AAG9D,SAAgB,qBACd,SACY;CACZ,MAAM,YAAY,UAAiB;AACjC,UAAS,MAAgC,OAAO;;AAGlD,YAAW,iBAAiB,mBAAmB,SAAS;AAExD,cAAa;AACX,aAAW,oBAAoB,mBAAmB,SAAS"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { decode, encode } from \"cborg\";\n\nconst READY_MESSAGE = new ArrayBuffer(0);\nconst ENCODE_OPTIONS = { float64: true } as const;\n\nexport type KiriePlatformOs = \"android\" | \"ios\" | \"macos\" | \"windows\" | \"linux\";\nexport type KiriePlatformBackend = \"webview\" | \"wkwebview\" | \"godot-cef\";\n\nexport interface KiriePlatform {\n os: KiriePlatformOs;\n backend: KiriePlatformBackend;\n}\n\nexport interface KirieRuntime {\n platform: KiriePlatform;\n}\n\ninterface KirieAndroidChannel {\n postMessage(message: ArrayBuffer): void;\n onmessage: ((event: MessageEvent) => void) | null;\n}\n\ninterface KirieIosMessageHandler {\n postMessage(message: string): void;\n}\n\ntype KirieLane = \"text\" | \"binary\" | \"data\";\n\ninterface KirieIosPacketMessage {\n lane: KirieLane;\n packet: string;\n}\n\ninterface KirieIosWebkit {\n messageHandlers?: {\n kirie?: KirieIosMessageHandler;\n };\n}\n\ndeclare global {\n interface Window {\n kirie?: KirieRuntime;\n KirieTextChannel?: KirieAndroidChannel;\n KirieBinaryChannel?: KirieAndroidChannel;\n KirieDataChannel?: KirieAndroidChannel;\n webkit?: KirieIosWebkit;\n sendIpcMessage(message: string): void;\n sendIpcBinaryMessage(message: ArrayBuffer): void;\n sendIpcData(message: KirieData): void;\n onIpcMessage?: KirieMessageHandler<string>;\n onIpcBinaryMessage?: KirieMessageHandler<ArrayBuffer>;\n onIpcDataMessage?: KirieMessageHandler<KirieData>;\n }\n}\n\n/**\n * Structured data lane subset shared with Godot Variant data.\n * It intentionally excludes engine-local and JavaScript-local object types.\n */\nexport type KirieData =\n | null\n | boolean\n | number\n | string\n | KirieData[]\n | { [key: string]: KirieData };\n\nexport type KirieMessageHandler<TMessage> = (message: TMessage) => void;\n\ninterface KirieTransport {\n sendText(message: string): void;\n sendBinary(bytes: Uint8Array): void;\n sendData(value: KirieData): void;\n onTextReceived(handler: KirieMessageHandler<string>): () => void;\n onBinaryReceived(handler: KirieMessageHandler<Uint8Array>): () => void;\n onDataReceived(handler: KirieMessageHandler<KirieData>): () => void;\n}\n\nfunction asArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n if (\n bytes.buffer instanceof ArrayBuffer &&\n bytes.byteOffset === 0 &&\n bytes.byteLength === bytes.buffer.byteLength\n ) {\n return bytes.buffer;\n }\n\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer as ArrayBuffer;\n}\n\nfunction asUint8Array(value: unknown): Uint8Array {\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n\n throw new TypeError(\"Kirie message must be an ArrayBuffer.\");\n}\n\nfunction decodeText(value: unknown): string {\n const decoded = decode(asUint8Array(value));\n if (typeof decoded !== \"string\") {\n throw new TypeError(\"Kirie text message must decode to a string.\");\n }\n\n return decoded;\n}\n\nfunction decodeBinary(value: unknown): Uint8Array {\n const decoded = decode(asUint8Array(value));\n if (decoded instanceof Uint8Array) {\n return decoded;\n }\n\n throw new TypeError(\"Kirie binary message must decode to bytes.\");\n}\n\nfunction currentTransport(): KirieTransport {\n const platform = window.kirie?.platform;\n return transports[`${platform?.os}/${platform?.backend}`];\n}\n\nfunction listenAndroid<TMessage>(\n channel: KirieAndroidChannel,\n read: (value: unknown) => TMessage,\n handler: KirieMessageHandler<TMessage>,\n): () => void {\n const listener = (event: MessageEvent) => {\n handler(read(event.data));\n };\n\n channel.onmessage = listener;\n channel.postMessage(READY_MESSAGE);\n\n return () => {\n if (channel.onmessage === listener) {\n channel.onmessage = null;\n }\n };\n}\n\nfunction requireAndroidChannel(\n name: \"KirieTextChannel\" | \"KirieBinaryChannel\" | \"KirieDataChannel\",\n): KirieAndroidChannel {\n const channel = window[name];\n if (!channel) {\n throw new Error(`Kirie Android channel is not available: ${name}`);\n }\n\n return channel;\n}\n\nconst androidTransport: KirieTransport = {\n sendText(message) {\n requireAndroidChannel(\"KirieTextChannel\").postMessage(\n asArrayBuffer(encode(message, ENCODE_OPTIONS)),\n );\n },\n\n sendBinary(bytes) {\n requireAndroidChannel(\"KirieBinaryChannel\").postMessage(\n asArrayBuffer(encode(bytes, ENCODE_OPTIONS)),\n );\n },\n\n sendData(value) {\n requireAndroidChannel(\"KirieDataChannel\").postMessage(\n asArrayBuffer(encode(value, ENCODE_OPTIONS)),\n );\n },\n\n onTextReceived(handler) {\n return listenAndroid(requireAndroidChannel(\"KirieTextChannel\"), decodeText, handler);\n },\n\n onBinaryReceived(handler) {\n return listenAndroid(requireAndroidChannel(\"KirieBinaryChannel\"), decodeBinary, handler);\n },\n\n onDataReceived(handler) {\n return listenAndroid(\n requireAndroidChannel(\"KirieDataChannel\"),\n (value) => decode(asUint8Array(value)) as KirieData,\n handler,\n );\n },\n};\n\nfunction requireIosMessageHandler(): KirieIosMessageHandler {\n const handler = window.webkit?.messageHandlers?.kirie;\n if (!handler) {\n throw new Error(\n \"Kirie iOS message handler is not available: window.webkit.messageHandlers.kirie\",\n );\n }\n\n return handler;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n return btoa(binary);\n}\n\nfunction base64ToArrayBuffer(encoded: string): ArrayBuffer {\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n\n return bytes.buffer as ArrayBuffer;\n}\n\nfunction postIosPacket(lane: KirieLane, packet: Uint8Array): void {\n requireIosMessageHandler().postMessage(\n JSON.stringify({\n lane,\n packet: bytesToBase64(packet),\n } satisfies KirieIosPacketMessage),\n );\n}\n\nfunction listenIos<TMessage>(\n lane: KirieLane,\n read: (value: unknown) => TMessage,\n handler: KirieMessageHandler<TMessage>,\n): () => void {\n const listener = (event: Event) => {\n if (!(event instanceof CustomEvent) || !isIosPacketMessage(event.detail)) {\n return;\n }\n\n if (event.detail.lane !== lane) {\n return;\n }\n\n handler(read(base64ToArrayBuffer(event.detail.packet)));\n };\n\n window.addEventListener(\"kirie:ipc-packet\", listener);\n return () => window.removeEventListener(\"kirie:ipc-packet\", listener);\n}\n\nfunction isIosPacketMessage(value: unknown): value is KirieIosPacketMessage {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const message = value as Partial<KirieIosPacketMessage>;\n return (\n (message.lane === \"text\" || message.lane === \"binary\" || message.lane === \"data\") &&\n typeof message.packet === \"string\"\n );\n}\n\nconst iosTransport: KirieTransport = {\n sendText(message) {\n postIosPacket(\"text\", encode(message, ENCODE_OPTIONS));\n },\n\n sendBinary(bytes) {\n postIosPacket(\"binary\", encode(bytes, ENCODE_OPTIONS));\n },\n\n sendData(value) {\n postIosPacket(\"data\", encode(value, ENCODE_OPTIONS));\n },\n\n onTextReceived(handler) {\n return listenIos(\"text\", decodeText, handler);\n },\n\n onBinaryReceived(handler) {\n return listenIos(\"binary\", decodeBinary, handler);\n },\n\n onDataReceived(handler) {\n return listenIos(\"data\", (value) => decode(asUint8Array(value)) as KirieData, handler);\n },\n};\n\ntype KirieCefCallbackName = \"onIpcMessage\" | \"onIpcBinaryMessage\" | \"onIpcDataMessage\";\n\ninterface KirieCefCallbacks {\n onIpcMessage?: KirieMessageHandler<string>;\n onIpcBinaryMessage?: KirieMessageHandler<ArrayBuffer>;\n onIpcDataMessage?: KirieMessageHandler<KirieData>;\n}\n\nfunction listenCefLegacy<TName extends KirieCefCallbackName>(\n name: TName,\n handler: KirieCefCallbacks[TName],\n): () => void {\n const callbacks = window as unknown as KirieCefCallbacks;\n callbacks[name] = handler;\n\n return () => {\n if (callbacks[name] === handler) {\n callbacks[name] = undefined;\n }\n };\n}\n\nconst cefTransport: KirieTransport = {\n sendText(message) {\n window.sendIpcMessage(message);\n },\n\n sendBinary(bytes) {\n window.sendIpcBinaryMessage(asArrayBuffer(bytes));\n },\n\n sendData(value) {\n window.sendIpcData(value);\n },\n\n onTextReceived(handler) {\n // TODO: Switch to Godot CEF listener objects after the upstream addListener lifecycle fix ships.\n return listenCefLegacy(\"onIpcMessage\", handler);\n },\n\n onBinaryReceived(handler) {\n return listenCefLegacy(\"onIpcBinaryMessage\", (value) => handler(new Uint8Array(value)));\n },\n\n onDataReceived(handler) {\n return listenCefLegacy(\"onIpcDataMessage\", handler);\n },\n};\n\nconst transports: Record<string, KirieTransport> = {\n \"android/webview\": androidTransport,\n \"ios/wkwebview\": iosTransport,\n \"linux/godot-cef\": cefTransport,\n \"macos/godot-cef\": cefTransport,\n \"windows/godot-cef\": cefTransport,\n};\n\nexport function sendText(message: string): void {\n currentTransport().sendText(message);\n}\n\nexport function sendBinary(bytes: Uint8Array): void {\n currentTransport().sendBinary(bytes);\n}\n\nexport function sendData(value: KirieData): void {\n currentTransport().sendData(value);\n}\n\nexport function onTextReceived(handler: KirieMessageHandler<string>): () => void {\n return currentTransport().onTextReceived(handler);\n}\n\nexport function onBinaryReceived(handler: KirieMessageHandler<Uint8Array>): () => void {\n return currentTransport().onBinaryReceived(handler);\n}\n\nexport function onDataReceived(handler: KirieMessageHandler<KirieData>): () => void {\n return currentTransport().onDataReceived(handler);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createPointerEventsHandler } from "./index.js";
|
|
2
|
+
//#region src/pointer-input/auto.ts
|
|
3
|
+
const pointerEventsHandler = createPointerEventsHandler();
|
|
4
|
+
document.addEventListener("pointerdown", pointerEventsHandler.bubble);
|
|
5
|
+
document.addEventListener("pointermove", pointerEventsHandler.capture, true);
|
|
6
|
+
document.addEventListener("pointerup", pointerEventsHandler.capture, true);
|
|
7
|
+
document.addEventListener("pointercancel", pointerEventsHandler.capture, true);
|
|
8
|
+
document.addEventListener("pointermove", pointerEventsHandler.bubble);
|
|
9
|
+
//#endregion
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=auto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto.js","names":[],"sources":["../../src/pointer-input/auto.ts"],"sourcesContent":["import { createPointerEventsHandler } from \"./index\";\n\nconst pointerEventsHandler = createPointerEventsHandler();\n\ndocument.addEventListener(\"pointerdown\", pointerEventsHandler.bubble);\ndocument.addEventListener(\"pointermove\", pointerEventsHandler.capture, true);\ndocument.addEventListener(\"pointerup\", pointerEventsHandler.capture, true);\ndocument.addEventListener(\"pointercancel\", pointerEventsHandler.capture, true);\ndocument.addEventListener(\"pointermove\", pointerEventsHandler.bubble);\n"],"mappings":";;AAEA,MAAM,uBAAuB,2BAA2B;AAExD,SAAS,iBAAiB,eAAe,qBAAqB,MAAM;AACpE,SAAS,iBAAiB,eAAe,qBAAqB,SAAS,IAAI;AAC3E,SAAS,iBAAiB,aAAa,qBAAqB,SAAS,IAAI;AACzE,SAAS,iBAAiB,iBAAiB,qBAAqB,SAAS,IAAI;AAC7E,SAAS,iBAAiB,eAAe,qBAAqB,MAAM"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/pointer-input/index.d.ts
|
|
2
|
+
type PointerPhase = "down" | "move" | "up" | "cancel";
|
|
3
|
+
type PointerEventSender = (event: PointerEvent, phase?: PointerPhase) => void;
|
|
4
|
+
interface PointerEventsHandler {
|
|
5
|
+
capture(event: PointerEvent): void;
|
|
6
|
+
bubble(event: PointerEvent): void;
|
|
7
|
+
cancel(): void;
|
|
8
|
+
}
|
|
9
|
+
declare function sendPointerEvent(event: PointerEvent, phase?: PointerPhase): void;
|
|
10
|
+
declare function createPointerEventsHandler(sendPointer?: PointerEventSender): PointerEventsHandler;
|
|
11
|
+
declare function phaseFromPointerEvent(event: PointerEvent): PointerPhase;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { PointerEventSender, PointerEventsHandler, PointerPhase, createPointerEventsHandler, phaseFromPointerEvent, sendPointerEvent };
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/pointer-input/index.ts"],"mappings":";KAGY,YAAA;AAAA,KAmBA,kBAAA,IAAsB,KAAA,EAAO,YAAA,EAAc,KAAA,GAAQ,YAAA;AAAA,UAE9C,oBAAA;EACf,OAAA,CAAQ,KAAA,EAAO,YAAA;EACf,MAAA,CAAO,KAAA,EAAO,YAAA;EACd,MAAA;AAAA;AAAA,iBAGc,gBAAA,CACd,KAAA,EAAO,YAAA,EACP,KAAA,GAAO,YAAA;AAAA,iBAwBO,0BAAA,CACd,WAAA,GAAa,kBAAA,GACZ,oBAAA;AAAA,iBA8Fa,qBAAA,CAAsB,KAAA,EAAO,YAAA,GAAe,YAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { sendData } from "../index.js";
|
|
2
|
+
//#region src/pointer-input/index.ts
|
|
3
|
+
function sendPointerEvent(event, phase = phaseFromPointerEvent(event)) {
|
|
4
|
+
const view = event.view ?? window;
|
|
5
|
+
const pointerType = event.pointerType;
|
|
6
|
+
if (pointerType !== "mouse" && pointerType !== "pen" && pointerType !== "touch") throw new TypeError(`Kirie cannot forward pointer type: ${pointerType}`);
|
|
7
|
+
sendData({ __gd_kirie_control: {
|
|
8
|
+
kind: "pointer",
|
|
9
|
+
phase,
|
|
10
|
+
pointer_id: event.pointerId,
|
|
11
|
+
pointer_type: pointerType,
|
|
12
|
+
normalized_x: event.clientX / view.innerWidth,
|
|
13
|
+
normalized_y: event.clientY / view.innerHeight,
|
|
14
|
+
button: event.button,
|
|
15
|
+
buttons: event.buttons,
|
|
16
|
+
pressure: event.pressure
|
|
17
|
+
} });
|
|
18
|
+
}
|
|
19
|
+
function createPointerEventsHandler(sendPointer = sendPointerEvent) {
|
|
20
|
+
const claimedPointers = /* @__PURE__ */ new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Completes events for pointer sequences previously claimed during bubbling.
|
|
23
|
+
*
|
|
24
|
+
* Triggering workflow:
|
|
25
|
+
*
|
|
26
|
+
* {@link EventTarget.addEventListener}
|
|
27
|
+
* -> `pointermove|pointerup|pointercancel`
|
|
28
|
+
* -> {@link capture}
|
|
29
|
+
*
|
|
30
|
+
* Upstream:
|
|
31
|
+
* - {@link EventTarget.addEventListener}
|
|
32
|
+
*
|
|
33
|
+
* Downstream:
|
|
34
|
+
* - {@link sendPointerEvent}
|
|
35
|
+
*/
|
|
36
|
+
const capture = (event) => {
|
|
37
|
+
if (!claimedPointers.has(event.pointerId) || event.type !== "pointermove" && event.type !== "pointerup" && event.type !== "pointercancel") return;
|
|
38
|
+
sendPointer(event);
|
|
39
|
+
if (event.type === "pointerup" || event.type === "pointercancel") {
|
|
40
|
+
claimedPointers.delete(event.pointerId);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
claimedPointers.set(event.pointerId, event);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Claims bubbled pointer downs and forwards unpressed mouse hover.
|
|
47
|
+
*
|
|
48
|
+
* Triggering workflow:
|
|
49
|
+
*
|
|
50
|
+
* {@link EventTarget.addEventListener}
|
|
51
|
+
* -> `pointerdown|pointermove`
|
|
52
|
+
* -> {@link bubble}
|
|
53
|
+
*
|
|
54
|
+
* Upstream:
|
|
55
|
+
* - {@link EventTarget.addEventListener}
|
|
56
|
+
*
|
|
57
|
+
* Downstream:
|
|
58
|
+
* - {@link sendPointerEvent}
|
|
59
|
+
*/
|
|
60
|
+
const bubble = (event) => {
|
|
61
|
+
if (event.type === "pointerdown") {
|
|
62
|
+
sendPointer(event);
|
|
63
|
+
claimedPointers.set(event.pointerId, event);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (event.type !== "pointermove" || claimedPointers.has(event.pointerId) || event.pointerType !== "mouse" || event.buttons !== 0) return;
|
|
67
|
+
sendPointer(event);
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Cancels every pointer sequence currently claimed by this handler.
|
|
71
|
+
*
|
|
72
|
+
* Triggering workflow:
|
|
73
|
+
*
|
|
74
|
+
* {@link createPointerEventsHandler}
|
|
75
|
+
* -> {@link PointerEventsHandler.cancel}
|
|
76
|
+
*
|
|
77
|
+
* Upstream:
|
|
78
|
+
* - caller of {@link PointerEventsHandler.cancel}
|
|
79
|
+
*
|
|
80
|
+
* Downstream:
|
|
81
|
+
* - {@link sendPointerEvent}
|
|
82
|
+
*/
|
|
83
|
+
const cancel = () => {
|
|
84
|
+
for (const pointerEvent of claimedPointers.values()) sendPointer(pointerEvent, "cancel");
|
|
85
|
+
claimedPointers.clear();
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
capture,
|
|
89
|
+
bubble,
|
|
90
|
+
cancel
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function phaseFromPointerEvent(event) {
|
|
94
|
+
switch (event.type) {
|
|
95
|
+
case "pointerdown": return "down";
|
|
96
|
+
case "pointermove": return "move";
|
|
97
|
+
case "pointerup": return "up";
|
|
98
|
+
case "pointercancel": return "cancel";
|
|
99
|
+
default: throw new TypeError(`Kirie cannot forward pointer event type: ${event.type}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { createPointerEventsHandler, phaseFromPointerEvent, sendPointerEvent };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/pointer-input/index.ts"],"sourcesContent":["import type { KirieData } from \"../index\";\nimport { sendData } from \"../index\";\n\nexport type PointerPhase = \"down\" | \"move\" | \"up\" | \"cancel\";\ntype PointerType = \"mouse\" | \"pen\" | \"touch\";\n\ninterface PointerInputRecord extends Record<string, KirieData> {\n kind: \"pointer\";\n phase: PointerPhase;\n pointer_id: number;\n pointer_type: PointerType;\n normalized_x: number;\n normalized_y: number;\n button: number;\n buttons: number;\n pressure: number;\n}\n\ninterface PointerControlRecord extends Record<string, KirieData> {\n __gd_kirie_control: PointerInputRecord;\n}\n\nexport type PointerEventSender = (event: PointerEvent, phase?: PointerPhase) => void;\n\nexport interface PointerEventsHandler {\n capture(event: PointerEvent): void;\n bubble(event: PointerEvent): void;\n cancel(): void;\n}\n\nexport function sendPointerEvent(\n event: PointerEvent,\n phase: PointerPhase = phaseFromPointerEvent(event),\n): void {\n const view = event.view ?? window;\n\n const pointerType = event.pointerType;\n if (pointerType !== \"mouse\" && pointerType !== \"pen\" && pointerType !== \"touch\") {\n throw new TypeError(`Kirie cannot forward pointer type: ${pointerType}`);\n }\n\n sendData({\n __gd_kirie_control: {\n kind: \"pointer\",\n phase,\n pointer_id: event.pointerId,\n pointer_type: pointerType,\n normalized_x: event.clientX / view.innerWidth,\n normalized_y: event.clientY / view.innerHeight,\n button: event.button,\n buttons: event.buttons,\n pressure: event.pressure,\n },\n } satisfies PointerControlRecord);\n}\n\nexport function createPointerEventsHandler(\n sendPointer: PointerEventSender = sendPointerEvent,\n): PointerEventsHandler {\n // A sequence is claimed only when its down event reaches the document bubble phase.\n const claimedPointers = new Map<number, PointerEvent>();\n\n /**\n * Completes events for pointer sequences previously claimed during bubbling.\n *\n * Triggering workflow:\n *\n * {@link EventTarget.addEventListener}\n * -> `pointermove|pointerup|pointercancel`\n * -> {@link capture}\n *\n * Upstream:\n * - {@link EventTarget.addEventListener}\n *\n * Downstream:\n * - {@link sendPointerEvent}\n */\n const capture = (event: PointerEvent): void => {\n if (\n !claimedPointers.has(event.pointerId) ||\n (event.type !== \"pointermove\" && event.type !== \"pointerup\" && event.type !== \"pointercancel\")\n ) {\n return;\n }\n\n sendPointer(event);\n if (event.type === \"pointerup\" || event.type === \"pointercancel\") {\n claimedPointers.delete(event.pointerId);\n return;\n }\n\n claimedPointers.set(event.pointerId, event);\n };\n\n /**\n * Claims bubbled pointer downs and forwards unpressed mouse hover.\n *\n * Triggering workflow:\n *\n * {@link EventTarget.addEventListener}\n * -> `pointerdown|pointermove`\n * -> {@link bubble}\n *\n * Upstream:\n * - {@link EventTarget.addEventListener}\n *\n * Downstream:\n * - {@link sendPointerEvent}\n */\n const bubble = (event: PointerEvent): void => {\n if (event.type === \"pointerdown\") {\n sendPointer(event);\n claimedPointers.set(event.pointerId, event);\n return;\n }\n\n if (\n event.type !== \"pointermove\" ||\n claimedPointers.has(event.pointerId) ||\n event.pointerType !== \"mouse\" ||\n event.buttons !== 0\n ) {\n return;\n }\n\n sendPointer(event);\n };\n\n /**\n * Cancels every pointer sequence currently claimed by this handler.\n *\n * Triggering workflow:\n *\n * {@link createPointerEventsHandler}\n * -> {@link PointerEventsHandler.cancel}\n *\n * Upstream:\n * - caller of {@link PointerEventsHandler.cancel}\n *\n * Downstream:\n * - {@link sendPointerEvent}\n */\n const cancel = (): void => {\n for (const pointerEvent of claimedPointers.values()) {\n sendPointer(pointerEvent, \"cancel\");\n }\n claimedPointers.clear();\n };\n\n return { capture, bubble, cancel };\n}\n\nexport function phaseFromPointerEvent(event: PointerEvent): PointerPhase {\n switch (event.type) {\n case \"pointerdown\":\n return \"down\";\n case \"pointermove\":\n return \"move\";\n case \"pointerup\":\n return \"up\";\n case \"pointercancel\":\n return \"cancel\";\n default:\n throw new TypeError(`Kirie cannot forward pointer event type: ${event.type}`);\n }\n}\n"],"mappings":";;AA8BA,SAAgB,iBACd,OACA,QAAsB,sBAAsB,KAAK,GAC3C;CACN,MAAM,OAAO,MAAM,QAAQ;CAE3B,MAAM,cAAc,MAAM;CAC1B,IAAI,gBAAgB,WAAW,gBAAgB,SAAS,gBAAgB,SACtE,MAAM,IAAI,UAAU,sCAAsC,aAAa;CAGzE,SAAS,EACP,oBAAoB;EAClB,MAAM;EACN;EACA,YAAY,MAAM;EAClB,cAAc;EACd,cAAc,MAAM,UAAU,KAAK;EACnC,cAAc,MAAM,UAAU,KAAK;EACnC,QAAQ,MAAM;EACd,SAAS,MAAM;EACf,UAAU,MAAM;CAClB,EACF,CAAgC;AAClC;AAEA,SAAgB,2BACd,cAAkC,kBACZ;CAEtB,MAAM,kCAAkB,IAAI,IAA0B;;;;;;;;;;;;;;;;CAiBtD,MAAM,WAAW,UAA8B;EAC7C,IACE,CAAC,gBAAgB,IAAI,MAAM,SAAS,KACnC,MAAM,SAAS,iBAAiB,MAAM,SAAS,eAAe,MAAM,SAAS,iBAE9E;EAGF,YAAY,KAAK;EACjB,IAAI,MAAM,SAAS,eAAe,MAAM,SAAS,iBAAiB;GAChE,gBAAgB,OAAO,MAAM,SAAS;GACtC;EACF;EAEA,gBAAgB,IAAI,MAAM,WAAW,KAAK;CAC5C;;;;;;;;;;;;;;;;CAiBA,MAAM,UAAU,UAA8B;EAC5C,IAAI,MAAM,SAAS,eAAe;GAChC,YAAY,KAAK;GACjB,gBAAgB,IAAI,MAAM,WAAW,KAAK;GAC1C;EACF;EAEA,IACE,MAAM,SAAS,iBACf,gBAAgB,IAAI,MAAM,SAAS,KACnC,MAAM,gBAAgB,WACtB,MAAM,YAAY,GAElB;EAGF,YAAY,KAAK;CACnB;;;;;;;;;;;;;;;CAgBA,MAAM,eAAqB;EACzB,KAAK,MAAM,gBAAgB,gBAAgB,OAAO,GAChD,YAAY,cAAc,QAAQ;EAEpC,gBAAgB,MAAM;CACxB;CAEA,OAAO;EAAE;EAAS;EAAQ;CAAO;AACnC;AAEA,SAAgB,sBAAsB,OAAmC;CACvE,QAAQ,MAAM,MAAd;EACE,KAAK,eACH,OAAO;EACT,KAAK,eACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,iBACH,OAAO;EACT,SACE,MAAM,IAAI,UAAU,4CAA4C,MAAM,MAAM;CAChF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gd-kirie/ipc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,14 +13,26 @@
|
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./pointer-input": {
|
|
18
|
+
"types": "./dist/pointer-input/index.d.ts",
|
|
19
|
+
"import": "./dist/pointer-input/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./pointer-input/auto": {
|
|
22
|
+
"types": "./dist/pointer-input/auto.d.ts",
|
|
23
|
+
"import": "./dist/pointer-input/auto.js"
|
|
16
24
|
}
|
|
17
25
|
},
|
|
18
26
|
"files": [
|
|
19
27
|
"dist"
|
|
20
28
|
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"cborg": "^4.5.8"
|
|
31
|
+
},
|
|
21
32
|
"devDependencies": {
|
|
22
|
-
"tsdown": "^0.
|
|
23
|
-
"typescript": "^
|
|
33
|
+
"tsdown": "^0.22.2",
|
|
34
|
+
"typescript": "^6.0.3",
|
|
35
|
+
"vitest": "^4.0.15"
|
|
24
36
|
},
|
|
25
37
|
"publishConfig": {
|
|
26
38
|
"access": "public",
|
|
@@ -28,6 +40,7 @@
|
|
|
28
40
|
},
|
|
29
41
|
"scripts": {
|
|
30
42
|
"build": "tsdown",
|
|
43
|
+
"test:run": "vitest run",
|
|
31
44
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
32
45
|
}
|
|
33
46
|
}
|