@kelnishi/satmouse-client 0.10.4 → 0.10.6
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/dist/elements/index.cjs +146 -62
- package/dist/elements/index.cjs.map +1 -1
- package/dist/elements/index.d.cts +22 -1
- package/dist/elements/index.d.ts +22 -1
- package/dist/elements/index.js +146 -62
- package/dist/elements/index.js.map +1 -1
- package/dist/react/index.cjs +17 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +17 -1
- package/dist/react/index.js.map +1 -1
- package/dist/utils/index.cjs +17 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +6 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +17 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/react/index.d.cts +0 -253
- package/dist/react/index.d.ts +0 -253
package/dist/elements/index.cjs
CHANGED
|
@@ -13,9 +13,10 @@ function registerSatMouse(manager) {
|
|
|
13
13
|
function getManager() {
|
|
14
14
|
return globalManager;
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function onManager(fn) {
|
|
17
17
|
if (globalManager) fn(globalManager);
|
|
18
18
|
else listeners.add(fn);
|
|
19
|
+
return () => listeners.delete(fn);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
// src/elements/satmouse-status.ts
|
|
@@ -41,7 +42,10 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
41
42
|
text;
|
|
42
43
|
proto;
|
|
43
44
|
launch;
|
|
44
|
-
|
|
45
|
+
manager = null;
|
|
46
|
+
unsub = null;
|
|
47
|
+
pollTimer = null;
|
|
48
|
+
stateHandler = (state, protocol) => this.update(state, protocol);
|
|
45
49
|
constructor() {
|
|
46
50
|
super();
|
|
47
51
|
const shadow = this.attachShadow({ mode: "open" });
|
|
@@ -51,44 +55,80 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
51
55
|
this.proto = shadow.querySelector(".protocol");
|
|
52
56
|
this.launch = shadow.querySelector(".launch");
|
|
53
57
|
this.launch.addEventListener("click", () => {
|
|
54
|
-
|
|
55
|
-
setTimeout(() => {
|
|
56
|
-
if (!document.hidden) {
|
|
57
|
-
if (confirm("SatMouse doesn't appear to be installed. Go to the download page?")) {
|
|
58
|
-
window.open("https://github.com/kelnishi/SatMouse/releases/latest", "_blank", "noopener");
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}, 1e3);
|
|
58
|
+
this.startLaunchFlow();
|
|
62
59
|
});
|
|
63
60
|
}
|
|
64
61
|
connectedCallback() {
|
|
65
|
-
this.
|
|
62
|
+
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
63
|
+
this.stopPoll();
|
|
64
|
+
this.launch.disabled = false;
|
|
65
|
+
this.launch.textContent = "Launch SatMouse";
|
|
66
|
+
}
|
|
67
|
+
disconnectedCallback() {
|
|
68
|
+
this.stopPoll();
|
|
69
|
+
this.unsub?.();
|
|
70
|
+
this.unbind();
|
|
71
|
+
}
|
|
72
|
+
bind(mgr) {
|
|
73
|
+
this.unbind();
|
|
74
|
+
this.manager = mgr;
|
|
75
|
+
mgr.on("stateChange", this.stateHandler);
|
|
76
|
+
this.update(mgr.state, mgr.protocol);
|
|
77
|
+
}
|
|
78
|
+
unbind() {
|
|
79
|
+
this.manager?.off("stateChange", this.stateHandler);
|
|
80
|
+
this.manager = null;
|
|
81
|
+
}
|
|
82
|
+
update(state, protocol) {
|
|
83
|
+
this.dot.dataset.state = state;
|
|
84
|
+
this.proto.textContent = protocol !== "none" ? protocol : "";
|
|
85
|
+
if (state === "connected") {
|
|
86
|
+
this.stopPoll();
|
|
87
|
+
this.text.textContent = "Connected";
|
|
88
|
+
this.launch.style.display = "none";
|
|
89
|
+
} else if (state === "connecting") {
|
|
90
|
+
this.text.textContent = "Connecting...";
|
|
91
|
+
this.launch.style.display = "none";
|
|
92
|
+
} else if (state === "failed") {
|
|
93
|
+
this.text.textContent = "Not running";
|
|
66
94
|
this.launch.style.display = "inline-block";
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
this.launch.disabled = false;
|
|
96
|
+
this.launch.textContent = "Launch SatMouse";
|
|
97
|
+
} else {
|
|
98
|
+
this.text.textContent = "Disconnected";
|
|
99
|
+
this.launch.style.display = "none";
|
|
100
|
+
}
|
|
69
101
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
102
|
+
startLaunchFlow() {
|
|
103
|
+
this.launch.textContent = "Connecting...";
|
|
104
|
+
this.launch.disabled = true;
|
|
105
|
+
this.manager?.retry();
|
|
106
|
+
window.location.href = "satmouse://launch";
|
|
107
|
+
let attempts = 0;
|
|
108
|
+
this.stopPoll();
|
|
109
|
+
this.pollTimer = setInterval(() => {
|
|
110
|
+
attempts++;
|
|
111
|
+
if (this.manager?.state === "connected") {
|
|
112
|
+
this.stopPoll();
|
|
113
|
+
return;
|
|
77
114
|
}
|
|
78
|
-
if (
|
|
79
|
-
this.
|
|
80
|
-
this.launch.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.launch.style.display = "inline-block";
|
|
87
|
-
} else {
|
|
88
|
-
this.text.textContent = "Disconnected";
|
|
89
|
-
this.launch.style.display = "none";
|
|
115
|
+
if (attempts >= 5) {
|
|
116
|
+
this.stopPoll();
|
|
117
|
+
this.launch.disabled = false;
|
|
118
|
+
this.launch.textContent = "Launch SatMouse";
|
|
119
|
+
if (confirm("SatMouse doesn't appear to be installed. Go to the download page?")) {
|
|
120
|
+
window.open("https://github.com/kelnishi/SatMouse/releases/latest", "_blank", "noopener");
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
90
123
|
}
|
|
91
|
-
|
|
124
|
+
this.manager?.retry();
|
|
125
|
+
}, 1500);
|
|
126
|
+
}
|
|
127
|
+
stopPoll() {
|
|
128
|
+
if (this.pollTimer) {
|
|
129
|
+
clearInterval(this.pollTimer);
|
|
130
|
+
this.pollTimer = null;
|
|
131
|
+
}
|
|
92
132
|
}
|
|
93
133
|
};
|
|
94
134
|
customElements.define("satmouse-status", SatMouseStatus);
|
|
@@ -132,19 +172,39 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
132
172
|
shadow.innerHTML = STYLES + `<div class="container"><span class="empty">No devices</span></div>`;
|
|
133
173
|
this.container = shadow.querySelector(".container");
|
|
134
174
|
}
|
|
175
|
+
unsub = null;
|
|
176
|
+
deviceStatusHandler = (event, device) => {
|
|
177
|
+
if (event === "connected") this.addDevice(device);
|
|
178
|
+
else this.removeDevice(device);
|
|
179
|
+
};
|
|
180
|
+
stateHandler = (state) => {
|
|
181
|
+
if (state === "connected") {
|
|
182
|
+
this.manager?.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));
|
|
183
|
+
}
|
|
184
|
+
};
|
|
135
185
|
connectedCallback() {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
187
|
+
}
|
|
188
|
+
disconnectedCallback() {
|
|
189
|
+
this.unsub?.();
|
|
190
|
+
this.unbind();
|
|
191
|
+
this.container.innerHTML = `<span class="empty">No devices</span>`;
|
|
192
|
+
}
|
|
193
|
+
bind(mgr) {
|
|
194
|
+
this.unbind();
|
|
195
|
+
this.manager = mgr;
|
|
196
|
+
mgr.on("deviceStatus", this.deviceStatusHandler);
|
|
197
|
+
mgr.on("stateChange", this.stateHandler);
|
|
198
|
+
if (mgr.state === "connected") {
|
|
199
|
+
mgr.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
unbind() {
|
|
203
|
+
if (this.manager) {
|
|
204
|
+
this.manager.off("deviceStatus", this.deviceStatusHandler);
|
|
205
|
+
this.manager.off("stateChange", this.stateHandler);
|
|
206
|
+
this.manager = null;
|
|
207
|
+
}
|
|
148
208
|
}
|
|
149
209
|
addDevice(device) {
|
|
150
210
|
const existing = this.shadowRoot.getElementById(`dev-${device.id}`);
|
|
@@ -273,6 +333,22 @@ var TEMPLATE2 = `
|
|
|
273
333
|
var SatMouseDebug = class extends HTMLElement {
|
|
274
334
|
els = {};
|
|
275
335
|
frameCount = 0;
|
|
336
|
+
fpsInterval = null;
|
|
337
|
+
manager = null;
|
|
338
|
+
unsub = null;
|
|
339
|
+
spatialHandler = (data) => {
|
|
340
|
+
this.frameCount++;
|
|
341
|
+
this.els.tx.textContent = String(Math.round(data.translation.x));
|
|
342
|
+
this.els.ty.textContent = String(Math.round(data.translation.y));
|
|
343
|
+
this.els.tz.textContent = String(Math.round(data.translation.z));
|
|
344
|
+
this.els.rx.textContent = String(Math.round(data.rotation.x));
|
|
345
|
+
this.els.ry.textContent = String(Math.round(data.rotation.y));
|
|
346
|
+
this.els.rz.textContent = String(Math.round(data.rotation.z));
|
|
347
|
+
};
|
|
348
|
+
stateHandler = (state, protocol) => {
|
|
349
|
+
this.els.state.textContent = state;
|
|
350
|
+
this.els.protocol.textContent = protocol !== "none" ? protocol : "";
|
|
351
|
+
};
|
|
276
352
|
constructor() {
|
|
277
353
|
super();
|
|
278
354
|
const shadow = this.attachShadow({ mode: "open" });
|
|
@@ -285,27 +361,35 @@ var SatMouseDebug = class extends HTMLElement {
|
|
|
285
361
|
this.els.fps = shadow.querySelector(".fps");
|
|
286
362
|
}
|
|
287
363
|
connectedCallback() {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
bind(manager) {
|
|
291
|
-
manager.on("rawSpatialData", (data) => {
|
|
292
|
-
this.frameCount++;
|
|
293
|
-
this.els.tx.textContent = String(Math.round(data.translation.x));
|
|
294
|
-
this.els.ty.textContent = String(Math.round(data.translation.y));
|
|
295
|
-
this.els.tz.textContent = String(Math.round(data.translation.z));
|
|
296
|
-
this.els.rx.textContent = String(Math.round(data.rotation.x));
|
|
297
|
-
this.els.ry.textContent = String(Math.round(data.rotation.y));
|
|
298
|
-
this.els.rz.textContent = String(Math.round(data.rotation.z));
|
|
299
|
-
});
|
|
300
|
-
manager.on("stateChange", (state, protocol) => {
|
|
301
|
-
this.els.state.textContent = state;
|
|
302
|
-
this.els.protocol.textContent = protocol !== "none" ? protocol : "";
|
|
303
|
-
});
|
|
304
|
-
setInterval(() => {
|
|
364
|
+
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
365
|
+
this.fpsInterval = setInterval(() => {
|
|
305
366
|
this.els.fps.textContent = String(this.frameCount);
|
|
306
367
|
this.frameCount = 0;
|
|
307
368
|
}, 1e3);
|
|
308
369
|
}
|
|
370
|
+
disconnectedCallback() {
|
|
371
|
+
this.unsub?.();
|
|
372
|
+
this.unbind();
|
|
373
|
+
if (this.fpsInterval) {
|
|
374
|
+
clearInterval(this.fpsInterval);
|
|
375
|
+
this.fpsInterval = null;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
bind(mgr) {
|
|
379
|
+
this.unbind();
|
|
380
|
+
this.manager = mgr;
|
|
381
|
+
mgr.on("rawSpatialData", this.spatialHandler);
|
|
382
|
+
mgr.on("stateChange", this.stateHandler);
|
|
383
|
+
this.els.state.textContent = mgr.state;
|
|
384
|
+
this.els.protocol.textContent = mgr.protocol !== "none" ? mgr.protocol : "";
|
|
385
|
+
}
|
|
386
|
+
unbind() {
|
|
387
|
+
if (this.manager) {
|
|
388
|
+
this.manager.off("rawSpatialData", this.spatialHandler);
|
|
389
|
+
this.manager.off("stateChange", this.stateHandler);
|
|
390
|
+
this.manager = null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
309
393
|
};
|
|
310
394
|
customElements.define("satmouse-debug", SatMouseDebug);
|
|
311
395
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/elements/registry.ts","../../src/elements/satmouse-status.ts","../../src/elements/satmouse-devices.ts","../../src/elements/satmouse-debug.ts"],"names":["FULL_AXES","buildRoutes","TEMPLATE"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { InputManager } from \"../utils/input-manager.js\";\n\n/**\n * Global registry for SatMouse Web Components.\n *\n * Usage:\n * import { registerSatMouse } from \"@kelnishi/satmouse-client/elements\";\n * registerSatMouse(manager);\n * // All <satmouse-*> elements auto-connect to this manager\n */\n\nlet globalManager: InputManager | null = null;\nconst listeners = new Set<(m: InputManager) => void>();\n\nexport function registerSatMouse(manager: InputManager): void {\n globalManager = manager;\n for (const fn of listeners) fn(manager);\n listeners.clear();\n}\n\nexport function getManager(): InputManager | null {\n return globalManager;\n}\n\nexport function onManagerReady(fn: (m: InputManager) => void): void {\n if (globalManager) fn(globalManager);\n else listeners.add(fn);\n}\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private disconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n // Try the URL scheme — if installed, the OS opens the app\n window.location.href = \"satmouse://launch\";\n // If we're still here after 1s, the scheme wasn't handled\n setTimeout(() => {\n if (!document.hidden) {\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n }\n }, 1000);\n });\n }\n\n connectedCallback() {\n // Show launch button if still disconnected after 3s (covers cold page load)\n this.disconnectTimer = setTimeout(() => { this.launch.style.display = \"inline-block\"; }, 3000);\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (this.disconnectTimer) { clearTimeout(this.disconnectTimer); this.disconnectTimer = null; }\n\n if (state === \"connected\") {\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n });\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis, AxisRoute } from \"../utils/action-map.js\";\nimport { FULL_AXES, buildRoutes, DEFAULT_ROUTES } from \"../utils/action-map.js\";\n\nconst STYLES = `\n<style>\n :host { display: block; font-family: inherit; font-size: 12px; }\n .panel { background: #0f3460; border: 1px solid #1a4a8a; border-radius: 6px; padding: 10px; margin-bottom: 8px; }\n summary { cursor: pointer; font-weight: 600; color: #e0e0e0; font-size: 13px; }\n .type { font-size: 10px; color: #7f8c8d; text-transform: uppercase; margin-left: 6px; }\n .controls { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n .slider-row { display: flex; align-items: center; gap: 6px; }\n .slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }\n .slider-row input[type=\"range\"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }\n .slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }\n .route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }\n .route-row { display: flex; gap: 4px; align-items: center; }\n .route-row label { color: #7f8c8d; white-space: nowrap; }\n .route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;\n font-size: 11px; padding: 1px 4px; }\n .route-row input[type=\"checkbox\"] { accent-color: #e74c3c; margin: 0; }\n .empty { color: #7f8c8d; font-style: italic; }\n .reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }\n .reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }\n</style>\n`;\n\nfunction mapSlider(v: number): number { return 0.0001 * Math.pow(500, v / 100); }\nfunction unmapSlider(v: number): number { return (100 * Math.log(v / 0.0001)) / Math.log(500); }\n\nexport class SatMouseDevices extends HTMLElement {\n private manager: InputManager | null = null;\n private container!: HTMLElement;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = STYLES + `<div class=\"container\"><span class=\"empty\">No devices</span></div>`;\n this.container = shadow.querySelector(\".container\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => {\n this.manager = manager;\n manager.on(\"deviceStatus\", (event, device) => {\n if (event === \"connected\") this.addDevice(device);\n else this.removeDevice(device);\n });\n manager.on(\"stateChange\", (state) => {\n if (state === \"connected\") {\n manager.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n });\n });\n }\n\n private addDevice(device: DeviceInfo): void {\n const existing = this.shadowRoot!.getElementById(`dev-${device.id}`);\n if (existing) {\n this.refreshControls(existing as HTMLDetailsElement, device);\n return;\n }\n const empty = this.container.querySelector(\".empty\");\n if (empty) empty.remove();\n\n const panel = document.createElement(\"details\");\n panel.className = \"panel\";\n panel.id = `dev-${device.id}`;\n panel.open = true;\n\n const summary = document.createElement(\"summary\");\n summary.innerHTML = `${device.model ?? device.name}<span class=\"type\">${device.connectionType ?? \"\"}</span>`;\n panel.appendChild(summary);\n\n this.refreshControls(panel, device);\n this.container.appendChild(panel);\n }\n\n private refreshControls(panel: HTMLDetailsElement, device: DeviceInfo): void {\n const old = panel.querySelector(\".controls\");\n if (old) old.remove();\n\n const mgr = this.manager!;\n const cfg = mgr.getDeviceConfig(device.id);\n\n const controls = document.createElement(\"div\");\n controls.className = \"controls\";\n\n // Axis routes — one row per device input: [flip] [label] → [target dropdown] [scale slider]\n const routeGroup = document.createElement(\"div\");\n routeGroup.className = \"route-group\";\n const deviceAxes = device.axes ?? [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n const routes = this.getRoutes(device.id, deviceAxes);\n\n for (let i = 0; i < deviceAxes.length; i++) {\n const route = routes[i] ?? { source: deviceAxes[i] as InputAxis, target: deviceAxes[i].replace(/[+-]$/, \"\") as InputAxis };\n const row = document.createElement(\"div\");\n row.className = \"route-row\";\n\n // Flip checkbox\n const cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.checked = route.flip ?? false;\n cb.title = \"Flip\";\n const routeIndex = i;\n cb.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });\n });\n row.appendChild(cb);\n\n // Label (device input name)\n const label = document.createElement(\"label\");\n label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();\n row.appendChild(label);\n\n // Target dropdown\n const sel = document.createElement(\"select\");\n for (const target of FULL_AXES) {\n const opt = document.createElement(\"option\");\n opt.value = target;\n opt.textContent = target.toUpperCase();\n if (target === route.target) opt.selected = true;\n sel.appendChild(opt);\n }\n sel.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value as InputAxis });\n });\n row.appendChild(sel);\n\n routeGroup.appendChild(row);\n }\n controls.appendChild(routeGroup);\n\n // Scale slider\n const sensRow = document.createElement(\"div\");\n sensRow.className = \"slider-row\";\n const currentScale = cfg.scale ?? mgr.config.scale;\n sensRow.innerHTML = `<label>Scale</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(currentScale))}\">` +\n `<span>${currentScale.toFixed(4)}</span>`;\n const slider = sensRow.querySelector(\"input\")! as HTMLInputElement;\n const span = sensRow.querySelector(\"span\")!;\n slider.addEventListener(\"input\", () => {\n const v = mapSlider(+slider.value);\n span.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { scale: v });\n });\n controls.appendChild(sensRow);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = \"Restore Defaults\";\n resetBtn.addEventListener(\"click\", () => {\n mgr.resetDeviceConfig(device.id);\n this.refreshControls(panel, device);\n });\n controls.appendChild(resetBtn);\n\n panel.appendChild(controls);\n }\n\n private getRoutes(deviceId: string, deviceAxes: string[]): AxisRoute[] {\n // Only use saved device config routes — not the global fallback\n const mgr = this.manager!;\n const devCfg = mgr.config.devices[deviceId];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // Check pattern matches\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && deviceId.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // Build from device axes\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const base = this.getRoutes(deviceId, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private removeDevice(device: DeviceInfo): void {\n this.shadowRoot!.getElementById(`dev-${device.id}`)?.remove();\n if (this.container.children.length === 0) {\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { SpatialData, ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: block; font-family: monospace; font-size: 12px; }\n .row { display: flex; justify-content: space-between; padding: 2px 0; }\n .label { color: #7f8c8d; font-weight: 600; width: 28px; }\n .value { color: #3498db; text-align: right; min-width: 50px; }\n .meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }\n</style>\n<div class=\"meta\"><span class=\"state\">Disconnected</span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> fps</div>\n<div class=\"row\"><span class=\"label\">TX</span><span class=\"value\" id=\"tx\">0</span></div>\n<div class=\"row\"><span class=\"label\">TY</span><span class=\"value\" id=\"ty\">0</span></div>\n<div class=\"row\"><span class=\"label\">TZ</span><span class=\"value\" id=\"tz\">0</span></div>\n<div class=\"row\"><span class=\"label\">RX</span><span class=\"value\" id=\"rx\">0</span></div>\n<div class=\"row\"><span class=\"label\">RY</span><span class=\"value\" id=\"ry\">0</span></div>\n<div class=\"row\"><span class=\"label\">RZ</span><span class=\"value\" id=\"rz\">0</span></div>\n`;\n\nexport class SatMouseDebug extends HTMLElement {\n private els: Record<string, HTMLElement> = {};\n private frameCount = 0;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n for (const id of [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"]) {\n this.els[id] = shadow.getElementById(id)!;\n }\n this.els.state = shadow.querySelector(\".state\")!;\n this.els.protocol = shadow.querySelector(\".protocol\")!;\n this.els.fps = shadow.querySelector(\".fps\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"rawSpatialData\", (data: SpatialData) => {\n this.frameCount++;\n this.els.tx.textContent = String(Math.round(data.translation.x));\n this.els.ty.textContent = String(Math.round(data.translation.y));\n this.els.tz.textContent = String(Math.round(data.translation.z));\n this.els.rx.textContent = String(Math.round(data.rotation.x));\n this.els.ry.textContent = String(Math.round(data.rotation.y));\n this.els.rz.textContent = String(Math.round(data.rotation.z));\n });\n\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.els.state.textContent = state;\n this.els.protocol.textContent = protocol !== \"none\" ? protocol : \"\";\n });\n\n setInterval(() => {\n this.els.fps.textContent = String(this.frameCount);\n this.frameCount = 0;\n }, 1000);\n }\n}\n\ncustomElements.define(\"satmouse-debug\", SatMouseDebug);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/elements/registry.ts","../../src/elements/satmouse-status.ts","../../src/elements/satmouse-devices.ts","../../src/elements/satmouse-debug.ts"],"names":["FULL_AXES","buildRoutes","TEMPLATE"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { InputManager } from \"../utils/input-manager.js\";\n\n/**\n * Global registry for SatMouse Web Components.\n *\n * Usage:\n * import { registerSatMouse } from \"@kelnishi/satmouse-client/elements\";\n * registerSatMouse(manager);\n * // All <satmouse-*> elements auto-connect to this manager\n */\n\nlet globalManager: InputManager | null = null;\nconst listeners = new Set<(m: InputManager) => void>();\n\nexport function registerSatMouse(manager: InputManager): void {\n globalManager = manager;\n for (const fn of listeners) fn(manager);\n listeners.clear();\n}\n\nexport function getManager(): InputManager | null {\n return globalManager;\n}\n\nexport function onManagerReady(fn: (m: InputManager) => void): void {\n if (globalManager) fn(globalManager);\n else listeners.add(fn);\n}\n\n/** Subscribe to manager availability. Calls fn immediately if already available.\n * Returns an unsubscribe function (for disconnectedCallback). */\nexport function onManager(fn: (m: InputManager) => void): () => void {\n if (globalManager) fn(globalManager);\n else listeners.add(fn);\n return () => listeners.delete(fn);\n}\n","import { onManager } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private manager: InputManager | null = null;\n private unsub: (() => void) | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n\n private stateHandler = (state: ConnectionState, protocol: TransportProtocol) => this.update(state, protocol);\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n this.startLaunchFlow();\n });\n }\n\n connectedCallback() {\n this.unsub = onManager((mgr) => this.bind(mgr));\n // Reset button state on remount\n this.stopPoll();\n this.launch.disabled = false;\n this.launch.textContent = \"Launch SatMouse\";\n }\n\n disconnectedCallback() {\n this.stopPoll();\n this.unsub?.();\n this.unbind();\n }\n\n private bind(mgr: InputManager): void {\n this.unbind();\n this.manager = mgr;\n mgr.on(\"stateChange\", this.stateHandler);\n this.update(mgr.state, mgr.protocol);\n }\n\n private unbind(): void {\n this.manager?.off(\"stateChange\", this.stateHandler);\n this.manager = null;\n }\n\n private update(state: ConnectionState, protocol: TransportProtocol): void {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (state === \"connected\") {\n this.stopPoll();\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = \"Launch SatMouse\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n }\n\n private startLaunchFlow(): void {\n this.launch.textContent = \"Connecting...\";\n this.launch.disabled = true;\n\n this.manager?.retry();\n window.location.href = \"satmouse://launch\";\n\n let attempts = 0;\n this.stopPoll();\n this.pollTimer = setInterval(() => {\n attempts++;\n if (this.manager?.state === \"connected\") {\n this.stopPoll();\n return;\n }\n if (attempts >= 5) {\n this.stopPoll();\n this.launch.disabled = false;\n this.launch.textContent = \"Launch SatMouse\";\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n return;\n }\n this.manager?.retry();\n }, 1500);\n }\n\n private stopPoll(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManager } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis, AxisRoute } from \"../utils/action-map.js\";\nimport { FULL_AXES, buildRoutes, DEFAULT_ROUTES } from \"../utils/action-map.js\";\n\nconst STYLES = `\n<style>\n :host { display: block; font-family: inherit; font-size: 12px; }\n .panel { background: #0f3460; border: 1px solid #1a4a8a; border-radius: 6px; padding: 10px; margin-bottom: 8px; }\n summary { cursor: pointer; font-weight: 600; color: #e0e0e0; font-size: 13px; }\n .type { font-size: 10px; color: #7f8c8d; text-transform: uppercase; margin-left: 6px; }\n .controls { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n .slider-row { display: flex; align-items: center; gap: 6px; }\n .slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }\n .slider-row input[type=\"range\"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }\n .slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }\n .route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }\n .route-row { display: flex; gap: 4px; align-items: center; }\n .route-row label { color: #7f8c8d; white-space: nowrap; }\n .route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;\n font-size: 11px; padding: 1px 4px; }\n .route-row input[type=\"checkbox\"] { accent-color: #e74c3c; margin: 0; }\n .empty { color: #7f8c8d; font-style: italic; }\n .reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }\n .reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }\n</style>\n`;\n\nfunction mapSlider(v: number): number { return 0.0001 * Math.pow(500, v / 100); }\nfunction unmapSlider(v: number): number { return (100 * Math.log(v / 0.0001)) / Math.log(500); }\n\nexport class SatMouseDevices extends HTMLElement {\n private manager: InputManager | null = null;\n private container!: HTMLElement;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = STYLES + `<div class=\"container\"><span class=\"empty\">No devices</span></div>`;\n this.container = shadow.querySelector(\".container\")!;\n }\n\n private unsub: (() => void) | null = null;\n\n private deviceStatusHandler = (event: \"connected\" | \"disconnected\", device: DeviceInfo) => {\n if (event === \"connected\") this.addDevice(device);\n else this.removeDevice(device);\n };\n\n private stateHandler = (state: string) => {\n if (state === \"connected\") {\n this.manager?.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n };\n\n connectedCallback() {\n this.unsub = onManager((mgr) => this.bind(mgr));\n }\n\n disconnectedCallback() {\n this.unsub?.();\n this.unbind();\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n\n private bind(mgr: InputManager): void {\n this.unbind();\n this.manager = mgr;\n mgr.on(\"deviceStatus\", this.deviceStatusHandler);\n mgr.on(\"stateChange\", this.stateHandler);\n if (mgr.state === \"connected\") {\n mgr.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n }\n\n private unbind(): void {\n if (this.manager) {\n this.manager.off(\"deviceStatus\", this.deviceStatusHandler);\n this.manager.off(\"stateChange\", this.stateHandler);\n this.manager = null;\n }\n }\n\n private addDevice(device: DeviceInfo): void {\n const existing = this.shadowRoot!.getElementById(`dev-${device.id}`);\n if (existing) {\n this.refreshControls(existing as HTMLDetailsElement, device);\n return;\n }\n const empty = this.container.querySelector(\".empty\");\n if (empty) empty.remove();\n\n const panel = document.createElement(\"details\");\n panel.className = \"panel\";\n panel.id = `dev-${device.id}`;\n panel.open = true;\n\n const summary = document.createElement(\"summary\");\n summary.innerHTML = `${device.model ?? device.name}<span class=\"type\">${device.connectionType ?? \"\"}</span>`;\n panel.appendChild(summary);\n\n this.refreshControls(panel, device);\n this.container.appendChild(panel);\n }\n\n private refreshControls(panel: HTMLDetailsElement, device: DeviceInfo): void {\n const old = panel.querySelector(\".controls\");\n if (old) old.remove();\n\n const mgr = this.manager!;\n const cfg = mgr.getDeviceConfig(device.id);\n\n const controls = document.createElement(\"div\");\n controls.className = \"controls\";\n\n // Axis routes — one row per device input: [flip] [label] → [target dropdown] [scale slider]\n const routeGroup = document.createElement(\"div\");\n routeGroup.className = \"route-group\";\n const deviceAxes = device.axes ?? [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n const routes = this.getRoutes(device.id, deviceAxes);\n\n for (let i = 0; i < deviceAxes.length; i++) {\n const route = routes[i] ?? { source: deviceAxes[i] as InputAxis, target: deviceAxes[i].replace(/[+-]$/, \"\") as InputAxis };\n const row = document.createElement(\"div\");\n row.className = \"route-row\";\n\n // Flip checkbox\n const cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.checked = route.flip ?? false;\n cb.title = \"Flip\";\n const routeIndex = i;\n cb.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });\n });\n row.appendChild(cb);\n\n // Label (device input name)\n const label = document.createElement(\"label\");\n label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();\n row.appendChild(label);\n\n // Target dropdown\n const sel = document.createElement(\"select\");\n for (const target of FULL_AXES) {\n const opt = document.createElement(\"option\");\n opt.value = target;\n opt.textContent = target.toUpperCase();\n if (target === route.target) opt.selected = true;\n sel.appendChild(opt);\n }\n sel.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value as InputAxis });\n });\n row.appendChild(sel);\n\n routeGroup.appendChild(row);\n }\n controls.appendChild(routeGroup);\n\n // Scale slider\n const sensRow = document.createElement(\"div\");\n sensRow.className = \"slider-row\";\n const currentScale = cfg.scale ?? mgr.config.scale;\n sensRow.innerHTML = `<label>Scale</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(currentScale))}\">` +\n `<span>${currentScale.toFixed(4)}</span>`;\n const slider = sensRow.querySelector(\"input\")! as HTMLInputElement;\n const span = sensRow.querySelector(\"span\")!;\n slider.addEventListener(\"input\", () => {\n const v = mapSlider(+slider.value);\n span.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { scale: v });\n });\n controls.appendChild(sensRow);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = \"Restore Defaults\";\n resetBtn.addEventListener(\"click\", () => {\n mgr.resetDeviceConfig(device.id);\n this.refreshControls(panel, device);\n });\n controls.appendChild(resetBtn);\n\n panel.appendChild(controls);\n }\n\n private getRoutes(deviceId: string, deviceAxes: string[]): AxisRoute[] {\n // Only use saved device config routes — not the global fallback\n const mgr = this.manager!;\n const devCfg = mgr.config.devices[deviceId];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // Check pattern matches\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && deviceId.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // Build from device axes\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const base = this.getRoutes(deviceId, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private removeDevice(device: DeviceInfo): void {\n this.shadowRoot!.getElementById(`dev-${device.id}`)?.remove();\n if (this.container.children.length === 0) {\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManager } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { SpatialData, ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: block; font-family: monospace; font-size: 12px; }\n .row { display: flex; justify-content: space-between; padding: 2px 0; }\n .label { color: #7f8c8d; font-weight: 600; width: 28px; }\n .value { color: #3498db; text-align: right; min-width: 50px; }\n .meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }\n</style>\n<div class=\"meta\"><span class=\"state\">Disconnected</span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> fps</div>\n<div class=\"row\"><span class=\"label\">TX</span><span class=\"value\" id=\"tx\">0</span></div>\n<div class=\"row\"><span class=\"label\">TY</span><span class=\"value\" id=\"ty\">0</span></div>\n<div class=\"row\"><span class=\"label\">TZ</span><span class=\"value\" id=\"tz\">0</span></div>\n<div class=\"row\"><span class=\"label\">RX</span><span class=\"value\" id=\"rx\">0</span></div>\n<div class=\"row\"><span class=\"label\">RY</span><span class=\"value\" id=\"ry\">0</span></div>\n<div class=\"row\"><span class=\"label\">RZ</span><span class=\"value\" id=\"rz\">0</span></div>\n`;\n\nexport class SatMouseDebug extends HTMLElement {\n private els: Record<string, HTMLElement> = {};\n private frameCount = 0;\n private fpsInterval: ReturnType<typeof setInterval> | null = null;\n private manager: InputManager | null = null;\n private unsub: (() => void) | null = null;\n\n private spatialHandler = (data: SpatialData) => {\n this.frameCount++;\n this.els.tx.textContent = String(Math.round(data.translation.x));\n this.els.ty.textContent = String(Math.round(data.translation.y));\n this.els.tz.textContent = String(Math.round(data.translation.z));\n this.els.rx.textContent = String(Math.round(data.rotation.x));\n this.els.ry.textContent = String(Math.round(data.rotation.y));\n this.els.rz.textContent = String(Math.round(data.rotation.z));\n };\n\n private stateHandler = (state: ConnectionState, protocol: TransportProtocol) => {\n this.els.state.textContent = state;\n this.els.protocol.textContent = protocol !== \"none\" ? protocol : \"\";\n };\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n for (const id of [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"]) {\n this.els[id] = shadow.getElementById(id)!;\n }\n this.els.state = shadow.querySelector(\".state\")!;\n this.els.protocol = shadow.querySelector(\".protocol\")!;\n this.els.fps = shadow.querySelector(\".fps\")!;\n }\n\n connectedCallback() {\n this.unsub = onManager((mgr) => this.bind(mgr));\n this.fpsInterval = setInterval(() => {\n this.els.fps.textContent = String(this.frameCount);\n this.frameCount = 0;\n }, 1000);\n }\n\n disconnectedCallback() {\n this.unsub?.();\n this.unbind();\n if (this.fpsInterval) {\n clearInterval(this.fpsInterval);\n this.fpsInterval = null;\n }\n }\n\n private bind(mgr: InputManager): void {\n this.unbind();\n this.manager = mgr;\n mgr.on(\"rawSpatialData\", this.spatialHandler);\n mgr.on(\"stateChange\", this.stateHandler);\n this.els.state.textContent = mgr.state;\n this.els.protocol.textContent = mgr.protocol !== \"none\" ? mgr.protocol : \"\";\n }\n\n private unbind(): void {\n if (this.manager) {\n this.manager.off(\"rawSpatialData\", this.spatialHandler);\n this.manager.off(\"stateChange\", this.stateHandler);\n this.manager = null;\n }\n }\n}\n\ncustomElements.define(\"satmouse-debug\", SatMouseDebug);\n"]}
|
|
@@ -6,17 +6,31 @@ declare class SatMouseStatus extends HTMLElement {
|
|
|
6
6
|
private text;
|
|
7
7
|
private proto;
|
|
8
8
|
private launch;
|
|
9
|
-
private
|
|
9
|
+
private manager;
|
|
10
|
+
private unsub;
|
|
11
|
+
private pollTimer;
|
|
12
|
+
private stateHandler;
|
|
10
13
|
constructor();
|
|
11
14
|
connectedCallback(): void;
|
|
15
|
+
disconnectedCallback(): void;
|
|
12
16
|
private bind;
|
|
17
|
+
private unbind;
|
|
18
|
+
private update;
|
|
19
|
+
private startLaunchFlow;
|
|
20
|
+
private stopPoll;
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
declare class SatMouseDevices extends HTMLElement {
|
|
16
24
|
private manager;
|
|
17
25
|
private container;
|
|
18
26
|
constructor();
|
|
27
|
+
private unsub;
|
|
28
|
+
private deviceStatusHandler;
|
|
29
|
+
private stateHandler;
|
|
19
30
|
connectedCallback(): void;
|
|
31
|
+
disconnectedCallback(): void;
|
|
32
|
+
private bind;
|
|
33
|
+
private unbind;
|
|
20
34
|
private addDevice;
|
|
21
35
|
private refreshControls;
|
|
22
36
|
private getRoutes;
|
|
@@ -27,9 +41,16 @@ declare class SatMouseDevices extends HTMLElement {
|
|
|
27
41
|
declare class SatMouseDebug extends HTMLElement {
|
|
28
42
|
private els;
|
|
29
43
|
private frameCount;
|
|
44
|
+
private fpsInterval;
|
|
45
|
+
private manager;
|
|
46
|
+
private unsub;
|
|
47
|
+
private spatialHandler;
|
|
48
|
+
private stateHandler;
|
|
30
49
|
constructor();
|
|
31
50
|
connectedCallback(): void;
|
|
51
|
+
disconnectedCallback(): void;
|
|
32
52
|
private bind;
|
|
53
|
+
private unbind;
|
|
33
54
|
}
|
|
34
55
|
|
|
35
56
|
declare function registerSatMouse(manager: InputManager): void;
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -6,17 +6,31 @@ declare class SatMouseStatus extends HTMLElement {
|
|
|
6
6
|
private text;
|
|
7
7
|
private proto;
|
|
8
8
|
private launch;
|
|
9
|
-
private
|
|
9
|
+
private manager;
|
|
10
|
+
private unsub;
|
|
11
|
+
private pollTimer;
|
|
12
|
+
private stateHandler;
|
|
10
13
|
constructor();
|
|
11
14
|
connectedCallback(): void;
|
|
15
|
+
disconnectedCallback(): void;
|
|
12
16
|
private bind;
|
|
17
|
+
private unbind;
|
|
18
|
+
private update;
|
|
19
|
+
private startLaunchFlow;
|
|
20
|
+
private stopPoll;
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
declare class SatMouseDevices extends HTMLElement {
|
|
16
24
|
private manager;
|
|
17
25
|
private container;
|
|
18
26
|
constructor();
|
|
27
|
+
private unsub;
|
|
28
|
+
private deviceStatusHandler;
|
|
29
|
+
private stateHandler;
|
|
19
30
|
connectedCallback(): void;
|
|
31
|
+
disconnectedCallback(): void;
|
|
32
|
+
private bind;
|
|
33
|
+
private unbind;
|
|
20
34
|
private addDevice;
|
|
21
35
|
private refreshControls;
|
|
22
36
|
private getRoutes;
|
|
@@ -27,9 +41,16 @@ declare class SatMouseDevices extends HTMLElement {
|
|
|
27
41
|
declare class SatMouseDebug extends HTMLElement {
|
|
28
42
|
private els;
|
|
29
43
|
private frameCount;
|
|
44
|
+
private fpsInterval;
|
|
45
|
+
private manager;
|
|
46
|
+
private unsub;
|
|
47
|
+
private spatialHandler;
|
|
48
|
+
private stateHandler;
|
|
30
49
|
constructor();
|
|
31
50
|
connectedCallback(): void;
|
|
51
|
+
disconnectedCallback(): void;
|
|
32
52
|
private bind;
|
|
53
|
+
private unbind;
|
|
33
54
|
}
|
|
34
55
|
|
|
35
56
|
declare function registerSatMouse(manager: InputManager): void;
|